Compare commits

...

23 Commits

Author SHA1 Message Date
Auke Kok
161477b987 block_write_{begin,end} take a folio as well as page_mkwrite.
Adds compat handlers for block_write_begin and block_write_end to take
a folio argument instead of page, as this is needed since v6.11-rc1-54-g9f04609f74ec.

To avoid having two duplicate page_mkwrite functions there's now a
complete page/folio ifdef split here to make it handle either. This is
ugly but it's the most straightforward solution here and avoids more
obscure macros.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:28:40 -08:00
Auke Kok
d51cb2000f Fix compat for list_lru_walk in el10
In el10, we don't need compat for list_lru_walk, as was intended
in 8b6418fb. However, the actual redefine from kc_list_lru_walk to
list_lru_walk was omitted. It wasn't needed until el10. Add it now.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:28:40 -08:00
Auke Kok
5407e2de5a Avoid \Z negative pattern in test exclude list
In RHEL10, the grep version is bumped from 3.6 to 3.11, and grep
no longer recognizes the \Z character anymore.

We have 2 solutions: We can either choose to use `grep -P` to
continue using it, or, alternatively, we can choose a different
`null` match to have an effectively empty exclude list.

The latter seems easy enough: By default, we can just exclude
empty lines ("^$") obtaining the exact same behavior as before.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:28:40 -08:00
Auke Kok
90a29aeee6 Switch to .iterate_shared
Since v4.6-rc3-29-g6192269444eb there has been a special readdir VFS
method that can be called for the same directory multiple times in
parallel, without any additional VFS locking. The VFS has provided a
WRAP_DIR_ITER() macro to re-wrap the method with extra locking, in case
the method wasn't safe for this.

With el10, the old .readdir method is now gone, and we have no choice
but to either use the wrapper, or just hook up our readdir() method to
the .iterate_shared op.

From what I can see, our implementation is safe to do this.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:28:40 -08:00
Auke Kok
bcdd6e89a4 Hook up buffer_migrate_folio.
This works together with the dropped block_write_full_page(), allowing
us to drop the _writepage() method as long as we implement
_writepages(). Since v5.19-rc3-395-g67235182a41c. This used to be the
.migratepage() method.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:28:40 -08:00
Auke Kok
f29a411bf1 generic_file_splice_read is removed.
Based on my reading of the gfs2 driver, it appears it's likely the safer
approach to take copy_splice_read instead of filemap_splice_read as it
may potentially lead to cluster deadlocks.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:28:30 -08:00
Auke Kok
8ceedbd819 Obsolete scoutfs_writepage.
Due to folios, the kernel will call scoutfs_writepages() and this
becomes unused. It could be ported but the helper function to call isn't
exported anymore.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:27:11 -08:00
Auke Kok
bcde8b2169 Fix unlocked pt_excl in scoutfs_readahead.
This caller of scoutfs_get_block is now actively used in el10 and
the WARN_ON_ONCE(!lock) in data.c:567 triggers.

XXX FIXME XXX
However, this will hit the `BUG_ON(!list_empty(pages));` that's a few
lines further, in some of our testing, so, it's still not right

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:27:11 -08:00
Auke Kok
92e3c72d9d mv overwrite error format changes in el10
This is somewhat cumbersome, we want to see the error message, but the
format changes enough to make this messy. We opt to change the golden to
the new format, which only shows one of the arguments in its error
output: the thing that cannot be overwritten. We then add a filter that
rewrites the old output format with sed patterns to be exactly like the
new format, so this will work everywhere again, without changing or
adding filters to obscure error messages.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:27:11 -08:00
Auke Kok
e42705d757 Add sysfs default_groups usage.
Since v5.1-rc3-29-gaa30f47cf666, and in el9, there are changes to reduce
the amount of boilerplate code needed to hook up lots of attribute files
using a .default_groups member. In el10, this becomes the required
method as the .default_attrs member now becomes removed. This touches
every sysfs part that we have.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:27:11 -08:00
Auke Kok
f08a338a6b set_blocksize() takes struct file argument.
In v6.9-rc4-8-gead083aeeed9, this now takes a struct file argument,
adding to the ifdef salad we've got going on here.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:27:11 -08:00
Auke Kok
38906a51da generic_fillattr() now wants the request_mask arg from caller.
Since ~v6.5-rc1-95-g0d72b92883c6, generic_fillattr() asks us to pass
through the request_mask from the caller. This allows it to only
request a subset.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:27:11 -08:00
Auke Kok
4ef1f56f76 Shrinker API v4.
Yet another major shrinker API evolution in v6.6-rc4-53-gc42d50aefd17.
The struct shrinker now has to be dynamically allocated. This is
purposely a backwards incompatible break. We add another KC_ wrapper
around the new shrinker_alloc() and move some initialization around to
make this as much as possible low impact, but compatible with the old
APIs through substitution.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:27:11 -08:00
Auke Kok
80926cfe55 bio_add_page is now __must_check
The return type always has been int, so, we just need to add return
value checking and do something with it. We could return -ENOMEM here as
well, either way it'll fall all the way through no matter what.

This is since v6.4-rc2-100-g83f2caaaf9cb.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:27:11 -08:00
Auke Kok
5f2f8f199b Adjust for __assign_str() losing second argument.
In v6.8-9146-gc759e609030c, the second argument for __assign_str() was
removed, as the second parameter is already derived from the __string()
definition and no longer needed. We have to do a little digging in
headers here to find the definition.

Note the missing `;` at a few places... it has to be added now.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-13 14:27:11 -08:00
Auke Kok
4c4a9c154d RIP bd_inode.
v6.9-rc4-29-g203c1ce0bb06 removes bd_inode. The canonical replacement is
bd_mapping->host, were applicable. We have one use where we directly
need the mapping instead of the inode, as well.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-11 11:30:23 -08:00
Auke Kok
b1bef1b7f5 Fix compiler warnings for flex array definitions.
Instead of defining a struct that ends with a flex array member with
`val[0]`, the compiler now balks at this since technically, the spec
considers this unsanitary. As a result however, we can't memcpy to
`struct->val` since that's a pointer and now we're writing something of
a different length (u8's in our case) into something that's of pointer
size. So there we have to do the opposite, and memcpy to
&struct->val[0].

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-11 11:30:23 -08:00
Auke Kok
34a78ae4a6 unaligned.h moved from asm/ to linux/
In v6.12-rc1-3-g5f60d5f6bbc1, asm/unaligned.h only included
asm-generic/unaligned.h and that was cleaned up from architecture
specific things. Everyone should now include linux/unaligned.h and the
former include was removed.

A quick peek at server.c shows that while included, it no longer uses
any function from this header at all, so it can just be dropped.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-11 11:30:23 -08:00
Auke Kok
c63b3188c3 Account for difference in stat output format for device nodes.
The new format in el10 has non-hex output, separated by a comma. Add the
additional filter string so this works as expected.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-11 11:30:23 -08:00
Auke Kok
a455d089e5 Fix el10 not skipping the format-version-forward-back test.
The logic only accounted for single-digit versions. With el10, that
breaks.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-11 11:30:23 -08:00
Auke Kok
85e3424a63 Use a/m/c_time accessor functions.
In v6.6-rc5-1-g077c212f0344, one can no longer directly access the
inode m_time and a_time etc. We have to go through these static inline
functions to get to them. The compat is matched closely to mimic the
new functions.

Further back, ctime accessors were added in v6.5-rc1-7-g9b6304c1d537,
and need to be applied as well.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-11 11:30:23 -08:00
Auke Kok
8a953c9ba3 Stop using egrep.
egrep Is no longer in el10, so replace it with `grep -E` everywhere.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-11 11:30:12 -08:00
Auke Kok
40df1e078b prandom_bytes and family removed, switch to get_random_bytes variants.
In v6.1-rc5-2-ge9a688bcb193, get_random_u32_below() becomes available and
can start replacing prandom_bytes_max(). Switch to it where we can.

get_random_bytes() has been available since el7, so also replace
prandom_bytes() where we're using it.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-02-06 11:14:31 -08:00
34 changed files with 621 additions and 156 deletions

View File

@@ -60,11 +60,11 @@ scoutfs-y += \
#
.PHONY: $(src)/check_exported_types
$(src)/check_exported_types:
@if egrep '\<[us](8|16|32|64\>)' $(src)/format.h $(src)/ioctl.h; then \
@if grep -E '\<[us](8|16|32|64\>)' $(src)/format.h $(src)/ioctl.h; then \
echo "no raw types in exported headers, preface with __"; \
exit 1; \
fi
@if egrep '\<__packed\>' $(src)/format.h $(src)/ioctl.h; then \
@if grep -E '\<__packed\>' $(src)/format.h $(src)/ioctl.h; then \
echo "no __packed allowed in exported headers"; \
exit 1; \
fi

View File

@@ -496,3 +496,131 @@ endif
ifneq (,$(shell grep 'struct posix_acl.*get_inode_acl' include/linux/fs.h))
ccflags-y += -DKC_GET_INODE_ACL
endif
#
# v6.1-rc5-2-ge9a688bcb193
#
# get_random_u32_below() implementation
ifneq (,$(shell grep 'u32 get_random_u32_below' include/linux/random.h))
ccflags-y += -DKC_HAVE_GET_RANDOM_U32_BELOW
endif
# v6.5-rc1-7-g9b6304c1d537
#
# ctime accessor methods
ifneq (,$(shell grep 'timespec64 inode_set_ctime_current' include/linux/fs.h))
ccflags-y += -DKC_FS_INODE_C_TIME_ACCESSOR
endif
#
# v6.6-rc5-1-g077c212f0344
#
# Must use access methods from fs.h to get to inode ctime/mtime/atime
ifneq (,$(shell grep 'inline time64_t inode_get_atime_sec' include/linux/fs.h))
ccflags-y += -DKC_FS_INODE_AM_TIME_ACCESSOR
endif
#
# v6.12-rc1-3-g5f60d5f6bbc1
#
# asm/unaligned.h replaced with linux/unaligned.h
ifneq (,$(shell grep -s 'define __LINUX_UNALIGNED_H' include/linux/unaligned.h))
ccflags-y += -DKC_HAVE__LINUX_UNALIGNED_H
endif
#
# v6.9-rc4-29-g203c1ce0bb06
#
# RIP bd_inode. (note, struct moved between headers!)
ifneq (,$(shell grep -s 'struct inode.*bd_inode' include/linux/blk_types.h include/linux/fs.h))
ccflags-y += -DKC_HAVE_BD_INODE
endif
#
# v6.8-9146-gc759e609030c
#
# Removes __assign_str_len() and removes the 2nd param of __assign_str().
ifneq (,$(shell grep -s 'define __assign_str.dst, src' \
include/trace/trace_events.h \
include/trace/ftrace.h \
include/trace/stages/stage6_event_callback.h))
ccflags-y += -DKC_HAVE_ASSIGN_STR_PARMS
endif
#
# v6.5-113-g615e95831ec3
#
ifneq (,$(shell grep 'generic_fillattr..*,.u32,' include/linux/fs.h))
ccflags-y += -DKC_GENERIC_FILLATTR_REQUEST_MASK
endif
#
# v6.6-rc4-53-gc42d50aefd17
#
# el10 yet again modifies the shrinker API significantly, breaking our current
# implementation.
ifneq (,$(shell grep 'struct shrinker .shrinker_alloc' include/linux/shrinker.h))
ccflags-y += -DKC_SHRINKER_ALLOC
endif
#
# v6.9-rc4-8-gead083aeeed9
#
# set_blocksize() now has a struct file arg.
ifneq (,$(shell grep -s 'int set_blocksize.struct file' include/linux/blkdev.h))
ccflags-y += -DKC_BLKDEV_SET_BLOCKSIZE_FILE
endif
#
# v5.1-rc3-29-gaa30f47cf666
#
# struct kobj_type now has member `default_groups`
ifneq (,$(shell grep 'const struct attribute_group ..default_groups;' include/linux/kobject.h))
ccflags-y += -DKC_KOBJECT_DEFAULT_GROUPS
endif
#
# v6.7-rc4-307-g17bf23a981be
#
# block_write_full_page() is replaced with block_write_full_folio(),
# but that isn't exported as it used to be (and the only users now
# are builtin). However, the kernel will fall back to using the
# .writepages method instead, so we can drop this method.
ifneq (,$(shell grep 'int block_write_full_page.struct page' include/linux/buffer_head.h))
ccflags-y += -DKC_HAVE_BLOCK_WRITE_FULL_PAGE
endif
#
# v6.4-rc2-29-gc6585011bc1d
#
# generic_file_splice_read is removed. It can be replaced with filemap_splice_read
# or copy_splice_read.
ifneq (,$(shell grep 'ssize_t generic_file_splice_read.struct file' include/linux/fs.h))
ccflags-y += -DKC_HAVE_GENERIC_FILE_SPLICE_READ
endif
#
# v5.19-rc3-395-g67235182a41c
#
# Adds buffer_migrate_folio(), similar to other fss. Quote willy: "If the filesystem
# implements migrate_folio and writepages, there is no need for a writepage implementation."
ifneq (,$(shell grep 'int buffer_migrate_folio.struct address_space' include/linux/buffer_head.h))
ccflags-y += -DKC_HAVE_BUFFER_MIGRATE_FOLIO
endif
#
# v4.6-rc3-29-g6192269444eb
#
# Adds .iterate_shared readdir() iterator vfs method.
ifneq (,$(shell grep 'iterate_shared...struct file.., struct dir_context' include/linux/fs.h))
ccflags-y += -DKC_HAVE_ITERATE_SHARED
endif
#
# v6.11-rc1-54-g9f04609f74ec
#
# Last of a series of changes that make block_write_begin/end take a folio instead of
# a struct pagep.
ifneq (,$(shell grep 'int __block_write_begin.struct.folio' include/linux/buffer_head.h))
ccflags-y += -DKC_BLOCK_WRITE_BEGIN_FOLIO
endif

View File

@@ -197,7 +197,7 @@ int scoutfs_set_acl_locked(struct inode *inode, struct posix_acl *acl, int type,
if (!value) {
/* can be setting an acl that only affects mode, didn't need xattr */
inode_inc_iversion(inode);
inode->i_ctime = current_time(inode);
inode_set_ctime_current(inode);
}
}

View File

@@ -308,14 +308,14 @@ static bool invalid_extent(u64 start, u64 end, u64 first, u64 last)
static bool invalid_meta_blkno(struct super_block *sb, u64 blkno)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
u64 last_meta = (i_size_read(sbi->meta_bdev->bd_inode) >> SCOUTFS_BLOCK_LG_SHIFT) - 1;
u64 last_meta = (i_size_read(KC_BDEV_INODE(sbi->meta_bdev)) >> SCOUTFS_BLOCK_LG_SHIFT) - 1;
return invalid_extent(blkno, blkno, SCOUTFS_META_DEV_START_BLKNO, last_meta);
}
static bool invalid_data_extent(struct super_block *sb, u64 start, u64 len)
{
u64 last_data = (i_size_read(sb->s_bdev->bd_inode) >> SCOUTFS_BLOCK_SM_SHIFT) - 1;
u64 last_data = (i_size_read(KC_BDEV_INODE(sb->s_bdev)) >> SCOUTFS_BLOCK_SM_SHIFT) - 1;
return invalid_extent(start, start + len - 1, SCOUTFS_DATA_DEV_START_BLKNO, last_data);
}

View File

@@ -103,8 +103,8 @@ int scoutfs_get_attr_x(struct inode *inode, struct scoutfs_ioctl_inode_attr_x *i
size = fill_attr(size, iax, SCOUTFS_IOC_IAX_OFFLINE_BLOCKS,
offline_blocks, offline);
}
size = fill_attr(size, iax, SCOUTFS_IOC_IAX_CTIME, ctime_sec, inode->i_ctime.tv_sec);
size = fill_attr(size, iax, SCOUTFS_IOC_IAX_CTIME, ctime_nsec, inode->i_ctime.tv_nsec);
size = fill_attr(size, iax, SCOUTFS_IOC_IAX_CTIME, ctime_sec, inode_get_ctime_sec(inode));
size = fill_attr(size, iax, SCOUTFS_IOC_IAX_CTIME, ctime_nsec, inode_get_ctime_nsec(inode));
size = fill_attr(size, iax, SCOUTFS_IOC_IAX_CRTIME, crtime_sec, si->crtime.tv_sec);
size = fill_attr(size, iax, SCOUTFS_IOC_IAX_CRTIME, crtime_nsec, si->crtime.tv_nsec);
size = fill_attr(size, iax, SCOUTFS_IOC_IAX_SIZE, size, i_size_read(inode));
@@ -223,10 +223,8 @@ int scoutfs_set_attr_x(struct inode *inode, struct scoutfs_ioctl_inode_attr_x *i
scoutfs_inode_set_data_version(inode, iax->data_version);
if (iax->x_mask & SCOUTFS_IOC_IAX_SIZE)
i_size_write(inode, iax->size);
if (iax->x_mask & SCOUTFS_IOC_IAX_CTIME) {
inode->i_ctime.tv_sec = iax->ctime_sec;
inode->i_ctime.tv_nsec = iax->ctime_nsec;
}
if (iax->x_mask & SCOUTFS_IOC_IAX_CTIME)
inode_set_ctime(inode, iax->ctime_sec, iax->ctime_nsec);
if (iax->x_mask & SCOUTFS_IOC_IAX_CRTIME) {
si->crtime.tv_sec = iax->crtime_sec;
si->crtime.tv_nsec = iax->crtime_nsec;

View File

@@ -884,7 +884,7 @@ int scoutfs_block_dirty_ref(struct super_block *sb, struct scoutfs_alloc *alloc,
hdr->magic = cpu_to_le32(magic);
hdr->fsid = cpu_to_le64(sbi->fsid);
hdr->blkno = cpu_to_le64(bl->blkno);
prandom_bytes(&hdr->seq, sizeof(hdr->seq));
get_random_bytes(&hdr->seq, sizeof(hdr->seq));
trace_scoutfs_block_dirty_ref(sb, le64_to_cpu(ref->blkno), le64_to_cpu(ref->seq),
le64_to_cpu(hdr->blkno), le64_to_cpu(hdr->seq));
@@ -1229,7 +1229,12 @@ static int sm_block_io(struct super_block *sb, struct block_device *bdev, blk_op
kc_bio_set_sector(bio, blkno << (SCOUTFS_BLOCK_SM_SHIFT - 9));
bio->bi_end_io = sm_block_bio_end_io;
bio->bi_private = &sbc;
bio_add_page(bio, page, SCOUTFS_BLOCK_SM_SIZE, 0);
ret = bio_add_page(bio, page, SCOUTFS_BLOCK_SM_SIZE, 0);
if (ret != SCOUTFS_BLOCK_SM_SIZE) {
bio_put(bio);
ret = -EFAULT;
goto out;
}
init_completion(&sbc.comp);
sbc.err = 0;
@@ -1285,9 +1290,12 @@ int scoutfs_block_setup(struct super_block *sb)
binf->sb = sb;
init_waitqueue_head(&binf->waitq);
KC_INIT_SHRINKER_FUNCS(&binf->shrinker, block_count_objects,
block_scan_objects);
KC_REGISTER_SHRINKER(&binf->shrinker, "scoutfs-block:" SCSBF, SCSB_ARGS(sb));
KC_SETUP_SHRINKER(binf->shrinker, binf, 0, block_count_objects,
block_scan_objects, "scoutfs-block:" SCSBF, SCSB_ARGS(sb));
if (KC_SHRINKER_IS_NULL(binf->shrinker)) {
ret = -ENOMEM;
goto out;
}
INIT_WORK(&binf->free_work, block_free_work);
init_llist_head(&binf->free_llist);
@@ -1309,7 +1317,7 @@ void scoutfs_block_destroy(struct super_block *sb)
struct block_info *binf = SCOUTFS_SB(sb)->block_info;
if (binf) {
KC_UNREGISTER_SHRINKER(&binf->shrinker);
KC_UNREGISTER_SHRINKER(binf->shrinker);
block_shrink_all(sb);
flush_work(&binf->free_work);
rhashtable_destroy(&binf->ht);

View File

@@ -2042,7 +2042,7 @@ struct merged_item {
u64 seq;
u8 flags;
unsigned int val_len;
u8 val[0];
u8 val[];
};
static inline struct merged_item *mitem_container(struct rb_node *node)
@@ -2208,7 +2208,7 @@ static int merge_read_item(struct super_block *sb, struct scoutfs_key *key, u64
mitem->flags = flags;
mitem->val_len = val_len;
if (val_len)
memcpy(mitem->val, val, val_len);
memcpy(&mitem->val[0], val, val_len);
if (found) {
replace_mitem(rng, found, mitem);

View File

@@ -30,7 +30,7 @@ struct scoutfs_btree_item_list {
u64 seq;
u8 flags;
int val_len;
u8 val[0];
u8 val[];
};
int scoutfs_btree_lookup(struct super_block *sb,

View File

@@ -34,6 +34,17 @@ static struct attribute scoutfs_counter_attrs[] = {
#define NR_ATTRS ARRAY_SIZE(scoutfs_counter_attrs)
static struct attribute *scoutfs_counter_attr_ptrs[NR_ATTRS + 1];
#ifdef KC_KOBJECT_DEFAULT_GROUPS
static struct attribute_group scoutfs_counter_attr_group = {
.attrs = scoutfs_counter_attr_ptrs,
};
static const struct attribute_group *scoutfs_counter_attr_groups[] = {
&scoutfs_counter_attr_group,
NULL,
};
#endif
static ssize_t scoutfs_counter_attr_show(struct kobject *kobj,
struct attribute *attr, char *buf)
{
@@ -45,7 +56,6 @@ static ssize_t scoutfs_counter_attr_show(struct kobject *kobj,
counters = container_of(kobj, struct scoutfs_counters, kobj);
index = attr - scoutfs_counter_attrs;
pcpu = &counters->FIRST_COUNTER + index;
return snprintf(buf, PAGE_SIZE, "%lld\n", percpu_counter_sum(pcpu));
}
@@ -63,7 +73,7 @@ static const struct sysfs_ops scoutfs_counter_attr_ops = {
};
static struct kobj_type scoutfs_counters_ktype = {
.default_attrs = scoutfs_counter_attr_ptrs,
.KC_KOBJ_DEFAULT_OP = KC_KOBJ_DEFAULT_PICK(scoutfs_counter_attr_groups, scoutfs_counter_attr_ptrs),
.sysfs_ops = &scoutfs_counter_attr_ops,
.release = scoutfs_counters_kobj_release,
};

View File

@@ -716,24 +716,24 @@ static int scoutfs_readpage(struct file *file, struct page *page)
return ret;
}
if (scoutfs_per_task_add_excl(&si->pt_data_lock, &pt_ent, inode_lock)) {
ret = scoutfs_data_wait_check(inode, page_offset(page),
PAGE_SIZE, SEF_OFFLINE,
SCOUTFS_IOC_DWO_READ, &dw,
inode_lock);
if (ret != 0) {
unlock_page(page);
scoutfs_per_task_del(&si->pt_data_lock, &pt_ent);
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
}
if (ret > 0) {
ret = scoutfs_data_wait(inode, &dw);
if (ret == 0)
ret = AOP_TRUNCATED_PAGE;
}
if (ret != 0)
return ret;
scoutfs_per_task_add_excl(&si->pt_data_lock, &pt_ent, inode_lock);
ret = scoutfs_data_wait_check(inode, page_offset(page),
PAGE_SIZE, SEF_OFFLINE,
SCOUTFS_IOC_DWO_READ, &dw,
inode_lock);
if (ret != 0) {
unlock_page(page);
scoutfs_per_task_del(&si->pt_data_lock, &pt_ent);
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
}
if (ret > 0) {
ret = scoutfs_data_wait(inode, &dw);
if (ret == 0)
ret = AOP_TRUNCATED_PAGE;
}
if (ret != 0)
return ret;
#ifdef KC_MPAGE_READ_FOLIO
ret = mpage_read_folio(folio, scoutfs_get_block_read);
@@ -741,8 +741,8 @@ static int scoutfs_readpage(struct file *file, struct page *page)
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);
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
return ret;
}
@@ -760,8 +760,10 @@ static int scoutfs_readpages(struct file *file, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages)
{
struct inode *inode = file->f_inode;
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
struct super_block *sb = inode->i_sb;
struct scoutfs_lock *inode_lock = NULL;
SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_ent);
struct page *page;
struct page *tmp;
int ret;
@@ -771,6 +773,8 @@ static int scoutfs_readpages(struct file *file, struct address_space *mapping,
if (ret)
goto out;
scoutfs_per_task_add_excl(&si->pt_data_lock, &pt_ent, inode_lock);
list_for_each_entry_safe(page, tmp, pages, lru) {
ret = scoutfs_data_wait_check(inode, page_offset(page),
PAGE_SIZE, SEF_OFFLINE,
@@ -790,6 +794,7 @@ static int scoutfs_readpages(struct file *file, struct address_space *mapping,
ret = mpage_readpages(mapping, pages, nr_pages, scoutfs_get_block_read);
out:
scoutfs_per_task_del(&si->pt_data_lock, &pt_ent);
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
BUG_ON(!list_empty(pages));
return ret;
@@ -798,8 +803,10 @@ out:
static void scoutfs_readahead(struct readahead_control *rac)
{
struct inode *inode = rac->file->f_inode;
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
struct super_block *sb = inode->i_sb;
struct scoutfs_lock *inode_lock = NULL;
SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_ent);
int ret;
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ,
@@ -807,6 +814,8 @@ static void scoutfs_readahead(struct readahead_control *rac)
if (ret)
return;
scoutfs_per_task_add_excl(&si->pt_data_lock, &pt_ent, inode_lock);
ret = scoutfs_data_wait_check(inode, readahead_pos(rac),
readahead_length(rac), SEF_OFFLINE,
SCOUTFS_IOC_DWO_READ, NULL,
@@ -814,14 +823,17 @@ static void scoutfs_readahead(struct readahead_control *rac)
if (ret == 0)
mpage_readahead(rac, scoutfs_get_block_read);
scoutfs_per_task_del(&si->pt_data_lock, &pt_ent);
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
}
#endif
#ifdef KC_HAVE_BLOCK_WRITE_FULL_PAGE
static int scoutfs_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, scoutfs_get_block_write, wbc);
}
#endif
static int scoutfs_writepages(struct address_space *mapping,
struct writeback_control *wbc)
@@ -841,7 +853,7 @@ static int scoutfs_write_begin(struct file *file,
#ifdef KC_BLOCK_WRITE_BEGIN_AOP_FLAGS
unsigned flags,
#endif
struct page **pagep, void **fsdata)
KC_PAGE_OR_FOLIO(struct page **pagep, struct folio **folio), void **fsdata)
{
struct inode *inode = mapping->host;
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
@@ -886,7 +898,7 @@ retry:
#ifdef KC_BLOCK_WRITE_BEGIN_AOP_FLAGS
flags,
#endif
pagep, scoutfs_get_block_write);
KC_PAGE_OR_FOLIO(pagep, folio), scoutfs_get_block_write);
if (ret < 0) {
scoutfs_release_trans(sb);
scoutfs_inode_index_unlock(sb, &wbd->ind_locks);
@@ -919,7 +931,8 @@ static int writepages_sync_none(struct address_space *mapping, loff_t start,
static int scoutfs_write_end(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata)
KC_PAGE_OR_FOLIO(struct page *pagep, struct folio *folio),
void *fsdata)
{
struct inode *inode = mapping->host;
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
@@ -927,10 +940,11 @@ static int scoutfs_write_end(struct file *file, struct address_space *mapping,
struct write_begin_data *wbd = fsdata;
int ret;
trace_scoutfs_write_end(sb, scoutfs_ino(inode), page->index, (u64)pos,
len, copied);
trace_scoutfs_write_end(sb, scoutfs_ino(inode),
KC_PAGE_OR_FOLIO(pagep->index, folio_index(folio)),
(u64)pos, len, copied);
ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
ret = generic_write_end(file, mapping, pos, len, copied, KC_PAGE_OR_FOLIO(pagep, folio), fsdata);
if (ret > 0) {
if (!si->staging) {
scoutfs_inode_set_data_seq(inode);
@@ -1483,12 +1497,14 @@ int scoutfs_data_move_blocks(struct inode *from, u64 from_off,
cur_time = current_time(from);
if (!is_stage) {
to->i_ctime = to->i_mtime = cur_time;
inode_set_ctime_to_ts(to, cur_time);
inode_set_mtime_to_ts(to, cur_time);
inode_inc_iversion(to);
scoutfs_inode_inc_data_version(to);
scoutfs_inode_set_data_seq(to);
}
from->i_ctime = from->i_mtime = cur_time;
inode_set_ctime_to_ts(from, cur_time);
inode_set_mtime_to_ts(from, cur_time);
inode_inc_iversion(from);
scoutfs_inode_inc_data_version(from);
scoutfs_inode_set_data_seq(from);
@@ -1967,7 +1983,11 @@ static int scoutfs_data_page_mkwrite(struct vm_area_struct *vma,
struct vm_fault *vmf)
{
#endif
#ifdef KC_MPAGE_READ_FOLIO
struct folio *folio = page_folio(vmf->page);
#else
struct page *page = vmf->page;
#endif
struct file *file = vma->vm_file;
struct inode *inode = file_inode(file);
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
@@ -2035,27 +2055,50 @@ static int scoutfs_data_page_mkwrite(struct vm_area_struct *vma,
down_write(&si->extent_sem);
#ifdef KC_MPAGE_READ_FOLIO
if (!folio_trylock(folio)) {
#else
if (!trylock_page(page)) {
#endif
ret = VM_FAULT_NOPAGE;
goto out_sem;
}
ret = VM_FAULT_LOCKED;
#ifdef KC_MPAGE_READ_FOLIO
if ((folio->mapping != inode->i_mapping) ||
(!folio_test_uptodate(folio)) ||
(folio_pos(folio) > size)) {
folio_unlock(folio);
#else
if ((page->mapping != inode->i_mapping) ||
(!PageUptodate(page)) ||
(page_offset(page) > size)) {
(page_offset(page) > size)) {
unlock_page(page);
#endif
ret = VM_FAULT_NOPAGE;
goto out_sem;
}
#ifdef KC_MPAGE_READ_FOLIO
if (folio_index(folio) == (size - 1) >> PAGE_SHIFT)
#else
if (page->index == (size - 1) >> PAGE_SHIFT)
#endif
len = ((size - 1) & ~PAGE_MASK) + 1;
#ifdef KC_MPAGE_READ_FOLIO
err = __block_write_begin(KC_PAGE_OR_FOLIO(folio_page(folio, 0), folio), pos, PAGE_SIZE, scoutfs_get_block);
#else
err = __block_write_begin(page, pos, PAGE_SIZE, scoutfs_get_block);
#endif
if (err) {
ret = vmf_error(err);
#ifdef KC_MPAGE_READ_FOLIO
folio_unlock(folio);
#else
unlock_page(page);
#endif
goto out_sem;
}
/* end scoutfs_write_begin */
@@ -2065,8 +2108,13 @@ static int scoutfs_data_page_mkwrite(struct vm_area_struct *vma,
* progress, we are guaranteed that writeback during freezing will
* see the dirty page and writeprotect it again.
*/
#ifdef KC_MPAGE_READ_FOLIO
folio_mark_dirty(folio);
folio_wait_stable(folio);
#else
set_page_dirty(page);
wait_for_stable_page(page);
#endif
/* scoutfs_write_end */
scoutfs_inode_set_data_seq(inode);
@@ -2193,6 +2241,9 @@ const struct address_space_operations scoutfs_file_aops = {
.dirty_folio = block_dirty_folio,
.invalidate_folio = block_invalidate_folio,
.read_folio = scoutfs_read_folio,
#ifdef KC_HAVE_BUFFER_MIGRATE_FOLIO
.migrate_folio = buffer_migrate_folio,
#endif
#else
.readpage = scoutfs_readpage,
#endif
@@ -2201,7 +2252,9 @@ const struct address_space_operations scoutfs_file_aops = {
#else
.readahead = scoutfs_readahead,
#endif
#ifdef KC_HAVE_BLOCK_WRITE_FULL_PAGE
.writepage = scoutfs_writepage,
#endif
.writepages = scoutfs_writepages,
.write_begin = scoutfs_write_begin,
.write_end = scoutfs_write_end,
@@ -2216,8 +2269,12 @@ 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
#ifdef KC_HAVE_GENERIC_FILE_SPLICE_READ
.splice_read = generic_file_splice_read,
#else
.splice_read = copy_splice_read,
#endif
.mmap = scoutfs_file_mmap,
.unlocked_ioctl = scoutfs_ioctl,

View File

@@ -759,6 +759,7 @@ static int scoutfs_mknod(KC_VFS_NS_DEF
struct scoutfs_lock *dir_lock = NULL;
struct scoutfs_lock *inode_lock = NULL;
struct scoutfs_inode_info *si;
struct kc_timespec cur_time;
LIST_HEAD(ind_locks);
u64 hash;
u64 pos;
@@ -790,9 +791,13 @@ static int scoutfs_mknod(KC_VFS_NS_DEF
set_dentry_fsdata(dentry, dir_lock);
i_size_write(dir, i_size_read(dir) + dentry->d_name.len);
dir->i_mtime = dir->i_ctime = current_time(inode);
inode->i_mtime = inode->i_atime = inode->i_ctime = dir->i_mtime;
si->crtime = inode->i_mtime;
cur_time = current_time(inode);
inode_set_mtime_to_ts(dir, cur_time);
inode_set_ctime_to_ts(dir, cur_time);
inode_set_mtime_to_ts(inode, cur_time);
inode_set_atime_to_ts(inode, cur_time);
inode_set_ctime_to_ts(inode, cur_time);
si->crtime = inode_get_mtime(inode);
inode_inc_iversion(dir);
inode_inc_iversion(inode);
scoutfs_forest_inc_inode_count(sb);
@@ -845,6 +850,7 @@ static int scoutfs_link(struct dentry *old_dentry,
struct scoutfs_lock *dir_lock;
struct scoutfs_lock *inode_lock = NULL;
struct scoutfs_lock *orph_lock = NULL;
struct kc_timespec cur_time;
LIST_HEAD(ind_locks);
bool del_orphan = false;
u64 dir_size;
@@ -919,8 +925,10 @@ retry:
set_dentry_fsdata(dentry, dir_lock);
i_size_write(dir, dir_size);
dir->i_mtime = dir->i_ctime = current_time(inode);
inode->i_ctime = dir->i_mtime;
cur_time = current_time(inode);
inode_set_mtime_to_ts(dir, cur_time);
inode_set_ctime_to_ts(dir, cur_time);
inode_set_ctime_to_ts(inode, inode_get_mtime(dir));
inc_nlink(inode);
inode_inc_iversion(dir);
inode_inc_iversion(inode);
@@ -1030,13 +1038,13 @@ retry:
set_dentry_fsdata(dentry, dir_lock);
dir->i_ctime = ts;
dir->i_mtime = ts;
inode_set_ctime_to_ts(dir, ts);
inode_set_mtime_to_ts(dir, ts);
i_size_write(dir, i_size_read(dir) - dentry->d_name.len);
inode_inc_iversion(dir);
inode_inc_iversion(inode);
inode->i_ctime = ts;
inode_set_ctime_to_ts(inode, ts);
drop_nlink(inode);
if (S_ISDIR(inode->i_mode)) {
drop_nlink(dir);
@@ -1239,6 +1247,7 @@ static int scoutfs_symlink(KC_VFS_NS_DEF
struct scoutfs_lock *dir_lock = NULL;
struct scoutfs_lock *inode_lock = NULL;
struct scoutfs_inode_info *si;
struct kc_timespec cur_time;
LIST_HEAD(ind_locks);
u64 hash;
u64 pos;
@@ -1278,11 +1287,13 @@ static int scoutfs_symlink(KC_VFS_NS_DEF
set_dentry_fsdata(dentry, dir_lock);
i_size_write(dir, i_size_read(dir) + dentry->d_name.len);
dir->i_mtime = dir->i_ctime = current_time(inode);
cur_time = current_time(inode);
inode_set_mtime_to_ts(dir, cur_time);
inode_set_ctime_to_ts(dir, cur_time);
inode_inc_iversion(dir);
inode->i_ctime = dir->i_mtime;
si->crtime = inode->i_ctime;
inode_set_ctime_to_ts(inode, inode_get_mtime(dir));
si->crtime = inode_get_ctime(inode);
i_size_write(inode, name_len);
inode_inc_iversion(inode);
scoutfs_forest_inc_inode_count(sb);
@@ -1804,15 +1815,15 @@ retry:
}
now = current_time(old_inode);
old_dir->i_ctime = now;
old_dir->i_mtime = now;
inode_set_ctime_to_ts(old_dir, now);
inode_set_mtime_to_ts(old_dir, now);
if (new_dir != old_dir) {
new_dir->i_ctime = now;
new_dir->i_mtime = now;
inode_set_ctime_to_ts(new_dir, now);
inode_set_mtime_to_ts(new_dir, now);
}
old_inode->i_ctime = now;
inode_set_ctime_to_ts(old_inode, now);
if (new_inode)
new_inode->i_ctime = now;
inode_set_ctime_to_ts(new_inode, now);
inode_inc_iversion(old_dir);
inode_inc_iversion(old_inode);
@@ -1939,6 +1950,7 @@ static int scoutfs_tmpfile(KC_VFS_NS_DEF
struct scoutfs_lock *inode_lock = NULL;
struct scoutfs_lock *orph_lock = NULL;
struct scoutfs_inode_info *si;
struct kc_timespec cur_time;
LIST_HEAD(ind_locks);
int ret;
@@ -1955,8 +1967,11 @@ static int scoutfs_tmpfile(KC_VFS_NS_DEF
if (ret < 0)
goto out; /* XXX returning error but items created */
inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
si->crtime = inode->i_mtime;
cur_time = current_time(inode);
inode_set_mtime_to_ts(inode, cur_time);
inode_set_ctime_to_ts(inode, cur_time);
inode_set_atime_to_ts(inode, cur_time);
si->crtime = inode_get_mtime(inode);
insert_inode_hash(inode);
ihold(inode); /* need to update inode modifications in d_tmpfile */
#ifdef KC_D_TMPFILE_DENTRY
@@ -2024,7 +2039,11 @@ const struct inode_operations scoutfs_symlink_iops = {
};
const struct file_operations scoutfs_dir_fops = {
#ifdef KC_HAVE_ITERATE_SHARED
.iterate_shared = scoutfs_readdir,
#else
.iterate = scoutfs_readdir,
#endif
#ifdef KC_FMODE_KABI_ITERATE
.open = scoutfs_dir_open,
#endif

View File

@@ -217,6 +217,9 @@ static struct attribute *fence_attrs[] = {
SCOUTFS_ATTR_PTR(rid),
NULL,
};
#ifdef KC_KOBJECT_DEFAULT_GROUPS
ATTRIBUTE_GROUPS(fence);
#endif
#define FENCE_TIMEOUT_MS (MSEC_PER_SEC * 30)
@@ -255,7 +258,8 @@ int scoutfs_fence_start(struct super_block *sb, u64 rid, __be32 ipv4_addr, int r
fence->rid = rid;
ret = scoutfs_sysfs_create_attrs_parent(sb, &fi->kset->kobj,
&fence->ssa, fence_attrs,
&fence->ssa,
KC_KOBJ_DEFAULT(fence),
"%016llx", rid);
if (ret < 0) {
kfree(fence);

View File

@@ -275,12 +275,9 @@ static void load_inode(struct inode *inode, struct scoutfs_inode *cinode, int in
i_gid_write(inode, le32_to_cpu(cinode->gid));
inode->i_mode = le32_to_cpu(cinode->mode);
inode->i_rdev = le32_to_cpu(cinode->rdev);
inode->i_atime.tv_sec = le64_to_cpu(cinode->atime.sec);
inode->i_atime.tv_nsec = le32_to_cpu(cinode->atime.nsec);
inode->i_mtime.tv_sec = le64_to_cpu(cinode->mtime.sec);
inode->i_mtime.tv_nsec = le32_to_cpu(cinode->mtime.nsec);
inode->i_ctime.tv_sec = le64_to_cpu(cinode->ctime.sec);
inode->i_ctime.tv_nsec = le32_to_cpu(cinode->ctime.nsec);
inode_set_atime(inode, le64_to_cpu(cinode->atime.sec), le32_to_cpu(cinode->atime.nsec));
inode_set_mtime(inode, le64_to_cpu(cinode->mtime.sec), le32_to_cpu(cinode->mtime.nsec));
inode_set_ctime(inode, le64_to_cpu(cinode->ctime.sec), le32_to_cpu(cinode->ctime.nsec));
si->meta_seq = le64_to_cpu(cinode->meta_seq);
si->data_seq = le64_to_cpu(cinode->data_seq);
@@ -401,6 +398,7 @@ int scoutfs_getattr(KC_VFS_NS_DEF
SCOUTFS_LKF_REFRESH_INODE, inode, &lock);
if (ret == 0) {
generic_fillattr(KC_VFS_INIT_NS
KC_FILLATTR_REQUEST_MASK
inode, stat);
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_READ);
}
@@ -412,6 +410,7 @@ static int set_inode_size(struct inode *inode, struct scoutfs_lock *lock,
{
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
struct super_block *sb = inode->i_sb;
struct kc_timespec cur_time;
SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_ent);
LIST_HEAD(ind_locks);
int ret;
@@ -434,7 +433,9 @@ static int set_inode_size(struct inode *inode, struct scoutfs_lock *lock,
scoutfs_inode_inc_data_version(inode);
truncate_setsize(inode, new_size);
inode->i_ctime = inode->i_mtime = current_time(inode);
cur_time = current_time(inode);
inode_set_ctime_to_ts(inode, cur_time);
inode_set_mtime_to_ts(inode, cur_time);
if (truncate)
si->flags |= SCOUTFS_INO_FLAG_TRUNCATE;
scoutfs_inode_set_data_seq(inode);
@@ -901,14 +902,14 @@ static void store_inode(struct scoutfs_inode *cinode, struct inode *inode, int i
cinode->gid = cpu_to_le32(i_gid_read(inode));
cinode->mode = cpu_to_le32(inode->i_mode);
cinode->rdev = cpu_to_le32(inode->i_rdev);
cinode->atime.sec = cpu_to_le64(inode->i_atime.tv_sec);
cinode->atime.nsec = cpu_to_le32(inode->i_atime.tv_nsec);
cinode->atime.sec = cpu_to_le64(inode_get_atime_sec(inode));
cinode->atime.nsec = cpu_to_le32(inode_get_atime_nsec(inode));
memset(cinode->atime.__pad, 0, sizeof(cinode->atime.__pad));
cinode->ctime.sec = cpu_to_le64(inode->i_ctime.tv_sec);
cinode->ctime.nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
cinode->ctime.sec = cpu_to_le64(inode_get_ctime_sec(inode));
cinode->ctime.nsec = cpu_to_le32(inode_get_ctime_nsec(inode));
memset(cinode->ctime.__pad, 0, sizeof(cinode->ctime.__pad));
cinode->mtime.sec = cpu_to_le64(inode->i_mtime.tv_sec);
cinode->mtime.nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
cinode->mtime.sec = cpu_to_le64(inode_get_mtime_sec(inode));
cinode->mtime.nsec = cpu_to_le32(inode_get_mtime_nsec(inode));
memset(cinode->mtime.__pad, 0, sizeof(cinode->mtime.__pad));
cinode->meta_seq = cpu_to_le64(scoutfs_inode_meta_seq(inode));
@@ -1566,6 +1567,7 @@ int scoutfs_new_inode(struct super_block *sb, struct inode *dir, umode_t mode, d
struct scoutfs_inode sinode;
struct scoutfs_key key;
struct inode *inode;
struct kc_timespec cur_time;
int inode_bytes;
int ret;
@@ -1595,7 +1597,10 @@ int scoutfs_new_inode(struct super_block *sb, struct inode *dir, umode_t mode, d
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);
cur_time = current_time(inode);
inode_set_mtime_to_ts(inode, cur_time);
inode_set_atime_to_ts(inode, cur_time);
inode_set_ctime_to_ts(inode, cur_time);
inode->i_rdev = rdev;
set_inode_ops(inode);
@@ -2068,7 +2073,7 @@ void scoutfs_inode_schedule_orphan_dwork(struct super_block *sb)
low = (opts.orphan_scan_delay_ms * 80) / 100;
high = (opts.orphan_scan_delay_ms * 120) / 100;
delay = msecs_to_jiffies(low + prandom_u32_max(high - low)) ?: 1;
delay = msecs_to_jiffies(low + get_random_u32_below(high - low)) ?: 1;
mod_delayed_work(system_wq, &inf->orphan_scan_dwork, delay);
}

View File

@@ -146,7 +146,7 @@ struct cached_item {
unsigned int val_len;
struct scoutfs_key key;
u64 seq;
char val[0];
char val[];
};
#define CACHED_ITEM_ALIGN 8
@@ -424,7 +424,7 @@ static struct cached_item *alloc_item(struct cached_page *pg,
item->seq = seq;
if (val_len)
memcpy(item->val, val, val_len);
memcpy(&item->val[0], val, val_len);
update_pg_max_seq(pg, item);
@@ -1999,7 +1999,7 @@ int scoutfs_item_update(struct super_block *sb, struct scoutfs_key *key,
if (val_len <= found->val_len) {
if (val_len)
memcpy(found->val, val, val_len);
memcpy(&found->val[0], val, val_len);
if (val_len < found->val_len)
pg->erased_bytes += item_val_bytes(found->val_len) -
item_val_bytes(val_len);
@@ -2316,7 +2316,7 @@ int scoutfs_item_write_dirty(struct super_block *sb)
lst->seq = item->seq;
lst->flags = item->deletion ? SCOUTFS_ITEM_FLAG_DELETION : 0;
lst->val_len = item->val_len;
memcpy(lst->val, item->val, item->val_len);
memcpy(&lst->val[0], item->val, item->val_len);
}
spin_lock(&cinf->dirty_lock);
@@ -2626,10 +2626,10 @@ int scoutfs_item_setup(struct super_block *sb)
for_each_possible_cpu(cpu)
init_pcpu_pages(cinf, cpu);
KC_INIT_SHRINKER_FUNCS(&cinf->shrinker, item_cache_count_objects,
item_cache_scan_objects);
KC_REGISTER_SHRINKER(&cinf->shrinker, "scoutfs-item:" SCSBF, SCSB_ARGS(sb));
KC_SETUP_SHRINKER(cinf->shrinker, cinf, 0, item_cache_count_objects,
item_cache_scan_objects, "scoutfs-item:" SCSBF, SCSB_ARGS(sb));
if (KC_SHRINKER_IS_NULL(cinf->shrinker))
return -ENOMEM;
#ifdef KC_CPU_NOTIFIER
cinf->notifier.notifier_call = item_cpu_callback;
register_hotcpu_notifier(&cinf->notifier);
@@ -2654,7 +2654,7 @@ void scoutfs_item_destroy(struct super_block *sb)
#ifdef KC_CPU_NOTIFIER
unregister_hotcpu_notifier(&cinf->notifier);
#endif
KC_UNREGISTER_SHRINKER(&cinf->shrinker);
KC_UNREGISTER_SHRINKER(cinf->shrinker);
for_each_possible_cpu(cpu)
drop_pcpu_pages(sb, cinf, cpu);

View File

@@ -147,3 +147,13 @@ unsigned long kc_list_lru_shrink_walk(struct list_lru *lru, struct shrink_contro
}
#endif
#ifndef KC_FS_INODE_C_TIME_ACCESSOR
struct timespec64 inode_set_ctime_current(struct inode *inode)
{
struct timespec64 now = current_time(inode);
inode_set_ctime(inode, now.tv_sec, now.tv_nsec);
return now;
}
#endif

View File

@@ -142,25 +142,54 @@ struct timespec64 kc_current_time(struct inode *inode);
#define kc_timespec timespec64
#endif
#ifndef KC_SHRINKER_SHRINK
#ifdef KC_SHRINKER_ALLOC
// el10+
#define KC_DEFINE_SHRINKER(name) struct shrinker name
#define KC_INIT_SHRINKER_FUNCS(name, countfn, scanfn) do { \
__typeof__(name) _shrink = (name); \
_shrink->count_objects = (countfn); \
_shrink->scan_objects = (scanfn); \
_shrink->seeks = DEFAULT_SEEKS; \
#define KC_DEFINE_SHRINKER(name) struct shrinker *(name)
#define KC_SHRINKER_CONTAINER_OF(ptr, type) ptr->private_data
#define KC_SETUP_SHRINKER(ptr, priv, flags, countfn, scanfn, fmt, args) \
do { \
ptr = shrinker_alloc(flags, fmt, args); \
if (ptr) { \
ptr->private_data = (priv); \
ptr->seeks = DEFAULT_SEEKS; \
ptr->count_objects = countfn; \
ptr->scan_objects = scanfn; \
shrinker_register(ptr); \
} \
} while (0)
#define KC_UNREGISTER_SHRINKER(ptr) shrinker_free(ptr)
#define KC_SHRINKER_FN(ptr) (ptr)
#define KC_SHRINKER_IS_NULL(ptr) (!(ptr))
#else /* KC_SHRINKER_ALLOC */
#ifndef KC_SHRINKER_SHRINK
// el9, el8
#define KC_DEFINE_SHRINKER(name) struct shrinker (name)
#define KC_SHRINKER_CONTAINER_OF(ptr, type) container_of(ptr, type, shrinker)
#ifdef KC_SHRINKER_NAME
#define KC_REGISTER_SHRINKER register_shrinker
#define KC_SETUP_SHRINKER(ptr, priv, flags, countfn, scanfn, fmt, args) \
do { \
(ptr).count_objects = (countfn); \
(ptr).scan_objects = (scanfn); \
(ptr).seeks = DEFAULT_SEEKS; \
register_shrinker(&(ptr), fmt, args); \
} while (0)
#else
#define KC_REGISTER_SHRINKER(ptr, fmt, ...) (register_shrinker(ptr))
#define KC_SETUP_SHRINKER(ptr, priv, flags, countfn, scanfn, fmt, args) \
do { \
(ptr).count_objects = (countfn); \
(ptr).scan_objects = (scanfn); \
(ptr).seeks = DEFAULT_SEEKS; \
register_shrinker(&(ptr)); \
} while (0)
#endif /* KC_SHRINKER_NAME */
#define KC_UNREGISTER_SHRINKER(ptr) (unregister_shrinker(ptr))
#define KC_SHRINKER_FN(ptr) (ptr)
#else
#define KC_UNREGISTER_SHRINKER(ptr) (unregister_shrinker(&(ptr)))
#define KC_SHRINKER_FN(ptr) (&ptr)
#else /* KC_SHRINKER_SHRINK */
// el7
#include <linux/shrinker.h>
#ifndef SHRINK_STOP
@@ -176,19 +205,21 @@ struct kc_shrinker_wrapper {
};
#define KC_DEFINE_SHRINKER(name) struct kc_shrinker_wrapper name;
#define KC_INIT_SHRINKER_FUNCS(name, countfn, scanfn) do { \
struct kc_shrinker_wrapper *_wrap = (name); \
_wrap->count_objects = (countfn); \
_wrap->scan_objects = (scanfn); \
_wrap->shrink.shrink = kc_shrink_wrapper_fn; \
_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, fmt, ...) (register_shrinker(ptr.shrink))
#define KC_UNREGISTER_SHRINKER(ptr) (unregister_shrinker(ptr.shrink))
#define KC_SHRINKER_FN(ptr) (ptr.shrink)
#define KC_SETUP_SHRINKER(ptr, priv, flags, countfn, scanfn, fmt, args) \
do { \
(ptr).count_objects = (countfn); \
(ptr).scan_objects = (scanfn); \
(ptr).shrink.shrink = kc_shrink_wrapper_fn; \
(ptr).shrink.seeks = DEFAULT_SEEKS; \
register_shrinker(&(ptr).shrink); \
} while (0)
#define KC_UNREGISTER_SHRINKER(ptr) (unregister_shrinker(&(ptr).shrink))
#define KC_SHRINKER_FN(ptr) (&(ptr).shrink)
#endif /* KC_SHRINKER_SHRINK */
#define KC_SHRINKER_IS_NULL(ptr) (0)
#endif /* KC_SHRINKER_ALLOC */
#ifdef KC_KERNEL_GETSOCKNAME_ADDRLEN
#include <linux/net.h>
@@ -279,6 +310,12 @@ typedef unsigned int blk_opf_t;
#endif
#endif /* KC_VFS_METHOD_MNT_IDMAP_ARG */
#ifdef KC_GENERIC_FILLATTR_REQUEST_MASK
#define KC_FILLATTR_REQUEST_MASK request_mask,
#else
#define KC_FILLATTR_REQUEST_MASK
#endif
#ifdef KC_BIO_ALLOC_DEV_OPF_ARGS
#define kc_bio_alloc bio_alloc
#else
@@ -452,6 +489,7 @@ unsigned long kc_list_lru_shrink_walk(struct list_lru *lru, struct shrink_contro
kc_list_lru_walk_cb_t isolate, void *cb_arg);
#else
#define kc_list_lru_shrink_walk list_lru_shrink_walk
#define kc_list_lru_walk list_lru_walk
#endif
#if defined(KC_LIST_LRU_WALK_CB_ITEM_LOCK)
@@ -489,4 +527,133 @@ static inline void stack_trace_print(unsigned long *entries, unsigned int nr_ent
}
#endif
#ifndef KC_HAVE_GET_RANDOM_U32_BELOW
#define get_random_u32_below prandom_u32_max
#endif
#ifndef KC_FS_INODE_C_TIME_ACCESSOR
struct timespec64 inode_set_ctime_current(struct inode *inode);
static inline struct timespec64 inode_set_ctime_to_ts(struct inode *inode,
struct timespec64 ts)
{
inode->i_ctime.tv_sec = ts.tv_sec;
inode->i_ctime.tv_nsec = ts.tv_nsec;
return ts;
}
static inline struct timespec64 inode_set_ctime(struct inode *inode,
time64_t sec, long nsec)
{
struct timespec64 ts = { .tv_sec = sec,
.tv_nsec = nsec };
return inode_set_ctime_to_ts(inode, ts);
}
static inline struct timespec64 inode_get_ctime(const struct inode *inode)
{
struct timespec64 ts = { .tv_sec = inode->i_ctime.tv_sec,
.tv_nsec = inode->i_ctime.tv_nsec };
return ts;
}
#endif
#ifndef KC_FS_INODE_AM_TIME_ACCESSOR
static inline struct timespec64 inode_get_mtime(const struct inode *inode)
{
struct timespec64 ts = { .tv_sec = inode->i_mtime.tv_sec,
.tv_nsec = inode->i_mtime.tv_nsec };
return ts;
}
static inline struct timespec64 inode_set_mtime_to_ts(struct inode *inode,
struct timespec64 ts)
{
inode->i_mtime.tv_sec = ts.tv_sec;
inode->i_mtime.tv_nsec = ts.tv_nsec;
return ts;
}
static inline struct timespec64 inode_set_mtime(struct inode *inode,
time64_t sec, long nsec)
{
struct timespec64 ts = { .tv_sec = sec,
.tv_nsec = nsec };
return inode_set_mtime_to_ts(inode, ts);
}
static inline struct timespec64 inode_set_atime_to_ts(struct inode *inode,
struct timespec64 ts)
{
inode->i_atime.tv_sec = ts.tv_sec;
inode->i_atime.tv_nsec = ts.tv_nsec;
return ts;
}
static inline struct timespec64 inode_set_atime(struct inode *inode,
time64_t sec, long nsec)
{
struct timespec64 ts = { .tv_sec = sec,
.tv_nsec = nsec };
return inode_set_atime_to_ts(inode, ts);
}
static inline time64_t inode_get_ctime_sec(const struct inode *inode)
{
return inode->i_ctime.tv_sec;
}
static inline long inode_get_ctime_nsec(const struct inode *inode)
{
return inode->i_ctime.tv_nsec;
}
static inline time64_t inode_get_mtime_sec(const struct inode *inode)
{
return inode->i_mtime.tv_sec;
}
static inline long inode_get_mtime_nsec(const struct inode *inode)
{
return inode->i_mtime.tv_nsec;
}
static inline time64_t inode_get_atime_sec(const struct inode *inode)
{
return inode->i_atime.tv_sec;
}
static inline long inode_get_atime_nsec(const struct inode *inode)
{
return inode->i_atime.tv_nsec;
}
#endif
#ifdef KC_HAVE_BD_INODE
#define KC_BDEV_INODE(b) (b)->bd_inode
#define KC_BDEV_MAPPING(b) (b)->bd_inode->i_mapping
#else
#define KC_BDEV_INODE(b) (b)->bd_mapping->host
#define KC_BDEV_MAPPING(b) (b)->bd_mapping
#endif
#ifdef KC_HAVE_ASSIGN_STR_PARMS
#define kc__assign_str(a, b) __assign_str(a, b)
#else
#define kc__assign_str(a, b) __assign_str(a)
#endif
#ifdef KC_KOBJECT_DEFAULT_GROUPS
#define KC_KOBJ_DEFAULT_OP default_groups
#define KC_KOBJ_DEFAULT(name) (name##_groups)
#define KC_KOBJ_DEFAULT_PICK(group, attrs) (group)
#else
#define KC_KOBJ_DEFAULT_OP default_attrs
#define KC_KOBJ_DEFAULT(name) (name##_attrs)
#define KC_KOBJ_DEFAULT_PICK(group, attrs) (attrs)
#endif
#ifdef KC_BLOCK_WRITE_BEGIN_FOLIO
#define KC_PAGE_OR_FOLIO(p, f) f
#else
#define KC_PAGE_OR_FOLIO(p, f) p
#endif
#endif

View File

@@ -752,13 +752,18 @@ static struct attribute *options_attrs[] = {
SCOUTFS_ATTR_PTR(quorum_slot_nr),
NULL,
};
#ifdef KC_KOBJECT_DEFAULT_GROUPS
ATTRIBUTE_GROUPS(options);
#endif
int scoutfs_options_setup(struct super_block *sb)
{
DECLARE_OPTIONS_INFO(sb, optinf);
int ret;
ret = scoutfs_sysfs_create_attrs(sb, &optinf->sysfs_attrs, options_attrs, "mount_options");
ret = scoutfs_sysfs_create_attrs(sb, &optinf->sysfs_attrs,
KC_KOBJ_DEFAULT_PICK(options_groups, options_attrs),
"mount_options");
if (ret < 0)
scoutfs_options_destroy(sb);
return ret;

View File

@@ -162,7 +162,7 @@ static void quorum_slot_sin(struct scoutfs_quorum_config *qconf, int i, struct s
static ktime_t election_timeout(void)
{
return ktime_add_ms(ktime_get(), SCOUTFS_QUORUM_ELECT_MIN_MS +
prandom_u32_max(SCOUTFS_QUORUM_ELECT_VAR_MS));
get_random_u32_below(SCOUTFS_QUORUM_ELECT_VAR_MS));
}
static ktime_t heartbeat_interval(void)
@@ -1192,6 +1192,9 @@ static struct attribute *quorum_attrs[] = {
SCOUTFS_ATTR_PTR(is_leader),
NULL,
};
#ifdef KC_KOBJECT_DEFAULT_GROUPS
ATTRIBUTE_GROUPS(quorum);
#endif
static inline bool valid_ipv4_unicast(__be32 addr)
{
@@ -1352,7 +1355,7 @@ int scoutfs_quorum_setup(struct super_block *sb)
if (ret < 0)
goto out;
ret = scoutfs_sysfs_create_attrs(sb, &qinf->ssa, quorum_attrs,
ret = scoutfs_sysfs_create_attrs(sb, &qinf->ssa, KC_KOBJ_DEFAULT(quorum),
"quorum");
if (ret < 0)
goto out;

View File

@@ -204,7 +204,7 @@ static struct squota_check *lookup_random_check(struct rhashtable *rht)
tbl = rht_dereference_rcu(rht->tbl, rht);
do {
for (s = 0, i = prandom_u32_max(tbl->size);
for (s = 0, i = get_random_u32_below(tbl->size);
s < tbl->size;
s++, i = (i + 1) % tbl->size) {
rht_for_each_entry_rcu(chk, pos, tbl, i, head) {
@@ -269,7 +269,7 @@ static void shrink_all_cached_checks(struct squota_info *qtinf)
{
struct shrink_control sc = { .nr_to_scan = LONG_MAX, };
scan_cached_checks(KC_SHRINKER_FN(&qtinf->shrinker), &sc);
scan_cached_checks(KC_SHRINKER_FN(qtinf->shrinker), &sc);
}
static u8 ns_is_attr(u8 ns)
@@ -1225,8 +1225,12 @@ int scoutfs_quota_setup(struct super_block *sb)
spin_lock_init(&qtinf->lock);
init_waitqueue_head(&qtinf->waitq);
KC_INIT_SHRINKER_FUNCS(&qtinf->shrinker, count_cached_checks, scan_cached_checks);
KC_REGISTER_SHRINKER(&qtinf->shrinker, "scoutfs-quota:" SCSBF, SCSB_ARGS(sb));
KC_SETUP_SHRINKER(qtinf->shrinker, qtinf, 0, count_cached_checks,
scan_cached_checks, "scoutfs-quota:" SCSBF, SCSB_ARGS(sb));
if (KC_SHRINKER_IS_NULL(qtinf->shrinker)) {
ret = -ENOMEM;
goto out;
}
sbi->squota_info = qtinf;
@@ -1250,7 +1254,7 @@ void scoutfs_quota_destroy(struct super_block *sb)
if (qtinf) {
debugfs_remove(qtinf->drop_dentry);
KC_UNREGISTER_SHRINKER(&qtinf->shrinker);
KC_UNREGISTER_SHRINKER(qtinf->shrinker);
spin_lock(&qtinf->lock);
rs = rcu_dereference_protected(qtinf->ruleset, lockdep_is_held(&qtinf->lock));

View File

@@ -102,7 +102,7 @@ TRACE_EVENT(scoutfs_setattr,
SCSB_TRACE_ASSIGN(dentry->d_inode->i_sb);
__entry->ino = scoutfs_ino(dentry->d_inode);
__entry->d_len = dentry->d_name.len;
__assign_str(d_name, dentry->d_name.name);
kc__assign_str(d_name, dentry->d_name.name);
__entry->ia_valid = attr->ia_valid;
__entry->size_change = !!(attr->ia_valid & ATTR_SIZE);
__entry->ia_size = attr->ia_size;
@@ -1638,9 +1638,9 @@ TRACE_EVENT(scoutfs_rename,
TP_fast_assign(
SCSB_TRACE_ASSIGN(sb);
__entry->old_dir_ino = scoutfs_ino(old_dir);
__assign_str(old_name, old_dentry->d_name.name)
kc__assign_str(old_name, old_dentry->d_name.name);
__entry->new_dir_ino = scoutfs_ino(new_dir);
__assign_str(new_name, new_dentry->d_name.name)
kc__assign_str(new_name, new_dentry->d_name.name);
__entry->new_inode_ino = new_dentry->d_inode ?
scoutfs_ino(new_dentry->d_inode) : 0;
),
@@ -1670,7 +1670,7 @@ TRACE_EVENT(scoutfs_d_revalidate,
TP_fast_assign(
SCSB_TRACE_ASSIGN(sb);
__entry->dentry = dentry;
__assign_str(name, dentry->d_name.name)
kc__assign_str(name, dentry->d_name.name);
__entry->ino = dentry->d_inode ? scoutfs_ino(dentry->d_inode) : 0;
__entry->dir_ino = dir_ino;
__entry->flags = flags;
@@ -1705,7 +1705,7 @@ TRACE_EVENT(scoutfs_validate_dentry,
SCSB_TRACE_ASSIGN(sb);
__entry->dentry = dentry;
__entry->dir_ino = dir_ino;
__assign_str(name, dentry->d_name.name)
kc__assign_str(name, dentry->d_name.name);
__entry->dentry_ino = dentry_ino;
__entry->dent_ino = dent_ino;
__entry->fsdata_gen = (unsigned long long)dentry->d_fsdata;
@@ -1827,7 +1827,7 @@ TRACE_EVENT(scoutfs_get_name,
SCSB_TRACE_ASSIGN(sb);
__entry->parent_ino = scoutfs_ino(parent);
__entry->child_ino = scoutfs_ino(child);
__assign_str(name, name);
kc__assign_str(name, name);
),
TP_printk(SCSBF" parent %llu child %llu name: %s",

View File

@@ -20,7 +20,6 @@
#include <net/sock.h>
#include <net/tcp.h>
#include <linux/log2.h>
#include <asm/unaligned.h>
#include "format.h"
#include "counters.h"
@@ -3372,7 +3371,7 @@ out:
static u64 device_blocks(struct block_device *bdev, int shift)
{
return i_size_read(bdev->bd_inode) >> shift;
return i_size_read(KC_BDEV_INODE(bdev)) >> shift;
}
static int server_resize_devices(struct super_block *sb, struct scoutfs_net_connection *conn,

View File

@@ -18,7 +18,11 @@
#include <linux/pagemap.h>
#include <linux/vmalloc.h>
#include <linux/sort.h>
#ifdef KC_HAVE__LINUX_UNALIGNED_H
#include <linux/unaligned.h>
#else
#include <asm/unaligned.h>
#endif
#include "super.h"
#include "format.h"
@@ -2346,6 +2350,9 @@ static struct attribute *srch_attrs[] = {
SCOUTFS_ATTR_PTR(compact_delay_ms),
NULL,
};
#ifdef KC_KOBJECT_DEFAULT_GROUPS
ATTRIBUTE_GROUPS(srch);
#endif
void scoutfs_srch_destroy(struct super_block *sb)
{
@@ -2387,7 +2394,8 @@ int scoutfs_srch_setup(struct super_block *sb)
sbi->srch_info = srinf;
ret = scoutfs_sysfs_create_attrs(sb, &srinf->ssa, srch_attrs, "srch");
ret = scoutfs_sysfs_create_attrs(sb, &srinf->ssa, KC_KOBJ_DEFAULT(srch),
"srch");
if (ret < 0)
goto out;

View File

@@ -283,7 +283,7 @@ int scoutfs_write_super(struct super_block *sb,
static bool small_bdev(struct super_block *sb, char *which, u64 blocks,
struct block_device *bdev, int shift)
{
u64 size = (u64)i_size_read(bdev->bd_inode);
u64 size = (u64)i_size_read(KC_BDEV_INODE(bdev));
u64 count = size >> shift;
if (blocks > count) {
@@ -508,7 +508,7 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_time_gran = 1;
/* btree blocks use long lived bh->b_data refs */
mapping_set_gfp_mask(sb->s_bdev->bd_inode->i_mapping, GFP_NOFS);
mapping_set_gfp_mask(KC_BDEV_MAPPING(sb->s_bdev), GFP_NOFS);
sbi = kzalloc(sizeof(struct scoutfs_sb_info), GFP_KERNEL);
sb->s_fs_info = sbi;
@@ -552,6 +552,7 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent)
}
sbi->meta_bdev_file = meta_bdev_file;
sbi->meta_bdev = file_bdev(meta_bdev_file);
#else
#ifdef KC_BLKDEV_PUT_HOLDER_ARG
meta_bdev = blkdev_get_by_path(opts.metadev_path, SCOUTFS_META_BDEV_MODE, sb, NULL);
@@ -567,7 +568,11 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent)
sbi->meta_bdev = meta_bdev;
#endif
#ifdef KC_BLKDEV_SET_BLOCKSIZE_FILE
ret = set_blocksize(sbi->meta_bdev_file, SCOUTFS_BLOCK_SM_SIZE);
#else
ret = set_blocksize(sbi->meta_bdev, SCOUTFS_BLOCK_SM_SIZE);
#endif
if (ret != 0) {
scoutfs_err(sb, "failed to set metadev blocksize, returned %d",
ret);

View File

@@ -103,12 +103,11 @@ static ssize_t attr_funcs_show(struct kobject *kobj, struct attribute *attr,
}; \
\
static struct kobj_type _name##_ktype = { \
.default_attrs = _name##_attrs, \
.KC_KOBJ_DEFAULT_OP = KC_KOBJ_DEFAULT(_name), \
.sysfs_ops = &_name##_sysfs_ops, \
.release = _name##_release, \
};
static struct attribute *sb_id_attrs[] = {
&data_device_maj_min_attr_funcs.attr,
&format_version_attr_funcs.attr,
@@ -116,6 +115,9 @@ static struct attribute *sb_id_attrs[] = {
&rid_attr_funcs.attr,
NULL,
};
#ifdef KC_KOBJECT_DEFAULT_GROUPS
ATTRIBUTE_GROUPS(sb_id);
#endif
KTYPE(sb_id);
struct kobject *scoutfs_sysfs_sb_dir(struct super_block *sb)
@@ -155,7 +157,12 @@ void scoutfs_sysfs_init_attrs(struct super_block *sb,
int scoutfs_sysfs_create_attrs_parent(struct super_block *sb,
struct kobject *parent,
struct scoutfs_sysfs_attrs *ssa,
struct attribute **attrs, char *fmt, ...)
#ifdef KC_KOBJECT_DEFAULT_GROUPS
const struct attribute_group **groups,
#else
struct attribute **attrs,
#endif
char *fmt, ...)
{
va_list args;
size_t name_len;
@@ -168,7 +175,11 @@ int scoutfs_sysfs_create_attrs_parent(struct super_block *sb,
ssa->sb = sb;
init_completion(&ssa->comp);
#ifdef KC_KOBJECT_DEFAULT_GROUPS
ssa->ktype.default_groups = groups;
#else
ssa->ktype.default_attrs = attrs;
#endif
ssa->ktype.sysfs_ops = &kobj_sysfs_ops;
ssa->ktype.release = scoutfs_sysfs_release;

View File

@@ -39,10 +39,15 @@ void scoutfs_sysfs_init_attrs(struct super_block *sb,
int scoutfs_sysfs_create_attrs_parent(struct super_block *sb,
struct kobject *parent,
struct scoutfs_sysfs_attrs *ssa,
struct attribute **attrs, char *fmt, ...);
#define scoutfs_sysfs_create_attrs(sb, ssa, attrs, fmt, args...) \
#ifdef KC_KOBJECT_DEFAULT_GROUPS
const struct attribute_group **groups,
#else
struct attribute **attrs,
#endif
char *fmt, ...);
#define scoutfs_sysfs_create_attrs(sb, ssa, group_or_attrs, fmt, args...) \
scoutfs_sysfs_create_attrs_parent(sb, scoutfs_sysfs_sb_dir(sb), \
ssa, attrs, fmt, ##args)
ssa, group_or_attrs, fmt, ##args)
void scoutfs_sysfs_destroy_attrs(struct super_block *sb,
struct scoutfs_sysfs_attrs *ssa);

View File

@@ -52,6 +52,15 @@ static struct volopt_nr_name {
/* initialized by setup, pointer array is null terminated */
static struct kobj_attribute volopt_attrs[ARRAY_SIZE(volopt_table)];
static struct attribute *volopt_attr_ptrs[ARRAY_SIZE(volopt_table) + 1];
#ifdef KC_KOBJECT_DEFAULT_GROUPS
static const struct attribute_group volopt_group = {
.attrs = volopt_attr_ptrs,
};
static const struct attribute_group *volopt_groups[] = {
&volopt_group,
NULL,
};
#endif
static void get_opt_data(struct kobj_attribute *attr, struct scoutfs_volume_options *volopt,
u64 *bit, __le64 **opt)
@@ -164,7 +173,9 @@ int scoutfs_volopt_setup(struct super_block *sb)
BUILD_BUG_ON(ARRAY_SIZE(volopt_table) != ARRAY_SIZE(volopt_attr_ptrs) - 1);
volopt_attr_ptrs[i] = NULL;
ret = scoutfs_sysfs_create_attrs(sb, &vinf->ssa, volopt_attr_ptrs, "volume_options");
ret = scoutfs_sysfs_create_attrs(sb, &vinf->ssa,
KC_KOBJ_DEFAULT_PICK(volopt_groups, volopt_attr_ptrs),
"volume_options");
if (ret < 0)
goto out;

View File

@@ -171,7 +171,7 @@ struct wkic_item {
u64 seq;
unsigned int val_len;
u8 flags;
u8 val[0] __aligned(ARCH_KMALLOC_MINALIGN); /* totls have native structs */
u8 val[] __aligned(ARCH_KMALLOC_MINALIGN); /* totls have native structs */
};
static struct wkic_item *witem_container(struct rb_node *node)
@@ -763,7 +763,7 @@ static void fill_page_items(struct super_block *sb, struct wkic_page *wpage, str
pg_item->val_len = witem->val_len;
pg_item->flags = witem->flags;
if (witem->val_len)
memcpy(pg_item->val, witem->val, witem->val_len);
memcpy(&pg_item->val[0], witem->val, witem->val_len);
/* always inserting greatest item into page */
rb_link_node(&pg_item->node, parent, node);
@@ -1112,8 +1112,13 @@ 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, "scoutfs-weak_item:" SCSBF, SCSB_ARGS(sb));
KC_SETUP_SHRINKER(winf->shrinker, winf, 0, wkic_shrink_count,
wkic_shrink_scan, "scoutfs-weak_item:" SCSBF, SCSB_ARGS(sb));
if (KC_SHRINKER_IS_NULL(winf->shrinker)) {
debugfs_remove(winf->drop_dentry);
kfree(winf);
return -ENOMEM;
}
sbi->wkic_info = winf;
return 0;
@@ -1141,7 +1146,7 @@ void scoutfs_wkic_destroy(struct super_block *sb)
if (winf) {
debugfs_remove(winf->drop_dentry);
KC_UNREGISTER_SHRINKER(&winf->shrinker);
KC_UNREGISTER_SHRINKER(winf->shrinker);
/* trees are in sync so tearing down one frees all pages */
rbtree_postorder_for_each_entry_safe(wpage, tmp, &winf->wpage_roots[0], nodes[0]) {

View File

@@ -907,7 +907,7 @@ int scoutfs_xattr_set_locked(struct inode *inode, const char *name, size_t name_
/* XXX do these want i_mutex or anything? */
inode_inc_iversion(inode);
inode->i_ctime = current_time(inode);
inode_set_ctime_to_ts(inode, current_time(inode));
ret = 0;
out:

View File

@@ -3,7 +3,8 @@
t_filter_fs()
{
sed -e 's@mnt/test\.[0-9]*@mnt/test@g' \
-e 's@Device: [a-fA-F0-9]*h/[0-9]*d@Device: 0h/0d@g'
-e 's@Device: [a-fA-F0-9]*h/[0-9]*d@Device: 0h/0d@g' \
-e 's@Device: [0-9]*,[0-9]*@Device: 0h/0d@g'
}
#
@@ -173,6 +174,6 @@ t_filter_dmesg()
# creating block devices may trigger this
re="$re|block device autoloading is deprecated and will be removed."
egrep -v "($re)" | \
grep -v -E "($re)" | \
ignore_harmless_unwind_kasan_stack_oob
}

View File

@@ -47,7 +47,7 @@ four
--- dir within dir
--- overwrite file
--- can't overwrite non-empty dir
mv: cannot move '/mnt/test/test/basic-posix-consistency/dir/c/clobber' to '/mnt/test/test/basic-posix-consistency/dir/a/dir': Directory not empty
mv: cannot overwrite '/mnt/test/test/basic-posix-consistency/dir/a/dir': Directory not empty
--- can overwrite empty dir
--- can rename into root
== path resoluion

View File

@@ -301,7 +301,7 @@ fi
# include everything by default
test -z "$T_INCLUDE" && T_INCLUDE="-e '.*'"
# (quickly) exclude nothing by default
test -z "$T_EXCLUDE" && T_EXCLUDE="-e '\Zx'"
test -z "$T_EXCLUDE" && T_EXCLUDE="-e '^$'"
# eval to strip re ticks but not expand
tests=$(grep -v "^#" $T_SEQUENCE |

View File

@@ -138,7 +138,9 @@ echo "--- can't overwrite non-empty dir"
mkdir "$T_D0/dir/a/dir"
touch "$T_D0/dir/a/dir/nope"
mkdir "$T_D1/dir/c/clobber"
mv -T "$T_D1/dir/c/clobber" "$T_D1/dir/a/dir" 2>&1 | t_filter_fs
mv -T "$T_D1/dir/c/clobber" "$T_D1/dir/a/dir" 2>&1 | \
sed "s@mv: cannot move '.*' to '\(.*\)': Directory not empty@mv: cannot overwrite '\1': Directory not empty@g" | \
t_filter_fs
find "$T_D0/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.0"
find "$T_D1/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"

View File

@@ -11,8 +11,8 @@
# format version.
#
# not supported on el8 or higher
if [ $(source /etc/os-release ; echo ${VERSION_ID:0:1}) -gt 7 ]; then
# not supported on el8, or higher versions.
if [ $(source /etc/os-release ; echo ${VERSION_ID} | cut -d. -f1) -gt 7 ]; then
t_skip_permitted "Unsupported OS version"
fi

View File

@@ -71,7 +71,7 @@ else
m64=""
fi
sparse $m64 $include $search/include "$@" 2>&1 | egrep -v "($RE)" | tee .sparse.output
sparse $m64 $include $search/include "$@" 2>&1 | grep -v -E "($RE)" | tee .sparse.output
rm -f $defines