Merge tag 'fs_for_v6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 20 May 2024 19:49:25 +0000 (12:49 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 20 May 2024 19:49:25 +0000 (12:49 -0700)
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

15 files changed:
fs/ext2/Kconfig
fs/ext2/dir.c
fs/ext2/file.c
fs/ext2/inode.c
fs/isofs/Makefile
fs/isofs/compress.c
fs/isofs/inode.c
fs/quota/dquot.c
fs/reiserfs/README
fs/reiserfs/inode.c
fs/udf/file.c
fs/udf/inode.c
fs/udf/super.c
fs/udf/symlink.c
fs/udf/udftime.c

index d6cfb18495801f48d33d570cf365a3469cdb96c6..d5bce83ad9054b7105c47715c47fb3851e7b9bb8 100644 (file)
@@ -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.
 
index 4fb155b5a958f6890522df9680310dc163e6d016..087457061c6ef40fb3135d0f2dd0a1210ef454b8 100644 (file)
@@ -175,7 +175,6 @@ Eend:
                        (unsigned long) le32_to_cpu(p->inode));
        }
 fail:
-       folio_set_error(folio);
        return false;
 }
 
index 4ddc36f4dbd407950994b278d658ad453482efed..10b061ac5bc098a5a2a3b6d489298a7ca530cb9c 100644 (file)
@@ -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,
index f3d570a9302b09a1dd206d369c445b745b290fba..0caa1650cee87593c7bd2c560efe63886df322a2 100644 (file)
@@ -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,
 };
 
index 6498fd2b0f6073bad2ca098873b2601262d957c7..b25bc542a22bfc0b0137ef26e89033b0cb0e1cca 100644 (file)
@@ -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
index c4da3f634b92e23ca5ade630b8eb38eb8730b814..34d5baa5d88a003bb22752d51da2744875f81f5a 100644 (file)
@@ -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]);
index 2a616a9f289dae4b301e0998299120b5000f0c9b..93b1077a380a8544dbb5809ec236fc2559a62c1e 100644 (file)
 #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,197 +289,161 @@ 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)
-{
-       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;
-
-       while ((p = strsep(&options, ",")) != NULL) {
-               int token;
-               substring_t args[MAX_OPT_ARGS];
-               unsigned n;
-
-               if (!*p)
-                       continue;
+static const struct constant_table isofs_param_check[] = {
+       {"relaxed",     'r'},
+       {"r",           'r'},
+       {"strict",      's'},
+       {"s",           's'},
+       {}
+};
 
-               token = match_token(p, tokens, args);
-               switch (token) {
-               case Opt_norock:
-                       popt->rock = 0;
-                       break;
-               case Opt_nojoliet:
-                       popt->joliet = 0;
-                       break;
-               case Opt_hide:
-                       popt->hide = 1;
-                       break;
-               case Opt_unhide:
-               case Opt_showassoc:
-                       popt->showassoc = 1;
-                       break;
-               case Opt_cruft:
-                       popt->cruft = 1;
-                       break;
+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)
+{
+       struct isofs_options *popt = fc->fs_private;
+       struct fs_parse_result result;
+       int opt;
+       kuid_t uid;
+       kgid_t gid;
+       unsigned int n;
+
+       /* There are no remountable options */
+       if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE)
+               return 0;
+
+       opt = fs_parse(fc, isofs_param_spec, param, &result);
+       if (opt < 0)
+               return opt;
+
+       switch (opt) {
+       case Opt_norock:
+               popt->rock = 0;
+               break;
+       case Opt_nojoliet:
+               popt->joliet = 0;
+               break;
+       case Opt_hide:
+               popt->hide = 1;
+               break;
+       case Opt_unhide:
+       case Opt_showassoc:
+               popt->showassoc = 1;
+               break;
+       case Opt_cruft:
+               popt->cruft = 1;
+               break;
 #ifdef CONFIG_JOLIET
-               case Opt_utf8:
-                       kfree(popt->iocharset);
-                       popt->iocharset = kstrdup("utf8", GFP_KERNEL);
-                       if (!popt->iocharset)
-                               return 0;
-                       break;
-               case Opt_iocharset:
-                       kfree(popt->iocharset);
-                       popt->iocharset = match_strdup(&args[0]);
-                       if (!popt->iocharset)
-                               return 0;
-                       break;
+       case Opt_utf8:
+               kfree(popt->iocharset);
+               popt->iocharset = kstrdup("utf8", GFP_KERNEL);
+               if (!popt->iocharset)
+                       return -ENOMEM;
+               break;
+       case Opt_iocharset:
+               kfree(popt->iocharset);
+               popt->iocharset = kstrdup(param->string, GFP_KERNEL);
+               if (!popt->iocharset)
+                       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';
-                       break;
-               case Opt_session:
-                       if (match_int(&args[0], &option))
-                               return 0;
-                       n = option;
-                       /*
-                        * Track numbers are supposed to be in range 1-99, the
-                        * mount option starts indexing at 0.
-                        */
-                       if (n >= 99)
-                               return 0;
-                       popt->session = n + 1;
-                       break;
-               case Opt_sb:
-                       if (match_int(&args[0], &option))
-                               return 0;
-                       popt->sbsector = option;
-                       break;
-               case Opt_check_r:
-                       popt->check = 'r';
-                       break;
-               case Opt_check_s:
-                       popt->check = 's';
-                       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;
-                       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;
-                       popt->gid_set = 1;
-                       break;
-               case Opt_mode:
-                       if (match_int(&args[0], &option))
-                               return 0;
-                       popt->fmode = option;
-                       break;
-               case Opt_dmode:
-                       if (match_int(&args[0], &option))
-                               return 0;
-                       popt->dmode = option;
-                       break;
-               case Opt_overriderockperm:
-                       popt->overriderockperm = 1;
-                       break;
-               case Opt_block:
-                       if (match_int(&args[0], &option))
-                               return 0;
-                       n = option;
-                       if (n != 512 && n != 1024 && n != 2048)
-                               return 0;
-                       popt->blocksize = n;
-                       break;
-               case Opt_nocompress:
-                       popt->nocompress = 1;
-                       break;
-               default:
-                       return 0;
-               }
+       case Opt_map:
+               popt->map = result.uint_32;
+               break;
+       case Opt_session:
+               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 -EINVAL;
+               popt->session = n + 1;
+               break;
+       case Opt_sb:
+               popt->sbsector = result.uint_32;
+               break;
+       case Opt_check:
+               popt->check = result.uint_32;
+               break;
+       case Opt_ignore:
+               break;
+       case Opt_uid:
+               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:
+               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:
+               popt->fmode = result.uint_32;
+               break;
+       case Opt_dmode:
+               popt->dmode = result.uint_32;
+               break;
+       case Opt_overriderockperm:
+               popt->overriderockperm = 1;
+               break;
+       case Opt_block:
+               n = result.uint_32;
+               if (n != 512 && n != 1024 && n != 2048)
+                       return -EINVAL;
+               popt->blocksize = n;
+               break;
+       case Opt_nocompress:
+               popt->nocompress = 1;
+               break;
+       default:
+               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 @@ root_found:
                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 @@ root_found:
         * 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 @@ root_found:
 
 #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 @@ root_found:
 #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 @@ root_found:
                }
        }
 
-       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 @@ root_found:
        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 @@ root_found:
                goto out_no_inode;
        }
 
-       kfree(opt.iocharset);
+       kfree(opt->iocharset);
 
        return 0;
 
@@ -1023,7 +985,7 @@ out_bad_zone_size:
        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 @@ out_freebh:
        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");
index dacbee455c034c5463c002d754a94e101d883452..627eb2f72ef376dab2e89168121e03bad9ebc18d 100644 (file)
@@ -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);
-               if (ret)
-                       panic("Cannot create dquot stat counters");
-       }
+       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);
index e2f7a264e3ff07eac4a3a1729706debb7708274a..11e9ecf24b63d6ae1610da3857585739611d1924 100644 (file)
@@ -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.
index 1d825459ee6e62ee5723022833e40e28ccd1adba..c1daedc50f4c2521fac4cf7c4c7102d58387bff5 100644 (file)
@@ -2503,8 +2503,8 @@ out:
  * 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 @@ out:
 }
 
 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,
 };
index 0ceac4b5937c745e3b7c9521f8bfe148d49b93e1..97c59585208ca0903c9879c781bfe6c239b51d41 100644 (file)
@@ -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);
index 2f831a3a91afe38351c5a16bf2e5138fda9e19d1..2fb21c5ffccfe477d85398a74df72005b10cbe6a 100644 (file)
@@ -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;
index 2217f7ed7a495c099eb4f6c12174344945561dc5..9381a66c6ce589d811dd108ade8fad82d3605831 100644 (file)
@@ -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);
 
index f7eaf7b145940ba7bc73abcfa0dd6a9efb1855f5..fe03745d09b181652c5606a079328ab0a1714d8a 100644 (file)
@@ -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;
 }
index 758163af39c2620186158df8cf8f96dc7f331ad8..78ecc633606fb345c69a9981ca135432769d3ed6 100644 (file)
@@ -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