Merge tag 'vfs-6.18-rc7.fixes' of gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs

Pull vfs fixes from Christian Brauner:

 - Fix unitialized variable in statmount_string()

 - Fix hostfs mounting when passing host root during boot

 - Fix dynamic lookup to fail on cell lookup failure

 - Fix missing file type when reading bfs inodes from disk

 - Enforce checking of sb_min_blocksize() calls and update all callers
   accordingly

 - Restore write access before closing files opened by open_exec() in
   binfmt_misc

 - Always freeze efivarfs during suspend/hibernate cycles

 - Fix statmount()'s and listmount()'s grab_requested_mnt_ns() helper to
   actually allow mount namespace file descriptor in addition to mount
   namespace ids

 - Fix tmpfs remount when noswap is specified

 - Switch Landlock to iput_not_last() to remove false-positives from
   might_sleep() annotations in iput()

 - Remove dead node_to_mnt_ns() code

 - Ensure that per-queue kobjects are successfully created

* tag 'vfs-6.18-rc7.fixes' of gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs:
  landlock: fix splats from iput() after it started calling might_sleep()
  fs: add iput_not_last()
  shmem: fix tmpfs reconfiguration (remount) when noswap is set
  fs/namespace: correctly handle errors returned by grab_requested_mnt_ns
  power: always freeze efivarfs
  binfmt_misc: restore write access before closing files opened by open_exec()
  block: add __must_check attribute to sb_min_blocksize()
  virtio-fs: fix incorrect check for fsvq->kobj
  xfs: check the return value of sb_min_blocksize() in xfs_fs_fill_super
  isofs: check the return value of sb_min_blocksize() in isofs_fill_super
  exfat: check return value of sb_min_blocksize in exfat_read_boot_sector
  vfat: fix missing sb_min_blocksize() return value checks
  mnt: Remove dead code which might prevent from building
  bfs: Reconstruct file type when loading from disk
  afs: Fix dynamic lookup to fail on cell lookup failure
  hostfs: Fix only passing host root in boot stage with new mount
  fs: Fix uninitialized 'offp' in statmount_string()
This commit is contained in:
Linus Torvalds
2025-11-17 09:11:27 -08:00
26 changed files with 206 additions and 91 deletions

View File

@@ -231,7 +231,7 @@ int sb_set_blocksize(struct super_block *sb, int size)
EXPORT_SYMBOL(sb_set_blocksize);
int sb_min_blocksize(struct super_block *sb, int size)
int __must_check sb_min_blocksize(struct super_block *sb, int size)
{
int minsize = bdev_logical_block_size(sb->s_bdev);
if (size < minsize)

View File

@@ -229,7 +229,7 @@ error:
* @name: The name of the cell.
* @namesz: The strlen of the cell name.
* @vllist: A colon/comma separated list of numeric IP addresses or NULL.
* @excl: T if an error should be given if the cell name already exists.
* @reason: The reason we're doing the lookup
* @trace: The reason to be logged if the lookup is successful.
*
* Look up a cell record by name and query the DNS for VL server addresses if
@@ -239,7 +239,8 @@ error:
*/
struct afs_cell *afs_lookup_cell(struct afs_net *net,
const char *name, unsigned int namesz,
const char *vllist, bool excl,
const char *vllist,
enum afs_lookup_cell_for reason,
enum afs_cell_trace trace)
{
struct afs_cell *cell, *candidate, *cursor;
@@ -247,12 +248,18 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
enum afs_cell_state state;
int ret, n;
_enter("%s,%s", name, vllist);
_enter("%s,%s,%u", name, vllist, reason);
if (!excl) {
if (reason != AFS_LOOKUP_CELL_PRELOAD) {
cell = afs_find_cell(net, name, namesz, trace);
if (!IS_ERR(cell))
if (!IS_ERR(cell)) {
if (reason == AFS_LOOKUP_CELL_DYNROOT)
goto no_wait;
if (cell->state == AFS_CELL_SETTING_UP ||
cell->state == AFS_CELL_UNLOOKED)
goto lookup_cell;
goto wait_for_cell;
}
}
/* Assume we're probably going to create a cell and preallocate and
@@ -298,26 +305,69 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
rb_insert_color(&cell->net_node, &net->cells);
up_write(&net->cells_lock);
afs_queue_cell(cell, afs_cell_trace_queue_new);
lookup_cell:
if (reason != AFS_LOOKUP_CELL_PRELOAD &&
reason != AFS_LOOKUP_CELL_ROOTCELL) {
set_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags);
afs_queue_cell(cell, afs_cell_trace_queue_new);
}
wait_for_cell:
_debug("wait_for_cell");
state = smp_load_acquire(&cell->state); /* vs error */
if (state != AFS_CELL_ACTIVE &&
state != AFS_CELL_DEAD) {
switch (state) {
case AFS_CELL_ACTIVE:
case AFS_CELL_DEAD:
break;
case AFS_CELL_UNLOOKED:
default:
if (reason == AFS_LOOKUP_CELL_PRELOAD ||
reason == AFS_LOOKUP_CELL_ROOTCELL)
break;
_debug("wait_for_cell");
afs_see_cell(cell, afs_cell_trace_wait);
wait_var_event(&cell->state,
({
state = smp_load_acquire(&cell->state); /* vs error */
state == AFS_CELL_ACTIVE || state == AFS_CELL_DEAD;
}));
_debug("waited_for_cell %d %d", cell->state, cell->error);
}
no_wait:
/* Check the state obtained from the wait check. */
state = smp_load_acquire(&cell->state); /* vs error */
if (state == AFS_CELL_DEAD) {
ret = cell->error;
goto error;
}
if (state == AFS_CELL_ACTIVE) {
switch (cell->dns_status) {
case DNS_LOOKUP_NOT_DONE:
if (cell->dns_source == DNS_RECORD_FROM_CONFIG) {
ret = 0;
break;
}
fallthrough;
default:
ret = -EIO;
goto error;
case DNS_LOOKUP_GOOD:
case DNS_LOOKUP_GOOD_WITH_BAD:
ret = 0;
break;
case DNS_LOOKUP_GOT_NOT_FOUND:
ret = -ENOENT;
goto error;
case DNS_LOOKUP_BAD:
ret = -EREMOTEIO;
goto error;
case DNS_LOOKUP_GOT_LOCAL_FAILURE:
case DNS_LOOKUP_GOT_TEMP_FAILURE:
case DNS_LOOKUP_GOT_NS_FAILURE:
ret = -EDESTADDRREQ;
goto error;
}
}
_leave(" = %p [cell]", cell);
return cell;
@@ -325,7 +375,7 @@ wait_for_cell:
cell_already_exists:
_debug("cell exists");
cell = cursor;
if (excl) {
if (reason == AFS_LOOKUP_CELL_PRELOAD) {
ret = -EEXIST;
} else {
afs_use_cell(cursor, trace);
@@ -384,7 +434,8 @@ int afs_cell_init(struct afs_net *net, const char *rootcell)
return -EINVAL;
/* allocate a cell record for the root/workstation cell */
new_root = afs_lookup_cell(net, rootcell, len, vllist, false,
new_root = afs_lookup_cell(net, rootcell, len, vllist,
AFS_LOOKUP_CELL_ROOTCELL,
afs_cell_trace_use_lookup_ws);
if (IS_ERR(new_root)) {
_leave(" = %ld", PTR_ERR(new_root));
@@ -777,6 +828,7 @@ static bool afs_manage_cell(struct afs_cell *cell)
switch (cell->state) {
case AFS_CELL_SETTING_UP:
goto set_up_cell;
case AFS_CELL_UNLOOKED:
case AFS_CELL_ACTIVE:
goto cell_is_active;
case AFS_CELL_REMOVING:
@@ -797,7 +849,7 @@ set_up_cell:
goto remove_cell;
}
afs_set_cell_state(cell, AFS_CELL_ACTIVE);
afs_set_cell_state(cell, AFS_CELL_UNLOOKED);
cell_is_active:
if (afs_has_cell_expired(cell, &next_manage))
@@ -807,6 +859,8 @@ cell_is_active:
ret = afs_update_cell(cell);
if (ret < 0)
cell->error = ret;
if (cell->state == AFS_CELL_UNLOOKED)
afs_set_cell_state(cell, AFS_CELL_ACTIVE);
}
if (next_manage < TIME64_MAX && cell->net->live) {

View File

@@ -108,7 +108,8 @@ static struct dentry *afs_dynroot_lookup_cell(struct inode *dir, struct dentry *
dotted = true;
}
cell = afs_lookup_cell(net, name, len, NULL, false,
cell = afs_lookup_cell(net, name, len, NULL,
AFS_LOOKUP_CELL_DYNROOT,
afs_cell_trace_use_lookup_dynroot);
if (IS_ERR(cell)) {
ret = PTR_ERR(cell);

View File

@@ -343,6 +343,7 @@ extern const char afs_init_sysname[];
enum afs_cell_state {
AFS_CELL_SETTING_UP,
AFS_CELL_UNLOOKED,
AFS_CELL_ACTIVE,
AFS_CELL_REMOVING,
AFS_CELL_DEAD,
@@ -1049,9 +1050,18 @@ static inline bool afs_cb_is_broken(unsigned int cb_break,
extern int afs_cell_init(struct afs_net *, const char *);
extern struct afs_cell *afs_find_cell(struct afs_net *, const char *, unsigned,
enum afs_cell_trace);
enum afs_lookup_cell_for {
AFS_LOOKUP_CELL_DYNROOT,
AFS_LOOKUP_CELL_MOUNTPOINT,
AFS_LOOKUP_CELL_DIRECT_MOUNT,
AFS_LOOKUP_CELL_PRELOAD,
AFS_LOOKUP_CELL_ROOTCELL,
AFS_LOOKUP_CELL_ALIAS_CHECK,
};
struct afs_cell *afs_lookup_cell(struct afs_net *net,
const char *name, unsigned int namesz,
const char *vllist, bool excl,
const char *vllist,
enum afs_lookup_cell_for reason,
enum afs_cell_trace trace);
extern struct afs_cell *afs_use_cell(struct afs_cell *, enum afs_cell_trace);
void afs_unuse_cell(struct afs_cell *cell, enum afs_cell_trace reason);

View File

@@ -107,7 +107,8 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
if (size > AFS_MAXCELLNAME)
return -ENAMETOOLONG;
cell = afs_lookup_cell(ctx->net, p, size, NULL, false,
cell = afs_lookup_cell(ctx->net, p, size, NULL,
AFS_LOOKUP_CELL_MOUNTPOINT,
afs_cell_trace_use_lookup_mntpt);
if (IS_ERR(cell)) {
pr_err("kAFS: unable to lookup cell '%pd'\n", mntpt);

View File

@@ -122,7 +122,8 @@ static int afs_proc_cells_write(struct file *file, char *buf, size_t size)
if (strcmp(buf, "add") == 0) {
struct afs_cell *cell;
cell = afs_lookup_cell(net, name, strlen(name), args, true,
cell = afs_lookup_cell(net, name, strlen(name), args,
AFS_LOOKUP_CELL_PRELOAD,
afs_cell_trace_use_lookup_add);
if (IS_ERR(cell)) {
ret = PTR_ERR(cell);

View File

@@ -290,7 +290,7 @@ static int afs_parse_source(struct fs_context *fc, struct fs_parameter *param)
/* lookup the cell record */
if (cellname) {
cell = afs_lookup_cell(ctx->net, cellname, cellnamesz,
NULL, false,
NULL, AFS_LOOKUP_CELL_DIRECT_MOUNT,
afs_cell_trace_use_lookup_mount);
if (IS_ERR(cell)) {
pr_err("kAFS: unable to lookup cell '%*.*s'\n",

View File

@@ -269,7 +269,8 @@ static int yfs_check_canonical_cell_name(struct afs_cell *cell, struct key *key)
if (!name_len || name_len > AFS_MAXCELLNAME)
master = ERR_PTR(-EOPNOTSUPP);
else
master = afs_lookup_cell(cell->net, cell_name, name_len, NULL, false,
master = afs_lookup_cell(cell->net, cell_name, name_len, NULL,
AFS_LOOKUP_CELL_ALIAS_CHECK,
afs_cell_trace_use_lookup_canonical);
kfree(cell_name);
if (IS_ERR(master))

View File

@@ -61,7 +61,19 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
di = (struct bfs_inode *)bh->b_data + off;
inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode);
/*
* https://martin.hinner.info/fs/bfs/bfs-structure.html explains that
* BFS in SCO UnixWare environment used only lower 9 bits of di->i_mode
* value. This means that, although bfs_write_inode() saves whole
* inode->i_mode bits (which include S_IFMT bits and S_IS{UID,GID,VTX}
* bits), middle 7 bits of di->i_mode value can be garbage when these
* bits were not saved by bfs_write_inode().
* Since we can't tell whether middle 7 bits are garbage, use only
* lower 12 bits (i.e. tolerate S_IS{UID,GID,VTX} bits possibly being
* garbage) and reconstruct S_IFMT bits for Linux environment from
* di->i_vtype value.
*/
inode->i_mode = 0x00000FFF & le32_to_cpu(di->i_mode);
if (le32_to_cpu(di->i_vtype) == BFS_VDIR) {
inode->i_mode |= S_IFDIR;
inode->i_op = &bfs_dir_inops;
@@ -71,6 +83,11 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
inode->i_op = &bfs_file_inops;
inode->i_fop = &bfs_file_operations;
inode->i_mapping->a_ops = &bfs_aops;
} else {
brelse(bh);
printf("Unknown vtype=%u %s:%08lx\n",
le32_to_cpu(di->i_vtype), inode->i_sb->s_id, ino);
goto error;
}
BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock);

View File

@@ -837,8 +837,10 @@ out:
inode_unlock(d_inode(root));
if (err) {
if (f)
if (f) {
exe_file_allow_write_access(f);
filp_close(f, NULL);
}
kfree(e);
return err;
}

View File

@@ -533,6 +533,7 @@ static struct file_system_type efivarfs_type = {
.init_fs_context = efivarfs_init_fs_context,
.kill_sb = efivarfs_kill_sb,
.parameters = efivarfs_parameters,
.fs_flags = FS_POWER_FREEZE,
};
static __init int efivarfs_init(void)

View File

@@ -433,7 +433,10 @@ static int exfat_read_boot_sector(struct super_block *sb)
struct exfat_sb_info *sbi = EXFAT_SB(sb);
/* set block size to read super block */
sb_min_blocksize(sb, 512);
if (!sb_min_blocksize(sb, 512)) {
exfat_err(sb, "unable to set blocksize");
return -EINVAL;
}
/* read boot sector */
sbi->boot_bh = sb_bread(sb, 0);

View File

@@ -1595,8 +1595,12 @@ int fat_fill_super(struct super_block *sb, struct fs_context *fc,
setup(sb); /* flavour-specific stuff that needs options */
error = -EINVAL;
if (!sb_min_blocksize(sb, 512)) {
fat_msg(sb, KERN_ERR, "unable to set blocksize");
goto out_fail;
}
error = -EIO;
sb_min_blocksize(sb, 512);
bh = sb_bread(sb, 0);
if (bh == NULL) {
fat_msg(sb, KERN_ERR, "unable to read boot sector");

View File

@@ -373,7 +373,7 @@ static int virtio_fs_add_queues_sysfs(struct virtio_fs *fs)
sprintf(buff, "%d", i);
fsvq->kobj = kobject_create_and_add(buff, fs->mqs_kobj);
if (!fs->mqs_kobj) {
if (!fsvq->kobj) {
ret = -ENOMEM;
goto out_del;
}

View File

@@ -979,7 +979,7 @@ static int hostfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
struct hostfs_fs_info *fsi = fc->s_fs_info;
struct fs_parse_result result;
char *host_root;
char *host_root, *tmp_root;
int opt;
opt = fs_parse(fc, hostfs_param_specs, param, &result);
@@ -990,11 +990,13 @@ static int hostfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
case Opt_hostfs:
host_root = param->string;
if (!*host_root)
host_root = "";
fsi->host_root_path =
kasprintf(GFP_KERNEL, "%s/%s", root_ino, host_root);
if (fsi->host_root_path == NULL)
break;
tmp_root = kasprintf(GFP_KERNEL, "%s%s",
fsi->host_root_path, host_root);
if (!tmp_root)
return -ENOMEM;
kfree(fsi->host_root_path);
fsi->host_root_path = tmp_root;
break;
}
@@ -1004,17 +1006,17 @@ static int hostfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
static int hostfs_parse_monolithic(struct fs_context *fc, void *data)
{
struct hostfs_fs_info *fsi = fc->s_fs_info;
char *host_root = (char *)data;
char *tmp_root, *host_root = (char *)data;
/* NULL is printed as '(null)' by printf(): avoid that. */
if (host_root == NULL)
host_root = "";
return 0;
fsi->host_root_path =
kasprintf(GFP_KERNEL, "%s/%s", root_ino, host_root);
if (fsi->host_root_path == NULL)
tmp_root = kasprintf(GFP_KERNEL, "%s%s", fsi->host_root_path, host_root);
if (!tmp_root)
return -ENOMEM;
kfree(fsi->host_root_path);
fsi->host_root_path = tmp_root;
return 0;
}
@@ -1049,6 +1051,11 @@ static int hostfs_init_fs_context(struct fs_context *fc)
if (!fsi)
return -ENOMEM;
fsi->host_root_path = kasprintf(GFP_KERNEL, "%s/", root_ino);
if (!fsi->host_root_path) {
kfree(fsi);
return -ENOMEM;
}
fc->s_fs_info = fsi;
fc->ops = &hostfs_context_ops;
return 0;

View File

@@ -1967,6 +1967,18 @@ retry:
}
EXPORT_SYMBOL(iput);
/**
* iput_not_last - put an inode assuming this is not the last reference
* @inode: inode to put
*/
void iput_not_last(struct inode *inode)
{
VFS_BUG_ON_INODE(atomic_read(&inode->i_count) < 2, inode);
WARN_ON(atomic_sub_return(1, &inode->i_count) == 0);
}
EXPORT_SYMBOL(iput_not_last);
#ifdef CONFIG_BLOCK
/**
* bmap - find a block number in a file

View File

@@ -610,6 +610,11 @@ static int isofs_fill_super(struct super_block *s, struct fs_context *fc)
goto out_freesbi;
}
opt->blocksize = sb_min_blocksize(s, opt->blocksize);
if (!opt->blocksize) {
printk(KERN_ERR
"ISOFS: unable to set blocksize\n");
goto out_freesbi;
}
sbi->s_high_sierra = 0; /* default is iso9660 */
sbi->s_session = opt->session;

View File

@@ -132,16 +132,6 @@ EXPORT_SYMBOL_GPL(fs_kobj);
*/
__cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock);
static inline struct mnt_namespace *node_to_mnt_ns(const struct rb_node *node)
{
struct ns_common *ns;
if (!node)
return NULL;
ns = rb_entry(node, struct ns_common, ns_tree_node);
return container_of(ns, struct mnt_namespace, ns);
}
static void mnt_ns_release(struct mnt_namespace *ns)
{
/* keep alive for {list,stat}mount() */
@@ -151,7 +141,8 @@ static void mnt_ns_release(struct mnt_namespace *ns)
kfree(ns);
}
}
DEFINE_FREE(mnt_ns_release, struct mnt_namespace *, if (_T) mnt_ns_release(_T))
DEFINE_FREE(mnt_ns_release, struct mnt_namespace *,
if (!IS_ERR(_T)) mnt_ns_release(_T))
static void mnt_ns_release_rcu(struct rcu_head *rcu)
{
@@ -5454,11 +5445,11 @@ static int statmount_string(struct kstatmount *s, u64 flag)
ret = statmount_sb_source(s, seq);
break;
case STATMOUNT_MNT_UIDMAP:
sm->mnt_uidmap = start;
offp = &sm->mnt_uidmap;
ret = statmount_mnt_uidmap(s, seq);
break;
case STATMOUNT_MNT_GIDMAP:
sm->mnt_gidmap = start;
offp = &sm->mnt_gidmap;
ret = statmount_mnt_gidmap(s, seq);
break;
default:
@@ -5736,7 +5727,7 @@ static int copy_mnt_id_req(const struct mnt_id_req __user *req,
ret = copy_struct_from_user(kreq, sizeof(*kreq), req, usize);
if (ret)
return ret;
if (kreq->spare != 0)
if (kreq->mnt_ns_fd != 0 && kreq->mnt_ns_id)
return -EINVAL;
/* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */
if (kreq->mnt_id <= MNT_UNIQUE_ID_OFFSET)
@@ -5753,16 +5744,12 @@ static struct mnt_namespace *grab_requested_mnt_ns(const struct mnt_id_req *kreq
{
struct mnt_namespace *mnt_ns;
if (kreq->mnt_ns_id && kreq->spare)
return ERR_PTR(-EINVAL);
if (kreq->mnt_ns_id)
return lookup_mnt_ns(kreq->mnt_ns_id);
if (kreq->spare) {
if (kreq->mnt_ns_id) {
mnt_ns = lookup_mnt_ns(kreq->mnt_ns_id);
} else if (kreq->mnt_ns_fd) {
struct ns_common *ns;
CLASS(fd, f)(kreq->spare);
CLASS(fd, f)(kreq->mnt_ns_fd);
if (fd_empty(f))
return ERR_PTR(-EBADF);
@@ -5777,6 +5764,8 @@ static struct mnt_namespace *grab_requested_mnt_ns(const struct mnt_id_req *kreq
} else {
mnt_ns = current->nsproxy->mnt_ns;
}
if (!mnt_ns)
return ERR_PTR(-ENOENT);
refcount_inc(&mnt_ns->passive);
return mnt_ns;
@@ -5801,8 +5790,8 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
return ret;
ns = grab_requested_mnt_ns(&kreq);
if (!ns)
return -ENOENT;
if (IS_ERR(ns))
return PTR_ERR(ns);
if (kreq.mnt_ns_id && (ns != current->nsproxy->mnt_ns) &&
!ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN))
@@ -5912,8 +5901,8 @@ static void __free_klistmount_free(const struct klistmount *kls)
static inline int prepare_klistmount(struct klistmount *kls, struct mnt_id_req *kreq,
size_t nr_mnt_ids)
{
u64 last_mnt_id = kreq->param;
struct mnt_namespace *ns;
/* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */
if (last_mnt_id != 0 && last_mnt_id <= MNT_UNIQUE_ID_OFFSET)
@@ -5927,9 +5916,10 @@ static inline int prepare_klistmount(struct klistmount *kls, struct mnt_id_req *
if (!kls->kmnt_ids)
return -ENOMEM;
kls->ns = grab_requested_mnt_ns(kreq);
if (!kls->ns)
return -ENOENT;
ns = grab_requested_mnt_ns(kreq);
if (IS_ERR(ns))
return PTR_ERR(ns);
kls->ns = ns;
kls->mnt_parent_id = kreq->mnt_id;
return 0;

View File

@@ -1183,11 +1183,14 @@ static inline bool get_active_super(struct super_block *sb)
static const char *filesystems_freeze_ptr = "filesystems_freeze";
static void filesystems_freeze_callback(struct super_block *sb, void *unused)
static void filesystems_freeze_callback(struct super_block *sb, void *freeze_all_ptr)
{
if (!sb->s_op->freeze_fs && !sb->s_op->freeze_super)
return;
if (freeze_all_ptr && !(sb->s_type->fs_flags & FS_POWER_FREEZE))
return;
if (!get_active_super(sb))
return;
@@ -1201,9 +1204,13 @@ static void filesystems_freeze_callback(struct super_block *sb, void *unused)
deactivate_super(sb);
}
void filesystems_freeze(void)
void filesystems_freeze(bool freeze_all)
{
__iterate_supers(filesystems_freeze_callback, NULL,
void *freeze_all_ptr = NULL;
if (freeze_all)
freeze_all_ptr = &freeze_all;
__iterate_supers(filesystems_freeze_callback, freeze_all_ptr,
SUPER_ITER_UNLOCKED | SUPER_ITER_REVERSE);
}

View File

@@ -1693,7 +1693,10 @@ xfs_fs_fill_super(
if (error)
return error;
sb_min_blocksize(sb, BBSIZE);
if (!sb_min_blocksize(sb, BBSIZE)) {
xfs_err(mp, "unable to set blocksize");
return -EINVAL;
}
sb->s_xattr = xfs_xattr_handlers;
sb->s_export_op = &xfs_export_operations;
#ifdef CONFIG_XFS_QUOTA

View File

@@ -2689,6 +2689,7 @@ struct file_system_type {
#define FS_ALLOW_IDMAP 32 /* FS has been updated to handle vfs idmappings. */
#define FS_MGTIME 64 /* FS uses multigrain timestamps */
#define FS_LBS 128 /* FS supports LBS */
#define FS_POWER_FREEZE 256 /* Always freeze on suspend/hibernate */
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
int (*init_fs_context)(struct fs_context *);
const struct fs_parameter_spec *parameters;
@@ -2823,6 +2824,7 @@ extern int current_umask(void);
extern void ihold(struct inode * inode);
extern void iput(struct inode *);
void iput_not_last(struct inode *);
int inode_update_timestamps(struct inode *inode, int flags);
int generic_update_time(struct inode *, int);
@@ -3423,8 +3425,8 @@ static inline void remove_inode_hash(struct inode *inode)
extern void inode_sb_list_add(struct inode *inode);
extern void inode_add_lru(struct inode *inode);
extern int sb_set_blocksize(struct super_block *, int);
extern int sb_min_blocksize(struct super_block *, int);
int sb_set_blocksize(struct super_block *sb, int size);
int __must_check sb_min_blocksize(struct super_block *sb, int size);
int generic_file_mmap(struct file *, struct vm_area_struct *);
int generic_file_mmap_prepare(struct vm_area_desc *desc);
@@ -3606,7 +3608,7 @@ extern void drop_super_exclusive(struct super_block *sb);
extern void iterate_supers(void (*f)(struct super_block *, void *), void *arg);
extern void iterate_supers_type(struct file_system_type *,
void (*)(struct super_block *, void *), void *);
void filesystems_freeze(void);
void filesystems_freeze(bool freeze_all);
void filesystems_thaw(void);
extern int dcache_dir_open(struct inode *, struct file *);

View File

@@ -197,7 +197,7 @@ struct statmount {
*/
struct mnt_id_req {
__u32 size;
__u32 spare;
__u32 mnt_ns_fd;
__u64 mnt_id;
__u64 param;
__u64 mnt_ns_id;

View File

@@ -821,8 +821,7 @@ int hibernate(void)
goto Restore;
ksys_sync_helper();
if (filesystem_freeze_enabled)
filesystems_freeze();
filesystems_freeze(filesystem_freeze_enabled);
error = freeze_processes();
if (error)
@@ -928,8 +927,7 @@ int hibernate_quiet_exec(int (*func)(void *data), void *data)
if (error)
goto restore;
if (filesystem_freeze_enabled)
filesystems_freeze();
filesystems_freeze(filesystem_freeze_enabled);
error = freeze_processes();
if (error)
@@ -1079,8 +1077,7 @@ static int software_resume(void)
if (error)
goto Restore;
if (filesystem_freeze_enabled)
filesystems_freeze();
filesystems_freeze(filesystem_freeze_enabled);
pm_pr_dbg("Preparing processes for hibernation restore.\n");
error = freeze_processes();

View File

@@ -375,8 +375,7 @@ static int suspend_prepare(suspend_state_t state)
if (error)
goto Restore;
if (filesystem_freeze_enabled)
filesystems_freeze();
filesystems_freeze(filesystem_freeze_enabled);
trace_suspend_resume(TPS("freeze_processes"), 0, true);
error = suspend_freeze_processes();
trace_suspend_resume(TPS("freeze_processes"), 0, false);

View File

@@ -131,8 +131,7 @@ struct shmem_options {
#define SHMEM_SEEN_INODES 2
#define SHMEM_SEEN_HUGE 4
#define SHMEM_SEEN_INUMS 8
#define SHMEM_SEEN_NOSWAP 16
#define SHMEM_SEEN_QUOTA 32
#define SHMEM_SEEN_QUOTA 16
};
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -4680,7 +4679,6 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
"Turning off swap in unprivileged tmpfs mounts unsupported");
}
ctx->noswap = true;
ctx->seen |= SHMEM_SEEN_NOSWAP;
break;
case Opt_quota:
if (fc->user_ns != &init_user_ns)
@@ -4830,14 +4828,15 @@ static int shmem_reconfigure(struct fs_context *fc)
err = "Current inum too high to switch to 32-bit inums";
goto out;
}
if ((ctx->seen & SHMEM_SEEN_NOSWAP) && ctx->noswap && !sbinfo->noswap) {
/*
* "noswap" doesn't use fsparam_flag_no, i.e. there's no "swap"
* counterpart for (re-)enabling swap.
*/
if (ctx->noswap && !sbinfo->noswap) {
err = "Cannot disable swap on remount";
goto out;
}
if (!(ctx->seen & SHMEM_SEEN_NOSWAP) && !ctx->noswap && sbinfo->noswap) {
err = "Cannot enable swap on remount if it was disabled on first mount";
goto out;
}
if (ctx->seen & SHMEM_SEEN_QUOTA &&
!sb_any_quota_loaded(fc->root->d_sb)) {

View File

@@ -1335,11 +1335,10 @@ static void hook_sb_delete(struct super_block *const sb)
* At this point, we own the ihold() reference that was
* originally set up by get_inode_object() and the
* __iget() reference that we just set in this loop
* walk. Therefore the following call to iput() will
* not sleep nor drop the inode because there is now at
* least two references to it.
* walk. Therefore there are at least two references
* on the inode.
*/
iput(inode);
iput_not_last(inode);
} else {
spin_unlock(&object->lock);
rcu_read_unlock();