mirror of
https://github.com/versity/scoutfs.git
synced 2026-01-29 06:42:03 +00:00
Compare commits
60 Commits
greg/per-k
...
v1.22
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f313f2818 | ||
|
|
6b4e666952 | ||
|
|
4a26059d00 | ||
|
|
19e78c32fc | ||
|
|
8c1a45c9f5 | ||
|
|
5a6eb569f3 | ||
|
|
69d9040e68 | ||
|
|
d94ec29ffa | ||
|
|
70c36ae394 | ||
|
|
1d08a58add | ||
|
|
fc7876e844 | ||
|
|
5337b9e221 | ||
|
|
8a22bdd366 | ||
|
|
235ab133a7 | ||
|
|
9335d2eb86 | ||
|
|
97b081de3f | ||
|
|
21b5032365 | ||
|
|
4723f4f9ab | ||
|
|
0a8b3f4e94 | ||
|
|
8a4b0967cb | ||
|
|
606c519e96 | ||
|
|
7d0e7e29f8 | ||
|
|
69de6d7a74 | ||
|
|
ac00f5cedb | ||
|
|
6d42d260cf | ||
|
|
00ebe92186 | ||
|
|
570c05898c | ||
|
|
c298360a49 | ||
|
|
95f4e56546 | ||
|
|
d5c2768f04 | ||
|
|
676d429264 | ||
|
|
5b260e6b54 | ||
|
|
e2b06f2c92 | ||
|
|
546b437df7 | ||
|
|
381f4543b7 | ||
|
|
418a441604 | ||
|
|
f3abf9710b | ||
|
|
8a45c2baff | ||
|
|
345ebd0876 | ||
|
|
b718cf09de | ||
|
|
e4721366ff | ||
|
|
4ef64c6fcf | ||
|
|
2d58ee2a37 | ||
|
|
1f0dd7f025 | ||
|
|
077468ac1e | ||
|
|
c951713ab2 | ||
|
|
ad82a5e52a | ||
|
|
d3c5328909 | ||
|
|
c30172210f | ||
|
|
19af6e28fb | ||
|
|
8885486bc8 | ||
|
|
0204e092e4 | ||
|
|
3b816cfd01 | ||
|
|
b45fbe0bbb | ||
|
|
c5d9b93b96 | ||
|
|
2984f4d3a8 | ||
|
|
3b8d2eab8e | ||
|
|
4dde57dc27 | ||
|
|
a4be74f4b1 | ||
|
|
9d8ac2c7d7 |
@@ -1,6 +1,21 @@
|
||||
Versity ScoutFS Release Notes
|
||||
=============================
|
||||
|
||||
---
|
||||
v1.22
|
||||
\
|
||||
*Nov 1, 2024*
|
||||
|
||||
Add support for building against the RHEL9 family of kernels.
|
||||
|
||||
Fix failure of the setattr\_more ioctl() to set the attributes of a
|
||||
zero-length file when restoring.
|
||||
|
||||
Fix support for POSIX ACLs in the RHEL8 and later family of kernels.
|
||||
|
||||
Fix a race condition in the lock server that could drop lock requests
|
||||
under heavy load and cause cluster lock attempts to hang.
|
||||
|
||||
---
|
||||
v1.21
|
||||
\
|
||||
|
||||
@@ -4,18 +4,13 @@
|
||||
%define kmod_git_describe @@GITDESCRIBE@@
|
||||
%define pkg_date %(date +%%Y%%m%%d)
|
||||
|
||||
# Disable the building of the debug package(s).
|
||||
%define debug_package %{nil}
|
||||
|
||||
# take kernel version or default to uname -r
|
||||
%{!?kversion: %global kversion %(uname -r)}
|
||||
%global kernel_version %{kversion}
|
||||
%global sanitized_kversion %(echo %{kernel_version} | sed -e 's/-/_/g' -e 's/\.el.*//')
|
||||
|
||||
%if 0%{?el7}
|
||||
%global kernel_source() /usr/src/kernels/%{kernel_version}.$(arch)
|
||||
%endif
|
||||
%if 0%{?el8}
|
||||
%else
|
||||
%global kernel_source() /usr/src/kernels/%{kernel_version}
|
||||
%endif
|
||||
|
||||
@@ -23,21 +18,19 @@
|
||||
|
||||
%if 0%{?el7}
|
||||
Name: %{kmod_name}
|
||||
%endif
|
||||
%if 0%{?el8}
|
||||
%else
|
||||
Name: kmod-%{kmod_name}
|
||||
%endif
|
||||
Summary: %{kmod_name} kernel module
|
||||
Version: %{kmod_version}
|
||||
Release: %{_release}+%{sanitized_kversion}%{?dist}
|
||||
Release: %{_release}%{?dist}
|
||||
License: GPLv2
|
||||
Group: System/Kernel
|
||||
URL: http://scoutfs.org/
|
||||
|
||||
%if 0%{?el7}
|
||||
BuildRequires: %{kernel_module_package_buildreqs}
|
||||
%endif
|
||||
%if 0%{?el8}
|
||||
%else
|
||||
BuildRequires: elfutils-libelf-devel
|
||||
%endif
|
||||
BuildRequires: kernel-devel-uname-r = %{kernel_version}
|
||||
@@ -55,7 +48,8 @@ Source: %{kmod_name}-kmod-%{kmod_version}.tar
|
||||
%endif
|
||||
|
||||
%global install_mod_dir extra/%{kmod_name}
|
||||
%if 0%{?el8}
|
||||
|
||||
%if ! 0%{?el7}
|
||||
%global flavors_to_build x86_64
|
||||
%endif
|
||||
|
||||
@@ -94,7 +88,7 @@ done
|
||||
# mark modules executable so that strip-to-file can strip them
|
||||
find %{buildroot} -type f -name \*.ko -exec %{__chmod} u+x \{\} \;
|
||||
|
||||
%if 0%{?el8}
|
||||
%if ! 0%{?el7}
|
||||
%files
|
||||
/lib/modules
|
||||
|
||||
@@ -112,8 +106,5 @@ SCOUTFS_RPM_NAME=$(rpm -q %{name} | grep "%{version}-%{release}")
|
||||
rpm -ql $SCOUTFS_RPM_NAME | grep '\.ko$' > /var/run/%{name}-modules-%{version}-%{release} || true
|
||||
|
||||
%postun
|
||||
if [ -x /sbin/weak-modules ]; then
|
||||
cat /var/run/%{name}-modules-%{version}-%{release} | /sbin/weak-modules --remove-modules --no-initramfs
|
||||
fi
|
||||
|
||||
cat /var/run/%{name}-modules-%{version}-%{release} | weak-modules --remove-modules --no-initramfs
|
||||
rm /var/run/%{name}-modules-%{version}-%{release} || true
|
||||
|
||||
@@ -78,8 +78,9 @@ endif
|
||||
# v4.8-rc1-29-g31051c85b5e2
|
||||
#
|
||||
# inode_change_ok() removed - replace with setattr_prepare()
|
||||
# v5.11-rc4-7-g2f221d6f7b88 removes extern attribute
|
||||
#
|
||||
ifneq (,$(shell grep 'extern int setattr_prepare' include/linux/fs.h))
|
||||
ifneq (,$(shell grep 'int setattr_prepare' include/linux/fs.h))
|
||||
ccflags-y += -DKC_SETATTR_PREPARE
|
||||
endif
|
||||
|
||||
@@ -258,3 +259,157 @@ endif
|
||||
ifneq (,$(shell grep 'static inline const char .xattr_prefix' include/linux/xattr.h))
|
||||
ccflags-y += -DKC_XATTR_HANDLER_NAME=1
|
||||
endif
|
||||
|
||||
#
|
||||
# v5.19-rc4-96-g342a72a33407
|
||||
#
|
||||
# Adds `typedef __u32 __bitwise blk_opf_t` to aid flag checking
|
||||
ifneq (,$(shell grep 'typedef __u32 __bitwise blk_opf_t' include/linux/blk_types.h))
|
||||
ccflags-y += -DKC_HAVE_BLK_OPF_T=1
|
||||
endif
|
||||
|
||||
#
|
||||
# v5.12-rc6-9-g4f0f586bf0c8
|
||||
#
|
||||
# list_sort cmp function takes const list_head args
|
||||
ifneq (,$(shell grep 'const struct list_head ., const struct list_head .' include/linux/list_sort.h))
|
||||
ccflags-y += -DKC_LIST_CMP_CONST_ARG_LIST_HEAD
|
||||
endif
|
||||
|
||||
# v5.7-523-g88dca4ca5a93
|
||||
#
|
||||
# The pgprot argument to vmalloc is always PAGE_KERNEL, so it is removed.
|
||||
ifneq (,$(shell grep 'extern void .__vmalloc.unsigned long size, gfp_t gfp_mask, pgprot_t prot' include/linux/vmalloc.h))
|
||||
ccflags-y += -DKC_VMALLOC_PGPROT_T
|
||||
endif
|
||||
|
||||
# v6.2-rc1-18-g01beba7957a2
|
||||
#
|
||||
# fs: port inode_owner_or_capable() to mnt_idmap
|
||||
ifneq (,$(shell grep 'bool inode_owner_or_capable.struct user_namespace .mnt_userns' include/linux/fs.h))
|
||||
ccflags-y += -DKC_INODE_OWNER_OR_CAPABLE_USERNS
|
||||
endif
|
||||
|
||||
#
|
||||
# v5.11-rc4-5-g47291baa8ddf
|
||||
#
|
||||
# namei: make permission helpers idmapped mount aware
|
||||
ifneq (,$(shell grep 'int inode_permission.struct user_namespace' include/linux/fs.h))
|
||||
ccflags-y += -DKC_INODE_PERMISSION_USERNS
|
||||
endif
|
||||
|
||||
#
|
||||
# v5.11-rc4-24-g549c7297717c
|
||||
#
|
||||
# fs: make helpers idmap mount aware
|
||||
# Enlarges the VFS API methods to include user namespace argument.
|
||||
ifneq (,$(shell grep 'int ..mknod. .struct user_namespace' include/linux/fs.h))
|
||||
ccflags-y += -DKC_VFS_METHOD_USER_NAMESPACE_ARG
|
||||
endif
|
||||
|
||||
#
|
||||
# v5.17-rc2-21-g07888c665b40
|
||||
#
|
||||
# Detect new style bio_alloc - pass bdev and opf.
|
||||
ifneq (,$(shell grep 'struct bio .bio_alloc.struct block_device .bdev' include/linux/bio.h))
|
||||
ccflags-y += -DKC_BIO_ALLOC_DEV_OPF_ARGS
|
||||
endif
|
||||
|
||||
#
|
||||
# v5.7-rc4-53-gcddf8a2c4a82
|
||||
#
|
||||
# fiemap_prep() replaces fiemap_check_flags()
|
||||
ifneq (,$(shell grep -s 'int fiemap_prep.struct inode' include/linux/fiemap.h))
|
||||
ccflags-y += -DKC_FIEMAP_PREP
|
||||
endif
|
||||
|
||||
#
|
||||
# v5.17-13043-g800ba29547e1
|
||||
#
|
||||
# generic_perform_write args use kiocb for passing filp and pos
|
||||
ifneq (,$(shell grep 'ssize_t generic_perform_write.struct kiocb ., struct iov_iter' include/linux/fs.h))
|
||||
ccflags-y += -DKC_GENERIC_PERFORM_WRITE_KIOCB_IOV_ITER
|
||||
endif
|
||||
|
||||
#
|
||||
# v5.7-rc6-2496-g76ee0785f42a
|
||||
#
|
||||
# net: add sock_set_sndtimeo
|
||||
ifneq (,$(shell grep 'void sock_set_sndtimeo.struct sock' include/net/sock.h))
|
||||
ccflags-y += -DKC_SOCK_SET_SNDTIMEO
|
||||
endif
|
||||
|
||||
#
|
||||
# v5.8-rc4-1931-gba423fdaa589
|
||||
#
|
||||
# setsockopt functions are now passed a sockptr_t value instead of char*
|
||||
ifneq (,$(shell grep -s 'include .linux/sockptr.h.' include/linux/net.h))
|
||||
ccflags-y += -DKC_SETSOCKOPT_SOCKPTR_T
|
||||
endif
|
||||
|
||||
#
|
||||
# v5.7-rc6-2507-g71c48eb81c9e
|
||||
#
|
||||
# Adds a bunch of low level TCP sock parameter functions that we want to use.
|
||||
ifneq (,$(shell grep 'int tcp_sock_set_keepintvl' include/linux/tcp.h))
|
||||
ccflags-y += -DKC_HAVE_TCP_SET_SOCKFN
|
||||
endif
|
||||
|
||||
#
|
||||
# v4.16-rc3-13-ga84d1169164b
|
||||
#
|
||||
# Fixes y2038 issues with struct timeval.
|
||||
ifneq (,$(shell grep -s '^struct __kernel_old_timeval .' include/uapi/linux/time_types.h))
|
||||
ccflags-y += -DKC_KERNEL_OLD_TIMEVAL_STRUCT
|
||||
endif
|
||||
|
||||
#
|
||||
# v5.19-rc4-52-ge33c267ab70d
|
||||
#
|
||||
# register_shrinker now requires a name, used for debug stats etc.
|
||||
ifneq (,$(shell grep 'int __printf.*register_shrinker.struct shrinker .shrinker,' include/linux/shrinker.h))
|
||||
ccflags-y += -DKC_SHRINKER_NAME
|
||||
endif
|
||||
|
||||
#
|
||||
# v5.18-rc5-246-gf132ab7d3ab0
|
||||
#
|
||||
# mpage_readpage() is now replaced with mpage_read_folio.
|
||||
ifneq (,$(shell grep 'int mpage_read_folio.struct folio .folio' include/linux/mpage.h))
|
||||
ccflags-y += -DKC_MPAGE_READ_FOLIO
|
||||
endif
|
||||
|
||||
#
|
||||
# v5.18-rc5-219-gb3992d1e2ebc
|
||||
#
|
||||
# block_write_begin() no longer is being passed aop_flags
|
||||
ifneq (,$(shell grep -C1 'int block_write_begin' include/linux/buffer_head.h | tail -n 2 | grep 'unsigned flags'))
|
||||
ccflags-y += -DKC_BLOCK_WRITE_BEGIN_AOP_FLAGS
|
||||
endif
|
||||
|
||||
#
|
||||
# v6.0-rc6-9-g863f144f12ad
|
||||
#
|
||||
# the .tmpfile() vfs method calling convention changed and now a struct
|
||||
# file* is passed to this metiond instead of a dentry. The function also
|
||||
# should open the created file and call finish_open_simple() before returning.
|
||||
ifneq (,$(shell grep 'extern void d_tmpfile.struct dentry' include/linux/dcache.h))
|
||||
ccflags-y += -DKC_D_TMPFILE_DENTRY
|
||||
endif
|
||||
|
||||
#
|
||||
# v6.4-rc2-201-g0733ad800291
|
||||
#
|
||||
# New blk_mode_t replaces abuse of fmode_t
|
||||
ifneq (,$(shell grep 'typedef unsigned int __bitwise blk_mode_t' include/linux/blkdev.h))
|
||||
ccflags-y += -DKC_HAVE_BLK_MODE_T
|
||||
endif
|
||||
|
||||
#
|
||||
# v6.4-rc2-186-g2736e8eeb0cc
|
||||
#
|
||||
# Reworks FMODE_EXCL kludge and instead modifies the blkdev_put() call to pass in
|
||||
# the (exclusive) holder to implement FMODE_EXCL handling.
|
||||
ifneq (,$(shell grep 'blkdev_put.struct block_device .bdev, void .holder' include/linux/blkdev.h))
|
||||
ccflags-y += -DKC_BLKDEV_PUT_HOLDER_ARG
|
||||
endif
|
||||
|
||||
@@ -153,7 +153,8 @@ int scoutfs_set_acl_locked(struct inode *inode, struct posix_acl *acl, int type,
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
if (acl) {
|
||||
ret = posix_acl_update_mode(inode, &new_mode, &acl);
|
||||
ret = posix_acl_update_mode(KC_VFS_INIT_NS
|
||||
inode, &new_mode, &acl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
set_mode = true;
|
||||
@@ -252,7 +253,9 @@ int scoutfs_acl_get_xattr(struct dentry *dentry, const char *name, void *value,
|
||||
}
|
||||
|
||||
#ifdef KC_XATTR_STRUCT_XATTR_HANDLER
|
||||
int scoutfs_acl_set_xattr(const struct xattr_handler *handler, struct dentry *dentry,
|
||||
int scoutfs_acl_set_xattr(const struct xattr_handler *handler,
|
||||
KC_VFS_NS_DEF
|
||||
struct dentry *dentry,
|
||||
struct inode *inode, const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
@@ -265,7 +268,7 @@ int scoutfs_acl_set_xattr(struct dentry *dentry, const char *name, const void *v
|
||||
struct posix_acl *acl = NULL;
|
||||
int ret;
|
||||
|
||||
if (!inode_owner_or_capable(dentry->d_inode))
|
||||
if (!inode_owner_or_capable(KC_VFS_INIT_NS dentry->d_inode))
|
||||
return -EPERM;
|
||||
|
||||
if (!IS_POSIXACL(dentry->d_inode))
|
||||
|
||||
@@ -10,7 +10,9 @@ int scoutfs_set_acl_locked(struct inode *inode, struct posix_acl *acl, int type,
|
||||
int scoutfs_acl_get_xattr(const struct xattr_handler *, struct dentry *dentry,
|
||||
struct inode *inode, const char *name, void *value,
|
||||
size_t size);
|
||||
int scoutfs_acl_set_xattr(const struct xattr_handler *, struct dentry *dentry,
|
||||
int scoutfs_acl_set_xattr(const struct xattr_handler *,
|
||||
KC_VFS_NS_DEF
|
||||
struct dentry *dentry,
|
||||
struct inode *inode, const char *name, const void *value,
|
||||
size_t size, int flags);
|
||||
#else
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/sort.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
|
||||
@@ -120,8 +120,7 @@ do { \
|
||||
|
||||
static __le32 block_calc_crc(struct scoutfs_block_header *hdr, u32 size)
|
||||
{
|
||||
int off = offsetof(struct scoutfs_block_header, crc) +
|
||||
FIELD_SIZEOF(struct scoutfs_block_header, crc);
|
||||
int off = offsetofend(struct scoutfs_block_header, crc);
|
||||
u32 calc = crc32c(~0, (char *)hdr + off, size - off);
|
||||
|
||||
return cpu_to_le32(calc);
|
||||
@@ -159,7 +158,7 @@ static struct block_private *block_alloc(struct super_block *sb, u64 blkno)
|
||||
*/
|
||||
lockdep_off();
|
||||
nofs_flags = memalloc_nofs_save();
|
||||
bp->virt = __vmalloc(SCOUTFS_BLOCK_LG_SIZE, GFP_NOFS | __GFP_HIGHMEM, PAGE_KERNEL);
|
||||
bp->virt = kc__vmalloc(SCOUTFS_BLOCK_LG_SIZE, GFP_NOFS | __GFP_HIGHMEM);
|
||||
memalloc_nofs_restore(nofs_flags);
|
||||
lockdep_on();
|
||||
|
||||
@@ -438,7 +437,7 @@ static void block_remove_all(struct super_block *sb)
|
||||
* possible. Final freeing, verifying checksums, and unlinking errored
|
||||
* blocks are all done by future users of the blocks.
|
||||
*/
|
||||
static void block_end_io(struct super_block *sb, unsigned int opf,
|
||||
static void block_end_io(struct super_block *sb, blk_opf_t opf,
|
||||
struct block_private *bp, int err)
|
||||
{
|
||||
DECLARE_BLOCK_INFO(sb, binf);
|
||||
@@ -478,7 +477,7 @@ static void KC_DECLARE_BIO_END_IO(block_bio_end_io, struct bio *bio)
|
||||
* Kick off IO for a single block.
|
||||
*/
|
||||
static int block_submit_bio(struct super_block *sb, struct block_private *bp,
|
||||
unsigned int opf)
|
||||
blk_opf_t opf)
|
||||
{
|
||||
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
|
||||
struct bio *bio = NULL;
|
||||
@@ -505,15 +504,13 @@ static int block_submit_bio(struct super_block *sb, struct block_private *bp,
|
||||
|
||||
for (off = 0; off < SCOUTFS_BLOCK_LG_SIZE; off += PAGE_SIZE) {
|
||||
if (!bio) {
|
||||
bio = bio_alloc(GFP_NOFS, SCOUTFS_BLOCK_LG_PAGES_PER);
|
||||
bio = kc_bio_alloc(sbi->meta_bdev, SCOUTFS_BLOCK_LG_PAGES_PER, opf, GFP_NOFS);
|
||||
if (!bio) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
kc_bio_set_opf(bio, opf);
|
||||
kc_bio_set_sector(bio, sector + (off >> 9));
|
||||
bio_set_dev(bio, sbi->meta_bdev);
|
||||
bio->bi_end_io = block_bio_end_io;
|
||||
bio->bi_private = bp;
|
||||
|
||||
@@ -1201,7 +1198,7 @@ static void KC_DECLARE_BIO_END_IO(sm_block_bio_end_io, struct bio *bio)
|
||||
* only layer that sees the full block buffer so we pass the calculated
|
||||
* crc to the caller for them to check in their context.
|
||||
*/
|
||||
static int sm_block_io(struct super_block *sb, struct block_device *bdev, unsigned int opf,
|
||||
static int sm_block_io(struct super_block *sb, struct block_device *bdev, blk_opf_t opf,
|
||||
u64 blkno, struct scoutfs_block_header *hdr, size_t len, __le32 *blk_crc)
|
||||
{
|
||||
struct scoutfs_block_header *pg_hdr;
|
||||
@@ -1233,15 +1230,13 @@ static int sm_block_io(struct super_block *sb, struct block_device *bdev, unsign
|
||||
pg_hdr->crc = block_calc_crc(pg_hdr, SCOUTFS_BLOCK_SM_SIZE);
|
||||
}
|
||||
|
||||
bio = bio_alloc(GFP_NOFS, 1);
|
||||
bio = kc_bio_alloc(bdev, 1, opf, GFP_NOFS);
|
||||
if (!bio) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
kc_bio_set_opf(bio, opf | REQ_SYNC);
|
||||
kc_bio_set_sector(bio, blkno << (SCOUTFS_BLOCK_SM_SHIFT - 9));
|
||||
bio_set_dev(bio, bdev);
|
||||
bio->bi_end_io = sm_block_bio_end_io;
|
||||
bio->bi_private = &sbc;
|
||||
bio_add_page(bio, page, SCOUTFS_BLOCK_SM_SIZE, 0);
|
||||
@@ -1302,7 +1297,7 @@ int scoutfs_block_setup(struct super_block *sb)
|
||||
init_waitqueue_head(&binf->waitq);
|
||||
KC_INIT_SHRINKER_FUNCS(&binf->shrinker, block_count_objects,
|
||||
block_scan_objects);
|
||||
KC_REGISTER_SHRINKER(&binf->shrinker);
|
||||
KC_REGISTER_SHRINKER(&binf->shrinker, "scoutfs-block:" SCSBF, SCSB_ARGS(sb));
|
||||
INIT_WORK(&binf->free_work, block_free_work);
|
||||
init_llist_head(&binf->free_llist);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <net/sock.h>
|
||||
#include <net/tcp.h>
|
||||
#include <asm/barrier.h>
|
||||
#include <linux/overflow.h>
|
||||
|
||||
#include "format.h"
|
||||
#include "counters.h"
|
||||
@@ -68,6 +69,7 @@ int scoutfs_client_alloc_inodes(struct super_block *sb, u64 count,
|
||||
struct client_info *client = SCOUTFS_SB(sb)->client_info;
|
||||
struct scoutfs_net_inode_alloc ial;
|
||||
__le64 lecount = cpu_to_le64(count);
|
||||
u64 tmp;
|
||||
int ret;
|
||||
|
||||
ret = scoutfs_net_sync_request(sb, client->conn,
|
||||
@@ -80,7 +82,7 @@ int scoutfs_client_alloc_inodes(struct super_block *sb, u64 count,
|
||||
|
||||
if (*nr == 0)
|
||||
ret = -ENOSPC;
|
||||
else if (*ino + *nr < *ino)
|
||||
else if (check_add_overflow(*ino, *nr - 1, &tmp))
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
#include <linux/hash.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/falloc.h>
|
||||
#include <linux/fiemap.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/overflow.h>
|
||||
|
||||
#include "format.h"
|
||||
#include "super.h"
|
||||
@@ -679,8 +681,14 @@ int scoutfs_get_block_write(struct inode *inode, sector_t iblock, struct buffer_
|
||||
* We can return errors from locking and checking offline extents. The
|
||||
* page is unlocked if we return an error.
|
||||
*/
|
||||
#ifdef KC_MPAGE_READ_FOLIO
|
||||
static int scoutfs_read_folio(struct file *file, struct folio *folio)
|
||||
{
|
||||
struct page *page = &folio->page;
|
||||
#else
|
||||
static int scoutfs_readpage(struct file *file, struct page *page)
|
||||
{
|
||||
#endif
|
||||
struct inode *inode = file->f_inode;
|
||||
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
|
||||
struct super_block *sb = inode->i_sb;
|
||||
@@ -727,7 +735,11 @@ static int scoutfs_readpage(struct file *file, struct page *page)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef KC_MPAGE_READ_FOLIO
|
||||
ret = mpage_read_folio(folio, scoutfs_get_block_read);
|
||||
#else
|
||||
ret = mpage_readpage(page, scoutfs_get_block_read);
|
||||
#endif
|
||||
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
|
||||
scoutfs_per_task_del(&si->pt_data_lock, &pt_ent);
|
||||
@@ -825,7 +837,10 @@ struct write_begin_data {
|
||||
|
||||
static int scoutfs_write_begin(struct file *file,
|
||||
struct address_space *mapping, loff_t pos,
|
||||
unsigned len, unsigned flags,
|
||||
unsigned len,
|
||||
#ifdef KC_BLOCK_WRITE_BEGIN_AOP_FLAGS
|
||||
unsigned flags,
|
||||
#endif
|
||||
struct page **pagep, void **fsdata)
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
@@ -860,13 +875,18 @@ retry:
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
#ifdef KC_BLOCK_WRITE_BEGIN_AOP_FLAGS
|
||||
/* can't re-enter fs, have trans */
|
||||
flags |= AOP_FLAG_NOFS;
|
||||
#endif
|
||||
|
||||
/* generic write_end updates i_size and calls dirty_inode */
|
||||
ret = scoutfs_dirty_inode_item(inode, wbd->lock) ?:
|
||||
block_write_begin(mapping, pos, len, flags, pagep,
|
||||
scoutfs_get_block_write);
|
||||
block_write_begin(mapping, pos, len,
|
||||
#ifdef KC_BLOCK_WRITE_BEGIN_AOP_FLAGS
|
||||
flags,
|
||||
#endif
|
||||
pagep, scoutfs_get_block_write);
|
||||
if (ret < 0) {
|
||||
scoutfs_release_trans(sb);
|
||||
scoutfs_inode_index_unlock(sb, &wbd->ind_locks);
|
||||
@@ -1068,6 +1088,7 @@ long scoutfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
|
||||
loff_t end;
|
||||
u64 iblock;
|
||||
u64 last;
|
||||
loff_t tmp;
|
||||
s64 ret;
|
||||
|
||||
/* XXX support more flags */
|
||||
@@ -1076,14 +1097,14 @@ long scoutfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* catch wrapping */
|
||||
if (offset + len < offset) {
|
||||
ret = -EINVAL;
|
||||
if (len == 0) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
ret = 0;
|
||||
/* catch wrapping */
|
||||
if (check_add_overflow(offset, len - 1, &tmp)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1304,8 +1325,8 @@ int scoutfs_data_move_blocks(struct inode *from, u64 from_off,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = inode_permission(from, MAY_WRITE) ?:
|
||||
inode_permission(to, MAY_WRITE);
|
||||
ret = inode_permission(KC_VFS_INIT_NS from, MAY_WRITE) ?:
|
||||
inode_permission(KC_VFS_INIT_NS to, MAY_WRITE);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
@@ -1543,7 +1564,7 @@ int scoutfs_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC);
|
||||
ret = fiemap_prep(inode, fieinfo, start, &len, FIEMAP_FLAG_SYNC);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -1709,12 +1730,16 @@ int scoutfs_data_wait_check(struct inode *inode, loff_t pos, loff_t len,
|
||||
u64 last_block;
|
||||
u64 on;
|
||||
u64 off;
|
||||
loff_t tmp;
|
||||
int ret = 0;
|
||||
|
||||
if (len == 0)
|
||||
goto out;
|
||||
|
||||
if (WARN_ON_ONCE(sef & SEF_UNKNOWN) ||
|
||||
WARN_ON_ONCE(op & SCOUTFS_IOC_DWO_UNKNOWN) ||
|
||||
WARN_ON_ONCE(dw && !RB_EMPTY_NODE(&dw->node)) ||
|
||||
WARN_ON_ONCE(pos + len < pos)) {
|
||||
WARN_ON_ONCE(check_add_overflow(pos, len - 1, &tmp))) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -1890,7 +1915,13 @@ int scoutfs_data_waiting(struct super_block *sb, u64 ino, u64 iblock,
|
||||
}
|
||||
|
||||
const struct address_space_operations scoutfs_file_aops = {
|
||||
#ifdef KC_MPAGE_READ_FOLIO
|
||||
.dirty_folio = block_dirty_folio,
|
||||
.invalidate_folio = block_invalidate_folio,
|
||||
.read_folio = scoutfs_read_folio,
|
||||
#else
|
||||
.readpage = scoutfs_readpage,
|
||||
#endif
|
||||
#ifndef KC_FILE_AOPS_READAHEAD
|
||||
.readpages = scoutfs_readpages,
|
||||
#else
|
||||
@@ -1911,6 +1942,8 @@ const struct file_operations scoutfs_file_fops = {
|
||||
#else
|
||||
.read_iter = scoutfs_file_read_iter,
|
||||
.write_iter = scoutfs_file_write_iter,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.splice_write = iter_file_splice_write,
|
||||
#endif
|
||||
.unlocked_ioctl = scoutfs_ioctl,
|
||||
.fsync = scoutfs_file_fsync,
|
||||
|
||||
@@ -703,8 +703,9 @@ out_unlock:
|
||||
return inode;
|
||||
}
|
||||
|
||||
static int scoutfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
|
||||
dev_t rdev)
|
||||
static int scoutfs_mknod(KC_VFS_NS_DEF
|
||||
struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, dev_t rdev)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct inode *inode = NULL;
|
||||
@@ -773,15 +774,20 @@ out:
|
||||
}
|
||||
|
||||
/* XXX hmm, do something with excl? */
|
||||
static int scoutfs_create(struct inode *dir, struct dentry *dentry,
|
||||
umode_t mode, bool excl)
|
||||
static int scoutfs_create(KC_VFS_NS_DEF
|
||||
struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
{
|
||||
return scoutfs_mknod(dir, dentry, mode | S_IFREG, 0);
|
||||
return scoutfs_mknod(KC_VFS_NS
|
||||
dir, dentry, mode | S_IFREG, 0);
|
||||
}
|
||||
|
||||
static int scoutfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
static int scoutfs_mkdir(KC_VFS_NS_DEF
|
||||
struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return scoutfs_mknod(dir, dentry, mode | S_IFDIR, 0);
|
||||
return scoutfs_mknod(KC_VFS_NS
|
||||
dir, dentry, mode | S_IFDIR, 0);
|
||||
}
|
||||
|
||||
static int scoutfs_link(struct dentry *old_dentry,
|
||||
@@ -1176,7 +1182,8 @@ static const char *scoutfs_get_link(struct dentry *dentry, struct inode *inode,
|
||||
* Symlink target paths can be annoyingly large. We store relatively
|
||||
* rare large paths in multiple items.
|
||||
*/
|
||||
static int scoutfs_symlink(struct inode *dir, struct dentry *dentry,
|
||||
static int scoutfs_symlink(KC_VFS_NS_DEF
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
const char *symname)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
@@ -1563,7 +1570,8 @@ static int verify_ancestors(struct super_block *sb, u64 p1, u64 p2,
|
||||
* from using parent/child locking orders as two groups can have both
|
||||
* parent and child relationships to each other.
|
||||
*/
|
||||
static int scoutfs_rename_common(struct inode *old_dir,
|
||||
static int scoutfs_rename_common(KC_VFS_NS_DEF
|
||||
struct inode *old_dir,
|
||||
struct dentry *old_dentry, struct inode *new_dir,
|
||||
struct dentry *new_dentry, unsigned int flags)
|
||||
{
|
||||
@@ -1840,18 +1848,21 @@ static int scoutfs_rename(struct inode *old_dir,
|
||||
struct dentry *old_dentry, struct inode *new_dir,
|
||||
struct dentry *new_dentry)
|
||||
{
|
||||
return scoutfs_rename_common(old_dir, old_dentry, new_dir, new_dentry, 0);
|
||||
return scoutfs_rename_common(KC_VFS_INIT_NS
|
||||
old_dir, old_dentry, new_dir, new_dentry, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int scoutfs_rename2(struct inode *old_dir,
|
||||
static int scoutfs_rename2(KC_VFS_NS_DEF
|
||||
struct inode *old_dir,
|
||||
struct dentry *old_dentry, struct inode *new_dir,
|
||||
struct dentry *new_dentry, unsigned int flags)
|
||||
{
|
||||
if (flags & ~RENAME_NOREPLACE)
|
||||
return -EINVAL;
|
||||
|
||||
return scoutfs_rename_common(old_dir, old_dentry, new_dir, new_dentry, flags);
|
||||
return scoutfs_rename_common(KC_VFS_NS
|
||||
old_dir, old_dentry, new_dir, new_dentry, flags);
|
||||
}
|
||||
|
||||
#ifdef KC_FMODE_KABI_ITERATE
|
||||
@@ -1863,8 +1874,18 @@ static int scoutfs_dir_open(struct inode *inode, struct file *file)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int scoutfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
static int scoutfs_tmpfile(KC_VFS_NS_DEF
|
||||
struct inode *dir,
|
||||
#ifdef KC_D_TMPFILE_DENTRY
|
||||
struct dentry *dentry,
|
||||
#else
|
||||
struct file *file,
|
||||
#endif
|
||||
umode_t mode)
|
||||
{
|
||||
#ifndef KC_D_TMPFILE_DENTRY
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
#endif
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct inode *inode = NULL;
|
||||
struct scoutfs_lock *dir_lock = NULL;
|
||||
@@ -1891,7 +1912,11 @@ static int scoutfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mod
|
||||
si->crtime = inode->i_mtime;
|
||||
insert_inode_hash(inode);
|
||||
ihold(inode); /* need to update inode modifications in d_tmpfile */
|
||||
#ifdef KC_D_TMPFILE_DENTRY
|
||||
d_tmpfile(dentry, inode);
|
||||
#else
|
||||
d_tmpfile(file, inode);
|
||||
#endif
|
||||
inode_inc_iversion(inode);
|
||||
scoutfs_forest_inc_inode_count(sb);
|
||||
|
||||
@@ -1899,6 +1924,10 @@ static int scoutfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mod
|
||||
scoutfs_update_inode_item(dir, dir_lock, &ind_locks);
|
||||
scoutfs_inode_index_unlock(sb, &ind_locks);
|
||||
|
||||
#ifndef KC_D_TMPFILE_DENTRY
|
||||
ret = finish_open_simple(file, 0);
|
||||
#endif
|
||||
|
||||
out:
|
||||
scoutfs_release_trans(sb);
|
||||
scoutfs_inode_index_unlock(sb, &ind_locks);
|
||||
|
||||
@@ -105,12 +105,12 @@ static ssize_t elapsed_secs_show(struct kobject *kobj,
|
||||
{
|
||||
DECLARE_FENCE_FROM_KOBJ(fence, kobj);
|
||||
ktime_t now = ktime_get();
|
||||
struct timeval tv = { 0, };
|
||||
ktime_t t = ns_to_ktime(0);
|
||||
|
||||
if (ktime_after(now, fence->start_kt))
|
||||
tv = ktime_to_timeval(ktime_sub(now, fence->start_kt));
|
||||
t = ktime_sub(now, fence->start_kt);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llu", (long long)tv.tv_sec);
|
||||
return snprintf(buf, PAGE_SIZE, "%llu", (long long)ktime_divns(t, NSEC_PER_SEC));
|
||||
}
|
||||
SCOUTFS_ATTR_RO(elapsed_secs);
|
||||
|
||||
|
||||
@@ -267,7 +267,8 @@ out:
|
||||
}
|
||||
#endif
|
||||
|
||||
int scoutfs_permission(struct inode *inode, int mask)
|
||||
int scoutfs_permission(KC_VFS_NS_DEF
|
||||
struct inode *inode, int mask)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct scoutfs_lock *inode_lock = NULL;
|
||||
@@ -281,7 +282,8 @@ int scoutfs_permission(struct inode *inode, int mask)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = generic_permission(inode, mask);
|
||||
ret = generic_permission(KC_VFS_INIT_NS
|
||||
inode, mask);
|
||||
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ ssize_t scoutfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
ssize_t scoutfs_file_read_iter(struct kiocb *, struct iov_iter *);
|
||||
ssize_t scoutfs_file_write_iter(struct kiocb *, struct iov_iter *);
|
||||
#endif
|
||||
int scoutfs_permission(struct inode *inode, int mask);
|
||||
int scoutfs_permission(KC_VFS_NS_DEF
|
||||
struct inode *inode, int mask);
|
||||
loff_t scoutfs_file_llseek(struct file *file, loff_t offset, int whence);
|
||||
|
||||
#endif /* _SCOUTFS_FILE_H_ */
|
||||
|
||||
@@ -373,7 +373,8 @@ int scoutfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
#else
|
||||
int scoutfs_getattr(const struct path *path, struct kstat *stat,
|
||||
int scoutfs_getattr(KC_VFS_NS_DEF
|
||||
const struct path *path, struct kstat *stat,
|
||||
u32 request_mask, unsigned int query_flags)
|
||||
{
|
||||
struct inode *inode = d_inode(path->dentry);
|
||||
@@ -385,7 +386,8 @@ int scoutfs_getattr(const struct path *path, struct kstat *stat,
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &lock);
|
||||
if (ret == 0) {
|
||||
generic_fillattr(inode, stat);
|
||||
generic_fillattr(KC_VFS_INIT_NS
|
||||
inode, stat);
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_READ);
|
||||
}
|
||||
return ret;
|
||||
@@ -483,7 +485,8 @@ int scoutfs_complete_truncate(struct inode *inode, struct scoutfs_lock *lock)
|
||||
* re-acquire it. Ideally we'd fix this so that we can acquire the lock
|
||||
* instead of the caller.
|
||||
*/
|
||||
int scoutfs_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
int scoutfs_setattr(KC_VFS_NS_DEF
|
||||
struct dentry *dentry, struct iattr *attr)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
@@ -501,7 +504,8 @@ retry:
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = setattr_prepare(dentry, attr);
|
||||
ret = setattr_prepare(KC_VFS_INIT_NS
|
||||
dentry, attr);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -565,7 +569,8 @@ retry:
|
||||
if (ret < 0)
|
||||
goto release;
|
||||
|
||||
setattr_copy(inode, attr);
|
||||
setattr_copy(KC_VFS_INIT_NS
|
||||
inode, attr);
|
||||
inode_inc_iversion(inode);
|
||||
scoutfs_update_inode_item(inode, lock, &ind_locks);
|
||||
|
||||
@@ -979,10 +984,10 @@ static bool inode_has_index(umode_t mode, u8 type)
|
||||
}
|
||||
}
|
||||
|
||||
static int cmp_index_lock(void *priv, struct list_head *A, struct list_head *B)
|
||||
static int cmp_index_lock(void *priv, KC_LIST_CMP_CONST struct list_head *A, KC_LIST_CMP_CONST struct list_head *B)
|
||||
{
|
||||
struct index_lock *a = list_entry(A, struct index_lock, head);
|
||||
struct index_lock *b = list_entry(B, struct index_lock, head);
|
||||
KC_LIST_CMP_CONST struct index_lock *a = list_entry(A, KC_LIST_CMP_CONST struct index_lock, head);
|
||||
KC_LIST_CMP_CONST struct index_lock *b = list_entry(B, KC_LIST_CMP_CONST struct index_lock, head);
|
||||
|
||||
return ((int)a->type - (int)b->type) ?:
|
||||
scoutfs_cmp_u64s(a->major, b->major) ?:
|
||||
@@ -1562,7 +1567,8 @@ int scoutfs_new_inode(struct super_block *sb, struct inode *dir, umode_t mode, d
|
||||
scoutfs_inode_set_data_seq(inode);
|
||||
|
||||
inode->i_ino = ino; /* XXX overflow */
|
||||
inode_init_owner(inode, dir, mode);
|
||||
inode_init_owner(KC_VFS_INIT_NS
|
||||
inode, dir, mode);
|
||||
inode_set_bytes(inode, 0);
|
||||
inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
|
||||
inode->i_rdev = rdev;
|
||||
|
||||
@@ -135,10 +135,12 @@ int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock);
|
||||
int scoutfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
struct kstat *stat);
|
||||
#else
|
||||
int scoutfs_getattr(const struct path *path, struct kstat *stat,
|
||||
int scoutfs_getattr(KC_VFS_NS_DEF
|
||||
const struct path *path, struct kstat *stat,
|
||||
u32 request_mask, unsigned int query_flags);
|
||||
#endif
|
||||
int scoutfs_setattr(struct dentry *dentry, struct iattr *attr);
|
||||
int scoutfs_setattr(KC_VFS_NS_DEF
|
||||
struct dentry *dentry, struct iattr *attr);
|
||||
|
||||
int scoutfs_inode_orphan_create(struct super_block *sb, u64 ino, struct scoutfs_lock *lock,
|
||||
struct scoutfs_lock *primary);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <linux/aio.h>
|
||||
#include <linux/list_sort.h>
|
||||
#include <linux/backing-dev.h>
|
||||
#include <linux/overflow.h>
|
||||
|
||||
#include "format.h"
|
||||
#include "key.h"
|
||||
@@ -47,6 +48,7 @@
|
||||
#include "wkic.h"
|
||||
#include "quota.h"
|
||||
#include "scoutfs_trace.h"
|
||||
#include "util.h"
|
||||
|
||||
/*
|
||||
* We make inode index items coherent by locking fixed size regions of
|
||||
@@ -288,6 +290,7 @@ static long scoutfs_ioc_release(struct file *file, unsigned long arg)
|
||||
u64 online;
|
||||
u64 offline;
|
||||
u64 isize;
|
||||
__u64 tmp;
|
||||
int ret;
|
||||
|
||||
if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
|
||||
@@ -297,12 +300,11 @@ static long scoutfs_ioc_release(struct file *file, unsigned long arg)
|
||||
|
||||
if (args.length == 0)
|
||||
return 0;
|
||||
if (((args.offset + args.length) < args.offset) ||
|
||||
if ((check_add_overflow(args.offset, args.length - 1, &tmp)) ||
|
||||
(args.offset & SCOUTFS_BLOCK_SM_MASK) ||
|
||||
(args.length & SCOUTFS_BLOCK_SM_MASK))
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
ret = mnt_want_write_file(file);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -674,8 +676,8 @@ static long scoutfs_ioc_setattr_more(struct file *file, unsigned long arg)
|
||||
goto out;
|
||||
}
|
||||
|
||||
iax->x_mask = SCOUTFS_IOC_IAX_DATA_VERSION | SCOUTFS_IOC_IAX_CTIME |
|
||||
SCOUTFS_IOC_IAX_CRTIME | SCOUTFS_IOC_IAX_SIZE;
|
||||
iax->x_mask = SCOUTFS_IOC_IAX_CTIME | SCOUTFS_IOC_IAX_CRTIME |
|
||||
SCOUTFS_IOC_IAX_SIZE;
|
||||
iax->data_version = sm.data_version;
|
||||
iax->ctime_sec = sm.ctime_sec;
|
||||
iax->ctime_nsec = sm.ctime_nsec;
|
||||
@@ -686,6 +688,9 @@ static long scoutfs_ioc_setattr_more(struct file *file, unsigned long arg)
|
||||
if (sm.flags & SCOUTFS_IOC_SETATTR_MORE_OFFLINE)
|
||||
iax->x_flags |= SCOUTFS_IOC_IAX_F_SIZE_OFFLINE;
|
||||
|
||||
if (sm.data_version != 0)
|
||||
iax->x_mask |= SCOUTFS_IOC_IAX_DATA_VERSION;
|
||||
|
||||
ret = mnt_want_write_file(file);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
@@ -713,7 +718,8 @@ static long scoutfs_ioc_listxattr_hidden(struct file *file, unsigned long arg)
|
||||
int total = 0;
|
||||
int ret;
|
||||
|
||||
ret = inode_permission(inode, MAY_READ);
|
||||
ret = inode_permission(KC_VFS_INIT_NS
|
||||
inode, MAY_READ);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
@@ -951,6 +957,7 @@ static long scoutfs_ioc_move_blocks(struct file *file, unsigned long arg)
|
||||
struct scoutfs_ioctl_move_blocks mb;
|
||||
struct file *from_file;
|
||||
struct inode *from;
|
||||
u64 tmp;
|
||||
int ret;
|
||||
|
||||
if (copy_from_user(&mb, umb, sizeof(mb)))
|
||||
@@ -959,8 +966,8 @@ static long scoutfs_ioc_move_blocks(struct file *file, unsigned long arg)
|
||||
if (mb.len == 0)
|
||||
return 0;
|
||||
|
||||
if (mb.from_off + mb.len < mb.from_off ||
|
||||
mb.to_off + mb.len < mb.to_off)
|
||||
if ((check_add_overflow(mb.from_off, mb.len - 1, &tmp)) ||
|
||||
(check_add_overflow(mb.to_off, mb.len - 1, &tmp)))
|
||||
return -EOVERFLOW;
|
||||
|
||||
from_file = fget(mb.from_fd);
|
||||
|
||||
@@ -2241,18 +2241,18 @@ u64 scoutfs_item_dirty_pages(struct super_block *sb)
|
||||
return (u64)atomic_read(&cinf->dirty_pages);
|
||||
}
|
||||
|
||||
static int cmp_pg_start(void *priv, struct list_head *A, struct list_head *B)
|
||||
static int cmp_pg_start(void *priv, KC_LIST_CMP_CONST struct list_head *A, KC_LIST_CMP_CONST struct list_head *B)
|
||||
{
|
||||
struct cached_page *a = list_entry(A, struct cached_page, dirty_head);
|
||||
struct cached_page *b = list_entry(B, struct cached_page, dirty_head);
|
||||
KC_LIST_CMP_CONST struct cached_page *a = list_entry(A, KC_LIST_CMP_CONST struct cached_page, dirty_head);
|
||||
KC_LIST_CMP_CONST struct cached_page *b = list_entry(B, KC_LIST_CMP_CONST struct cached_page, dirty_head);
|
||||
|
||||
return scoutfs_key_compare(&a->start, &b->start);
|
||||
}
|
||||
|
||||
static int cmp_item_key(void *priv, struct list_head *A, struct list_head *B)
|
||||
static int cmp_item_key(void *priv, KC_LIST_CMP_CONST struct list_head *A, KC_LIST_CMP_CONST struct list_head *B)
|
||||
{
|
||||
struct cached_item *a = list_entry(A, struct cached_item, dirty_head);
|
||||
struct cached_item *b = list_entry(B, struct cached_item, dirty_head);
|
||||
KC_LIST_CMP_CONST struct cached_item *a = list_entry(A, KC_LIST_CMP_CONST struct cached_item, dirty_head);
|
||||
KC_LIST_CMP_CONST struct cached_item *b = list_entry(B, KC_LIST_CMP_CONST struct cached_item, dirty_head);
|
||||
|
||||
return scoutfs_key_compare(&a->key, &b->key);
|
||||
}
|
||||
@@ -2693,7 +2693,7 @@ int scoutfs_item_setup(struct super_block *sb)
|
||||
|
||||
KC_INIT_SHRINKER_FUNCS(&cinf->shrinker, item_cache_count_objects,
|
||||
item_cache_scan_objects);
|
||||
KC_REGISTER_SHRINKER(&cinf->shrinker);
|
||||
KC_REGISTER_SHRINKER(&cinf->shrinker, "scoutfs-item:" SCSBF, SCSB_ARGS(sb));
|
||||
#ifdef KC_CPU_NOTIFIER
|
||||
cinf->notifier.notifier_call = item_cpu_callback;
|
||||
register_hotcpu_notifier(&cinf->notifier);
|
||||
|
||||
@@ -67,12 +67,11 @@ kc_generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos, loff_t *ppos,
|
||||
size_t count, ssize_t written)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
ssize_t status;
|
||||
struct iov_iter i;
|
||||
|
||||
iov_iter_init(&i, WRITE, iov, nr_segs, count);
|
||||
status = generic_perform_write(file, &i, pos);
|
||||
status = kc_generic_perform_write(iocb, &i, pos);
|
||||
|
||||
if (likely(status >= 0)) {
|
||||
written += status;
|
||||
|
||||
@@ -197,7 +197,11 @@ struct timespec64 kc_current_time(struct inode *inode);
|
||||
} while (0)
|
||||
|
||||
#define KC_SHRINKER_CONTAINER_OF(ptr, type) container_of(ptr, type, shrinker)
|
||||
#define KC_REGISTER_SHRINKER(ptr) (register_shrinker(ptr))
|
||||
#ifdef KC_SHRINKER_NAME
|
||||
#define KC_REGISTER_SHRINKER register_shrinker
|
||||
#else
|
||||
#define KC_REGISTER_SHRINKER(ptr, fmt, ...) (register_shrinker(ptr))
|
||||
#endif /* KC_SHRINKER_NAME */
|
||||
#define KC_UNREGISTER_SHRINKER(ptr) (unregister_shrinker(ptr))
|
||||
#define KC_SHRINKER_FN(ptr) (ptr)
|
||||
#else
|
||||
@@ -224,7 +228,7 @@ struct kc_shrinker_wrapper {
|
||||
_wrap->shrink.seeks = DEFAULT_SEEKS; \
|
||||
} while (0)
|
||||
#define KC_SHRINKER_CONTAINER_OF(ptr, type) container_of(container_of(ptr, struct kc_shrinker_wrapper, shrink), type, shrinker)
|
||||
#define KC_REGISTER_SHRINKER(ptr) (register_shrinker(ptr.shrink))
|
||||
#define KC_REGISTER_SHRINKER(ptr, fmt, ...) (register_shrinker(ptr.shrink))
|
||||
#define KC_UNREGISTER_SHRINKER(ptr) (unregister_shrinker(ptr.shrink))
|
||||
#define KC_SHRINKER_FN(ptr) (ptr.shrink)
|
||||
|
||||
@@ -271,6 +275,167 @@ ssize_t kc_generic_file_buffered_write(struct kiocb *iocb, const struct iovec *i
|
||||
unsigned long nr_segs, loff_t pos, loff_t *ppos,
|
||||
size_t count, ssize_t written);
|
||||
#define generic_file_buffered_write kc_generic_file_buffered_write
|
||||
#ifdef KC_GENERIC_PERFORM_WRITE_KIOCB_IOV_ITER
|
||||
static inline int kc_generic_perform_write(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
|
||||
{
|
||||
iocb->ki_pos = pos;
|
||||
return generic_perform_write(iocb, iter);
|
||||
}
|
||||
#else
|
||||
static inline int kc_generic_perform_write(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
return generic_perform_write(file, iter, pos);
|
||||
}
|
||||
#endif
|
||||
#endif // KC_GENERIC_FILE_BUFFERED_WRITE
|
||||
|
||||
#ifndef KC_HAVE_BLK_OPF_T
|
||||
/* typedef __u32 __bitwise blk_opf_t; */
|
||||
typedef unsigned int blk_opf_t;
|
||||
#endif
|
||||
|
||||
#ifdef KC_LIST_CMP_CONST_ARG_LIST_HEAD
|
||||
#define KC_LIST_CMP_CONST const
|
||||
#else
|
||||
#define KC_LIST_CMP_CONST
|
||||
#endif
|
||||
|
||||
#ifdef KC_VMALLOC_PGPROT_T
|
||||
#define kc__vmalloc(size, gfp_mask) __vmalloc(size, gfp_mask, PAGE_KERNEL)
|
||||
#else
|
||||
#define kc__vmalloc __vmalloc
|
||||
#endif
|
||||
|
||||
#ifdef KC_VFS_METHOD_USER_NAMESPACE_ARG
|
||||
#define KC_VFS_NS_DEF struct user_namespace *mnt_user_ns,
|
||||
#define KC_VFS_NS mnt_user_ns,
|
||||
#define KC_VFS_INIT_NS &init_user_ns,
|
||||
#else
|
||||
#define KC_VFS_NS_DEF
|
||||
#define KC_VFS_NS
|
||||
#define KC_VFS_INIT_NS
|
||||
#endif
|
||||
|
||||
#ifdef KC_BIO_ALLOC_DEV_OPF_ARGS
|
||||
#define kc_bio_alloc bio_alloc
|
||||
#else
|
||||
#include <linux/bio.h>
|
||||
static inline struct bio *kc_bio_alloc(struct block_device *bdev, unsigned short nr_vecs,
|
||||
blk_opf_t opf, gfp_t gfp_mask)
|
||||
{
|
||||
struct bio *b = bio_alloc(gfp_mask, nr_vecs);
|
||||
if (b) {
|
||||
kc_bio_set_opf(b, opf);
|
||||
bio_set_dev(b, bdev);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef KC_FIEMAP_PREP
|
||||
#define fiemap_prep(inode, fieinfo, start, len, flags) fiemap_check_flags(fieinfo, flags)
|
||||
#endif
|
||||
|
||||
#ifndef KC_KERNEL_OLD_TIMEVAL_STRUCT
|
||||
#define __kernel_old_timeval timeval
|
||||
#define ns_to_kernel_old_timeval(ktime) ns_to_timeval(ktime.tv64)
|
||||
#endif
|
||||
|
||||
#ifdef KC_SOCK_SET_SNDTIMEO
|
||||
#include <net/sock.h>
|
||||
static inline int kc_sock_set_sndtimeo(struct socket *sock, s64 secs)
|
||||
{
|
||||
sock_set_sndtimeo(sock->sk, secs);
|
||||
return 0;
|
||||
}
|
||||
static inline int kc_tcp_sock_set_rcvtimeo(struct socket *sock, ktime_t to)
|
||||
{
|
||||
struct __kernel_old_timeval tv;
|
||||
sockptr_t kopt;
|
||||
|
||||
tv = ns_to_kernel_old_timeval(to);
|
||||
|
||||
kopt = KERNEL_SOCKPTR(&tv);
|
||||
|
||||
return sock_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO_NEW,
|
||||
kopt, sizeof(tv));
|
||||
}
|
||||
#else
|
||||
#include <net/sock.h>
|
||||
static inline int kc_sock_set_sndtimeo(struct socket *sock, s64 secs)
|
||||
{
|
||||
struct timeval tv = { .tv_sec = secs, .tv_usec = 0 };
|
||||
return kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
|
||||
(char *)&tv, sizeof(tv));
|
||||
}
|
||||
static inline int kc_tcp_sock_set_rcvtimeo(struct socket *sock, ktime_t to)
|
||||
{
|
||||
struct __kernel_old_timeval tv;
|
||||
|
||||
tv = ns_to_kernel_old_timeval(to);
|
||||
return kernel_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
|
||||
(char *)&tv, sizeof(tv));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef KC_SETSOCKOPT_SOCKPTR_T
|
||||
static inline int kc_sock_setsockopt(struct socket *sock, int level, int op, int *optval, unsigned int optlen)
|
||||
{
|
||||
sockptr_t kopt = KERNEL_SOCKPTR(optval);
|
||||
return sock_setsockopt(sock, level, op, kopt, sizeof(optval));
|
||||
}
|
||||
#else
|
||||
static inline int kc_sock_setsockopt(struct socket *sock, int level, int op, int *optval, unsigned int optlen)
|
||||
{
|
||||
return kernel_setsockopt(sock, level, op, (char *)optval, sizeof(optval));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef KC_HAVE_TCP_SET_SOCKFN
|
||||
#include <linux/net.h>
|
||||
#include <net/tcp.h>
|
||||
static inline int kc_tcp_sock_set_keepintvl(struct socket *sock, int val)
|
||||
{
|
||||
return tcp_sock_set_keepintvl(sock->sk, val);
|
||||
}
|
||||
static inline int kc_tcp_sock_set_keepidle(struct socket *sock, int val)
|
||||
{
|
||||
return tcp_sock_set_keepidle(sock->sk, val);
|
||||
}
|
||||
static inline int kc_tcp_sock_set_user_timeout(struct socket *sock, int val)
|
||||
{
|
||||
tcp_sock_set_user_timeout(sock->sk, val);
|
||||
return 0;
|
||||
}
|
||||
static inline int kc_tcp_sock_set_nodelay(struct socket *sock)
|
||||
{
|
||||
tcp_sock_set_nodelay(sock->sk);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#include <linux/net.h>
|
||||
#include <net/tcp.h>
|
||||
static inline int kc_tcp_sock_set_keepintvl(struct socket *sock, int val)
|
||||
{
|
||||
int optval = val;
|
||||
return kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, (char *)&optval, sizeof(optval));
|
||||
}
|
||||
static inline int kc_tcp_sock_set_keepidle(struct socket *sock, int val)
|
||||
{
|
||||
int optval = val;
|
||||
return kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, (char *)&optval, sizeof(optval));
|
||||
}
|
||||
static inline int kc_tcp_sock_set_user_timeout(struct socket *sock, int val)
|
||||
{
|
||||
int optval = val;
|
||||
return kernel_setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT, (char *)&optval, sizeof(optval));
|
||||
}
|
||||
static inline int kc_tcp_sock_set_nodelay(struct socket *sock)
|
||||
{
|
||||
int optval = 1;
|
||||
return kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&optval, sizeof(optval));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -125,8 +125,8 @@ static inline bool scoutfs_key_is_ones(struct scoutfs_key *key)
|
||||
* other alternatives across keys that first differ in any of the
|
||||
* values. Say maybe 20% faster than memcmp.
|
||||
*/
|
||||
static inline int scoutfs_key_compare(struct scoutfs_key *a,
|
||||
struct scoutfs_key *b)
|
||||
static inline int scoutfs_key_compare(const struct scoutfs_key *a,
|
||||
const struct scoutfs_key *b)
|
||||
{
|
||||
return scoutfs_cmp(a->sk_zone, b->sk_zone) ?:
|
||||
scoutfs_cmp(le64_to_cpu(a->_sk_first), le64_to_cpu(b->_sk_first)) ?:
|
||||
@@ -142,10 +142,10 @@ static inline int scoutfs_key_compare(struct scoutfs_key *a,
|
||||
* 1: a_start > b_end
|
||||
* else 0: ranges overlap
|
||||
*/
|
||||
static inline int scoutfs_key_compare_ranges(struct scoutfs_key *a_start,
|
||||
struct scoutfs_key *a_end,
|
||||
struct scoutfs_key *b_start,
|
||||
struct scoutfs_key *b_end)
|
||||
static inline int scoutfs_key_compare_ranges(const struct scoutfs_key *a_start,
|
||||
const struct scoutfs_key *a_end,
|
||||
const struct scoutfs_key *b_start,
|
||||
const struct scoutfs_key *b_end)
|
||||
{
|
||||
return scoutfs_key_compare(a_end, b_start) < 0 ? -1 :
|
||||
scoutfs_key_compare(a_start, b_end) > 0 ? 1 :
|
||||
|
||||
@@ -1732,7 +1732,7 @@ int scoutfs_lock_setup(struct super_block *sb)
|
||||
linfo->lock_range_tree = RB_ROOT;
|
||||
KC_INIT_SHRINKER_FUNCS(&linfo->shrinker, lock_count_objects,
|
||||
lock_scan_objects);
|
||||
KC_REGISTER_SHRINKER(&linfo->shrinker);
|
||||
KC_REGISTER_SHRINKER(&linfo->shrinker, "scoutfs-lock:" SCSBF, SCSB_ARGS(sb));
|
||||
INIT_LIST_HEAD(&linfo->lru_list);
|
||||
INIT_WORK(&linfo->inv_work, lock_invalidate_worker);
|
||||
INIT_LIST_HEAD(&linfo->inv_list);
|
||||
|
||||
@@ -202,21 +202,48 @@ static u8 invalidation_mode(u8 granted, u8 requested)
|
||||
|
||||
/*
|
||||
* Return true of the client lock instances described by the entries can
|
||||
* be granted at the same time. Typically this only means they're both
|
||||
* modes that are compatible between nodes. In addition there's the
|
||||
* special case where a read lock on a client is compatible with a write
|
||||
* lock on the same client because the client's cache covered by the
|
||||
* read lock is still valid if they get a write lock.
|
||||
* be granted at the same time. There's only three cases where this is
|
||||
* true.
|
||||
*
|
||||
* First, the two locks are both of the same mode that allows full
|
||||
* sharing -- read and write only. The only point of these modes is
|
||||
* that everyone can share them.
|
||||
*
|
||||
* Second, a write lock gives the client permission to read as well.
|
||||
* This means that a client can upgrade its read lock to a write lock
|
||||
* without having to invalidate the existing read and drop caches.
|
||||
*
|
||||
* Third, null locks are always compatible between clients. It's as
|
||||
* though the client with the null lock has no lock at all. But it's
|
||||
* never compatible with all locks on the client requesting null.
|
||||
* Sending invalidations for existing locks on a client when we get a
|
||||
* null request is how we resolve races in shrinking locks -- we turn it
|
||||
* into the unsolicited remote invalidation case.
|
||||
*
|
||||
* All other mode and client combinations can not be shared, most
|
||||
* typically a write lock invalidating all other non-write holders to
|
||||
* drop caches and force a read after the write has completed.
|
||||
*/
|
||||
static bool client_entries_compatible(struct client_lock_entry *granted,
|
||||
struct client_lock_entry *requested)
|
||||
{
|
||||
return (granted->mode == requested->mode &&
|
||||
(granted->mode == SCOUTFS_LOCK_READ ||
|
||||
granted->mode == SCOUTFS_LOCK_WRITE_ONLY)) ||
|
||||
(granted->rid == requested->rid &&
|
||||
granted->mode == SCOUTFS_LOCK_READ &&
|
||||
requested->mode == SCOUTFS_LOCK_WRITE);
|
||||
/* only read and write_only can be full shared */
|
||||
if ((granted->mode == requested->mode) &&
|
||||
(granted->mode == SCOUTFS_LOCK_READ || granted->mode == SCOUTFS_LOCK_WRITE_ONLY))
|
||||
return true;
|
||||
|
||||
/* _write includes reading, so a client can upgrade its read to write */
|
||||
if (granted->rid == requested->rid &&
|
||||
granted->mode == SCOUTFS_LOCK_READ &&
|
||||
requested->mode == SCOUTFS_LOCK_WRITE)
|
||||
return true;
|
||||
|
||||
/* null is always compatible across clients, never within a client */
|
||||
if ((granted->rid != requested->rid) &&
|
||||
(granted->mode == SCOUTFS_LOCK_NULL || requested->mode == SCOUTFS_LOCK_NULL))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -317,16 +344,18 @@ static void put_server_lock(struct lock_server_info *inf,
|
||||
|
||||
BUG_ON(!mutex_is_locked(&snode->mutex));
|
||||
|
||||
spin_lock(&inf->lock);
|
||||
|
||||
if (atomic_dec_and_test(&snode->refcount) &&
|
||||
list_empty(&snode->granted) &&
|
||||
list_empty(&snode->requested) &&
|
||||
list_empty(&snode->invalidated)) {
|
||||
spin_lock(&inf->lock);
|
||||
rb_erase(&snode->node, &inf->locks_root);
|
||||
spin_unlock(&inf->lock);
|
||||
should_free = true;
|
||||
}
|
||||
|
||||
spin_unlock(&inf->lock);
|
||||
|
||||
mutex_unlock(&snode->mutex);
|
||||
|
||||
if (should_free) {
|
||||
|
||||
@@ -502,12 +502,12 @@ static void scoutfs_net_proc_worker(struct work_struct *work)
|
||||
* Free live responses up to and including the seq by marking them dead
|
||||
* and moving them to the send queue to be freed.
|
||||
*/
|
||||
static int move_acked_responses(struct scoutfs_net_connection *conn,
|
||||
struct list_head *list, u64 seq)
|
||||
static bool move_acked_responses(struct scoutfs_net_connection *conn,
|
||||
struct list_head *list, u64 seq)
|
||||
{
|
||||
struct message_send *msend;
|
||||
struct message_send *tmp;
|
||||
int ret = 0;
|
||||
bool moved = false;
|
||||
|
||||
assert_spin_locked(&conn->lock);
|
||||
|
||||
@@ -519,20 +519,20 @@ static int move_acked_responses(struct scoutfs_net_connection *conn,
|
||||
|
||||
msend->dead = 1;
|
||||
list_move(&msend->head, &conn->send_queue);
|
||||
ret = 1;
|
||||
moved = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return moved;
|
||||
}
|
||||
|
||||
/* acks are processed inline in the recv worker */
|
||||
static void free_acked_responses(struct scoutfs_net_connection *conn, u64 seq)
|
||||
{
|
||||
int moved;
|
||||
bool moved;
|
||||
|
||||
spin_lock(&conn->lock);
|
||||
|
||||
moved = move_acked_responses(conn, &conn->send_queue, seq) +
|
||||
moved = move_acked_responses(conn, &conn->send_queue, seq) |
|
||||
move_acked_responses(conn, &conn->resend_queue, seq);
|
||||
|
||||
spin_unlock(&conn->lock);
|
||||
@@ -904,53 +904,44 @@ static void destroy_conn(struct scoutfs_net_connection *conn)
|
||||
static int sock_opts_and_names(struct scoutfs_net_connection *conn,
|
||||
struct socket *sock)
|
||||
{
|
||||
struct timeval tv;
|
||||
int optval;
|
||||
int ret;
|
||||
|
||||
/* we use a keepalive timeout instead of send timeout */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
ret = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
|
||||
(char *)&tv, sizeof(tv));
|
||||
ret = kc_sock_set_sndtimeo(sock, 0);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* not checked when user_timeout != 0, but for clarity */
|
||||
optval = UNRESPONSIVE_PROBES;
|
||||
ret = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
|
||||
(char *)&optval, sizeof(optval));
|
||||
ret = kc_sock_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
|
||||
&optval, sizeof(optval));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
BUILD_BUG_ON(UNRESPONSIVE_PROBES >= UNRESPONSIVE_TIMEOUT_SECS);
|
||||
optval = UNRESPONSIVE_TIMEOUT_SECS - (UNRESPONSIVE_PROBES);
|
||||
ret = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE,
|
||||
(char *)&optval, sizeof(optval));
|
||||
ret = kc_tcp_sock_set_keepidle(sock, optval);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
optval = 1;
|
||||
ret = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,
|
||||
(char *)&optval, sizeof(optval));
|
||||
ret = kc_tcp_sock_set_keepintvl(sock, optval);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
optval = UNRESPONSIVE_TIMEOUT_SECS * MSEC_PER_SEC;
|
||||
ret = kernel_setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT,
|
||||
(char *)&optval, sizeof(optval));
|
||||
ret = kc_tcp_sock_set_user_timeout(sock, optval);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
optval = 1;
|
||||
ret = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(char *)&optval, sizeof(optval));
|
||||
ret = kc_sock_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
|
||||
&optval, sizeof(optval));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
optval = 1;
|
||||
ret = kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
|
||||
(char *)&optval, sizeof(optval));
|
||||
ret = kc_tcp_sock_set_nodelay(sock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -1049,7 +1040,6 @@ static void scoutfs_net_connect_worker(struct work_struct *work)
|
||||
DEFINE_CONN_FROM_WORK(conn, work, connect_work);
|
||||
struct super_block *sb = conn->sb;
|
||||
struct socket *sock;
|
||||
struct timeval tv;
|
||||
int ret;
|
||||
|
||||
trace_scoutfs_net_connect_work_enter(sb, 0, 0);
|
||||
@@ -1060,11 +1050,8 @@ static void scoutfs_net_connect_worker(struct work_struct *work)
|
||||
|
||||
sock->sk->sk_allocation = GFP_NOFS;
|
||||
|
||||
/* caller specified connect timeout */
|
||||
tv.tv_sec = conn->connect_timeout_ms / MSEC_PER_SEC;
|
||||
tv.tv_usec = (conn->connect_timeout_ms % MSEC_PER_SEC) * USEC_PER_MSEC;
|
||||
ret = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
|
||||
(char *)&tv, sizeof(tv));
|
||||
/* caller specified connect timeout, defaults to 1 sec */
|
||||
ret = kc_sock_set_sndtimeo(sock, conn->connect_timeout_ms / MSEC_PER_SEC);
|
||||
if (ret) {
|
||||
sock_release(sock);
|
||||
goto out;
|
||||
@@ -1462,8 +1449,8 @@ int scoutfs_net_bind(struct super_block *sb,
|
||||
sock->sk->sk_allocation = GFP_NOFS;
|
||||
|
||||
optval = 1;
|
||||
ret = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char *)&optval, sizeof(optval));
|
||||
ret = kc_sock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
&optval, sizeof(optval));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -303,7 +303,6 @@ static int recv_msg(struct super_block *sb, struct quorum_host_msg *msg,
|
||||
DECLARE_QUORUM_INFO(sb, qinf);
|
||||
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
|
||||
struct scoutfs_quorum_message qmes;
|
||||
struct timeval tv;
|
||||
ktime_t rel_to;
|
||||
ktime_t now;
|
||||
int ret;
|
||||
@@ -328,14 +327,10 @@ static int recv_msg(struct super_block *sb, struct quorum_host_msg *msg,
|
||||
else
|
||||
rel_to = ns_to_ktime(0);
|
||||
|
||||
tv = ktime_to_timeval(rel_to);
|
||||
if (tv.tv_sec == 0 && tv.tv_usec == 0) {
|
||||
if (ktime_compare(rel_to, ns_to_ktime(NSEC_PER_USEC)) <= 0) {
|
||||
mh.msg_flags |= MSG_DONTWAIT;
|
||||
} else {
|
||||
ret = kernel_setsockopt(qinf->sock, SOL_SOCKET, SO_RCVTIMEO,
|
||||
(char *)&tv, sizeof(tv));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = kc_tcp_sock_set_rcvtimeo(qinf->sock, rel_to);
|
||||
}
|
||||
|
||||
#ifdef KC_MSGHDR_STRUCT_IOV_ITER
|
||||
@@ -486,7 +481,7 @@ static void set_quorum_block_event(struct super_block *sb, struct scoutfs_quorum
|
||||
if (WARN_ON_ONCE(event < 0 || event >= SCOUTFS_QUORUM_EVENT_NR))
|
||||
return;
|
||||
|
||||
getnstimeofday64(&ts);
|
||||
ktime_get_ts64(&ts);
|
||||
le64_add_cpu(&blk->write_nr, 1);
|
||||
|
||||
ev = &blk->events[event];
|
||||
@@ -1325,8 +1320,8 @@ int scoutfs_quorum_setup(struct super_block *sb)
|
||||
qinf = kzalloc(sizeof(struct quorum_info), GFP_KERNEL);
|
||||
super = kmalloc(sizeof(struct scoutfs_super_block), GFP_KERNEL);
|
||||
if (qinf)
|
||||
qinf->hb_delay = __vmalloc(HB_DELAY_NR * sizeof(struct count_recent),
|
||||
GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
|
||||
qinf->hb_delay = kc__vmalloc(HB_DELAY_NR * sizeof(struct count_recent),
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!qinf || !super || !qinf->hb_delay) {
|
||||
if (qinf)
|
||||
vfree(qinf->hb_delay);
|
||||
|
||||
@@ -1226,7 +1226,7 @@ int scoutfs_quota_setup(struct super_block *sb)
|
||||
init_waitqueue_head(&qtinf->waitq);
|
||||
|
||||
KC_INIT_SHRINKER_FUNCS(&qtinf->shrinker, count_cached_checks, scan_cached_checks);
|
||||
KC_REGISTER_SHRINKER(&qtinf->shrinker);
|
||||
KC_REGISTER_SHRINKER(&qtinf->shrinker, "scoutfs-quota:" SCSBF, SCSB_ARGS(sb));
|
||||
|
||||
sbi->squota_info = qtinf;
|
||||
|
||||
|
||||
@@ -76,10 +76,10 @@ static struct recov_pending *lookup_pending(struct recov_info *recinf, u64 rid,
|
||||
* We keep the pending list sorted by rid so that we can iterate over
|
||||
* them. The list should be small and shouldn't be used often.
|
||||
*/
|
||||
static int cmp_pending_rid(void *priv, struct list_head *A, struct list_head *B)
|
||||
static int cmp_pending_rid(void *priv, KC_LIST_CMP_CONST struct list_head *A, KC_LIST_CMP_CONST struct list_head *B)
|
||||
{
|
||||
struct recov_pending *a = list_entry(A, struct recov_pending, head);
|
||||
struct recov_pending *b = list_entry(B, struct recov_pending, head);
|
||||
KC_LIST_CMP_CONST struct recov_pending *a = list_entry(A, KC_LIST_CMP_CONST struct recov_pending, head);
|
||||
KC_LIST_CMP_CONST struct recov_pending *b = list_entry(B, KC_LIST_CMP_CONST struct recov_pending, head);
|
||||
|
||||
return scoutfs_cmp_u64s(a->rid, b->rid);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/unaligned/access_ok.h>
|
||||
|
||||
#include "key.h"
|
||||
#include "format.h"
|
||||
@@ -1047,9 +1046,12 @@ DECLARE_EVENT_CLASS(scoutfs_lock_class,
|
||||
sk_trace_define(start)
|
||||
sk_trace_define(end)
|
||||
__field(u64, refresh_gen)
|
||||
__field(u64, write_seq)
|
||||
__field(u64, dirty_trans_seq)
|
||||
__field(unsigned char, request_pending)
|
||||
__field(unsigned char, invalidate_pending)
|
||||
__field(int, mode)
|
||||
__field(int, invalidating_mode)
|
||||
__field(unsigned int, waiters_cw)
|
||||
__field(unsigned int, waiters_pr)
|
||||
__field(unsigned int, waiters_ex)
|
||||
@@ -1062,9 +1064,12 @@ DECLARE_EVENT_CLASS(scoutfs_lock_class,
|
||||
sk_trace_assign(start, &lck->start);
|
||||
sk_trace_assign(end, &lck->end);
|
||||
__entry->refresh_gen = lck->refresh_gen;
|
||||
__entry->write_seq = lck->write_seq;
|
||||
__entry->dirty_trans_seq = lck->dirty_trans_seq;
|
||||
__entry->request_pending = lck->request_pending;
|
||||
__entry->invalidate_pending = lck->invalidate_pending;
|
||||
__entry->mode = lck->mode;
|
||||
__entry->invalidating_mode = lck->invalidating_mode;
|
||||
__entry->waiters_pr = lck->waiters[SCOUTFS_LOCK_READ];
|
||||
__entry->waiters_ex = lck->waiters[SCOUTFS_LOCK_WRITE];
|
||||
__entry->waiters_cw = lck->waiters[SCOUTFS_LOCK_WRITE_ONLY];
|
||||
@@ -1072,10 +1077,11 @@ DECLARE_EVENT_CLASS(scoutfs_lock_class,
|
||||
__entry->users_ex = lck->users[SCOUTFS_LOCK_WRITE];
|
||||
__entry->users_cw = lck->users[SCOUTFS_LOCK_WRITE_ONLY];
|
||||
),
|
||||
TP_printk(SCSBF" start "SK_FMT" end "SK_FMT" mode %u reqpnd %u invpnd %u rfrgen %llu waiters: pr %u ex %u cw %u users: pr %u ex %u cw %u",
|
||||
TP_printk(SCSBF" start "SK_FMT" end "SK_FMT" mode %u invmd %u reqp %u invp %u refg %llu wris %llu dts %llu waiters: pr %u ex %u cw %u users: pr %u ex %u cw %u",
|
||||
SCSB_TRACE_ARGS, sk_trace_args(start), sk_trace_args(end),
|
||||
__entry->mode, __entry->request_pending,
|
||||
__entry->invalidate_pending, __entry->refresh_gen,
|
||||
__entry->mode, __entry->invalidating_mode, __entry->request_pending,
|
||||
__entry->invalidate_pending, __entry->refresh_gen, __entry->write_seq,
|
||||
__entry->dirty_trans_seq,
|
||||
__entry->waiters_pr, __entry->waiters_ex, __entry->waiters_cw,
|
||||
__entry->users_pr, __entry->users_ex, __entry->users_cw)
|
||||
);
|
||||
|
||||
@@ -298,7 +298,7 @@ static void check_holder_budget(struct super_block *sb, struct server_info *serv
|
||||
{
|
||||
static bool exceeded_once = false;
|
||||
struct commit_hold *hold;
|
||||
struct timespec ts;
|
||||
struct timespec64 ts;
|
||||
u32 avail_used;
|
||||
u32 freed_used;
|
||||
u32 avail_now;
|
||||
@@ -330,7 +330,7 @@ static void check_holder_budget(struct super_block *sb, struct server_info *serv
|
||||
cusers->freed_before, freed_now);
|
||||
|
||||
list_for_each_entry(hold, &cusers->holding, entry) {
|
||||
ts = ktime_to_timespec(hold->start);
|
||||
ts = ktime_to_timespec64(hold->start);
|
||||
scoutfs_err(sb, "exceeding hold start %llu.%09llu av %u fr %u",
|
||||
(u64)ts.tv_sec, (u64)ts.tv_nsec, hold->avail, hold->freed);
|
||||
hold->exceeded = true;
|
||||
@@ -445,7 +445,7 @@ static int server_apply_commit(struct super_block *sb, struct commit_hold *hold,
|
||||
{
|
||||
DECLARE_SERVER_INFO(sb, server);
|
||||
struct commit_users *cusers = &server->cusers;
|
||||
struct timespec ts;
|
||||
struct timespec64 ts;
|
||||
|
||||
spin_lock(&cusers->lock);
|
||||
|
||||
@@ -454,7 +454,7 @@ static int server_apply_commit(struct super_block *sb, struct commit_hold *hold,
|
||||
check_holder_budget(sb, server, cusers);
|
||||
|
||||
if (hold->exceeded) {
|
||||
ts = ktime_to_timespec(hold->start);
|
||||
ts = ktime_to_timespec64(hold->start);
|
||||
scoutfs_err(sb, "exceeding hold start %llu.%09llu stack:",
|
||||
(u64)ts.tv_sec, (u64)ts.tv_nsec);
|
||||
dump_stack();
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/sort.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "super.h"
|
||||
#include "format.h"
|
||||
@@ -1588,8 +1589,7 @@ static int kway_merge(struct super_block *sb,
|
||||
nr_parents = max_t(unsigned long, 1, roundup_pow_of_two(nr) - 1);
|
||||
/* root at [1] for easy sib/parent index calc, final pad for odd sib */
|
||||
nr_nodes = 1 + nr_parents + nr + 1;
|
||||
tnodes = __vmalloc(nr_nodes * sizeof(struct tourn_node),
|
||||
GFP_NOFS, PAGE_KERNEL);
|
||||
tnodes = kc__vmalloc(nr_nodes * sizeof(struct tourn_node), GFP_NOFS);
|
||||
if (!tnodes)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -160,7 +160,11 @@ static void scoutfs_metadev_close(struct super_block *sb)
|
||||
* from kill_sb->put_super.
|
||||
*/
|
||||
lockdep_off();
|
||||
#ifdef KC_BLKDEV_PUT_HOLDER_ARG
|
||||
blkdev_put(sbi->meta_bdev, sb);
|
||||
#else
|
||||
blkdev_put(sbi->meta_bdev, SCOUTFS_META_BDEV_MODE);
|
||||
#endif
|
||||
lockdep_on();
|
||||
sbi->meta_bdev = NULL;
|
||||
}
|
||||
@@ -523,7 +527,11 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef KC_BLKDEV_PUT_HOLDER_ARG
|
||||
meta_bdev = blkdev_get_by_path(opts.metadev_path, SCOUTFS_META_BDEV_MODE, sb, NULL);
|
||||
#else
|
||||
meta_bdev = blkdev_get_by_path(opts.metadev_path, SCOUTFS_META_BDEV_MODE, sb);
|
||||
#endif
|
||||
if (IS_ERR(meta_bdev)) {
|
||||
scoutfs_err(sb, "could not open metadev: error %ld",
|
||||
PTR_ERR(meta_bdev));
|
||||
|
||||
@@ -101,7 +101,11 @@ static inline bool SCOUTFS_IS_META_BDEV(struct scoutfs_super_block *super_block)
|
||||
return !!(le64_to_cpu(super_block->flags) & SCOUTFS_FLAG_IS_META_BDEV);
|
||||
}
|
||||
|
||||
#ifdef KC_HAVE_BLK_MODE_T
|
||||
#define SCOUTFS_META_BDEV_MODE (BLK_OPEN_READ | BLK_OPEN_WRITE | BLK_OPEN_EXCL)
|
||||
#else
|
||||
#define SCOUTFS_META_BDEV_MODE (FMODE_READ | FMODE_WRITE | FMODE_EXCL)
|
||||
#endif
|
||||
|
||||
static inline bool scoutfs_forcing_unmount(struct super_block *sb)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/blkdev.h>
|
||||
|
||||
#include "super.h"
|
||||
#include "sysfs.h"
|
||||
|
||||
@@ -93,13 +93,9 @@ int scoutfs_setup_triggers(struct super_block *sb)
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(triggers->atomics); i++) {
|
||||
if (!debugfs_create_atomic_t(names[i], 0644, triggers->dir,
|
||||
&triggers->atomics[i])) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(triggers->atomics); i++)
|
||||
debugfs_create_atomic_t(names[i], 0644, triggers->dir,
|
||||
&triggers->atomics[i]);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
|
||||
@@ -183,6 +183,13 @@ static void *scoutfs_tseq_seq_next(struct seq_file *m, void *v, loff_t *pos)
|
||||
ent = tseq_rb_next(ent);
|
||||
if (ent)
|
||||
*pos = ent->pos;
|
||||
else
|
||||
/*
|
||||
* once we hit the end, *pos is never used, but it has to
|
||||
* be updated to avoid an error in bpf_seq_read()
|
||||
*/
|
||||
(*pos)++;
|
||||
|
||||
return ent;
|
||||
}
|
||||
|
||||
|
||||
@@ -1113,7 +1113,7 @@ int scoutfs_wkic_setup(struct super_block *sb)
|
||||
|
||||
winf->sb = sb;
|
||||
KC_INIT_SHRINKER_FUNCS(&winf->shrinker, wkic_shrink_count, wkic_shrink_scan);
|
||||
KC_REGISTER_SHRINKER(&winf->shrinker);
|
||||
KC_REGISTER_SHRINKER(&winf->shrinker, "scoutfs-weak_item:" SCSBF, SCSB_ARGS(sb));
|
||||
|
||||
sbi->wkic_info = winf;
|
||||
return 0;
|
||||
|
||||
@@ -1026,7 +1026,9 @@ static int scoutfs_xattr_get_handler
|
||||
|
||||
static int scoutfs_xattr_set_handler
|
||||
#ifdef KC_XATTR_STRUCT_XATTR_HANDLER
|
||||
(const struct xattr_handler *handler, struct dentry *dentry,
|
||||
(const struct xattr_handler *handler,
|
||||
KC_VFS_NS_DEF
|
||||
struct dentry *dentry,
|
||||
struct inode *inode, const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
|
||||
1
tests/.xfstests-branch
Normal file
1
tests/.xfstests-branch
Normal file
@@ -0,0 +1 @@
|
||||
v2022.05.01-2-g787cd20
|
||||
@@ -7,8 +7,9 @@ t_status_msg()
|
||||
export T_PASS_STATUS=100
|
||||
export T_SKIP_STATUS=101
|
||||
export T_FAIL_STATUS=102
|
||||
export T_SKIP_PERMITTED_STATUS=103
|
||||
export T_FIRST_STATUS="$T_PASS_STATUS"
|
||||
export T_LAST_STATUS="$T_FAIL_STATUS"
|
||||
export T_LAST_STATUS="$T_SKIP_PERMITTED_STATUS"
|
||||
|
||||
t_pass()
|
||||
{
|
||||
@@ -21,6 +22,17 @@ t_skip()
|
||||
exit $T_SKIP_STATUS
|
||||
}
|
||||
|
||||
#
|
||||
# This exit code is *reserved* for tests that are up-front never going to work
|
||||
# in certain cases. This should be expressly documented per-case and made
|
||||
# abundantly clear before merging. The test itself should document its case.
|
||||
#
|
||||
t_skip_permitted()
|
||||
{
|
||||
t_status_msg "$@"
|
||||
exit $T_SKIP_PERMITTED_STATUS
|
||||
}
|
||||
|
||||
t_fail()
|
||||
{
|
||||
t_status_msg "$@"
|
||||
|
||||
@@ -143,14 +143,23 @@ t_filter_dmesg()
|
||||
# change-devices causes loop device resizing
|
||||
re="$re|loop: module loaded"
|
||||
re="$re|loop[0-9].* detected capacity change from.*"
|
||||
re="$re|dm-[0-9].* detected capacity change from.*"
|
||||
|
||||
# ignore systemd-journal rotating
|
||||
re="$re|systemd-journald.*"
|
||||
|
||||
# process accounting can be noisy
|
||||
re="$re|Process accounting resumed.*"
|
||||
|
||||
# format vers back/compat tries bad mounts
|
||||
re="$re|scoutfs .* error.*outside of supported version.*"
|
||||
re="$re|scoutfs .* error.*could not get .*super.*"
|
||||
|
||||
# ignore "unsafe core pattern" when xfstests tries to disable cores"
|
||||
re="$re|Unsafe core_pattern used with fs.suid_dumpable=2.*"
|
||||
re="$re|Pipe handler or fully qualified core dump path required.*"
|
||||
re="$re|Set kernel.core_pattern before fs.suid_dumpable.*"
|
||||
|
||||
egrep -v "($re)" | \
|
||||
ignore_harmless_unwind_kasan_stack_oob
|
||||
}
|
||||
|
||||
@@ -41,9 +41,7 @@ group::r-x
|
||||
mask::rwx
|
||||
other::r-x
|
||||
|
||||
bash: line 0: cd: dir-root: Permission denied
|
||||
Failed
|
||||
bash: line 0: cd: symlinkdir-root: Permission denied
|
||||
Failed
|
||||
# file: dir-root
|
||||
# owner: root
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
== initial writes smaller than prealloc grow to prealloc size
|
||||
/mnt/test/test/data-prealloc/file-1: 7 extents found
|
||||
/mnt/test/test/data-prealloc/file-2: 7 extents found
|
||||
/mnt/test/test/data-prealloc/file-1: extents: 7
|
||||
/mnt/test/test/data-prealloc/file-2: extents: 7
|
||||
== larger files get full prealloc extents
|
||||
/mnt/test/test/data-prealloc/file-1: 9 extents found
|
||||
/mnt/test/test/data-prealloc/file-2: 9 extents found
|
||||
/mnt/test/test/data-prealloc/file-1: extents: 9
|
||||
/mnt/test/test/data-prealloc/file-2: extents: 9
|
||||
== non-streaming writes with contig have per-block extents
|
||||
/mnt/test/test/data-prealloc/file-1: 32 extents found
|
||||
/mnt/test/test/data-prealloc/file-2: 32 extents found
|
||||
/mnt/test/test/data-prealloc/file-1: extents: 32
|
||||
/mnt/test/test/data-prealloc/file-2: extents: 32
|
||||
== any writes to region prealloc get full extents
|
||||
/mnt/test/test/data-prealloc/file-1: 4 extents found
|
||||
/mnt/test/test/data-prealloc/file-2: 4 extents found
|
||||
/mnt/test/test/data-prealloc/file-1: 4 extents found
|
||||
/mnt/test/test/data-prealloc/file-2: 4 extents found
|
||||
/mnt/test/test/data-prealloc/file-1: extents: 4
|
||||
/mnt/test/test/data-prealloc/file-2: extents: 4
|
||||
/mnt/test/test/data-prealloc/file-1: extents: 4
|
||||
/mnt/test/test/data-prealloc/file-2: extents: 4
|
||||
== streaming offline writes get full extents either way
|
||||
/mnt/test/test/data-prealloc/file-1: 4 extents found
|
||||
/mnt/test/test/data-prealloc/file-2: 4 extents found
|
||||
/mnt/test/test/data-prealloc/file-1: 4 extents found
|
||||
/mnt/test/test/data-prealloc/file-2: 4 extents found
|
||||
/mnt/test/test/data-prealloc/file-1: extents: 4
|
||||
/mnt/test/test/data-prealloc/file-2: extents: 4
|
||||
/mnt/test/test/data-prealloc/file-1: extents: 4
|
||||
/mnt/test/test/data-prealloc/file-2: extents: 4
|
||||
== goofy preallocation amounts work
|
||||
/mnt/test/test/data-prealloc/file-1: 5 extents found
|
||||
/mnt/test/test/data-prealloc/file-2: 5 extents found
|
||||
/mnt/test/test/data-prealloc/file-1: 5 extents found
|
||||
/mnt/test/test/data-prealloc/file-2: 5 extents found
|
||||
/mnt/test/test/data-prealloc/file-1: 3 extents found
|
||||
/mnt/test/test/data-prealloc/file-2: 3 extents found
|
||||
/mnt/test/test/data-prealloc/file-1: extents: 6
|
||||
/mnt/test/test/data-prealloc/file-2: extents: 6
|
||||
/mnt/test/test/data-prealloc/file-1: extents: 6
|
||||
/mnt/test/test/data-prealloc/file-2: extents: 6
|
||||
/mnt/test/test/data-prealloc/file-1: extents: 3
|
||||
/mnt/test/test/data-prealloc/file-2: extents: 3
|
||||
== block writes into region allocs hole
|
||||
wrote blk 24
|
||||
wrote blk 32
|
||||
|
||||
2
tests/golden/lock-shrink-read-race
Normal file
2
tests/golden/lock-shrink-read-race
Normal file
@@ -0,0 +1,2 @@
|
||||
=== setup
|
||||
=== spin reading and shrinking
|
||||
@@ -22,10 +22,8 @@ scoutfs: setattr failed: Invalid argument (22)
|
||||
== large ctime is set
|
||||
1972-02-19 00:06:25.999999999 +0000
|
||||
== large offline extents are created
|
||||
Filesystem type is: 554f4353
|
||||
File size of /mnt/test/test/setattr_more/file is 40988672 (10007 blocks of 4096 bytes)
|
||||
ext: logical_offset: physical_offset: length: expected: flags:
|
||||
0: 0.. 10006: 0.. 10006: 10007: unknown,eof
|
||||
/mnt/test/test/setattr_more/file: 1 extent found
|
||||
0: offset: 0 0 length: 10007 flags: O.L
|
||||
extents: 1
|
||||
== correct offline extent length
|
||||
976563
|
||||
== omitting data_version should not fail
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
== create/release/stage single block file
|
||||
0: offset: 0 0 length: 1 flags: O.L
|
||||
extents: 1
|
||||
== create/release/stage larger file
|
||||
0: offset: 0 0 length: 4096 flags: O.L
|
||||
extents: 1
|
||||
== multiple release,drop_cache,stage cycles
|
||||
== release+stage shouldn't change stat, data seq or vers
|
||||
== stage does change meta_seq
|
||||
@@ -7,16 +11,22 @@
|
||||
stage: must provide file version with --data-version
|
||||
Try `stage --help' or `stage --usage' for more information.
|
||||
== wrapped region fails
|
||||
stage returned -1, not 4096: error Invalid argument (22)
|
||||
stage returned -1, not 8192: error Invalid argument (22)
|
||||
scoutfs: stage failed: Input/output error (5)
|
||||
== non-block aligned offset fails
|
||||
stage returned -1, not 4095: error Invalid argument (22)
|
||||
scoutfs: stage failed: Input/output error (5)
|
||||
0: offset: 0 0 length: 1 flags: O.L
|
||||
extents: 1
|
||||
== non-block aligned len within block fails
|
||||
stage returned -1, not 1024: error Invalid argument (22)
|
||||
scoutfs: stage failed: Input/output error (5)
|
||||
0: offset: 0 0 length: 1 flags: O.L
|
||||
extents: 1
|
||||
== partial final block that writes to i_size does work
|
||||
== zero length stage doesn't bring blocks online
|
||||
0: offset: 0 0 length: 100 flags: O.L
|
||||
extents: 1
|
||||
== stage of non-regular file fails
|
||||
ioctl failed: Inappropriate ioctl for device (25)
|
||||
stage: must provide file version with --data-version
|
||||
|
||||
@@ -5,24 +5,44 @@ generic/004
|
||||
generic/005
|
||||
generic/006
|
||||
generic/007
|
||||
generic/008
|
||||
generic/009
|
||||
generic/011
|
||||
generic/012
|
||||
generic/013
|
||||
generic/014
|
||||
generic/015
|
||||
generic/016
|
||||
generic/018
|
||||
generic/020
|
||||
generic/021
|
||||
generic/022
|
||||
generic/023
|
||||
generic/024
|
||||
generic/025
|
||||
generic/026
|
||||
generic/028
|
||||
generic/031
|
||||
generic/032
|
||||
generic/033
|
||||
generic/034
|
||||
generic/035
|
||||
generic/037
|
||||
generic/039
|
||||
generic/040
|
||||
generic/041
|
||||
generic/050
|
||||
generic/052
|
||||
generic/053
|
||||
generic/056
|
||||
generic/057
|
||||
generic/058
|
||||
generic/059
|
||||
generic/060
|
||||
generic/061
|
||||
generic/062
|
||||
generic/063
|
||||
generic/064
|
||||
generic/065
|
||||
generic/066
|
||||
generic/067
|
||||
@@ -31,42 +51,193 @@ generic/070
|
||||
generic/071
|
||||
generic/073
|
||||
generic/076
|
||||
generic/078
|
||||
generic/079
|
||||
generic/081
|
||||
generic/082
|
||||
generic/084
|
||||
generic/086
|
||||
generic/087
|
||||
generic/088
|
||||
generic/090
|
||||
generic/091
|
||||
generic/092
|
||||
generic/094
|
||||
generic/096
|
||||
generic/097
|
||||
generic/098
|
||||
generic/099
|
||||
generic/101
|
||||
generic/104
|
||||
generic/105
|
||||
generic/106
|
||||
generic/107
|
||||
generic/110
|
||||
generic/111
|
||||
generic/113
|
||||
generic/114
|
||||
generic/115
|
||||
generic/116
|
||||
generic/117
|
||||
generic/118
|
||||
generic/119
|
||||
generic/121
|
||||
generic/122
|
||||
generic/123
|
||||
generic/124
|
||||
generic/128
|
||||
generic/129
|
||||
generic/130
|
||||
generic/131
|
||||
generic/134
|
||||
generic/135
|
||||
generic/136
|
||||
generic/138
|
||||
generic/139
|
||||
generic/140
|
||||
generic/142
|
||||
generic/143
|
||||
generic/144
|
||||
generic/145
|
||||
generic/146
|
||||
generic/147
|
||||
generic/148
|
||||
generic/149
|
||||
generic/150
|
||||
generic/151
|
||||
generic/152
|
||||
generic/153
|
||||
generic/154
|
||||
generic/155
|
||||
generic/156
|
||||
generic/157
|
||||
generic/158
|
||||
generic/159
|
||||
generic/160
|
||||
generic/161
|
||||
generic/162
|
||||
generic/163
|
||||
generic/169
|
||||
generic/171
|
||||
generic/172
|
||||
generic/173
|
||||
generic/174
|
||||
generic/177
|
||||
generic/178
|
||||
generic/179
|
||||
generic/180
|
||||
generic/181
|
||||
generic/182
|
||||
generic/183
|
||||
generic/184
|
||||
generic/185
|
||||
generic/188
|
||||
generic/189
|
||||
generic/190
|
||||
generic/191
|
||||
generic/193
|
||||
generic/194
|
||||
generic/195
|
||||
generic/196
|
||||
generic/197
|
||||
generic/198
|
||||
generic/199
|
||||
generic/200
|
||||
generic/201
|
||||
generic/202
|
||||
generic/203
|
||||
generic/205
|
||||
generic/206
|
||||
generic/207
|
||||
generic/210
|
||||
generic/211
|
||||
generic/212
|
||||
generic/214
|
||||
generic/216
|
||||
generic/217
|
||||
generic/218
|
||||
generic/219
|
||||
generic/220
|
||||
generic/221
|
||||
generic/222
|
||||
generic/223
|
||||
generic/225
|
||||
generic/227
|
||||
generic/228
|
||||
generic/229
|
||||
generic/230
|
||||
generic/235
|
||||
generic/236
|
||||
generic/237
|
||||
generic/238
|
||||
generic/240
|
||||
generic/244
|
||||
generic/245
|
||||
generic/249
|
||||
generic/250
|
||||
generic/252
|
||||
generic/253
|
||||
generic/254
|
||||
generic/255
|
||||
generic/256
|
||||
generic/257
|
||||
generic/258
|
||||
generic/259
|
||||
generic/260
|
||||
generic/261
|
||||
generic/262
|
||||
generic/263
|
||||
generic/264
|
||||
generic/265
|
||||
generic/266
|
||||
generic/267
|
||||
generic/268
|
||||
generic/271
|
||||
generic/272
|
||||
generic/276
|
||||
generic/277
|
||||
generic/278
|
||||
generic/279
|
||||
generic/281
|
||||
generic/282
|
||||
generic/283
|
||||
generic/284
|
||||
generic/286
|
||||
generic/287
|
||||
generic/288
|
||||
generic/289
|
||||
generic/290
|
||||
generic/291
|
||||
generic/292
|
||||
generic/293
|
||||
generic/294
|
||||
generic/295
|
||||
generic/296
|
||||
generic/301
|
||||
generic/302
|
||||
generic/303
|
||||
generic/304
|
||||
generic/305
|
||||
generic/306
|
||||
generic/307
|
||||
generic/308
|
||||
generic/309
|
||||
generic/312
|
||||
generic/313
|
||||
generic/314
|
||||
generic/315
|
||||
generic/316
|
||||
generic/317
|
||||
generic/319
|
||||
generic/322
|
||||
generic/324
|
||||
generic/326
|
||||
generic/327
|
||||
generic/328
|
||||
generic/329
|
||||
generic/330
|
||||
generic/331
|
||||
generic/332
|
||||
generic/335
|
||||
generic/336
|
||||
generic/337
|
||||
@@ -74,10 +245,255 @@ generic/341
|
||||
generic/342
|
||||
generic/343
|
||||
generic/348
|
||||
generic/353
|
||||
generic/355
|
||||
generic/358
|
||||
generic/359
|
||||
generic/360
|
||||
generic/361
|
||||
generic/362
|
||||
generic/363
|
||||
generic/364
|
||||
generic/365
|
||||
generic/366
|
||||
generic/367
|
||||
generic/368
|
||||
generic/369
|
||||
generic/370
|
||||
generic/371
|
||||
generic/372
|
||||
generic/373
|
||||
generic/374
|
||||
generic/375
|
||||
generic/376
|
||||
generic/377
|
||||
generic/378
|
||||
generic/379
|
||||
generic/380
|
||||
generic/381
|
||||
generic/382
|
||||
generic/383
|
||||
generic/384
|
||||
generic/385
|
||||
generic/386
|
||||
generic/389
|
||||
generic/391
|
||||
generic/392
|
||||
generic/393
|
||||
generic/394
|
||||
generic/395
|
||||
generic/396
|
||||
generic/397
|
||||
generic/398
|
||||
generic/400
|
||||
generic/401
|
||||
generic/402
|
||||
generic/403
|
||||
generic/404
|
||||
generic/406
|
||||
generic/407
|
||||
generic/408
|
||||
generic/412
|
||||
generic/413
|
||||
generic/414
|
||||
generic/417
|
||||
generic/419
|
||||
generic/420
|
||||
generic/421
|
||||
generic/422
|
||||
generic/424
|
||||
generic/425
|
||||
generic/426
|
||||
generic/427
|
||||
generic/436
|
||||
generic/439
|
||||
generic/440
|
||||
generic/443
|
||||
generic/445
|
||||
generic/446
|
||||
generic/448
|
||||
generic/449
|
||||
generic/450
|
||||
generic/451
|
||||
generic/453
|
||||
generic/454
|
||||
generic/456
|
||||
generic/458
|
||||
generic/460
|
||||
generic/462
|
||||
generic/463
|
||||
generic/465
|
||||
generic/466
|
||||
generic/468
|
||||
generic/469
|
||||
generic/470
|
||||
generic/471
|
||||
generic/474
|
||||
generic/477
|
||||
generic/478
|
||||
generic/479
|
||||
generic/480
|
||||
generic/481
|
||||
generic/483
|
||||
generic/485
|
||||
generic/486
|
||||
generic/487
|
||||
generic/488
|
||||
generic/489
|
||||
generic/490
|
||||
generic/491
|
||||
generic/492
|
||||
generic/498
|
||||
generic/499
|
||||
generic/501
|
||||
generic/502
|
||||
generic/503
|
||||
generic/504
|
||||
generic/505
|
||||
generic/506
|
||||
generic/507
|
||||
generic/508
|
||||
generic/509
|
||||
generic/510
|
||||
generic/511
|
||||
generic/512
|
||||
generic/513
|
||||
generic/514
|
||||
generic/515
|
||||
generic/516
|
||||
generic/517
|
||||
generic/518
|
||||
generic/519
|
||||
generic/520
|
||||
generic/523
|
||||
generic/524
|
||||
generic/525
|
||||
generic/526
|
||||
generic/527
|
||||
generic/528
|
||||
generic/529
|
||||
generic/530
|
||||
generic/531
|
||||
generic/533
|
||||
generic/534
|
||||
generic/535
|
||||
generic/536
|
||||
generic/537
|
||||
generic/538
|
||||
generic/539
|
||||
generic/540
|
||||
generic/541
|
||||
generic/542
|
||||
generic/543
|
||||
generic/544
|
||||
generic/545
|
||||
generic/546
|
||||
generic/547
|
||||
generic/548
|
||||
generic/549
|
||||
generic/550
|
||||
generic/552
|
||||
generic/553
|
||||
generic/555
|
||||
generic/556
|
||||
generic/557
|
||||
generic/566
|
||||
generic/567
|
||||
generic/571
|
||||
generic/572
|
||||
generic/573
|
||||
generic/574
|
||||
generic/575
|
||||
generic/576
|
||||
generic/577
|
||||
generic/578
|
||||
generic/580
|
||||
generic/581
|
||||
generic/582
|
||||
generic/583
|
||||
generic/584
|
||||
generic/586
|
||||
generic/587
|
||||
generic/588
|
||||
generic/591
|
||||
generic/592
|
||||
generic/593
|
||||
generic/594
|
||||
generic/595
|
||||
generic/596
|
||||
generic/597
|
||||
generic/598
|
||||
generic/599
|
||||
generic/600
|
||||
generic/601
|
||||
generic/602
|
||||
generic/603
|
||||
generic/604
|
||||
generic/605
|
||||
generic/606
|
||||
generic/607
|
||||
generic/608
|
||||
generic/609
|
||||
generic/610
|
||||
generic/611
|
||||
generic/612
|
||||
generic/613
|
||||
generic/618
|
||||
generic/621
|
||||
generic/623
|
||||
generic/624
|
||||
generic/625
|
||||
generic/626
|
||||
generic/628
|
||||
generic/629
|
||||
generic/630
|
||||
generic/632
|
||||
generic/634
|
||||
generic/635
|
||||
generic/637
|
||||
generic/639
|
||||
generic/640
|
||||
generic/644
|
||||
generic/645
|
||||
generic/646
|
||||
generic/647
|
||||
generic/651
|
||||
generic/652
|
||||
generic/653
|
||||
generic/654
|
||||
generic/655
|
||||
generic/657
|
||||
generic/658
|
||||
generic/659
|
||||
generic/660
|
||||
generic/661
|
||||
generic/662
|
||||
generic/663
|
||||
generic/664
|
||||
generic/665
|
||||
generic/666
|
||||
generic/667
|
||||
generic/668
|
||||
generic/669
|
||||
generic/673
|
||||
generic/674
|
||||
generic/675
|
||||
generic/676
|
||||
generic/677
|
||||
generic/678
|
||||
generic/679
|
||||
generic/680
|
||||
generic/681
|
||||
generic/682
|
||||
generic/683
|
||||
generic/684
|
||||
generic/685
|
||||
generic/686
|
||||
generic/687
|
||||
generic/688
|
||||
generic/689
|
||||
shared/002
|
||||
shared/032
|
||||
Not
|
||||
run:
|
||||
generic/008
|
||||
@@ -251,8 +667,6 @@ generic/331
|
||||
generic/332
|
||||
generic/353
|
||||
generic/355
|
||||
generic/356
|
||||
generic/357
|
||||
generic/358
|
||||
generic/359
|
||||
generic/361
|
||||
@@ -278,11 +692,174 @@ generic/383
|
||||
generic/384
|
||||
generic/385
|
||||
generic/386
|
||||
shared/001
|
||||
generic/391
|
||||
generic/392
|
||||
generic/395
|
||||
generic/396
|
||||
generic/397
|
||||
generic/398
|
||||
generic/400
|
||||
generic/402
|
||||
generic/404
|
||||
generic/406
|
||||
generic/407
|
||||
generic/408
|
||||
generic/412
|
||||
generic/413
|
||||
generic/414
|
||||
generic/417
|
||||
generic/419
|
||||
generic/420
|
||||
generic/421
|
||||
generic/422
|
||||
generic/424
|
||||
generic/425
|
||||
generic/427
|
||||
generic/439
|
||||
generic/440
|
||||
generic/446
|
||||
generic/449
|
||||
generic/450
|
||||
generic/451
|
||||
generic/453
|
||||
generic/454
|
||||
generic/456
|
||||
generic/458
|
||||
generic/462
|
||||
generic/463
|
||||
generic/465
|
||||
generic/466
|
||||
generic/468
|
||||
generic/469
|
||||
generic/470
|
||||
generic/471
|
||||
generic/474
|
||||
generic/485
|
||||
generic/487
|
||||
generic/488
|
||||
generic/491
|
||||
generic/492
|
||||
generic/499
|
||||
generic/501
|
||||
generic/503
|
||||
generic/505
|
||||
generic/506
|
||||
generic/507
|
||||
generic/508
|
||||
generic/511
|
||||
generic/513
|
||||
generic/514
|
||||
generic/515
|
||||
generic/516
|
||||
generic/517
|
||||
generic/518
|
||||
generic/519
|
||||
generic/520
|
||||
generic/528
|
||||
generic/530
|
||||
generic/536
|
||||
generic/537
|
||||
generic/538
|
||||
generic/539
|
||||
generic/540
|
||||
generic/541
|
||||
generic/542
|
||||
generic/543
|
||||
generic/544
|
||||
generic/545
|
||||
generic/546
|
||||
generic/548
|
||||
generic/549
|
||||
generic/550
|
||||
generic/552
|
||||
generic/553
|
||||
generic/555
|
||||
generic/556
|
||||
generic/566
|
||||
generic/567
|
||||
generic/572
|
||||
generic/573
|
||||
generic/574
|
||||
generic/575
|
||||
generic/576
|
||||
generic/577
|
||||
generic/578
|
||||
generic/580
|
||||
generic/581
|
||||
generic/582
|
||||
generic/583
|
||||
generic/584
|
||||
generic/586
|
||||
generic/587
|
||||
generic/588
|
||||
generic/591
|
||||
generic/592
|
||||
generic/593
|
||||
generic/594
|
||||
generic/595
|
||||
generic/596
|
||||
generic/597
|
||||
generic/598
|
||||
generic/599
|
||||
generic/600
|
||||
generic/601
|
||||
generic/602
|
||||
generic/603
|
||||
generic/605
|
||||
generic/606
|
||||
generic/607
|
||||
generic/608
|
||||
generic/609
|
||||
generic/610
|
||||
generic/612
|
||||
generic/613
|
||||
generic/621
|
||||
generic/623
|
||||
generic/624
|
||||
generic/625
|
||||
generic/626
|
||||
generic/628
|
||||
generic/629
|
||||
generic/630
|
||||
generic/635
|
||||
generic/644
|
||||
generic/645
|
||||
generic/646
|
||||
generic/647
|
||||
generic/651
|
||||
generic/652
|
||||
generic/653
|
||||
generic/654
|
||||
generic/655
|
||||
generic/657
|
||||
generic/658
|
||||
generic/659
|
||||
generic/660
|
||||
generic/661
|
||||
generic/662
|
||||
generic/663
|
||||
generic/664
|
||||
generic/665
|
||||
generic/666
|
||||
generic/667
|
||||
generic/668
|
||||
generic/669
|
||||
generic/673
|
||||
generic/674
|
||||
generic/675
|
||||
generic/677
|
||||
generic/678
|
||||
generic/679
|
||||
generic/680
|
||||
generic/681
|
||||
generic/682
|
||||
generic/683
|
||||
generic/684
|
||||
generic/685
|
||||
generic/686
|
||||
generic/687
|
||||
generic/688
|
||||
generic/689
|
||||
shared/002
|
||||
shared/003
|
||||
shared/004
|
||||
shared/032
|
||||
shared/051
|
||||
shared/289
|
||||
Passed all 79 tests
|
||||
Passed all 495 tests
|
||||
|
||||
@@ -515,6 +515,7 @@ msg "running tests"
|
||||
passed=0
|
||||
skipped=0
|
||||
failed=0
|
||||
skipped_permitted=0
|
||||
for t in $tests; do
|
||||
# tests has basenames from sequence, get path and name
|
||||
t="tests/$t"
|
||||
@@ -557,6 +558,9 @@ for t in $tests; do
|
||||
|
||||
printf " %-30s $stats" "$test_name"
|
||||
|
||||
# mark in dmesg as to what test we are running
|
||||
echo "run scoutfs test $test_name" > /dev/kmsg
|
||||
|
||||
# record dmesg before
|
||||
dmesg | t_filter_dmesg > "$T_TMPDIR/dmesg.before"
|
||||
|
||||
@@ -618,6 +622,10 @@ for t in $tests; do
|
||||
grep -s -v "^$test_name " "$last" > "$last.tmp"
|
||||
echo "$test_name $stats" >> "$last.tmp"
|
||||
mv -f "$last.tmp" "$last"
|
||||
elif [ "$sts" == "$T_SKIP_PERMITTED_STATUS" ]; then
|
||||
echo " [ skipped (permitted): $message ]"
|
||||
echo "$test_name skipped (permitted) $message " >> "$T_RESULTS/skip.log"
|
||||
((skipped_permitted++))
|
||||
elif [ "$sts" == "$T_SKIP_STATUS" ]; then
|
||||
echo " [ skipped: $message ]"
|
||||
echo "$test_name $message" >> "$T_RESULTS/skip.log"
|
||||
@@ -631,7 +639,7 @@ for t in $tests; do
|
||||
fi
|
||||
done
|
||||
|
||||
msg "all tests run: $passed passed, $skipped skipped, $failed failed"
|
||||
msg "all tests run: $passed passed, $skipped skipped, $skipped_permitted skipped (permitted), $failed failed"
|
||||
|
||||
|
||||
if [ -n "$T_TRACE_GLOB" -o -n "$T_TRACE_PRINTK" ]; then
|
||||
|
||||
@@ -25,6 +25,7 @@ totl-xattr-tag.sh
|
||||
quota.sh
|
||||
lock-refleak.sh
|
||||
lock-shrink-consistency.sh
|
||||
lock-shrink-read-race.sh
|
||||
lock-pr-cw-conflict.sh
|
||||
lock-revoke-getcwd.sh
|
||||
lock-recover-invalidate.sh
|
||||
|
||||
@@ -55,16 +55,16 @@ L dir-root/file-group-write
|
||||
L symlinkdir-root/file-group-write
|
||||
|
||||
echo "== directory exec"
|
||||
setpriv $SET_UID bash -c "cd dir-root && echo Success"
|
||||
setpriv $SET_UID bash -c "cd symlinkdir-root && echo Success"
|
||||
setpriv $SET_UID bash -c "cd dir-root 2>&- && echo Success"
|
||||
setpriv $SET_UID bash -c "cd symlinkdir-root 2>&- && echo Success"
|
||||
setfacl -m u:22222:rw dir-root
|
||||
getfacl dir-root
|
||||
setpriv $SET_UID bash -c "cd dir-root || echo Failed"
|
||||
setpriv $SET_UID bash -c "cd symlinkdir-root || echo Failed"
|
||||
setpriv $SET_UID bash -c "cd dir-root 2>&- || echo Failed"
|
||||
setpriv $SET_UID bash -c "cd symlinkdir-root 2>&- || echo Failed"
|
||||
setfacl -m g:44444:rwx dir-root
|
||||
getfacl dir-root
|
||||
setpriv $SET_GID bash -c "cd dir-root && echo Success"
|
||||
setpriv $SET_GID bash -c "cd symlinkdir-root && echo Success"
|
||||
setpriv $SET_GID bash -c "cd dir-root 2>&- && echo Success"
|
||||
setpriv $SET_GID bash -c "cd symlinkdir-root 2>&- && echo Success"
|
||||
|
||||
echo "== get/set attr"
|
||||
rm -rf file-root
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
# operations in one mount and verify the results in another.
|
||||
#
|
||||
|
||||
t_require_commands getfattr setfattr dd filefrag diff touch stat scoutfs
|
||||
t_require_commands getfattr setfattr dd diff touch stat scoutfs
|
||||
t_require_mounts 2
|
||||
|
||||
GETFATTR="getfattr --absolute-names"
|
||||
SETFATTR="setfattr"
|
||||
DD="dd status=none"
|
||||
FILEFRAG="filefrag -v -b4096"
|
||||
FIEMAP="scoutfs get-fiemap"
|
||||
|
||||
echo "== root inode updates flow back and forth"
|
||||
sleep 1
|
||||
@@ -55,8 +55,8 @@ for i in $(seq 1 10); do
|
||||
conv=notrunc oflag=append &
|
||||
wait
|
||||
done
|
||||
$FILEFRAG "$T_D0/file" | t_filter_fs > "$T_TMP.0"
|
||||
$FILEFRAG "$T_D1/file" | t_filter_fs > "$T_TMP.1"
|
||||
$FIEMAP "$T_D0/file" > "$T_TMP.0"
|
||||
$FIEMAP "$T_D1/file" > "$T_TMP.1"
|
||||
diff -u "$T_TMP.0" "$T_TMP.1"
|
||||
|
||||
echo "== unlinked file isn't found"
|
||||
|
||||
@@ -4,7 +4,16 @@
|
||||
# merge adjacent consecutive allocations. (we don't have multiple
|
||||
# allocation cursors)
|
||||
#
|
||||
t_require_commands scoutfs stat filefrag dd touch truncate
|
||||
t_require_commands scoutfs stat dd touch truncate
|
||||
|
||||
get_fiemap()
|
||||
{
|
||||
scoutfs get-fiemap "$1" | awk '($1 != "extents:") {
|
||||
unwritten = (substr($8, 2, 1) == "U") ? "unwritten" : "";
|
||||
eof = (substr($8, 3, 1) == "L") ? "eof" : "";
|
||||
print $3 ".. " $6 ": " unwritten eof;
|
||||
};'
|
||||
}
|
||||
|
||||
write_block()
|
||||
{
|
||||
@@ -76,26 +85,9 @@ print_extents_found()
|
||||
{
|
||||
local prefix="$1"
|
||||
|
||||
filefrag "$prefix"* 2>&1 | grep "extent.*found" | t_filter_fs
|
||||
}
|
||||
|
||||
#
|
||||
# print the logical start, len, and flags if they're there.
|
||||
#
|
||||
print_logical_extents()
|
||||
{
|
||||
local file="$1"
|
||||
|
||||
filefrag -v -b4096 "$file" 2>&1 | t_filter_fs | awk '
|
||||
($1 ~ /[0-9]+:/) {
|
||||
if ($NF !~ /[0-9]+:/) {
|
||||
flags=$NF
|
||||
} else {
|
||||
flags=""
|
||||
}
|
||||
print $2, $6, flags
|
||||
}
|
||||
' | sed 's/last,eof/eof/'
|
||||
for f in "$prefix"-*; do
|
||||
echo "$f: $(scoutfs get-fiemap "$f" | tail -n 1)" | t_filter_fs
|
||||
done
|
||||
}
|
||||
|
||||
t_save_all_sysfs_mount_options data_prealloc_blocks
|
||||
@@ -197,7 +189,7 @@ for sides in 0 1 2 3; do
|
||||
done
|
||||
|
||||
echo before:
|
||||
print_logical_extents "$prefix"
|
||||
get_fiemap "$prefix"
|
||||
|
||||
# now write into the first, middle, and last empty block of each
|
||||
t_set_sysfs_mount_option 0 data_prealloc_contig_only 0
|
||||
@@ -223,7 +215,7 @@ for sides in 0 1 2 3; do
|
||||
# mid (both has 6 blocks internally)
|
||||
2) write_block $prefix $((left + 3)) ;;
|
||||
esac
|
||||
print_logical_extents "$prefix"
|
||||
get_fiemap "$prefix"
|
||||
((base+=8))
|
||||
done
|
||||
done
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
# format version.
|
||||
#
|
||||
|
||||
# not supported on el9!
|
||||
if [ $(source /etc/os-release ; echo ${VERSION_ID:0:1}) -gt 8 ]; then
|
||||
t_skip_permitted "Unsupported OS version"
|
||||
fi
|
||||
|
||||
mount_has_format_version()
|
||||
{
|
||||
local mnt="$1"
|
||||
|
||||
40
tests/tests/lock-shrink-read-race.sh
Normal file
40
tests/tests/lock-shrink-read-race.sh
Normal file
@@ -0,0 +1,40 @@
|
||||
#
|
||||
# We had a lock server refcounting bug that could let one thread get a
|
||||
# reference on a lock struct that was being freed by another thread. We
|
||||
# were able to reproduce this by having all clients try and produce a
|
||||
# lot of read and null requests.
|
||||
#
|
||||
# This will manfiest as a hung lock and timed out test runs, probably
|
||||
# with hung task messages on the console. Depending on how the race
|
||||
# turns out, it can trigger KASAN warnings in
|
||||
# process_waiting_requests().
|
||||
#
|
||||
|
||||
READERS_PER=3
|
||||
SECS=30
|
||||
|
||||
echo "=== setup"
|
||||
touch "$T_D0/file"
|
||||
|
||||
echo "=== spin reading and shrinking"
|
||||
END=$((SECONDS + SECS))
|
||||
for m in $(t_fs_nrs); do
|
||||
eval file="\$T_D${m}/file"
|
||||
|
||||
# lots of tasks reading as fast as they can
|
||||
for t in $(seq 1 $READERS_PER); do
|
||||
(while [ $SECONDS -lt $END ]; do
|
||||
stat $file > /dev/null
|
||||
done) &
|
||||
done
|
||||
# one task shrinking (triggering null requests) and reading
|
||||
(while [ $SECONDS -lt $END ]; do
|
||||
stat $file > /dev/null
|
||||
t_trigger_arm_silent statfs_lock_purge $m
|
||||
stat -f "$file" > /dev/null
|
||||
done) &
|
||||
done
|
||||
|
||||
wait
|
||||
|
||||
t_pass
|
||||
@@ -83,9 +83,9 @@ touch "$OTHER"
|
||||
ln "$FROM" "$HARD"
|
||||
|
||||
echo "== wrapped offsets should fail"
|
||||
HUGE=0x8000000000000000
|
||||
scoutfs move-blocks "$FROM" -f "$HUGE" -l "$HUGE" "$TO" -t 0 2>&1 | t_filter_fs
|
||||
scoutfs move-blocks "$FROM" -f 0 -l "$HUGE" "$TO" -t "$HUGE" 2>&1 | t_filter_fs
|
||||
HUGE=0xfffffffffffff000
|
||||
scoutfs move-blocks "$FROM" -f "$HUGE" -l "8192" "$TO" -t 0 2>&1 | t_filter_fs
|
||||
scoutfs move-blocks "$FROM" -f 0 -l "$HUGE" "$TO" -t "8192" 2>&1 | t_filter_fs
|
||||
|
||||
echo "== specifying same file fails"
|
||||
scoutfs move-blocks "$FROM" -f 0 -l "$BS" "$HARD" -t 0 2>&1 | t_filter_fs
|
||||
|
||||
@@ -22,7 +22,7 @@ reset_all()
|
||||
getfattr --absolute-names -d -m - "$T_D0" | \
|
||||
grep "^scoutfs.totl." | \
|
||||
cut -d '=' -f 1 | \
|
||||
xargs -n 1 -I'{}' setfattr -x '{}' "$T_D0"
|
||||
xargs -I'{}' setfattr -x '{}' "$T_D0"
|
||||
}
|
||||
|
||||
echo "== prepare dir with write perm for test ids"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Test correctness of the setattr_more ioctl.
|
||||
#
|
||||
|
||||
t_require_commands filefrag scoutfs touch mkdir rm stat mknod
|
||||
t_require_commands scoutfs touch mkdir rm stat mknod
|
||||
|
||||
FILE="$T_D0/file"
|
||||
|
||||
@@ -55,17 +55,10 @@ scoutfs setattr -t 67305985.999999999 -V 1 -s 1 "$FILE" 2>&1 | t_filter_fs
|
||||
TZ=GMT stat -c "%z" "$FILE"
|
||||
rm "$FILE"
|
||||
|
||||
#
|
||||
# With e2fsprogs-v1.42.10-10-g29758d2f, the output of filefrag 'flags' changes
|
||||
# significantly. First, the _LAST flag is now output. Second, the 'unknown'
|
||||
# flag is now printed out as 'unknown_loc'. To compensate for this, we check
|
||||
# and replace the "correct" output for new versions here with the expected
|
||||
# value.
|
||||
#
|
||||
echo "== large offline extents are created"
|
||||
touch "$FILE"
|
||||
scoutfs setattr -V 1 -o -s $((10007 * 4096)) "$FILE" 2>&1 | t_filter_fs
|
||||
filefrag -v -b4096 "$FILE" 2>&1 | sed 's/last,unknown_loc,eof$/unknown,eof/' | t_filter_fs
|
||||
scoutfs get-fiemap "$FILE"
|
||||
rm "$FILE"
|
||||
|
||||
# had a bug where we were creating extents that were too long
|
||||
@@ -75,4 +68,11 @@ scoutfs setattr -V 1 -o -s 4000000000 "$FILE" 2>&1 | t_filter_fs
|
||||
scoutfs stat -s offline_blocks "$FILE"
|
||||
rm "$FILE"
|
||||
|
||||
# Do not fail if data_version is unset - the unset `0` value should not
|
||||
# be passed down to attr_x handling code which will -EINVAL on that.
|
||||
echo "== omitting data_version should not fail"
|
||||
touch "$FILE"
|
||||
scoutfs setattr -s 0 -t 1725670311.0 -r 1725670311.0 "$FILE"
|
||||
rm "$FILE"
|
||||
|
||||
t_pass
|
||||
|
||||
@@ -7,6 +7,7 @@ t_require_commands xfs_io filefrag scoutfs mknod
|
||||
# this test wants to ignore unwritten extents
|
||||
fiemap_file() {
|
||||
filefrag -v -b4096 "$1" | grep -v "unwritten"
|
||||
scoutfs get-fiemap "$1" | grep -v 'flags:.*U'
|
||||
}
|
||||
|
||||
create_file() {
|
||||
@@ -61,7 +62,10 @@ echo "== release past i_size is fine"
|
||||
release_vers "$FILE" stat 400K 4K
|
||||
|
||||
echo "== wrapped blocks fails"
|
||||
release_vers "$FILE" stat $vers 0x8000000000000000 0x8000000000000000
|
||||
# just under!
|
||||
release_vers "$FILE" stat $vers 0xfffffffffffff000 4096
|
||||
# this goes over
|
||||
release_vers "$FILE" stat $vers 0xfffffffffffff000 8192
|
||||
|
||||
echo "== releasing non-file fails"
|
||||
mknod "$CHAR" c 1 3
|
||||
@@ -105,25 +109,20 @@ for c in $(seq 0 4); do
|
||||
fi
|
||||
done
|
||||
|
||||
start=$(fiemap_file "$FILE" | \
|
||||
awk '($1 == "0:"){print substr($4, 0, length($4)- 2)}')
|
||||
|
||||
release_vers "$FILE" stat $(($a * 4))K 4K
|
||||
release_vers "$FILE" stat $(($b * 4))K 4K
|
||||
release_vers "$FILE" stat $(($c * 4))K 4K
|
||||
|
||||
echo -n "$a $b $c:"
|
||||
|
||||
fiemap_file "$FILE" | \
|
||||
awk 'BEGIN{ORS=""}($1 == (NR - 4)":") {
|
||||
off=substr($2, 0, length($2)- 2);
|
||||
phys=substr($4, 0, length($4)- 2);
|
||||
if (phys > 100) {
|
||||
phys = phys - phys + 100 + off;
|
||||
}
|
||||
len=substr($6, 0, length($6)- 1);
|
||||
print " (" off, phys, len ")";
|
||||
}'
|
||||
scoutfs get-fiemap "$FILE" | \
|
||||
awk 'BEGIN{ORS=""}($1 != "extents:") {
|
||||
off=$3;
|
||||
len=$6;
|
||||
phys=substr($8, 0, 1);
|
||||
phys = (phys == ".") ? off + 100 : 0;
|
||||
print " (" off, phys, len ")"
|
||||
};'
|
||||
echo
|
||||
|
||||
rm "$FILE"
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
# Test correctness of the staging operation
|
||||
#
|
||||
|
||||
t_require_commands filefrag dd scoutfs cp cmp rm
|
||||
|
||||
fiemap_file() {
|
||||
filefrag -v -b4096 "$1"
|
||||
}
|
||||
t_require_commands dd scoutfs cp cmp rm
|
||||
|
||||
create_file() {
|
||||
local file="$1"
|
||||
@@ -62,7 +58,7 @@ create_file "$FILE" 4096
|
||||
cp "$FILE" "$T_TMP"
|
||||
release_vers "$FILE" stat 0 4K
|
||||
# make sure there only offline extents
|
||||
fiemap_file "$FILE" | grep "^[ 0-9]*:" | grep -v "unknown"
|
||||
scoutfs get-fiemap "$FILE"
|
||||
stage_vers "$FILE" stat 0 4096 "$T_TMP"
|
||||
cmp "$FILE" "$T_TMP"
|
||||
rm -f "$FILE"
|
||||
@@ -72,7 +68,7 @@ create_file "$FILE" $((4096 * 4096))
|
||||
cp "$FILE" "$T_TMP"
|
||||
release_vers "$FILE" stat 0 16M
|
||||
# make sure there only offline extents
|
||||
fiemap_file "$FILE" | grep "^[ 0-9]*:" | grep -v "unknown"
|
||||
scoutfs get-fiemap "$FILE"
|
||||
stage_vers "$FILE" stat 0 $((4096 * 4096)) "$T_TMP"
|
||||
cmp "$FILE" "$T_TMP"
|
||||
rm -f "$FILE"
|
||||
@@ -143,8 +139,8 @@ hexdump -C "$FILE"
|
||||
rm -f "$FILE"
|
||||
|
||||
echo "== wrapped region fails"
|
||||
create_file "$FILE" 4096
|
||||
stage_vers "$FILE" stat 0xFFFFFFFFFFFFF000 4096 /dev/zero
|
||||
create_file "$FILE" 8192
|
||||
stage_vers "$FILE" stat 0xFFFFFFFFFFFFF000 8192 /dev/zero
|
||||
rm -f "$FILE"
|
||||
|
||||
echo "== non-block aligned offset fails"
|
||||
@@ -152,7 +148,7 @@ create_file "$FILE" 4096
|
||||
cp "$FILE" "$T_TMP"
|
||||
release_vers "$FILE" stat 0 4K
|
||||
stage_vers "$FILE" stat 1 4095 "$T_TMP"
|
||||
fiemap_file "$FILE" | grep "^[ 0-9]*:" | grep -v "unknown"
|
||||
scoutfs get-fiemap "$FILE"
|
||||
rm -f "$FILE"
|
||||
|
||||
echo "== non-block aligned len within block fails"
|
||||
@@ -160,7 +156,7 @@ create_file "$FILE" 4096
|
||||
cp "$FILE" "$T_TMP"
|
||||
release_vers "$FILE" stat 0 4K
|
||||
stage_vers "$FILE" stat 0 1024 "$T_TMP"
|
||||
fiemap_file "$FILE" | grep "^[ 0-9]*:" | grep -v "unknown"
|
||||
scoutfs get-fiemap "$FILE"
|
||||
rm -f "$FILE"
|
||||
|
||||
echo "== partial final block that writes to i_size does work"
|
||||
@@ -175,7 +171,7 @@ echo "== zero length stage doesn't bring blocks online"
|
||||
create_file "$FILE" $((4096 * 100))
|
||||
release_vers "$FILE" stat 0 400K
|
||||
stage_vers "$FILE" stat 4096 0 /dev/zero
|
||||
fiemap_file "$FILE" | grep "^[ 0-9]*:" | grep -v "unknown"
|
||||
scoutfs get-fiemap "$FILE"
|
||||
rm -f "$FILE"
|
||||
|
||||
# XXX yup, needs to be updated for demand staging
|
||||
|
||||
@@ -30,8 +30,13 @@ t_quiet mkdir -p "$T_TMPDIR/mnt.scratch"
|
||||
t_quiet cd "$T_XFSTESTS_REPO"
|
||||
if [ -z "$T_SKIP_CHECKOUT" ]; then
|
||||
t_quiet git fetch
|
||||
# if we're passed a tag instead of a branch, we can't --track
|
||||
TRACK="--track"
|
||||
if git tag -l | grep -q "$T_XFSTESTS_BRANCH" ; then
|
||||
TRACK=""
|
||||
fi
|
||||
# this remote use is bad, do better
|
||||
t_quiet git checkout -B "$T_XFSTESTS_BRANCH" --track "origin/$T_XFSTESTS_BRANCH"
|
||||
t_quiet git checkout -B "$T_XFSTESTS_BRANCH" ${TRACK} "origin/$T_XFSTESTS_BRANCH"
|
||||
fi
|
||||
t_quiet make
|
||||
t_quiet sync
|
||||
@@ -81,6 +86,45 @@ generic/325 # mmap missing
|
||||
generic/338 # BUG_ON update inode error handling
|
||||
generic/346 # mmap missing
|
||||
generic/347 # _dmthin_mount doesn't work?
|
||||
generic/356 # swap
|
||||
generic/357 # swap
|
||||
generic/409 # bind mounts not scripted yet
|
||||
generic/410 # bind mounts not scripted yet
|
||||
generic/411 # bind mounts not scripted yet
|
||||
generic/423 # symlink inode size is strlen() + 1 on scoutfs
|
||||
generic/428 # mmap missing
|
||||
generic/430 # xfs_io copy_range missing in el7
|
||||
generic/431 # xfs_io copy_range missing in el7
|
||||
generic/432 # xfs_io copy_range missing in el7
|
||||
generic/433 # xfs_io copy_range missing in el7
|
||||
generic/434 # xfs_io copy_range missing in el7
|
||||
generic/437 # mmap missing
|
||||
generic/441 # dm-mapper
|
||||
generic/444 # el9's posix_acl_update_mode is buggy ?
|
||||
generic/452 # exec test - no mmap
|
||||
generic/467 # open_by_handle ESTALE
|
||||
generic/472 # swap
|
||||
generic/484 # dm-mapper
|
||||
generic/493 # swap
|
||||
generic/494 # swap
|
||||
generic/495 # swap
|
||||
generic/496 # swap
|
||||
generic/497 # swap
|
||||
generic/532 # xfs_io statx attrib_mask missing in el7
|
||||
generic/554 # swap
|
||||
generic/563 # cgroup+loopdev
|
||||
generic/564 # xfs_io copy_range missing in el7
|
||||
generic/565 # xfs_io copy_range missing in el7
|
||||
generic/568 # falloc not resulting in block count increase
|
||||
generic/569 # swap
|
||||
generic/570 # swap
|
||||
generic/614 # mmap missing
|
||||
generic/620 # dm-hugedisk
|
||||
generic/633 # mmap, id-mapped mounts missing in el7
|
||||
generic/636 # swap
|
||||
generic/638 # mmap missing
|
||||
generic/641 # swap
|
||||
generic/643 # swap
|
||||
EOF
|
||||
|
||||
t_restore_output
|
||||
|
||||
@@ -37,10 +37,23 @@ search=$(gcc -print-search-dirs | awk '($1 == "install:"){print "-I" $2}')
|
||||
#
|
||||
# We're trying to use sparse against glibc headers which go wild trying to
|
||||
# use internal compiler macros to test features. We copy gcc's and give
|
||||
# them to sparse. But not __SIZE_TYPE__ 'cause sparse defines that one.
|
||||
# them to sparse, but not the ones that sparse already has.
|
||||
#
|
||||
defines=".sparse.gcc-defines.h"
|
||||
gcc -dM -E -x c - < /dev/null | grep -v __SIZE_TYPE__ > $defines
|
||||
defines=".sparse.gcc-defines.$$.h"
|
||||
awk '
|
||||
# save defines from gcc
|
||||
( FNR == NR ) { lines[$2]=$0 }
|
||||
|
||||
# delete defines that sparse also has
|
||||
( FNR < NR ) { delete lines[$2] }
|
||||
|
||||
# dump remaining lines unique to gcc
|
||||
END {
|
||||
for (a in lines) {
|
||||
print lines[a]
|
||||
}
|
||||
}
|
||||
' <(gcc -dM -E -x c - < /dev/null) <(sparse -dM -E -x c - < /dev/null) > $defines
|
||||
include="-include $defines"
|
||||
|
||||
#
|
||||
@@ -54,6 +67,9 @@ else
|
||||
fi
|
||||
|
||||
sparse $m64 $include $search/include "$@" 2>&1 | egrep -v "($RE)" | tee .sparse.output
|
||||
|
||||
rm -f $defines
|
||||
|
||||
if [ -s .sparse.output ]; then
|
||||
exit 1
|
||||
else
|
||||
|
||||
191
utils/src/fiemap.c
Normal file
191
utils/src/fiemap.c
Normal file
@@ -0,0 +1,191 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/fiemap.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <argp.h>
|
||||
|
||||
#include "sparse.h"
|
||||
#include "parse.h"
|
||||
#include "util.h"
|
||||
#include "format.h"
|
||||
#include "ioctl.h"
|
||||
#include "cmd.h"
|
||||
|
||||
/*
|
||||
* This is wholly modeled after e2fsprogs/filefrag.c from tso
|
||||
*/
|
||||
|
||||
struct get_fiemap_args {
|
||||
char *filename;
|
||||
bool phys;
|
||||
bool logical;
|
||||
bool byte;
|
||||
};
|
||||
|
||||
static int do_get_fiemap(struct get_fiemap_args *args)
|
||||
{
|
||||
__u64 buf[2048]; /* __u64 for proper field alignment */
|
||||
struct stat st;
|
||||
struct fiemap *fiemap = (struct fiemap *)buf;
|
||||
struct fiemap_extent *fm_ext = &fiemap->fm_extents[0];
|
||||
int count = (sizeof(buf) - sizeof(*fiemap)) /
|
||||
sizeof(struct fiemap_extent);
|
||||
int fd;
|
||||
int ret;
|
||||
int i;
|
||||
u64 nr = 0; /* XXX we could put this in fm_start to make start/count an option */
|
||||
int last = 0;
|
||||
u64 off_p, off_l;
|
||||
u64 len;
|
||||
|
||||
memset(fiemap, 0, sizeof(struct fiemap));
|
||||
|
||||
fd = open(args->filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "failed to open '%s': %s (%d)\n",
|
||||
args->filename, strerror(errno), errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* get block size from stat */
|
||||
if (fstat(fd, &st) != 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "stat failed on '%s': %s (%d)\n",
|
||||
args->filename, strerror(errno), errno);
|
||||
goto out;
|
||||
};
|
||||
|
||||
do {
|
||||
fiemap->fm_length = ~0ULL;
|
||||
fiemap->fm_extent_count = count;
|
||||
|
||||
ret = ioctl(fd, FS_IOC_FIEMAP, (unsigned long) fiemap);
|
||||
if (ret < 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "get_fiemap ioctl failed: "
|
||||
"%s (%d)\n", strerror(errno), errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* nothing returned, so exit */
|
||||
if (fiemap->fm_mapped_extents == 0)
|
||||
break;
|
||||
|
||||
for (i = 0; i < fiemap->fm_mapped_extents; i++) {
|
||||
off_p = fm_ext[i].fe_physical;
|
||||
off_l = fm_ext[i].fe_logical;
|
||||
len = fm_ext[i].fe_length;
|
||||
|
||||
if (!args->byte) {
|
||||
off_p /= st.st_blksize;
|
||||
off_l /= st.st_blksize;
|
||||
len /= st.st_blksize;
|
||||
}
|
||||
|
||||
printf("%llu: offset: ", nr++);
|
||||
|
||||
if (!args->phys)
|
||||
printf("%llu ", off_l);
|
||||
else if (!args->logical)
|
||||
printf("%llu ", off_p);
|
||||
else
|
||||
printf("%llu %llu ", off_l, off_p);
|
||||
|
||||
printf("length: %llu flags: %c%c%c\n",
|
||||
len,
|
||||
(fm_ext[i].fe_flags & FIEMAP_EXTENT_UNKNOWN) ? 'O' : '.',
|
||||
(fm_ext[i].fe_flags & FIEMAP_EXTENT_UNWRITTEN) ? 'U' : '.',
|
||||
(fm_ext[i].fe_flags & FIEMAP_EXTENT_LAST) ? 'L' : '.');
|
||||
|
||||
if (fm_ext[i].fe_flags & FIEMAP_EXTENT_LAST)
|
||||
last = 1;
|
||||
}
|
||||
|
||||
/* fm_start from the next logical extent */
|
||||
fiemap->fm_start = fm_ext[i-1].fe_logical + fm_ext[i-1].fe_length;
|
||||
} while (last == 0);
|
||||
|
||||
printf("extents: %llu\n", nr);
|
||||
|
||||
out:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
static int parse_opt(int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
struct get_fiemap_args *args = state->input;
|
||||
|
||||
switch (key) {
|
||||
case 'P':
|
||||
args->logical = false;
|
||||
break;
|
||||
case 'L':
|
||||
args->phys = false;
|
||||
break;
|
||||
case 'b':
|
||||
args->byte = true;
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (!args->filename)
|
||||
args->filename = strdup_or_error(state, arg);
|
||||
else
|
||||
argp_error(state, "more than one argument given");
|
||||
break;
|
||||
case ARGP_KEY_FINI:
|
||||
if ((!args->logical) && (!args->phys))
|
||||
argp_error(state, "can't pass both -P and -L options");
|
||||
if (!args->filename)
|
||||
argp_error(state, "no filename given");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct argp_option options[] = {
|
||||
{ "physical", 'P', NULL, 0, "Output physical offsets only"},
|
||||
{ "logical", 'L', NULL, 0, "Output logical offsets only"},
|
||||
{ "byte", 'b', NULL, 0, "Output byte values instead of blocks"},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static struct argp argp = {
|
||||
options,
|
||||
parse_opt,
|
||||
"FILE",
|
||||
"Print fiemap extent mapping"
|
||||
};
|
||||
|
||||
static int get_fiemap_cmd(int argc, char **argv)
|
||||
{
|
||||
struct get_fiemap_args get_fiemap_args = {NULL};
|
||||
int ret;
|
||||
|
||||
get_fiemap_args.phys = true;
|
||||
get_fiemap_args.logical = true;
|
||||
|
||||
ret = argp_parse(&argp, argc, argv, 0, NULL, &get_fiemap_args);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return do_get_fiemap(&get_fiemap_args);
|
||||
}
|
||||
|
||||
static void __attribute__((constructor)) get_fiemap_ctor(void)
|
||||
{
|
||||
cmd_register_argp("get-fiemap", &argp, GROUP_DEBUG, get_fiemap_cmd);
|
||||
}
|
||||
@@ -385,7 +385,8 @@ static int parse_stdin_in_fn(int fd, struct scoutfs_ioctl_quota_rule *irules, si
|
||||
|
||||
ret = getline(&line, &size, stdin);
|
||||
if (ret < 0) {
|
||||
if (errno == ENOENT)
|
||||
free(line);
|
||||
if ((errno == ENOENT) || (errno == 0))
|
||||
return 0;
|
||||
|
||||
ret = -errno;
|
||||
|
||||
@@ -145,7 +145,7 @@ int read_block_verify(int fd, u32 magic, u64 fsid, u64 blkno, int shift, void **
|
||||
else if (fsid != 0 && le64_to_cpu(hdr->fsid) != fsid)
|
||||
fprintf(stderr, "read blkno %llu has bad fsid %016llx != expected %016llx\n",
|
||||
blkno, le64_to_cpu(hdr->fsid), fsid);
|
||||
else if (le32_to_cpu(hdr->blkno) != blkno)
|
||||
else if (le64_to_cpu(hdr->blkno) != blkno)
|
||||
fprintf(stderr, "read blkno %llu has bad blkno %llu != expected %llu\n",
|
||||
blkno, le64_to_cpu(hdr->blkno), blkno);
|
||||
else
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define _UTIL_H_
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
Reference in New Issue
Block a user