Commit bb6b2062 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fs_for_v6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull isofs, udf, quota, ext2, and reiserfs updates from Jan Kara:

 - convert isofs to the new mount API

 - cleanup isofs Makefile

 - udf conversion to folios

 - some other small udf cleanups and fixes

 - ext2 cleanups

 - removal of reiserfs .writepage method

 - update reiserfs README file

* tag 'fs_for_v6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  isofs: Use *-y instead of *-objs in Makefile
  ext2: Remove LEGACY_DIRECT_IO dependency
  isofs: Remove calls to set/clear the error flag
  ext2: Remove call to folio_set_error()
  udf: Use a folio in udf_write_end()
  udf: Convert udf_page_mkwrite() to use a folio
  udf: Convert udf_symlink_getattr() to use a folio
  udf: Convert udf_adinicb_readpage() to udf_adinicb_read_folio()
  udf: Convert udf_expand_file_adinicb() to use a folio
  udf: Convert udf_write_begin() to use a folio
  udf: Convert udf_symlink_filler() to use a folio
  reiserfs: Trim some README bits
  quota: fix to propagate error of mark_dquot_dirty() to caller
  reiserfs: Convert to writepages
  udf: udftime: prevent overflow in udf_disk_stamp_to_time()
  ext2: set FMODE_CAN_ODIRECT instead of a dummy direct_IO method
  udf: replace deprecated strncpy/strcpy with strscpy
  udf: Remove second semicolon
  isofs: convert isofs to use the new mount API
  fs: quota: use group allocation of per-cpu counters API
parents d0e71e23 1dd719a9
......@@ -3,7 +3,6 @@ config EXT2_FS
tristate "Second extended fs support (DEPRECATED)"
select BUFFER_HEAD
select FS_IOMAP
select LEGACY_DIRECT_IO
help
Ext2 is a standard Linux file system for hard disks.
......
......@@ -175,7 +175,6 @@ static bool ext2_check_folio(struct folio *folio, int quiet, char *kaddr)
(unsigned long) le32_to_cpu(p->inode));
}
fail:
folio_set_error(folio);
return false;
}
......
......@@ -302,6 +302,12 @@ static ssize_t ext2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
return generic_file_write_iter(iocb, from);
}
static int ext2_file_open(struct inode *inode, struct file *filp)
{
filp->f_mode |= FMODE_CAN_ODIRECT;
return dquot_file_open(inode, filp);
}
const struct file_operations ext2_file_operations = {
.llseek = generic_file_llseek,
.read_iter = ext2_file_read_iter,
......@@ -311,7 +317,7 @@ const struct file_operations ext2_file_operations = {
.compat_ioctl = ext2_compat_ioctl,
#endif
.mmap = ext2_file_mmap,
.open = dquot_file_open,
.open = ext2_file_open,
.release = ext2_release_file,
.fsync = ext2_fsync,
.get_unmapped_area = thp_get_unmapped_area,
......
......@@ -965,7 +965,6 @@ const struct address_space_operations ext2_aops = {
.write_begin = ext2_write_begin,
.write_end = ext2_write_end,
.bmap = ext2_bmap,
.direct_IO = noop_direct_IO,
.writepages = ext2_writepages,
.migrate_folio = buffer_migrate_folio,
.is_partially_uptodate = block_is_partially_uptodate,
......@@ -974,7 +973,6 @@ const struct address_space_operations ext2_aops = {
static const struct address_space_operations ext2_dax_aops = {
.writepages = ext2_dax_writepages,
.direct_IO = noop_direct_IO,
.dirty_folio = noop_dirty_folio,
};
......
......@@ -5,7 +5,6 @@
obj-$(CONFIG_ISO9660_FS) += isofs.o
isofs-objs-y := namei.o inode.o dir.o util.o rock.o export.o
isofs-objs-$(CONFIG_JOLIET) += joliet.o
isofs-objs-$(CONFIG_ZISOFS) += compress.o
isofs-objs := $(isofs-objs-y)
isofs-y := namei.o inode.o dir.o util.o rock.o export.o
isofs-$(CONFIG_JOLIET) += joliet.o
isofs-$(CONFIG_ZISOFS) += compress.o
......@@ -346,8 +346,6 @@ static int zisofs_read_folio(struct file *file, struct folio *folio)
for (i = 0; i < pcount; i++, index++) {
if (i != full_page)
pages[i] = grab_cache_page_nowait(mapping, index);
if (pages[i])
ClearPageError(pages[i]);
}
err = zisofs_fill_pages(inode, full_page, pcount, pages);
......@@ -356,8 +354,6 @@ static int zisofs_read_folio(struct file *file, struct folio *folio)
for (i = 0; i < pcount; i++) {
if (pages[i]) {
flush_dcache_page(pages[i]);
if (i == full_page && err)
SetPageError(pages[i]);
unlock_page(pages[i]);
if (i != full_page)
put_page(pages[i]);
......
......@@ -21,11 +21,12 @@
#include <linux/ctype.h>
#include <linux/statfs.h>
#include <linux/cdrom.h>
#include <linux/parser.h>
#include <linux/mpage.h>
#include <linux/user_namespace.h>
#include <linux/seq_file.h>
#include <linux/blkdev.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
#include "isofs.h"
#include "zisofs.h"
......@@ -110,10 +111,10 @@ static void destroy_inodecache(void)
kmem_cache_destroy(isofs_inode_cachep);
}
static int isofs_remount(struct super_block *sb, int *flags, char *data)
static int isofs_reconfigure(struct fs_context *fc)
{
sync_filesystem(sb);
if (!(*flags & SB_RDONLY))
sync_filesystem(fc->root->d_sb);
if (!(fc->sb_flags & SB_RDONLY))
return -EROFS;
return 0;
}
......@@ -123,7 +124,6 @@ static const struct super_operations isofs_sops = {
.free_inode = isofs_free_inode,
.put_super = isofs_put_super,
.statfs = isofs_statfs,
.remount_fs = isofs_remount,
.show_options = isofs_show_options,
};
......@@ -145,7 +145,7 @@ static const struct dentry_operations isofs_dentry_ops[] = {
#endif
};
struct iso9660_options{
struct isofs_options{
unsigned int rock:1;
unsigned int joliet:1;
unsigned int cruft:1;
......@@ -289,88 +289,74 @@ isofs_dentry_cmpi_ms(const struct dentry *dentry,
#endif
enum {
Opt_block, Opt_check_r, Opt_check_s, Opt_cruft, Opt_gid, Opt_ignore,
Opt_iocharset, Opt_map_a, Opt_map_n, Opt_map_o, Opt_mode, Opt_nojoliet,
Opt_norock, Opt_sb, Opt_session, Opt_uid, Opt_unhide, Opt_utf8, Opt_err,
Opt_nocompress, Opt_hide, Opt_showassoc, Opt_dmode, Opt_overriderockperm,
Opt_block, Opt_check, Opt_cruft, Opt_gid, Opt_ignore, Opt_iocharset,
Opt_map, Opt_mode, Opt_nojoliet, Opt_norock, Opt_sb, Opt_session,
Opt_uid, Opt_unhide, Opt_utf8, Opt_err, Opt_nocompress, Opt_hide,
Opt_showassoc, Opt_dmode, Opt_overriderockperm,
};
static const match_table_t tokens = {
{Opt_norock, "norock"},
{Opt_nojoliet, "nojoliet"},
{Opt_unhide, "unhide"},
{Opt_hide, "hide"},
{Opt_showassoc, "showassoc"},
{Opt_cruft, "cruft"},
{Opt_utf8, "utf8"},
{Opt_iocharset, "iocharset=%s"},
{Opt_map_a, "map=acorn"},
{Opt_map_a, "map=a"},
{Opt_map_n, "map=normal"},
{Opt_map_n, "map=n"},
{Opt_map_o, "map=off"},
{Opt_map_o, "map=o"},
{Opt_session, "session=%u"},
{Opt_sb, "sbsector=%u"},
{Opt_check_r, "check=relaxed"},
{Opt_check_r, "check=r"},
{Opt_check_s, "check=strict"},
{Opt_check_s, "check=s"},
{Opt_uid, "uid=%u"},
{Opt_gid, "gid=%u"},
{Opt_mode, "mode=%u"},
{Opt_dmode, "dmode=%u"},
{Opt_overriderockperm, "overriderockperm"},
{Opt_block, "block=%u"},
{Opt_ignore, "conv=binary"},
{Opt_ignore, "conv=b"},
{Opt_ignore, "conv=text"},
{Opt_ignore, "conv=t"},
{Opt_ignore, "conv=mtext"},
{Opt_ignore, "conv=m"},
{Opt_ignore, "conv=auto"},
{Opt_ignore, "conv=a"},
{Opt_nocompress, "nocompress"},
{Opt_err, NULL}
static const struct constant_table isofs_param_map[] = {
{"acorn", 'a'},
{"a", 'a'},
{"normal", 'n'},
{"n", 'n'},
{"off", 'o'},
{"o", 'o'},
{}
};
static int parse_options(char *options, struct iso9660_options *popt)
static const struct constant_table isofs_param_check[] = {
{"relaxed", 'r'},
{"r", 'r'},
{"strict", 's'},
{"s", 's'},
{}
};
static const struct fs_parameter_spec isofs_param_spec[] = {
fsparam_flag ("norock", Opt_norock),
fsparam_flag ("nojoliet", Opt_nojoliet),
fsparam_flag ("unhide", Opt_unhide),
fsparam_flag ("hide", Opt_hide),
fsparam_flag ("showassoc", Opt_showassoc),
fsparam_flag ("cruft", Opt_cruft),
fsparam_flag ("utf8", Opt_utf8),
fsparam_string ("iocharset", Opt_iocharset),
fsparam_enum ("map", Opt_map, isofs_param_map),
fsparam_u32 ("session", Opt_session),
fsparam_u32 ("sbsector", Opt_sb),
fsparam_enum ("check", Opt_check, isofs_param_check),
fsparam_u32 ("uid", Opt_uid),
fsparam_u32 ("gid", Opt_gid),
/* Note: mode/dmode historically accepted %u not strictly %o */
fsparam_u32 ("mode", Opt_mode),
fsparam_u32 ("dmode", Opt_dmode),
fsparam_flag ("overriderockperm", Opt_overriderockperm),
fsparam_u32 ("block", Opt_block),
fsparam_string ("conv", Opt_ignore),
fsparam_flag ("nocompress", Opt_nocompress),
{}
};
static int isofs_parse_param(struct fs_context *fc,
struct fs_parameter *param)
{
char *p;
int option;
unsigned int uv;
popt->map = 'n';
popt->rock = 1;
popt->joliet = 1;
popt->cruft = 0;
popt->hide = 0;
popt->showassoc = 0;
popt->check = 'u'; /* unset */
popt->nocompress = 0;
popt->blocksize = 1024;
popt->fmode = popt->dmode = ISOFS_INVALID_MODE;
popt->uid_set = 0;
popt->gid_set = 0;
popt->gid = GLOBAL_ROOT_GID;
popt->uid = GLOBAL_ROOT_UID;
popt->iocharset = NULL;
popt->overriderockperm = 0;
popt->session=-1;
popt->sbsector=-1;
if (!options)
return 1;
struct isofs_options *popt = fc->fs_private;
struct fs_parse_result result;
int opt;
kuid_t uid;
kgid_t gid;
unsigned int n;
while ((p = strsep(&options, ",")) != NULL) {
int token;
substring_t args[MAX_OPT_ARGS];
unsigned n;
/* There are no remountable options */
if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE)
return 0;
if (!*p)
continue;
opt = fs_parse(fc, isofs_param_spec, param, &result);
if (opt < 0)
return opt;
token = match_token(p, tokens, args);
switch (token) {
switch (opt) {
case Opt_norock:
popt->rock = 0;
break;
......@@ -392,94 +378,72 @@ static int parse_options(char *options, struct iso9660_options *popt)
kfree(popt->iocharset);
popt->iocharset = kstrdup("utf8", GFP_KERNEL);
if (!popt->iocharset)
return 0;
return -ENOMEM;
break;
case Opt_iocharset:
kfree(popt->iocharset);
popt->iocharset = match_strdup(&args[0]);
popt->iocharset = kstrdup(param->string, GFP_KERNEL);
if (!popt->iocharset)
return 0;
return -ENOMEM;
break;
#endif
case Opt_map_a:
popt->map = 'a';
break;
case Opt_map_o:
popt->map = 'o';
break;
case Opt_map_n:
popt->map = 'n';
case Opt_map:
popt->map = result.uint_32;
break;
case Opt_session:
if (match_int(&args[0], &option))
return 0;
n = option;
n = result.uint_32;
/*
* Track numbers are supposed to be in range 1-99, the
* mount option starts indexing at 0.
*/
if (n >= 99)
return 0;
return -EINVAL;
popt->session = n + 1;
break;
case Opt_sb:
if (match_int(&args[0], &option))
return 0;
popt->sbsector = option;
popt->sbsector = result.uint_32;
break;
case Opt_check_r:
popt->check = 'r';
break;
case Opt_check_s:
popt->check = 's';
case Opt_check:
popt->check = result.uint_32;
break;
case Opt_ignore:
break;
case Opt_uid:
if (match_uint(&args[0], &uv))
return 0;
popt->uid = make_kuid(current_user_ns(), uv);
if (!uid_valid(popt->uid))
return 0;
uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(uid))
return -EINVAL;
popt->uid = uid;
popt->uid_set = 1;
break;
case Opt_gid:
if (match_uint(&args[0], &uv))
return 0;
popt->gid = make_kgid(current_user_ns(), uv);
if (!gid_valid(popt->gid))
return 0;
gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(gid))
return -EINVAL;
popt->gid = gid;
popt->gid_set = 1;
break;
case Opt_mode:
if (match_int(&args[0], &option))
return 0;
popt->fmode = option;
popt->fmode = result.uint_32;
break;
case Opt_dmode:
if (match_int(&args[0], &option))
return 0;
popt->dmode = option;
popt->dmode = result.uint_32;
break;
case Opt_overriderockperm:
popt->overriderockperm = 1;
break;
case Opt_block:
if (match_int(&args[0], &option))
return 0;
n = option;
n = result.uint_32;
if (n != 512 && n != 1024 && n != 2048)
return 0;
return -EINVAL;
popt->blocksize = n;
break;
case Opt_nocompress:
popt->nocompress = 1;
break;
default:
return 0;
}
return -EINVAL;
}
return 1;
return 0;
}
/*
......@@ -615,7 +579,7 @@ static bool rootdir_empty(struct super_block *sb, unsigned long block)
/*
* Initialize the superblock and read the root inode.
*/
static int isofs_fill_super(struct super_block *s, void *data, int silent)
static int isofs_fill_super(struct super_block *s, struct fs_context *fc)
{
struct buffer_head *bh = NULL, *pri_bh = NULL;
struct hs_primary_descriptor *h_pri = NULL;
......@@ -623,7 +587,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
struct iso_supplementary_descriptor *sec = NULL;
struct iso_directory_record *rootp;
struct inode *inode;
struct iso9660_options opt;
struct isofs_options *opt = fc->fs_private;
struct isofs_sb_info *sbi;
unsigned long first_data_zone;
int joliet_level = 0;
......@@ -631,15 +595,13 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
int orig_zonesize;
int table, error = -EINVAL;
unsigned int vol_desc_start;
int silent = fc->sb_flags & SB_SILENT;
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
return -ENOMEM;
s->s_fs_info = sbi;
if (!parse_options((char *)data, &opt))
goto out_freesbi;
/*
* First of all, get the hardware blocksize for this device.
* If we don't know what it is, or the hardware blocksize is
......@@ -655,14 +617,14 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
bdev_logical_block_size(s->s_bdev));
goto out_freesbi;
}
opt.blocksize = sb_min_blocksize(s, opt.blocksize);
opt->blocksize = sb_min_blocksize(s, opt->blocksize);
sbi->s_high_sierra = 0; /* default is iso9660 */
sbi->s_session = opt.session;
sbi->s_sbsector = opt.sbsector;
sbi->s_session = opt->session;
sbi->s_sbsector = opt->sbsector;
vol_desc_start = (opt.sbsector != -1) ?
opt.sbsector : isofs_get_last_session(s,opt.session);
vol_desc_start = (opt->sbsector != -1) ?
opt->sbsector : isofs_get_last_session(s, opt->session);
for (iso_blknum = vol_desc_start+16;
iso_blknum < vol_desc_start+100; iso_blknum++) {
......@@ -696,7 +658,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
else if (isonum_711(vdp->type) == ISO_VD_SUPPLEMENTARY) {
sec = (struct iso_supplementary_descriptor *)vdp;
if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
if (opt.joliet) {
if (opt->joliet) {
if (sec->escape[2] == 0x40)
joliet_level = 1;
else if (sec->escape[2] == 0x43)
......@@ -721,7 +683,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
goto out_freebh;
sbi->s_high_sierra = 1;
opt.rock = 0;
opt->rock = 0;
h_pri = (struct hs_primary_descriptor *)vdp;
goto root_found;
}
......@@ -749,7 +711,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
goto out_freebh;
}
if (joliet_level && (!pri || !opt.rock)) {
if (joliet_level && (!pri || !opt->rock)) {
/* This is the case of Joliet with the norock mount flag.
* A disc with both Joliet and Rock Ridge is handled later
*/
......@@ -780,7 +742,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
* blocks that were 512 bytes (which should only very rarely
* happen.)
*/
if (orig_zonesize < opt.blocksize)
if (orig_zonesize < opt->blocksize)
goto out_bad_size;
/* RDE: convert log zone size to bit shift */
......@@ -865,10 +827,10 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
#ifdef CONFIG_JOLIET
if (joliet_level) {
char *p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT;
char *p = opt->iocharset ? opt->iocharset : CONFIG_NLS_DEFAULT;
if (strcmp(p, "utf8") != 0) {
sbi->s_nls_iocharset = opt.iocharset ?
load_nls(opt.iocharset) : load_nls_default();
sbi->s_nls_iocharset = opt->iocharset ?
load_nls(opt->iocharset) : load_nls_default();
if (!sbi->s_nls_iocharset)
goto out_freesbi;
}
......@@ -876,29 +838,29 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
#endif
s->s_op = &isofs_sops;
s->s_export_op = &isofs_export_ops;
sbi->s_mapping = opt.map;
sbi->s_rock = (opt.rock ? 2 : 0);
sbi->s_mapping = opt->map;
sbi->s_rock = (opt->rock ? 2 : 0);
sbi->s_rock_offset = -1; /* initial offset, will guess until SP is found*/
sbi->s_cruft = opt.cruft;
sbi->s_hide = opt.hide;
sbi->s_showassoc = opt.showassoc;
sbi->s_uid = opt.uid;
sbi->s_gid = opt.gid;
sbi->s_uid_set = opt.uid_set;
sbi->s_gid_set = opt.gid_set;
sbi->s_nocompress = opt.nocompress;
sbi->s_overriderockperm = opt.overriderockperm;
sbi->s_cruft = opt->cruft;
sbi->s_hide = opt->hide;
sbi->s_showassoc = opt->showassoc;
sbi->s_uid = opt->uid;
sbi->s_gid = opt->gid;
sbi->s_uid_set = opt->uid_set;
sbi->s_gid_set = opt->gid_set;
sbi->s_nocompress = opt->nocompress;
sbi->s_overriderockperm = opt->overriderockperm;
/*
* It would be incredibly stupid to allow people to mark every file
* on the disk as suid, so we merely allow them to set the default
* permissions.
*/
if (opt.fmode != ISOFS_INVALID_MODE)
sbi->s_fmode = opt.fmode & 0777;
if (opt->fmode != ISOFS_INVALID_MODE)
sbi->s_fmode = opt->fmode & 0777;
else
sbi->s_fmode = ISOFS_INVALID_MODE;
if (opt.dmode != ISOFS_INVALID_MODE)
sbi->s_dmode = opt.dmode & 0777;
if (opt->dmode != ISOFS_INVALID_MODE)
sbi->s_dmode = opt->dmode & 0777;
else
sbi->s_dmode = ISOFS_INVALID_MODE;
......@@ -960,12 +922,12 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
}
}
if (opt.check == 'u') {
if (opt->check == 'u') {
/* Only Joliet is case insensitive by default */
if (joliet_level)
opt.check = 'r';
opt->check = 'r';
else
opt.check = 's';
opt->check = 's';
}
sbi->s_joliet_level = joliet_level;
......@@ -980,9 +942,9 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
table = 0;
if (joliet_level)
table += 2;
if (opt.check == 'r')
if (opt->check == 'r')
table++;
sbi->s_check = opt.check;
sbi->s_check = opt->check;
if (table)
s->s_d_op = &isofs_dentry_ops[table - 1];
......@@ -994,7 +956,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
goto out_no_inode;
}
kfree(opt.iocharset);
kfree(opt->iocharset);
return 0;
......@@ -1023,7 +985,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
goto out_freebh;
out_bad_size:
printk(KERN_WARNING "ISOFS: Logical zone size(%d) < hardware blocksize(%u)\n",
orig_zonesize, opt.blocksize);
orig_zonesize, opt->blocksize);
goto out_freebh;
out_unknown_format:
if (!silent)
......@@ -1033,7 +995,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
brelse(bh);
brelse(pri_bh);
out_freesbi:
kfree(opt.iocharset);
kfree(opt->iocharset);
kfree(sbi);
s->s_fs_info = NULL;
return error;
......@@ -1567,18 +1529,63 @@ struct inode *__isofs_iget(struct super_block *sb,
return inode;
}
static struct dentry *isofs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
static int isofs_get_tree(struct fs_context *fc)
{
return mount_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
return get_tree_bdev(fc, isofs_fill_super);
}
static void isofs_free_fc(struct fs_context *fc)
{
kfree(fc->fs_private);
}
static const struct fs_context_operations isofs_context_ops = {
.parse_param = isofs_parse_param,
.get_tree = isofs_get_tree,
.reconfigure = isofs_reconfigure,
.free = isofs_free_fc,
};
static int isofs_init_fs_context(struct fs_context *fc)
{
struct isofs_options *opt;
opt = kzalloc(sizeof(*opt), GFP_KERNEL);
if (!opt)
return -ENOMEM;
opt->map = 'n';
opt->rock = 1;
opt->joliet = 1;
opt->cruft = 0;
opt->hide = 0;
opt->showassoc = 0;
opt->check = 'u'; /* unset */
opt->nocompress = 0;
opt->blocksize = 1024;
opt->fmode = opt->dmode = ISOFS_INVALID_MODE;
opt->uid_set = 0;
opt->gid_set = 0;
opt->gid = GLOBAL_ROOT_GID;
opt->uid = GLOBAL_ROOT_UID;
opt->iocharset = NULL;
opt->overriderockperm = 0;
opt->session = -1;
opt->sbsector = -1;
fc->fs_private = opt;
fc->ops = &isofs_context_ops;
return 0;
}
static struct file_system_type iso9660_fs_type = {
.owner = THIS_MODULE,
.name = "iso9660",
.mount = isofs_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
.init_fs_context = isofs_init_fs_context,
.parameters = isofs_param_spec,
};
MODULE_ALIAS_FS("iso9660");
MODULE_ALIAS("iso9660");
......
......@@ -410,7 +410,7 @@ static inline int mark_all_dquot_dirty(struct dquot __rcu * const *dquots)
if (dquot)
/* Even in case of error we have to continue */
ret = mark_dquot_dirty(dquot);
if (!err)
if (!err && ret < 0)
err = ret;
}
return err;
......@@ -1737,7 +1737,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
if (reserve)
goto out_flush_warn;
mark_all_dquot_dirty(dquots);
ret = mark_all_dquot_dirty(dquots);
out_flush_warn:
srcu_read_unlock(&dquot_srcu, index);
flush_warnings(warn);
......@@ -1786,7 +1786,7 @@ int dquot_alloc_inode(struct inode *inode)
warn_put_all:
spin_unlock(&inode->i_lock);
if (ret == 0)
mark_all_dquot_dirty(dquots);
ret = mark_all_dquot_dirty(dquots);
srcu_read_unlock(&dquot_srcu, index);
flush_warnings(warn);
return ret;
......@@ -1990,7 +1990,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
qsize_t inode_usage = 1;
struct dquot __rcu **dquots;
struct dquot *transfer_from[MAXQUOTAS] = {};
int cnt, index, ret = 0;
int cnt, index, ret = 0, err;
char is_valid[MAXQUOTAS] = {};
struct dquot_warn warn_to[MAXQUOTAS];
struct dquot_warn warn_from_inodes[MAXQUOTAS];
......@@ -2087,8 +2087,12 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
* mark_all_dquot_dirty().
*/
index = srcu_read_lock(&dquot_srcu);
mark_all_dquot_dirty((struct dquot __rcu **)transfer_from);
mark_all_dquot_dirty((struct dquot __rcu **)transfer_to);
err = mark_all_dquot_dirty((struct dquot __rcu **)transfer_from);
if (err < 0)
ret = err;
err = mark_all_dquot_dirty((struct dquot __rcu **)transfer_to);
if (err < 0)
ret = err;
srcu_read_unlock(&dquot_srcu, index);
flush_warnings(warn_to);
......@@ -2098,7 +2102,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
if (is_valid[cnt])
transfer_to[cnt] = transfer_from[cnt];
return 0;
return ret;
over_quota:
/* Back out changes we already did */
for (cnt--; cnt >= 0; cnt--) {
......@@ -2726,6 +2730,7 @@ static int do_set_dqblk(struct dquot *dquot, struct qc_dqblk *di)
struct mem_dqblk *dm = &dquot->dq_dqb;
int check_blim = 0, check_ilim = 0;
struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type];
int ret;
if (di->d_fieldmask & ~VFS_QC_MASK)
return -EINVAL;
......@@ -2807,8 +2812,9 @@ static int do_set_dqblk(struct dquot *dquot, struct qc_dqblk *di)
else
set_bit(DQ_FAKE_B, &dquot->dq_flags);
spin_unlock(&dquot->dq_dqb_lock);
mark_dquot_dirty(dquot);
ret = mark_dquot_dirty(dquot);
if (ret < 0)
return ret;
return 0;
}
......@@ -3016,11 +3022,10 @@ static int __init dquot_init(void)
if (!dquot_hash)
panic("Cannot create dquot hash table");
for (i = 0; i < _DQST_DQSTAT_LAST; i++) {
ret = percpu_counter_init(&dqstats.counter[i], 0, GFP_KERNEL);
ret = percpu_counter_init_many(dqstats.counter, 0, GFP_KERNEL,
_DQST_DQSTAT_LAST);
if (ret)
panic("Cannot create dquot stat counters");
}
/* Find power-of-two hlist_heads which can fit into allocation */
nr_hash = (1UL << order) * PAGE_SIZE / sizeof(struct hlist_head);
......
......@@ -102,19 +102,9 @@ that start on a node aligned boundary (there are reasons to want to node
align files), and he invented and implemented indirect items and
unformatted nodes as the solution.
Konstantin Shvachko, with the help of the Russian version of a VC,
tried to put me in a position where I was forced into giving control
of the project to him. (Fortunately, as the person paying the money
for all salaries from my dayjob I owned all copyrights, and you can't
really force takeovers of sole proprietorships.) This was something
curious, because he never really understood the value of our project,
why we should do what we do, or why innovation was possible in
general, but he was sure that he ought to be controlling it. Every
innovation had to be forced past him while he was with us. He added
two years to the time required to complete reiserfs, and was a net
loss for me. Mikhail Gilula was a brilliant innovator who also left
in a destructive way that erased the value of his contributions, and
that he was shown much generosity just makes it more painful.
Konstantin Shvachko was taking part in the early days.
Mikhail Gilula was a brilliant innovator that has shown much generosity.
Grigory Zaigralin was an extremely effective system administrator for
our group.
......
......@@ -2503,8 +2503,8 @@ static int map_block_for_writepage(struct inode *inode,
* start/recovery path as __block_write_full_folio, along with special
* code to handle reiserfs tails.
*/
static int reiserfs_write_full_folio(struct folio *folio,
struct writeback_control *wbc)
static int reiserfs_write_folio(struct folio *folio,
struct writeback_control *wbc, void *data)
{
struct inode *inode = folio->mapping->host;
unsigned long end_index = inode->i_size >> PAGE_SHIFT;
......@@ -2721,12 +2721,11 @@ static int reiserfs_read_folio(struct file *f, struct folio *folio)
return block_read_full_folio(folio, reiserfs_get_block);
}
static int reiserfs_writepage(struct page *page, struct writeback_control *wbc)
static int reiserfs_writepages(struct address_space *mapping,
struct writeback_control *wbc)
{
struct folio *folio = page_folio(page);
struct inode *inode = folio->mapping->host;
reiserfs_wait_on_write_block(inode->i_sb);
return reiserfs_write_full_folio(folio, wbc);
reiserfs_wait_on_write_block(mapping->host->i_sb);
return write_cache_pages(mapping, wbc, reiserfs_write_folio, NULL);
}
static void reiserfs_truncate_failed_write(struct inode *inode)
......@@ -3405,7 +3404,7 @@ int reiserfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
}
const struct address_space_operations reiserfs_address_space_operations = {
.writepage = reiserfs_writepage,
.writepages = reiserfs_writepages,
.read_folio = reiserfs_read_folio,
.readahead = reiserfs_readahead,
.release_folio = reiserfs_release_folio,
......@@ -3415,4 +3414,5 @@ const struct address_space_operations reiserfs_address_space_operations = {
.bmap = reiserfs_aop_bmap,
.direct_IO = reiserfs_direct_IO,
.dirty_folio = reiserfs_dirty_folio,
.migrate_folio = buffer_migrate_folio,
};
......@@ -39,7 +39,7 @@ static vm_fault_t udf_page_mkwrite(struct vm_fault *vmf)
struct vm_area_struct *vma = vmf->vma;
struct inode *inode = file_inode(vma->vm_file);
struct address_space *mapping = inode->i_mapping;
struct page *page = vmf->page;
struct folio *folio = page_folio(vmf->page);
loff_t size;
unsigned int end;
vm_fault_t ret = VM_FAULT_LOCKED;
......@@ -48,31 +48,31 @@ static vm_fault_t udf_page_mkwrite(struct vm_fault *vmf)
sb_start_pagefault(inode->i_sb);
file_update_time(vma->vm_file);
filemap_invalidate_lock_shared(mapping);
lock_page(page);
folio_lock(folio);
size = i_size_read(inode);
if (page->mapping != inode->i_mapping || page_offset(page) >= size) {
unlock_page(page);
if (folio->mapping != inode->i_mapping || folio_pos(folio) >= size) {
folio_unlock(folio);
ret = VM_FAULT_NOPAGE;
goto out_unlock;
}
/* Space is already allocated for in-ICB file */
if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
goto out_dirty;
if (page->index == size >> PAGE_SHIFT)
if (folio->index == size >> PAGE_SHIFT)
end = size & ~PAGE_MASK;
else
end = PAGE_SIZE;
err = __block_write_begin(page, 0, end, udf_get_block);
err = __block_write_begin(&folio->page, 0, end, udf_get_block);
if (err) {
unlock_page(page);
folio_unlock(folio);
ret = vmf_fs_error(err);
goto out_unlock;
}
block_commit_write(page, 0, end);
block_commit_write(&folio->page, 0, end);
out_dirty:
set_page_dirty(page);
wait_for_stable_page(page);
folio_mark_dirty(folio);
folio_wait_stable(folio);
out_unlock:
filemap_invalidate_unlock_shared(mapping);
sb_end_pagefault(inode->i_sb);
......
......@@ -208,19 +208,14 @@ static int udf_writepages(struct address_space *mapping,
return write_cache_pages(mapping, wbc, udf_adinicb_writepage, NULL);
}
static void udf_adinicb_readpage(struct page *page)
static void udf_adinicb_read_folio(struct folio *folio)
{
struct inode *inode = page->mapping->host;
char *kaddr;
struct inode *inode = folio->mapping->host;
struct udf_inode_info *iinfo = UDF_I(inode);
loff_t isize = i_size_read(inode);
kaddr = kmap_local_page(page);
memcpy(kaddr, iinfo->i_data + iinfo->i_lenEAttr, isize);
memset(kaddr + isize, 0, PAGE_SIZE - isize);
flush_dcache_page(page);
SetPageUptodate(page);
kunmap_local(kaddr);
folio_fill_tail(folio, 0, iinfo->i_data + iinfo->i_lenEAttr, isize);
folio_mark_uptodate(folio);
}
static int udf_read_folio(struct file *file, struct folio *folio)
......@@ -228,7 +223,7 @@ static int udf_read_folio(struct file *file, struct folio *folio)
struct udf_inode_info *iinfo = UDF_I(file_inode(file));
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
udf_adinicb_readpage(&folio->page);
udf_adinicb_read_folio(folio);
folio_unlock(folio);
return 0;
}
......@@ -254,7 +249,7 @@ static int udf_write_begin(struct file *file, struct address_space *mapping,
struct page **pagep, void **fsdata)
{
struct udf_inode_info *iinfo = UDF_I(file_inode(file));
struct page *page;
struct folio *folio;
int ret;
if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
......@@ -266,12 +261,13 @@ static int udf_write_begin(struct file *file, struct address_space *mapping,
}
if (WARN_ON_ONCE(pos >= PAGE_SIZE))
return -EIO;
page = grab_cache_page_write_begin(mapping, 0);
if (!page)
return -ENOMEM;
*pagep = page;
if (!PageUptodate(page))
udf_adinicb_readpage(page);
folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN,
mapping_gfp_mask(mapping));
if (IS_ERR(folio))
return PTR_ERR(folio);
*pagep = &folio->page;
if (!folio_test_uptodate(folio))
udf_adinicb_read_folio(folio);
return 0;
}
......@@ -280,17 +276,19 @@ static int udf_write_end(struct file *file, struct address_space *mapping,
struct page *page, void *fsdata)
{
struct inode *inode = file_inode(file);
struct folio *folio;
loff_t last_pos;
if (UDF_I(inode)->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB)
return generic_write_end(file, mapping, pos, len, copied, page,
fsdata);
folio = page_folio(page);
last_pos = pos + copied;
if (last_pos > inode->i_size)
i_size_write(inode, last_pos);
set_page_dirty(page);
unlock_page(page);
put_page(page);
folio_mark_dirty(folio);
folio_unlock(folio);
folio_put(folio);
return copied;
}
......@@ -341,7 +339,7 @@ const struct address_space_operations udf_aops = {
*/
int udf_expand_file_adinicb(struct inode *inode)
{
struct page *page;
struct folio *folio;
struct udf_inode_info *iinfo = UDF_I(inode);
int err;
......@@ -357,12 +355,13 @@ int udf_expand_file_adinicb(struct inode *inode)
return 0;
}
page = find_or_create_page(inode->i_mapping, 0, GFP_KERNEL);
if (!page)
return -ENOMEM;
folio = __filemap_get_folio(inode->i_mapping, 0,
FGP_LOCK | FGP_ACCESSED | FGP_CREAT, GFP_KERNEL);
if (IS_ERR(folio))
return PTR_ERR(folio);
if (!PageUptodate(page))
udf_adinicb_readpage(page);
if (!folio_test_uptodate(folio))
udf_adinicb_read_folio(folio);
down_write(&iinfo->i_data_sem);
memset(iinfo->i_data + iinfo->i_lenEAttr, 0x00,
iinfo->i_lenAlloc);
......@@ -371,22 +370,22 @@ int udf_expand_file_adinicb(struct inode *inode)
iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
else
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
set_page_dirty(page);
unlock_page(page);
folio_mark_dirty(folio);
folio_unlock(folio);
up_write(&iinfo->i_data_sem);
err = filemap_fdatawrite(inode->i_mapping);
if (err) {
/* Restore everything back so that we don't lose data... */
lock_page(page);
folio_lock(folio);
down_write(&iinfo->i_data_sem);
memcpy_to_page(page, 0, iinfo->i_data + iinfo->i_lenEAttr,
inode->i_size);
unlock_page(page);
memcpy_from_folio(iinfo->i_data + iinfo->i_lenEAttr,
folio, 0, inode->i_size);
folio_unlock(folio);
iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
iinfo->i_lenAlloc = inode->i_size;
up_write(&iinfo->i_data_sem);
}
put_page(page);
folio_put(folio);
mark_inode_dirty(inode);
return err;
......
......@@ -630,7 +630,7 @@ static int udf_parse_param(struct fs_context *fc, struct fs_parameter *param)
if (!uopt->nls_map) {
errorf(fc, "iocharset %s not found",
param->string);
return -EINVAL;;
return -EINVAL;
}
}
break;
......@@ -895,7 +895,7 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
int ret;
struct timestamp *ts;
outstr = kmalloc(128, GFP_KERNEL);
outstr = kzalloc(128, GFP_KERNEL);
if (!outstr)
return -ENOMEM;
......@@ -921,11 +921,11 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
ret = udf_dstrCS0toChar(sb, outstr, 31, pvoldesc->volIdent, 32);
if (ret < 0) {
strcpy(UDF_SB(sb)->s_volume_ident, "InvalidName");
strscpy_pad(UDF_SB(sb)->s_volume_ident, "InvalidName");
pr_warn("incorrect volume identification, setting to "
"'InvalidName'\n");
} else {
strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret);
strscpy_pad(UDF_SB(sb)->s_volume_ident, outstr);
}
udf_debug("volIdent[] = '%s'\n", UDF_SB(sb)->s_volume_ident);
......
......@@ -99,18 +99,17 @@ static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
static int udf_symlink_filler(struct file *file, struct folio *folio)
{
struct page *page = &folio->page;
struct inode *inode = page->mapping->host;
struct inode *inode = folio->mapping->host;
struct buffer_head *bh = NULL;
unsigned char *symlink;
int err = 0;
unsigned char *p = page_address(page);
unsigned char *p = folio_address(folio);
struct udf_inode_info *iinfo = UDF_I(inode);
/* We don't support symlinks longer than one block */
if (inode->i_size > inode->i_sb->s_blocksize) {
err = -ENAMETOOLONG;
goto out_unlock;
goto out;
}
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
......@@ -120,24 +119,15 @@ static int udf_symlink_filler(struct file *file, struct folio *folio)
if (!bh) {
if (!err)
err = -EFSCORRUPTED;
goto out_err;
goto out;
}
symlink = bh->b_data;
}
err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE);
brelse(bh);
if (err)
goto out_err;
SetPageUptodate(page);
unlock_page(page);
return 0;
out_err:
SetPageError(page);
out_unlock:
unlock_page(page);
out:
folio_end_read(folio, err == 0);
return err;
}
......@@ -147,12 +137,12 @@ static int udf_symlink_getattr(struct mnt_idmap *idmap,
{
struct dentry *dentry = path->dentry;
struct inode *inode = d_backing_inode(dentry);
struct page *page;
struct folio *folio;
generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
page = read_mapping_page(inode->i_mapping, 0, NULL);
if (IS_ERR(page))
return PTR_ERR(page);
folio = read_mapping_folio(inode->i_mapping, 0, NULL);
if (IS_ERR(folio))
return PTR_ERR(folio);
/*
* UDF uses non-trivial encoding of symlinks so i_size does not match
* number of characters reported by readlink(2) which apparently some
......@@ -162,8 +152,8 @@ static int udf_symlink_getattr(struct mnt_idmap *idmap,
* let's report the length of string returned by readlink(2) for
* st_size.
*/
stat->size = strlen(page_address(page));
put_page(page);
stat->size = strlen(folio_address(folio));
folio_put(folio);
return 0;
}
......
......@@ -46,13 +46,18 @@ udf_disk_stamp_to_time(struct timespec64 *dest, struct timestamp src)
dest->tv_sec = mktime64(year, src.month, src.day, src.hour, src.minute,
src.second);
dest->tv_sec -= offset * 60;
dest->tv_nsec = 1000 * (src.centiseconds * 10000 +
src.hundredsOfMicroseconds * 100 + src.microseconds);
/*
* Sanitize nanosecond field since reportedly some filesystems are
* recorded with bogus sub-second values.
*/
dest->tv_nsec %= NSEC_PER_SEC;
if (src.centiseconds < 100 && src.hundredsOfMicroseconds < 100 &&
src.microseconds < 100) {
dest->tv_nsec = 1000 * (src.centiseconds * 10000 +
src.hundredsOfMicroseconds * 100 + src.microseconds);
} else {
dest->tv_nsec = 0;
}
}
void
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment