summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/fid.c2
-rw-r--r--fs/Kconfig.binfmt2
-rw-r--r--fs/adfs/inode.c7
-rw-r--r--fs/adfs/super.c2
-rw-r--r--fs/afs/Makefile4
-rw-r--r--fs/afs/addr_list.c2
-rw-r--r--fs/afs/callback.c110
-rw-r--r--fs/afs/cell.c24
-rw-r--r--fs/afs/cmservice.c9
-rw-r--r--fs/afs/dynroot.c126
-rw-r--r--fs/afs/fsclient.c102
-rw-r--r--fs/afs/internal.h75
-rw-r--r--fs/afs/main.c35
-rw-r--r--fs/afs/netdevices.c6
-rw-r--r--fs/afs/proc.c793
-rw-r--r--fs/afs/rxrpc.c2
-rw-r--r--fs/afs/server.c2
-rw-r--r--fs/afs/super.c68
-rw-r--r--fs/aio.c4
-rw-r--r--fs/attr.c14
-rw-r--r--fs/autofs/Kconfig2
-rw-r--r--fs/bad_inode.c2
-rw-r--r--fs/befs/ChangeLog2
-rw-r--r--fs/binfmt_elf.c19
-rw-r--r--fs/binfmt_elf_fdpic.c3
-rw-r--r--fs/binfmt_misc.c2
-rw-r--r--fs/block_dev.c3
-rw-r--r--fs/btrfs/check-integrity.c4
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/extent_io.c4
-rw-r--r--fs/btrfs/file.c6
-rw-r--r--fs/btrfs/inode.c34
-rw-r--r--fs/btrfs/ioctl.c8
-rw-r--r--fs/btrfs/root-tree.c4
-rw-r--r--fs/btrfs/scrub.c2
-rw-r--r--fs/btrfs/transaction.c2
-rw-r--r--fs/ceph/addr.c24
-rw-r--r--fs/ceph/cache.c4
-rw-r--r--fs/ceph/caps.c166
-rw-r--r--fs/ceph/dir.c2
-rw-r--r--fs/ceph/file.c7
-rw-r--r--fs/ceph/inode.c153
-rw-r--r--fs/ceph/mds_client.c12
-rw-r--r--fs/ceph/snap.c6
-rw-r--r--fs/ceph/super.c35
-rw-r--r--fs/ceph/xattr.c60
-rw-r--r--fs/cifs/asn1.c2
-rw-r--r--fs/cifs/cache.c4
-rw-r--r--fs/cifs/cifsacl.c4
-rw-r--r--fs/cifs/cifssmb.c2
-rw-r--r--fs/cifs/file.c2
-rw-r--r--fs/cifs/fscache.c8
-rw-r--r--fs/cifs/inode.c28
-rw-r--r--fs/cifs/misc.c4
-rw-r--r--fs/cifs/smb2pdu.c6
-rw-r--r--fs/cifs/transport.c8
-rw-r--r--fs/coda/coda_linux.c12
-rw-r--r--fs/configfs/inode.c12
-rw-r--r--fs/cramfs/inode.c2
-rw-r--r--fs/debugfs/inode.c4
-rw-r--r--fs/dlm/lockspace.c2
-rw-r--r--fs/eventfd.c4
-rw-r--r--fs/eventpoll.c15
-rw-r--r--fs/exofs/inode.c4
-rw-r--r--fs/exofs/ore.c84
-rw-r--r--fs/exofs/ore_raid.c75
-rw-r--r--fs/exofs/super.c23
-rw-r--r--fs/ext2/super.c4
-rw-r--r--fs/ext4/ext4.h34
-rw-r--r--fs/ext4/extents.c8
-rw-r--r--fs/ext4/ialloc.c4
-rw-r--r--fs/ext4/namei.c2
-rw-r--r--fs/ext4/resize.c10
-rw-r--r--fs/ext4/super.c6
-rw-r--r--fs/f2fs/checkpoint.c3
-rw-r--r--fs/f2fs/f2fs.h10
-rw-r--r--fs/f2fs/file.c18
-rw-r--r--fs/f2fs/inode.c12
-rw-r--r--fs/f2fs/namei.c4
-rw-r--r--fs/f2fs/node.c12
-rw-r--r--fs/f2fs/segment.c15
-rw-r--r--fs/f2fs/super.c20
-rw-r--r--fs/fat/inode.c28
-rw-r--r--fs/fat/namei_msdos.c21
-rw-r--r--fs/fat/namei_vfat.c24
-rw-r--r--fs/fuse/dev.c15
-rw-r--r--fs/fuse/inode.c2
-rw-r--r--fs/gfs2/dir.c12
-rw-r--r--fs/gfs2/glock.c3
-rw-r--r--fs/gfs2/glops.c4
-rw-r--r--fs/gfs2/quota.c2
-rw-r--r--fs/gfs2/rgrp.c5
-rw-r--r--fs/gfs2/super.c2
-rw-r--r--fs/hfs/inode.c4
-rw-r--r--fs/hfsplus/inode.c12
-rw-r--r--fs/hostfs/hostfs_kern.c12
-rw-r--r--fs/hpfs/dnode.c3
-rw-r--r--fs/hpfs/map.c2
-rw-r--r--fs/inode.c58
-rw-r--r--fs/iomap.c6
-rw-r--r--fs/jbd2/revoke.c2
-rw-r--r--fs/jffs2/acl.c3
-rw-r--r--fs/jffs2/acl.h1
-rw-r--r--fs/jffs2/dir.c18
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jffs2/fs.c12
-rw-r--r--fs/jffs2/wbuf.c2
-rw-r--r--fs/jfs/jfs_dmap.c2
-rw-r--r--fs/jfs/jfs_dtree.c9
-rw-r--r--fs/jfs/jfs_unicode.c2
-rw-r--r--fs/kernfs/dir.c4
-rw-r--r--fs/kernfs/inode.c8
-rw-r--r--fs/locks.c2
-rw-r--r--fs/mbcache.c5
-rw-r--r--fs/namei.c33
-rw-r--r--fs/nfs/callback_proc.c47
-rw-r--r--fs/nfs/client.c3
-rw-r--r--fs/nfs/delegation.c86
-rw-r--r--fs/nfs/dir.c51
-rw-r--r--fs/nfs/export.c2
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c3
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayoutdev.c3
-rw-r--r--fs/nfs/fscache-index.c4
-rw-r--r--fs/nfs/fscache.c12
-rw-r--r--fs/nfs/inode.c165
-rw-r--r--fs/nfs/nfs2xdr.c25
-rw-r--r--fs/nfs/nfs3proc.c13
-rw-r--r--fs/nfs/nfs3xdr.c8
-rw-r--r--fs/nfs/nfs42proc.c6
-rw-r--r--fs/nfs/nfs4_fs.h27
-rw-r--r--fs/nfs/nfs4idmap.c5
-rw-r--r--fs/nfs/nfs4proc.c391
-rw-r--r--fs/nfs/nfs4state.c8
-rw-r--r--fs/nfs/nfs4xdr.c72
-rw-r--r--fs/nfs/pnfs.c331
-rw-r--r--fs/nfs/pnfs.h28
-rw-r--r--fs/nfs/proc.c13
-rw-r--r--fs/nfs/unlink.c20
-rw-r--r--fs/nfs/write.c10
-rw-r--r--fs/nfsd/blocklayout.c26
-rw-r--r--fs/nfsd/cache.h5
-rw-r--r--fs/nfsd/export.c5
-rw-r--r--fs/nfsd/nfs3xdr.c14
-rw-r--r--fs/nfsd/nfs4recover.c5
-rw-r--r--fs/nfsd/nfs4state.c25
-rw-r--r--fs/nfsd/nfs4xdr.c14
-rw-r--r--fs/nfsd/nfscache.c9
-rw-r--r--fs/nfsd/nfsxdr.c2
-rw-r--r--fs/notify/dnotify/dnotify.c8
-rw-r--r--fs/notify/fanotify/fanotify.c46
-rw-r--r--fs/notify/fdinfo.c6
-rw-r--r--fs/notify/fsnotify.c138
-rw-r--r--fs/notify/fsnotify.h6
-rw-r--r--fs/notify/group.c2
-rw-r--r--fs/notify/inotify/inotify.h2
-rw-r--r--fs/notify/inotify/inotify_fsnotify.c6
-rw-r--r--fs/notify/inotify/inotify_user.c10
-rw-r--r--fs/notify/mark.c52
-rw-r--r--fs/ntfs/compress.c2
-rw-r--r--fs/ntfs/inode.c30
-rw-r--r--fs/ocfs2/cluster/tcp.c2
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c2
-rw-r--r--fs/ocfs2/dlmglue.c20
-rw-r--r--fs/ocfs2/file.c6
-rw-r--r--fs/ocfs2/journal.c2
-rw-r--r--fs/ocfs2/sysfile.c9
-rw-r--r--fs/orangefs/devorangefs-req.c54
-rw-r--r--fs/orangefs/inode.c2
-rw-r--r--fs/orangefs/orangefs-kernel.h2
-rw-r--r--fs/orangefs/orangefs-sysfs.c2
-rw-r--r--fs/overlayfs/inode.c2
-rw-r--r--fs/overlayfs/namei.c2
-rw-r--r--fs/overlayfs/overlayfs.h2
-rw-r--r--fs/proc/base.c12
-rw-r--r--fs/proc/generic.c26
-rw-r--r--fs/proc/inode.c5
-rw-r--r--fs/proc/internal.h20
-rw-r--r--fs/proc/proc_net.c92
-rw-r--r--fs/proc/proc_sysctl.c2
-rw-r--r--fs/proc/root.c3
-rw-r--r--fs/proc/task_mmu.c2
-rw-r--r--fs/proc/uptime.c2
-rw-r--r--fs/pstore/platform.c2
-rw-r--r--fs/pstore/ram.c18
-rw-r--r--fs/read_write.c4
-rw-r--r--fs/reiserfs/bitmap.c2
-rw-r--r--fs/reiserfs/inode.c3
-rw-r--r--fs/reiserfs/journal.c13
-rw-r--r--fs/reiserfs/namei.c2
-rw-r--r--fs/reiserfs/resize.c3
-rw-r--r--fs/reiserfs/xattr.c4
-rw-r--r--fs/select.c2
-rw-r--r--fs/signalfd.c50
-rw-r--r--fs/splice.c151
-rw-r--r--fs/ubifs/dir.c4
-rw-r--r--fs/ubifs/file.c23
-rw-r--r--fs/ubifs/journal.c5
-rw-r--r--fs/ubifs/lpt.c25
-rw-r--r--fs/ubifs/super.c3
-rw-r--r--fs/ubifs/tnc.c5
-rw-r--r--fs/ubifs/tnc_commit.c5
-rw-r--r--fs/ubifs/ubifs.h2
-rw-r--r--fs/udf/ialloc.c4
-rw-r--r--fs/udf/inode.c59
-rw-r--r--fs/udf/super.c24
-rw-r--r--fs/udf/udfdecl.h4
-rw-r--r--fs/udf/udftime.c9
-rw-r--r--fs/ufs/super.c4
-rw-r--r--fs/xfs/Makefile15
-rw-r--r--fs/xfs/kmem.c14
-rw-r--r--fs/xfs/kmem.h14
-rw-r--r--fs/xfs/libxfs/xfs_ag_resv.c16
-rw-r--r--fs/xfs/libxfs/xfs_ag_resv.h16
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c95
-rw-r--r--fs/xfs/libxfs/xfs_alloc.h18
-rw-r--r--fs/xfs/libxfs/xfs_alloc_btree.c15
-rw-r--r--fs/xfs/libxfs/xfs_alloc_btree.h14
-rw-r--r--fs/xfs/libxfs/xfs_attr.c14
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.c21
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.h14
-rw-r--r--fs/xfs/libxfs/xfs_attr_remote.c14
-rw-r--r--fs/xfs/libxfs/xfs_attr_remote.h14
-rw-r--r--fs/xfs/libxfs/xfs_attr_sf.h14
-rw-r--r--fs/xfs/libxfs/xfs_bit.c14
-rw-r--r--fs/xfs/libxfs/xfs_bit.h14
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c54
-rw-r--r--fs/xfs/libxfs/xfs_bmap.h14
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.c14
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.h14
-rw-r--r--fs/xfs/libxfs/xfs_btree.c171
-rw-r--r--fs/xfs/libxfs/xfs_btree.h14
-rw-r--r--fs/xfs/libxfs/xfs_da_btree.c24
-rw-r--r--fs/xfs/libxfs/xfs_da_btree.h14
-rw-r--r--fs/xfs/libxfs/xfs_da_format.c14
-rw-r--r--fs/xfs/libxfs/xfs_da_format.h14
-rw-r--r--fs/xfs/libxfs/xfs_defer.c16
-rw-r--r--fs/xfs/libxfs/xfs_defer.h16
-rw-r--r--fs/xfs/libxfs/xfs_dir2.c14
-rw-r--r--fs/xfs/libxfs/xfs_dir2.h14
-rw-r--r--fs/xfs/libxfs/xfs_dir2_block.c22
-rw-r--r--fs/xfs/libxfs/xfs_dir2_data.c122
-rw-r--r--fs/xfs/libxfs/xfs_dir2_leaf.c26
-rw-r--r--fs/xfs/libxfs/xfs_dir2_node.c17
-rw-r--r--fs/xfs/libxfs/xfs_dir2_priv.h14
-rw-r--r--fs/xfs/libxfs/xfs_dir2_sf.c14
-rw-r--r--fs/xfs/libxfs/xfs_dquot_buf.c14
-rw-r--r--fs/xfs/libxfs/xfs_errortag.h15
-rw-r--r--fs/xfs/libxfs/xfs_format.h14
-rw-r--r--fs/xfs/libxfs/xfs_fs.h14
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c160
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.h21
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.c14
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.h14
-rw-r--r--fs/xfs/libxfs/xfs_iext_tree.c10
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.c34
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.h14
-rw-r--r--fs/xfs/libxfs/xfs_inode_fork.c14
-rw-r--r--fs/xfs/libxfs/xfs_inode_fork.h14
-rw-r--r--fs/xfs/libxfs/xfs_log_format.h14
-rw-r--r--fs/xfs/libxfs/xfs_log_recover.h14
-rw-r--r--fs/xfs/libxfs/xfs_log_rlimit.c14
-rw-r--r--fs/xfs/libxfs/xfs_quota_defs.h14
-rw-r--r--fs/xfs/libxfs/xfs_refcount.c63
-rw-r--r--fs/xfs/libxfs/xfs_refcount.h16
-rw-r--r--fs/xfs/libxfs/xfs_refcount_btree.c17
-rw-r--r--fs/xfs/libxfs/xfs_refcount_btree.h16
-rw-r--r--fs/xfs/libxfs/xfs_rmap.c55
-rw-r--r--fs/xfs/libxfs/xfs_rmap.h16
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.c15
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.h14
-rw-r--r--fs/xfs/libxfs/xfs_rtbitmap.c26
-rw-r--r--fs/xfs/libxfs/xfs_sb.c40
-rw-r--r--fs/xfs/libxfs/xfs_sb.h14
-rw-r--r--fs/xfs/libxfs/xfs_shared.h14
-rw-r--r--fs/xfs/libxfs/xfs_symlink_remote.c14
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.c30
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.h14
-rw-r--r--fs/xfs/libxfs/xfs_trans_space.h14
-rw-r--r--fs/xfs/libxfs/xfs_types.c173
-rw-r--r--fs/xfs/libxfs/xfs_types.h33
-rw-r--r--fs/xfs/mrlock.h14
-rw-r--r--fs/xfs/scrub/agheader.c18
-rw-r--r--fs/xfs/scrub/agheader_repair.c16
-rw-r--r--fs/xfs/scrub/alloc.c16
-rw-r--r--fs/xfs/scrub/attr.c16
-rw-r--r--fs/xfs/scrub/bmap.c16
-rw-r--r--fs/xfs/scrub/btree.c16
-rw-r--r--fs/xfs/scrub/btree.h16
-rw-r--r--fs/xfs/scrub/common.c16
-rw-r--r--fs/xfs/scrub/common.h16
-rw-r--r--fs/xfs/scrub/dabtree.c16
-rw-r--r--fs/xfs/scrub/dabtree.h16
-rw-r--r--fs/xfs/scrub/dir.c16
-rw-r--r--fs/xfs/scrub/ialloc.c16
-rw-r--r--fs/xfs/scrub/inode.c16
-rw-r--r--fs/xfs/scrub/parent.c16
-rw-r--r--fs/xfs/scrub/quota.c16
-rw-r--r--fs/xfs/scrub/refcount.c16
-rw-r--r--fs/xfs/scrub/repair.c16
-rw-r--r--fs/xfs/scrub/repair.h16
-rw-r--r--fs/xfs/scrub/rmap.c16
-rw-r--r--fs/xfs/scrub/rtbitmap.c16
-rw-r--r--fs/xfs/scrub/scrub.c16
-rw-r--r--fs/xfs/scrub/scrub.h16
-rw-r--r--fs/xfs/scrub/symlink.c16
-rw-r--r--fs/xfs/scrub/trace.c16
-rw-r--r--fs/xfs/scrub/trace.h16
-rw-r--r--fs/xfs/scrub/xfs_scrub.h16
-rw-r--r--fs/xfs/xfs.h14
-rw-r--r--fs/xfs/xfs_acl.c14
-rw-r--r--fs/xfs/xfs_acl.h14
-rw-r--r--fs/xfs/xfs_aops.c25
-rw-r--r--fs/xfs/xfs_aops.h14
-rw-r--r--fs/xfs/xfs_attr.h14
-rw-r--r--fs/xfs/xfs_attr_inactive.c14
-rw-r--r--fs/xfs/xfs_attr_list.c19
-rw-r--r--fs/xfs/xfs_bmap_item.c16
-rw-r--r--fs/xfs/xfs_bmap_item.h16
-rw-r--r--fs/xfs/xfs_bmap_util.c26
-rw-r--r--fs/xfs/xfs_bmap_util.h14
-rw-r--r--fs/xfs/xfs_buf.c15
-rw-r--r--fs/xfs/xfs_buf.h14
-rw-r--r--fs/xfs/xfs_buf_item.c16
-rw-r--r--fs/xfs/xfs_buf_item.h14
-rw-r--r--fs/xfs/xfs_dir2_readdir.c14
-rw-r--r--fs/xfs/xfs_discard.c14
-rw-r--r--fs/xfs/xfs_dquot.c14
-rw-r--r--fs/xfs/xfs_dquot.h14
-rw-r--r--fs/xfs/xfs_dquot_item.c14
-rw-r--r--fs/xfs/xfs_dquot_item.h14
-rw-r--r--fs/xfs/xfs_error.c19
-rw-r--r--fs/xfs/xfs_error.h23
-rw-r--r--fs/xfs/xfs_export.c29
-rw-r--r--fs/xfs/xfs_export.h14
-rw-r--r--fs/xfs/xfs_extent_busy.c14
-rw-r--r--fs/xfs/xfs_extent_busy.h14
-rw-r--r--fs/xfs/xfs_extfree_item.c14
-rw-r--r--fs/xfs/xfs_extfree_item.h14
-rw-r--r--fs/xfs/xfs_file.c14
-rw-r--r--fs/xfs/xfs_filestream.c14
-rw-r--r--fs/xfs/xfs_filestream.h14
-rw-r--r--fs/xfs/xfs_fsmap.c16
-rw-r--r--fs/xfs/xfs_fsmap.h16
-rw-r--r--fs/xfs/xfs_fsops.c14
-rw-r--r--fs/xfs/xfs_fsops.h14
-rw-r--r--fs/xfs/xfs_globals.c14
-rw-r--r--fs/xfs/xfs_icache.c14
-rw-r--r--fs/xfs/xfs_icache.h14
-rw-r--r--fs/xfs/xfs_icreate_item.c14
-rw-r--r--fs/xfs/xfs_icreate_item.h14
-rw-r--r--fs/xfs/xfs_inode.c37
-rw-r--r--fs/xfs/xfs_inode.h14
-rw-r--r--fs/xfs/xfs_inode_item.c14
-rw-r--r--fs/xfs/xfs_inode_item.h14
-rw-r--r--fs/xfs/xfs_ioctl.c33
-rw-r--r--fs/xfs/xfs_ioctl.h14
-rw-r--r--fs/xfs/xfs_ioctl32.c14
-rw-r--r--fs/xfs/xfs_ioctl32.h14
-rw-r--r--fs/xfs/xfs_iomap.c20
-rw-r--r--fs/xfs/xfs_iomap.h18
-rw-r--r--fs/xfs/xfs_iops.c24
-rw-r--r--fs/xfs/xfs_iops.h14
-rw-r--r--fs/xfs/xfs_itable.c16
-rw-r--r--fs/xfs/xfs_itable.h14
-rw-r--r--fs/xfs/xfs_linux.h36
-rw-r--r--fs/xfs/xfs_log.c18
-rw-r--r--fs/xfs/xfs_log.h14
-rw-r--r--fs/xfs/xfs_log_cil.c14
-rw-r--r--fs/xfs/xfs_log_priv.h14
-rw-r--r--fs/xfs/xfs_log_recover.c67
-rw-r--r--fs/xfs/xfs_message.c14
-rw-r--r--fs/xfs/xfs_mount.c21
-rw-r--r--fs/xfs/xfs_mount.h16
-rw-r--r--fs/xfs/xfs_mru_cache.c14
-rw-r--r--fs/xfs/xfs_mru_cache.h14
-rw-r--r--fs/xfs/xfs_ondisk.h14
-rw-r--r--fs/xfs/xfs_qm.c14
-rw-r--r--fs/xfs/xfs_qm.h14
-rw-r--r--fs/xfs/xfs_qm_bhv.c14
-rw-r--r--fs/xfs/xfs_qm_syscalls.c14
-rw-r--r--fs/xfs/xfs_quota.h14
-rw-r--r--fs/xfs/xfs_quotaops.c14
-rw-r--r--fs/xfs/xfs_refcount_item.c16
-rw-r--r--fs/xfs/xfs_refcount_item.h16
-rw-r--r--fs/xfs/xfs_reflink.c16
-rw-r--r--fs/xfs/xfs_reflink.h16
-rw-r--r--fs/xfs/xfs_rmap_item.c16
-rw-r--r--fs/xfs/xfs_rmap_item.h16
-rw-r--r--fs/xfs/xfs_rtalloc.c24
-rw-r--r--fs/xfs/xfs_rtalloc.h14
-rw-r--r--fs/xfs/xfs_stats.c14
-rw-r--r--fs/xfs/xfs_stats.h14
-rw-r--r--fs/xfs/xfs_super.c16
-rw-r--r--fs/xfs/xfs_super.h14
-rw-r--r--fs/xfs/xfs_symlink.c14
-rw-r--r--fs/xfs/xfs_symlink.h14
-rw-r--r--fs/xfs/xfs_sysctl.c14
-rw-r--r--fs/xfs/xfs_sysctl.h14
-rw-r--r--fs/xfs/xfs_sysfs.c14
-rw-r--r--fs/xfs/xfs_sysfs.h14
-rw-r--r--fs/xfs/xfs_trace.c14
-rw-r--r--fs/xfs/xfs_trace.h14
-rw-r--r--fs/xfs/xfs_trans.c14
-rw-r--r--fs/xfs/xfs_trans.h14
-rw-r--r--fs/xfs/xfs_trans_ail.c14
-rw-r--r--fs/xfs/xfs_trans_bmap.c16
-rw-r--r--fs/xfs/xfs_trans_buf.c14
-rw-r--r--fs/xfs/xfs_trans_dquot.c14
-rw-r--r--fs/xfs/xfs_trans_extfree.c14
-rw-r--r--fs/xfs/xfs_trans_inode.c16
-rw-r--r--fs/xfs/xfs_trans_priv.h14
-rw-r--r--fs/xfs/xfs_trans_refcount.c16
-rw-r--r--fs/xfs/xfs_trans_rmap.c16
-rw-r--r--fs/xfs/xfs_xattr.c14
414 files changed, 4052 insertions, 5273 deletions
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index ed4f8519b627..a9ef46f02354 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -100,7 +100,7 @@ static int build_path_from_dentry(struct v9fs_session_info *v9ses,
for (ds = dentry; !IS_ROOT(ds); ds = ds->d_parent)
n++;
- wnames = kmalloc(sizeof(char *) * n, GFP_KERNEL);
+ wnames = kmalloc_array(n, sizeof(char *), GFP_KERNEL);
if (!wnames)
goto err_out;
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index 57a27c42b5ac..56df483de619 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -168,7 +168,7 @@ config BINFMT_MISC
will automatically feed it to the correct interpreter.
You can do other nice things, too. Read the file
- <file:Documentation/binfmt_misc.txt> to learn how to use this
+ <file:Documentation/admin-guide/binfmt-misc.rst> to learn how to use this
feature, <file:Documentation/admin-guide/java.rst> for information about how
to include Java support. and <file:Documentation/admin-guide/mono.rst> for
information about how to include Mono-based .NET support.
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index 8dbd36f5e581..c836c425ca94 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -199,7 +199,7 @@ adfs_adfs2unix_time(struct timespec *tv, struct inode *inode)
return;
cur_time:
- *tv = current_time(inode);
+ *tv = timespec64_to_timespec(current_time(inode));
return;
too_early:
@@ -242,6 +242,7 @@ adfs_unix2adfs_time(struct inode *inode, unsigned int secs)
struct inode *
adfs_iget(struct super_block *sb, struct object_info *obj)
{
+ struct timespec ts;
struct inode *inode;
inode = new_inode(sb);
@@ -270,7 +271,9 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
ADFS_I(inode)->stamped = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
inode->i_mode = adfs_atts2mode(sb, inode);
- adfs_adfs2unix_time(&inode->i_mtime, inode);
+ ts = timespec64_to_timespec(inode->i_mtime);
+ adfs_adfs2unix_time(&ts, inode);
+ inode->i_mtime = timespec_to_timespec64(ts);
inode->i_atime = inode->i_mtime;
inode->i_ctime = inode->i_mtime;
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index cfda2c7caedc..71fa525d63a0 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -313,7 +313,7 @@ static struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_di
asb->s_ids_per_zone = zone_size / (asb->s_idlen + 1);
- dm = kmalloc(nzones * sizeof(*dm), GFP_KERNEL);
+ dm = kmalloc_array(nzones, sizeof(*dm), GFP_KERNEL);
if (dm == NULL) {
adfs_error(sb, "not enough memory");
return ERR_PTR(-ENOMEM);
diff --git a/fs/afs/Makefile b/fs/afs/Makefile
index 532acae25453..546874057bd3 100644
--- a/fs/afs/Makefile
+++ b/fs/afs/Makefile
@@ -5,7 +5,7 @@
afs-cache-$(CONFIG_AFS_FSCACHE) := cache.o
-kafs-objs := \
+kafs-y := \
$(afs-cache-y) \
addr_list.o \
callback.o \
@@ -21,7 +21,6 @@ kafs-objs := \
main.o \
misc.o \
mntpt.o \
- proc.o \
rotate.o \
rxrpc.o \
security.o \
@@ -34,4 +33,5 @@ kafs-objs := \
write.o \
xattr.o
+kafs-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_AFS_FS) := kafs.o
diff --git a/fs/afs/addr_list.c b/fs/afs/addr_list.c
index 2c46c46f3a6d..025a9a5e1c32 100644
--- a/fs/afs/addr_list.c
+++ b/fs/afs/addr_list.c
@@ -215,7 +215,7 @@ struct afs_addr_list *afs_dns_query(struct afs_cell *cell, time64_t *_expiry)
_enter("%s", cell->name);
ret = dns_query("afsdb", cell->name, cell->name_len,
- "ipv4", &vllist, _expiry);
+ "", &vllist, _expiry);
if (ret < 0)
return ERR_PTR(ret);
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index 571437dcb252..5f261fbf2182 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -21,6 +21,66 @@
#include "internal.h"
/*
+ * Create volume and callback interests on a server.
+ */
+static struct afs_cb_interest *afs_create_interest(struct afs_server *server,
+ struct afs_vnode *vnode)
+{
+ struct afs_vol_interest *new_vi, *vi;
+ struct afs_cb_interest *new;
+ struct hlist_node **pp;
+
+ new_vi = kzalloc(sizeof(struct afs_vol_interest), GFP_KERNEL);
+ if (!new_vi)
+ return NULL;
+
+ new = kzalloc(sizeof(struct afs_cb_interest), GFP_KERNEL);
+ if (!new) {
+ kfree(new_vi);
+ return NULL;
+ }
+
+ new_vi->usage = 1;
+ new_vi->vid = vnode->volume->vid;
+ INIT_HLIST_NODE(&new_vi->srv_link);
+ INIT_HLIST_HEAD(&new_vi->cb_interests);
+
+ refcount_set(&new->usage, 1);
+ new->sb = vnode->vfs_inode.i_sb;
+ new->vid = vnode->volume->vid;
+ new->server = afs_get_server(server);
+ INIT_HLIST_NODE(&new->cb_vlink);
+
+ write_lock(&server->cb_break_lock);
+
+ for (pp = &server->cb_volumes.first; *pp; pp = &(*pp)->next) {
+ vi = hlist_entry(*pp, struct afs_vol_interest, srv_link);
+ if (vi->vid < new_vi->vid)
+ continue;
+ if (vi->vid > new_vi->vid)
+ break;
+ vi->usage++;
+ goto found_vi;
+ }
+
+ new_vi->srv_link.pprev = pp;
+ new_vi->srv_link.next = *pp;
+ if (*pp)
+ (*pp)->pprev = &new_vi->srv_link.next;
+ *pp = &new_vi->srv_link;
+ vi = new_vi;
+ new_vi = NULL;
+found_vi:
+
+ new->vol_interest = vi;
+ hlist_add_head(&new->cb_vlink, &vi->cb_interests);
+
+ write_unlock(&server->cb_break_lock);
+ kfree(new_vi);
+ return new;
+}
+
+/*
* Set up an interest-in-callbacks record for a volume on a server and
* register it with the server.
* - Called with vnode->io_lock held.
@@ -77,20 +137,10 @@ again:
}
if (!cbi) {
- new = kzalloc(sizeof(struct afs_cb_interest), GFP_KERNEL);
+ new = afs_create_interest(server, vnode);
if (!new)
return -ENOMEM;
- refcount_set(&new->usage, 1);
- new->sb = vnode->vfs_inode.i_sb;
- new->vid = vnode->volume->vid;
- new->server = afs_get_server(server);
- INIT_LIST_HEAD(&new->cb_link);
-
- write_lock(&server->cb_break_lock);
- list_add_tail(&new->cb_link, &server->cb_interests);
- write_unlock(&server->cb_break_lock);
-
write_lock(&slist->lock);
if (!entry->cb_interest) {
entry->cb_interest = afs_get_cb_interest(new);
@@ -126,11 +176,22 @@ again:
*/
void afs_put_cb_interest(struct afs_net *net, struct afs_cb_interest *cbi)
{
+ struct afs_vol_interest *vi;
+
if (cbi && refcount_dec_and_test(&cbi->usage)) {
- if (!list_empty(&cbi->cb_link)) {
+ if (!hlist_unhashed(&cbi->cb_vlink)) {
write_lock(&cbi->server->cb_break_lock);
- list_del_init(&cbi->cb_link);
+
+ hlist_del_init(&cbi->cb_vlink);
+ vi = cbi->vol_interest;
+ cbi->vol_interest = NULL;
+ if (--vi->usage == 0)
+ hlist_del(&vi->srv_link);
+ else
+ vi = NULL;
+
write_unlock(&cbi->server->cb_break_lock);
+ kfree(vi);
afs_put_server(net, cbi->server);
}
kfree(cbi);
@@ -182,20 +243,34 @@ void afs_break_callback(struct afs_vnode *vnode)
static void afs_break_one_callback(struct afs_server *server,
struct afs_fid *fid)
{
+ struct afs_vol_interest *vi;
struct afs_cb_interest *cbi;
struct afs_iget_data data;
struct afs_vnode *vnode;
struct inode *inode;
read_lock(&server->cb_break_lock);
+ hlist_for_each_entry(vi, &server->cb_volumes, srv_link) {
+ if (vi->vid < fid->vid)
+ continue;
+ if (vi->vid > fid->vid) {
+ vi = NULL;
+ break;
+ }
+ //atomic_inc(&vi->usage);
+ break;
+ }
+
+ /* TODO: Find all matching volumes if we couldn't match the server and
+ * break them anyway.
+ */
+ if (!vi)
+ goto out;
/* Step through all interested superblocks. There may be more than one
* because of cell aliasing.
*/
- list_for_each_entry(cbi, &server->cb_interests, cb_link) {
- if (cbi->vid != fid->vid)
- continue;
-
+ hlist_for_each_entry(cbi, &vi->cb_interests, cb_vlink) {
if (fid->vnode == 0 && fid->unique == 0) {
/* The callback break applies to an entire volume. */
struct afs_super_info *as = AFS_FS_S(cbi->sb);
@@ -217,6 +292,7 @@ static void afs_break_one_callback(struct afs_server *server,
}
}
+out:
read_unlock(&server->cb_break_lock);
}
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index fdf4c36cff79..f3d0bef16d78 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -15,6 +15,7 @@
#include <linux/dns_resolver.h>
#include <linux/sched.h>
#include <linux/inet.h>
+#include <linux/namei.h>
#include <keys/rxrpc-type.h>
#include "internal.h"
@@ -341,8 +342,8 @@ int afs_cell_init(struct afs_net *net, const char *rootcell)
/* install the new cell */
write_seqlock(&net->cells_lock);
- old_root = net->ws_cell;
- net->ws_cell = new_root;
+ old_root = rcu_access_pointer(net->ws_cell);
+ rcu_assign_pointer(net->ws_cell, new_root);
write_sequnlock(&net->cells_lock);
afs_put_cell(net, old_root);
@@ -528,12 +529,14 @@ static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell)
NULL, 0,
cell, 0, true);
#endif
- ret = afs_proc_cell_setup(net, cell);
+ ret = afs_proc_cell_setup(cell);
if (ret < 0)
return ret;
- spin_lock(&net->proc_cells_lock);
+
+ mutex_lock(&net->proc_cells_lock);
list_add_tail(&cell->proc_link, &net->proc_cells);
- spin_unlock(&net->proc_cells_lock);
+ afs_dynroot_mkdir(net, cell);
+ mutex_unlock(&net->proc_cells_lock);
return 0;
}
@@ -544,11 +547,12 @@ static void afs_deactivate_cell(struct afs_net *net, struct afs_cell *cell)
{
_enter("%s", cell->name);
- afs_proc_cell_remove(net, cell);
+ afs_proc_cell_remove(cell);
- spin_lock(&net->proc_cells_lock);
+ mutex_lock(&net->proc_cells_lock);
list_del_init(&cell->proc_link);
- spin_unlock(&net->proc_cells_lock);
+ afs_dynroot_rmdir(net, cell);
+ mutex_unlock(&net->proc_cells_lock);
#ifdef CONFIG_AFS_FSCACHE
fscache_relinquish_cookie(cell->cache, NULL, false);
@@ -755,8 +759,8 @@ void afs_cell_purge(struct afs_net *net)
_enter("");
write_seqlock(&net->cells_lock);
- ws = net->ws_cell;
- net->ws_cell = NULL;
+ ws = rcu_access_pointer(net->ws_cell);
+ RCU_INIT_POINTER(net->ws_cell, NULL);
write_sequnlock(&net->cells_lock);
afs_put_cell(net, ws);
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index c332c95a6940..9e51d6fe7e8f 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -191,7 +191,8 @@ static int afs_deliver_cb_callback(struct afs_call *call)
if (call->count > AFSCBMAX)
return afs_protocol_error(call, -EBADMSG);
- call->buffer = kmalloc(call->count * 3 * 4, GFP_KERNEL);
+ call->buffer = kmalloc(array3_size(call->count, 3, 4),
+ GFP_KERNEL);
if (!call->buffer)
return -ENOMEM;
call->offset = 0;
@@ -330,7 +331,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
switch (call->unmarshall) {
case 0:
call->offset = 0;
- call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL);
+ call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
if (!call->buffer)
return -ENOMEM;
call->unmarshall++;
@@ -453,7 +454,7 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call)
switch (call->unmarshall) {
case 0:
call->offset = 0;
- call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL);
+ call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
if (!call->buffer)
return -ENOMEM;
call->unmarshall++;
@@ -525,7 +526,7 @@ static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
nifs = 0;
ifs = kcalloc(32, sizeof(*ifs), GFP_KERNEL);
if (ifs) {
- nifs = afs_get_ipv4_interfaces(ifs, 32, false);
+ nifs = afs_get_ipv4_interfaces(call->net, ifs, 32, false);
if (nifs < 0) {
kfree(ifs);
ifs = NULL;
diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c
index 983f3946ab57..174e843f0633 100644
--- a/fs/afs/dynroot.c
+++ b/fs/afs/dynroot.c
@@ -1,4 +1,4 @@
-/* dir.c: AFS dynamic root handling
+/* AFS dynamic root handling
*
* Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
@@ -46,7 +46,7 @@ static int afs_probe_cell_name(struct dentry *dentry)
return 0;
}
- ret = dns_query("afsdb", name, len, "ipv4", NULL, NULL);
+ ret = dns_query("afsdb", name, len, "", NULL, NULL);
if (ret == -ENODATA)
ret = -EDESTADDRREQ;
return ret;
@@ -207,3 +207,125 @@ const struct dentry_operations afs_dynroot_dentry_operations = {
.d_release = afs_d_release,
.d_automount = afs_d_automount,
};
+
+/*
+ * Create a manually added cell mount directory.
+ * - The caller must hold net->proc_cells_lock
+ */
+int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell)
+{
+ struct super_block *sb = net->dynroot_sb;
+ struct dentry *root, *subdir;
+ int ret;
+
+ if (!sb || atomic_read(&sb->s_active) == 0)
+ return 0;
+
+ /* Let the ->lookup op do the creation */
+ root = sb->s_root;
+ inode_lock(root->d_inode);
+ subdir = lookup_one_len(cell->name, root, cell->name_len);
+ if (IS_ERR(subdir)) {
+ ret = PTR_ERR(subdir);
+ goto unlock;
+ }
+
+ /* Note that we're retaining an extra ref on the dentry */
+ subdir->d_fsdata = (void *)1UL;
+ ret = 0;
+unlock:
+ inode_unlock(root->d_inode);
+ return ret;
+}
+
+/*
+ * Remove a manually added cell mount directory.
+ * - The caller must hold net->proc_cells_lock
+ */
+void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell)
+{
+ struct super_block *sb = net->dynroot_sb;
+ struct dentry *root, *subdir;
+
+ if (!sb || atomic_read(&sb->s_active) == 0)
+ return;
+
+ root = sb->s_root;
+ inode_lock(root->d_inode);
+
+ /* Don't want to trigger a lookup call, which will re-add the cell */
+ subdir = try_lookup_one_len(cell->name, root, cell->name_len);
+ if (IS_ERR_OR_NULL(subdir)) {
+ _debug("lookup %ld", PTR_ERR(subdir));
+ goto no_dentry;
+ }
+
+ _debug("rmdir %pd %u", subdir, d_count(subdir));
+
+ if (subdir->d_fsdata) {
+ _debug("unpin %u", d_count(subdir));
+ subdir->d_fsdata = NULL;
+ dput(subdir);
+ }
+ dput(subdir);
+no_dentry:
+ inode_unlock(root->d_inode);
+ _leave("");
+}
+
+/*
+ * Populate a newly created dynamic root with cell names.
+ */
+int afs_dynroot_populate(struct super_block *sb)
+{
+ struct afs_cell *cell;
+ struct afs_net *net = afs_sb2net(sb);
+ int ret;
+
+ if (mutex_lock_interruptible(&net->proc_cells_lock) < 0)
+ return -ERESTARTSYS;
+
+ net->dynroot_sb = sb;
+ list_for_each_entry(cell, &net->proc_cells, proc_link) {
+ ret = afs_dynroot_mkdir(net, cell);
+ if (ret < 0)
+ goto error;
+ }
+
+ ret = 0;
+out:
+ mutex_unlock(&net->proc_cells_lock);
+ return ret;
+
+error:
+ net->dynroot_sb = NULL;
+ goto out;
+}
+
+/*
+ * When a dynamic root that's in the process of being destroyed, depopulate it
+ * of pinned directories.
+ */
+void afs_dynroot_depopulate(struct super_block *sb)
+{
+ struct afs_net *net = afs_sb2net(sb);
+ struct dentry *root = sb->s_root, *subdir, *tmp;
+
+ /* Prevent more subdirs from being created */
+ mutex_lock(&net->proc_cells_lock);
+ if (net->dynroot_sb == sb)
+ net->dynroot_sb = NULL;
+ mutex_unlock(&net->proc_cells_lock);
+
+ inode_lock(root->d_inode);
+
+ /* Remove all the pins for dirs created for manually added cells */
+ list_for_each_entry_safe(subdir, tmp, &root->d_subdirs, d_child) {
+ if (subdir->d_fsdata) {
+ subdir->d_fsdata = NULL;
+ dput(subdir);
+ }
+ }
+
+ inode_unlock(root->d_inode);
+}
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index b273e1d60478..50929cb91732 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -72,7 +72,7 @@ void afs_update_inode_from_status(struct afs_vnode *vnode,
const afs_dataversion_t *expected_version,
u8 flags)
{
- struct timespec t;
+ struct timespec64 t;
umode_t mode;
t.tv_sec = status->mtime_client;
@@ -138,10 +138,6 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
u64 data_version, size;
u32 type, abort_code;
u8 flags = 0;
- int ret;
-
- if (vnode)
- write_seqlock(&vnode->cb_lock);
abort_code = ntohl(xdr->abort_code);
@@ -154,8 +150,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
* case.
*/
status->abort_code = abort_code;
- ret = 0;
- goto out;
+ return 0;
}
pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
@@ -164,8 +159,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
if (abort_code != 0 && inline_error) {
status->abort_code = abort_code;
- ret = 0;
- goto out;
+ return 0;
}
type = ntohl(xdr->type);
@@ -235,17 +229,35 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
flags);
}
- ret = 0;
-
-out:
- if (vnode)
- write_sequnlock(&vnode->cb_lock);
- return ret;
+ return 0;
bad:
xdr_dump_bad(*_bp);
- ret = afs_protocol_error(call, -EBADMSG);
- goto out;
+ return afs_protocol_error(call, -EBADMSG);
+}
+
+/*
+ * Decode the file status. We need to lock the target vnode if we're going to
+ * update its status so that stat() sees the attributes update atomically.
+ */
+static int afs_decode_status(struct afs_call *call,
+ const __be32 **_bp,
+ struct afs_file_status *status,
+ struct afs_vnode *vnode,
+ const afs_dataversion_t *expected_version,
+ struct afs_read *read_req)
+{
+ int ret;
+
+ if (!vnode)
+ return xdr_decode_AFSFetchStatus(call, _bp, status, vnode,
+ expected_version, read_req);
+
+ write_seqlock(&vnode->cb_lock);
+ ret = xdr_decode_AFSFetchStatus(call, _bp, status, vnode,
+ expected_version, read_req);
+ write_sequnlock(&vnode->cb_lock);
+ return ret;
}
/*
@@ -387,8 +399,8 @@ static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, &vnode->status, vnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
xdr_decode_AFSCallBack(call, vnode, &bp);
if (call->reply[1])
@@ -568,8 +580,8 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
return ret;
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &vnode->status.data_version, req) < 0)
+ if (afs_decode_status(call, &bp, &vnode->status, vnode,
+ &vnode->status.data_version, req) < 0)
return afs_protocol_error(call, -EBADMSG);
xdr_decode_AFSCallBack(call, vnode, &bp);
if (call->reply[1])
@@ -721,9 +733,9 @@ static int afs_deliver_fs_create_vnode(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
xdr_decode_AFSFid(&bp, call->reply[1]);
- if (xdr_decode_AFSFetchStatus(call, &bp, call->reply[2], NULL, NULL, NULL) < 0 ||
- xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL) < 0 ||
+ afs_decode_status(call, &bp, &vnode->status, vnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
xdr_decode_AFSCallBack_raw(&bp, call->reply[3]);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -827,8 +839,8 @@ static int afs_deliver_fs_remove(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, &vnode->status, vnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -917,9 +929,9 @@ static int afs_deliver_fs_link(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode, NULL, NULL) < 0 ||
- xdr_decode_AFSFetchStatus(call, &bp, &dvnode->status, dvnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL) < 0 ||
+ afs_decode_status(call, &bp, &dvnode->status, dvnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -1004,9 +1016,9 @@ static int afs_deliver_fs_symlink(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
xdr_decode_AFSFid(&bp, call->reply[1]);
- if (xdr_decode_AFSFetchStatus(call, &bp, call->reply[2], NULL, NULL, NULL) ||
- xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL) ||
+ afs_decode_status(call, &bp, &vnode->status, vnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -1110,12 +1122,12 @@ static int afs_deliver_fs_rename(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &orig_dvnode->status, orig_dvnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
if (new_dvnode != orig_dvnode &&
- xdr_decode_AFSFetchStatus(call, &bp, &new_dvnode->status, new_dvnode,
- &call->expected_version_2, NULL) < 0)
+ afs_decode_status(call, &bp, &new_dvnode->status, new_dvnode,
+ &call->expected_version_2, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -1219,8 +1231,8 @@ static int afs_deliver_fs_store_data(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, &vnode->status, vnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -1395,8 +1407,8 @@ static int afs_deliver_fs_store_status(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, &vnode->status, vnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -2097,8 +2109,8 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- xdr_decode_AFSFetchStatus(call, &bp, status, vnode,
- &call->expected_version, NULL);
+ afs_decode_status(call, &bp, status, vnode,
+ &call->expected_version, NULL);
callback[call->count].version = ntohl(bp[0]);
callback[call->count].expiry = ntohl(bp[1]);
callback[call->count].type = ntohl(bp[2]);
@@ -2209,9 +2221,9 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
bp = call->buffer;
statuses = call->reply[1];
- if (xdr_decode_AFSFetchStatus(call, &bp, &statuses[call->count],
- call->count == 0 ? vnode : NULL,
- NULL, NULL) < 0)
+ if (afs_decode_status(call, &bp, &statuses[call->count],
+ call->count == 0 ? vnode : NULL,
+ NULL, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
call->count++;
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index e3f8a46663db..9778df135717 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -22,6 +22,8 @@
#include <linux/backing-dev.h>
#include <linux/uuid.h>
#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+#include <net/sock.h>
#include <net/af_rxrpc.h>
#include "afs.h"
@@ -40,7 +42,8 @@ struct afs_mount_params {
afs_voltype_t type; /* type of volume requested */
int volnamesz; /* size of volume name */
const char *volname; /* name of volume to mount */
- struct afs_net *net; /* Network namespace in effect */
+ struct net *net_ns; /* Network namespace in effect */
+ struct afs_net *net; /* the AFS net namespace stuff */
struct afs_cell *cell; /* cell in which to find volume */
struct afs_volume *volume; /* volume record */
struct key *key; /* key to use for secure mounting */
@@ -189,7 +192,7 @@ struct afs_read {
* - there's one superblock per volume
*/
struct afs_super_info {
- struct afs_net *net; /* Network namespace */
+ struct net *net_ns; /* Network namespace */
struct afs_cell *cell; /* The cell in which the volume resides */
struct afs_volume *volume; /* volume record */
bool dyn_root; /* True if dynamic root */
@@ -210,7 +213,6 @@ struct afs_sysnames {
char *subs[AFS_NR_SYSNAME];
refcount_t usage;
unsigned short nr;
- short error;
char blank[1];
};
@@ -218,6 +220,7 @@ struct afs_sysnames {
* AFS network namespace record.
*/
struct afs_net {
+ struct net *net; /* Backpointer to the owning net namespace */
struct afs_uuid uuid;
bool live; /* F if this namespace is being removed */
@@ -231,13 +234,13 @@ struct afs_net {
/* Cell database */
struct rb_root cells;
- struct afs_cell *ws_cell;
+ struct afs_cell __rcu *ws_cell;
struct work_struct cells_manager;
struct timer_list cells_timer;
atomic_t cells_outstanding;
seqlock_t cells_lock;
- spinlock_t proc_cells_lock;
+ struct mutex proc_cells_lock;
struct list_head proc_cells;
/* Known servers. Theoretically each fileserver can only be in one
@@ -261,6 +264,7 @@ struct afs_net {
struct mutex lock_manager_mutex;
/* Misc */
+ struct super_block *dynroot_sb; /* Dynamic root mount superblock */
struct proc_dir_entry *proc_afs; /* /proc/net/afs directory */
struct afs_sysnames *sysnames;
rwlock_t sysnames_lock;
@@ -280,7 +284,6 @@ struct afs_net {
};
extern const char afs_init_sysname[];
-extern struct afs_net __afs_net;// Dummy AFS network namespace; TODO: replace with real netns
enum afs_cell_state {
AFS_CELL_UNSET,
@@ -404,16 +407,27 @@ struct afs_server {
rwlock_t fs_lock; /* access lock */
/* callback promise management */
- struct list_head cb_interests; /* List of superblocks using this server */
+ struct hlist_head cb_volumes; /* List of volume interests on this server */
unsigned cb_s_break; /* Break-everything counter. */
rwlock_t cb_break_lock; /* Volume finding lock */
};
/*
+ * Volume collation in the server's callback interest list.
+ */
+struct afs_vol_interest {
+ struct hlist_node srv_link; /* Link in server->cb_volumes */
+ struct hlist_head cb_interests; /* List of callback interests on the server */
+ afs_volid_t vid; /* Volume ID to match */
+ unsigned int usage;
+};
+
+/*
* Interest by a superblock on a server.
*/
struct afs_cb_interest {
- struct list_head cb_link; /* Link in server->cb_interests */
+ struct hlist_node cb_vlink; /* Link in vol_interest->cb_interests */
+ struct afs_vol_interest *vol_interest;
struct afs_server *server; /* Server on which this interest resides */
struct super_block *sb; /* Superblock on which inodes reside */
afs_volid_t vid; /* Volume ID to match */
@@ -720,6 +734,10 @@ extern const struct inode_operations afs_dynroot_inode_operations;
extern const struct dentry_operations afs_dynroot_dentry_operations;
extern struct inode *afs_try_auto_mntpt(struct dentry *, struct inode *);
+extern int afs_dynroot_mkdir(struct afs_net *, struct afs_cell *);
+extern void afs_dynroot_rmdir(struct afs_net *, struct afs_cell *);
+extern int afs_dynroot_populate(struct super_block *);
+extern void afs_dynroot_depopulate(struct super_block *);
/*
* file.c
@@ -806,34 +824,36 @@ extern int afs_drop_inode(struct inode *);
* main.c
*/
extern struct workqueue_struct *afs_wq;
+extern int afs_net_id;
-static inline struct afs_net *afs_d2net(struct dentry *dentry)
+static inline struct afs_net *afs_net(struct net *net)
{
- return &__afs_net;
+ return net_generic(net, afs_net_id);
}
-static inline struct afs_net *afs_i2net(struct inode *inode)
+static inline struct afs_net *afs_sb2net(struct super_block *sb)
{
- return &__afs_net;
+ return afs_net(AFS_FS_S(sb)->net_ns);
}
-static inline struct afs_net *afs_v2net(struct afs_vnode *vnode)
+static inline struct afs_net *afs_d2net(struct dentry *dentry)
{
- return &__afs_net;
+ return afs_sb2net(dentry->d_sb);
}
-static inline struct afs_net *afs_sock2net(struct sock *sk)
+static inline struct afs_net *afs_i2net(struct inode *inode)
{
- return &__afs_net;
+ return afs_sb2net(inode->i_sb);
}
-static inline struct afs_net *afs_get_net(struct afs_net *net)
+static inline struct afs_net *afs_v2net(struct afs_vnode *vnode)
{
- return net;
+ return afs_i2net(&vnode->vfs_inode);
}
-static inline void afs_put_net(struct afs_net *net)
+static inline struct afs_net *afs_sock2net(struct sock *sk)
{
+ return net_generic(sock_net(sk), afs_net_id);
}
static inline void __afs_stat(atomic_t *s)
@@ -861,16 +881,25 @@ extern void afs_mntpt_kill_timer(void);
/*
* netdevices.c
*/
-extern int afs_get_ipv4_interfaces(struct afs_interface *, size_t, bool);
+extern int afs_get_ipv4_interfaces(struct afs_net *, struct afs_interface *,
+ size_t, bool);
/*
* proc.c
*/
+#ifdef CONFIG_PROC_FS
extern int __net_init afs_proc_init(struct afs_net *);
extern void __net_exit afs_proc_cleanup(struct afs_net *);
-extern int afs_proc_cell_setup(struct afs_net *, struct afs_cell *);
-extern void afs_proc_cell_remove(struct afs_net *, struct afs_cell *);
+extern int afs_proc_cell_setup(struct afs_cell *);
+extern void afs_proc_cell_remove(struct afs_cell *);
extern void afs_put_sysnames(struct afs_sysnames *);
+#else
+static inline int afs_proc_init(struct afs_net *net) { return 0; }
+static inline void afs_proc_cleanup(struct afs_net *net) {}
+static inline int afs_proc_cell_setup(struct afs_cell *cell) { return 0; }
+static inline void afs_proc_cell_remove(struct afs_cell *cell) {}
+static inline void afs_put_sysnames(struct afs_sysnames *sysnames) {}
+#endif
/*
* rotate.c
@@ -1002,7 +1031,7 @@ extern bool afs_annotate_server_list(struct afs_server_list *, struct afs_server
* super.c
*/
extern int __init afs_fs_init(void);
-extern void __exit afs_fs_exit(void);
+extern void afs_fs_exit(void);
/*
* vlclient.c
diff --git a/fs/afs/main.c b/fs/afs/main.c
index d7560168b3bf..e84fe822a960 100644
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -15,6 +15,7 @@
#include <linux/completion.h>
#include <linux/sched.h>
#include <linux/random.h>
+#include <linux/proc_fs.h>
#define CREATE_TRACE_POINTS
#include "internal.h"
@@ -32,7 +33,7 @@ module_param(rootcell, charp, 0);
MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");
struct workqueue_struct *afs_wq;
-struct afs_net __afs_net;
+static struct proc_dir_entry *afs_proc_symlink;
#if defined(CONFIG_ALPHA)
const char afs_init_sysname[] = "alpha_linux26";
@@ -67,11 +68,13 @@ const char afs_init_sysname[] = "unknown_linux26";
/*
* Initialise an AFS network namespace record.
*/
-static int __net_init afs_net_init(struct afs_net *net)
+static int __net_init afs_net_init(struct net *net_ns)
{
struct afs_sysnames *sysnames;
+ struct afs_net *net = afs_net(net_ns);
int ret;
+ net->net = net_ns;
net->live = true;
generate_random_uuid((unsigned char *)&net->uuid);
@@ -83,7 +86,7 @@ static int __net_init afs_net_init(struct afs_net *net)
INIT_WORK(&net->cells_manager, afs_manage_cells);
timer_setup(&net->cells_timer, afs_cells_timer, 0);
- spin_lock_init(&net->proc_cells_lock);
+ mutex_init(&net->proc_cells_lock);
INIT_LIST_HEAD(&net->proc_cells);
seqlock_init(&net->fs_lock);
@@ -142,8 +145,10 @@ error_sysnames:
/*
* Clean up and destroy an AFS network namespace record.
*/
-static void __net_exit afs_net_exit(struct afs_net *net)
+static void __net_exit afs_net_exit(struct net *net_ns)
{
+ struct afs_net *net = afs_net(net_ns);
+
net->live = false;
afs_cell_purge(net);
afs_purge_servers(net);
@@ -152,6 +157,13 @@ static void __net_exit afs_net_exit(struct afs_net *net)
afs_put_sysnames(net->sysnames);
}
+static struct pernet_operations afs_net_ops = {
+ .init = afs_net_init,
+ .exit = afs_net_exit,
+ .id = &afs_net_id,
+ .size = sizeof(struct afs_net),
+};
+
/*
* initialise the AFS client FS module
*/
@@ -178,7 +190,7 @@ static int __init afs_init(void)
goto error_cache;
#endif
- ret = afs_net_init(&__afs_net);
+ ret = register_pernet_subsys(&afs_net_ops);
if (ret < 0)
goto error_net;
@@ -187,10 +199,18 @@ static int __init afs_init(void)
if (ret < 0)
goto error_fs;
+ afs_proc_symlink = proc_symlink("fs/afs", NULL, "../self/net/afs");
+ if (IS_ERR(afs_proc_symlink)) {
+ ret = PTR_ERR(afs_proc_symlink);
+ goto error_proc;
+ }
+
return ret;
+error_proc:
+ afs_fs_exit();
error_fs:
- afs_net_exit(&__afs_net);
+ unregister_pernet_subsys(&afs_net_ops);
error_net:
#ifdef CONFIG_AFS_FSCACHE
fscache_unregister_netfs(&afs_cache_netfs);
@@ -219,8 +239,9 @@ static void __exit afs_exit(void)
{
printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");
+ proc_remove(afs_proc_symlink);
afs_fs_exit();
- afs_net_exit(&__afs_net);
+ unregister_pernet_subsys(&afs_net_ops);
#ifdef CONFIG_AFS_FSCACHE
fscache_unregister_netfs(&afs_cache_netfs);
#endif
diff --git a/fs/afs/netdevices.c b/fs/afs/netdevices.c
index 50bd5bb1c4fb..2a009d1939d7 100644
--- a/fs/afs/netdevices.c
+++ b/fs/afs/netdevices.c
@@ -17,8 +17,8 @@
* - maxbufs must be at least 1
* - returns the number of interface records in the buffer
*/
-int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs,
- bool wantloopback)
+int afs_get_ipv4_interfaces(struct afs_net *net, struct afs_interface *bufs,
+ size_t maxbufs, bool wantloopback)
{
struct net_device *dev;
struct in_device *idev;
@@ -27,7 +27,7 @@ int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs,
ASSERT(maxbufs > 0);
rtnl_lock();
- for_each_netdev(&init_net, dev) {
+ for_each_netdev(net->net, dev) {
if (dev->type == ARPHRD_LOOPBACK && !wantloopback)
continue;
idev = __in_dev_get_rtnl(dev);
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 3aad32762989..0c3285c8db95 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -17,240 +17,78 @@
#include <linux/uaccess.h>
#include "internal.h"
-static inline struct afs_net *afs_proc2net(struct file *f)
+static inline struct afs_net *afs_seq2net(struct seq_file *m)
{
- return &__afs_net;
+ return afs_net(seq_file_net(m));
}
-static inline struct afs_net *afs_seq2net(struct seq_file *m)
+static inline struct afs_net *afs_seq2net_single(struct seq_file *m)
{
- return &__afs_net; // TODO: use seq_file_net(m)
+ return afs_net(seq_file_single_net(m));
}
-static int afs_proc_cells_open(struct inode *inode, struct file *file);
-static void *afs_proc_cells_start(struct seq_file *p, loff_t *pos);
-static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos);
-static void afs_proc_cells_stop(struct seq_file *p, void *v);
-static int afs_proc_cells_show(struct seq_file *m, void *v);
-static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
- size_t size, loff_t *_pos);
-
-static const struct seq_operations afs_proc_cells_ops = {
- .start = afs_proc_cells_start,
- .next = afs_proc_cells_next,
- .stop = afs_proc_cells_stop,
- .show = afs_proc_cells_show,
-};
-
-static const struct file_operations afs_proc_cells_fops = {
- .open = afs_proc_cells_open,
- .read = seq_read,
- .write = afs_proc_cells_write,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf,
- size_t size, loff_t *_pos);
-static ssize_t afs_proc_rootcell_write(struct file *file,
- const char __user *buf,
- size_t size, loff_t *_pos);
-
-static const struct file_operations afs_proc_rootcell_fops = {
- .read = afs_proc_rootcell_read,
- .write = afs_proc_rootcell_write,
- .llseek = no_llseek,
-};
-
-static void *afs_proc_cell_volumes_start(struct seq_file *p, loff_t *pos);
-static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v,
- loff_t *pos);
-static void afs_proc_cell_volumes_stop(struct seq_file *p, void *v);
-static int afs_proc_cell_volumes_show(struct seq_file *m, void *v);
-
-static const struct seq_operations afs_proc_cell_volumes_ops = {
- .start = afs_proc_cell_volumes_start,
- .next = afs_proc_cell_volumes_next,
- .stop = afs_proc_cell_volumes_stop,
- .show = afs_proc_cell_volumes_show,
-};
-
-static void *afs_proc_cell_vlservers_start(struct seq_file *p, loff_t *pos);
-static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v,
- loff_t *pos);
-static void afs_proc_cell_vlservers_stop(struct seq_file *p, void *v);
-static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v);
-
-static const struct seq_operations afs_proc_cell_vlservers_ops = {
- .start = afs_proc_cell_vlservers_start,
- .next = afs_proc_cell_vlservers_next,
- .stop = afs_proc_cell_vlservers_stop,
- .show = afs_proc_cell_vlservers_show,
-};
-
-static void *afs_proc_servers_start(struct seq_file *p, loff_t *pos);
-static void *afs_proc_servers_next(struct seq_file *p, void *v,
- loff_t *pos);
-static void afs_proc_servers_stop(struct seq_file *p, void *v);
-static int afs_proc_servers_show(struct seq_file *m, void *v);
-
-static const struct seq_operations afs_proc_servers_ops = {
- .start = afs_proc_servers_start,
- .next = afs_proc_servers_next,
- .stop = afs_proc_servers_stop,
- .show = afs_proc_servers_show,
-};
-
-static int afs_proc_sysname_open(struct inode *inode, struct file *file);
-static int afs_proc_sysname_release(struct inode *inode, struct file *file);
-static void *afs_proc_sysname_start(struct seq_file *p, loff_t *pos);
-static void *afs_proc_sysname_next(struct seq_file *p, void *v,
- loff_t *pos);
-static void afs_proc_sysname_stop(struct seq_file *p, void *v);
-static int afs_proc_sysname_show(struct seq_file *m, void *v);
-static ssize_t afs_proc_sysname_write(struct file *file,
- const char __user *buf,
- size_t size, loff_t *_pos);
-
-static const struct seq_operations afs_proc_sysname_ops = {
- .start = afs_proc_sysname_start,
- .next = afs_proc_sysname_next,
- .stop = afs_proc_sysname_stop,
- .show = afs_proc_sysname_show,
-};
-
-static const struct file_operations afs_proc_sysname_fops = {
- .open = afs_proc_sysname_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = afs_proc_sysname_release,
- .write = afs_proc_sysname_write,
-};
-
-static int afs_proc_stats_show(struct seq_file *m, void *v);
-
/*
- * initialise the /proc/fs/afs/ directory
+ * Display the list of cells known to the namespace.
*/
-int afs_proc_init(struct afs_net *net)
+static int afs_proc_cells_show(struct seq_file *m, void *v)
{
- _enter("");
-
- net->proc_afs = proc_mkdir("fs/afs", NULL);
- if (!net->proc_afs)
- goto error_dir;
+ struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link);
+ struct afs_net *net = afs_seq2net(m);
- if (!proc_create("cells", 0644, net->proc_afs, &afs_proc_cells_fops) ||
- !proc_create("rootcell", 0644, net->proc_afs, &afs_proc_rootcell_fops) ||
- !proc_create_seq("servers", 0644, net->proc_afs, &afs_proc_servers_ops) ||
- !proc_create_single("stats", 0644, net->proc_afs, afs_proc_stats_show) ||
- !proc_create("sysname", 0644, net->proc_afs, &afs_proc_sysname_fops))
- goto error_tree;
+ if (v == &net->proc_cells) {
+ /* display header on line 1 */
+ seq_puts(m, "USE NAME\n");
+ return 0;
+ }
- _leave(" = 0");
+ /* display one cell per line on subsequent lines */
+ seq_printf(m, "%3u %s\n", atomic_read(&cell->usage), cell->name);
return 0;
-
-error_tree:
- proc_remove(net->proc_afs);
-error_dir:
- _leave(" = -ENOMEM");
- return -ENOMEM;
-}
-
-/*
- * clean up the /proc/fs/afs/ directory
- */
-void afs_proc_cleanup(struct afs_net *net)
-{
- proc_remove(net->proc_afs);
- net->proc_afs = NULL;
-}
-
-/*
- * open "/proc/fs/afs/cells" which provides a summary of extant cells
- */
-static int afs_proc_cells_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &afs_proc_cells_ops);
}
-/*
- * set up the iterator to start reading from the cells list and return the
- * first item
- */
static void *afs_proc_cells_start(struct seq_file *m, loff_t *_pos)
__acquires(rcu)
{
- struct afs_net *net = afs_seq2net(m);
-
rcu_read_lock();
- return seq_list_start_head(&net->proc_cells, *_pos);
+ return seq_list_start_head(&afs_seq2net(m)->proc_cells, *_pos);
}
-/*
- * move to next cell in cells list
- */
static void *afs_proc_cells_next(struct seq_file *m, void *v, loff_t *pos)
{
- struct afs_net *net = afs_seq2net(m);
-
- return seq_list_next(v, &net->proc_cells, pos);
+ return seq_list_next(v, &afs_seq2net(m)->proc_cells, pos);
}
-/*
- * clean up after reading from the cells list
- */
static void afs_proc_cells_stop(struct seq_file *m, void *v)
__releases(rcu)
{
rcu_read_unlock();
}
-/*
- * display a header line followed by a load of cell lines
- */
-static int afs_proc_cells_show(struct seq_file *m, void *v)
-{
- struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link);
- struct afs_net *net = afs_seq2net(m);
-
- if (v == &net->proc_cells) {
- /* display header on line 1 */
- seq_puts(m, "USE NAME\n");
- return 0;
- }
-
- /* display one cell per line on subsequent lines */
- seq_printf(m, "%3u %s\n", atomic_read(&cell->usage), cell->name);
- return 0;
-}
+static const struct seq_operations afs_proc_cells_ops = {
+ .start = afs_proc_cells_start,
+ .next = afs_proc_cells_next,
+ .stop = afs_proc_cells_stop,
+ .show = afs_proc_cells_show,
+};
/*
* handle writes to /proc/fs/afs/cells
* - to add cells: echo "add <cellname> <IP>[:<IP>][:<IP>]"
*/
-static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
- size_t size, loff_t *_pos)
+static int afs_proc_cells_write(struct file *file, char *buf, size_t size)
{
- struct afs_net *net = afs_proc2net(file);
- char *kbuf, *name, *args;
+ struct seq_file *m = file->private_data;
+ struct afs_net *net = afs_seq2net(m);
+ char *name, *args;
int ret;
- /* start by dragging the command into memory */
- if (size <= 1 || size >= PAGE_SIZE)
- return -EINVAL;
-
- kbuf = memdup_user_nul(buf, size);
- if (IS_ERR(kbuf))
- return PTR_ERR(kbuf);
-
/* trim to first NL */
- name = memchr(kbuf, '\n', size);
+ name = memchr(buf, '\n', size);
if (name)
*name = 0;
/* split into command, name and argslist */
- name = strchr(kbuf, ' ');
+ name = strchr(buf, ' ');
if (!name)
goto inval;
do {
@@ -269,9 +107,9 @@ static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
goto inval;
/* determine command to perform */
- _debug("cmd=%s name=%s args=%s", kbuf, name, args);
+ _debug("cmd=%s name=%s args=%s", buf, name, args);
- if (strcmp(kbuf, "add") == 0) {
+ if (strcmp(buf, "add") == 0) {
struct afs_cell *cell;
cell = afs_lookup_cell(net, name, strlen(name), args, true);
@@ -287,10 +125,9 @@ static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
goto inval;
}
- ret = size;
+ ret = 0;
done:
- kfree(kbuf);
_leave(" = %d", ret);
return ret;
@@ -300,200 +137,136 @@ inval:
goto done;
}
-static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf,
- size_t size, loff_t *_pos)
+/*
+ * Display the name of the current workstation cell.
+ */
+static int afs_proc_rootcell_show(struct seq_file *m, void *v)
{
struct afs_cell *cell;
- struct afs_net *net = afs_proc2net(file);
- unsigned int seq = 0;
- char name[AFS_MAXCELLNAME + 1];
- int len;
-
- if (*_pos > 0)
- return 0;
- if (!net->ws_cell)
- return 0;
-
- rcu_read_lock();
- do {
- read_seqbegin_or_lock(&net->cells_lock, &seq);
- len = 0;
- cell = rcu_dereference_raw(net->ws_cell);
- if (cell) {
- len = cell->name_len;
- memcpy(name, cell->name, len);
- }
- } while (need_seqretry(&net->cells_lock, seq));
- done_seqretry(&net->cells_lock, seq);
- rcu_read_unlock();
-
- if (!len)
- return 0;
-
- name[len++] = '\n';
- if (len > size)
- len = size;
- if (copy_to_user(buf, name, len) != 0)
- return -EFAULT;
- *_pos = 1;
- return len;
+ struct afs_net *net;
+
+ net = afs_seq2net_single(m);
+ if (rcu_access_pointer(net->ws_cell)) {
+ rcu_read_lock();
+ cell = rcu_dereference(net->ws_cell);
+ if (cell)
+ seq_printf(m, "%s\n", cell->name);
+ rcu_read_unlock();
+ }
+ return 0;
}
/*
- * handle writes to /proc/fs/afs/rootcell
- * - to initialize rootcell: echo "cell.name:192.168.231.14"
+ * Set the current workstation cell and optionally supply its list of volume
+ * location servers.
+ *
+ * echo "cell.name:192.168.231.14" >/proc/fs/afs/rootcell
*/
-static ssize_t afs_proc_rootcell_write(struct file *file,
- const char __user *buf,
- size_t size, loff_t *_pos)
+static int afs_proc_rootcell_write(struct file *file, char *buf, size_t size)
{
- struct afs_net *net = afs_proc2net(file);
- char *kbuf, *s;
+ struct seq_file *m = file->private_data;
+ struct afs_net *net = afs_seq2net_single(m);
+ char *s;
int ret;
- /* start by dragging the command into memory */
- if (size <= 1 || size >= PAGE_SIZE)
- return -EINVAL;
-
- kbuf = memdup_user_nul(buf, size);
- if (IS_ERR(kbuf))
- return PTR_ERR(kbuf);
-
ret = -EINVAL;
- if (kbuf[0] == '.')
+ if (buf[0] == '.')
goto out;
- if (memchr(kbuf, '/', size))
+ if (memchr(buf, '/', size))
goto out;
/* trim to first NL */
- s = memchr(kbuf, '\n', size);
+ s = memchr(buf, '\n', size);
if (s)
*s = 0;
/* determine command to perform */
- _debug("rootcell=%s", kbuf);
+ _debug("rootcell=%s", buf);
- ret = afs_cell_init(net, kbuf);
- if (ret >= 0)
- ret = size; /* consume everything, always */
+ ret = afs_cell_init(net, buf);
out:
- kfree(kbuf);
_leave(" = %d", ret);
return ret;
}
+static const char afs_vol_types[3][3] = {
+ [AFSVL_RWVOL] = "RW",
+ [AFSVL_ROVOL] = "RO",
+ [AFSVL_BACKVOL] = "BK",
+};
+
/*
- * initialise /proc/fs/afs/<cell>/
+ * Display the list of volumes known to a cell.
*/
-int afs_proc_cell_setup(struct afs_net *net, struct afs_cell *cell)
+static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
{
- struct proc_dir_entry *dir;
-
- _enter("%p{%s},%p", cell, cell->name, net->proc_afs);
+ struct afs_cell *cell = PDE_DATA(file_inode(m->file));
+ struct afs_volume *vol = list_entry(v, struct afs_volume, proc_link);
- dir = proc_mkdir(cell->name, net->proc_afs);
- if (!dir)
- goto error_dir;
+ /* Display header on line 1 */
+ if (v == &cell->proc_volumes) {
+ seq_puts(m, "USE VID TY\n");
+ return 0;
+ }
- if (!proc_create_seq_data("vlservers", 0, dir,
- &afs_proc_cell_vlservers_ops, cell))
- goto error_tree;
- if (!proc_create_seq_data("volumes", 0, dir, &afs_proc_cell_volumes_ops,
- cell))
- goto error_tree;
+ seq_printf(m, "%3d %08x %s\n",
+ atomic_read(&vol->usage), vol->vid,
+ afs_vol_types[vol->type]);
- _leave(" = 0");
return 0;
-
-error_tree:
- remove_proc_subtree(cell->name, net->proc_afs);
-error_dir:
- _leave(" = -ENOMEM");
- return -ENOMEM;
}
-/*
- * remove /proc/fs/afs/<cell>/
- */
-void afs_proc_cell_remove(struct afs_net *net, struct afs_cell *cell)
-{
- _enter("");
-
- remove_proc_subtree(cell->name, net->proc_afs);
-
- _leave("");
-}
-
-/*
- * set up the iterator to start reading from the cells list and return the
- * first item
- */
static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos)
__acquires(cell->proc_lock)
{
struct afs_cell *cell = PDE_DATA(file_inode(m->file));
- _enter("cell=%p pos=%Ld", cell, *_pos);
-
read_lock(&cell->proc_lock);
return seq_list_start_head(&cell->proc_volumes, *_pos);
}
-/*
- * move to next cell in cells list
- */
-static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v,
+static void *afs_proc_cell_volumes_next(struct seq_file *m, void *v,
loff_t *_pos)
{
- struct afs_cell *cell = PDE_DATA(file_inode(p->file));
+ struct afs_cell *cell = PDE_DATA(file_inode(m->file));
- _enter("cell=%p pos=%Ld", cell, *_pos);
return seq_list_next(v, &cell->proc_volumes, _pos);
}
-/*
- * clean up after reading from the cells list
- */
-static void afs_proc_cell_volumes_stop(struct seq_file *p, void *v)
+static void afs_proc_cell_volumes_stop(struct seq_file *m, void *v)
__releases(cell->proc_lock)
{
- struct afs_cell *cell = PDE_DATA(file_inode(p->file));
+ struct afs_cell *cell = PDE_DATA(file_inode(m->file));
read_unlock(&cell->proc_lock);
}
-static const char afs_vol_types[3][3] = {
- [AFSVL_RWVOL] = "RW",
- [AFSVL_ROVOL] = "RO",
- [AFSVL_BACKVOL] = "BK",
+static const struct seq_operations afs_proc_cell_volumes_ops = {
+ .start = afs_proc_cell_volumes_start,
+ .next = afs_proc_cell_volumes_next,
+ .stop = afs_proc_cell_volumes_stop,
+ .show = afs_proc_cell_volumes_show,
};
/*
- * display a header line followed by a load of volume lines
+ * Display the list of Volume Location servers we're using for a cell.
*/
-static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
+static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v)
{
- struct afs_cell *cell = PDE_DATA(file_inode(m->file));
- struct afs_volume *vol = list_entry(v, struct afs_volume, proc_link);
+ struct sockaddr_rxrpc *addr = v;
- /* Display header on line 1 */
- if (v == &cell->proc_volumes) {
- seq_puts(m, "USE VID TY\n");
+ /* display header on line 1 */
+ if (v == (void *)1) {
+ seq_puts(m, "ADDRESS\n");
return 0;
}
- seq_printf(m, "%3d %08x %s\n",
- atomic_read(&vol->usage), vol->vid,
- afs_vol_types[vol->type]);
-
+ /* display one cell per line on subsequent lines */
+ seq_printf(m, "%pISp\n", &addr->transport);
return 0;
}
-/*
- * set up the iterator to start reading from the cells list and return the
- * first item
- */
static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos)
__acquires(rcu)
{
@@ -516,14 +289,11 @@ static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos)
return alist->addrs + pos;
}
-/*
- * move to next cell in cells list
- */
-static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v,
+static void *afs_proc_cell_vlservers_next(struct seq_file *m, void *v,
loff_t *_pos)
{
struct afs_addr_list *alist;
- struct afs_cell *cell = PDE_DATA(file_inode(p->file));
+ struct afs_cell *cell = PDE_DATA(file_inode(m->file));
loff_t pos;
alist = rcu_dereference(cell->vl_addrs);
@@ -536,161 +306,145 @@ static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v,
return alist->addrs + pos;
}
-/*
- * clean up after reading from the cells list
- */
-static void afs_proc_cell_vlservers_stop(struct seq_file *p, void *v)
+static void afs_proc_cell_vlservers_stop(struct seq_file *m, void *v)
__releases(rcu)
{
rcu_read_unlock();
}
+static const struct seq_operations afs_proc_cell_vlservers_ops = {
+ .start = afs_proc_cell_vlservers_start,
+ .next = afs_proc_cell_vlservers_next,
+ .stop = afs_proc_cell_vlservers_stop,
+ .show = afs_proc_cell_vlservers_show,
+};
+
/*
- * display a header line followed by a load of volume lines
+ * Display the list of fileservers we're using within a namespace.
*/
-static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v)
+static int afs_proc_servers_show(struct seq_file *m, void *v)
{
- struct sockaddr_rxrpc *addr = v;
+ struct afs_server *server;
+ struct afs_addr_list *alist;
+ int i;
- /* display header on line 1 */
- if (v == (void *)1) {
- seq_puts(m, "ADDRESS\n");
+ if (v == SEQ_START_TOKEN) {
+ seq_puts(m, "UUID USE ADDR\n");
return 0;
}
- /* display one cell per line on subsequent lines */
- seq_printf(m, "%pISp\n", &addr->transport);
+ server = list_entry(v, struct afs_server, proc_link);
+ alist = rcu_dereference(server->addresses);
+ seq_printf(m, "%pU %3d %pISpc%s\n",
+ &server->uuid,
+ atomic_read(&server->usage),
+ &alist->addrs[0].transport,
+ alist->index == 0 ? "*" : "");
+ for (i = 1; i < alist->nr_addrs; i++)
+ seq_printf(m, " %pISpc%s\n",
+ &alist->addrs[i].transport,
+ alist->index == i ? "*" : "");
return 0;
}
-/*
- * Set up the iterator to start reading from the server list and return the
- * first item.
- */
static void *afs_proc_servers_start(struct seq_file *m, loff_t *_pos)
__acquires(rcu)
{
- struct afs_net *net = afs_seq2net(m);
-
rcu_read_lock();
- return seq_hlist_start_head_rcu(&net->fs_proc, *_pos);
+ return seq_hlist_start_head_rcu(&afs_seq2net(m)->fs_proc, *_pos);
}
-/*
- * move to next cell in cells list
- */
static void *afs_proc_servers_next(struct seq_file *m, void *v, loff_t *_pos)
{
- struct afs_net *net = afs_seq2net(m);
-
- return seq_hlist_next_rcu(v, &net->fs_proc, _pos);
+ return seq_hlist_next_rcu(v, &afs_seq2net(m)->fs_proc, _pos);
}
-/*
- * clean up after reading from the cells list
- */
-static void afs_proc_servers_stop(struct seq_file *p, void *v)
+static void afs_proc_servers_stop(struct seq_file *m, void *v)
__releases(rcu)
{
rcu_read_unlock();
}
+static const struct seq_operations afs_proc_servers_ops = {
+ .start = afs_proc_servers_start,
+ .next = afs_proc_servers_next,
+ .stop = afs_proc_servers_stop,
+ .show = afs_proc_servers_show,
+};
+
/*
- * display a header line followed by a load of volume lines
+ * Display the list of strings that may be substituted for the @sys pathname
+ * macro.
*/
-static int afs_proc_servers_show(struct seq_file *m, void *v)
+static int afs_proc_sysname_show(struct seq_file *m, void *v)
{
- struct afs_server *server;
- struct afs_addr_list *alist;
-
- if (v == SEQ_START_TOKEN) {
- seq_puts(m, "UUID USE ADDR\n");
- return 0;
- }
+ struct afs_net *net = afs_seq2net(m);
+ struct afs_sysnames *sysnames = net->sysnames;
+ unsigned int i = (unsigned long)v - 1;
- server = list_entry(v, struct afs_server, proc_link);
- alist = rcu_dereference(server->addresses);
- seq_printf(m, "%pU %3d %pISp\n",
- &server->uuid,
- atomic_read(&server->usage),
- &alist->addrs[alist->index].transport);
+ if (i < sysnames->nr)
+ seq_printf(m, "%s\n", sysnames->subs[i]);
return 0;
}
-void afs_put_sysnames(struct afs_sysnames *sysnames)
+static void *afs_proc_sysname_start(struct seq_file *m, loff_t *pos)
+ __acquires(&net->sysnames_lock)
{
- int i;
+ struct afs_net *net = afs_seq2net(m);
+ struct afs_sysnames *names;
- if (sysnames && refcount_dec_and_test(&sysnames->usage)) {
- for (i = 0; i < sysnames->nr; i++)
- if (sysnames->subs[i] != afs_init_sysname &&
- sysnames->subs[i] != sysnames->blank)
- kfree(sysnames->subs[i]);
- }
+ read_lock(&net->sysnames_lock);
+
+ names = net->sysnames;
+ if (*pos >= names->nr)
+ return NULL;
+ return (void *)(unsigned long)(*pos + 1);
}
-/*
- * Handle opening of /proc/fs/afs/sysname. If it is opened for writing, we
- * assume the caller wants to change the substitution list and we allocate a
- * buffer to hold the list.
- */
-static int afs_proc_sysname_open(struct inode *inode, struct file *file)
+static void *afs_proc_sysname_next(struct seq_file *m, void *v, loff_t *pos)
{
- struct afs_sysnames *sysnames;
- struct seq_file *m;
- int ret;
-
- ret = seq_open(file, &afs_proc_sysname_ops);
- if (ret < 0)
- return ret;
+ struct afs_net *net = afs_seq2net(m);
+ struct afs_sysnames *names = net->sysnames;
- if (file->f_mode & FMODE_WRITE) {
- sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL);
- if (!sysnames) {
- seq_release(inode, file);
- return -ENOMEM;
- }
+ *pos += 1;
+ if (*pos >= names->nr)
+ return NULL;
+ return (void *)(unsigned long)(*pos + 1);
+}
- refcount_set(&sysnames->usage, 1);
- m = file->private_data;
- m->private = sysnames;
- }
+static void afs_proc_sysname_stop(struct seq_file *m, void *v)
+ __releases(&net->sysnames_lock)
+{
+ struct afs_net *net = afs_seq2net(m);
- return 0;
+ read_unlock(&net->sysnames_lock);
}
+static const struct seq_operations afs_proc_sysname_ops = {
+ .start = afs_proc_sysname_start,
+ .next = afs_proc_sysname_next,
+ .stop = afs_proc_sysname_stop,
+ .show = afs_proc_sysname_show,
+};
+
/*
- * Handle writes to /proc/fs/afs/sysname to set the @sys substitution.
+ * Allow the @sys substitution to be configured.
*/
-static ssize_t afs_proc_sysname_write(struct file *file,
- const char __user *buf,
- size_t size, loff_t *_pos)
+static int afs_proc_sysname_write(struct file *file, char *buf, size_t size)
{
- struct afs_sysnames *sysnames;
+ struct afs_sysnames *sysnames, *kill;
struct seq_file *m = file->private_data;
- char *kbuf = NULL, *s, *p, *sub;
+ struct afs_net *net = afs_seq2net(m);
+ char *s, *p, *sub;
int ret, len;
- sysnames = m->private;
+ sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL);
if (!sysnames)
- return -EINVAL;
- if (sysnames->error)
- return sysnames->error;
-
- if (size >= PAGE_SIZE - 1) {
- sysnames->error = -EINVAL;
- return -EINVAL;
- }
- if (size == 0)
- return 0;
-
- kbuf = memdup_user_nul(buf, size);
- if (IS_ERR(kbuf))
- return PTR_ERR(kbuf);
-
- inode_lock(file_inode(file));
+ return -ENOMEM;
+ refcount_set(&sysnames->usage, 1);
+ kill = sysnames;
- p = kbuf;
+ p = buf;
while ((s = strsep(&p, " \t\n"))) {
len = strlen(s);
if (len == 0)
@@ -731,85 +485,36 @@ static ssize_t afs_proc_sysname_write(struct file *file,
sysnames->nr++;
}
- ret = size; /* consume everything, always */
+ if (sysnames->nr == 0) {
+ sysnames->subs[0] = sysnames->blank;
+ sysnames->nr++;
+ }
+
+ write_lock(&net->sysnames_lock);
+ kill = net->sysnames;
+ net->sysnames = sysnames;
+ write_unlock(&net->sysnames_lock);
+ ret = 0;
out:
- inode_unlock(file_inode(file));
- kfree(kbuf);
+ afs_put_sysnames(kill);
return ret;
invalid:
ret = -EINVAL;
error:
- sysnames->error = ret;
goto out;
}
-static int afs_proc_sysname_release(struct inode *inode, struct file *file)
+void afs_put_sysnames(struct afs_sysnames *sysnames)
{
- struct afs_sysnames *sysnames, *kill = NULL;
- struct seq_file *m = file->private_data;
- struct afs_net *net = afs_seq2net(m);
+ int i;
- sysnames = m->private;
- if (sysnames) {
- if (!sysnames->error) {
- kill = sysnames;
- if (sysnames->nr == 0) {
- sysnames->subs[0] = sysnames->blank;
- sysnames->nr++;
- }
- write_lock(&net->sysnames_lock);
- kill = net->sysnames;
- net->sysnames = sysnames;
- write_unlock(&net->sysnames_lock);
- }
- afs_put_sysnames(kill);
+ if (sysnames && refcount_dec_and_test(&sysnames->usage)) {
+ for (i = 0; i < sysnames->nr; i++)
+ if (sysnames->subs[i] != afs_init_sysname &&
+ sysnames->subs[i] != sysnames->blank)
+ kfree(sysnames->subs[i]);
}
-
- return seq_release(inode, file);
-}
-
-static void *afs_proc_sysname_start(struct seq_file *m, loff_t *pos)
- __acquires(&net->sysnames_lock)
-{
- struct afs_net *net = afs_seq2net(m);
- struct afs_sysnames *names = net->sysnames;
-
- read_lock(&net->sysnames_lock);
-
- if (*pos >= names->nr)
- return NULL;
- return (void *)(unsigned long)(*pos + 1);
-}
-
-static void *afs_proc_sysname_next(struct seq_file *m, void *v, loff_t *pos)
-{
- struct afs_net *net = afs_seq2net(m);
- struct afs_sysnames *names = net->sysnames;
-
- *pos += 1;
- if (*pos >= names->nr)
- return NULL;
- return (void *)(unsigned long)(*pos + 1);
-}
-
-static void afs_proc_sysname_stop(struct seq_file *m, void *v)
- __releases(&net->sysnames_lock)
-{
- struct afs_net *net = afs_seq2net(m);
-
- read_unlock(&net->sysnames_lock);
-}
-
-static int afs_proc_sysname_show(struct seq_file *m, void *v)
-{
- struct afs_net *net = afs_seq2net(m);
- struct afs_sysnames *sysnames = net->sysnames;
- unsigned int i = (unsigned long)v - 1;
-
- if (i < sysnames->nr)
- seq_printf(m, "%s\n", sysnames->subs[i]);
- return 0;
}
/*
@@ -817,7 +522,7 @@ static int afs_proc_sysname_show(struct seq_file *m, void *v)
*/
static int afs_proc_stats_show(struct seq_file *m, void *v)
{
- struct afs_net *net = afs_seq2net(m);
+ struct afs_net *net = afs_seq2net_single(m);
seq_puts(m, "kAFS statistics\n");
@@ -842,3 +547,101 @@ static int afs_proc_stats_show(struct seq_file *m, void *v)
atomic_long_read(&net->n_store_bytes));
return 0;
}
+
+/*
+ * initialise /proc/fs/afs/<cell>/
+ */
+int afs_proc_cell_setup(struct afs_cell *cell)
+{
+ struct proc_dir_entry *dir;
+ struct afs_net *net = cell->net;
+
+ _enter("%p{%s},%p", cell, cell->name, net->proc_afs);
+
+ dir = proc_net_mkdir(net->net, cell->name, net->proc_afs);
+ if (!dir)
+ goto error_dir;
+
+ if (!proc_create_net_data("vlservers", 0444, dir,
+ &afs_proc_cell_vlservers_ops,
+ sizeof(struct seq_net_private),
+ cell) ||
+ !proc_create_net_data("volumes", 0444, dir,
+ &afs_proc_cell_volumes_ops,
+ sizeof(struct seq_net_private),
+ cell))
+ goto error_tree;
+
+ _leave(" = 0");
+ return 0;
+
+error_tree:
+ remove_proc_subtree(cell->name, net->proc_afs);
+error_dir:
+ _leave(" = -ENOMEM");
+ return -ENOMEM;
+}
+
+/*
+ * remove /proc/fs/afs/<cell>/
+ */
+void afs_proc_cell_remove(struct afs_cell *cell)
+{
+ struct afs_net *net = cell->net;
+
+ _enter("");
+ remove_proc_subtree(cell->name, net->proc_afs);
+ _leave("");
+}
+
+/*
+ * initialise the /proc/fs/afs/ directory
+ */
+int afs_proc_init(struct afs_net *net)
+{
+ struct proc_dir_entry *p;
+
+ _enter("");
+
+ p = proc_net_mkdir(net->net, "afs", net->net->proc_net);
+ if (!p)
+ goto error_dir;
+
+ if (!proc_create_net_data_write("cells", 0644, p,
+ &afs_proc_cells_ops,
+ afs_proc_cells_write,
+ sizeof(struct seq_net_private),
+ NULL) ||
+ !proc_create_net_single_write("rootcell", 0644, p,
+ afs_proc_rootcell_show,
+ afs_proc_rootcell_write,
+ NULL) ||
+ !proc_create_net("servers", 0444, p, &afs_proc_servers_ops,
+ sizeof(struct seq_net_private)) ||
+ !proc_create_net_single("stats", 0444, p, afs_proc_stats_show, NULL) ||
+ !proc_create_net_data_write("sysname", 0644, p,
+ &afs_proc_sysname_ops,
+ afs_proc_sysname_write,
+ sizeof(struct seq_net_private),
+ NULL))
+ goto error_tree;
+
+ net->proc_afs = p;
+ _leave(" = 0");
+ return 0;
+
+error_tree:
+ proc_remove(p);
+error_dir:
+ _leave(" = -ENOMEM");
+ return -ENOMEM;
+}
+
+/*
+ * clean up the /proc/fs/afs/ directory
+ */
+void afs_proc_cleanup(struct afs_net *net)
+{
+ proc_remove(net->proc_afs);
+ net->proc_afs = NULL;
+}
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index 08735948f15d..a1b18082991b 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -46,7 +46,7 @@ int afs_open_socket(struct afs_net *net)
_enter("");
- ret = sock_create_kern(&init_net, AF_RXRPC, SOCK_DGRAM, PF_INET6, &socket);
+ ret = sock_create_kern(net->net, AF_RXRPC, SOCK_DGRAM, PF_INET6, &socket);
if (ret < 0)
goto error_1;
diff --git a/fs/afs/server.c b/fs/afs/server.c
index 3af4625e2f8c..1d329e6981d5 100644
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -228,7 +228,7 @@ static struct afs_server *afs_alloc_server(struct afs_net *net,
server->flags = (1UL << AFS_SERVER_FL_NEW);
server->update_at = ktime_get_real_seconds() + afs_server_update_delay;
rwlock_init(&server->fs_lock);
- INIT_LIST_HEAD(&server->cb_interests);
+ INIT_HLIST_HEAD(&server->cb_volumes);
rwlock_init(&server->cb_break_lock);
afs_inc_servers_outstanding(net);
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 9e5d7966621c..4d3e274207fb 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -48,6 +48,8 @@ struct file_system_type afs_fs_type = {
};
MODULE_ALIAS_FS("afs");
+int afs_net_id;
+
static const struct super_operations afs_super_ops = {
.statfs = afs_statfs,
.alloc_inode = afs_alloc_inode,
@@ -117,7 +119,7 @@ int __init afs_fs_init(void)
/*
* clean up the filesystem
*/
-void __exit afs_fs_exit(void)
+void afs_fs_exit(void)
{
_enter("");
@@ -351,14 +353,19 @@ static int afs_test_super(struct super_block *sb, void *data)
struct afs_super_info *as1 = data;
struct afs_super_info *as = AFS_FS_S(sb);
- return (as->net == as1->net &&
+ return (as->net_ns == as1->net_ns &&
as->volume &&
- as->volume->vid == as1->volume->vid);
+ as->volume->vid == as1->volume->vid &&
+ !as->dyn_root);
}
static int afs_dynroot_test_super(struct super_block *sb, void *data)
{
- return false;
+ struct afs_super_info *as1 = data;
+ struct afs_super_info *as = AFS_FS_S(sb);
+
+ return (as->net_ns == as1->net_ns &&
+ as->dyn_root);
}
static int afs_set_super(struct super_block *sb, void *data)
@@ -418,10 +425,14 @@ static int afs_fill_super(struct super_block *sb,
if (!sb->s_root)
goto error;
- if (params->dyn_root)
+ if (as->dyn_root) {
sb->s_d_op = &afs_dynroot_dentry_operations;
- else
+ ret = afs_dynroot_populate(sb);
+ if (ret < 0)
+ goto error;
+ } else {
sb->s_d_op = &afs_fs_dentry_operations;
+ }
_leave(" = 0");
return 0;
@@ -437,7 +448,7 @@ static struct afs_super_info *afs_alloc_sbi(struct afs_mount_params *params)
as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL);
if (as) {
- as->net = afs_get_net(params->net);
+ as->net_ns = get_net(params->net_ns);
if (params->dyn_root)
as->dyn_root = true;
else
@@ -450,12 +461,31 @@ static void afs_destroy_sbi(struct afs_super_info *as)
{
if (as) {
afs_put_volume(as->cell, as->volume);
- afs_put_cell(as->net, as->cell);
- afs_put_net(as->net);
+ afs_put_cell(afs_net(as->net_ns), as->cell);
+ put_net(as->net_ns);
kfree(as);
}
}
+static void afs_kill_super(struct super_block *sb)
+{
+ struct afs_super_info *as = AFS_FS_S(sb);
+ struct afs_net *net = afs_net(as->net_ns);
+
+ if (as->dyn_root)
+ afs_dynroot_depopulate(sb);
+
+ /* Clear the callback interests (which will do ilookup5) before
+ * deactivating the superblock.
+ */
+ if (as->volume)
+ afs_clear_callback_interests(net, as->volume->servers);
+ kill_anon_super(sb);
+ if (as->volume)
+ afs_deactivate_volume(as->volume);
+ afs_destroy_sbi(as);
+}
+
/*
* get an AFS superblock
*/
@@ -472,12 +502,13 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,
_enter(",,%s,%p", dev_name, options);
memset(&params, 0, sizeof(params));
- params.net = &__afs_net;
ret = -EINVAL;
if (current->nsproxy->net_ns != &init_net)
goto error;
-
+ params.net_ns = current->nsproxy->net_ns;
+ params.net = afs_net(params.net_ns);
+
/* parse the options and device name */
if (options) {
ret = afs_parse_options(&params, options, &dev_name);
@@ -563,21 +594,6 @@ error:
return ERR_PTR(ret);
}
-static void afs_kill_super(struct super_block *sb)
-{
- struct afs_super_info *as = AFS_FS_S(sb);
-
- /* Clear the callback interests (which will do ilookup5) before
- * deactivating the superblock.
- */
- if (as->volume)
- afs_clear_callback_interests(as->net, as->volume->servers);
- kill_anon_super(sb);
- if (as->volume)
- afs_deactivate_volume(as->volume);
- afs_destroy_sbi(as);
-}
-
/*
* Initialise an inode cache slab element prior to any use. Note that
* afs_alloc_inode() *must* reset anything that could incorrectly leak from one
diff --git a/fs/aio.c b/fs/aio.c
index 134e5b635d64..e1d20124ec0e 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1661,7 +1661,7 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
if (mask && !(mask & req->events))
return 0;
- mask = file->f_op->poll_mask(file, req->events);
+ mask = file->f_op->poll_mask(file, req->events) & req->events;
if (!mask)
return 0;
@@ -1719,7 +1719,7 @@ static ssize_t aio_poll(struct aio_kiocb *aiocb, struct iocb *iocb)
spin_lock_irq(&ctx->ctx_lock);
spin_lock(&req->head->lock);
- mask = req->file->f_op->poll_mask(req->file, req->events);
+ mask = req->file->f_op->poll_mask(req->file, req->events) & req->events;
if (!mask) {
__add_wait_queue(req->head, &req->wait);
list_add_tail(&aiocb->ki_list, &ctx->active_reqs);
diff --git a/fs/attr.c b/fs/attr.c
index d0b4d34878fb..e3d53bf12240 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -183,14 +183,14 @@ void setattr_copy(struct inode *inode, const struct iattr *attr)
if (ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
if (ia_valid & ATTR_ATIME)
- inode->i_atime = timespec_trunc(attr->ia_atime,
- inode->i_sb->s_time_gran);
+ inode->i_atime = timespec64_trunc(attr->ia_atime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MTIME)
- inode->i_mtime = timespec_trunc(attr->ia_mtime,
- inode->i_sb->s_time_gran);
+ inode->i_mtime = timespec64_trunc(attr->ia_mtime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_CTIME)
- inode->i_ctime = timespec_trunc(attr->ia_ctime,
- inode->i_sb->s_time_gran);
+ inode->i_ctime = timespec64_trunc(attr->ia_ctime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MODE) {
umode_t mode = attr->ia_mode;
@@ -227,7 +227,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
struct inode *inode = dentry->d_inode;
umode_t mode = inode->i_mode;
int error;
- struct timespec now;
+ struct timespec64 now;
unsigned int ia_valid = attr->ia_valid;
WARN_ON_ONCE(!inode_is_locked(inode));
diff --git a/fs/autofs/Kconfig b/fs/autofs/Kconfig
index 55c3930a907b..eaebcd430cc3 100644
--- a/fs/autofs/Kconfig
+++ b/fs/autofs/Kconfig
@@ -4,7 +4,7 @@ config AUTOFS4_FS
help
This name exists for people to just automatically pick up the
new name of the autofs Kconfig option. All it does is select
- thenew new option name.
+ the new option name.
It will go away in a release or two as people have
transitioned to just plain AUTOFS_FS.
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 213b51dbbb60..125e8bbd22a2 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -126,7 +126,7 @@ static int bad_inode_fiemap(struct inode *inode,
return -EIO;
}
-static int bad_inode_update_time(struct inode *inode, struct timespec *time,
+static int bad_inode_update_time(struct inode *inode, struct timespec64 *time,
int flags)
{
return -EIO;
diff --git a/fs/befs/ChangeLog b/fs/befs/ChangeLog
index 16f2dfe8c2f7..aff7eec8f327 100644
--- a/fs/befs/ChangeLog
+++ b/fs/befs/ChangeLog
@@ -389,7 +389,7 @@ Version 0.4 (2001-10-28)
(fs/nls/Config.in)
* Added Configure.help entries for CONFIG_BEFS_FS and CONFIG_DEBUG_BEFS
- (Documentation/Configure.help)
+ (currently at fs/befs/Kconfig)
2001-08-??
==========
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 4ad6f669fe34..0ac456b52bdd 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1621,8 +1621,8 @@ static int fill_files_note(struct memelfnote *note)
if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */
return -EINVAL;
size = round_up(size, PAGE_SIZE);
- data = vmalloc(size);
- if (!data)
+ data = kvmalloc(size, GFP_KERNEL);
+ if (ZERO_OR_NULL_PTR(data))
return -ENOMEM;
start_end_ofs = data + 2;
@@ -1639,7 +1639,7 @@ static int fill_files_note(struct memelfnote *note)
filename = file_path(file, name_curpos, remaining);
if (IS_ERR(filename)) {
if (PTR_ERR(filename) == -ENAMETOOLONG) {
- vfree(data);
+ kvfree(data);
size = size * 5 / 4;
goto alloc;
}
@@ -1932,7 +1932,7 @@ static void free_note_info(struct elf_note_info *info)
kfree(t);
}
kfree(info->psinfo.data);
- vfree(info->files.data);
+ kvfree(info->files.data);
}
#else
@@ -2010,7 +2010,7 @@ static int elf_note_info_init(struct elf_note_info *info)
INIT_LIST_HEAD(&info->thread_list);
/* Allocate space for ELF notes */
- info->notes = kmalloc(8 * sizeof(struct memelfnote), GFP_KERNEL);
+ info->notes = kmalloc_array(8, sizeof(struct memelfnote), GFP_KERNEL);
if (!info->notes)
return 0;
info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL);
@@ -2148,7 +2148,7 @@ static void free_note_info(struct elf_note_info *info)
/* Free data possibly allocated by fill_files_note(): */
if (info->notes_files)
- vfree(info->notes_files->data);
+ kvfree(info->notes_files->data);
kfree(info->prstatus);
kfree(info->psinfo);
@@ -2294,8 +2294,9 @@ static int elf_core_dump(struct coredump_params *cprm)
if (segs - 1 > ULONG_MAX / sizeof(*vma_filesz))
goto end_coredump;
- vma_filesz = vmalloc((segs - 1) * sizeof(*vma_filesz));
- if (!vma_filesz)
+ vma_filesz = kvmalloc(array_size(sizeof(*vma_filesz), (segs - 1)),
+ GFP_KERNEL);
+ if (ZERO_OR_NULL_PTR(vma_filesz))
goto end_coredump;
for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;
@@ -2402,7 +2403,7 @@ end_coredump:
cleanup:
free_note_info(&info);
kfree(shdr4extnum);
- vfree(vma_filesz);
+ kvfree(vma_filesz);
kfree(phdr4note);
kfree(elf);
out:
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index d90993adeffa..b53bb3729ac1 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -1600,7 +1600,8 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
if (!psinfo)
goto cleanup;
- notes = kmalloc(NUM_NOTES * sizeof(struct memelfnote), GFP_KERNEL);
+ notes = kmalloc_array(NUM_NOTES, sizeof(struct memelfnote),
+ GFP_KERNEL);
if (!notes)
goto cleanup;
fpu = kmalloc(sizeof(*fpu), GFP_KERNEL);
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 4de191563261..4b5fff31ef27 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -4,7 +4,7 @@
* Copyright (C) 1997 Richard Günther
*
* binfmt_misc detects binaries via a magic or filename extension and invokes
- * a specified wrapper. See Documentation/binfmt_misc.txt for more details.
+ * a specified wrapper. See Documentation/admin-guide/binfmt-misc.rst for more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 05e12aea2404..0dd87aaeb39a 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -205,7 +205,8 @@ __blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter,
if (nr_pages <= DIO_INLINE_BIO_VECS)
vecs = inline_vecs;
else {
- vecs = kmalloc(nr_pages * sizeof(struct bio_vec), GFP_KERNEL);
+ vecs = kmalloc_array(nr_pages, sizeof(struct bio_vec),
+ GFP_KERNEL);
if (!vecs)
return -ENOMEM;
}
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c
index dc062b195c46..a3fdb4fe967d 100644
--- a/fs/btrfs/check-integrity.c
+++ b/fs/btrfs/check-integrity.c
@@ -1603,8 +1603,8 @@ static int btrfsic_read_block(struct btrfsic_state *state,
num_pages = (block_ctx->len + (u64)PAGE_SIZE - 1) >>
PAGE_SHIFT;
- block_ctx->mem_to_free = kzalloc((sizeof(*block_ctx->datav) +
- sizeof(*block_ctx->pagev)) *
+ block_ctx->mem_to_free = kcalloc(sizeof(*block_ctx->datav) +
+ sizeof(*block_ctx->pagev),
num_pages, GFP_NOFS);
if (!block_ctx->mem_to_free)
return -ENOMEM;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index f4bf7874c24a..118346aceea9 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3197,7 +3197,7 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
size_t size, struct bio *bio,
unsigned long bio_flags);
void btrfs_set_range_writeback(void *private_data, u64 start, u64 end);
-int btrfs_page_mkwrite(struct vm_fault *vmf);
+vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf);
int btrfs_readpage(struct file *file, struct page *page);
void btrfs_evict_inode(struct inode *inode);
int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 51fc015c7d2c..cce6087d6880 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -4542,7 +4542,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
offset_in_extent = em_start - em->start;
em_end = extent_map_end(em);
em_len = em_end - em_start;
- disko = 0;
+ disko = em->block_start + offset_in_extent;
flags = 0;
/*
@@ -4565,8 +4565,6 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 bytenr = em->block_start -
(em->start - em->orig_start);
- disko = em->block_start + offset_in_extent;
-
/*
* As btrfs supports shared space, this information
* can be exported to userspace tools via
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index f660ba1e5e58..51e77d72068a 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1842,16 +1842,16 @@ out:
static void update_time_for_write(struct inode *inode)
{
- struct timespec now;
+ struct timespec64 now;
if (IS_NOCMTIME(inode))
return;
now = current_time(inode);
- if (!timespec_equal(&inode->i_mtime, &now))
+ if (!timespec64_equal(&inode->i_mtime, &now))
inode->i_mtime = now;
- if (!timespec_equal(&inode->i_ctime, &now))
+ if (!timespec64_equal(&inode->i_ctime, &now))
inode->i_ctime = now;
if (IS_I_VERSION(inode))
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 89b208201783..e9482f0db9d0 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5745,7 +5745,7 @@ static struct inode *new_simple_dir(struct super_block *s,
inode->i_mtime = current_time(inode);
inode->i_atime = inode->i_mtime;
inode->i_ctime = inode->i_mtime;
- BTRFS_I(inode)->i_otime = inode->i_mtime;
+ BTRFS_I(inode)->i_otime = timespec64_to_timespec(inode->i_mtime);
return inode;
}
@@ -6094,7 +6094,7 @@ static int btrfs_dirty_inode(struct inode *inode)
* This is a copy of file_update_time. We need this so we can return error on
* ENOSPC for updating the inode in the case of file write and mmap writes.
*/
-static int btrfs_update_time(struct inode *inode, struct timespec *now,
+static int btrfs_update_time(struct inode *inode, struct timespec64 *now,
int flags)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -6349,7 +6349,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
inode->i_mtime = current_time(inode);
inode->i_atime = inode->i_mtime;
inode->i_ctime = inode->i_mtime;
- BTRFS_I(inode)->i_otime = inode->i_mtime;
+ BTRFS_I(inode)->i_otime = timespec64_to_timespec(inode->i_mtime);
inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
struct btrfs_inode_item);
@@ -8872,7 +8872,7 @@ again:
* beyond EOF, then the page is guaranteed safe against truncation until we
* unlock the page.
*/
-int btrfs_page_mkwrite(struct vm_fault *vmf)
+vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf)
{
struct page *page = vmf->page;
struct inode *inode = file_inode(vmf->vma->vm_file);
@@ -8884,7 +8884,8 @@ int btrfs_page_mkwrite(struct vm_fault *vmf)
char *kaddr;
unsigned long zero_start;
loff_t size;
- int ret;
+ vm_fault_t ret;
+ int ret2;
int reserved = 0;
u64 reserved_space;
u64 page_start;
@@ -8906,17 +8907,14 @@ int btrfs_page_mkwrite(struct vm_fault *vmf)
* end up waiting indefinitely to get a lock on the page currently
* being processed by btrfs_page_mkwrite() function.
*/
- ret = btrfs_delalloc_reserve_space(inode, &data_reserved, page_start,
+ ret2 = btrfs_delalloc_reserve_space(inode, &data_reserved, page_start,
reserved_space);
- if (!ret) {
- ret = file_update_time(vmf->vma->vm_file);
+ if (!ret2) {
+ ret2 = file_update_time(vmf->vma->vm_file);
reserved = 1;
}
- if (ret) {
- if (ret == -ENOMEM)
- ret = VM_FAULT_OOM;
- else /* -ENOSPC, -EIO, etc */
- ret = VM_FAULT_SIGBUS;
+ if (ret2) {
+ ret = vmf_error(ret2);
if (reserved)
goto out;
goto out_noreserve;
@@ -8975,15 +8973,15 @@ again:
EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
0, 0, &cached_state);
- ret = btrfs_set_extent_delalloc(inode, page_start, end, 0,
+ ret2 = btrfs_set_extent_delalloc(inode, page_start, end, 0,
&cached_state, 0);
- if (ret) {
+ if (ret2) {
unlock_extent_cached(io_tree, page_start, page_end,
&cached_state);
ret = VM_FAULT_SIGBUS;
goto out_unlock;
}
- ret = 0;
+ ret2 = 0;
/* page is wholly or partially inside EOF */
if (page_start + PAGE_SIZE > size)
@@ -9008,7 +9006,7 @@ again:
unlock_extent_cached(io_tree, page_start, page_end, &cached_state);
out_unlock:
- if (!ret) {
+ if (!ret2) {
btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, true);
sb_end_pagefault(inode->i_sb);
extent_changeset_free(data_reserved);
@@ -9437,7 +9435,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
struct btrfs_root *dest = BTRFS_I(new_dir)->root;
struct inode *new_inode = new_dentry->d_inode;
struct inode *old_inode = old_dentry->d_inode;
- struct timespec ctime = current_time(old_inode);
+ struct timespec64 ctime = current_time(old_inode);
struct dentry *parent;
u64 old_ino = btrfs_ino(BTRFS_I(old_inode));
u64 new_ino = btrfs_ino(BTRFS_I(new_inode));
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index d29992f7dc63..c2837a32d689 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -562,7 +562,7 @@ static noinline int create_subvol(struct inode *dir,
struct btrfs_root *root = BTRFS_I(dir)->root;
struct btrfs_root *new_root;
struct btrfs_block_rsv block_rsv;
- struct timespec cur_time = current_time(dir);
+ struct timespec64 cur_time = current_time(dir);
struct inode *inode;
int ret;
int err;
@@ -2438,6 +2438,10 @@ static int btrfs_search_path_in_tree_user(struct inode *inode,
}
temp_inode = btrfs_iget(sb, &key2, root, NULL);
+ if (IS_ERR(temp_inode)) {
+ ret = PTR_ERR(temp_inode);
+ goto out;
+ }
ret = inode_permission(temp_inode, MAY_READ | MAY_EXEC);
iput(temp_inode);
if (ret) {
@@ -5391,7 +5395,7 @@ static long _btrfs_ioctl_set_received_subvol(struct file *file,
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_root_item *root_item = &root->root_item;
struct btrfs_trans_handle *trans;
- struct timespec ct = current_time(inode);
+ struct timespec64 ct = current_time(inode);
int ret = 0;
int received_uuid_changed;
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
index 6db3bda44aa5..c451285976ac 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -485,9 +485,9 @@ void btrfs_update_root_times(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
struct btrfs_root_item *item = &root->root_item;
- struct timespec ct;
+ struct timespec64 ct;
- ktime_get_real_ts(&ct);
+ ktime_get_real_ts64(&ct);
spin_lock(&root->root_item_lock);
btrfs_set_root_ctransid(item, trans->transid);
btrfs_set_stack_timespec_sec(&item->ctime, ct.tv_sec);
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index a59005862010..572306036477 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -2799,7 +2799,7 @@ static int scrub_extent(struct scrub_ctx *sctx, struct map_lookup *map,
have_csum = scrub_find_csum(sctx, logical, csum);
if (have_csum == 0)
++sctx->stat.no_csum;
- if (sctx->is_dev_replace && !have_csum) {
+ if (0 && sctx->is_dev_replace && !have_csum) {
ret = copy_nocow_pages(sctx, logical, l,
mirror_num,
physical_for_dev_replace);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 4485eae41e88..ff5f6c719976 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1422,7 +1422,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
struct dentry *dentry;
struct extent_buffer *tmp;
struct extent_buffer *old;
- struct timespec cur_time;
+ struct timespec64 cur_time;
int ret = 0;
u64 to_reserve = 0;
u64 index = 0;
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 5f7ad3d0df2e..292b3d72d725 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -370,7 +370,7 @@ static int start_read(struct inode *inode, struct ceph_rw_context *rw_ctx,
/* build page vector */
nr_pages = calc_pages_for(0, len);
- pages = kmalloc(sizeof(*pages) * nr_pages, GFP_KERNEL);
+ pages = kmalloc_array(nr_pages, sizeof(*pages), GFP_KERNEL);
if (!pages) {
ret = -ENOMEM;
goto out_put;
@@ -574,6 +574,7 @@ static u64 get_writepages_data_length(struct inode *inode,
*/
static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
{
+ struct timespec ts;
struct inode *inode;
struct ceph_inode_info *ci;
struct ceph_fs_client *fsc;
@@ -624,11 +625,12 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
set_bdi_congested(inode_to_bdi(inode), BLK_RW_ASYNC);
set_page_writeback(page);
+ ts = timespec64_to_timespec(inode->i_mtime);
err = ceph_osdc_writepages(&fsc->client->osdc, ceph_vino(inode),
&ci->i_layout, snapc, page_off, len,
ceph_wbc.truncate_seq,
ceph_wbc.truncate_size,
- &inode->i_mtime, &page, 1);
+ &ts, &page, 1);
if (err < 0) {
struct writeback_control tmp_wbc;
if (!wbc)
@@ -966,8 +968,9 @@ get_more_pages:
BUG_ON(pages);
max_pages = calc_pages_for(0, (u64)len);
- pages = kmalloc(max_pages * sizeof (*pages),
- GFP_NOFS);
+ pages = kmalloc_array(max_pages,
+ sizeof(*pages),
+ GFP_NOFS);
if (!pages) {
pool = fsc->wb_pagevec_pool;
pages = mempool_alloc(pool, GFP_NOFS);
@@ -1113,8 +1116,8 @@ new_request:
/* allocate new pages array for next request */
data_pages = pages;
- pages = kmalloc(locked_pages * sizeof (*pages),
- GFP_NOFS);
+ pages = kmalloc_array(locked_pages, sizeof(*pages),
+ GFP_NOFS);
if (!pages) {
pool = fsc->wb_pagevec_pool;
pages = mempool_alloc(pool, GFP_NOFS);
@@ -1131,7 +1134,7 @@ new_request:
pages = NULL;
}
- req->r_mtime = inode->i_mtime;
+ req->r_mtime = timespec64_to_timespec(inode->i_mtime);
rc = ceph_osdc_start_request(&fsc->client->osdc, req, true);
BUG_ON(rc);
req = NULL;
@@ -1731,7 +1734,7 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page)
goto out;
}
- req->r_mtime = inode->i_mtime;
+ req->r_mtime = timespec64_to_timespec(inode->i_mtime);
err = ceph_osdc_start_request(&fsc->client->osdc, req, false);
if (!err)
err = ceph_osdc_wait_request(&fsc->client->osdc, req);
@@ -1773,7 +1776,7 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page)
goto out_put;
}
- req->r_mtime = inode->i_mtime;
+ req->r_mtime = timespec64_to_timespec(inode->i_mtime);
err = ceph_osdc_start_request(&fsc->client->osdc, req, false);
if (!err)
err = ceph_osdc_wait_request(&fsc->client->osdc, req);
@@ -1934,8 +1937,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
0, false, true);
err = ceph_osdc_start_request(&fsc->client->osdc, rd_req, false);
- wr_req->r_mtime = ci->vfs_inode.i_mtime;
- wr_req->r_abort_on_full = true;
+ wr_req->r_mtime = timespec64_to_timespec(ci->vfs_inode.i_mtime);
err2 = ceph_osdc_start_request(&fsc->client->osdc, wr_req, false);
if (!err)
diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c
index bb524c880b1e..362900e42424 100644
--- a/fs/ceph/cache.c
+++ b/fs/ceph/cache.c
@@ -130,7 +130,7 @@ static enum fscache_checkaux ceph_fscache_inode_check_aux(
memset(&aux, 0, sizeof(aux));
aux.version = ci->i_version;
- aux.mtime = inode->i_mtime;
+ aux.mtime = timespec64_to_timespec(inode->i_mtime);
if (memcmp(data, &aux, sizeof(aux)) != 0)
return FSCACHE_CHECKAUX_OBSOLETE;
@@ -163,7 +163,7 @@ void ceph_fscache_register_inode_cookie(struct inode *inode)
if (!ci->fscache) {
memset(&aux, 0, sizeof(aux));
aux.version = ci->i_version;
- aux.mtime = inode->i_mtime;
+ aux.mtime = timespec64_to_timespec(inode->i_mtime);
ci->fscache = fscache_acquire_cookie(fsc->fscache,
&ceph_fscache_inode_object_def,
&ci->i_vino, sizeof(ci->i_vino),
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 23dbfae16156..990258cbd836 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -69,6 +69,8 @@ static char *gcap_string(char *s, int c)
*s++ = 'w';
if (c & CEPH_CAP_GBUFFER)
*s++ = 'b';
+ if (c & CEPH_CAP_GWREXTEND)
+ *s++ = 'a';
if (c & CEPH_CAP_GLAZYIO)
*s++ = 'l';
return s;
@@ -1358,9 +1360,9 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
arg.xattr_buf = NULL;
}
- arg.mtime = inode->i_mtime;
- arg.atime = inode->i_atime;
- arg.ctime = inode->i_ctime;
+ arg.mtime = timespec64_to_timespec(inode->i_mtime);
+ arg.atime = timespec64_to_timespec(inode->i_atime);
+ arg.ctime = timespec64_to_timespec(inode->i_ctime);
arg.op = op;
arg.caps = cap->implemented;
@@ -3022,30 +3024,41 @@ static void invalidate_aliases(struct inode *inode)
dput(prev);
}
+struct cap_extra_info {
+ struct ceph_string *pool_ns;
+ /* inline data */
+ u64 inline_version;
+ void *inline_data;
+ u32 inline_len;
+ /* dirstat */
+ bool dirstat_valid;
+ u64 nfiles;
+ u64 nsubdirs;
+ /* currently issued */
+ int issued;
+};
+
/*
* Handle a cap GRANT message from the MDS. (Note that a GRANT may
* actually be a revocation if it specifies a smaller cap set.)
*
* caller holds s_mutex and i_ceph_lock, we drop both.
*/
-static void handle_cap_grant(struct ceph_mds_client *mdsc,
- struct inode *inode, struct ceph_mds_caps *grant,
- struct ceph_string **pns, u64 inline_version,
- void *inline_data, u32 inline_len,
- struct ceph_buffer *xattr_buf,
+static void handle_cap_grant(struct inode *inode,
struct ceph_mds_session *session,
- struct ceph_cap *cap, int issued)
+ struct ceph_cap *cap,
+ struct ceph_mds_caps *grant,
+ struct ceph_buffer *xattr_buf,
+ struct cap_extra_info *extra_info)
__releases(ci->i_ceph_lock)
- __releases(mdsc->snap_rwsem)
+ __releases(session->s_mdsc->snap_rwsem)
{
struct ceph_inode_info *ci = ceph_inode(inode);
- int mds = session->s_mds;
int seq = le32_to_cpu(grant->seq);
int newcaps = le32_to_cpu(grant->caps);
int used, wanted, dirty;
u64 size = le64_to_cpu(grant->size);
u64 max_size = le64_to_cpu(grant->max_size);
- struct timespec mtime, atime, ctime;
int check_caps = 0;
bool wake = false;
bool writeback = false;
@@ -3055,7 +3068,7 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
bool fill_inline = false;
dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
- inode, cap, mds, seq, ceph_cap_string(newcaps));
+ inode, cap, session->s_mds, seq, ceph_cap_string(newcaps));
dout(" size %llu max_size %llu, i_size %llu\n", size, max_size,
inode->i_size);
@@ -3101,7 +3114,7 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
__check_cap_issue(ci, cap, newcaps);
if ((newcaps & CEPH_CAP_AUTH_SHARED) &&
- (issued & CEPH_CAP_AUTH_EXCL) == 0) {
+ (extra_info->issued & CEPH_CAP_AUTH_EXCL) == 0) {
inode->i_mode = le32_to_cpu(grant->mode);
inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid));
inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid));
@@ -3110,15 +3123,16 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
from_kgid(&init_user_ns, inode->i_gid));
}
- if ((newcaps & CEPH_CAP_AUTH_SHARED) &&
- (issued & CEPH_CAP_LINK_EXCL) == 0) {
+ if ((newcaps & CEPH_CAP_LINK_SHARED) &&
+ (extra_info->issued & CEPH_CAP_LINK_EXCL) == 0) {
set_nlink(inode, le32_to_cpu(grant->nlink));
if (inode->i_nlink == 0 &&
(newcaps & (CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL)))
deleted_inode = true;
}
- if ((issued & CEPH_CAP_XATTR_EXCL) == 0 && grant->xattr_len) {
+ if ((extra_info->issued & CEPH_CAP_XATTR_EXCL) == 0 &&
+ grant->xattr_len) {
int len = le32_to_cpu(grant->xattr_len);
u64 version = le64_to_cpu(grant->xattr_version);
@@ -3134,15 +3148,21 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
}
if (newcaps & CEPH_CAP_ANY_RD) {
+ struct timespec mtime, atime, ctime;
/* ctime/mtime/atime? */
ceph_decode_timespec(&mtime, &grant->mtime);
ceph_decode_timespec(&atime, &grant->atime);
ceph_decode_timespec(&ctime, &grant->ctime);
- ceph_fill_file_time(inode, issued,
+ ceph_fill_file_time(inode, extra_info->issued,
le32_to_cpu(grant->time_warp_seq),
&ctime, &mtime, &atime);
}
+ if ((newcaps & CEPH_CAP_FILE_SHARED) && extra_info->dirstat_valid) {
+ ci->i_files = extra_info->nfiles;
+ ci->i_subdirs = extra_info->nsubdirs;
+ }
+
if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) {
/* file layout may have changed */
s64 old_pool = ci->i_layout.pool_id;
@@ -3151,15 +3171,16 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
ceph_file_layout_from_legacy(&ci->i_layout, &grant->layout);
old_ns = rcu_dereference_protected(ci->i_layout.pool_ns,
lockdep_is_held(&ci->i_ceph_lock));
- rcu_assign_pointer(ci->i_layout.pool_ns, *pns);
+ rcu_assign_pointer(ci->i_layout.pool_ns, extra_info->pool_ns);
- if (ci->i_layout.pool_id != old_pool || *pns != old_ns)
+ if (ci->i_layout.pool_id != old_pool ||
+ extra_info->pool_ns != old_ns)
ci->i_ceph_flags &= ~CEPH_I_POOL_PERM;
- *pns = old_ns;
+ extra_info->pool_ns = old_ns;
/* size/truncate_seq? */
- queue_trunc = ceph_fill_file_size(inode, issued,
+ queue_trunc = ceph_fill_file_size(inode, extra_info->issued,
le32_to_cpu(grant->truncate_seq),
le64_to_cpu(grant->truncate_size),
size);
@@ -3238,24 +3259,26 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
}
BUG_ON(cap->issued & ~cap->implemented);
- if (inline_version > 0 && inline_version >= ci->i_inline_version) {
- ci->i_inline_version = inline_version;
+ if (extra_info->inline_version > 0 &&
+ extra_info->inline_version >= ci->i_inline_version) {
+ ci->i_inline_version = extra_info->inline_version;
if (ci->i_inline_version != CEPH_INLINE_NONE &&
(newcaps & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)))
fill_inline = true;
}
if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) {
- if (newcaps & ~issued)
+ if (newcaps & ~extra_info->issued)
wake = true;
- kick_flushing_inode_caps(mdsc, session, inode);
- up_read(&mdsc->snap_rwsem);
+ kick_flushing_inode_caps(session->s_mdsc, session, inode);
+ up_read(&session->s_mdsc->snap_rwsem);
} else {
spin_unlock(&ci->i_ceph_lock);
}
if (fill_inline)
- ceph_fill_inline_data(inode, NULL, inline_data, inline_len);
+ ceph_fill_inline_data(inode, NULL, extra_info->inline_data,
+ extra_info->inline_len);
if (queue_trunc)
ceph_queue_vmtruncate(inode);
@@ -3720,31 +3743,25 @@ void ceph_handle_caps(struct ceph_mds_session *session,
struct ceph_msg *msg)
{
struct ceph_mds_client *mdsc = session->s_mdsc;
- struct super_block *sb = mdsc->fsc->sb;
struct inode *inode;
struct ceph_inode_info *ci;
struct ceph_cap *cap;
struct ceph_mds_caps *h;
struct ceph_mds_cap_peer *peer = NULL;
struct ceph_snap_realm *realm = NULL;
- struct ceph_string *pool_ns = NULL;
- int mds = session->s_mds;
- int op, issued;
+ int op;
+ int msg_version = le16_to_cpu(msg->hdr.version);
u32 seq, mseq;
struct ceph_vino vino;
- u64 tid;
- u64 inline_version = 0;
- void *inline_data = NULL;
- u32 inline_len = 0;
void *snaptrace;
size_t snaptrace_len;
void *p, *end;
+ struct cap_extra_info extra_info = {};
- dout("handle_caps from mds%d\n", mds);
+ dout("handle_caps from mds%d\n", session->s_mds);
/* decode */
end = msg->front.iov_base + msg->front.iov_len;
- tid = le64_to_cpu(msg->hdr.tid);
if (msg->front.iov_len < sizeof(*h))
goto bad;
h = msg->front.iov_base;
@@ -3758,7 +3775,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
snaptrace_len = le32_to_cpu(h->snap_trace_len);
p = snaptrace + snaptrace_len;
- if (le16_to_cpu(msg->hdr.version) >= 2) {
+ if (msg_version >= 2) {
u32 flock_len;
ceph_decode_32_safe(&p, end, flock_len, bad);
if (p + flock_len > end)
@@ -3766,7 +3783,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
p += flock_len;
}
- if (le16_to_cpu(msg->hdr.version) >= 3) {
+ if (msg_version >= 3) {
if (op == CEPH_CAP_OP_IMPORT) {
if (p + sizeof(*peer) > end)
goto bad;
@@ -3778,16 +3795,16 @@ void ceph_handle_caps(struct ceph_mds_session *session,
}
}
- if (le16_to_cpu(msg->hdr.version) >= 4) {
- ceph_decode_64_safe(&p, end, inline_version, bad);
- ceph_decode_32_safe(&p, end, inline_len, bad);
- if (p + inline_len > end)
+ if (msg_version >= 4) {
+ ceph_decode_64_safe(&p, end, extra_info.inline_version, bad);
+ ceph_decode_32_safe(&p, end, extra_info.inline_len, bad);
+ if (p + extra_info.inline_len > end)
goto bad;
- inline_data = p;
- p += inline_len;
+ extra_info.inline_data = p;
+ p += extra_info.inline_len;
}
- if (le16_to_cpu(msg->hdr.version) >= 5) {
+ if (msg_version >= 5) {
struct ceph_osd_client *osdc = &mdsc->fsc->client->osdc;
u32 epoch_barrier;
@@ -3795,7 +3812,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
ceph_osdc_update_epoch_barrier(osdc, epoch_barrier);
}
- if (le16_to_cpu(msg->hdr.version) >= 8) {
+ if (msg_version >= 8) {
u64 flush_tid;
u32 caller_uid, caller_gid;
u32 pool_ns_len;
@@ -3809,13 +3826,33 @@ void ceph_handle_caps(struct ceph_mds_session *session,
ceph_decode_32_safe(&p, end, pool_ns_len, bad);
if (pool_ns_len > 0) {
ceph_decode_need(&p, end, pool_ns_len, bad);
- pool_ns = ceph_find_or_create_string(p, pool_ns_len);
+ extra_info.pool_ns =
+ ceph_find_or_create_string(p, pool_ns_len);
p += pool_ns_len;
}
}
+ if (msg_version >= 11) {
+ struct ceph_timespec *btime;
+ u64 change_attr;
+ u32 flags;
+
+ /* version >= 9 */
+ if (p + sizeof(*btime) > end)
+ goto bad;
+ btime = p;
+ p += sizeof(*btime);
+ ceph_decode_64_safe(&p, end, change_attr, bad);
+ /* version >= 10 */
+ ceph_decode_32_safe(&p, end, flags, bad);
+ /* version >= 11 */
+ extra_info.dirstat_valid = true;
+ ceph_decode_64_safe(&p, end, extra_info.nfiles, bad);
+ ceph_decode_64_safe(&p, end, extra_info.nsubdirs, bad);
+ }
+
/* lookup ino */
- inode = ceph_find_inode(sb, vino);
+ inode = ceph_find_inode(mdsc->fsc->sb, vino);
ci = ceph_inode(inode);
dout(" op %s ino %llx.%llx inode %p\n", ceph_cap_op_name(op), vino.ino,
vino.snap, inode);
@@ -3848,7 +3885,8 @@ void ceph_handle_caps(struct ceph_mds_session *session,
/* these will work even if we don't have a cap yet */
switch (op) {
case CEPH_CAP_OP_FLUSHSNAP_ACK:
- handle_cap_flushsnap_ack(inode, tid, h, session);
+ handle_cap_flushsnap_ack(inode, le64_to_cpu(msg->hdr.tid),
+ h, session);
goto done;
case CEPH_CAP_OP_EXPORT:
@@ -3867,10 +3905,9 @@ void ceph_handle_caps(struct ceph_mds_session *session,
down_read(&mdsc->snap_rwsem);
}
handle_cap_import(mdsc, inode, h, peer, session,
- &cap, &issued);
- handle_cap_grant(mdsc, inode, h, &pool_ns,
- inline_version, inline_data, inline_len,
- msg->middle, session, cap, issued);
+ &cap, &extra_info.issued);
+ handle_cap_grant(inode, session, cap,
+ h, msg->middle, &extra_info);
if (realm)
ceph_put_snap_realm(mdsc, realm);
goto done_unlocked;
@@ -3878,10 +3915,11 @@ void ceph_handle_caps(struct ceph_mds_session *session,
/* the rest require a cap */
spin_lock(&ci->i_ceph_lock);
- cap = __get_cap_for_mds(ceph_inode(inode), mds);
+ cap = __get_cap_for_mds(ceph_inode(inode), session->s_mds);
if (!cap) {
dout(" no cap on %p ino %llx.%llx from mds%d\n",
- inode, ceph_ino(inode), ceph_snap(inode), mds);
+ inode, ceph_ino(inode), ceph_snap(inode),
+ session->s_mds);
spin_unlock(&ci->i_ceph_lock);
goto flush_cap_releases;
}
@@ -3890,15 +3928,15 @@ void ceph_handle_caps(struct ceph_mds_session *session,
switch (op) {
case CEPH_CAP_OP_REVOKE:
case CEPH_CAP_OP_GRANT:
- __ceph_caps_issued(ci, &issued);
- issued |= __ceph_caps_dirty(ci);
- handle_cap_grant(mdsc, inode, h, &pool_ns,
- inline_version, inline_data, inline_len,
- msg->middle, session, cap, issued);
+ __ceph_caps_issued(ci, &extra_info.issued);
+ extra_info.issued |= __ceph_caps_dirty(ci);
+ handle_cap_grant(inode, session, cap,
+ h, msg->middle, &extra_info);
goto done_unlocked;
case CEPH_CAP_OP_FLUSH_ACK:
- handle_cap_flush_ack(inode, tid, h, session, cap);
+ handle_cap_flush_ack(inode, le64_to_cpu(msg->hdr.tid),
+ h, session, cap);
break;
case CEPH_CAP_OP_TRUNC:
@@ -3925,7 +3963,7 @@ done:
mutex_unlock(&session->s_mutex);
done_unlocked:
iput(inode);
- ceph_put_string(pool_ns);
+ ceph_put_string(extra_info.pool_ns);
return;
bad:
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 1a78dd6f8bf2..036ac0f3a393 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -1486,6 +1486,8 @@ const struct file_operations ceph_dir_fops = {
.release = ceph_release,
.unlocked_ioctl = ceph_ioctl,
.fsync = ceph_fsync,
+ .lock = ceph_lock,
+ .flock = ceph_flock,
};
const struct file_operations ceph_snapdir_fops = {
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index cf0e45b10121..ad0bed99b1d5 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -895,7 +895,6 @@ static void ceph_aio_retry_work(struct work_struct *work)
req->r_callback = ceph_aio_complete_req;
req->r_inode = inode;
req->r_priv = aio_req;
- req->r_abort_on_full = true;
ret = ceph_osdc_start_request(req->r_osdc, req, false);
out:
@@ -924,7 +923,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
int num_pages = 0;
int flags;
int ret;
- struct timespec mtime = current_time(inode);
+ struct timespec mtime = timespec64_to_timespec(current_time(inode));
size_t count = iov_iter_count(iter);
loff_t pos = iocb->ki_pos;
bool write = iov_iter_rw(iter) == WRITE;
@@ -1132,7 +1131,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
int flags;
int ret;
bool check_caps = false;
- struct timespec mtime = current_time(inode);
+ struct timespec mtime = timespec64_to_timespec(current_time(inode));
size_t count = iov_iter_count(from);
if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
@@ -1664,7 +1663,7 @@ static int ceph_zero_partial_object(struct inode *inode,
goto out;
}
- req->r_mtime = inode->i_mtime;
+ req->r_mtime = timespec64_to_timespec(inode->i_mtime);
ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
if (!ret) {
ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index ae056927080d..ee764ac352ab 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -662,6 +662,9 @@ void ceph_fill_file_time(struct inode *inode, int issued,
struct timespec *mtime, struct timespec *atime)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct timespec64 ctime64 = timespec_to_timespec64(*ctime);
+ struct timespec64 mtime64 = timespec_to_timespec64(*mtime);
+ struct timespec64 atime64 = timespec_to_timespec64(*atime);
int warn = 0;
if (issued & (CEPH_CAP_FILE_EXCL|
@@ -670,39 +673,39 @@ void ceph_fill_file_time(struct inode *inode, int issued,
CEPH_CAP_AUTH_EXCL|
CEPH_CAP_XATTR_EXCL)) {
if (ci->i_version == 0 ||
- timespec_compare(ctime, &inode->i_ctime) > 0) {
- dout("ctime %ld.%09ld -> %ld.%09ld inc w/ cap\n",
- inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
- ctime->tv_sec, ctime->tv_nsec);
- inode->i_ctime = *ctime;
+ timespec64_compare(&ctime64, &inode->i_ctime) > 0) {
+ dout("ctime %lld.%09ld -> %lld.%09ld inc w/ cap\n",
+ (long long)inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
+ (long long)ctime->tv_sec, ctime->tv_nsec);
+ inode->i_ctime = ctime64;
}
if (ci->i_version == 0 ||
ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) {
/* the MDS did a utimes() */
- dout("mtime %ld.%09ld -> %ld.%09ld "
+ dout("mtime %lld.%09ld -> %lld.%09ld "
"tw %d -> %d\n",
- inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
- mtime->tv_sec, mtime->tv_nsec,
+ (long long)inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
+ (long long)mtime->tv_sec, mtime->tv_nsec,
ci->i_time_warp_seq, (int)time_warp_seq);
- inode->i_mtime = *mtime;
- inode->i_atime = *atime;
+ inode->i_mtime = mtime64;
+ inode->i_atime = atime64;
ci->i_time_warp_seq = time_warp_seq;
} else if (time_warp_seq == ci->i_time_warp_seq) {
/* nobody did utimes(); take the max */
- if (timespec_compare(mtime, &inode->i_mtime) > 0) {
- dout("mtime %ld.%09ld -> %ld.%09ld inc\n",
- inode->i_mtime.tv_sec,
+ if (timespec64_compare(&mtime64, &inode->i_mtime) > 0) {
+ dout("mtime %lld.%09ld -> %lld.%09ld inc\n",
+ (long long)inode->i_mtime.tv_sec,
inode->i_mtime.tv_nsec,
- mtime->tv_sec, mtime->tv_nsec);
- inode->i_mtime = *mtime;
+ (long long)mtime->tv_sec, mtime->tv_nsec);
+ inode->i_mtime = mtime64;
}
- if (timespec_compare(atime, &inode->i_atime) > 0) {
- dout("atime %ld.%09ld -> %ld.%09ld inc\n",
- inode->i_atime.tv_sec,
+ if (timespec64_compare(&atime64, &inode->i_atime) > 0) {
+ dout("atime %lld.%09ld -> %lld.%09ld inc\n",
+ (long long)inode->i_atime.tv_sec,
inode->i_atime.tv_nsec,
- atime->tv_sec, atime->tv_nsec);
- inode->i_atime = *atime;
+ (long long)atime->tv_sec, atime->tv_nsec);
+ inode->i_atime = atime64;
}
} else if (issued & CEPH_CAP_FILE_EXCL) {
/* we did a utimes(); ignore mds values */
@@ -712,9 +715,9 @@ void ceph_fill_file_time(struct inode *inode, int issued,
} else {
/* we have no write|excl caps; whatever the MDS says is true */
if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) >= 0) {
- inode->i_ctime = *ctime;
- inode->i_mtime = *mtime;
- inode->i_atime = *atime;
+ inode->i_ctime = ctime64;
+ inode->i_mtime = mtime64;
+ inode->i_atime = atime64;
ci->i_time_warp_seq = time_warp_seq;
} else {
warn = 1;
@@ -739,7 +742,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
struct ceph_mds_reply_inode *info = iinfo->in;
struct ceph_inode_info *ci = ceph_inode(inode);
- int issued = 0, implemented, new_issued;
+ int issued, new_issued, info_caps;
struct timespec mtime, atime, ctime;
struct ceph_buffer *xattr_blob = NULL;
struct ceph_string *pool_ns = NULL;
@@ -754,8 +757,10 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
inode, ceph_vinop(inode), le64_to_cpu(info->version),
ci->i_version);
+ info_caps = le32_to_cpu(info->cap.caps);
+
/* prealloc new cap struct */
- if (info->cap.caps && ceph_snap(inode) == CEPH_NOSNAP)
+ if (info_caps && ceph_snap(inode) == CEPH_NOSNAP)
new_cap = ceph_get_cap(mdsc, caps_reservation);
/*
@@ -792,9 +797,9 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
le64_to_cpu(info->version) > (ci->i_version & ~1)))
new_version = true;
- issued = __ceph_caps_issued(ci, &implemented);
- issued |= implemented | __ceph_caps_dirty(ci);
- new_issued = ~issued & le32_to_cpu(info->cap.caps);
+ __ceph_caps_issued(ci, &issued);
+ issued |= __ceph_caps_dirty(ci);
+ new_issued = ~issued & info_caps;
/* update inode */
inode->i_rdev = le32_to_cpu(info->rdev);
@@ -826,6 +831,11 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
&ctime, &mtime, &atime);
}
+ if (new_version || (info_caps & CEPH_CAP_FILE_SHARED)) {
+ ci->i_files = le64_to_cpu(info->files);
+ ci->i_subdirs = le64_to_cpu(info->subdirs);
+ }
+
if (new_version ||
(new_issued & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR))) {
s64 old_pool = ci->i_layout.pool_id;
@@ -854,6 +864,18 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
}
}
+ /* layout and rstat are not tracked by capability, update them if
+ * the inode info is from auth mds */
+ if (new_version || (info->cap.flags & CEPH_CAP_FLAG_AUTH)) {
+ if (S_ISDIR(inode->i_mode)) {
+ ci->i_dir_layout = iinfo->dir_layout;
+ ci->i_rbytes = le64_to_cpu(info->rbytes);
+ ci->i_rfiles = le64_to_cpu(info->rfiles);
+ ci->i_rsubdirs = le64_to_cpu(info->rsubdirs);
+ ceph_decode_timespec(&ci->i_rctime, &info->rctime);
+ }
+ }
+
/* xattrs */
/* note that if i_xattrs.len <= 4, i_xattrs.data will still be NULL. */
if ((ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) &&
@@ -870,7 +892,8 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
}
/* finally update i_version */
- ci->i_version = le64_to_cpu(info->version);
+ if (le64_to_cpu(info->version) > ci->i_version)
+ ci->i_version = le64_to_cpu(info->version);
inode->i_mapping->a_ops = &ceph_aops;
@@ -918,15 +941,6 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
case S_IFDIR:
inode->i_op = &ceph_dir_iops;
inode->i_fop = &ceph_dir_fops;
-
- ci->i_dir_layout = iinfo->dir_layout;
-
- ci->i_files = le64_to_cpu(info->files);
- ci->i_subdirs = le64_to_cpu(info->subdirs);
- ci->i_rbytes = le64_to_cpu(info->rbytes);
- ci->i_rfiles = le64_to_cpu(info->rfiles);
- ci->i_rsubdirs = le64_to_cpu(info->rsubdirs);
- ceph_decode_timespec(&ci->i_rctime, &info->rctime);
break;
default:
pr_err("fill_inode %llx.%llx BAD mode 0%o\n",
@@ -934,12 +948,11 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
}
/* were we issued a capability? */
- if (info->cap.caps) {
+ if (info_caps) {
if (ceph_snap(inode) == CEPH_NOSNAP) {
- unsigned caps = le32_to_cpu(info->cap.caps);
ceph_add_cap(inode, session,
le64_to_cpu(info->cap.cap_id),
- cap_fmode, caps,
+ cap_fmode, info_caps,
le32_to_cpu(info->cap.wanted),
le32_to_cpu(info->cap.seq),
le32_to_cpu(info->cap.mseq),
@@ -949,7 +962,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
/* set dir completion flag? */
if (S_ISDIR(inode->i_mode) &&
ci->i_files == 0 && ci->i_subdirs == 0 &&
- (caps & CEPH_CAP_FILE_SHARED) &&
+ (info_caps & CEPH_CAP_FILE_SHARED) &&
(issued & CEPH_CAP_FILE_EXCL) == 0 &&
!__ceph_dir_is_complete(ci)) {
dout(" marking %p complete (empty)\n", inode);
@@ -962,8 +975,8 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
wake = true;
} else {
dout(" %p got snap_caps %s\n", inode,
- ceph_cap_string(le32_to_cpu(info->cap.caps)));
- ci->i_snap_caps |= le32_to_cpu(info->cap.caps);
+ ceph_cap_string(info_caps));
+ ci->i_snap_caps |= info_caps;
if (cap_fmode >= 0)
__ceph_get_fmode(ci, cap_fmode);
}
@@ -978,8 +991,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
int cache_caps = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
ci->i_inline_version = iinfo->inline_version;
if (ci->i_inline_version != CEPH_INLINE_NONE &&
- (locked_page ||
- (le32_to_cpu(info->cap.caps) & cache_caps)))
+ (locked_page || (info_caps & cache_caps)))
fill_inline = true;
}
@@ -1941,6 +1953,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
int err = 0;
int inode_dirty_flags = 0;
bool lock_snap_rwsem = false;
+ struct timespec ts;
prealloc_cf = ceph_alloc_cap_flush();
if (!prealloc_cf)
@@ -2015,44 +2028,44 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
}
if (ia_valid & ATTR_ATIME) {
- dout("setattr %p atime %ld.%ld -> %ld.%ld\n", inode,
- inode->i_atime.tv_sec, inode->i_atime.tv_nsec,
- attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec);
+ dout("setattr %p atime %lld.%ld -> %lld.%ld\n", inode,
+ (long long)inode->i_atime.tv_sec, inode->i_atime.tv_nsec,
+ (long long)attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec);
if (issued & CEPH_CAP_FILE_EXCL) {
ci->i_time_warp_seq++;
inode->i_atime = attr->ia_atime;
dirtied |= CEPH_CAP_FILE_EXCL;
} else if ((issued & CEPH_CAP_FILE_WR) &&
- timespec_compare(&inode->i_atime,
+ timespec64_compare(&inode->i_atime,
&attr->ia_atime) < 0) {
inode->i_atime = attr->ia_atime;
dirtied |= CEPH_CAP_FILE_WR;
} else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
- !timespec_equal(&inode->i_atime, &attr->ia_atime)) {
- ceph_encode_timespec(&req->r_args.setattr.atime,
- &attr->ia_atime);
+ !timespec64_equal(&inode->i_atime, &attr->ia_atime)) {
+ ts = timespec64_to_timespec(attr->ia_atime);
+ ceph_encode_timespec(&req->r_args.setattr.atime, &ts);
mask |= CEPH_SETATTR_ATIME;
release |= CEPH_CAP_FILE_SHARED |
CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
}
}
if (ia_valid & ATTR_MTIME) {
- dout("setattr %p mtime %ld.%ld -> %ld.%ld\n", inode,
- inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
- attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec);
+ dout("setattr %p mtime %lld.%ld -> %lld.%ld\n", inode,
+ (long long)inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
+ (long long)attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec);
if (issued & CEPH_CAP_FILE_EXCL) {
ci->i_time_warp_seq++;
inode->i_mtime = attr->ia_mtime;
dirtied |= CEPH_CAP_FILE_EXCL;
} else if ((issued & CEPH_CAP_FILE_WR) &&
- timespec_compare(&inode->i_mtime,
+ timespec64_compare(&inode->i_mtime,
&attr->ia_mtime) < 0) {
inode->i_mtime = attr->ia_mtime;
dirtied |= CEPH_CAP_FILE_WR;
} else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
- !timespec_equal(&inode->i_mtime, &attr->ia_mtime)) {
- ceph_encode_timespec(&req->r_args.setattr.mtime,
- &attr->ia_mtime);
+ !timespec64_equal(&inode->i_mtime, &attr->ia_mtime)) {
+ ts = timespec64_to_timespec(attr->ia_mtime);
+ ceph_encode_timespec(&req->r_args.setattr.mtime, &ts);
mask |= CEPH_SETATTR_MTIME;
release |= CEPH_CAP_FILE_SHARED |
CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
@@ -2082,9 +2095,9 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
if (ia_valid & ATTR_CTIME) {
bool only = (ia_valid & (ATTR_SIZE|ATTR_MTIME|ATTR_ATIME|
ATTR_MODE|ATTR_UID|ATTR_GID)) == 0;
- dout("setattr %p ctime %ld.%ld -> %ld.%ld (%s)\n", inode,
- inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
- attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
+ dout("setattr %p ctime %lld.%ld -> %lld.%ld (%s)\n", inode,
+ (long long)inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
+ (long long)attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
only ? "ctime only" : "ignored");
if (only) {
/*
@@ -2126,7 +2139,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
req->r_inode_drop = release;
req->r_args.setattr.mask = cpu_to_le32(mask);
req->r_num_caps = 1;
- req->r_stamp = attr->ia_ctime;
+ req->r_stamp = timespec64_to_timespec(attr->ia_ctime);
err = ceph_mdsc_do_request(mdsc, NULL, req);
}
dout("setattr %p result=%d (%s locally, %d remote)\n", inode, err,
@@ -2178,6 +2191,7 @@ int __ceph_do_getattr(struct inode *inode, struct page *locked_page,
struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_mds_request *req;
+ int mode;
int err;
if (ceph_snap(inode) == CEPH_SNAPDIR) {
@@ -2190,7 +2204,8 @@ int __ceph_do_getattr(struct inode *inode, struct page *locked_page,
if (!force && ceph_caps_issued_mask(ceph_inode(inode), mask, 1))
return 0;
- req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS);
+ mode = (mask & CEPH_STAT_RSTAT) ? USE_AUTH_MDS : USE_ANY_MDS;
+ req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, mode);
if (IS_ERR(req))
return PTR_ERR(req);
req->r_inode = inode;
@@ -2261,6 +2276,14 @@ int ceph_getattr(const struct path *path, struct kstat *stat,
stat->size = ci->i_files + ci->i_subdirs;
stat->blocks = 0;
stat->blksize = 65536;
+ /*
+ * Some applications rely on the number of st_nlink
+ * value on directories to be either 0 (if unlinked)
+ * or 2 + number of subdirectories.
+ */
+ if (stat->nlink == 1)
+ /* '.' + '..' + subdirs */
+ stat->nlink = 1 + 1 + ci->i_subdirs;
}
}
return err;
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 5ece2e6ad154..dc8bc664a871 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -2958,12 +2958,15 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
rec.v2.flock_len = (__force __le32)
((ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) ? 0 : 1);
} else {
+ struct timespec ts;
rec.v1.cap_id = cpu_to_le64(cap->cap_id);
rec.v1.wanted = cpu_to_le32(__ceph_caps_wanted(ci));
rec.v1.issued = cpu_to_le32(cap->issued);
rec.v1.size = cpu_to_le64(inode->i_size);
- ceph_encode_timespec(&rec.v1.mtime, &inode->i_mtime);
- ceph_encode_timespec(&rec.v1.atime, &inode->i_atime);
+ ts = timespec64_to_timespec(inode->i_mtime);
+ ceph_encode_timespec(&rec.v1.mtime, &ts);
+ ts = timespec64_to_timespec(inode->i_atime);
+ ceph_encode_timespec(&rec.v1.atime, &ts);
rec.v1.snaprealm = cpu_to_le64(ci->i_snap_realm->ino);
rec.v1.pathbase = cpu_to_le64(pathbase);
}
@@ -2992,8 +2995,9 @@ encode_again:
num_flock_locks = 0;
}
if (num_fcntl_locks + num_flock_locks > 0) {
- flocks = kmalloc((num_fcntl_locks + num_flock_locks) *
- sizeof(struct ceph_filelock), GFP_NOFS);
+ flocks = kmalloc_array(num_fcntl_locks + num_flock_locks,
+ sizeof(struct ceph_filelock),
+ GFP_NOFS);
if (!flocks) {
err = -ENOMEM;
goto out_free;
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index 041c27ea8de1..af81555c14fd 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -594,9 +594,9 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
BUG_ON(capsnap->writing);
capsnap->size = inode->i_size;
- capsnap->mtime = inode->i_mtime;
- capsnap->atime = inode->i_atime;
- capsnap->ctime = inode->i_ctime;
+ capsnap->mtime = timespec64_to_timespec(inode->i_mtime);
+ capsnap->atime = timespec64_to_timespec(inode->i_atime);
+ capsnap->ctime = timespec64_to_timespec(inode->i_ctime);
capsnap->time_warp_seq = ci->i_time_warp_seq;
capsnap->truncate_size = ci->i_truncate_size;
capsnap->truncate_seq = ci->i_truncate_seq;
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index b33082e6878f..95a3b3ac9b6e 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -45,7 +45,7 @@ static void ceph_put_super(struct super_block *s)
static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct ceph_fs_client *fsc = ceph_inode_to_client(d_inode(dentry));
- struct ceph_monmap *monmap = fsc->client->monc.monmap;
+ struct ceph_mon_client *monc = &fsc->client->monc;
struct ceph_statfs st;
u64 fsid;
int err;
@@ -58,7 +58,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
}
dout("statfs\n");
- err = ceph_monc_do_statfs(&fsc->client->monc, data_pool, &st);
+ err = ceph_monc_do_statfs(monc, data_pool, &st);
if (err < 0)
return err;
@@ -94,8 +94,11 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
buf->f_namelen = NAME_MAX;
/* Must convert the fsid, for consistent values across arches */
- fsid = le64_to_cpu(*(__le64 *)(&monmap->fsid)) ^
- le64_to_cpu(*((__le64 *)&monmap->fsid + 1));
+ mutex_lock(&monc->mutex);
+ fsid = le64_to_cpu(*(__le64 *)(&monc->monmap->fsid)) ^
+ le64_to_cpu(*((__le64 *)&monc->monmap->fsid + 1));
+ mutex_unlock(&monc->mutex);
+
buf->f_fsid.val[0] = fsid & 0xffffffff;
buf->f_fsid.val[1] = fsid >> 32;
@@ -256,19 +259,19 @@ static int parse_fsopt_token(char *c, void *private)
break;
/* misc */
case Opt_wsize:
- if (intval < PAGE_SIZE || intval > CEPH_MAX_WRITE_SIZE)
+ if (intval < (int)PAGE_SIZE || intval > CEPH_MAX_WRITE_SIZE)
return -EINVAL;
fsopt->wsize = ALIGN(intval, PAGE_SIZE);
break;
case Opt_rsize:
- if (intval < PAGE_SIZE || intval > CEPH_MAX_READ_SIZE)
+ if (intval < (int)PAGE_SIZE || intval > CEPH_MAX_READ_SIZE)
return -EINVAL;
fsopt->rsize = ALIGN(intval, PAGE_SIZE);
break;
case Opt_rasize:
if (intval < 0)
return -EINVAL;
- fsopt->rasize = ALIGN(intval + PAGE_SIZE - 1, PAGE_SIZE);
+ fsopt->rasize = ALIGN(intval, PAGE_SIZE);
break;
case Opt_caps_wanted_delay_min:
if (intval < 1)
@@ -286,7 +289,7 @@ static int parse_fsopt_token(char *c, void *private)
fsopt->max_readdir = intval;
break;
case Opt_readdir_max_bytes:
- if (intval < PAGE_SIZE && intval != 0)
+ if (intval < (int)PAGE_SIZE && intval != 0)
return -EINVAL;
fsopt->max_readdir_bytes = intval;
break;
@@ -534,6 +537,8 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
seq_puts(m, ",noasyncreaddir");
if ((fsopt->flags & CEPH_MOUNT_OPT_DCACHE) == 0)
seq_puts(m, ",nodcache");
+ if (fsopt->flags & CEPH_MOUNT_OPT_INO32)
+ seq_puts(m, ",ino32");
if (fsopt->flags & CEPH_MOUNT_OPT_FSCACHE) {
seq_show_option(m, "fsc", fsopt->fscache_uniq);
}
@@ -551,7 +556,7 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
if (fsopt->mds_namespace)
seq_show_option(m, "mds_namespace", fsopt->mds_namespace);
- if (fsopt->wsize)
+ if (fsopt->wsize != CEPH_MAX_WRITE_SIZE)
seq_printf(m, ",wsize=%d", fsopt->wsize);
if (fsopt->rsize != CEPH_MAX_READ_SIZE)
seq_printf(m, ",rsize=%d", fsopt->rsize);
@@ -616,7 +621,9 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
err = PTR_ERR(fsc->client);
goto fail;
}
+
fsc->client->extra_mon_dispatch = extra_mon_dispatch;
+ fsc->client->osdc.abort_on_full = true;
if (!fsopt->mds_namespace) {
ceph_monc_want_map(&fsc->client->monc, CEPH_SUB_MDSMAP,
@@ -674,6 +681,13 @@ fail:
return ERR_PTR(err);
}
+static void flush_fs_workqueues(struct ceph_fs_client *fsc)
+{
+ flush_workqueue(fsc->wb_wq);
+ flush_workqueue(fsc->pg_inv_wq);
+ flush_workqueue(fsc->trunc_wq);
+}
+
static void destroy_fs_client(struct ceph_fs_client *fsc)
{
dout("destroy_fs_client %p\n", fsc);
@@ -793,6 +807,7 @@ static void ceph_umount_begin(struct super_block *sb)
if (!fsc)
return;
fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
+ ceph_osdc_abort_requests(&fsc->client->osdc, -EIO);
ceph_mdsc_force_umount(fsc->mdsc);
return;
}
@@ -1088,6 +1103,8 @@ static void ceph_kill_sb(struct super_block *s)
dout("kill_sb %p\n", s);
ceph_mdsc_pre_umount(fsc->mdsc);
+ flush_fs_workqueues(fsc);
+
generic_shutdown_super(s);
fsc->client->extra_mon_dispatch = NULL;
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 315f7e63e7cc..5bc8edb4c2a6 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -50,10 +50,14 @@ struct ceph_vxattr {
size_t name_size; /* strlen(name) + 1 (for '\0') */
size_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val,
size_t size);
- bool readonly, hidden;
bool (*exists_cb)(struct ceph_inode_info *ci);
+ unsigned int flags;
};
+#define VXATTR_FLAG_READONLY (1<<0)
+#define VXATTR_FLAG_HIDDEN (1<<1)
+#define VXATTR_FLAG_RSTAT (1<<2)
+
/* layouts */
static bool ceph_vxattrcb_layout_exists(struct ceph_inode_info *ci)
@@ -262,32 +266,31 @@ static size_t ceph_vxattrcb_quota_max_files(struct ceph_inode_info *ci,
#define CEPH_XATTR_NAME2(_type, _name, _name2) \
XATTR_CEPH_PREFIX #_type "." #_name "." #_name2
-#define XATTR_NAME_CEPH(_type, _name) \
+#define XATTR_NAME_CEPH(_type, _name, _flags) \
{ \
.name = CEPH_XATTR_NAME(_type, _name), \
.name_size = sizeof (CEPH_XATTR_NAME(_type, _name)), \
.getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \
- .readonly = true, \
- .hidden = false, \
- .exists_cb = NULL, \
+ .exists_cb = NULL, \
+ .flags = (VXATTR_FLAG_READONLY | _flags), \
}
+#define XATTR_RSTAT_FIELD(_type, _name) \
+ XATTR_NAME_CEPH(_type, _name, VXATTR_FLAG_RSTAT)
#define XATTR_LAYOUT_FIELD(_type, _name, _field) \
{ \
.name = CEPH_XATTR_NAME2(_type, _name, _field), \
.name_size = sizeof (CEPH_XATTR_NAME2(_type, _name, _field)), \
.getxattr_cb = ceph_vxattrcb_ ## _name ## _ ## _field, \
- .readonly = false, \
- .hidden = true, \
.exists_cb = ceph_vxattrcb_layout_exists, \
+ .flags = VXATTR_FLAG_HIDDEN, \
}
#define XATTR_QUOTA_FIELD(_type, _name) \
{ \
.name = CEPH_XATTR_NAME(_type, _name), \
.name_size = sizeof(CEPH_XATTR_NAME(_type, _name)), \
.getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \
- .readonly = false, \
- .hidden = true, \
.exists_cb = ceph_vxattrcb_quota_exists, \
+ .flags = VXATTR_FLAG_HIDDEN, \
}
static struct ceph_vxattr ceph_dir_vxattrs[] = {
@@ -295,30 +298,28 @@ static struct ceph_vxattr ceph_dir_vxattrs[] = {
.name = "ceph.dir.layout",
.name_size = sizeof("ceph.dir.layout"),
.getxattr_cb = ceph_vxattrcb_layout,
- .readonly = false,
- .hidden = true,
.exists_cb = ceph_vxattrcb_layout_exists,
+ .flags = VXATTR_FLAG_HIDDEN,
},
XATTR_LAYOUT_FIELD(dir, layout, stripe_unit),
XATTR_LAYOUT_FIELD(dir, layout, stripe_count),
XATTR_LAYOUT_FIELD(dir, layout, object_size),
XATTR_LAYOUT_FIELD(dir, layout, pool),
XATTR_LAYOUT_FIELD(dir, layout, pool_namespace),
- XATTR_NAME_CEPH(dir, entries),
- XATTR_NAME_CEPH(dir, files),
- XATTR_NAME_CEPH(dir, subdirs),
- XATTR_NAME_CEPH(dir, rentries),
- XATTR_NAME_CEPH(dir, rfiles),
- XATTR_NAME_CEPH(dir, rsubdirs),
- XATTR_NAME_CEPH(dir, rbytes),
- XATTR_NAME_CEPH(dir, rctime),
+ XATTR_NAME_CEPH(dir, entries, 0),
+ XATTR_NAME_CEPH(dir, files, 0),
+ XATTR_NAME_CEPH(dir, subdirs, 0),
+ XATTR_RSTAT_FIELD(dir, rentries),
+ XATTR_RSTAT_FIELD(dir, rfiles),
+ XATTR_RSTAT_FIELD(dir, rsubdirs),
+ XATTR_RSTAT_FIELD(dir, rbytes),
+ XATTR_RSTAT_FIELD(dir, rctime),
{
.name = "ceph.quota",
.name_size = sizeof("ceph.quota"),
.getxattr_cb = ceph_vxattrcb_quota,
- .readonly = false,
- .hidden = true,
.exists_cb = ceph_vxattrcb_quota_exists,
+ .flags = VXATTR_FLAG_HIDDEN,
},
XATTR_QUOTA_FIELD(quota, max_bytes),
XATTR_QUOTA_FIELD(quota, max_files),
@@ -333,9 +334,8 @@ static struct ceph_vxattr ceph_file_vxattrs[] = {
.name = "ceph.file.layout",
.name_size = sizeof("ceph.file.layout"),
.getxattr_cb = ceph_vxattrcb_layout,
- .readonly = false,
- .hidden = true,
.exists_cb = ceph_vxattrcb_layout_exists,
+ .flags = VXATTR_FLAG_HIDDEN,
},
XATTR_LAYOUT_FIELD(file, layout, stripe_unit),
XATTR_LAYOUT_FIELD(file, layout, stripe_count),
@@ -374,9 +374,10 @@ static size_t __init vxattrs_name_size(struct ceph_vxattr *vxattrs)
struct ceph_vxattr *vxattr;
size_t size = 0;
- for (vxattr = vxattrs; vxattr->name; vxattr++)
- if (!vxattr->hidden)
+ for (vxattr = vxattrs; vxattr->name; vxattr++) {
+ if (!(vxattr->flags & VXATTR_FLAG_HIDDEN))
size += vxattr->name_size;
+ }
return size;
}
@@ -809,7 +810,10 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
/* let's see if a virtual xattr was requested */
vxattr = ceph_match_vxattr(inode, name);
if (vxattr) {
- err = ceph_do_getattr(inode, 0, true);
+ int mask = 0;
+ if (vxattr->flags & VXATTR_FLAG_RSTAT)
+ mask |= CEPH_STAT_RSTAT;
+ err = ceph_do_getattr(inode, mask, true);
if (err)
return err;
err = -ENODATA;
@@ -919,7 +923,7 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)
err = namelen;
if (vxattrs) {
for (i = 0; vxattrs[i].name; i++) {
- if (!vxattrs[i].hidden &&
+ if (!(vxattrs[i].flags & VXATTR_FLAG_HIDDEN) &&
!(vxattrs[i].exists_cb &&
!vxattrs[i].exists_cb(ci))) {
len = sprintf(names, "%s", vxattrs[i].name);
@@ -1024,7 +1028,7 @@ int __ceph_setxattr(struct inode *inode, const char *name,
vxattr = ceph_match_vxattr(inode, name);
if (vxattr) {
- if (vxattr->readonly)
+ if (vxattr->flags & VXATTR_FLAG_READONLY)
return -EOPNOTSUPP;
if (value && !strncmp(vxattr->name, "ceph.quota", 10))
check_realm = true;
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index a3b56544c21b..3d19595eb352 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -428,7 +428,7 @@ asn1_oid_decode(struct asn1_ctx *ctx,
if (size < 2 || size > UINT_MAX/sizeof(unsigned long))
return 0;
- *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
+ *oid = kmalloc_array(size, sizeof(unsigned long), GFP_ATOMIC);
if (*oid == NULL)
return 0;
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
index edf5f40898bf..e1553d1e0e50 100644
--- a/fs/cifs/cache.c
+++ b/fs/cifs/cache.c
@@ -128,8 +128,8 @@ fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data,
memset(&auxdata, 0, sizeof(auxdata));
auxdata.eof = cifsi->server_eof;
- auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
- auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
+ auxdata.last_write_time = timespec64_to_timespec(cifsi->vfs_inode.i_mtime);
+ auxdata.last_change_time = timespec64_to_timespec(cifsi->vfs_inode.i_ctime);
if (memcmp(data, &auxdata, datalen) != 0)
return FSCACHE_CHECKAUX_OBSOLETE;
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 13a8a77322c9..1d377b7f2860 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -747,8 +747,8 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
return;
- ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
- GFP_KERNEL);
+ ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
+ GFP_KERNEL);
if (!ppace)
return;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 5aca336642c0..42329b25877d 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2077,7 +2077,7 @@ struct cifs_writedata *
cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
{
struct page **pages =
- kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
+ kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
if (pages)
return cifs_writedata_direct_alloc(pages, complete);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 87eece6fbd48..8d41ca7bfcf1 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2900,7 +2900,7 @@ static struct cifs_readdata *
cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete)
{
struct page **pages =
- kzalloc(sizeof(struct page *) * nr_pages, GFP_KERNEL);
+ kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
struct cifs_readdata *ret = NULL;
if (pages) {
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index 25d3f66b2d50..85145a763021 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -129,8 +129,8 @@ static void cifs_fscache_acquire_inode_cookie(struct cifsInodeInfo *cifsi,
memset(&auxdata, 0, sizeof(auxdata));
auxdata.eof = cifsi->server_eof;
- auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
- auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
+ auxdata.last_write_time = timespec64_to_timespec(cifsi->vfs_inode.i_mtime);
+ auxdata.last_change_time = timespec64_to_timespec(cifsi->vfs_inode.i_ctime);
cifsi->fscache =
fscache_acquire_cookie(tcon->fscache,
@@ -166,8 +166,8 @@ void cifs_fscache_release_inode_cookie(struct inode *inode)
if (cifsi->fscache) {
memset(&auxdata, 0, sizeof(auxdata));
auxdata.eof = cifsi->server_eof;
- auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
- auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
+ auxdata.last_write_time = timespec64_to_timespec(cifsi->vfs_inode.i_mtime);
+ auxdata.last_change_time = timespec64_to_timespec(cifsi->vfs_inode.i_ctime);
cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
fscache_relinquish_cookie(cifsi->fscache, &auxdata, false);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 745fd7fe8d0e..f4697f548a39 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -95,6 +95,7 @@ static void
cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
{
struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+ struct timespec ts;
cifs_dbg(FYI, "%s: revalidating inode %llu\n",
__func__, cifs_i->uniqueid);
@@ -113,7 +114,8 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
}
/* revalidate if mtime or size have changed */
- if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
+ ts = timespec64_to_timespec(inode->i_mtime);
+ if (timespec_equal(&ts, &fattr->cf_mtime) &&
cifs_i->server_eof == fattr->cf_eof) {
cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
__func__, cifs_i->uniqueid);
@@ -162,9 +164,9 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
cifs_revalidate_cache(inode, fattr);
spin_lock(&inode->i_lock);
- inode->i_atime = fattr->cf_atime;
- inode->i_mtime = fattr->cf_mtime;
- inode->i_ctime = fattr->cf_ctime;
+ inode->i_atime = timespec_to_timespec64(fattr->cf_atime);
+ inode->i_mtime = timespec_to_timespec64(fattr->cf_mtime);
+ inode->i_ctime = timespec_to_timespec64(fattr->cf_ctime);
inode->i_rdev = fattr->cf_rdev;
cifs_nlink_fattr_to_inode(inode, fattr);
inode->i_uid = fattr->cf_uid;
@@ -1123,14 +1125,14 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
if (attrs->ia_valid & ATTR_ATIME) {
set_time = true;
info_buf.LastAccessTime =
- cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
+ cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_atime)));
} else
info_buf.LastAccessTime = 0;
if (attrs->ia_valid & ATTR_MTIME) {
set_time = true;
info_buf.LastWriteTime =
- cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
+ cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_mtime)));
} else
info_buf.LastWriteTime = 0;
@@ -1143,7 +1145,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
cifs_dbg(FYI, "CIFS - CTIME changed\n");
info_buf.ChangeTime =
- cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
+ cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_ctime)));
} else
info_buf.ChangeTime = 0;
@@ -1792,7 +1794,7 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
* with unix extensions enabled.
*/
info_buf_source =
- kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
+ kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
GFP_KERNEL);
if (info_buf_source == NULL) {
rc = -ENOMEM;
@@ -2060,8 +2062,8 @@ int cifs_getattr(const struct path *path, struct kstat *stat,
/* old CIFS Unix Extensions doesn't return create time */
if (CIFS_I(inode)->createtime) {
stat->result_mask |= STATX_BTIME;
- stat->btime =
- cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
+ stat->btime = timespec_to_timespec64(
+ cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime)));
}
stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
@@ -2267,17 +2269,17 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
args->gid = INVALID_GID; /* no change */
if (attrs->ia_valid & ATTR_ATIME)
- args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
+ args->atime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_atime));
else
args->atime = NO_CHANGE_64;
if (attrs->ia_valid & ATTR_MTIME)
- args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
+ args->mtime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_mtime));
else
args->mtime = NO_CHANGE_64;
if (attrs->ia_valid & ATTR_CTIME)
- args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
+ args->ctime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_ctime));
else
args->ctime = NO_CHANGE_64;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index f90d4ad6624c..af29ade195c0 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -789,7 +789,7 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
GFP_KERNEL);
if (!bv) {
- bv = vmalloc(max_pages * sizeof(struct bio_vec));
+ bv = vmalloc(array_size(max_pages, sizeof(struct bio_vec)));
if (!bv)
return -ENOMEM;
}
@@ -799,7 +799,7 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
GFP_KERNEL);
if (!pages) {
- pages = vmalloc(max_pages * sizeof(struct page *));
+ pages = vmalloc(array_size(max_pages, sizeof(struct page *)));
if (!pages) {
kvfree(bv);
return -ENOMEM;
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 48e2004c75fb..af032e1a3eac 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -3471,7 +3471,7 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
if (!num)
return -EINVAL;
- iov = kmalloc(sizeof(struct kvec) * num, GFP_KERNEL);
+ iov = kmalloc_array(num, sizeof(struct kvec), GFP_KERNEL);
if (!iov)
return -ENOMEM;
@@ -3535,7 +3535,7 @@ SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
int rc;
int len = (2 * UniStrnlen((wchar_t *)target_file, PATH_MAX));
- data = kmalloc(sizeof(void *) * 2, GFP_KERNEL);
+ data = kmalloc_array(2, sizeof(void *), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -3583,7 +3583,7 @@ SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
int rc;
int len = (2 * UniStrnlen((wchar_t *)target_file, PATH_MAX));
- data = kmalloc(sizeof(void *) * 2, GFP_KERNEL);
+ data = kmalloc_array(2, sizeof(void *), GFP_KERNEL);
if (!data)
return -ENOMEM;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 24887a0898c0..1f1a68f89110 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -844,8 +844,8 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
int rc;
if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
- new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1),
- GFP_KERNEL);
+ new_iov = kmalloc_array(n_vec + 1, sizeof(struct kvec),
+ GFP_KERNEL);
if (!new_iov) {
/* otherwise cifs_send_recv below sets resp_buf_type */
*resp_buf_type = CIFS_NO_BUFFER;
@@ -886,8 +886,8 @@ smb2_send_recv(const unsigned int xid, struct cifs_ses *ses,
__be32 rfc1002_marker;
if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
- new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1),
- GFP_KERNEL);
+ new_iov = kmalloc_array(n_vec + 1, sizeof(struct kvec),
+ GFP_KERNEL);
if (!new_iov)
return -ENOMEM;
} else
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
index ca599df0dcb1..f3d543dd9a98 100644
--- a/fs/coda/coda_linux.c
+++ b/fs/coda/coda_linux.c
@@ -105,11 +105,11 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
if (attr->va_size != -1)
inode->i_blocks = (attr->va_size + 511) >> 9;
if (attr->va_atime.tv_sec != -1)
- inode->i_atime = attr->va_atime;
+ inode->i_atime = timespec_to_timespec64(attr->va_atime);
if (attr->va_mtime.tv_sec != -1)
- inode->i_mtime = attr->va_mtime;
+ inode->i_mtime = timespec_to_timespec64(attr->va_mtime);
if (attr->va_ctime.tv_sec != -1)
- inode->i_ctime = attr->va_ctime;
+ inode->i_ctime = timespec_to_timespec64(attr->va_ctime);
}
@@ -175,13 +175,13 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
vattr->va_size = iattr->ia_size;
}
if ( valid & ATTR_ATIME ) {
- vattr->va_atime = iattr->ia_atime;
+ vattr->va_atime = timespec64_to_timespec(iattr->ia_atime);
}
if ( valid & ATTR_MTIME ) {
- vattr->va_mtime = iattr->ia_mtime;
+ vattr->va_mtime = timespec64_to_timespec(iattr->ia_mtime);
}
if ( valid & ATTR_CTIME ) {
- vattr->va_ctime = iattr->ia_ctime;
+ vattr->va_ctime = timespec64_to_timespec(iattr->ia_ctime);
}
}
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index ad718e5e37bb..28ef9e528853 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -90,14 +90,14 @@ int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
if (ia_valid & ATTR_GID)
sd_iattr->ia_gid = iattr->ia_gid;
if (ia_valid & ATTR_ATIME)
- sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
- inode->i_sb->s_time_gran);
+ sd_iattr->ia_atime = timespec64_trunc(iattr->ia_atime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MTIME)
- sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
- inode->i_sb->s_time_gran);
+ sd_iattr->ia_mtime = timespec64_trunc(iattr->ia_mtime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_CTIME)
- sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
- inode->i_sb->s_time_gran);
+ sd_iattr->ia_ctime = timespec64_trunc(iattr->ia_ctime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MODE) {
umode_t mode = iattr->ia_mode;
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index c4fb9ad7c808..f408994fc632 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -90,7 +90,7 @@ static struct inode *get_cramfs_inode(struct super_block *sb,
const struct cramfs_inode *cramfs_inode, unsigned int offset)
{
struct inode *inode;
- static struct timespec zerotime;
+ static struct timespec64 zerotime;
inode = iget_locked(sb, cramino(cramfs_inode, offset));
if (!inode)
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index a913b12fc7f8..13b01351dd1c 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -512,9 +512,7 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
if (unlikely(!inode))
return failed_creating(dentry);
- if (!parent)
- parent = debugfs_mount->mnt_root;
- inode->i_mode = S_IFDIR | ((d_inode(parent)->i_mode & 0770));
+ inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 78a7c855b06b..5ba94be006ee 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -517,7 +517,7 @@ static int new_lockspace(const char *name, const char *cluster,
size = dlm_config.ci_rsbtbl_size;
ls->ls_rsbtbl_size = size;
- ls->ls_rsbtbl = vmalloc(sizeof(struct dlm_rsbtable) * size);
+ ls->ls_rsbtbl = vmalloc(array_size(size, sizeof(struct dlm_rsbtable)));
if (!ls->ls_rsbtbl)
goto out_lsfree;
for (i = 0; i < size; i++) {
diff --git a/fs/eventfd.c b/fs/eventfd.c
index 61c9514da5e9..ceb1031f1cac 100644
--- a/fs/eventfd.c
+++ b/fs/eventfd.c
@@ -156,11 +156,11 @@ static __poll_t eventfd_poll_mask(struct file *file, __poll_t eventmask)
count = READ_ONCE(ctx->count);
if (count > 0)
- events |= EPOLLIN;
+ events |= (EPOLLIN & eventmask);
if (count == ULLONG_MAX)
events |= EPOLLERR;
if (ULLONG_MAX - 1 > count)
- events |= EPOLLOUT;
+ events |= (EPOLLOUT & eventmask);
return events;
}
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 67db22fe99c5..ea4436f409fb 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -922,13 +922,17 @@ static __poll_t ep_read_events_proc(struct eventpoll *ep, struct list_head *head
return 0;
}
-static __poll_t ep_eventpoll_poll(struct file *file, poll_table *wait)
+static struct wait_queue_head *ep_eventpoll_get_poll_head(struct file *file,
+ __poll_t eventmask)
{
struct eventpoll *ep = file->private_data;
- int depth = 0;
+ return &ep->poll_wait;
+}
- /* Insert inside our poll wait queue */
- poll_wait(file, &ep->poll_wait, wait);
+static __poll_t ep_eventpoll_poll_mask(struct file *file, __poll_t eventmask)
+{
+ struct eventpoll *ep = file->private_data;
+ int depth = 0;
/*
* Proceed to find out if wanted events are really available inside
@@ -968,7 +972,8 @@ static const struct file_operations eventpoll_fops = {
.show_fdinfo = ep_show_fdinfo,
#endif
.release = ep_eventpoll_release,
- .poll = ep_eventpoll_poll,
+ .get_poll_head = ep_eventpoll_get_poll_head,
+ .poll_mask = ep_eventpoll_poll_mask,
.llseek = noop_llseek,
};
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index 0ac62811b341..5f81fcd383a4 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -110,8 +110,8 @@ static int pcol_try_alloc(struct page_collect *pcol)
pages = exofs_max_io_pages(&pcol->sbi->layout, pcol->expected_pages);
for (; pages; pages >>= 1) {
- pcol->pages = kmalloc(pages * sizeof(struct page *),
- GFP_KERNEL);
+ pcol->pages = kmalloc_array(pages, sizeof(struct page *),
+ GFP_KERNEL);
if (likely(pcol->pages)) {
pcol->alloc_pages = pages;
return 0;
diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c
index ddbf87246898..1b8b44637e70 100644
--- a/fs/exofs/ore.c
+++ b/fs/exofs/ore.c
@@ -146,68 +146,82 @@ int _ore_get_io_state(struct ore_layout *layout,
struct ore_io_state **pios)
{
struct ore_io_state *ios;
- struct page **pages;
- struct osd_sg_entry *sgilist;
+ size_t size_ios, size_extra, size_total;
+ void *ios_extra;
+
+ /*
+ * The desired layout looks like this, with the extra_allocation
+ * items pointed at from fields within ios or per_dev:
+
struct __alloc_all_io_state {
struct ore_io_state ios;
struct ore_per_dev_state per_dev[numdevs];
union {
struct osd_sg_entry sglist[sgs_per_dev * numdevs];
struct page *pages[num_par_pages];
- };
- } *_aios;
-
- if (likely(sizeof(*_aios) <= PAGE_SIZE)) {
- _aios = kzalloc(sizeof(*_aios), GFP_KERNEL);
- if (unlikely(!_aios)) {
- ORE_DBGMSG("Failed kzalloc bytes=%zd\n",
- sizeof(*_aios));
+ } extra_allocation;
+ } whole_allocation;
+
+ */
+
+ /* This should never happen, so abort early if it ever does. */
+ if (sgs_per_dev && num_par_pages) {
+ ORE_DBGMSG("Tried to use both pages and sglist\n");
+ *pios = NULL;
+ return -EINVAL;
+ }
+
+ if (numdevs > (INT_MAX - sizeof(*ios)) /
+ sizeof(struct ore_per_dev_state))
+ return -ENOMEM;
+ size_ios = sizeof(*ios) + sizeof(struct ore_per_dev_state) * numdevs;
+
+ if (sgs_per_dev * numdevs > INT_MAX / sizeof(struct osd_sg_entry))
+ return -ENOMEM;
+ if (num_par_pages > INT_MAX / sizeof(struct page *))
+ return -ENOMEM;
+ size_extra = max(sizeof(struct osd_sg_entry) * (sgs_per_dev * numdevs),
+ sizeof(struct page *) * num_par_pages);
+
+ size_total = size_ios + size_extra;
+
+ if (likely(size_total <= PAGE_SIZE)) {
+ ios = kzalloc(size_total, GFP_KERNEL);
+ if (unlikely(!ios)) {
+ ORE_DBGMSG("Failed kzalloc bytes=%zd\n", size_total);
*pios = NULL;
return -ENOMEM;
}
- pages = num_par_pages ? _aios->pages : NULL;
- sgilist = sgs_per_dev ? _aios->sglist : NULL;
- ios = &_aios->ios;
+ ios_extra = (char *)ios + size_ios;
} else {
- struct __alloc_small_io_state {
- struct ore_io_state ios;
- struct ore_per_dev_state per_dev[numdevs];
- } *_aio_small;
- union __extra_part {
- struct osd_sg_entry sglist[sgs_per_dev * numdevs];
- struct page *pages[num_par_pages];
- } *extra_part;
-
- _aio_small = kzalloc(sizeof(*_aio_small), GFP_KERNEL);
- if (unlikely(!_aio_small)) {
+ ios = kzalloc(size_ios, GFP_KERNEL);
+ if (unlikely(!ios)) {
ORE_DBGMSG("Failed alloc first part bytes=%zd\n",
- sizeof(*_aio_small));
+ size_ios);
*pios = NULL;
return -ENOMEM;
}
- extra_part = kzalloc(sizeof(*extra_part), GFP_KERNEL);
- if (unlikely(!extra_part)) {
+ ios_extra = kzalloc(size_extra, GFP_KERNEL);
+ if (unlikely(!ios_extra)) {
ORE_DBGMSG("Failed alloc second part bytes=%zd\n",
- sizeof(*extra_part));
- kfree(_aio_small);
+ size_extra);
+ kfree(ios);
*pios = NULL;
return -ENOMEM;
}
- pages = num_par_pages ? extra_part->pages : NULL;
- sgilist = sgs_per_dev ? extra_part->sglist : NULL;
/* In this case the per_dev[0].sgilist holds the pointer to
* be freed
*/
- ios = &_aio_small->ios;
ios->extra_part_alloc = true;
}
- if (pages) {
- ios->parity_pages = pages;
+ if (num_par_pages) {
+ ios->parity_pages = ios_extra;
ios->max_par_pages = num_par_pages;
}
- if (sgilist) {
+ if (sgs_per_dev) {
+ struct osd_sg_entry *sgilist = ios_extra;
unsigned d;
for (d = 0; d < numdevs; ++d) {
diff --git a/fs/exofs/ore_raid.c b/fs/exofs/ore_raid.c
index 27cbdb697649..199590f36203 100644
--- a/fs/exofs/ore_raid.c
+++ b/fs/exofs/ore_raid.c
@@ -71,6 +71,11 @@ static int _sp2d_alloc(unsigned pages_in_unit, unsigned group_width,
{
struct __stripe_pages_2d *sp2d;
unsigned data_devs = group_width - parity;
+
+ /*
+ * Desired allocation layout is, though when larger than PAGE_SIZE,
+ * each struct __alloc_1p_arrays is separately allocated:
+
struct _alloc_all_bytes {
struct __alloc_stripe_pages_2d {
struct __stripe_pages_2d sp2d;
@@ -82,55 +87,85 @@ static int _sp2d_alloc(unsigned pages_in_unit, unsigned group_width,
char page_is_read[data_devs];
} __a1pa[pages_in_unit];
} *_aab;
+
struct __alloc_1p_arrays *__a1pa;
struct __alloc_1p_arrays *__a1pa_end;
- const unsigned sizeof__a1pa = sizeof(_aab->__a1pa[0]);
+
+ */
+
+ char *__a1pa;
+ char *__a1pa_end;
+
+ const size_t sizeof_stripe_pages_2d =
+ sizeof(struct __stripe_pages_2d) +
+ sizeof(struct __1_page_stripe) * pages_in_unit;
+ const size_t sizeof__a1pa =
+ ALIGN(sizeof(struct page *) * (2 * group_width) + data_devs,
+ sizeof(void *));
+ const size_t sizeof__a1pa_arrays = sizeof__a1pa * pages_in_unit;
+ const size_t alloc_total = sizeof_stripe_pages_2d +
+ sizeof__a1pa_arrays;
+
unsigned num_a1pa, alloc_size, i;
/* FIXME: check these numbers in ore_verify_layout */
- BUG_ON(sizeof(_aab->__asp2d) > PAGE_SIZE);
+ BUG_ON(sizeof_stripe_pages_2d > PAGE_SIZE);
BUG_ON(sizeof__a1pa > PAGE_SIZE);
- if (sizeof(*_aab) > PAGE_SIZE) {
- num_a1pa = (PAGE_SIZE - sizeof(_aab->__asp2d)) / sizeof__a1pa;
- alloc_size = sizeof(_aab->__asp2d) + sizeof__a1pa * num_a1pa;
+ /*
+ * If alloc_total would be larger than PAGE_SIZE, only allocate
+ * as many a1pa items as would fill the rest of the page, instead
+ * of the full pages_in_unit count.
+ */
+ if (alloc_total > PAGE_SIZE) {
+ num_a1pa = (PAGE_SIZE - sizeof_stripe_pages_2d) / sizeof__a1pa;
+ alloc_size = sizeof_stripe_pages_2d + sizeof__a1pa * num_a1pa;
} else {
num_a1pa = pages_in_unit;
- alloc_size = sizeof(*_aab);
+ alloc_size = alloc_total;
}
- _aab = kzalloc(alloc_size, GFP_KERNEL);
- if (unlikely(!_aab)) {
+ *psp2d = sp2d = kzalloc(alloc_size, GFP_KERNEL);
+ if (unlikely(!sp2d)) {
ORE_DBGMSG("!! Failed to alloc sp2d size=%d\n", alloc_size);
return -ENOMEM;
}
+ /* From here Just call _sp2d_free */
- sp2d = &_aab->__asp2d.sp2d;
- *psp2d = sp2d; /* From here Just call _sp2d_free */
-
- __a1pa = _aab->__a1pa;
- __a1pa_end = __a1pa + num_a1pa;
+ /* Find start of a1pa area. */
+ __a1pa = (char *)sp2d + sizeof_stripe_pages_2d;
+ /* Find end of the _allocated_ a1pa area. */
+ __a1pa_end = __a1pa + alloc_size;
+ /* Allocate additionally needed a1pa items in PAGE_SIZE chunks. */
for (i = 0; i < pages_in_unit; ++i) {
+ struct __1_page_stripe *stripe = &sp2d->_1p_stripes[i];
+
if (unlikely(__a1pa >= __a1pa_end)) {
num_a1pa = min_t(unsigned, PAGE_SIZE / sizeof__a1pa,
pages_in_unit - i);
+ alloc_size = sizeof__a1pa * num_a1pa;
- __a1pa = kcalloc(num_a1pa, sizeof__a1pa, GFP_KERNEL);
+ __a1pa = kzalloc(alloc_size, GFP_KERNEL);
if (unlikely(!__a1pa)) {
ORE_DBGMSG("!! Failed to _alloc_1p_arrays=%d\n",
num_a1pa);
return -ENOMEM;
}
- __a1pa_end = __a1pa + num_a1pa;
+ __a1pa_end = __a1pa + alloc_size;
/* First *pages is marked for kfree of the buffer */
- sp2d->_1p_stripes[i].alloc = true;
+ stripe->alloc = true;
}
- sp2d->_1p_stripes[i].pages = __a1pa->pages;
- sp2d->_1p_stripes[i].scribble = __a1pa->scribble ;
- sp2d->_1p_stripes[i].page_is_read = __a1pa->page_is_read;
- ++__a1pa;
+ /*
+ * Attach all _lp_stripes pointers to the allocation for
+ * it which was either part of the original PAGE_SIZE
+ * allocation or the subsequent allocation in this loop.
+ */
+ stripe->pages = (void *)__a1pa;
+ stripe->scribble = stripe->pages + group_width;
+ stripe->page_is_read = (char *)stripe->scribble + group_width;
+ __a1pa += sizeof__a1pa;
}
sp2d->parity = parity;
diff --git a/fs/exofs/super.c b/fs/exofs/super.c
index 719a3152da80..41cf2fbee50d 100644
--- a/fs/exofs/super.c
+++ b/fs/exofs/super.c
@@ -549,27 +549,26 @@ static int exofs_devs_2_odi(struct exofs_dt_device_info *dt_dev,
static int __alloc_dev_table(struct exofs_sb_info *sbi, unsigned numdevs,
struct exofs_dev **peds)
{
- struct __alloc_ore_devs_and_exofs_devs {
- /* Twice bigger table: See exofs_init_comps() and comment at
- * exofs_read_lookup_dev_table()
- */
- struct ore_dev *oreds[numdevs * 2 - 1];
- struct exofs_dev eds[numdevs];
- } *aoded;
+ /* Twice bigger table: See exofs_init_comps() and comment at
+ * exofs_read_lookup_dev_table()
+ */
+ const size_t numores = numdevs * 2 - 1;
struct exofs_dev *eds;
unsigned i;
- aoded = kzalloc(sizeof(*aoded), GFP_KERNEL);
- if (unlikely(!aoded)) {
+ sbi->oc.ods = kzalloc(numores * sizeof(struct ore_dev *) +
+ numdevs * sizeof(struct exofs_dev), GFP_KERNEL);
+ if (unlikely(!sbi->oc.ods)) {
EXOFS_ERR("ERROR: failed allocating Device array[%d]\n",
numdevs);
return -ENOMEM;
}
- sbi->oc.ods = aoded->oreds;
- *peds = eds = aoded->eds;
+ /* Start of allocated struct exofs_dev entries */
+ *peds = eds = (void *)sbi->oc.ods[numores];
+ /* Initialize pointers into struct exofs_dev */
for (i = 0; i < numdevs; ++i)
- aoded->oreds[i] = &eds[i].ored;
+ sbi->oc.ods[i] = &eds[i].ored;
return 0;
}
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index c09289a42dc5..25ab1274090f 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -1082,7 +1082,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
/ EXT2_BLOCKS_PER_GROUP(sb)) + 1;
db_count = (sbi->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
EXT2_DESC_PER_BLOCK(sb);
- sbi->s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL);
+ sbi->s_group_desc = kmalloc_array (db_count,
+ sizeof(struct buffer_head *),
+ GFP_KERNEL);
if (sbi->s_group_desc == NULL) {
ext2_msg(sb, KERN_ERR, "error: not enough memory");
goto failed_mount;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index df95412915ea..0b127853c584 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -817,12 +817,14 @@ static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
}
-#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
-do { \
- (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec); \
- if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \
- (raw_inode)->xtime ## _extra = \
- ext4_encode_extra_time(&(inode)->xtime); \
+#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
+do { \
+ (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec); \
+ if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) {\
+ struct timespec ts = timespec64_to_timespec((inode)->xtime); \
+ (raw_inode)->xtime ## _extra = \
+ ext4_encode_extra_time(&ts); \
+ } \
} while (0)
#define EXT4_EINODE_SET_XTIME(xtime, einode, raw_inode) \
@@ -834,16 +836,20 @@ do { \
ext4_encode_extra_time(&(einode)->xtime); \
} while (0)
-#define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \
-do { \
- (inode)->xtime.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime); \
- if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \
- ext4_decode_extra_time(&(inode)->xtime, \
- raw_inode->xtime ## _extra); \
- else \
- (inode)->xtime.tv_nsec = 0; \
+#define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \
+do { \
+ (inode)->xtime.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime); \
+ if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) { \
+ struct timespec ts = timespec64_to_timespec((inode)->xtime); \
+ ext4_decode_extra_time(&ts, \
+ raw_inode->xtime ## _extra); \
+ (inode)->xtime = timespec_to_timespec64(ts); \
+ } \
+ else \
+ (inode)->xtime.tv_nsec = 0; \
} while (0)
+
#define EXT4_EINODE_GET_XTIME(xtime, einode, raw_inode) \
do { \
if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index c969275ce3ee..0057fe3f248d 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -577,7 +577,7 @@ int ext4_ext_precache(struct inode *inode)
down_read(&ei->i_data_sem);
depth = ext_depth(inode);
- path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1),
+ path = kcalloc(depth + 1, sizeof(struct ext4_ext_path),
GFP_NOFS);
if (path == NULL) {
up_read(&ei->i_data_sem);
@@ -879,7 +879,7 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block,
}
if (!path) {
/* account possible depth increase */
- path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 2),
+ path = kcalloc(depth + 2, sizeof(struct ext4_ext_path),
GFP_NOFS);
if (unlikely(!path))
return ERR_PTR(-ENOMEM);
@@ -1063,7 +1063,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
* We need this to handle errors and free blocks
* upon them.
*/
- ablocks = kzalloc(sizeof(ext4_fsblk_t) * depth, GFP_NOFS);
+ ablocks = kcalloc(depth, sizeof(ext4_fsblk_t), GFP_NOFS);
if (!ablocks)
return -ENOMEM;
@@ -2921,7 +2921,7 @@ again:
path[k].p_block =
le16_to_cpu(path[k].p_hdr->eh_entries)+1;
} else {
- path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1),
+ path = kcalloc(depth + 1, sizeof(struct ext4_ext_path),
GFP_NOFS);
if (path == NULL) {
ext4_journal_stop(handle);
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 4d6e007f3569..f525f909b559 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1072,8 +1072,8 @@ got:
inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);
/* This is the optimal IO size (for stat), not the fs block size */
inode->i_blocks = 0;
- inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
- current_time(inode);
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ ei->i_crtime = timespec64_to_timespec(inode->i_mtime);
memset(ei->i_data, 0, sizeof(ei->i_data));
ei->i_dir_start_lookup = 0;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 4a09063ce1d2..2a4c25c4681d 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3673,7 +3673,7 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
};
u8 new_file_type;
int retval;
- struct timespec ctime;
+ struct timespec64 ctime;
if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT) &&
!projid_eq(EXT4_I(new_dir)->i_projid,
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index d792b7689d92..e5fb38451a73 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -204,12 +204,14 @@ static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned long flexbg_size)
goto out2;
flex_gd->count = flexbg_size;
- flex_gd->groups = kmalloc(sizeof(struct ext4_new_group_data) *
- flexbg_size, GFP_NOFS);
+ flex_gd->groups = kmalloc_array(flexbg_size,
+ sizeof(struct ext4_new_group_data),
+ GFP_NOFS);
if (flex_gd->groups == NULL)
goto out2;
- flex_gd->bg_flags = kmalloc(flexbg_size * sizeof(__u16), GFP_NOFS);
+ flex_gd->bg_flags = kmalloc_array(flexbg_size, sizeof(__u16),
+ GFP_NOFS);
if (flex_gd->bg_flags == NULL)
goto out1;
@@ -969,7 +971,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
int res, i;
int err;
- primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_NOFS);
+ primary = kmalloc_array(reserved_gdb, sizeof(*primary), GFP_NOFS);
if (!primary)
return -ENOMEM;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 00fe75a71c4b..0c4c2201b3aa 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3993,9 +3993,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
goto failed_mount;
}
}
- sbi->s_group_desc = kvmalloc(db_count *
- sizeof(struct buffer_head *),
- GFP_KERNEL);
+ sbi->s_group_desc = kvmalloc_array(db_count,
+ sizeof(struct buffer_head *),
+ GFP_KERNEL);
if (sbi->s_group_desc == NULL) {
ext4_msg(sb, KERN_ERR, "not enough memory");
ret = -ENOMEM;
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 9624a8f7254b..9f1c96caebda 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -806,7 +806,8 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
block_t cp_blk_no;
int i;
- sbi->ckpt = f2fs_kzalloc(sbi, cp_blks * blk_size, GFP_KERNEL);
+ sbi->ckpt = f2fs_kzalloc(sbi, array_size(blk_size, cp_blks),
+ GFP_KERNEL);
if (!sbi->ckpt)
return -ENOMEM;
/*
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 4c09e770a0a3..4d8b1de83143 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -2518,6 +2518,7 @@ static inline void clear_file(struct inode *inode, int type)
static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
{
+ struct timespec ts;
bool ret;
if (dsync) {
@@ -2533,11 +2534,14 @@ static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
i_size_read(inode) & ~PAGE_MASK)
return false;
- if (!timespec_equal(F2FS_I(inode)->i_disk_time, &inode->i_atime))
+ ts = timespec64_to_timespec(inode->i_atime);
+ if (!timespec_equal(F2FS_I(inode)->i_disk_time, &ts))
return false;
- if (!timespec_equal(F2FS_I(inode)->i_disk_time + 1, &inode->i_ctime))
+ ts = timespec64_to_timespec(inode->i_ctime);
+ if (!timespec_equal(F2FS_I(inode)->i_disk_time + 1, &ts))
return false;
- if (!timespec_equal(F2FS_I(inode)->i_disk_time + 2, &inode->i_mtime))
+ ts = timespec64_to_timespec(inode->i_mtime);
+ if (!timespec_equal(F2FS_I(inode)->i_disk_time + 2, &ts))
return false;
if (!timespec_equal(F2FS_I(inode)->i_disk_time + 3,
&F2FS_I(inode)->i_crtime))
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 13f2f6845e87..6880c6f78d58 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -730,14 +730,14 @@ static void __setattr_copy(struct inode *inode, const struct iattr *attr)
if (ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
if (ia_valid & ATTR_ATIME)
- inode->i_atime = timespec_trunc(attr->ia_atime,
- inode->i_sb->s_time_gran);
+ inode->i_atime = timespec64_trunc(attr->ia_atime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MTIME)
- inode->i_mtime = timespec_trunc(attr->ia_mtime,
- inode->i_sb->s_time_gran);
+ inode->i_mtime = timespec64_trunc(attr->ia_mtime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_CTIME)
- inode->i_ctime = timespec_trunc(attr->ia_ctime,
- inode->i_sb->s_time_gran);
+ inode->i_ctime = timespec64_trunc(attr->ia_ctime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MODE) {
umode_t mode = attr->ia_mode;
@@ -1122,12 +1122,14 @@ static int __exchange_data_block(struct inode *src_inode,
olen = min((pgoff_t)4 * ADDRS_PER_BLOCK, len);
src_blkaddr = f2fs_kvzalloc(F2FS_I_SB(src_inode),
- sizeof(block_t) * olen, GFP_KERNEL);
+ array_size(olen, sizeof(block_t)),
+ GFP_KERNEL);
if (!src_blkaddr)
return -ENOMEM;
do_replace = f2fs_kvzalloc(F2FS_I_SB(src_inode),
- sizeof(int) * olen, GFP_KERNEL);
+ array_size(olen, sizeof(int)),
+ GFP_KERNEL);
if (!do_replace) {
kvfree(src_blkaddr);
return -ENOMEM;
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 30a777369d2b..f121c864f4c0 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -297,9 +297,9 @@ static int do_read_inode(struct inode *inode)
fi->i_crtime.tv_nsec = le32_to_cpu(ri->i_crtime_nsec);
}
- F2FS_I(inode)->i_disk_time[0] = inode->i_atime;
- F2FS_I(inode)->i_disk_time[1] = inode->i_ctime;
- F2FS_I(inode)->i_disk_time[2] = inode->i_mtime;
+ F2FS_I(inode)->i_disk_time[0] = timespec64_to_timespec(inode->i_atime);
+ F2FS_I(inode)->i_disk_time[1] = timespec64_to_timespec(inode->i_ctime);
+ F2FS_I(inode)->i_disk_time[2] = timespec64_to_timespec(inode->i_mtime);
F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime;
f2fs_put_page(node_page, 1);
@@ -470,9 +470,9 @@ void f2fs_update_inode(struct inode *inode, struct page *node_page)
if (inode->i_nlink == 0)
clear_inline_node(node_page);
- F2FS_I(inode)->i_disk_time[0] = inode->i_atime;
- F2FS_I(inode)->i_disk_time[1] = inode->i_ctime;
- F2FS_I(inode)->i_disk_time[2] = inode->i_mtime;
+ F2FS_I(inode)->i_disk_time[0] = timespec64_to_timespec(inode->i_atime);
+ F2FS_I(inode)->i_disk_time[1] = timespec64_to_timespec(inode->i_ctime);
+ F2FS_I(inode)->i_disk_time[2] = timespec64_to_timespec(inode->i_mtime);
F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime;
}
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 64050c84d353..231b7f3ea7d3 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -50,8 +50,8 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
inode->i_ino = ino;
inode->i_blocks = 0;
- inode->i_mtime = inode->i_atime = inode->i_ctime =
- F2FS_I(inode)->i_crtime = current_time(inode);
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ F2FS_I(inode)->i_crtime = timespec64_to_timespec(inode->i_mtime);
inode->i_generation = sbi->s_next_generation++;
if (S_ISDIR(inode->i_mode))
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 47d0e64a95a8..10643b11bd59 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -2753,8 +2753,10 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi)
struct f2fs_nm_info *nm_i = NM_I(sbi);
int i;
- nm_i->free_nid_bitmap = f2fs_kzalloc(sbi, nm_i->nat_blocks *
- sizeof(unsigned char *), GFP_KERNEL);
+ nm_i->free_nid_bitmap =
+ f2fs_kzalloc(sbi, array_size(sizeof(unsigned char *),
+ nm_i->nat_blocks),
+ GFP_KERNEL);
if (!nm_i->free_nid_bitmap)
return -ENOMEM;
@@ -2770,8 +2772,10 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi)
if (!nm_i->nat_block_bitmap)
return -ENOMEM;
- nm_i->free_nid_count = f2fs_kvzalloc(sbi, nm_i->nat_blocks *
- sizeof(unsigned short), GFP_KERNEL);
+ nm_i->free_nid_count =
+ f2fs_kvzalloc(sbi, array_size(sizeof(unsigned short),
+ nm_i->nat_blocks),
+ GFP_KERNEL);
if (!nm_i->free_nid_count)
return -ENOMEM;
return 0;
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 6dbdf2c48fba..9efce174c51a 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -3517,8 +3517,10 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
SM_I(sbi)->sit_info = sit_i;
- sit_i->sentries = f2fs_kvzalloc(sbi, MAIN_SEGS(sbi) *
- sizeof(struct seg_entry), GFP_KERNEL);
+ sit_i->sentries =
+ f2fs_kvzalloc(sbi, array_size(sizeof(struct seg_entry),
+ MAIN_SEGS(sbi)),
+ GFP_KERNEL);
if (!sit_i->sentries)
return -ENOMEM;
@@ -3558,8 +3560,10 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
return -ENOMEM;
if (sbi->segs_per_sec > 1) {
- sit_i->sec_entries = f2fs_kvzalloc(sbi, MAIN_SECS(sbi) *
- sizeof(struct sec_entry), GFP_KERNEL);
+ sit_i->sec_entries =
+ f2fs_kvzalloc(sbi, array_size(sizeof(struct sec_entry),
+ MAIN_SECS(sbi)),
+ GFP_KERNEL);
if (!sit_i->sec_entries)
return -ENOMEM;
}
@@ -3635,7 +3639,8 @@ static int build_curseg(struct f2fs_sb_info *sbi)
struct curseg_info *array;
int i;
- array = f2fs_kzalloc(sbi, sizeof(*array) * NR_CURSEG_TYPE, GFP_KERNEL);
+ array = f2fs_kzalloc(sbi, array_size(NR_CURSEG_TYPE, sizeof(*array)),
+ GFP_KERNEL);
if (!array)
return -ENOMEM;
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index e7441e8d1ff8..3995e926ba3a 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2419,8 +2419,10 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi)
#define F2FS_REPORT_NR_ZONES 4096
- zones = f2fs_kzalloc(sbi, sizeof(struct blk_zone) *
- F2FS_REPORT_NR_ZONES, GFP_KERNEL);
+ zones = f2fs_kzalloc(sbi,
+ array_size(F2FS_REPORT_NR_ZONES,
+ sizeof(struct blk_zone)),
+ GFP_KERNEL);
if (!zones)
return -ENOMEM;
@@ -2560,8 +2562,10 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
* Initialize multiple devices information, or single
* zoned block device information.
*/
- sbi->devs = f2fs_kzalloc(sbi, sizeof(struct f2fs_dev_info) *
- max_devices, GFP_KERNEL);
+ sbi->devs = f2fs_kzalloc(sbi,
+ array_size(max_devices,
+ sizeof(struct f2fs_dev_info)),
+ GFP_KERNEL);
if (!sbi->devs)
return -ENOMEM;
@@ -2783,9 +2787,11 @@ try_onemore:
int n = (i == META) ? 1: NR_TEMP_TYPE;
int j;
- sbi->write_io[i] = f2fs_kmalloc(sbi,
- n * sizeof(struct f2fs_bio_info),
- GFP_KERNEL);
+ sbi->write_io[i] =
+ f2fs_kmalloc(sbi,
+ array_size(n,
+ sizeof(struct f2fs_bio_info)),
+ GFP_KERNEL);
if (!sbi->write_io[i]) {
err = -ENOMEM;
goto free_options;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index ffbbf0520d9e..065dc919a0ce 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -158,8 +158,14 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock,
err = fat_bmap(inode, iblock, &phys, &mapped_blocks, create, false);
if (err)
return err;
+ if (!phys) {
+ fat_fs_error(sb,
+ "invalid FAT chain (i_pos %lld, last_block %llu)",
+ MSDOS_I(inode)->i_pos,
+ (unsigned long long)last_block);
+ return -EIO;
+ }
- BUG_ON(!phys);
BUG_ON(*max_blocks != mapped_blocks);
set_buffer_new(bh_result);
map_bh(bh_result, sb, phys);
@@ -502,6 +508,7 @@ static int fat_validate_dir(struct inode *dir)
/* doesn't deal with root inode */
int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
{
+ struct timespec ts;
struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
int error;
@@ -552,11 +559,14 @@ int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
& ~((loff_t)sbi->cluster_size - 1)) >> 9;
- fat_time_fat2unix(sbi, &inode->i_mtime, de->time, de->date, 0);
+ fat_time_fat2unix(sbi, &ts, de->time, de->date, 0);
+ inode->i_mtime = timespec_to_timespec64(ts);
if (sbi->options.isvfat) {
- fat_time_fat2unix(sbi, &inode->i_ctime, de->ctime,
+ fat_time_fat2unix(sbi, &ts, de->ctime,
de->cdate, de->ctime_cs);
- fat_time_fat2unix(sbi, &inode->i_atime, 0, de->adate, 0);
+ inode->i_ctime = timespec_to_timespec64(ts);
+ fat_time_fat2unix(sbi, &ts, 0, de->adate, 0);
+ inode->i_atime = timespec_to_timespec64(ts);
} else
inode->i_ctime = inode->i_atime = inode->i_mtime;
@@ -825,6 +835,7 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
static int __fat_write_inode(struct inode *inode, int wait)
{
+ struct timespec ts;
struct super_block *sb = inode->i_sb;
struct msdos_sb_info *sbi = MSDOS_SB(sb);
struct buffer_head *bh;
@@ -862,13 +873,16 @@ retry:
raw_entry->size = cpu_to_le32(inode->i_size);
raw_entry->attr = fat_make_attrs(inode);
fat_set_start(raw_entry, MSDOS_I(inode)->i_logstart);
- fat_time_unix2fat(sbi, &inode->i_mtime, &raw_entry->time,
+ ts = timespec64_to_timespec(inode->i_mtime);
+ fat_time_unix2fat(sbi, &ts, &raw_entry->time,
&raw_entry->date, NULL);
if (sbi->options.isvfat) {
__le16 atime;
- fat_time_unix2fat(sbi, &inode->i_ctime, &raw_entry->ctime,
+ ts = timespec64_to_timespec(inode->i_ctime);
+ fat_time_unix2fat(sbi, &ts, &raw_entry->ctime,
&raw_entry->cdate, &raw_entry->ctime_cs);
- fat_time_unix2fat(sbi, &inode->i_atime, &atime,
+ ts = timespec64_to_timespec(inode->i_atime);
+ fat_time_unix2fat(sbi, &ts, &atime,
&raw_entry->adate, NULL);
}
spin_unlock(&sbi->inode_hash_lock);
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 484ce674e0cd..16a832c37d66 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -250,7 +250,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
if (err)
return err;
- dir->i_ctime = dir->i_mtime = *ts;
+ dir->i_ctime = dir->i_mtime = timespec_to_timespec64(*ts);
if (IS_DIRSYNC(dir))
(void)fat_sync_inode(dir);
else
@@ -266,7 +266,8 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
struct super_block *sb = dir->i_sb;
struct inode *inode = NULL;
struct fat_slot_info sinfo;
- struct timespec ts;
+ struct timespec64 ts;
+ struct timespec t;
unsigned char msdos_name[MSDOS_NAME];
int err, is_hid;
@@ -285,7 +286,8 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
}
ts = current_time(dir);
- err = msdos_add_entry(dir, msdos_name, 0, is_hid, 0, &ts, &sinfo);
+ t = timespec64_to_timespec(ts);
+ err = msdos_add_entry(dir, msdos_name, 0, is_hid, 0, &t, &sinfo);
if (err)
goto out;
inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
@@ -344,7 +346,8 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
struct fat_slot_info sinfo;
struct inode *inode;
unsigned char msdos_name[MSDOS_NAME];
- struct timespec ts;
+ struct timespec64 ts;
+ struct timespec t;
int err, is_hid, cluster;
mutex_lock(&MSDOS_SB(sb)->s_lock);
@@ -362,12 +365,13 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
}
ts = current_time(dir);
- cluster = fat_alloc_new_dir(dir, &ts);
+ t = timespec64_to_timespec(ts);
+ cluster = fat_alloc_new_dir(dir, &t);
if (cluster < 0) {
err = cluster;
goto out;
}
- err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &ts, &sinfo);
+ err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &t, &sinfo);
if (err)
goto out_free;
inc_nlink(dir);
@@ -432,7 +436,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
struct msdos_dir_entry *dotdot_de;
struct inode *old_inode, *new_inode;
struct fat_slot_info old_sinfo, sinfo;
- struct timespec ts;
+ struct timespec64 ts;
loff_t new_i_pos;
int err, old_attrs, is_dir, update_dotdot, corrupt = 0;
@@ -499,8 +503,9 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
new_i_pos = MSDOS_I(new_inode)->i_pos;
fat_detach(new_inode);
} else {
+ struct timespec t = timespec64_to_timespec(ts);
err = msdos_add_entry(new_dir, new_name, is_dir, is_hid, 0,
- &ts, &sinfo);
+ &t, &sinfo);
if (err)
goto out;
new_i_pos = sinfo.i_pos;
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 4f4362d5a04c..9a5469120caa 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -664,7 +664,7 @@ static int vfat_add_entry(struct inode *dir, const struct qstr *qname,
if (len == 0)
return -ENOENT;
- slots = kmalloc(sizeof(*slots) * MSDOS_SLOTS, GFP_NOFS);
+ slots = kmalloc_array(MSDOS_SLOTS, sizeof(*slots), GFP_NOFS);
if (slots == NULL)
return -ENOMEM;
@@ -678,7 +678,7 @@ static int vfat_add_entry(struct inode *dir, const struct qstr *qname,
goto cleanup;
/* update timestamp */
- dir->i_ctime = dir->i_mtime = dir->i_atime = *ts;
+ dir->i_ctime = dir->i_mtime = dir->i_atime = timespec_to_timespec64(*ts);
if (IS_DIRSYNC(dir))
(void)fat_sync_inode(dir);
else
@@ -761,13 +761,15 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
struct super_block *sb = dir->i_sb;
struct inode *inode;
struct fat_slot_info sinfo;
- struct timespec ts;
+ struct timespec64 ts;
+ struct timespec t;
int err;
mutex_lock(&MSDOS_SB(sb)->s_lock);
ts = current_time(dir);
- err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo);
+ t = timespec64_to_timespec(ts);
+ err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &t, &sinfo);
if (err)
goto out;
inode_inc_iversion(dir);
@@ -850,18 +852,20 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
struct super_block *sb = dir->i_sb;
struct inode *inode;
struct fat_slot_info sinfo;
- struct timespec ts;
+ struct timespec64 ts;
+ struct timespec t;
int err, cluster;
mutex_lock(&MSDOS_SB(sb)->s_lock);
ts = current_time(dir);
- cluster = fat_alloc_new_dir(dir, &ts);
+ t = timespec64_to_timespec(ts);
+ cluster = fat_alloc_new_dir(dir, &t);
if (cluster < 0) {
err = cluster;
goto out;
}
- err = vfat_add_entry(dir, &dentry->d_name, 1, cluster, &ts, &sinfo);
+ err = vfat_add_entry(dir, &dentry->d_name, 1, cluster, &t, &sinfo);
if (err)
goto out_free;
inode_inc_iversion(dir);
@@ -899,7 +903,8 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
struct msdos_dir_entry *dotdot_de;
struct inode *old_inode, *new_inode;
struct fat_slot_info old_sinfo, sinfo;
- struct timespec ts;
+ struct timespec64 ts;
+ struct timespec t;
loff_t new_i_pos;
int err, is_dir, update_dotdot, corrupt = 0;
struct super_block *sb = old_dir->i_sb;
@@ -934,8 +939,9 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
new_i_pos = MSDOS_I(new_inode)->i_pos;
fat_detach(new_inode);
} else {
+ t = timespec64_to_timespec(ts);
err = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir, 0,
- &ts, &sinfo);
+ &t, &sinfo);
if (err)
goto out;
new_i_pos = sinfo.i_pos;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index e03ca14f40e9..c6b88fa85e2e 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -64,9 +64,12 @@ static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags)
pages = req->inline_pages;
page_descs = req->inline_page_descs;
} else {
- pages = kmalloc(sizeof(struct page *) * npages, flags);
- page_descs = kmalloc(sizeof(struct fuse_page_desc) *
- npages, flags);
+ pages = kmalloc_array(npages, sizeof(struct page *),
+ flags);
+ page_descs =
+ kmalloc_array(npages,
+ sizeof(struct fuse_page_desc),
+ flags);
}
if (!pages || !page_descs) {
@@ -1359,7 +1362,8 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
if (!fud)
return -EPERM;
- bufs = kmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL);
+ bufs = kmalloc_array(pipe->buffers, sizeof(struct pipe_buffer),
+ GFP_KERNEL);
if (!bufs)
return -ENOMEM;
@@ -1940,7 +1944,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
if (!fud)
return -EPERM;
- bufs = kmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL);
+ bufs = kmalloc_array(pipe->buffers, sizeof(struct pipe_buffer),
+ GFP_KERNEL);
if (!bufs)
return -ENOMEM;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index ffcaf98044b9..a24df8861b40 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -217,7 +217,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
return;
}
- old_mtime = inode->i_mtime;
+ old_mtime = timespec64_to_timespec(inode->i_mtime);
fuse_change_attributes_common(inode, attr, attr_valid);
oldsize = inode->i_size;
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index d9fb0ad6cc30..d97ad89955d1 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -871,7 +871,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
struct buffer_head *bh;
struct gfs2_leaf *leaf;
struct gfs2_dirent *dent;
- struct timespec tv = current_time(inode);
+ struct timespec64 tv = current_time(inode);
error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
if (error)
@@ -1055,7 +1055,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
/* Change the pointers.
Don't bother distinguishing stuffed from non-stuffed.
This code is complicated enough already. */
- lp = kmalloc(half_len * sizeof(__be64), GFP_NOFS);
+ lp = kmalloc_array(half_len, sizeof(__be64), GFP_NOFS);
if (!lp) {
error = -ENOMEM;
goto fail_brelse;
@@ -1169,7 +1169,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
if (IS_ERR(hc))
return PTR_ERR(hc);
- hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS | __GFP_NOWARN);
+ hc2 = kmalloc_array(hsize_bytes, 2, GFP_NOFS | __GFP_NOWARN);
if (hc2 == NULL)
hc2 = __vmalloc(hsize_bytes * 2, GFP_NOFS, PAGE_KERNEL);
@@ -1596,7 +1596,7 @@ int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
error = -ENOMEM;
/* 96 is max number of dirents which can be stuffed into an inode */
- darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_NOFS);
+ darr = kmalloc_array(96, sizeof(struct gfs2_dirent *), GFP_NOFS);
if (darr) {
g.pdent = (const struct gfs2_dirent **)darr;
g.offset = 0;
@@ -1802,7 +1802,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
struct gfs2_inode *ip = GFS2_I(inode);
struct buffer_head *bh = da->bh;
struct gfs2_dirent *dent = da->dent;
- struct timespec tv;
+ struct timespec64 tv;
struct gfs2_leaf *leaf;
int error;
@@ -1880,7 +1880,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry)
const struct qstr *name = &dentry->d_name;
struct gfs2_dirent *dent, *prev = NULL;
struct buffer_head *bh;
- struct timespec tv = current_time(&dip->i_inode);
+ struct timespec64 tv = current_time(&dip->i_inode);
/* Returns _either_ the entry (if its first in block) or the
previous entry otherwise */
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 097bd3c0f270..4614ee25f621 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -1303,7 +1303,8 @@ int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs)
default:
if (num_gh <= 4)
break;
- pph = kmalloc(num_gh * sizeof(struct gfs2_holder *), GFP_NOFS);
+ pph = kmalloc_array(num_gh, sizeof(struct gfs2_holder *),
+ GFP_NOFS);
if (!pph)
return -ENOMEM;
}
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index d8782a7a1e7d..c63bee9adb6a 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -338,7 +338,7 @@ static int inode_go_demote_ok(const struct gfs2_glock *gl)
static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
{
const struct gfs2_dinode *str = buf;
- struct timespec atime;
+ struct timespec64 atime;
u16 height, depth;
if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)))
@@ -361,7 +361,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
atime.tv_sec = be64_to_cpu(str->di_atime);
atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
- if (timespec_compare(&ip->i_inode.i_atime, &atime) < 0)
+ if (timespec64_compare(&ip->i_inode.i_atime, &atime) < 0)
ip->i_inode.i_atime = atime;
ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec);
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index e8585dfd209f..0efae7a0ee80 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -886,7 +886,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
&data_blocks, &ind_blocks);
- ghs = kmalloc(num_qd * sizeof(struct gfs2_holder), GFP_NOFS);
+ ghs = kmalloc_array(num_qd, sizeof(struct gfs2_holder), GFP_NOFS);
if (!ghs)
return -ENOMEM;
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 6bc5cfe710d1..33abcf29bc05 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -2605,8 +2605,9 @@ void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state)
{
unsigned int x;
- rlist->rl_ghs = kmalloc(rlist->rl_rgrps * sizeof(struct gfs2_holder),
- GFP_NOFS | __GFP_NOFAIL);
+ rlist->rl_ghs = kmalloc_array(rlist->rl_rgrps,
+ sizeof(struct gfs2_holder),
+ GFP_NOFS | __GFP_NOFAIL);
for (x = 0; x < rlist->rl_rgrps; x++)
gfs2_holder_init(rlist->rl_rgd[x]->rd_gl,
state, 0,
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index cf5c7f3080d2..af0d5b01cf0b 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1097,7 +1097,7 @@ static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host
int error = 0, err;
memset(sc, 0, sizeof(struct gfs2_statfs_change_host));
- gha = kmalloc(slots * sizeof(struct gfs2_holder), GFP_KERNEL);
+ gha = kmalloc_array(slots, sizeof(struct gfs2_holder), GFP_KERNEL);
if (!gha)
return -ENOMEM;
for (x = 0; x < slots; x++)
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index b3309b83371a..2a16111d312f 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -351,7 +351,7 @@ static int hfs_read_inode(struct inode *inode, void *data)
inode->i_mode &= ~hsb->s_file_umask;
inode->i_mode |= S_IFREG;
inode->i_ctime = inode->i_atime = inode->i_mtime =
- hfs_m_to_utime(rec->file.MdDat);
+ timespec_to_timespec64(hfs_m_to_utime(rec->file.MdDat));
inode->i_op = &hfs_file_inode_operations;
inode->i_fop = &hfs_file_operations;
inode->i_mapping->a_ops = &hfs_aops;
@@ -362,7 +362,7 @@ static int hfs_read_inode(struct inode *inode, void *data)
HFS_I(inode)->fs_blocks = 0;
inode->i_mode = S_IFDIR | (S_IRWXUGO & ~hsb->s_dir_umask);
inode->i_ctime = inode->i_atime = inode->i_mtime =
- hfs_m_to_utime(rec->dir.MdDat);
+ timespec_to_timespec64(hfs_m_to_utime(rec->dir.MdDat));
inode->i_op = &hfs_dir_inode_operations;
inode->i_fop = &hfs_dir_operations;
break;
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index c0c8d433864f..c824f702feec 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -493,9 +493,9 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
hfsplus_get_perms(inode, &folder->permissions, 1);
set_nlink(inode, 1);
inode->i_size = 2 + be32_to_cpu(folder->valence);
- inode->i_atime = hfsp_mt2ut(folder->access_date);
- inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
- inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
+ inode->i_atime = timespec_to_timespec64(hfsp_mt2ut(folder->access_date));
+ inode->i_mtime = timespec_to_timespec64(hfsp_mt2ut(folder->content_mod_date));
+ inode->i_ctime = timespec_to_timespec64(hfsp_mt2ut(folder->attribute_mod_date));
HFSPLUS_I(inode)->create_date = folder->create_date;
HFSPLUS_I(inode)->fs_blocks = 0;
if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) {
@@ -531,9 +531,9 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
init_special_inode(inode, inode->i_mode,
be32_to_cpu(file->permissions.dev));
}
- inode->i_atime = hfsp_mt2ut(file->access_date);
- inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
- inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date);
+ inode->i_atime = timespec_to_timespec64(hfsp_mt2ut(file->access_date));
+ inode->i_mtime = timespec_to_timespec64(hfsp_mt2ut(file->content_mod_date));
+ inode->i_ctime = timespec_to_timespec64(hfsp_mt2ut(file->attribute_mod_date));
HFSPLUS_I(inode)->create_date = file->create_date;
} else {
pr_err("bad catalog entry used to create inode\n");
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 3cd85eb5bbb1..2597b290c2a5 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -555,9 +555,9 @@ static int read_name(struct inode *ino, char *name)
set_nlink(ino, st.nlink);
i_uid_write(ino, st.uid);
i_gid_write(ino, st.gid);
- ino->i_atime = st.atime;
- ino->i_mtime = st.mtime;
- ino->i_ctime = st.ctime;
+ ino->i_atime = timespec_to_timespec64(st.atime);
+ ino->i_mtime = timespec_to_timespec64(st.mtime);
+ ino->i_ctime = timespec_to_timespec64(st.ctime);
ino->i_size = st.size;
ino->i_blocks = st.blocks;
return 0;
@@ -838,15 +838,15 @@ static int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
}
if (attr->ia_valid & ATTR_ATIME) {
attrs.ia_valid |= HOSTFS_ATTR_ATIME;
- attrs.ia_atime = attr->ia_atime;
+ attrs.ia_atime = timespec64_to_timespec(attr->ia_atime);
}
if (attr->ia_valid & ATTR_MTIME) {
attrs.ia_valid |= HOSTFS_ATTR_MTIME;
- attrs.ia_mtime = attr->ia_mtime;
+ attrs.ia_mtime = timespec64_to_timespec(attr->ia_mtime);
}
if (attr->ia_valid & ATTR_CTIME) {
attrs.ia_valid |= HOSTFS_ATTR_CTIME;
- attrs.ia_ctime = attr->ia_ctime;
+ attrs.ia_ctime = timespec64_to_timespec(attr->ia_ctime);
}
if (attr->ia_valid & ATTR_ATIME_SET) {
attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c
index a4ad18afbdec..4ada525c5c43 100644
--- a/fs/hpfs/dnode.c
+++ b/fs/hpfs/dnode.c
@@ -33,7 +33,8 @@ int hpfs_add_pos(struct inode *inode, loff_t *pos)
if (hpfs_inode->i_rddir_off[i] == pos)
return 0;
if (!(i&0x0f)) {
- if (!(ppos = kmalloc((i+0x11) * sizeof(loff_t*), GFP_NOFS))) {
+ ppos = kmalloc_array(i + 0x11, sizeof(loff_t *), GFP_NOFS);
+ if (!ppos) {
pr_err("out of memory for position list\n");
return -ENOMEM;
}
diff --git a/fs/hpfs/map.c b/fs/hpfs/map.c
index 7c49f1ef0c85..ecd9fccd1663 100644
--- a/fs/hpfs/map.c
+++ b/fs/hpfs/map.c
@@ -115,7 +115,7 @@ __le32 *hpfs_load_bitmap_directory(struct super_block *s, secno bmp)
int n = (hpfs_sb(s)->sb_fs_size + 0x200000 - 1) >> 21;
int i;
__le32 *b;
- if (!(b = kmalloc(n * 512, GFP_KERNEL))) {
+ if (!(b = kmalloc_array(n, 512, GFP_KERNEL))) {
pr_err("can't allocate memory for bitmap directory\n");
return NULL;
}
diff --git a/fs/inode.c b/fs/inode.c
index 0df41bb77e0f..2c300e981796 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1577,8 +1577,8 @@ static void update_ovl_inode_times(struct dentry *dentry, struct inode *inode,
if (upperdentry) {
struct inode *realinode = d_inode(upperdentry);
- if ((!timespec_equal(&inode->i_mtime, &realinode->i_mtime) ||
- !timespec_equal(&inode->i_ctime, &realinode->i_ctime))) {
+ if ((!timespec64_equal(&inode->i_mtime, &realinode->i_mtime) ||
+ !timespec64_equal(&inode->i_ctime, &realinode->i_ctime))) {
inode->i_mtime = realinode->i_mtime;
inode->i_ctime = realinode->i_ctime;
}
@@ -1601,12 +1601,12 @@ static int relatime_need_update(const struct path *path, struct inode *inode,
/*
* Is mtime younger than atime? If yes, update atime:
*/
- if (timespec_compare(&inode->i_mtime, &inode->i_atime) >= 0)
+ if (timespec64_compare(&inode->i_mtime, &inode->i_atime) >= 0)
return 1;
/*
* Is ctime younger than atime? If yes, update atime:
*/
- if (timespec_compare(&inode->i_ctime, &inode->i_atime) >= 0)
+ if (timespec64_compare(&inode->i_ctime, &inode->i_atime) >= 0)
return 1;
/*
@@ -1621,7 +1621,7 @@ static int relatime_need_update(const struct path *path, struct inode *inode,
return 0;
}
-int generic_update_time(struct inode *inode, struct timespec *time, int flags)
+int generic_update_time(struct inode *inode, struct timespec64 *time, int flags)
{
int iflags = I_DIRTY_TIME;
bool dirty = false;
@@ -1649,9 +1649,9 @@ EXPORT_SYMBOL(generic_update_time);
* This does the actual work of updating an inodes time or version. Must have
* had called mnt_want_write() before calling this.
*/
-static int update_time(struct inode *inode, struct timespec *time, int flags)
+static int update_time(struct inode *inode, struct timespec64 *time, int flags)
{
- int (*update_time)(struct inode *, struct timespec *, int);
+ int (*update_time)(struct inode *, struct timespec64 *, int);
update_time = inode->i_op->update_time ? inode->i_op->update_time :
generic_update_time;
@@ -1672,7 +1672,7 @@ bool __atime_needs_update(const struct path *path, struct inode *inode,
bool rcu)
{
struct vfsmount *mnt = path->mnt;
- struct timespec now;
+ struct timespec64 now;
if (inode->i_flags & S_NOATIME)
return false;
@@ -1695,10 +1695,10 @@ bool __atime_needs_update(const struct path *path, struct inode *inode,
now = current_time(inode);
- if (!relatime_need_update(path, inode, now, rcu))
+ if (!relatime_need_update(path, inode, timespec64_to_timespec(now), rcu))
return false;
- if (timespec_equal(&inode->i_atime, &now))
+ if (timespec64_equal(&inode->i_atime, &now))
return false;
return true;
@@ -1708,7 +1708,7 @@ void touch_atime(const struct path *path)
{
struct vfsmount *mnt = path->mnt;
struct inode *inode = d_inode(path->dentry);
- struct timespec now;
+ struct timespec64 now;
if (!__atime_needs_update(path, inode, false))
return;
@@ -1842,7 +1842,7 @@ EXPORT_SYMBOL(file_remove_privs);
int file_update_time(struct file *file)
{
struct inode *inode = file_inode(file);
- struct timespec now;
+ struct timespec64 now;
int sync_it = 0;
int ret;
@@ -1851,10 +1851,10 @@ int file_update_time(struct file *file)
return 0;
now = current_time(inode);
- if (!timespec_equal(&inode->i_mtime, &now))
+ if (!timespec64_equal(&inode->i_mtime, &now))
sync_it = S_MTIME;
- if (!timespec_equal(&inode->i_ctime, &now))
+ if (!timespec64_equal(&inode->i_ctime, &now))
sync_it |= S_CTIME;
if (IS_I_VERSION(inode) && inode_iversion_need_inc(inode))
@@ -2098,6 +2098,30 @@ void inode_nohighmem(struct inode *inode)
EXPORT_SYMBOL(inode_nohighmem);
/**
+ * timespec64_trunc - Truncate timespec64 to a granularity
+ * @t: Timespec64
+ * @gran: Granularity in ns.
+ *
+ * Truncate a timespec64 to a granularity. Always rounds down. gran must
+ * not be 0 nor greater than a second (NSEC_PER_SEC, or 10^9 ns).
+ */
+struct timespec64 timespec64_trunc(struct timespec64 t, unsigned gran)
+{
+ /* Avoid division in the common cases 1 ns and 1 s. */
+ if (gran == 1) {
+ /* nothing */
+ } else if (gran == NSEC_PER_SEC) {
+ t.tv_nsec = 0;
+ } else if (gran > 1 && gran < NSEC_PER_SEC) {
+ t.tv_nsec -= t.tv_nsec % gran;
+ } else {
+ WARN(1, "illegal file time granularity: %u", gran);
+ }
+ return t;
+}
+EXPORT_SYMBOL(timespec64_trunc);
+
+/**
* current_time - Return FS time
* @inode: inode.
*
@@ -2107,15 +2131,15 @@ EXPORT_SYMBOL(inode_nohighmem);
* Note that inode and inode->sb cannot be NULL.
* Otherwise, the function warns and returns time without truncation.
*/
-struct timespec current_time(struct inode *inode)
+struct timespec64 current_time(struct inode *inode)
{
- struct timespec now = current_kernel_time();
+ struct timespec64 now = current_kernel_time64();
if (unlikely(!inode->i_sb)) {
WARN(1, "current_time() called with uninitialized super_block in the inode");
return now;
}
- return timespec_trunc(now, inode->i_sb->s_time_gran);
+ return timespec64_trunc(now, inode->i_sb->s_time_gran);
}
EXPORT_SYMBOL(current_time);
diff --git a/fs/iomap.c b/fs/iomap.c
index 7d1e9f45f098..77397b5a96ef 100644
--- a/fs/iomap.c
+++ b/fs/iomap.c
@@ -1388,7 +1388,11 @@ int iomap_swapfile_activate(struct swap_info_struct *sis,
loff_t len = ALIGN_DOWN(i_size_read(inode), PAGE_SIZE);
loff_t ret;
- ret = filemap_write_and_wait(inode->i_mapping);
+ /*
+ * Persist all file mapping metadata so that we won't have any
+ * IOMAP_F_DIRTY iomaps.
+ */
+ ret = vfs_fsync(swap_file, 1);
if (ret)
return ret;
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index 240779e4689c..a1143e57a718 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -223,7 +223,7 @@ static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size)
table->hash_size = hash_size;
table->hash_shift = shift;
table->hash_table =
- kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
+ kmalloc_array(hash_size, sizeof(struct list_head), GFP_KERNEL);
if (!table->hash_table) {
kmem_cache_free(jbd2_revoke_table_cache, table);
table = NULL;
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 7ebacf14837f..093ffbd82395 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -133,7 +133,8 @@ static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size)
size_t i;
*size = jffs2_acl_size(acl->a_count);
- header = kmalloc(sizeof(*header) + acl->a_count * sizeof(*entry), GFP_KERNEL);
+ header = kmalloc(struct_size(header, a_entries, acl->a_count),
+ GFP_KERNEL);
if (!header)
return ERR_PTR(-ENOMEM);
header->a_version = cpu_to_je32(JFFS2_ACL_VERSION);
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
index 2e2b5745c3b7..12d0271bdde3 100644
--- a/fs/jffs2/acl.h
+++ b/fs/jffs2/acl.h
@@ -22,6 +22,7 @@ struct jffs2_acl_entry_short {
struct jffs2_acl_header {
jint32_t a_version;
+ struct jffs2_acl_entry a_entries[];
};
#ifdef CONFIG_JFFS2_FS_POSIX_ACL
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index e5a6deb38e1e..b2944f9218f7 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -201,7 +201,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry,
if (ret)
goto fail;
- dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(ri->ctime)));
jffs2_free_raw_inode(ri);
@@ -234,7 +234,7 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
if (dead_f->inocache)
set_nlink(d_inode(dentry), dead_f->inocache->pino_nlink);
if (!ret)
- dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
return ret;
}
/***********************************************************************/
@@ -268,7 +268,7 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
set_nlink(d_inode(old_dentry), ++f->inocache->pino_nlink);
mutex_unlock(&f->sem);
d_instantiate(dentry, d_inode(old_dentry));
- dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
ihold(d_inode(old_dentry));
}
return ret;
@@ -418,7 +418,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
goto fail;
}
- dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(rd->mctime)));
jffs2_free_raw_dirent(rd);
@@ -561,7 +561,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, umode_t mode
goto fail;
}
- dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(rd->mctime)));
inc_nlink(dir_i);
jffs2_free_raw_dirent(rd);
@@ -598,7 +598,7 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
dentry->d_name.len, f, now);
if (!ret) {
- dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
clear_nlink(d_inode(dentry));
drop_nlink(dir_i);
}
@@ -733,7 +733,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode
goto fail;
}
- dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(rd->mctime)));
jffs2_free_raw_dirent(rd);
@@ -853,14 +853,14 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
* caller won't do it on its own since we are returning an error.
*/
d_invalidate(new_dentry);
- new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now);
+ new_dir_i->i_mtime = new_dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
return ret;
}
if (d_is_dir(old_dentry))
drop_nlink(old_dir_i);
- new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now);
+ new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
return 0;
}
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index bd0428bebe9b..481afd4c2e1a 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -308,7 +308,7 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping,
inode->i_size = pos + writtenlen;
inode->i_blocks = (inode->i_size + 511) >> 9;
- inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime));
+ inode->i_ctime = inode->i_mtime = timespec_to_timespec64(ITIME(je32_to_cpu(ri->ctime)));
}
}
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index eab04eca95a3..0ecfb8ea38cd 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -146,9 +146,9 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
return PTR_ERR(new_metadata);
}
/* It worked. Update the inode */
- inode->i_atime = ITIME(je32_to_cpu(ri->atime));
- inode->i_ctime = ITIME(je32_to_cpu(ri->ctime));
- inode->i_mtime = ITIME(je32_to_cpu(ri->mtime));
+ inode->i_atime = timespec_to_timespec64(ITIME(je32_to_cpu(ri->atime)));
+ inode->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(ri->ctime)));
+ inode->i_mtime = timespec_to_timespec64(ITIME(je32_to_cpu(ri->mtime)));
inode->i_mode = jemode_to_cpu(ri->mode);
i_uid_write(inode, je16_to_cpu(ri->uid));
i_gid_write(inode, je16_to_cpu(ri->gid));
@@ -280,9 +280,9 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
i_uid_write(inode, je16_to_cpu(latest_node.uid));
i_gid_write(inode, je16_to_cpu(latest_node.gid));
inode->i_size = je32_to_cpu(latest_node.isize);
- inode->i_atime = ITIME(je32_to_cpu(latest_node.atime));
- inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime));
- inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime));
+ inode->i_atime = timespec_to_timespec64(ITIME(je32_to_cpu(latest_node.atime)));
+ inode->i_mtime = timespec_to_timespec64(ITIME(je32_to_cpu(latest_node.mtime)));
+ inode->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(latest_node.ctime)));
set_nlink(inode, f->inocache->pino_nlink);
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 2cfe487708e0..c6821a509481 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -1208,7 +1208,7 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
if (!c->wbuf)
return -ENOMEM;
- c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->oobavail, GFP_KERNEL);
+ c->oobbuf = kmalloc_array(NR_OOB_SCAN_PAGES, c->oobavail, GFP_KERNEL);
if (!c->oobbuf) {
kfree(c->wbuf);
return -ENOMEM;
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index 2d514c7affc2..49263e220dbc 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -1641,7 +1641,7 @@ s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen)
max_ranges = nblocks;
do_div(max_ranges, minlen);
range_cnt = min_t(u64, max_ranges + 1, 32 * 1024);
- totrim = kmalloc(sizeof(struct range2trim) * range_cnt, GFP_NOFS);
+ totrim = kmalloc_array(range_cnt, sizeof(struct range2trim), GFP_NOFS);
if (totrim == NULL) {
jfs_error(bmp->db_ipbmap->i_sb, "no memory for trim array\n");
IWRITE_UNLOCK(ipbmap);
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index de2bcb36e079..52bae3f5c914 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -594,7 +594,8 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
struct component_name ciKey;
struct super_block *sb = ip->i_sb;
- ciKey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t), GFP_NOFS);
+ ciKey.name = kmalloc_array(JFS_NAME_MAX + 1, sizeof(wchar_t),
+ GFP_NOFS);
if (!ciKey.name) {
rc = -ENOMEM;
goto dtSearch_Exit2;
@@ -957,7 +958,7 @@ static int dtSplitUp(tid_t tid,
smp = split->mp;
sp = DT_PAGE(ip, smp);
- key.name = kmalloc((JFS_NAME_MAX + 2) * sizeof(wchar_t), GFP_NOFS);
+ key.name = kmalloc_array(JFS_NAME_MAX + 2, sizeof(wchar_t), GFP_NOFS);
if (!key.name) {
DT_PUTPAGE(smp);
rc = -ENOMEM;
@@ -3779,12 +3780,12 @@ static int ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
struct component_name lkey;
struct component_name rkey;
- lkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+ lkey.name = kmalloc_array(JFS_NAME_MAX + 1, sizeof(wchar_t),
GFP_KERNEL);
if (lkey.name == NULL)
return -ENOMEM;
- rkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+ rkey.name = kmalloc_array(JFS_NAME_MAX + 1, sizeof(wchar_t),
GFP_KERNEL);
if (rkey.name == NULL) {
kfree(lkey.name);
diff --git a/fs/jfs/jfs_unicode.c b/fs/jfs/jfs_unicode.c
index c7de6f5bbefc..0148e2e4d97a 100644
--- a/fs/jfs/jfs_unicode.c
+++ b/fs/jfs/jfs_unicode.c
@@ -121,7 +121,7 @@ int get_UCSname(struct component_name * uniName, struct dentry *dentry)
return -ENAMETOOLONG;
uniName->name =
- kmalloc((length + 1) * sizeof(wchar_t), GFP_NOFS);
+ kmalloc_array(length + 1, sizeof(wchar_t), GFP_NOFS);
if (uniName->name == NULL)
return -ENOMEM;
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 89d1dc19340b..d66cc0777303 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -779,7 +779,7 @@ int kernfs_add_one(struct kernfs_node *kn)
ps_iattr = parent->iattr;
if (ps_iattr) {
struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
- ktime_get_real_ts(&ps_iattrs->ia_ctime);
+ ktime_get_real_ts64(&ps_iattrs->ia_ctime);
ps_iattrs->ia_mtime = ps_iattrs->ia_ctime;
}
@@ -1306,7 +1306,7 @@ static void __kernfs_remove(struct kernfs_node *kn)
/* update timestamps on the parent */
if (ps_iattr) {
- ktime_get_real_ts(&ps_iattr->ia_iattr.ia_ctime);
+ ktime_get_real_ts64(&ps_iattr->ia_iattr.ia_ctime);
ps_iattr->ia_iattr.ia_mtime =
ps_iattr->ia_iattr.ia_ctime;
}
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index a34303981deb..3d73fe9d56e2 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -52,7 +52,7 @@ static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)
iattrs->ia_uid = GLOBAL_ROOT_UID;
iattrs->ia_gid = GLOBAL_ROOT_GID;
- ktime_get_real_ts(&iattrs->ia_atime);
+ ktime_get_real_ts64(&iattrs->ia_atime);
iattrs->ia_mtime = iattrs->ia_atime;
iattrs->ia_ctime = iattrs->ia_atime;
@@ -176,9 +176,9 @@ static inline void set_inode_attr(struct inode *inode, struct iattr *iattr)
struct super_block *sb = inode->i_sb;
inode->i_uid = iattr->ia_uid;
inode->i_gid = iattr->ia_gid;
- inode->i_atime = timespec_trunc(iattr->ia_atime, sb->s_time_gran);
- inode->i_mtime = timespec_trunc(iattr->ia_mtime, sb->s_time_gran);
- inode->i_ctime = timespec_trunc(iattr->ia_ctime, sb->s_time_gran);
+ inode->i_atime = timespec64_trunc(iattr->ia_atime, sb->s_time_gran);
+ inode->i_mtime = timespec64_trunc(iattr->ia_mtime, sb->s_time_gran);
+ inode->i_ctime = timespec64_trunc(iattr->ia_ctime, sb->s_time_gran);
}
static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode)
diff --git a/fs/locks.c b/fs/locks.c
index 05e211be8684..db7b6917d9c5 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1562,7 +1562,7 @@ EXPORT_SYMBOL(__break_lease);
* exclusive leases. The justification is that if someone has an
* exclusive lease, then they could be modifying it.
*/
-void lease_get_mtime(struct inode *inode, struct timespec *time)
+void lease_get_mtime(struct inode *inode, struct timespec64 *time)
{
bool has_lease = false;
struct file_lock_context *ctx;
diff --git a/fs/mbcache.c b/fs/mbcache.c
index bf41e2e72c18..081ccf0caee3 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -353,8 +353,9 @@ struct mb_cache *mb_cache_create(int bucket_bits)
cache->c_max_entries = bucket_count << 4;
INIT_LIST_HEAD(&cache->c_list);
spin_lock_init(&cache->c_list_lock);
- cache->c_hash = kmalloc(bucket_count * sizeof(struct hlist_bl_head),
- GFP_KERNEL);
+ cache->c_hash = kmalloc_array(bucket_count,
+ sizeof(struct hlist_bl_head),
+ GFP_KERNEL);
if (!cache->c_hash) {
kfree(cache);
goto err_out;
diff --git a/fs/namei.c b/fs/namei.c
index 6df1f61855d6..734cef54fdf8 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -537,12 +537,12 @@ static int __nd_alloc_stack(struct nameidata *nd)
struct saved *p;
if (nd->flags & LOOKUP_RCU) {
- p= kmalloc(MAXSYMLINKS * sizeof(struct saved),
+ p= kmalloc_array(MAXSYMLINKS, sizeof(struct saved),
GFP_ATOMIC);
if (unlikely(!p))
return -ECHILD;
} else {
- p= kmalloc(MAXSYMLINKS * sizeof(struct saved),
+ p= kmalloc_array(MAXSYMLINKS, sizeof(struct saved),
GFP_KERNEL);
if (unlikely(!p))
return -ENOMEM;
@@ -2464,6 +2464,35 @@ static int lookup_one_len_common(const char *name, struct dentry *base,
}
/**
+ * try_lookup_one_len - filesystem helper to lookup single pathname component
+ * @name: pathname component to lookup
+ * @base: base directory to lookup from
+ * @len: maximum length @len should be interpreted to
+ *
+ * Look up a dentry by name in the dcache, returning NULL if it does not
+ * currently exist. The function does not try to create a dentry.
+ *
+ * Note that this routine is purely a helper for filesystem usage and should
+ * not be called by generic code.
+ *
+ * The caller must hold base->i_mutex.
+ */
+struct dentry *try_lookup_one_len(const char *name, struct dentry *base, int len)
+{
+ struct qstr this;
+ int err;
+
+ WARN_ON_ONCE(!inode_is_locked(base->d_inode));
+
+ err = lookup_one_len_common(name, base, len, &this);
+ if (err)
+ return ERR_PTR(err);
+
+ return lookup_dcache(&this, base, 0);
+}
+EXPORT_SYMBOL(try_lookup_one_len);
+
+/**
* lookup_one_len - filesystem helper to lookup single pathname component
* @name: pathname component to lookup
* @base: base directory to lookup from
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index a50d7813e3ea..64c214fb9da6 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -40,7 +40,9 @@ __be32 nfs4_callback_getattr(void *argp, void *resp,
rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
inode = nfs_delegation_find_inode(cps->clp, &args->fh);
- if (inode == NULL) {
+ if (IS_ERR(inode)) {
+ if (inode == ERR_PTR(-EAGAIN))
+ res->status = htonl(NFS4ERR_DELAY);
trace_nfs4_cb_getattr(cps->clp, &args->fh, NULL,
-ntohl(res->status));
goto out;
@@ -54,8 +56,8 @@ __be32 nfs4_callback_getattr(void *argp, void *resp,
res->change_attr = delegation->change_attr;
if (nfs_have_writebacks(inode))
res->change_attr++;
- res->ctime = inode->i_ctime;
- res->mtime = inode->i_mtime;
+ res->ctime = timespec64_to_timespec(inode->i_ctime);
+ res->mtime = timespec64_to_timespec(inode->i_mtime);
res->bitmap[0] = (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) &
args->bitmap[0];
res->bitmap[1] = (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) &
@@ -86,7 +88,9 @@ __be32 nfs4_callback_recall(void *argp, void *resp,
res = htonl(NFS4ERR_BADHANDLE);
inode = nfs_delegation_find_inode(cps->clp, &args->fh);
- if (inode == NULL) {
+ if (IS_ERR(inode)) {
+ if (inode == ERR_PTR(-EAGAIN))
+ res = htonl(NFS4ERR_DELAY);
trace_nfs4_cb_recall(cps->clp, &args->fh, NULL,
&args->stateid, -ntohl(res));
goto out;
@@ -124,7 +128,6 @@ static struct inode *nfs_layout_find_inode_by_stateid(struct nfs_client *clp,
struct inode *inode;
struct pnfs_layout_hdr *lo;
-restart:
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
list_for_each_entry(lo, &server->layouts, plh_layouts) {
if (stateid != NULL &&
@@ -132,20 +135,20 @@ restart:
continue;
inode = igrab(lo->plh_inode);
if (!inode)
- continue;
+ return ERR_PTR(-EAGAIN);
if (!nfs_sb_active(inode->i_sb)) {
rcu_read_unlock();
spin_unlock(&clp->cl_lock);
iput(inode);
spin_lock(&clp->cl_lock);
rcu_read_lock();
- goto restart;
+ return ERR_PTR(-EAGAIN);
}
return inode;
}
}
- return NULL;
+ return ERR_PTR(-ENOENT);
}
/*
@@ -162,7 +165,6 @@ static struct inode *nfs_layout_find_inode_by_fh(struct nfs_client *clp,
struct inode *inode;
struct pnfs_layout_hdr *lo;
-restart:
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
list_for_each_entry(lo, &server->layouts, plh_layouts) {
nfsi = NFS_I(lo->plh_inode);
@@ -172,20 +174,20 @@ restart:
continue;
inode = igrab(lo->plh_inode);
if (!inode)
- continue;
+ return ERR_PTR(-EAGAIN);
if (!nfs_sb_active(inode->i_sb)) {
rcu_read_unlock();
spin_unlock(&clp->cl_lock);
iput(inode);
spin_lock(&clp->cl_lock);
rcu_read_lock();
- goto restart;
+ return ERR_PTR(-EAGAIN);
}
return inode;
}
}
- return NULL;
+ return ERR_PTR(-ENOENT);
}
static struct inode *nfs_layout_find_inode(struct nfs_client *clp,
@@ -197,7 +199,7 @@ static struct inode *nfs_layout_find_inode(struct nfs_client *clp,
spin_lock(&clp->cl_lock);
rcu_read_lock();
inode = nfs_layout_find_inode_by_stateid(clp, stateid);
- if (!inode)
+ if (inode == ERR_PTR(-ENOENT))
inode = nfs_layout_find_inode_by_fh(clp, fh);
rcu_read_unlock();
spin_unlock(&clp->cl_lock);
@@ -252,8 +254,11 @@ static u32 initiate_file_draining(struct nfs_client *clp,
LIST_HEAD(free_me_list);
ino = nfs_layout_find_inode(clp, &args->cbl_fh, &args->cbl_stateid);
- if (!ino)
- goto out;
+ if (IS_ERR(ino)) {
+ if (ino == ERR_PTR(-EAGAIN))
+ rv = NFS4ERR_DELAY;
+ goto out_noput;
+ }
pnfs_layoutcommit_inode(ino, false);
@@ -299,9 +304,10 @@ unlock:
nfs_commit_inode(ino, 0);
pnfs_put_layout_hdr(lo);
out:
+ nfs_iput_and_deactive(ino);
+out_noput:
trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, ino,
&args->cbl_stateid, -rv);
- nfs_iput_and_deactive(ino);
return rv;
}
@@ -322,6 +328,8 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
static u32 do_callback_layoutrecall(struct nfs_client *clp,
struct cb_layoutrecallargs *args)
{
+ write_seqcount_begin(&clp->cl_callback_count);
+ write_seqcount_end(&clp->cl_callback_count);
if (args->cbl_recall_type == RETURN_FILE)
return initiate_file_draining(clp, args);
return initiate_bulk_draining(clp, args);
@@ -420,11 +428,8 @@ validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot,
return htonl(NFS4ERR_SEQ_FALSE_RETRY);
}
- /* Wraparound */
- if (unlikely(slot->seq_nr == 0xFFFFFFFFU)) {
- if (args->csa_sequenceid == 1)
- return htonl(NFS4_OK);
- } else if (likely(args->csa_sequenceid == slot->seq_nr + 1))
+ /* Note: wraparound relies on seq_nr being of type u32 */
+ if (likely(args->csa_sequenceid == slot->seq_nr + 1))
return htonl(NFS4_OK);
/* Misordered request */
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index bbc91d7ca1bd..377a61654a88 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -969,7 +969,8 @@ struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info,
}
if (!(fattr->valid & NFS_ATTR_FATTR)) {
- error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh, fattr, NULL);
+ error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh,
+ fattr, NULL, NULL);
if (error < 0) {
dprintk("nfs_create_server: getattr error = %d\n", -error);
goto error;
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 1819d0d0ba4b..bbd0465535eb 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -404,6 +404,10 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred,
trace_nfs4_set_delegation(inode, type);
+ spin_lock(&inode->i_lock);
+ if (NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME))
+ NFS_I(inode)->cache_validity |= NFS_INO_REVAL_FORCED;
+ spin_unlock(&inode->i_lock);
out:
spin_unlock(&clp->cl_lock);
if (delegation != NULL)
@@ -483,38 +487,88 @@ out:
int nfs_client_return_marked_delegations(struct nfs_client *clp)
{
struct nfs_delegation *delegation;
+ struct nfs_delegation *prev;
struct nfs_server *server;
struct inode *inode;
+ struct inode *place_holder = NULL;
+ struct nfs_delegation *place_holder_deleg = NULL;
int err = 0;
restart:
+ /*
+ * To avoid quadratic looping we hold a reference
+ * to an inode place_holder. Each time we restart, we
+ * list nfs_servers from the server of that inode, and
+ * delegation in the server from the delegations of that
+ * inode.
+ * prev is an RCU-protected pointer to a delegation which
+ * wasn't marked for return and might be a good choice for
+ * the next place_holder.
+ */
rcu_read_lock();
- list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
- list_for_each_entry_rcu(delegation, &server->delegations,
- super_list) {
- if (!nfs_delegation_need_return(delegation))
+ prev = NULL;
+ if (place_holder)
+ server = NFS_SERVER(place_holder);
+ else
+ server = list_entry_rcu(clp->cl_superblocks.next,
+ struct nfs_server, client_link);
+ list_for_each_entry_from_rcu(server, &clp->cl_superblocks, client_link) {
+ delegation = NULL;
+ if (place_holder && server == NFS_SERVER(place_holder))
+ delegation = rcu_dereference(NFS_I(place_holder)->delegation);
+ if (!delegation || delegation != place_holder_deleg)
+ delegation = list_entry_rcu(server->delegations.next,
+ struct nfs_delegation, super_list);
+ list_for_each_entry_from_rcu(delegation, &server->delegations, super_list) {
+ struct inode *to_put = NULL;
+
+ if (!nfs_delegation_need_return(delegation)) {
+ prev = delegation;
continue;
+ }
if (!nfs_sb_active(server->super))
- continue;
+ break; /* continue in outer loop */
+
+ if (prev) {
+ struct inode *tmp;
+
+ tmp = nfs_delegation_grab_inode(prev);
+ if (tmp) {
+ to_put = place_holder;
+ place_holder = tmp;
+ place_holder_deleg = prev;
+ }
+ }
+
inode = nfs_delegation_grab_inode(delegation);
if (inode == NULL) {
rcu_read_unlock();
+ if (to_put)
+ iput(to_put);
nfs_sb_deactive(server->super);
goto restart;
}
delegation = nfs_start_delegation_return_locked(NFS_I(inode));
rcu_read_unlock();
+ if (to_put)
+ iput(to_put);
+
err = nfs_end_delegation_return(inode, delegation, 0);
iput(inode);
nfs_sb_deactive(server->super);
+ cond_resched();
if (!err)
goto restart;
set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
+ if (place_holder)
+ iput(place_holder);
return err;
}
}
rcu_read_unlock();
+ if (place_holder)
+ iput(place_holder);
return 0;
}
@@ -802,12 +856,14 @@ nfs_delegation_find_inode_server(struct nfs_server *server,
if (delegation->inode != NULL &&
nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
res = igrab(delegation->inode);
+ spin_unlock(&delegation->lock);
+ if (res != NULL)
+ return res;
+ return ERR_PTR(-EAGAIN);
}
spin_unlock(&delegation->lock);
- if (res != NULL)
- break;
}
- return res;
+ return ERR_PTR(-ENOENT);
}
/**
@@ -822,16 +878,16 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp,
const struct nfs_fh *fhandle)
{
struct nfs_server *server;
- struct inode *res = NULL;
+ struct inode *res;
rcu_read_lock();
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
res = nfs_delegation_find_inode_server(server, fhandle);
- if (res != NULL)
- break;
+ if (res != ERR_PTR(-ENOENT))
+ return res;
}
rcu_read_unlock();
- return res;
+ return ERR_PTR(-ENOENT);
}
static void nfs_delegation_mark_reclaim_server(struct nfs_server *server)
@@ -887,7 +943,7 @@ restart:
&delegation->flags) == 0)
continue;
if (!nfs_sb_active(server->super))
- continue;
+ break; /* continue in outer loop */
inode = nfs_delegation_grab_inode(delegation);
if (inode == NULL) {
rcu_read_unlock();
@@ -904,6 +960,7 @@ restart:
}
iput(inode);
nfs_sb_deactive(server->super);
+ cond_resched();
goto restart;
}
}
@@ -995,7 +1052,7 @@ restart:
&delegation->flags) == 0)
continue;
if (!nfs_sb_active(server->super))
- continue;
+ break; /* continue in outer loop */
inode = nfs_delegation_grab_inode(delegation);
if (inode == NULL) {
rcu_read_unlock();
@@ -1020,6 +1077,7 @@ restart:
}
iput(inode);
nfs_sb_deactive(server->super);
+ cond_resched();
goto restart;
}
}
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 73f8b43d988c..7a9c14426855 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1012,13 +1012,25 @@ int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags)
if (IS_AUTOMOUNT(inode))
return 0;
+
+ if (flags & LOOKUP_OPEN) {
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFREG:
+ /* A NFSv4 OPEN will revalidate later */
+ if (server->caps & NFS_CAP_ATOMIC_OPEN)
+ goto out;
+ /* Fallthrough */
+ case S_IFDIR:
+ if (server->flags & NFS_MOUNT_NOCTO)
+ break;
+ /* NFS close-to-open cache consistency validation */
+ goto out_force;
+ }
+ }
+
/* VFS wants an on-the-wire revalidation */
if (flags & LOOKUP_REVAL)
goto out_force;
- /* This is an open(2) */
- if ((flags & LOOKUP_OPEN) && !(server->flags & NFS_MOUNT_NOCTO) &&
- (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
- goto out_force;
out:
return (inode->i_nlink == 0) ? -ENOENT : 0;
out_force:
@@ -1039,13 +1051,15 @@ out_force:
*
* If LOOKUP_RCU prevents us from performing a full check, return 1
* suggesting a reval is needed.
+ *
+ * Note that when creating a new file, or looking up a rename target,
+ * then it shouldn't be necessary to revalidate a negative dentry.
*/
static inline
int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
unsigned int flags)
{
- /* Don't revalidate a negative dentry if we're creating a new file */
- if (flags & LOOKUP_CREATE)
+ if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
return 0;
if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG)
return 1;
@@ -1106,7 +1120,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
goto out_set_verifier;
/* Force a full look up iff the parent directory has changed */
- if (!nfs_is_exclusive_create(dir, flags) &&
+ if (!(flags & (LOOKUP_EXCL | LOOKUP_REVAL)) &&
nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU)) {
error = nfs_lookup_verify_inode(inode, flags);
if (error) {
@@ -1270,11 +1284,13 @@ static void nfs_drop_nlink(struct inode *inode)
{
spin_lock(&inode->i_lock);
/* drop the inode if we're reasonably sure this is the last link */
- if (inode->i_nlink == 1)
- clear_nlink(inode);
+ if (inode->i_nlink > 0)
+ drop_nlink(inode);
+ NFS_I(inode)->attr_gencount = nfs_inc_attr_generation_counter();
NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE
| NFS_INO_INVALID_CTIME
- | NFS_INO_INVALID_OTHER;
+ | NFS_INO_INVALID_OTHER
+ | NFS_INO_REVAL_FORCED;
spin_unlock(&inode->i_lock);
}
@@ -1335,7 +1351,7 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
* If we're doing an exclusive create, optimize away the lookup
* but don't hash the dentry.
*/
- if (nfs_is_exclusive_create(dir, flags))
+ if (nfs_is_exclusive_create(dir, flags) || flags & LOOKUP_RENAME_TARGET)
return NULL;
res = ERR_PTR(-ENOMEM);
@@ -1640,7 +1656,8 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
if (!(fattr->valid & NFS_ATTR_FATTR)) {
struct nfs_server *server = NFS_SB(dentry->d_sb);
- error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr, NULL);
+ error = server->nfs_client->rpc_ops->getattr(server, fhandle,
+ fattr, NULL, NULL);
if (error < 0)
goto out_error;
}
@@ -2036,7 +2053,15 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
} else
error = task->tk_status;
rpc_put_task(task);
- nfs_mark_for_revalidate(old_inode);
+ /* Ensure the inode attributes are revalidated */
+ if (error == 0) {
+ spin_lock(&old_inode->i_lock);
+ NFS_I(old_inode)->attr_gencount = nfs_inc_attr_generation_counter();
+ NFS_I(old_inode)->cache_validity |= NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_CTIME
+ | NFS_INO_REVAL_FORCED;
+ spin_unlock(&old_inode->i_lock);
+ }
out:
if (rehash)
d_rehash(rehash);
diff --git a/fs/nfs/export.c b/fs/nfs/export.c
index ab5de3246c5c..deecb67638aa 100644
--- a/fs/nfs/export.c
+++ b/fs/nfs/export.c
@@ -102,7 +102,7 @@ nfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
}
rpc_ops = NFS_SB(sb)->nfs_client->rpc_ops;
- ret = rpc_ops->getattr(NFS_SB(sb), server_fh, fattr, label);
+ ret = rpc_ops->getattr(NFS_SB(sb), server_fh, fattr, label, NULL);
if (ret) {
dprintk("%s: getattr failed %d\n", __func__, ret);
dentry = ERR_PTR(ret);
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index c75ad982bcfc..d4a07acad598 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -461,7 +461,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
fh_count = be32_to_cpup(p);
fls->mirror_array[i]->fh_versions =
- kzalloc(fh_count * sizeof(struct nfs_fh),
+ kcalloc(fh_count, sizeof(struct nfs_fh),
gfp_flags);
if (fls->mirror_array[i]->fh_versions == NULL) {
rc = -ENOMEM;
@@ -2347,6 +2347,7 @@ static struct pnfs_layoutdriver_type flexfilelayout_type = {
.id = LAYOUT_FLEX_FILES,
.name = "LAYOUT_FLEX_FILES",
.owner = THIS_MODULE,
+ .flags = PNFS_LAYOUTGET_ON_OPEN,
.set_layoutdriver = ff_layout_set_layoutdriver,
.alloc_layout_hdr = ff_layout_alloc_layout_hdr,
.free_layout_hdr = ff_layout_free_layout_hdr,
diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
index d62279d3fc5d..59aa04976331 100644
--- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c
+++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
@@ -99,7 +99,8 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
version_count = be32_to_cpup(p);
dprintk("%s: version count %d\n", __func__, version_count);
- ds_versions = kzalloc(version_count * sizeof(struct nfs4_ff_ds_version),
+ ds_versions = kcalloc(version_count,
+ sizeof(struct nfs4_ff_ds_version),
gfp_flags);
if (!ds_versions)
goto out_scratch;
diff --git a/fs/nfs/fscache-index.c b/fs/nfs/fscache-index.c
index 1c5d8d31fc0a..666415d13d52 100644
--- a/fs/nfs/fscache-index.c
+++ b/fs/nfs/fscache-index.c
@@ -88,8 +88,8 @@ enum fscache_checkaux nfs_fscache_inode_check_aux(void *cookie_netfs_data,
return FSCACHE_CHECKAUX_OBSOLETE;
memset(&auxdata, 0, sizeof(auxdata));
- auxdata.mtime = nfsi->vfs_inode.i_mtime;
- auxdata.ctime = nfsi->vfs_inode.i_ctime;
+ auxdata.mtime = timespec64_to_timespec(nfsi->vfs_inode.i_mtime);
+ auxdata.ctime = timespec64_to_timespec(nfsi->vfs_inode.i_ctime);
if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
auxdata.change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index b55fc7920c3b..4dc887813c71 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -237,8 +237,8 @@ void nfs_fscache_init_inode(struct inode *inode)
return;
memset(&auxdata, 0, sizeof(auxdata));
- auxdata.mtime = nfsi->vfs_inode.i_mtime;
- auxdata.ctime = nfsi->vfs_inode.i_ctime;
+ auxdata.mtime = timespec64_to_timespec(nfsi->vfs_inode.i_mtime);
+ auxdata.ctime = timespec64_to_timespec(nfsi->vfs_inode.i_ctime);
if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
auxdata.change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
@@ -262,8 +262,8 @@ void nfs_fscache_clear_inode(struct inode *inode)
dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie);
memset(&auxdata, 0, sizeof(auxdata));
- auxdata.mtime = nfsi->vfs_inode.i_mtime;
- auxdata.ctime = nfsi->vfs_inode.i_ctime;
+ auxdata.mtime = timespec64_to_timespec(nfsi->vfs_inode.i_mtime);
+ auxdata.ctime = timespec64_to_timespec(nfsi->vfs_inode.i_ctime);
fscache_relinquish_cookie(cookie, &auxdata, false);
nfsi->fscache = NULL;
}
@@ -304,8 +304,8 @@ void nfs_fscache_open_file(struct inode *inode, struct file *filp)
return;
memset(&auxdata, 0, sizeof(auxdata));
- auxdata.mtime = nfsi->vfs_inode.i_mtime;
- auxdata.ctime = nfsi->vfs_inode.i_ctime;
+ auxdata.mtime = timespec64_to_timespec(nfsi->vfs_inode.i_mtime);
+ auxdata.ctime = timespec64_to_timespec(nfsi->vfs_inode.i_ctime);
if (inode_is_open_for_write(inode)) {
dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index bd15d0b57626..b65aee481d13 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -195,10 +195,16 @@ bool nfs_check_cache_invalid(struct inode *inode, unsigned long flags)
static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
{
struct nfs_inode *nfsi = NFS_I(inode);
- bool have_delegation = nfs_have_delegated_attributes(inode);
+ bool have_delegation = NFS_PROTO(inode)->have_delegation(inode, FMODE_READ);
+
+ if (have_delegation) {
+ if (!(flags & NFS_INO_REVAL_FORCED))
+ flags &= ~NFS_INO_INVALID_OTHER;
+ flags &= ~(NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_SIZE
+ | NFS_INO_REVAL_PAGECACHE);
+ }
- if (have_delegation)
- flags &= ~(NFS_INO_INVALID_CHANGE|NFS_INO_REVAL_PAGECACHE);
if (inode->i_mapping->nrpages == 0)
flags &= ~NFS_INO_INVALID_DATA;
nfsi->cache_validity |= flags;
@@ -448,6 +454,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
/* We can't support update_atime(), since the server will reset it */
inode->i_flags |= S_NOATIME|S_NOCMTIME;
inode->i_mode = fattr->mode;
+ nfsi->cache_validity = 0;
if ((fattr->valid & NFS_ATTR_FATTR_MODE) == 0
&& nfs_server_capable(inode, NFS_CAP_MODE))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
@@ -494,15 +501,15 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
nfsi->read_cache_jiffies = fattr->time_start;
nfsi->attr_gencount = fattr->gencount;
if (fattr->valid & NFS_ATTR_FATTR_ATIME)
- inode->i_atime = fattr->atime;
+ inode->i_atime = timespec_to_timespec64(fattr->atime);
else if (nfs_server_capable(inode, NFS_CAP_ATIME))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATIME);
if (fattr->valid & NFS_ATTR_FATTR_MTIME)
- inode->i_mtime = fattr->mtime;
+ inode->i_mtime = timespec_to_timespec64(fattr->mtime);
else if (nfs_server_capable(inode, NFS_CAP_MTIME))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
if (fattr->valid & NFS_ATTR_FATTR_CTIME)
- inode->i_ctime = fattr->ctime;
+ inode->i_ctime = timespec_to_timespec64(fattr->ctime);
else if (nfs_server_capable(inode, NFS_CAP_CTIME))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_CTIME);
if (fattr->valid & NFS_ATTR_FATTR_CHANGE)
@@ -534,6 +541,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
}
+ if (nfsi->cache_validity != 0)
+ nfsi->cache_validity |= NFS_INO_REVAL_FORCED;
+
nfs_setsecurity(inode, fattr, label);
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
@@ -667,9 +677,13 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
spin_lock(&inode->i_lock);
NFS_I(inode)->attr_gencount = fattr->gencount;
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
- | NFS_INO_INVALID_CTIME);
+ if ((attr->ia_valid & ATTR_SIZE) != 0) {
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
+ nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
+ nfs_vmtruncate(inode, attr->ia_size);
+ }
if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
+ NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_CTIME;
if ((attr->ia_valid & ATTR_MODE) != 0) {
int mode = attr->ia_mode & S_IALLUGO;
mode |= inode->i_mode & ~S_IALLUGO;
@@ -679,13 +693,45 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
inode->i_uid = attr->ia_uid;
if ((attr->ia_valid & ATTR_GID) != 0)
inode->i_gid = attr->ia_gid;
+ if (fattr->valid & NFS_ATTR_FATTR_CTIME)
+ inode->i_ctime = timespec_to_timespec64(fattr->ctime);
+ else
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_CTIME);
nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS
| NFS_INO_INVALID_ACL);
}
- if ((attr->ia_valid & ATTR_SIZE) != 0) {
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
- nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
- nfs_vmtruncate(inode, attr->ia_size);
+ if (attr->ia_valid & (ATTR_ATIME_SET|ATTR_ATIME)) {
+ NFS_I(inode)->cache_validity &= ~(NFS_INO_INVALID_ATIME
+ | NFS_INO_INVALID_CTIME);
+ if (fattr->valid & NFS_ATTR_FATTR_ATIME)
+ inode->i_atime = timespec_to_timespec64(fattr->atime);
+ else if (attr->ia_valid & ATTR_ATIME_SET)
+ inode->i_atime = attr->ia_atime;
+ else
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATIME);
+
+ if (fattr->valid & NFS_ATTR_FATTR_CTIME)
+ inode->i_ctime = timespec_to_timespec64(fattr->ctime);
+ else
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_CTIME);
+ }
+ if (attr->ia_valid & (ATTR_MTIME_SET|ATTR_MTIME)) {
+ NFS_I(inode)->cache_validity &= ~(NFS_INO_INVALID_MTIME
+ | NFS_INO_INVALID_CTIME);
+ if (fattr->valid & NFS_ATTR_FATTR_MTIME)
+ inode->i_mtime = timespec_to_timespec64(fattr->mtime);
+ else if (attr->ia_valid & ATTR_MTIME_SET)
+ inode->i_mtime = attr->ia_mtime;
+ else
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
+
+ if (fattr->valid & NFS_ATTR_FATTR_CTIME)
+ inode->i_ctime = timespec_to_timespec64(fattr->ctime);
+ else
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_CTIME);
}
if (fattr->valid)
nfs_update_inode(inode, fattr);
@@ -1097,7 +1143,8 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
goto out;
}
- status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr, label);
+ status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr,
+ label, inode);
if (status != 0) {
dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Lu) getattr failed, error=%d\n",
inode->i_sb->s_id,
@@ -1304,6 +1351,8 @@ static bool nfs_file_has_buffered_writers(struct nfs_inode *nfsi)
static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
{
+ struct timespec ts;
+
if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE)
&& (fattr->valid & NFS_ATTR_FATTR_CHANGE)
&& inode_eq_iversion_raw(inode, fattr->pre_change_attr)) {
@@ -1312,16 +1361,18 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA);
}
/* If we have atomic WCC data, we may update some attributes */
+ ts = timespec64_to_timespec(inode->i_ctime);
if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME)
&& (fattr->valid & NFS_ATTR_FATTR_CTIME)
- && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) {
- memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+ && timespec_equal(&ts, &fattr->pre_ctime)) {
+ inode->i_ctime = timespec_to_timespec64(fattr->ctime);
}
+ ts = timespec64_to_timespec(inode->i_mtime);
if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME)
&& (fattr->valid & NFS_ATTR_FATTR_MTIME)
- && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) {
- memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
+ && timespec_equal(&ts, &fattr->pre_mtime)) {
+ inode->i_mtime = timespec_to_timespec64(fattr->mtime);
if (S_ISDIR(inode->i_mode))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA);
}
@@ -1347,10 +1398,11 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
struct nfs_inode *nfsi = NFS_I(inode);
loff_t cur_size, new_isize;
unsigned long invalid = 0;
+ struct timespec ts;
-
- if (nfs_have_delegated_attributes(inode))
+ if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ))
return 0;
+
/* Has the inode gone and changed behind our back? */
if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid)
return -ESTALE;
@@ -1363,10 +1415,12 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
invalid |= NFS_INO_INVALID_CHANGE
| NFS_INO_REVAL_PAGECACHE;
- if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&inode->i_mtime, &fattr->mtime))
+ ts = timespec64_to_timespec(inode->i_mtime);
+ if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&ts, &fattr->mtime))
invalid |= NFS_INO_INVALID_MTIME;
- if ((fattr->valid & NFS_ATTR_FATTR_CTIME) && !timespec_equal(&inode->i_ctime, &fattr->ctime))
+ ts = timespec64_to_timespec(inode->i_ctime);
+ if ((fattr->valid & NFS_ATTR_FATTR_CTIME) && !timespec_equal(&ts, &fattr->ctime))
invalid |= NFS_INO_INVALID_CTIME;
if (fattr->valid & NFS_ATTR_FATTR_SIZE) {
@@ -1396,11 +1450,12 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
if ((fattr->valid & NFS_ATTR_FATTR_NLINK) && inode->i_nlink != fattr->nlink)
invalid |= NFS_INO_INVALID_OTHER;
- if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&inode->i_atime, &fattr->atime))
+ ts = timespec64_to_timespec(inode->i_atime);
+ if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&ts, &fattr->atime))
invalid |= NFS_INO_INVALID_ATIME;
if (invalid != 0)
- nfs_set_cache_invalid(inode, invalid | NFS_INO_REVAL_FORCED);
+ nfs_set_cache_invalid(inode, invalid);
nfsi->read_cache_jiffies = fattr->time_start;
return 0;
@@ -1629,7 +1684,8 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
nfs_fattr_set_barrier(fattr);
status = nfs_post_op_update_inode_locked(inode, fattr,
NFS_INO_INVALID_CHANGE
- | NFS_INO_INVALID_CTIME);
+ | NFS_INO_INVALID_CTIME
+ | NFS_INO_REVAL_FORCED);
spin_unlock(&inode->i_lock);
return status;
@@ -1667,12 +1723,12 @@ int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fa
}
if ((fattr->valid & NFS_ATTR_FATTR_CTIME) != 0 &&
(fattr->valid & NFS_ATTR_FATTR_PRECTIME) == 0) {
- memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime));
+ fattr->pre_ctime = timespec64_to_timespec(inode->i_ctime);
fattr->valid |= NFS_ATTR_FATTR_PRECTIME;
}
if ((fattr->valid & NFS_ATTR_FATTR_MTIME) != 0 &&
(fattr->valid & NFS_ATTR_FATTR_PREMTIME) == 0) {
- memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime));
+ fattr->pre_mtime = timespec64_to_timespec(inode->i_mtime);
fattr->valid |= NFS_ATTR_FATTR_PREMTIME;
}
if ((fattr->valid & NFS_ATTR_FATTR_SIZE) != 0 &&
@@ -1746,6 +1802,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
unsigned long save_cache_validity;
bool have_writers = nfs_file_has_buffered_writers(nfsi);
bool cache_revalidated = true;
+ bool attr_changed = false;
+ bool have_delegation;
dfprintk(VFS, "NFS: %s(%s/%lu fh_crc=0x%08x ct=%d info=0x%x)\n",
__func__, inode->i_sb->s_id, inode->i_ino,
@@ -1780,6 +1838,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
!IS_AUTOMOUNT(inode))
server->fsid = fattr->fsid;
+ /* Save the delegation state before clearing cache_validity */
+ have_delegation = nfs_have_delegated_attributes(inode);
+
/*
* Update the read time so we don't revalidate too often.
*/
@@ -1802,12 +1863,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
/* More cache consistency checks */
if (fattr->valid & NFS_ATTR_FATTR_CHANGE) {
if (!inode_eq_iversion_raw(inode, fattr->change_attr)) {
- dprintk("NFS: change_attr change on server for file %s/%ld\n",
- inode->i_sb->s_id, inode->i_ino);
/* Could it be a race with writeback? */
- if (!have_writers) {
- invalid |= NFS_INO_INVALID_CHANGE
- | NFS_INO_INVALID_DATA
+ if (!(have_writers || have_delegation)) {
+ invalid |= NFS_INO_INVALID_DATA
| NFS_INO_INVALID_ACCESS
| NFS_INO_INVALID_ACL;
/* Force revalidate of all attributes */
@@ -1817,8 +1875,12 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
| NFS_INO_INVALID_OTHER;
if (S_ISDIR(inode->i_mode))
nfs_force_lookup_revalidate(inode);
+ dprintk("NFS: change_attr change on server for file %s/%ld\n",
+ inode->i_sb->s_id,
+ inode->i_ino);
}
inode_set_iversion_raw(inode, fattr->change_attr);
+ attr_changed = true;
}
} else {
nfsi->cache_validity |= save_cache_validity &
@@ -1829,7 +1891,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
}
if (fattr->valid & NFS_ATTR_FATTR_MTIME) {
- memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
+ inode->i_mtime = timespec_to_timespec64(fattr->mtime);
} else if (server->caps & NFS_CAP_MTIME) {
nfsi->cache_validity |= save_cache_validity &
(NFS_INO_INVALID_MTIME
@@ -1838,7 +1900,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
}
if (fattr->valid & NFS_ATTR_FATTR_CTIME) {
- memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+ inode->i_ctime = timespec_to_timespec64(fattr->ctime);
} else if (server->caps & NFS_CAP_CTIME) {
nfsi->cache_validity |= save_cache_validity &
(NFS_INO_INVALID_CTIME
@@ -1850,13 +1912,14 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (fattr->valid & NFS_ATTR_FATTR_SIZE) {
new_isize = nfs_size_to_loff_t(fattr->size);
cur_isize = i_size_read(inode);
- if (new_isize != cur_isize) {
+ if (new_isize != cur_isize && !have_delegation) {
/* Do we perhaps have any outstanding writes, or has
* the file grown beyond our last write? */
if (!nfs_have_writebacks(inode) || new_isize > cur_isize) {
i_size_write(inode, new_isize);
if (!have_writers)
invalid |= NFS_INO_INVALID_DATA;
+ attr_changed = true;
}
dprintk("NFS: isize change on server for file %s/%ld "
"(%Ld to %Ld)\n",
@@ -1875,7 +1938,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (fattr->valid & NFS_ATTR_FATTR_ATIME)
- memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
+ inode->i_atime = timespec_to_timespec64(fattr->atime);
else if (server->caps & NFS_CAP_ATIME) {
nfsi->cache_validity |= save_cache_validity &
(NFS_INO_INVALID_ATIME
@@ -1889,14 +1952,12 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
newmode |= fattr->mode & S_IALLUGO;
inode->i_mode = newmode;
invalid |= NFS_INO_INVALID_ACCESS
- | NFS_INO_INVALID_ACL
- | NFS_INO_INVALID_OTHER;
+ | NFS_INO_INVALID_ACL;
+ attr_changed = true;
}
} else if (server->caps & NFS_CAP_MODE) {
nfsi->cache_validity |= save_cache_validity &
- (NFS_INO_INVALID_ACCESS
- | NFS_INO_INVALID_ACL
- | NFS_INO_INVALID_OTHER
+ (NFS_INO_INVALID_OTHER
| NFS_INO_REVAL_FORCED);
cache_revalidated = false;
}
@@ -1904,15 +1965,13 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (fattr->valid & NFS_ATTR_FATTR_OWNER) {
if (!uid_eq(inode->i_uid, fattr->uid)) {
invalid |= NFS_INO_INVALID_ACCESS
- | NFS_INO_INVALID_ACL
- | NFS_INO_INVALID_OTHER;
+ | NFS_INO_INVALID_ACL;
inode->i_uid = fattr->uid;
+ attr_changed = true;
}
} else if (server->caps & NFS_CAP_OWNER) {
nfsi->cache_validity |= save_cache_validity &
- (NFS_INO_INVALID_ACCESS
- | NFS_INO_INVALID_ACL
- | NFS_INO_INVALID_OTHER
+ (NFS_INO_INVALID_OTHER
| NFS_INO_REVAL_FORCED);
cache_revalidated = false;
}
@@ -1920,25 +1979,23 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (fattr->valid & NFS_ATTR_FATTR_GROUP) {
if (!gid_eq(inode->i_gid, fattr->gid)) {
invalid |= NFS_INO_INVALID_ACCESS
- | NFS_INO_INVALID_ACL
- | NFS_INO_INVALID_OTHER;
+ | NFS_INO_INVALID_ACL;
inode->i_gid = fattr->gid;
+ attr_changed = true;
}
} else if (server->caps & NFS_CAP_OWNER_GROUP) {
nfsi->cache_validity |= save_cache_validity &
- (NFS_INO_INVALID_ACCESS
- | NFS_INO_INVALID_ACL
- | NFS_INO_INVALID_OTHER
+ (NFS_INO_INVALID_OTHER
| NFS_INO_REVAL_FORCED);
cache_revalidated = false;
}
if (fattr->valid & NFS_ATTR_FATTR_NLINK) {
if (inode->i_nlink != fattr->nlink) {
- invalid |= NFS_INO_INVALID_OTHER;
if (S_ISDIR(inode->i_mode))
invalid |= NFS_INO_INVALID_DATA;
set_nlink(inode, fattr->nlink);
+ attr_changed = true;
}
} else if (server->caps & NFS_CAP_NLINK) {
nfsi->cache_validity |= save_cache_validity &
@@ -1958,7 +2015,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
cache_revalidated = false;
/* Update attrtimeo value if we're out of the unstable period */
- if (invalid & NFS_INO_INVALID_ATTR) {
+ if (attr_changed) {
invalid &= ~NFS_INO_INVALID_ATTR;
nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
@@ -1984,9 +2041,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
|| S_ISLNK(inode->i_mode)))
invalid &= ~NFS_INO_INVALID_DATA;
- if (!NFS_PROTO(inode)->have_delegation(inode, FMODE_READ) ||
- (save_cache_validity & NFS_INO_REVAL_FORCED))
- nfs_set_cache_invalid(inode, invalid);
+ nfs_set_cache_invalid(inode, invalid);
return 0;
out_err:
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 85e4b4a233f9..350675e3ed47 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -354,6 +354,7 @@ static __be32 *xdr_time_not_set(__be32 *p)
static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)
{
+ struct timespec ts;
__be32 *p;
p = xdr_reserve_space(xdr, NFS_sattr_sz << 2);
@@ -375,17 +376,21 @@ static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)
else
*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
- if (attr->ia_valid & ATTR_ATIME_SET)
- p = xdr_encode_time(p, &attr->ia_atime);
- else if (attr->ia_valid & ATTR_ATIME)
- p = xdr_encode_current_server_time(p, &attr->ia_atime);
- else
+ if (attr->ia_valid & ATTR_ATIME_SET) {
+ ts = timespec64_to_timespec(attr->ia_atime);
+ p = xdr_encode_time(p, &ts);
+ } else if (attr->ia_valid & ATTR_ATIME) {
+ ts = timespec64_to_timespec(attr->ia_atime);
+ p = xdr_encode_current_server_time(p, &ts);
+ } else
p = xdr_time_not_set(p);
- if (attr->ia_valid & ATTR_MTIME_SET)
- xdr_encode_time(p, &attr->ia_mtime);
- else if (attr->ia_valid & ATTR_MTIME)
- xdr_encode_current_server_time(p, &attr->ia_mtime);
- else
+ if (attr->ia_valid & ATTR_MTIME_SET) {
+ ts = timespec64_to_timespec(attr->ia_atime);
+ xdr_encode_time(p, &ts);
+ } else if (attr->ia_valid & ATTR_MTIME) {
+ ts = timespec64_to_timespec(attr->ia_mtime);
+ xdr_encode_current_server_time(p, &ts);
+ } else
xdr_time_not_set(p);
}
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index eadf1ab31d16..ec8a9efa268f 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -101,7 +101,8 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
*/
static int
nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr, struct nfs4_label *label)
+ struct nfs_fattr *fattr, struct nfs4_label *label,
+ struct inode *inode)
{
struct rpc_message msg = {
.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR],
@@ -414,7 +415,9 @@ out:
}
static void
-nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dentry)
+nfs3_proc_unlink_setup(struct rpc_message *msg,
+ struct dentry *dentry,
+ struct inode *inode)
{
msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
}
@@ -823,7 +826,8 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
}
static void nfs3_proc_write_setup(struct nfs_pgio_header *hdr,
- struct rpc_message *msg)
+ struct rpc_message *msg,
+ struct rpc_clnt **clnt)
{
msg->rpc_proc = &nfs3_procedures[NFS3PROC_WRITE];
}
@@ -844,7 +848,8 @@ static int nfs3_commit_done(struct rpc_task *task, struct nfs_commit_data *data)
return 0;
}
-static void nfs3_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
+static void nfs3_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg,
+ struct rpc_clnt **clnt)
{
msg->rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT];
}
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 09ee36dd8426..64e4fa33d89f 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -561,6 +561,7 @@ static __be32 *xdr_decode_nfstime3(__be32 *p, struct timespec *timep)
*/
static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
{
+ struct timespec ts;
u32 nbytes;
__be32 *p;
@@ -610,8 +611,10 @@ static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
*p++ = xdr_zero;
if (attr->ia_valid & ATTR_ATIME_SET) {
+ struct timespec ts;
*p++ = xdr_two;
- p = xdr_encode_nfstime3(p, &attr->ia_atime);
+ ts = timespec64_to_timespec(attr->ia_atime);
+ p = xdr_encode_nfstime3(p, &ts);
} else if (attr->ia_valid & ATTR_ATIME) {
*p++ = xdr_one;
} else
@@ -619,7 +622,8 @@ static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
if (attr->ia_valid & ATTR_MTIME_SET) {
*p++ = xdr_two;
- xdr_encode_nfstime3(p, &attr->ia_mtime);
+ ts = timespec64_to_timespec(attr->ia_mtime);
+ xdr_encode_nfstime3(p, &ts);
} else if (attr->ia_valid & ATTR_MTIME) {
*p = xdr_one;
} else
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
index 9c374441f660..5f59b6f65a42 100644
--- a/fs/nfs/nfs42proc.c
+++ b/fs/nfs/nfs42proc.c
@@ -370,6 +370,10 @@ nfs42_layoutstat_done(struct rpc_task *task, void *calldata)
switch (task->tk_status) {
case 0:
break;
+ case -NFS4ERR_BADHANDLE:
+ case -ESTALE:
+ pnfs_destroy_layout(NFS_I(inode));
+ break;
case -NFS4ERR_EXPIRED:
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_DELEG_REVOKED:
@@ -462,7 +466,7 @@ int nfs42_proc_layoutstats_generic(struct nfs_server *server,
nfs42_layoutstat_release(data);
return -EAGAIN;
}
- nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
+ nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0, 0);
task = rpc_run_task(&task_setup);
if (IS_ERR(task))
return PTR_ERR(task);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index b374f680830c..137e18abb7e7 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -212,6 +212,31 @@ struct nfs4_state_recovery_ops {
struct rpc_cred *);
};
+struct nfs4_opendata {
+ struct kref kref;
+ struct nfs_openargs o_arg;
+ struct nfs_openres o_res;
+ struct nfs_open_confirmargs c_arg;
+ struct nfs_open_confirmres c_res;
+ struct nfs4_string owner_name;
+ struct nfs4_string group_name;
+ struct nfs4_label *a_label;
+ struct nfs_fattr f_attr;
+ struct nfs4_label *f_label;
+ struct dentry *dir;
+ struct dentry *dentry;
+ struct nfs4_state_owner *owner;
+ struct nfs4_state *state;
+ struct iattr attrs;
+ struct nfs4_layoutget *lgp;
+ unsigned long timestamp;
+ bool rpc_done;
+ bool file_created;
+ bool is_recover;
+ bool cancelled;
+ int rpc_status;
+};
+
struct nfs4_add_xprt_data {
struct nfs_client *clp;
struct rpc_cred *cred;
@@ -251,7 +276,7 @@ extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception
extern int nfs4_call_sync(struct rpc_clnt *, struct nfs_server *,
struct rpc_message *, struct nfs4_sequence_args *,
struct nfs4_sequence_res *, int);
-extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct nfs4_sequence_res *, int);
+extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct nfs4_sequence_res *, int, int);
extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *);
extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *);
extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *, bool);
diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c
index 22dc30a679a0..b6f9d84ba19b 100644
--- a/fs/nfs/nfs4idmap.c
+++ b/fs/nfs/nfs4idmap.c
@@ -343,7 +343,7 @@ static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf,
int id_len;
ssize_t ret;
- id_len = snprintf(id_str, sizeof(id_str), "%u", id);
+ id_len = nfs_map_numeric_to_string(id, id_str, sizeof(id_str));
ret = nfs_idmap_get_key(id_str, id_len, type, buf, buflen, idmap);
if (ret < 0)
return -EINVAL;
@@ -627,7 +627,8 @@ static int nfs_idmap_read_and_verify_message(struct idmap_msg *im,
if (strcmp(upcall->im_name, im->im_name) != 0)
break;
/* Note: here we store the NUL terminator too */
- len = sprintf(id_str, "%d", im->im_id) + 1;
+ len = 1 + nfs_map_numeric_to_string(im->im_id, id_str,
+ sizeof(id_str));
ret = nfs_idmap_instantiate(key, authkey, id_str, len);
break;
case IDMAP_CONV_IDTONAME:
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index b71757e85066..ed45090e4df6 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -71,6 +71,8 @@
#define NFSDBG_FACILITY NFSDBG_PROC
+#define NFS4_BITMASK_SZ 3
+
#define NFS4_POLL_RETRY_MIN (HZ/10)
#define NFS4_POLL_RETRY_MAX (15*HZ)
@@ -86,12 +88,11 @@
| ATTR_MTIME_SET)
struct nfs4_opendata;
-static int _nfs4_proc_open(struct nfs4_opendata *data);
static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
-static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label);
-static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label);
+static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label, struct inode *inode);
+static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label, struct inode *inode);
static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
struct nfs_fattr *fattr, struct iattr *sattr,
struct nfs_open_context *ctx, struct nfs4_label *ilabel,
@@ -274,6 +275,33 @@ const u32 nfs4_fs_locations_bitmap[3] = {
| FATTR4_WORD1_MOUNTED_ON_FILEID,
};
+static void nfs4_bitmap_copy_adjust(__u32 *dst, const __u32 *src,
+ struct inode *inode)
+{
+ unsigned long cache_validity;
+
+ memcpy(dst, src, NFS4_BITMASK_SZ*sizeof(*dst));
+ if (!inode || !nfs4_have_delegation(inode, FMODE_READ))
+ return;
+
+ cache_validity = READ_ONCE(NFS_I(inode)->cache_validity);
+ if (!(cache_validity & NFS_INO_REVAL_FORCED))
+ cache_validity &= ~(NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_SIZE);
+
+ if (!(cache_validity & NFS_INO_INVALID_SIZE))
+ dst[0] &= ~FATTR4_WORD0_SIZE;
+
+ if (!(cache_validity & NFS_INO_INVALID_CHANGE))
+ dst[0] &= ~FATTR4_WORD0_CHANGE;
+}
+
+static void nfs4_bitmap_copy_adjust_setattr(__u32 *dst,
+ const __u32 *src, struct inode *inode)
+{
+ nfs4_bitmap_copy_adjust(dst, src, inode);
+}
+
static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
struct nfs4_readdir_arg *readdir)
{
@@ -407,6 +435,11 @@ static int nfs4_do_handle_exception(struct nfs_server *server,
switch(errorcode) {
case 0:
return 0;
+ case -NFS4ERR_BADHANDLE:
+ case -ESTALE:
+ if (inode != NULL && S_ISREG(inode->i_mode))
+ pnfs_destroy_layout(NFS_I(inode));
+ break;
case -NFS4ERR_DELEG_REVOKED:
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_EXPIRED:
@@ -608,20 +641,16 @@ struct nfs4_call_sync_data {
};
void nfs4_init_sequence(struct nfs4_sequence_args *args,
- struct nfs4_sequence_res *res, int cache_reply)
+ struct nfs4_sequence_res *res, int cache_reply,
+ int privileged)
{
args->sa_slot = NULL;
args->sa_cache_this = cache_reply;
- args->sa_privileged = 0;
+ args->sa_privileged = privileged;
res->sr_slot = NULL;
}
-static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args)
-{
- args->sa_privileged = 1;
-}
-
static void nfs40_sequence_free_slot(struct nfs4_sequence_res *res)
{
struct nfs4_slot *slot = res->sr_slot;
@@ -746,12 +775,19 @@ static int nfs41_sequence_process(struct rpc_task *task,
slot->slot_nr,
slot->seq_nr);
goto out_retry;
+ case -NFS4ERR_RETRY_UNCACHED_REP:
+ case -NFS4ERR_SEQ_FALSE_RETRY:
+ /*
+ * The server thinks we tried to replay a request.
+ * Retry the call after bumping the sequence ID.
+ */
+ goto retry_new_seq;
case -NFS4ERR_BADSLOT:
/*
* The slot id we used was probably retired. Try again
* using a different slot id.
*/
- if (slot->seq_nr < slot->table->target_highest_slotid)
+ if (slot->slot_nr < slot->table->target_highest_slotid)
goto session_recover;
goto retry_nowait;
case -NFS4ERR_SEQ_MISORDERED:
@@ -770,10 +806,6 @@ static int nfs41_sequence_process(struct rpc_task *task,
goto retry_nowait;
}
goto session_recover;
- case -NFS4ERR_SEQ_FALSE_RETRY:
- if (interrupted)
- goto retry_new_seq;
- goto session_recover;
default:
/* Just update the slot sequence no. */
slot->seq_done = 1;
@@ -1035,7 +1067,7 @@ int nfs4_call_sync(struct rpc_clnt *clnt,
struct nfs4_sequence_res *res,
int cache_reply)
{
- nfs4_init_sequence(args, res, cache_reply);
+ nfs4_init_sequence(args, res, cache_reply, 0);
return nfs4_call_sync_sequence(clnt, server, msg, args, res);
}
@@ -1064,30 +1096,6 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo,
spin_unlock(&dir->i_lock);
}
-struct nfs4_opendata {
- struct kref kref;
- struct nfs_openargs o_arg;
- struct nfs_openres o_res;
- struct nfs_open_confirmargs c_arg;
- struct nfs_open_confirmres c_res;
- struct nfs4_string owner_name;
- struct nfs4_string group_name;
- struct nfs4_label *a_label;
- struct nfs_fattr f_attr;
- struct nfs4_label *f_label;
- struct dentry *dir;
- struct dentry *dentry;
- struct nfs4_state_owner *owner;
- struct nfs4_state *state;
- struct iattr attrs;
- unsigned long timestamp;
- bool rpc_done;
- bool file_created;
- bool is_recover;
- bool cancelled;
- int rpc_status;
-};
-
struct nfs4_open_createattrs {
struct nfs4_label *label;
struct iattr *sattr;
@@ -1268,6 +1276,7 @@ static void nfs4_opendata_free(struct kref *kref)
struct nfs4_opendata, kref);
struct super_block *sb = p->dentry->d_sb;
+ nfs4_lgopen_release(p->lgp);
nfs_free_seqid(p->o_arg.seqid);
nfs4_sequence_free_slot(&p->o_res.seq_res);
if (p->state != NULL)
@@ -2187,13 +2196,12 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
};
int status;
- nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1);
+ nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1,
+ data->is_recover);
kref_get(&data->kref);
data->rpc_done = false;
data->rpc_status = 0;
data->timestamp = jiffies;
- if (data->is_recover)
- nfs4_set_sequence_privileged(&data->c_arg.seq_args);
task = rpc_run_task(&task_setup_data);
if (IS_ERR(task))
return PTR_ERR(task);
@@ -2327,7 +2335,8 @@ static const struct rpc_call_ops nfs4_open_ops = {
.rpc_release = nfs4_open_release,
};
-static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
+static int nfs4_run_open_task(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx)
{
struct inode *dir = d_inode(data->dir);
struct nfs_server *server = NFS_SERVER(dir);
@@ -2350,15 +2359,17 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
};
int status;
- nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1);
kref_get(&data->kref);
data->rpc_done = false;
data->rpc_status = 0;
data->cancelled = false;
data->is_recover = false;
- if (isrecover) {
- nfs4_set_sequence_privileged(&o_arg->seq_args);
+ if (!ctx) {
+ nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 1);
data->is_recover = true;
+ } else {
+ nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 0);
+ pnfs_lgopen_prepare(data, ctx);
}
task = rpc_run_task(&task_setup_data);
if (IS_ERR(task))
@@ -2380,7 +2391,7 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
struct nfs_openres *o_res = &data->o_res;
int status;
- status = nfs4_run_open_task(data, 1);
+ status = nfs4_run_open_task(data, NULL);
if (status != 0 || !data->rpc_done)
return status;
@@ -2441,7 +2452,8 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
/*
* Note: On error, nfs4_proc_open will free the struct nfs4_opendata
*/
-static int _nfs4_proc_open(struct nfs4_opendata *data)
+static int _nfs4_proc_open(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx)
{
struct inode *dir = d_inode(data->dir);
struct nfs_server *server = NFS_SERVER(dir);
@@ -2449,7 +2461,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
struct nfs_openres *o_res = &data->o_res;
int status;
- status = nfs4_run_open_task(data, 0);
+ status = nfs4_run_open_task(data, ctx);
if (!data->rpc_done)
return status;
if (status != 0) {
@@ -2480,7 +2492,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
}
if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) {
nfs4_sequence_free_slot(&o_res->seq_res);
- nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, o_res->f_label);
+ nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr,
+ o_res->f_label, NULL);
}
return 0;
}
@@ -2800,11 +2813,11 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
- ret = _nfs4_proc_open(opendata);
+ ret = _nfs4_proc_open(opendata, ctx);
if (ret != 0)
goto out;
- state = nfs4_opendata_to_nfs4_state(opendata);
+ state = _nfs4_opendata_to_nfs4_state(opendata);
ret = PTR_ERR(state);
if (IS_ERR(state))
goto out;
@@ -2838,8 +2851,12 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
nfs_inode_attach_open_context(ctx);
if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
nfs4_schedule_stateid_recovery(server, state);
+ else
+ pnfs_parse_lgopen(state->inode, opendata->lgp, ctx);
}
+
out:
+ nfs4_sequence_free_slot(&opendata->o_res.seq_res);
return ret;
}
@@ -3039,7 +3056,6 @@ static int _nfs4_do_setattr(struct inode *inode,
};
struct rpc_cred *delegation_cred = NULL;
unsigned long timestamp = jiffies;
- fmode_t fmode;
bool truncate;
int status;
@@ -3047,11 +3063,12 @@ static int _nfs4_do_setattr(struct inode *inode,
/* Servers should only apply open mode checks for file size changes */
truncate = (arg->iap->ia_valid & ATTR_SIZE) ? true : false;
- fmode = truncate ? FMODE_WRITE : FMODE_READ;
+ if (!truncate)
+ goto zero_stateid;
- if (nfs4_copy_delegation_stateid(inode, fmode, &arg->stateid, &delegation_cred)) {
+ if (nfs4_copy_delegation_stateid(inode, FMODE_WRITE, &arg->stateid, &delegation_cred)) {
/* Use that stateid */
- } else if (truncate && ctx != NULL) {
+ } else if (ctx != NULL) {
struct nfs_lock_context *l_ctx;
if (!nfs4_valid_open_stateid(ctx->state))
return -EBADF;
@@ -3063,8 +3080,10 @@ static int _nfs4_do_setattr(struct inode *inode,
nfs_put_lock_context(l_ctx);
if (status == -EIO)
return -EBADF;
- } else
+ } else {
+zero_stateid:
nfs4_stateid_copy(&arg->stateid, &zero_stateid);
+ }
if (delegation_cred)
msg.rpc_cred = delegation_cred;
@@ -3083,12 +3102,13 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
struct nfs4_label *olabel)
{
struct nfs_server *server = NFS_SERVER(inode);
+ __u32 bitmask[NFS4_BITMASK_SZ];
struct nfs4_state *state = ctx ? ctx->state : NULL;
struct nfs_setattrargs arg = {
.fh = NFS_FH(inode),
.iap = sattr,
.server = server,
- .bitmask = server->attr_bitmask,
+ .bitmask = bitmask,
.label = ilabel,
};
struct nfs_setattrres res = {
@@ -3103,11 +3123,11 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
};
int err;
- arg.bitmask = nfs4_bitmask(server, ilabel);
- if (ilabel)
- arg.bitmask = nfs4_bitmask(server, olabel);
-
do {
+ nfs4_bitmap_copy_adjust_setattr(bitmask,
+ nfs4_bitmask(server, olabel),
+ inode);
+
err = _nfs4_do_setattr(inode, &arg, &res, cred, ctx);
switch (err) {
case -NFS4ERR_OPENMODE:
@@ -3393,7 +3413,7 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait)
calldata = kzalloc(sizeof(*calldata), gfp_mask);
if (calldata == NULL)
goto out;
- nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 1);
+ nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 1, 0);
calldata->inode = state->inode;
calldata->state = state;
calldata->arg.fh = NFS_FH(state->inode);
@@ -3742,7 +3762,7 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *mntfh,
if (IS_ERR(label))
return PTR_ERR(label);
- error = nfs4_proc_getattr(server, mntfh, fattr, label);
+ error = nfs4_proc_getattr(server, mntfh, fattr, label, NULL);
if (error < 0) {
dprintk("nfs4_get_root: getattr error = %d\n", -error);
goto err_free_label;
@@ -3807,11 +3827,13 @@ out:
}
static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr, struct nfs4_label *label)
+ struct nfs_fattr *fattr, struct nfs4_label *label,
+ struct inode *inode)
{
+ __u32 bitmask[NFS4_BITMASK_SZ];
struct nfs4_getattr_arg args = {
.fh = fhandle,
- .bitmask = server->attr_bitmask,
+ .bitmask = bitmask,
};
struct nfs4_getattr_res res = {
.fattr = fattr,
@@ -3824,19 +3846,20 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
.rpc_resp = &res,
};
- args.bitmask = nfs4_bitmask(server, label);
+ nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, label), inode);
nfs_fattr_init(fattr);
return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
}
static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr, struct nfs4_label *label)
+ struct nfs_fattr *fattr, struct nfs4_label *label,
+ struct inode *inode)
{
struct nfs4_exception exception = { };
int err;
do {
- err = _nfs4_proc_getattr(server, fhandle, fattr, label);
+ err = _nfs4_proc_getattr(server, fhandle, fattr, label, inode);
trace_nfs4_getattr(server, fhandle, fattr, err);
err = nfs4_handle_exception(server, err,
&exception);
@@ -4089,7 +4112,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
};
int status = 0;
- if (!nfs_have_delegated_attributes(inode)) {
+ if (!nfs4_have_delegation(inode, FMODE_READ)) {
res.fattr = nfs_alloc_fattr();
if (res.fattr == NULL)
return -ENOMEM;
@@ -4265,15 +4288,16 @@ static int nfs4_proc_rmdir(struct inode *dir, const struct qstr *name)
return err;
}
-static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dentry)
+static void nfs4_proc_unlink_setup(struct rpc_message *msg,
+ struct dentry *dentry,
+ struct inode *inode)
{
struct nfs_removeargs *args = msg->rpc_argp;
struct nfs_removeres *res = msg->rpc_resp;
- struct inode *inode = d_inode(dentry);
res->server = NFS_SB(dentry->d_sb);
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
- nfs4_init_sequence(&args->seq_args, &res->seq_res, 1);
+ nfs4_init_sequence(&args->seq_args, &res->seq_res, 1, 0);
nfs_fattr_init(res->dir_attr);
@@ -4319,7 +4343,7 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg,
nfs4_inode_return_delegation(new_inode);
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
res->server = NFS_SB(old_dentry->d_sb);
- nfs4_init_sequence(&arg->seq_args, &res->seq_res, 1);
+ nfs4_init_sequence(&arg->seq_args, &res->seq_res, 1, 0);
}
static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data)
@@ -4352,11 +4376,12 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
{
struct nfs_server *server = NFS_SERVER(inode);
+ __u32 bitmask[NFS4_BITMASK_SZ];
struct nfs4_link_arg arg = {
.fh = NFS_FH(inode),
.dir_fh = NFS_FH(dir),
.name = name,
- .bitmask = server->attr_bitmask,
+ .bitmask = bitmask,
};
struct nfs4_link_res res = {
.server = server,
@@ -4378,9 +4403,9 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct
status = PTR_ERR(res.label);
goto out;
}
- arg.bitmask = nfs4_bitmask(server, res.label);
nfs4_inode_make_writeable(inode);
+ nfs4_bitmap_copy_adjust_setattr(bitmask, nfs4_bitmask(server, res.label), inode);
status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
if (!status) {
@@ -4895,7 +4920,7 @@ static void nfs4_proc_read_setup(struct nfs_pgio_header *hdr,
if (!hdr->pgio_done_cb)
hdr->pgio_done_cb = nfs4_read_done_cb;
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
- nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 0);
+ nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 0, 0);
}
static int nfs4_proc_pgio_rpc_prepare(struct rpc_task *task,
@@ -4979,7 +5004,8 @@ bool nfs4_write_need_cache_consistency_data(struct nfs_pgio_header *hdr)
}
static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
- struct rpc_message *msg)
+ struct rpc_message *msg,
+ struct rpc_clnt **clnt)
{
struct nfs_server *server = NFS_SERVER(hdr->inode);
@@ -4995,7 +5021,8 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
hdr->timestamp = jiffies;
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE];
- nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 1);
+ nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 1, 0);
+ nfs4_state_protect_write(server->nfs_client, clnt, msg, hdr);
}
static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
@@ -5026,7 +5053,8 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_commit_data *data)
return data->commit_done_cb(task, data);
}
-static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
+static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg,
+ struct rpc_clnt **clnt)
{
struct nfs_server *server = NFS_SERVER(data->inode);
@@ -5034,7 +5062,8 @@ static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_mess
data->commit_done_cb = nfs4_commit_done_cb;
data->res.server = server;
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT];
- nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
+ nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, 0);
+ nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_COMMIT, clnt, msg);
}
struct nfs4_renewdata {
@@ -5391,7 +5420,8 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
*/
spin_lock(&inode->i_lock);
NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE
- | NFS_INO_INVALID_CTIME;
+ | NFS_INO_INVALID_CTIME
+ | NFS_INO_REVAL_FORCED;
spin_unlock(&inode->i_lock);
nfs_access_zap_cache(inode);
nfs_zap_acl_cache(inode);
@@ -5591,13 +5621,14 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp)
return 0;
rcu_read_lock();
- len = 14 + strlen(clp->cl_ipaddr) + 1 +
- strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)) +
+ len = 14 +
+ strlen(clp->cl_rpcclient->cl_nodename) +
1 +
- strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_PROTO)) +
+ strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)) +
1;
rcu_read_unlock();
-
+ if (nfs4_client_id_uniquifier[0] != '\0')
+ len += strlen(nfs4_client_id_uniquifier) + 1;
if (len > NFS4_OPAQUE_LIMIT + 1)
return -EINVAL;
@@ -5611,10 +5642,17 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp)
return -ENOMEM;
rcu_read_lock();
- scnprintf(str, len, "Linux NFSv4.0 %s/%s %s",
- clp->cl_ipaddr,
- rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR),
- rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_PROTO));
+ if (nfs4_client_id_uniquifier[0] != '\0')
+ scnprintf(str, len, "Linux NFSv4.0 %s/%s/%s",
+ clp->cl_rpcclient->cl_nodename,
+ nfs4_client_id_uniquifier,
+ rpc_peeraddr2str(clp->cl_rpcclient,
+ RPC_DISPLAY_ADDR));
+ else
+ scnprintf(str, len, "Linux NFSv4.0 %s/%s",
+ clp->cl_rpcclient->cl_nodename,
+ rpc_peeraddr2str(clp->cl_rpcclient,
+ RPC_DISPLAY_ADDR));
rcu_read_unlock();
clp->cl_owner_id = str;
@@ -5972,7 +6010,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
data = kzalloc(sizeof(*data), GFP_NOFS);
if (data == NULL)
return -ENOMEM;
- nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
+ nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, 0);
nfs4_state_protect(server->nfs_client,
NFS_SP4_MACH_CRED_CLEANUP,
@@ -6247,7 +6285,7 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
return ERR_PTR(-ENOMEM);
}
- nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1);
+ nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1, 0);
msg.rpc_argp = &data->arg;
msg.rpc_resp = &data->res;
task_setup_data.callback_data = data;
@@ -6411,32 +6449,36 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
case 0:
renew_lease(NFS_SERVER(d_inode(data->ctx->dentry)),
data->timestamp);
- if (data->arg.new_lock) {
+ if (data->arg.new_lock && !data->cancelled) {
data->fl.fl_flags &= ~(FL_SLEEP | FL_ACCESS);
- if (locks_lock_inode_wait(lsp->ls_state->inode, &data->fl) < 0) {
- rpc_restart_call_prepare(task);
+ if (locks_lock_inode_wait(lsp->ls_state->inode, &data->fl) < 0)
break;
- }
}
+
if (data->arg.new_lock_owner != 0) {
nfs_confirm_seqid(&lsp->ls_seqid, 0);
nfs4_stateid_copy(&lsp->ls_stateid, &data->res.stateid);
set_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags);
- } else if (!nfs4_update_lock_stateid(lsp, &data->res.stateid))
- rpc_restart_call_prepare(task);
+ goto out_done;
+ } else if (nfs4_update_lock_stateid(lsp, &data->res.stateid))
+ goto out_done;
+
break;
case -NFS4ERR_BAD_STATEID:
case -NFS4ERR_OLD_STATEID:
case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_EXPIRED:
if (data->arg.new_lock_owner != 0) {
- if (!nfs4_stateid_match(&data->arg.open_stateid,
+ if (nfs4_stateid_match(&data->arg.open_stateid,
&lsp->ls_state->open_stateid))
- rpc_restart_call_prepare(task);
- } else if (!nfs4_stateid_match(&data->arg.lock_stateid,
+ goto out_done;
+ } else if (nfs4_stateid_match(&data->arg.lock_stateid,
&lsp->ls_stateid))
- rpc_restart_call_prepare(task);
+ goto out_done;
}
+ if (!data->cancelled)
+ rpc_restart_call_prepare(task);
+out_done:
dprintk("%s: done, ret = %d!\n", __func__, data->rpc_status);
}
@@ -6509,14 +6551,14 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
return -ENOMEM;
if (IS_SETLKW(cmd))
data->arg.block = 1;
- nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1);
+ nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1,
+ recovery_type > NFS_LOCK_NEW);
msg.rpc_argp = &data->arg;
msg.rpc_resp = &data->res;
task_setup_data.callback_data = data;
if (recovery_type > NFS_LOCK_NEW) {
if (recovery_type == NFS_LOCK_RECLAIM)
data->arg.reclaim = NFS_LOCK_RECLAIM;
- nfs4_set_sequence_privileged(&data->arg.seq_args);
} else
data->arg.new_lock = 1;
task = rpc_run_task(&task_setup_data);
@@ -6911,7 +6953,7 @@ nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
msg.rpc_argp = &data->args;
msg.rpc_resp = &data->res;
- nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
+ nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0, 0);
rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data);
}
@@ -7107,8 +7149,7 @@ static int _nfs40_proc_get_locations(struct inode *inode,
locations->server = server;
locations->nlocations = 0;
- nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
- nfs4_set_sequence_privileged(&args.seq_args);
+ nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 1);
status = nfs4_call_sync_sequence(clnt, server, &msg,
&args.seq_args, &res.seq_res);
if (status)
@@ -7161,8 +7202,7 @@ static int _nfs41_proc_get_locations(struct inode *inode,
locations->server = server;
locations->nlocations = 0;
- nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
- nfs4_set_sequence_privileged(&args.seq_args);
+ nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 1);
status = nfs4_call_sync_sequence(clnt, server, &msg,
&args.seq_args, &res.seq_res);
if (status == NFS4_OK &&
@@ -7249,8 +7289,7 @@ static int _nfs40_proc_fsid_present(struct inode *inode, struct rpc_cred *cred)
if (res.fh == NULL)
return -ENOMEM;
- nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
- nfs4_set_sequence_privileged(&args.seq_args);
+ nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 1);
status = nfs4_call_sync_sequence(clnt, server, &msg,
&args.seq_args, &res.seq_res);
nfs_free_fhandle(res.fh);
@@ -7291,8 +7330,7 @@ static int _nfs41_proc_fsid_present(struct inode *inode, struct rpc_cred *cred)
if (res.fh == NULL)
return -ENOMEM;
- nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
- nfs4_set_sequence_privileged(&args.seq_args);
+ nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 1);
status = nfs4_call_sync_sequence(clnt, server, &msg,
&args.seq_args, &res.seq_res);
nfs_free_fhandle(res.fh);
@@ -8070,8 +8108,7 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
};
int status;
- nfs4_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0);
- nfs4_set_sequence_privileged(&args.la_seq_args);
+ nfs4_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0, 1);
task = rpc_run_task(&task_setup);
if (IS_ERR(task))
@@ -8408,10 +8445,8 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
if (calldata == NULL)
goto out_put_clp;
- nfs4_init_sequence(&calldata->args, &calldata->res, 0);
+ nfs4_init_sequence(&calldata->args, &calldata->res, 0, is_privileged);
nfs4_sequence_attach_slot(&calldata->args, &calldata->res, slot);
- if (is_privileged)
- nfs4_set_sequence_privileged(&calldata->args);
msg.rpc_argp = &calldata->args;
msg.rpc_resp = &calldata->res;
calldata->clp = clp;
@@ -8563,8 +8598,7 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp,
calldata->clp = clp;
calldata->arg.one_fs = 0;
- nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0);
- nfs4_set_sequence_privileged(&calldata->arg.seq_args);
+ nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0, 1);
msg.rpc_argp = &calldata->arg;
msg.rpc_resp = &calldata->res;
task_setup_data.callback_data = calldata;
@@ -8693,63 +8727,19 @@ out:
return status;
}
-static size_t max_response_pages(struct nfs_server *server)
+size_t max_response_pages(struct nfs_server *server)
{
u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
return nfs_page_array_len(0, max_resp_sz);
}
-static void nfs4_free_pages(struct page **pages, size_t size)
-{
- int i;
-
- if (!pages)
- return;
-
- for (i = 0; i < size; i++) {
- if (!pages[i])
- break;
- __free_page(pages[i]);
- }
- kfree(pages);
-}
-
-static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags)
-{
- struct page **pages;
- int i;
-
- pages = kcalloc(size, sizeof(struct page *), gfp_flags);
- if (!pages) {
- dprintk("%s: can't alloc array of %zu pages\n", __func__, size);
- return NULL;
- }
-
- for (i = 0; i < size; i++) {
- pages[i] = alloc_page(gfp_flags);
- if (!pages[i]) {
- dprintk("%s: failed to allocate page\n", __func__);
- nfs4_free_pages(pages, size);
- return NULL;
- }
- }
-
- return pages;
-}
-
static void nfs4_layoutget_release(void *calldata)
{
struct nfs4_layoutget *lgp = calldata;
- struct inode *inode = lgp->args.inode;
- struct nfs_server *server = NFS_SERVER(inode);
- size_t max_pages = max_response_pages(server);
dprintk("--> %s\n", __func__);
nfs4_sequence_free_slot(&lgp->res.seq_res);
- nfs4_free_pages(lgp->args.layout.pages, max_pages);
- pnfs_put_layout_hdr(NFS_I(inode)->layout);
- put_nfs_open_context(lgp->args.ctx);
- kfree(calldata);
+ pnfs_layoutget_free(lgp);
dprintk("<-- %s\n", __func__);
}
@@ -8760,11 +8750,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = {
};
struct pnfs_layout_segment *
-nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags)
+nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout)
{
struct inode *inode = lgp->args.inode;
struct nfs_server *server = NFS_SERVER(inode);
- size_t max_pages = max_response_pages(server);
struct rpc_task *task;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
@@ -8791,16 +8780,7 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags)
/* nfs4_layoutget_release calls pnfs_put_layout_hdr */
pnfs_get_layout_hdr(NFS_I(inode)->layout);
- lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
- if (!lgp->args.layout.pages) {
- nfs4_layoutget_release(lgp);
- return ERR_PTR(-ENOMEM);
- }
- lgp->args.layout.pglen = max_pages * PAGE_SIZE;
-
- lgp->res.layoutp = &lgp->args.layout;
- lgp->res.seq_res.sr_slot = NULL;
- nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);
+ nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0, 0);
task = rpc_run_task(&task_setup_data);
if (IS_ERR(task))
@@ -8927,7 +8907,7 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync)
}
task_setup_data.flags |= RPC_TASK_ASYNC;
}
- nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1);
+ nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1, 0);
task = rpc_run_task(&task_setup_data);
if (IS_ERR(task))
return PTR_ERR(task);
@@ -9074,7 +9054,7 @@ nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync)
}
task_setup_data.flags = RPC_TASK_ASYNC;
}
- nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
+ nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, 0);
task = rpc_run_task(&task_setup_data);
if (IS_ERR(task))
return PTR_ERR(task);
@@ -9254,8 +9234,7 @@ static int _nfs41_test_stateid(struct nfs_server *server,
&rpc_client, &msg);
dprintk("NFS call test_stateid %p\n", stateid);
- nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
- nfs4_set_sequence_privileged(&args.seq_args);
+ nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 1);
status = nfs4_call_sync_sequence(rpc_client, server, &msg,
&args.seq_args, &res.seq_res);
if (status != NFS_OK) {
@@ -9347,7 +9326,17 @@ static const struct rpc_call_ops nfs41_free_stateid_ops = {
.rpc_release = nfs41_free_stateid_release,
};
-static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server,
+/**
+ * nfs41_free_stateid - perform a FREE_STATEID operation
+ *
+ * @server: server / transport on which to perform the operation
+ * @stateid: state ID to release
+ * @cred: credential
+ * @is_recovery: set to true if this call needs to be privileged
+ *
+ * Note: this function is always asynchronous.
+ */
+static int nfs41_free_stateid(struct nfs_server *server,
const nfs4_stateid *stateid,
struct rpc_cred *cred,
bool privileged)
@@ -9363,6 +9352,7 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server,
.flags = RPC_TASK_ASYNC,
};
struct nfs_free_stateid_data *data;
+ struct rpc_task *task;
nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
&task_setup.rpc_client, &msg);
@@ -9370,7 +9360,7 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server,
dprintk("NFS call free_stateid %p\n", stateid);
data = kmalloc(sizeof(*data), GFP_NOFS);
if (!data)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
data->server = server;
nfs4_stateid_copy(&data->args.stateid, stateid);
@@ -9378,31 +9368,8 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server,
msg.rpc_argp = &data->args;
msg.rpc_resp = &data->res;
- nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
- if (privileged)
- nfs4_set_sequence_privileged(&data->args.seq_args);
-
- return rpc_run_task(&task_setup);
-}
-
-/**
- * nfs41_free_stateid - perform a FREE_STATEID operation
- *
- * @server: server / transport on which to perform the operation
- * @stateid: state ID to release
- * @cred: credential
- * @is_recovery: set to true if this call needs to be privileged
- *
- * Note: this function is always asynchronous.
- */
-static int nfs41_free_stateid(struct nfs_server *server,
- const nfs4_stateid *stateid,
- struct rpc_cred *cred,
- bool is_recovery)
-{
- struct rpc_task *task;
-
- task = _nfs41_free_stateid(server, stateid, cred, is_recovery);
+ nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, privileged);
+ task = rpc_run_task(&task_setup);
if (IS_ERR(task))
return PTR_ERR(task);
rpc_put_task(task);
@@ -9539,7 +9506,8 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
| NFS_CAP_ATOMIC_OPEN
| NFS_CAP_POSIX_LOCK
| NFS_CAP_STATEID_NFSV41
- | NFS_CAP_ATOMIC_OPEN_V1,
+ | NFS_CAP_ATOMIC_OPEN_V1
+ | NFS_CAP_LGOPEN,
.init_client = nfs41_init_client,
.shutdown_client = nfs41_shutdown_client,
.match_stateid = nfs41_match_stateid,
@@ -9564,6 +9532,7 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
| NFS_CAP_POSIX_LOCK
| NFS_CAP_STATEID_NFSV41
| NFS_CAP_ATOMIC_OPEN_V1
+ | NFS_CAP_LGOPEN
| NFS_CAP_ALLOCATE
| NFS_CAP_COPY
| NFS_CAP_DEALLOCATE
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index c10a422efe6f..2bf2eaa08ca7 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -77,6 +77,14 @@ const nfs4_stateid invalid_stateid = {
.type = NFS4_INVALID_STATEID_TYPE,
};
+const nfs4_stateid current_stateid = {
+ {
+ /* Funky initialiser keeps older gcc versions happy */
+ .data = { 0x0, 0x0, 0x0, 0x1, 0 },
+ },
+ .type = NFS4_SPECIAL_STATEID_TYPE,
+};
+
static DEFINE_MUTEX(nfs_clid_init_mutex);
int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 9b7392032321..cd41d2577a04 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -65,7 +65,13 @@
/* Mapping from NFS error code to "errno" error code. */
#define errno_NFSERR_IO EIO
+struct compound_hdr;
static int nfs4_stat_to_errno(int);
+static void encode_layoutget(struct xdr_stream *xdr,
+ const struct nfs4_layoutget_args *args,
+ struct compound_hdr *hdr);
+static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
+ struct nfs4_layoutget_res *res);
/* NFSv4 COMPOUND tags are only wanted for debugging purposes */
#ifdef DEBUG
@@ -424,6 +430,8 @@ static int nfs4_stat_to_errno(int);
#define decode_sequence_maxsz 0
#define encode_layoutreturn_maxsz 0
#define decode_layoutreturn_maxsz 0
+#define encode_layoutget_maxsz 0
+#define decode_layoutget_maxsz 0
#endif /* CONFIG_NFS_V4_1 */
#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
@@ -476,14 +484,16 @@ static int nfs4_stat_to_errno(int);
encode_open_maxsz + \
encode_access_maxsz + \
encode_getfh_maxsz + \
- encode_getattr_maxsz)
+ encode_getattr_maxsz + \
+ encode_layoutget_maxsz)
#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_open_maxsz + \
decode_access_maxsz + \
decode_getfh_maxsz + \
- decode_getattr_maxsz)
+ decode_getattr_maxsz + \
+ decode_layoutget_maxsz)
#define NFS4_enc_open_confirm_sz \
(compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
@@ -497,13 +507,15 @@ static int nfs4_stat_to_errno(int);
encode_putfh_maxsz + \
encode_open_maxsz + \
encode_access_maxsz + \
- encode_getattr_maxsz)
+ encode_getattr_maxsz + \
+ encode_layoutget_maxsz)
#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_open_maxsz + \
decode_access_maxsz + \
- decode_getattr_maxsz)
+ decode_getattr_maxsz + \
+ decode_layoutget_maxsz)
#define NFS4_enc_open_downgrade_sz \
(compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
@@ -1057,6 +1069,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
const struct nfs_server *server,
const uint32_t attrmask[])
{
+ struct timespec ts;
char owner_name[IDMAP_NAMESZ];
char owner_group[IDMAP_NAMESZ];
int owner_namelen = 0;
@@ -1145,14 +1158,16 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
if (iap->ia_valid & ATTR_ATIME_SET) {
*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
- p = xdr_encode_nfstime4(p, &iap->ia_atime);
+ ts = timespec64_to_timespec(iap->ia_atime);
+ p = xdr_encode_nfstime4(p, &ts);
} else
*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
}
if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
if (iap->ia_valid & ATTR_MTIME_SET) {
*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
- p = xdr_encode_nfstime4(p, &iap->ia_mtime);
+ ts = timespec64_to_timespec(iap->ia_mtime);
+ p = xdr_encode_nfstime4(p, &ts);
} else
*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
}
@@ -2070,6 +2085,13 @@ encode_layoutreturn(struct xdr_stream *xdr,
struct compound_hdr *hdr)
{
}
+
+static void
+encode_layoutget(struct xdr_stream *xdr,
+ const struct nfs4_layoutget_args *args,
+ struct compound_hdr *hdr)
+{
+}
#endif /* CONFIG_NFS_V4_1 */
/*
@@ -2316,6 +2338,12 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr,
if (args->access)
encode_access(xdr, args->access, &hdr);
encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
+ if (args->lg_args) {
+ encode_layoutget(xdr, args->lg_args, &hdr);
+ xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
+ args->lg_args->layout.pages,
+ 0, args->lg_args->layout.pglen);
+ }
encode_nops(&hdr);
}
@@ -2356,6 +2384,12 @@ static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req,
if (args->access)
encode_access(xdr, args->access, &hdr);
encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
+ if (args->lg_args) {
+ encode_layoutget(xdr, args->lg_args, &hdr);
+ xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
+ args->lg_args->layout.pages,
+ 0, args->lg_args->layout.pglen);
+ }
encode_nops(&hdr);
}
@@ -6024,7 +6058,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
status = decode_op_hdr(xdr, OP_LAYOUTGET);
if (status)
- return status;
+ goto out;
p = xdr_inline_decode(xdr, 4);
if (unlikely(!p))
goto out_overflow;
@@ -6037,7 +6071,8 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
if (!layout_count) {
dprintk("%s: server responded with empty layout array\n",
__func__);
- return -EINVAL;
+ status = -EINVAL;
+ goto out;
}
p = xdr_inline_decode(xdr, 28);
@@ -6062,7 +6097,8 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
dprintk("NFS: server cheating in layoutget reply: "
"layout len %u > recvd %u\n",
res->layoutp->len, recvd);
- return -EINVAL;
+ status = -EINVAL;
+ goto out;
}
if (layout_count > 1) {
@@ -6075,10 +6111,13 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
__func__, layout_count);
}
- return 0;
+out:
+ res->status = status;
+ return status;
out_overflow:
print_overflow_msg(__func__, xdr);
- return -EIO;
+ status = -EIO;
+ goto out;
}
static int decode_layoutreturn(struct xdr_stream *xdr,
@@ -6177,6 +6216,13 @@ int decode_layoutreturn(struct xdr_stream *xdr,
{
return 0;
}
+
+static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
+ struct nfs4_layoutget_res *res)
+{
+ return 0;
+}
+
#endif /* CONFIG_NFS_V4_1 */
/*
@@ -6623,6 +6669,8 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
if (res->access_request)
decode_access(xdr, &res->access_supported, &res->access_result);
decode_getfattr_label(xdr, res->f_attr, res->f_label, res->server);
+ if (res->lg_res)
+ decode_layoutget(xdr, rqstp, res->lg_res);
out:
return status;
}
@@ -6675,6 +6723,8 @@ static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp,
if (res->access_request)
decode_access(xdr, &res->access_supported, &res->access_result);
decode_getfattr(xdr, res->f_attr, res->server);
+ if (res->lg_res)
+ decode_layoutget(xdr, rqstp, res->lg_res);
out:
return status;
}
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index ee723aa153a3..bcc3addec3c5 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -37,6 +37,7 @@
#include "nfs4trace.h"
#include "delegation.h"
#include "nfs42.h"
+#include "nfs4_fs.h"
#define NFSDBG_FACILITY NFSDBG_PNFS
#define PNFS_LAYOUTGET_RETRY_TIMEOUT (120*HZ)
@@ -915,45 +916,99 @@ pnfs_layoutgets_blocked(const struct pnfs_layout_hdr *lo)
test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
}
-/*
- * Get layout from server.
- * for now, assume that whole file layouts are requested.
- * arg->offset: 0
- * arg->length: all ones
- */
-static struct pnfs_layout_segment *
-send_layoutget(struct pnfs_layout_hdr *lo,
+static struct nfs_server *
+pnfs_find_server(struct inode *inode, struct nfs_open_context *ctx)
+{
+ struct nfs_server *server;
+
+ if (inode) {
+ server = NFS_SERVER(inode);
+ } else {
+ struct dentry *parent_dir = dget_parent(ctx->dentry);
+ server = NFS_SERVER(parent_dir->d_inode);
+ dput(parent_dir);
+ }
+ return server;
+}
+
+static void nfs4_free_pages(struct page **pages, size_t size)
+{
+ int i;
+
+ if (!pages)
+ return;
+
+ for (i = 0; i < size; i++) {
+ if (!pages[i])
+ break;
+ __free_page(pages[i]);
+ }
+ kfree(pages);
+}
+
+static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags)
+{
+ struct page **pages;
+ int i;
+
+ pages = kcalloc(size, sizeof(struct page *), gfp_flags);
+ if (!pages) {
+ dprintk("%s: can't alloc array of %zu pages\n", __func__, size);
+ return NULL;
+ }
+
+ for (i = 0; i < size; i++) {
+ pages[i] = alloc_page(gfp_flags);
+ if (!pages[i]) {
+ dprintk("%s: failed to allocate page\n", __func__);
+ nfs4_free_pages(pages, size);
+ return NULL;
+ }
+ }
+
+ return pages;
+}
+
+static struct nfs4_layoutget *
+pnfs_alloc_init_layoutget_args(struct inode *ino,
struct nfs_open_context *ctx,
- nfs4_stateid *stateid,
+ const nfs4_stateid *stateid,
const struct pnfs_layout_range *range,
- long *timeout, gfp_t gfp_flags)
+ gfp_t gfp_flags)
{
- struct inode *ino = lo->plh_inode;
- struct nfs_server *server = NFS_SERVER(ino);
+ struct nfs_server *server = pnfs_find_server(ino, ctx);
+ size_t max_pages = max_response_pages(server);
struct nfs4_layoutget *lgp;
- loff_t i_size;
dprintk("--> %s\n", __func__);
- /*
- * Synchronously retrieve layout information from server and
- * store in lseg. If we race with a concurrent seqid morphing
- * op, then re-send the LAYOUTGET.
- */
lgp = kzalloc(sizeof(*lgp), gfp_flags);
if (lgp == NULL)
- return ERR_PTR(-ENOMEM);
+ return NULL;
+
+ lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
+ if (!lgp->args.layout.pages) {
+ kfree(lgp);
+ return NULL;
+ }
+ lgp->args.layout.pglen = max_pages * PAGE_SIZE;
+ lgp->res.layoutp = &lgp->args.layout;
- i_size = i_size_read(ino);
+ /* Don't confuse uninitialised result and success */
+ lgp->res.status = -NFS4ERR_DELAY;
lgp->args.minlength = PAGE_SIZE;
if (lgp->args.minlength > range->length)
lgp->args.minlength = range->length;
- if (range->iomode == IOMODE_READ) {
- if (range->offset >= i_size)
- lgp->args.minlength = 0;
- else if (i_size - range->offset < lgp->args.minlength)
- lgp->args.minlength = i_size - range->offset;
+ if (ino) {
+ loff_t i_size = i_size_read(ino);
+
+ if (range->iomode == IOMODE_READ) {
+ if (range->offset >= i_size)
+ lgp->args.minlength = 0;
+ else if (i_size - range->offset < lgp->args.minlength)
+ lgp->args.minlength = i_size - range->offset;
+ }
}
lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE;
pnfs_copy_range(&lgp->args.range, range);
@@ -962,9 +1017,21 @@ send_layoutget(struct pnfs_layout_hdr *lo,
lgp->args.ctx = get_nfs_open_context(ctx);
nfs4_stateid_copy(&lgp->args.stateid, stateid);
lgp->gfp_flags = gfp_flags;
- lgp->cred = lo->plh_lc_cred;
+ lgp->cred = get_rpccred(ctx->cred);
+ lgp->callback_count = raw_seqcount_begin(&server->nfs_client->cl_callback_count);
+ return lgp;
+}
- return nfs4_proc_layoutget(lgp, timeout, gfp_flags);
+void pnfs_layoutget_free(struct nfs4_layoutget *lgp)
+{
+ size_t max_pages = lgp->args.layout.pglen / PAGE_SIZE;
+
+ nfs4_free_pages(lgp->args.layout.pages, max_pages);
+ if (lgp->args.inode)
+ pnfs_put_layout_hdr(NFS_I(lgp->args.inode)->layout);
+ put_rpccred(lgp->cred);
+ put_nfs_open_context(lgp->args.ctx);
+ kfree(lgp);
}
static void pnfs_clear_layoutcommit(struct inode *inode,
@@ -1144,7 +1211,7 @@ _pnfs_return_layout(struct inode *ino)
LIST_HEAD(tmp_list);
nfs4_stateid stateid;
int status = 0;
- bool send;
+ bool send, valid_layout;
dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino);
@@ -1165,6 +1232,7 @@ _pnfs_return_layout(struct inode *ino)
goto out_put_layout_hdr;
spin_lock(&ino->i_lock);
}
+ valid_layout = pnfs_layout_is_valid(lo);
pnfs_clear_layoutcommit(ino, &tmp_list);
pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL, 0);
@@ -1178,7 +1246,8 @@ _pnfs_return_layout(struct inode *ino)
}
/* Don't send a LAYOUTRETURN if list was initially empty */
- if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags)) {
+ if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags) ||
+ !valid_layout) {
spin_unlock(&ino->i_lock);
dprintk("NFS: %s no layout segments to return\n", __func__);
goto out_put_layout_hdr;
@@ -1671,6 +1740,22 @@ static void pnfs_clear_first_layoutget(struct pnfs_layout_hdr *lo)
wake_up_bit(bitlock, NFS_LAYOUT_FIRST_LAYOUTGET);
}
+static void _add_to_server_list(struct pnfs_layout_hdr *lo,
+ struct nfs_server *server)
+{
+ if (list_empty(&lo->plh_layouts)) {
+ struct nfs_client *clp = server->nfs_client;
+
+ /* The lo must be on the clp list if there is any
+ * chance of a CB_LAYOUTRECALL(FILE) coming in.
+ */
+ spin_lock(&clp->cl_lock);
+ if (list_empty(&lo->plh_layouts))
+ list_add_tail(&lo->plh_layouts, &server->layouts);
+ spin_unlock(&clp->cl_lock);
+ }
+}
+
/*
* Layout segment is retreived from the server if not cached.
* The appropriate layout segment is referenced and returned to the caller.
@@ -1694,6 +1779,7 @@ pnfs_update_layout(struct inode *ino,
struct nfs_client *clp = server->nfs_client;
struct pnfs_layout_hdr *lo = NULL;
struct pnfs_layout_segment *lseg = NULL;
+ struct nfs4_layoutget *lgp;
nfs4_stateid stateid;
long timeout = 0;
unsigned long giveup = jiffies + (clp->cl_lease_time << 1);
@@ -1820,15 +1906,7 @@ lookup_again:
atomic_inc(&lo->plh_outstanding);
spin_unlock(&ino->i_lock);
- if (list_empty(&lo->plh_layouts)) {
- /* The lo must be on the clp list if there is any
- * chance of a CB_LAYOUTRECALL(FILE) coming in.
- */
- spin_lock(&clp->cl_lock);
- if (list_empty(&lo->plh_layouts))
- list_add_tail(&lo->plh_layouts, &server->layouts);
- spin_unlock(&clp->cl_lock);
- }
+ _add_to_server_list(lo, server);
pg_offset = arg.offset & ~PAGE_MASK;
if (pg_offset) {
@@ -1838,7 +1916,15 @@ lookup_again:
if (arg.length != NFS4_MAX_UINT64)
arg.length = PAGE_ALIGN(arg.length);
- lseg = send_layoutget(lo, ctx, &stateid, &arg, &timeout, gfp_flags);
+ lgp = pnfs_alloc_init_layoutget_args(ino, ctx, &stateid, &arg, gfp_flags);
+ if (!lgp) {
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo, NULL,
+ PNFS_UPDATE_LAYOUT_NOMEM);
+ atomic_dec(&lo->plh_outstanding);
+ goto out_put_layout_hdr;
+ }
+
+ lseg = nfs4_proc_layoutget(lgp, &timeout);
trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET);
atomic_dec(&lo->plh_outstanding);
@@ -1919,6 +2005,171 @@ pnfs_sanity_check_layout_range(struct pnfs_layout_range *range)
return true;
}
+static struct pnfs_layout_hdr *
+_pnfs_grab_empty_layout(struct inode *ino, struct nfs_open_context *ctx)
+{
+ struct pnfs_layout_hdr *lo;
+
+ spin_lock(&ino->i_lock);
+ lo = pnfs_find_alloc_layout(ino, ctx, GFP_KERNEL);
+ if (!lo)
+ goto out_unlock;
+ if (!test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags))
+ goto out_unlock;
+ if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
+ goto out_unlock;
+ if (pnfs_layoutgets_blocked(lo))
+ goto out_unlock;
+ if (test_and_set_bit(NFS_LAYOUT_FIRST_LAYOUTGET, &lo->plh_flags))
+ goto out_unlock;
+ atomic_inc(&lo->plh_outstanding);
+ spin_unlock(&ino->i_lock);
+ _add_to_server_list(lo, NFS_SERVER(ino));
+ return lo;
+
+out_unlock:
+ spin_unlock(&ino->i_lock);
+ pnfs_put_layout_hdr(lo);
+ return NULL;
+}
+
+extern const nfs4_stateid current_stateid;
+
+static void _lgopen_prepare_attached(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx)
+{
+ struct inode *ino = data->dentry->d_inode;
+ struct pnfs_layout_range rng = {
+ .iomode = (data->o_arg.fmode & FMODE_WRITE) ?
+ IOMODE_RW: IOMODE_READ,
+ .offset = 0,
+ .length = NFS4_MAX_UINT64,
+ };
+ struct nfs4_layoutget *lgp;
+ struct pnfs_layout_hdr *lo;
+
+ /* Heuristic: don't send layoutget if we have cached data */
+ if (rng.iomode == IOMODE_READ &&
+ (i_size_read(ino) == 0 || ino->i_mapping->nrpages != 0))
+ return;
+
+ lo = _pnfs_grab_empty_layout(ino, ctx);
+ if (!lo)
+ return;
+ lgp = pnfs_alloc_init_layoutget_args(ino, ctx, &current_stateid,
+ &rng, GFP_KERNEL);
+ if (!lgp) {
+ pnfs_clear_first_layoutget(lo);
+ pnfs_put_layout_hdr(lo);
+ return;
+ }
+ data->lgp = lgp;
+ data->o_arg.lg_args = &lgp->args;
+ data->o_res.lg_res = &lgp->res;
+}
+
+static void _lgopen_prepare_floating(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx)
+{
+ struct pnfs_layout_range rng = {
+ .iomode = (data->o_arg.fmode & FMODE_WRITE) ?
+ IOMODE_RW: IOMODE_READ,
+ .offset = 0,
+ .length = NFS4_MAX_UINT64,
+ };
+ struct nfs4_layoutget *lgp;
+
+ lgp = pnfs_alloc_init_layoutget_args(NULL, ctx, &current_stateid,
+ &rng, GFP_KERNEL);
+ if (!lgp)
+ return;
+ data->lgp = lgp;
+ data->o_arg.lg_args = &lgp->args;
+ data->o_res.lg_res = &lgp->res;
+}
+
+void pnfs_lgopen_prepare(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx)
+{
+ struct nfs_server *server = NFS_SERVER(data->dir->d_inode);
+
+ if (!(pnfs_enabled_sb(server) &&
+ server->pnfs_curr_ld->flags & PNFS_LAYOUTGET_ON_OPEN))
+ return;
+ /* Could check on max_ops, but currently hardcoded high enough */
+ if (!nfs_server_capable(data->dir->d_inode, NFS_CAP_LGOPEN))
+ return;
+ if (data->state)
+ _lgopen_prepare_attached(data, ctx);
+ else
+ _lgopen_prepare_floating(data, ctx);
+}
+
+void pnfs_parse_lgopen(struct inode *ino, struct nfs4_layoutget *lgp,
+ struct nfs_open_context *ctx)
+{
+ struct pnfs_layout_hdr *lo;
+ struct pnfs_layout_segment *lseg;
+ struct nfs_server *srv = NFS_SERVER(ino);
+ u32 iomode;
+
+ if (!lgp)
+ return;
+ dprintk("%s: entered with status %i\n", __func__, lgp->res.status);
+ if (lgp->res.status) {
+ switch (lgp->res.status) {
+ default:
+ break;
+ /*
+ * Halt lgopen attempts if the server doesn't recognise
+ * the "current stateid" value, the layout type, or the
+ * layoutget operation as being valid.
+ * Also if it complains about too many ops in the compound
+ * or of the request/reply being too big.
+ */
+ case -NFS4ERR_BAD_STATEID:
+ case -NFS4ERR_NOTSUPP:
+ case -NFS4ERR_REP_TOO_BIG:
+ case -NFS4ERR_REP_TOO_BIG_TO_CACHE:
+ case -NFS4ERR_REQ_TOO_BIG:
+ case -NFS4ERR_TOO_MANY_OPS:
+ case -NFS4ERR_UNKNOWN_LAYOUTTYPE:
+ srv->caps &= ~NFS_CAP_LGOPEN;
+ }
+ return;
+ }
+ if (!lgp->args.inode) {
+ lo = _pnfs_grab_empty_layout(ino, ctx);
+ if (!lo)
+ return;
+ lgp->args.inode = ino;
+ } else
+ lo = NFS_I(lgp->args.inode)->layout;
+
+ if (read_seqcount_retry(&srv->nfs_client->cl_callback_count,
+ lgp->callback_count))
+ return;
+ lseg = pnfs_layout_process(lgp);
+ if (!IS_ERR(lseg)) {
+ iomode = lgp->args.range.iomode;
+ pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode));
+ pnfs_put_lseg(lseg);
+ }
+}
+
+void nfs4_lgopen_release(struct nfs4_layoutget *lgp)
+{
+ if (lgp != NULL) {
+ struct inode *inode = lgp->args.inode;
+ if (inode) {
+ struct pnfs_layout_hdr *lo = NFS_I(inode)->layout;
+ atomic_dec(&lo->plh_outstanding);
+ pnfs_clear_first_layoutget(lo);
+ }
+ pnfs_layoutget_free(lgp);
+ }
+}
+
struct pnfs_layout_segment *
pnfs_layout_process(struct nfs4_layoutget *lgp)
{
@@ -1984,8 +2235,6 @@ out_forget:
spin_unlock(&ino->i_lock);
lseg->pls_layout = lo;
NFS_SERVER(ino)->pnfs_curr_ld->free_lseg(lseg);
- if (!pnfs_layout_is_valid(lo))
- nfs_commit_inode(ino, 0);
return ERR_PTR(-EAGAIN);
}
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index daf6cbf5c15f..a8f5e6b16749 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -35,6 +35,8 @@
#include <linux/nfs_page.h>
#include <linux/workqueue.h>
+struct nfs4_opendata;
+
enum {
NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */
NFS_LSEG_ROC, /* roc bit received from server */
@@ -110,6 +112,7 @@ enum layoutdriver_policy_flags {
PNFS_LAYOUTRET_ON_SETATTR = 1 << 0,
PNFS_LAYOUTRET_ON_ERROR = 1 << 1,
PNFS_READ_WHOLE_PAGE = 1 << 2,
+ PNFS_LAYOUTGET_ON_OPEN = 1 << 3,
};
struct nfs4_deviceid_node;
@@ -223,10 +226,11 @@ extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
/* nfs4proc.c */
+extern size_t max_response_pages(struct nfs_server *server);
extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,
struct pnfs_device *dev,
struct rpc_cred *cred);
-extern struct pnfs_layout_segment* nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags);
+extern struct pnfs_layout_segment* nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout);
extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync);
/* pnfs.c */
@@ -246,6 +250,7 @@ size_t pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio,
struct nfs_page *prev, struct nfs_page *req);
void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg);
struct pnfs_layout_segment *pnfs_layout_process(struct nfs4_layoutget *lgp);
+void pnfs_layoutget_free(struct nfs4_layoutget *lgp);
void pnfs_free_lseg_list(struct list_head *tmp_list);
void pnfs_destroy_layout(struct nfs_inode *);
void pnfs_destroy_all_layouts(struct nfs_client *);
@@ -375,6 +380,11 @@ void pnfs_layout_mark_request_commit(struct nfs_page *req,
struct pnfs_layout_segment *lseg,
struct nfs_commit_info *cinfo,
u32 ds_commit_idx);
+void pnfs_lgopen_prepare(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx);
+void pnfs_parse_lgopen(struct inode *ino, struct nfs4_layoutget *lgp,
+ struct nfs_open_context *ctx);
+void nfs4_lgopen_release(struct nfs4_layoutget *lgp);
static inline bool nfs_have_layout(struct inode *inode)
{
@@ -775,6 +785,22 @@ static inline bool nfs4_refresh_layout_stateid(nfs4_stateid *dst,
{
return false;
}
+
+static inline void pnfs_lgopen_prepare(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx)
+{
+}
+
+static inline void pnfs_parse_lgopen(struct inode *ino,
+ struct nfs4_layoutget *lgp,
+ struct nfs_open_context *ctx)
+{
+}
+
+static inline void nfs4_lgopen_release(struct nfs4_layoutget *lgp)
+{
+}
+
#endif /* CONFIG_NFS_V4_1 */
#if IS_ENABLED(CONFIG_NFS_V4_2)
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 4e93d6308733..e0c257bd62b9 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -99,7 +99,8 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
*/
static int
nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr, struct nfs4_label *label)
+ struct nfs_fattr *fattr, struct nfs4_label *label,
+ struct inode *inode)
{
struct rpc_message msg = {
.rpc_proc = &nfs_procedures[NFSPROC_GETATTR],
@@ -321,7 +322,9 @@ nfs_proc_remove(struct inode *dir, struct dentry *dentry)
}
static void
-nfs_proc_unlink_setup(struct rpc_message *msg, struct dentry *dentry)
+nfs_proc_unlink_setup(struct rpc_message *msg,
+ struct dentry *dentry,
+ struct inode *inode)
{
msg->rpc_proc = &nfs_procedures[NFSPROC_REMOVE];
}
@@ -618,7 +621,8 @@ static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
}
static void nfs_proc_write_setup(struct nfs_pgio_header *hdr,
- struct rpc_message *msg)
+ struct rpc_message *msg,
+ struct rpc_clnt **clnt)
{
/* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */
hdr->args.stable = NFS_FILE_SYNC;
@@ -631,7 +635,8 @@ static void nfs_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit
}
static void
-nfs_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
+nfs_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg,
+ struct rpc_clnt **clnt)
{
BUG();
}
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index bf54fc9ae135..fd61bf0fce63 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -85,7 +85,7 @@ static const struct rpc_call_ops nfs_unlink_ops = {
.rpc_call_prepare = nfs_unlink_prepare,
};
-static void nfs_do_call_unlink(struct nfs_unlinkdata *data)
+static void nfs_do_call_unlink(struct inode *inode, struct nfs_unlinkdata *data)
{
struct rpc_message msg = {
.rpc_argp = &data->args,
@@ -105,7 +105,7 @@ static void nfs_do_call_unlink(struct nfs_unlinkdata *data)
data->args.fh = NFS_FH(dir);
nfs_fattr_init(data->res.dir_attr);
- NFS_PROTO(dir)->unlink_setup(&msg, data->dentry);
+ NFS_PROTO(dir)->unlink_setup(&msg, data->dentry, inode);
task_setup_data.rpc_client = NFS_CLIENT(dir);
task = rpc_run_task(&task_setup_data);
@@ -113,7 +113,7 @@ static void nfs_do_call_unlink(struct nfs_unlinkdata *data)
rpc_put_task_async(task);
}
-static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
+static int nfs_call_unlink(struct dentry *dentry, struct inode *inode, struct nfs_unlinkdata *data)
{
struct inode *dir = d_inode(dentry->d_parent);
struct dentry *alias;
@@ -153,7 +153,7 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
return ret;
}
data->dentry = alias;
- nfs_do_call_unlink(data);
+ nfs_do_call_unlink(inode, data);
return 1;
}
@@ -231,7 +231,7 @@ nfs_complete_unlink(struct dentry *dentry, struct inode *inode)
dentry->d_fsdata = NULL;
spin_unlock(&dentry->d_lock);
- if (NFS_STALE(inode) || !nfs_call_unlink(dentry, data))
+ if (NFS_STALE(inode) || !nfs_call_unlink(dentry, inode, data))
nfs_free_unlinkdata(data);
}
@@ -448,6 +448,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
unsigned char silly[SILLYNAME_LEN + 1];
unsigned long long fileid;
struct dentry *sdentry;
+ struct inode *inode = d_inode(dentry);
struct rpc_task *task;
int error = -EBUSY;
@@ -485,6 +486,8 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
goto out;
} while (d_inode(sdentry) != NULL); /* need negative lookup */
+ ihold(inode);
+
/* queue unlink first. Can't do this from rpc_release as it
* has to allocate memory
*/
@@ -509,6 +512,12 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
case 0:
/* The rename succeeded */
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+ spin_lock(&inode->i_lock);
+ NFS_I(inode)->attr_gencount = nfs_inc_attr_generation_counter();
+ NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_CTIME
+ | NFS_INO_REVAL_FORCED;
+ spin_unlock(&inode->i_lock);
d_move(dentry, sdentry);
break;
case -ERESTARTSYS:
@@ -519,6 +528,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
}
rpc_put_task(task);
out_dput:
+ iput(inode);
dput(sdentry);
out:
return error;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 0193053bc139..a057b4f45a46 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1375,12 +1375,9 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr,
int priority = flush_task_priority(how);
task_setup_data->priority = priority;
- rpc_ops->write_setup(hdr, msg);
+ rpc_ops->write_setup(hdr, msg, &task_setup_data->rpc_client);
trace_nfs_initiate_write(hdr->inode, hdr->io_start, hdr->good_bytes,
hdr->args.stable);
-
- nfs4_state_protect_write(NFS_SERVER(hdr->inode)->nfs_client,
- &task_setup_data->rpc_client, msg, hdr);
}
/* If a nfs_flush_* function fails, it should remove reqs from @head and
@@ -1669,14 +1666,11 @@ int nfs_initiate_commit(struct rpc_clnt *clnt, struct nfs_commit_data *data,
.priority = priority,
};
/* Set up the initial task struct. */
- nfs_ops->commit_setup(data, &msg);
+ nfs_ops->commit_setup(data, &msg, &task_setup_data.rpc_client);
trace_nfs_initiate_commit(data);
dprintk("NFS: initiated commit call\n");
- nfs4_state_protect(NFS_SERVER(data->inode)->nfs_client,
- NFS_SP4_MACH_CRED_COMMIT, &task_setup_data.rpc_client, &msg);
-
task = rpc_run_task(&task_setup_data);
if (IS_ERR(task))
return PTR_ERR(task);
diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c
index a43dfedd69ec..4fb1f72a25fb 100644
--- a/fs/nfsd/blocklayout.c
+++ b/fs/nfsd/blocklayout.c
@@ -121,13 +121,15 @@ nfsd4_block_commit_blocks(struct inode *inode, struct nfsd4_layoutcommit *lcp,
{
loff_t new_size = lcp->lc_last_wr + 1;
struct iattr iattr = { .ia_valid = 0 };
+ struct timespec ts;
int error;
+ ts = timespec64_to_timespec(inode->i_mtime);
if (lcp->lc_mtime.tv_nsec == UTIME_NOW ||
- timespec_compare(&lcp->lc_mtime, &inode->i_mtime) < 0)
- lcp->lc_mtime = current_time(inode);
+ timespec_compare(&lcp->lc_mtime, &ts) < 0)
+ lcp->lc_mtime = timespec64_to_timespec(current_time(inode));
iattr.ia_valid |= ATTR_ATIME | ATTR_CTIME | ATTR_MTIME;
- iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = lcp->lc_mtime;
+ iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = timespec_to_timespec64(lcp->lc_mtime);
if (new_size > i_size_read(inode)) {
iattr.ia_valid |= ATTR_SIZE;
@@ -216,13 +218,21 @@ static int nfsd4_scsi_identify_device(struct block_device *bdev,
struct request_queue *q = bdev->bd_disk->queue;
struct request *rq;
struct scsi_request *req;
- size_t bufflen = 252, len, id_len;
+ /*
+ * The allocation length (passed in bytes 3 and 4 of the INQUIRY
+ * command descriptor block) specifies the number of bytes that have
+ * been allocated for the data-in buffer.
+ * 252 is the highest one-byte value that is a multiple of 4.
+ * 65532 is the highest two-byte value that is a multiple of 4.
+ */
+ size_t bufflen = 252, maxlen = 65532, len, id_len;
u8 *buf, *d, type, assoc;
- int error;
+ int retries = 1, error;
if (WARN_ON_ONCE(!blk_queue_scsi_passthrough(q)))
return -EINVAL;
+again:
buf = kzalloc(bufflen, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -255,6 +265,12 @@ static int nfsd4_scsi_identify_device(struct block_device *bdev,
len = (buf[2] << 8) + buf[3] + 4;
if (len > bufflen) {
+ if (len <= maxlen && retries--) {
+ blk_put_request(rq);
+ kfree(buf);
+ bufflen = len;
+ goto again;
+ }
pr_err("pNFS: INQUIRY 0x83 response invalid (len = %zd)\n",
len);
goto out_put_request;
diff --git a/fs/nfsd/cache.h b/fs/nfsd/cache.h
index 046b3f048757..b7559c6f2b97 100644
--- a/fs/nfsd/cache.h
+++ b/fs/nfsd/cache.h
@@ -67,11 +67,6 @@ enum {
RC_REPLBUFF,
};
-/*
- * If requests are retransmitted within this interval, they're dropped.
- */
-#define RC_DELAY (HZ/5)
-
/* Cache entries expire after this time period */
#define RC_EXPIRE (120 * HZ)
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 8ceb25a10ea0..a1143f7c2201 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -404,8 +404,9 @@ fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc)
if (fsloc->locations_count == 0)
return 0;
- fsloc->locations = kzalloc(fsloc->locations_count
- * sizeof(struct nfsd4_fs_location), GFP_KERNEL);
+ fsloc->locations = kcalloc(fsloc->locations_count,
+ sizeof(struct nfsd4_fs_location),
+ GFP_KERNEL);
if (!fsloc->locations)
return -ENOMEM;
for (i=0; i < fsloc->locations_count; i++) {
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 3192b544a441..9b973f4f7d01 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -165,6 +165,7 @@ static __be32 *
encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
struct kstat *stat)
{
+ struct timespec ts;
*p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
*p++ = htonl((u32) (stat->mode & S_IALLUGO));
*p++ = htonl((u32) stat->nlink);
@@ -180,9 +181,12 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
*p++ = htonl((u32) MINOR(stat->rdev));
p = encode_fsid(p, fhp);
p = xdr_encode_hyper(p, stat->ino);
- p = encode_time3(p, &stat->atime);
- p = encode_time3(p, &stat->mtime);
- p = encode_time3(p, &stat->ctime);
+ ts = timespec64_to_timespec(stat->atime);
+ p = encode_time3(p, &ts);
+ ts = timespec64_to_timespec(stat->mtime);
+ p = encode_time3(p, &ts);
+ ts = timespec64_to_timespec(stat->ctime);
+ p = encode_time3(p, &ts);
return p;
}
@@ -271,8 +275,8 @@ void fill_pre_wcc(struct svc_fh *fhp)
stat.size = inode->i_size;
}
- fhp->fh_pre_mtime = stat.mtime;
- fhp->fh_pre_ctime = stat.ctime;
+ fhp->fh_pre_mtime = timespec64_to_timespec(stat.mtime);
+ fhp->fh_pre_ctime = timespec64_to_timespec(stat.ctime);
fhp->fh_pre_size = stat.size;
fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode);
fhp->fh_pre_saved = true;
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 66eaeb1e8c2c..9c247fa1e959 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -510,8 +510,9 @@ nfs4_legacy_state_init(struct net *net)
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
int i;
- nn->reclaim_str_hashtbl = kmalloc(sizeof(struct list_head) *
- CLIENT_HASH_SIZE, GFP_KERNEL);
+ nn->reclaim_str_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
+ sizeof(struct list_head),
+ GFP_KERNEL);
if (!nn->reclaim_str_hashtbl)
return -ENOMEM;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index fc74d6f46bd5..857141446d6b 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1807,8 +1807,9 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
clp->cl_name.data = kmemdup(name.data, name.len, GFP_KERNEL);
if (clp->cl_name.data == NULL)
goto err_no_name;
- clp->cl_ownerstr_hashtbl = kmalloc(sizeof(struct list_head) *
- OWNER_HASH_SIZE, GFP_KERNEL);
+ clp->cl_ownerstr_hashtbl = kmalloc_array(OWNER_HASH_SIZE,
+ sizeof(struct list_head),
+ GFP_KERNEL);
if (!clp->cl_ownerstr_hashtbl)
goto err_no_hashtbl;
for (i = 0; i < OWNER_HASH_SIZE; i++)
@@ -4378,8 +4379,11 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
spin_unlock(&state_lock);
if (status)
- destroy_unhashed_deleg(dp);
+ goto out_unlock;
+
return dp;
+out_unlock:
+ vfs_setlease(fp->fi_deleg_file, F_UNLCK, NULL, (void **)&dp);
out_clnt_odstate:
put_clnt_odstate(dp->dl_clnt_odstate);
out_stid:
@@ -7093,16 +7097,19 @@ static int nfs4_state_create_net(struct net *net)
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
int i;
- nn->conf_id_hashtbl = kmalloc(sizeof(struct list_head) *
- CLIENT_HASH_SIZE, GFP_KERNEL);
+ nn->conf_id_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
+ sizeof(struct list_head),
+ GFP_KERNEL);
if (!nn->conf_id_hashtbl)
goto err;
- nn->unconf_id_hashtbl = kmalloc(sizeof(struct list_head) *
- CLIENT_HASH_SIZE, GFP_KERNEL);
+ nn->unconf_id_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
+ sizeof(struct list_head),
+ GFP_KERNEL);
if (!nn->unconf_id_hashtbl)
goto err_unconf_id;
- nn->sessionid_hashtbl = kmalloc(sizeof(struct list_head) *
- SESSION_HASH_SIZE, GFP_KERNEL);
+ nn->sessionid_hashtbl = kmalloc_array(SESSION_HASH_SIZE,
+ sizeof(struct list_head),
+ GFP_KERNEL);
if (!nn->sessionid_hashtbl)
goto err_sessionid;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 1d048dd95464..a96843c59fc1 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -320,6 +320,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
struct iattr *iattr, struct nfs4_acl **acl,
struct xdr_netobj *label, int *umask)
{
+ struct timespec ts;
int expected_len, len = 0;
u32 dummy32;
char *buf;
@@ -421,7 +422,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
switch (dummy32) {
case NFS4_SET_TO_CLIENT_TIME:
len += 12;
- status = nfsd4_decode_time(argp, &iattr->ia_atime);
+ status = nfsd4_decode_time(argp, &ts);
+ iattr->ia_atime = timespec_to_timespec64(ts);
if (status)
return status;
iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
@@ -440,7 +442,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
switch (dummy32) {
case NFS4_SET_TO_CLIENT_TIME:
len += 12;
- status = nfsd4_decode_time(argp, &iattr->ia_mtime);
+ status = nfsd4_decode_time(argp, &ts);
+ iattr->ia_mtime = timespec_to_timespec64(ts);
if (status)
return status;
iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
@@ -1585,6 +1588,8 @@ nfsd4_decode_getdeviceinfo(struct nfsd4_compoundargs *argp,
gdev->gd_maxcount = be32_to_cpup(p++);
num = be32_to_cpup(p++);
if (num) {
+ if (num > 1000)
+ goto xdr_error;
READ_BUF(4 * num);
gdev->gd_notify_types = be32_to_cpup(p++);
for (i = 1; i < num; i++) {
@@ -3651,7 +3656,8 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
nfserr = nfserr_resource;
goto err_no_verf;
}
- maxcount = min_t(u32, readdir->rd_maxcount, INT_MAX);
+ maxcount = svc_max_payload(resp->rqstp);
+ maxcount = min_t(u32, readdir->rd_maxcount, maxcount);
/*
* Note the rfc defines rd_maxcount as the size of the
* READDIR4resok structure, which includes the verifier above
@@ -3665,7 +3671,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
/* RFC 3530 14.2.24 allows us to ignore dircount when it's 0: */
if (!readdir->rd_dircount)
- readdir->rd_dircount = INT_MAX;
+ readdir->rd_dircount = svc_max_payload(resp->rqstp);
readdir->xdr = xdr;
readdir->rd_maxcount = maxcount;
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index 334f2ad60704..dbdeb9d6af03 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -177,7 +177,8 @@ int nfsd_reply_cache_init(void)
drc_hashtbl = kcalloc(hashsize, sizeof(*drc_hashtbl), GFP_KERNEL);
if (!drc_hashtbl) {
- drc_hashtbl = vzalloc(hashsize * sizeof(*drc_hashtbl));
+ drc_hashtbl = vzalloc(array_size(hashsize,
+ sizeof(*drc_hashtbl)));
if (!drc_hashtbl)
goto out_nomem;
}
@@ -394,7 +395,6 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
__wsum csum;
u32 hash = nfsd_cache_hash(xid);
struct nfsd_drc_bucket *b = &drc_hashtbl[hash];
- unsigned long age;
int type = rqstp->rq_cachetype;
int rtn = RC_DOIT;
@@ -461,12 +461,11 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
found_entry:
nfsdstats.rchits++;
/* We found a matching entry which is either in progress or done. */
- age = jiffies - rp->c_timestamp;
lru_put_end(b, rp);
rtn = RC_DROPIT;
- /* Request being processed or excessive rexmits */
- if (rp->c_state == RC_INPROG || age < RC_DELAY)
+ /* Request being processed */
+ if (rp->c_state == RC_INPROG)
goto out;
/* From the hall of fame of impractical attacks:
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index a43e8260520a..6b2e8b73d36e 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -131,7 +131,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
{
struct dentry *dentry = fhp->fh_dentry;
int type;
- struct timespec time;
+ struct timespec64 time;
u32 f;
type = (stat->mode & S_IFMT);
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index 63a1ca4b9dee..e2bea2ac5dfb 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -79,12 +79,11 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark)
*/
static int dnotify_handle_event(struct fsnotify_group *group,
struct inode *inode,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmount_mark,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info)
{
+ struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
struct dnotify_mark *dn_mark;
struct dnotify_struct *dn;
struct dnotify_struct **prev;
@@ -95,7 +94,8 @@ static int dnotify_handle_event(struct fsnotify_group *group,
if (!S_ISDIR(inode->i_mode))
return 0;
- BUG_ON(vfsmount_mark);
+ if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info)))
+ return 0;
dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark);
@@ -319,7 +319,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
spin_lock(&fsn_mark->lock);
} else {
- error = fsnotify_add_mark_locked(new_fsn_mark, inode, NULL, 0);
+ error = fsnotify_add_inode_mark_locked(new_fsn_mark, inode, 0);
if (error) {
mutex_unlock(&dnotify_group->mark_mutex);
goto out_err;
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index d94e8031fe5f..f90842efea13 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -87,17 +87,17 @@ static int fanotify_get_response(struct fsnotify_group *group,
return ret;
}
-static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmnt_mark,
- u32 event_mask,
- const void *data, int data_type)
+static bool fanotify_should_send_event(struct fsnotify_iter_info *iter_info,
+ u32 event_mask, const void *data,
+ int data_type)
{
__u32 marks_mask = 0, marks_ignored_mask = 0;
const struct path *path = data;
+ struct fsnotify_mark *mark;
+ int type;
- pr_debug("%s: inode_mark=%p vfsmnt_mark=%p mask=%x data=%p"
- " data_type=%d\n", __func__, inode_mark, vfsmnt_mark,
- event_mask, data, data_type);
+ pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",
+ __func__, iter_info->report_mask, event_mask, data, data_type);
/* if we don't have enough info to send an event to userspace say no */
if (data_type != FSNOTIFY_EVENT_PATH)
@@ -108,20 +108,21 @@ static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark,
!d_can_lookup(path->dentry))
return false;
- /*
- * if the event is for a child and this inode doesn't care about
- * events on the child, don't send it!
- */
- if (inode_mark &&
- (!(event_mask & FS_EVENT_ON_CHILD) ||
- (inode_mark->mask & FS_EVENT_ON_CHILD))) {
- marks_mask |= inode_mark->mask;
- marks_ignored_mask |= inode_mark->ignored_mask;
- }
+ fsnotify_foreach_obj_type(type) {
+ if (!fsnotify_iter_should_report_type(iter_info, type))
+ continue;
+ mark = iter_info->marks[type];
+ /*
+ * if the event is for a child and this inode doesn't care about
+ * events on the child, don't send it!
+ */
+ if (type == FSNOTIFY_OBJ_TYPE_INODE &&
+ (event_mask & FS_EVENT_ON_CHILD) &&
+ !(mark->mask & FS_EVENT_ON_CHILD))
+ continue;
- if (vfsmnt_mark) {
- marks_mask |= vfsmnt_mark->mask;
- marks_ignored_mask |= vfsmnt_mark->ignored_mask;
+ marks_mask |= mark->mask;
+ marks_ignored_mask |= mark->ignored_mask;
}
if (d_is_dir(path->dentry) &&
@@ -178,8 +179,6 @@ init: __maybe_unused
static int fanotify_handle_event(struct fsnotify_group *group,
struct inode *inode,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *fanotify_mark,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info)
@@ -199,8 +198,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM);
BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR);
- if (!fanotify_should_send_event(inode_mark, fanotify_mark, mask, data,
- data_type))
+ if (!fanotify_should_send_event(iter_info, mask, data, data_type))
return 0;
pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode,
diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c
index d478629c728b..10aac1942c9f 100644
--- a/fs/notify/fdinfo.c
+++ b/fs/notify/fdinfo.c
@@ -77,7 +77,7 @@ static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
struct inotify_inode_mark *inode_mark;
struct inode *inode;
- if (!(mark->connector->flags & FSNOTIFY_OBJ_TYPE_INODE))
+ if (mark->connector->type != FSNOTIFY_OBJ_TYPE_INODE)
return;
inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark);
@@ -116,7 +116,7 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
if (mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)
mflags |= FAN_MARK_IGNORED_SURV_MODIFY;
- if (mark->connector->flags & FSNOTIFY_OBJ_TYPE_INODE) {
+ if (mark->connector->type == FSNOTIFY_OBJ_TYPE_INODE) {
inode = igrab(mark->connector->inode);
if (!inode)
return;
@@ -126,7 +126,7 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
show_mark_fhandle(m, inode);
seq_putc(m, '\n');
iput(inode);
- } else if (mark->connector->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
+ } else if (mark->connector->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
struct mount *mnt = real_mount(mark->connector->mnt);
seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n",
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 613ec7e5a465..f174397b63a0 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -184,8 +184,6 @@ int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask
EXPORT_SYMBOL_GPL(__fsnotify_parent);
static int send_to_group(struct inode *to_tell,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmount_mark,
__u32 mask, const void *data,
int data_is, u32 cookie,
const unsigned char *file_name,
@@ -195,48 +193,45 @@ static int send_to_group(struct inode *to_tell,
__u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
__u32 marks_mask = 0;
__u32 marks_ignored_mask = 0;
+ struct fsnotify_mark *mark;
+ int type;
- if (unlikely(!inode_mark && !vfsmount_mark)) {
- BUG();
+ if (WARN_ON(!iter_info->report_mask))
return 0;
- }
/* clear ignored on inode modification */
if (mask & FS_MODIFY) {
- if (inode_mark &&
- !(inode_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
- inode_mark->ignored_mask = 0;
- if (vfsmount_mark &&
- !(vfsmount_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
- vfsmount_mark->ignored_mask = 0;
- }
-
- /* does the inode mark tell us to do something? */
- if (inode_mark) {
- group = inode_mark->group;
- marks_mask |= inode_mark->mask;
- marks_ignored_mask |= inode_mark->ignored_mask;
+ fsnotify_foreach_obj_type(type) {
+ if (!fsnotify_iter_should_report_type(iter_info, type))
+ continue;
+ mark = iter_info->marks[type];
+ if (mark &&
+ !(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
+ mark->ignored_mask = 0;
+ }
}
- /* does the vfsmount_mark tell us to do something? */
- if (vfsmount_mark) {
- group = vfsmount_mark->group;
- marks_mask |= vfsmount_mark->mask;
- marks_ignored_mask |= vfsmount_mark->ignored_mask;
+ fsnotify_foreach_obj_type(type) {
+ if (!fsnotify_iter_should_report_type(iter_info, type))
+ continue;
+ mark = iter_info->marks[type];
+ /* does the object mark tell us to do something? */
+ if (mark) {
+ group = mark->group;
+ marks_mask |= mark->mask;
+ marks_ignored_mask |= mark->ignored_mask;
+ }
}
- pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p"
- " vfsmount_mark=%p marks_mask=%x marks_ignored_mask=%x"
+ pr_debug("%s: group=%p to_tell=%p mask=%x marks_mask=%x marks_ignored_mask=%x"
" data=%p data_is=%d cookie=%d\n",
- __func__, group, to_tell, mask, inode_mark, vfsmount_mark,
- marks_mask, marks_ignored_mask, data,
- data_is, cookie);
+ __func__, group, to_tell, mask, marks_mask, marks_ignored_mask,
+ data, data_is, cookie);
if (!(test_mask & marks_mask & ~marks_ignored_mask))
return 0;
- return group->ops->handle_event(group, to_tell, inode_mark,
- vfsmount_mark, mask, data, data_is,
+ return group->ops->handle_event(group, to_tell, mask, data, data_is,
file_name, cookie, iter_info);
}
@@ -264,6 +259,57 @@ static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
}
/*
+ * iter_info is a multi head priority queue of marks.
+ * Pick a subset of marks from queue heads, all with the
+ * same group and set the report_mask for selected subset.
+ * Returns the report_mask of the selected subset.
+ */
+static unsigned int fsnotify_iter_select_report_types(
+ struct fsnotify_iter_info *iter_info)
+{
+ struct fsnotify_group *max_prio_group = NULL;
+ struct fsnotify_mark *mark;
+ int type;
+
+ /* Choose max prio group among groups of all queue heads */
+ fsnotify_foreach_obj_type(type) {
+ mark = iter_info->marks[type];
+ if (mark &&
+ fsnotify_compare_groups(max_prio_group, mark->group) > 0)
+ max_prio_group = mark->group;
+ }
+
+ if (!max_prio_group)
+ return 0;
+
+ /* Set the report mask for marks from same group as max prio group */
+ iter_info->report_mask = 0;
+ fsnotify_foreach_obj_type(type) {
+ mark = iter_info->marks[type];
+ if (mark &&
+ fsnotify_compare_groups(max_prio_group, mark->group) == 0)
+ fsnotify_iter_set_report_type(iter_info, type);
+ }
+
+ return iter_info->report_mask;
+}
+
+/*
+ * Pop from iter_info multi head queue, the marks that were iterated in the
+ * current iteration step.
+ */
+static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info)
+{
+ int type;
+
+ fsnotify_foreach_obj_type(type) {
+ if (fsnotify_iter_should_report_type(iter_info, type))
+ iter_info->marks[type] =
+ fsnotify_next_mark(iter_info->marks[type]);
+ }
+}
+
+/*
* This is the main call to fsnotify. The VFS calls into hook specific functions
* in linux/fsnotify.h. Those functions then in turn call here. Here will call
* out to all of the registered fsnotify_group. Those groups can then use the
@@ -307,15 +353,15 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
if ((mask & FS_MODIFY) ||
(test_mask & to_tell->i_fsnotify_mask)) {
- iter_info.inode_mark =
+ iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] =
fsnotify_first_mark(&to_tell->i_fsnotify_marks);
}
if (mnt && ((mask & FS_MODIFY) ||
(test_mask & mnt->mnt_fsnotify_mask))) {
- iter_info.inode_mark =
+ iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] =
fsnotify_first_mark(&to_tell->i_fsnotify_marks);
- iter_info.vfsmount_mark =
+ iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] =
fsnotify_first_mark(&mnt->mnt_fsnotify_marks);
}
@@ -324,32 +370,14 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
* ignore masks are properly reflected for mount mark notifications.
* That's why this traversal is so complicated...
*/
- while (iter_info.inode_mark || iter_info.vfsmount_mark) {
- struct fsnotify_mark *inode_mark = iter_info.inode_mark;
- struct fsnotify_mark *vfsmount_mark = iter_info.vfsmount_mark;
-
- if (inode_mark && vfsmount_mark) {
- int cmp = fsnotify_compare_groups(inode_mark->group,
- vfsmount_mark->group);
- if (cmp > 0)
- inode_mark = NULL;
- else if (cmp < 0)
- vfsmount_mark = NULL;
- }
-
- ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask,
- data, data_is, cookie, file_name,
- &iter_info);
+ while (fsnotify_iter_select_report_types(&iter_info)) {
+ ret = send_to_group(to_tell, mask, data, data_is, cookie,
+ file_name, &iter_info);
if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
goto out;
- if (inode_mark)
- iter_info.inode_mark =
- fsnotify_next_mark(iter_info.inode_mark);
- if (vfsmount_mark)
- iter_info.vfsmount_mark =
- fsnotify_next_mark(iter_info.vfsmount_mark);
+ fsnotify_iter_next(&iter_info);
}
ret = 0;
out:
diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h
index 60f365dc1408..34515d2c4ba3 100644
--- a/fs/notify/fsnotify.h
+++ b/fs/notify/fsnotify.h
@@ -9,12 +9,6 @@
#include "../mount.h"
-struct fsnotify_iter_info {
- struct fsnotify_mark *inode_mark;
- struct fsnotify_mark *vfsmount_mark;
- int srcu_idx;
-};
-
/* destroy all events sitting in this groups notification queue */
extern void fsnotify_flush_notify(struct fsnotify_group *group);
diff --git a/fs/notify/group.c b/fs/notify/group.c
index b7a4b6a69efa..aa5468f23e45 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -67,7 +67,7 @@ void fsnotify_destroy_group(struct fsnotify_group *group)
fsnotify_group_stop_queueing(group);
/* Clear all marks for this group and queue them for destruction */
- fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_ALL_TYPES);
+ fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_ALL_TYPES_MASK);
/*
* Some marks can still be pinned when waiting for response from
diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h
index c00d2caca894..7e4578d35b61 100644
--- a/fs/notify/inotify/inotify.h
+++ b/fs/notify/inotify/inotify.h
@@ -25,8 +25,6 @@ extern void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
struct fsnotify_group *group);
extern int inotify_handle_event(struct fsnotify_group *group,
struct inode *inode,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmount_mark,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info);
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index 40dedb37a1f3..9ab6dde38a14 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -65,12 +65,11 @@ static int inotify_merge(struct list_head *list,
int inotify_handle_event(struct fsnotify_group *group,
struct inode *inode,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmount_mark,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info)
{
+ struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
struct inotify_inode_mark *i_mark;
struct inotify_event_info *event;
struct fsnotify_event *fsn_event;
@@ -78,7 +77,8 @@ int inotify_handle_event(struct fsnotify_group *group,
int len = 0;
int alloc_len = sizeof(struct inotify_event_info);
- BUG_ON(vfsmount_mark);
+ if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info)))
+ return 0;
if ((inode_mark->mask & FS_EXCL_UNLINK) &&
(data_type == FSNOTIFY_EVENT_PATH)) {
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index ef32f3657958..1cf5b779d862 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -485,10 +485,14 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
struct fsnotify_group *group)
{
struct inotify_inode_mark *i_mark;
+ struct fsnotify_iter_info iter_info = { };
+
+ fsnotify_iter_set_report_type_mark(&iter_info, FSNOTIFY_OBJ_TYPE_INODE,
+ fsn_mark);
/* Queue ignore event for the watch */
- inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED,
- NULL, FSNOTIFY_EVENT_NONE, NULL, 0, NULL);
+ inotify_handle_event(group, NULL, FS_IN_IGNORED, NULL,
+ FSNOTIFY_EVENT_NONE, NULL, 0, &iter_info);
i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
/* remove this mark from the idr */
@@ -578,7 +582,7 @@ static int inotify_new_watch(struct fsnotify_group *group,
}
/* we are on the idr, now get on the inode */
- ret = fsnotify_add_mark_locked(&tmp_i_mark->fsn_mark, inode, NULL, 0);
+ ret = fsnotify_add_inode_mark_locked(&tmp_i_mark->fsn_mark, inode, 0);
if (ret) {
/* we failed to get on the inode, get off the idr */
inotify_remove_from_idr(group, tmp_i_mark);
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index e9191b416434..61f4c5fa34c7 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -119,9 +119,9 @@ static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)
new_mask |= mark->mask;
}
- if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE)
+ if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
conn->inode->i_fsnotify_mask = new_mask;
- else if (conn->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT)
+ else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT)
real_mount(conn->mnt)->mnt_fsnotify_mask = new_mask;
}
@@ -139,7 +139,7 @@ void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
spin_lock(&conn->lock);
__fsnotify_recalc_mask(conn);
spin_unlock(&conn->lock);
- if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE)
+ if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
__fsnotify_update_child_dentry_flags(conn->inode);
}
@@ -166,18 +166,18 @@ static struct inode *fsnotify_detach_connector_from_object(
{
struct inode *inode = NULL;
- if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE) {
+ if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) {
inode = conn->inode;
rcu_assign_pointer(inode->i_fsnotify_marks, NULL);
inode->i_fsnotify_mask = 0;
conn->inode = NULL;
- conn->flags &= ~FSNOTIFY_OBJ_TYPE_INODE;
- } else if (conn->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
+ conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;
+ } else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
rcu_assign_pointer(real_mount(conn->mnt)->mnt_fsnotify_marks,
NULL);
real_mount(conn->mnt)->mnt_fsnotify_mask = 0;
conn->mnt = NULL;
- conn->flags &= ~FSNOTIFY_OBJ_TYPE_VFSMOUNT;
+ conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;
}
return inode;
@@ -294,12 +294,12 @@ static void fsnotify_put_mark_wake(struct fsnotify_mark *mark)
bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
{
- /* This can fail if mark is being removed */
- if (!fsnotify_get_mark_safe(iter_info->inode_mark))
- return false;
- if (!fsnotify_get_mark_safe(iter_info->vfsmount_mark)) {
- fsnotify_put_mark_wake(iter_info->inode_mark);
- return false;
+ int type;
+
+ fsnotify_foreach_obj_type(type) {
+ /* This can fail if mark is being removed */
+ if (!fsnotify_get_mark_safe(iter_info->marks[type]))
+ goto fail;
}
/*
@@ -310,13 +310,20 @@ bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
srcu_read_unlock(&fsnotify_mark_srcu, iter_info->srcu_idx);
return true;
+
+fail:
+ for (type--; type >= 0; type--)
+ fsnotify_put_mark_wake(iter_info->marks[type]);
+ return false;
}
void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info)
{
+ int type;
+
iter_info->srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
- fsnotify_put_mark_wake(iter_info->inode_mark);
- fsnotify_put_mark_wake(iter_info->vfsmount_mark);
+ fsnotify_foreach_obj_type(type)
+ fsnotify_put_mark_wake(iter_info->marks[type]);
}
/*
@@ -442,10 +449,10 @@ static int fsnotify_attach_connector_to_object(
spin_lock_init(&conn->lock);
INIT_HLIST_HEAD(&conn->list);
if (inode) {
- conn->flags = FSNOTIFY_OBJ_TYPE_INODE;
+ conn->type = FSNOTIFY_OBJ_TYPE_INODE;
conn->inode = igrab(inode);
} else {
- conn->flags = FSNOTIFY_OBJ_TYPE_VFSMOUNT;
+ conn->type = FSNOTIFY_OBJ_TYPE_VFSMOUNT;
conn->mnt = mnt;
}
/*
@@ -479,8 +486,7 @@ static struct fsnotify_mark_connector *fsnotify_grab_connector(
if (!conn)
goto out;
spin_lock(&conn->lock);
- if (!(conn->flags & (FSNOTIFY_OBJ_TYPE_INODE |
- FSNOTIFY_OBJ_TYPE_VFSMOUNT))) {
+ if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) {
spin_unlock(&conn->lock);
srcu_read_unlock(&fsnotify_mark_srcu, idx);
return NULL;
@@ -646,16 +652,16 @@ struct fsnotify_mark *fsnotify_find_mark(
return NULL;
}
-/* Clear any marks in a group with given type */
+/* Clear any marks in a group with given type mask */
void fsnotify_clear_marks_by_group(struct fsnotify_group *group,
- unsigned int type)
+ unsigned int type_mask)
{
struct fsnotify_mark *lmark, *mark;
LIST_HEAD(to_free);
struct list_head *head = &to_free;
/* Skip selection step if we want to clear all marks. */
- if (type == FSNOTIFY_OBJ_ALL_TYPES) {
+ if (type_mask == FSNOTIFY_OBJ_ALL_TYPES_MASK) {
head = &group->marks_list;
goto clear;
}
@@ -670,7 +676,7 @@ void fsnotify_clear_marks_by_group(struct fsnotify_group *group,
*/
mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) {
- if (mark->connector->flags & type)
+ if ((1U << mark->connector->type) & type_mask)
list_move(&mark->g_list, &to_free);
}
mutex_unlock(&group->mark_mutex);
diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c
index f8eb04387ca4..fbd0090d7d0c 100644
--- a/fs/ntfs/compress.c
+++ b/fs/ntfs/compress.c
@@ -527,7 +527,7 @@ int ntfs_read_compressed_block(struct page *page)
BUG_ON(ni->type != AT_DATA);
BUG_ON(ni->name_len);
- pages = kmalloc(nr_pages * sizeof(struct page *), GFP_NOFS);
+ pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_NOFS);
/* Allocate memory to store the buffer heads we need. */
bhs_size = cb_size / block_size * sizeof(struct buffer_head *);
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 1c1ee489284b..decaf75d1cd5 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -667,18 +667,18 @@ static int ntfs_read_locked_inode(struct inode *vi)
* mtime is the last change of the data within the file. Not changed
* when only metadata is changed, e.g. a rename doesn't affect mtime.
*/
- vi->i_mtime = ntfs2utc(si->last_data_change_time);
+ vi->i_mtime = timespec_to_timespec64(ntfs2utc(si->last_data_change_time));
/*
* ctime is the last change of the metadata of the file. This obviously
* always changes, when mtime is changed. ctime can be changed on its
* own, mtime is then not changed, e.g. when a file is renamed.
*/
- vi->i_ctime = ntfs2utc(si->last_mft_change_time);
+ vi->i_ctime = timespec_to_timespec64(ntfs2utc(si->last_mft_change_time));
/*
* Last access to the data within the file. Not changed during a rename
* for example but changed whenever the file is written to.
*/
- vi->i_atime = ntfs2utc(si->last_access_time);
+ vi->i_atime = timespec_to_timespec64(ntfs2utc(si->last_access_time));
/* Find the attribute list attribute if present. */
ntfs_attr_reinit_search_ctx(ctx);
@@ -2804,11 +2804,11 @@ done:
* for real.
*/
if (!IS_NOCMTIME(VFS_I(base_ni)) && !IS_RDONLY(VFS_I(base_ni))) {
- struct timespec now = current_time(VFS_I(base_ni));
+ struct timespec64 now = current_time(VFS_I(base_ni));
int sync_it = 0;
- if (!timespec_equal(&VFS_I(base_ni)->i_mtime, &now) ||
- !timespec_equal(&VFS_I(base_ni)->i_ctime, &now))
+ if (!timespec64_equal(&VFS_I(base_ni)->i_mtime, &now) ||
+ !timespec64_equal(&VFS_I(base_ni)->i_ctime, &now))
sync_it = 1;
VFS_I(base_ni)->i_mtime = now;
VFS_I(base_ni)->i_ctime = now;
@@ -2923,14 +2923,14 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
}
}
if (ia_valid & ATTR_ATIME)
- vi->i_atime = timespec_trunc(attr->ia_atime,
- vi->i_sb->s_time_gran);
+ vi->i_atime = timespec64_trunc(attr->ia_atime,
+ vi->i_sb->s_time_gran);
if (ia_valid & ATTR_MTIME)
- vi->i_mtime = timespec_trunc(attr->ia_mtime,
- vi->i_sb->s_time_gran);
+ vi->i_mtime = timespec64_trunc(attr->ia_mtime,
+ vi->i_sb->s_time_gran);
if (ia_valid & ATTR_CTIME)
- vi->i_ctime = timespec_trunc(attr->ia_ctime,
- vi->i_sb->s_time_gran);
+ vi->i_ctime = timespec64_trunc(attr->ia_ctime,
+ vi->i_sb->s_time_gran);
mark_inode_dirty(vi);
out:
return err;
@@ -2997,7 +2997,7 @@ int __ntfs_write_inode(struct inode *vi, int sync)
si = (STANDARD_INFORMATION*)((u8*)ctx->attr +
le16_to_cpu(ctx->attr->data.resident.value_offset));
/* Update the access times if they have changed. */
- nt = utc2ntfs(vi->i_mtime);
+ nt = utc2ntfs(timespec64_to_timespec(vi->i_mtime));
if (si->last_data_change_time != nt) {
ntfs_debug("Updating mtime for inode 0x%lx: old = 0x%llx, "
"new = 0x%llx", vi->i_ino, (long long)
@@ -3006,7 +3006,7 @@ int __ntfs_write_inode(struct inode *vi, int sync)
si->last_data_change_time = nt;
modified = true;
}
- nt = utc2ntfs(vi->i_ctime);
+ nt = utc2ntfs(timespec64_to_timespec(vi->i_ctime));
if (si->last_mft_change_time != nt) {
ntfs_debug("Updating ctime for inode 0x%lx: old = 0x%llx, "
"new = 0x%llx", vi->i_ino, (long long)
@@ -3015,7 +3015,7 @@ int __ntfs_write_inode(struct inode *vi, int sync)
si->last_mft_change_time = nt;
modified = true;
}
- nt = utc2ntfs(vi->i_atime);
+ nt = utc2ntfs(timespec64_to_timespec(vi->i_atime));
if (si->last_access_time != nt) {
ntfs_debug("Updating atime for inode 0x%lx: old = 0x%llx, "
"new = 0x%llx", vi->i_ino,
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index e5076185cc1e..1296f78ae966 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -1078,7 +1078,7 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
o2net_set_nst_sock_container(&nst, sc);
veclen = caller_veclen + 1;
- vec = kmalloc(sizeof(struct kvec) * veclen, GFP_ATOMIC);
+ vec = kmalloc_array(veclen, sizeof(struct kvec), GFP_ATOMIC);
if (vec == NULL) {
mlog(0, "failed to %zu element kvec!\n", veclen);
ret = -ENOMEM;
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index 425081be6161..2acd58ba9b7b 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -86,7 +86,7 @@ static void dlm_free_pagevec(void **vec, int pages)
static void **dlm_alloc_pagevec(int pages)
{
- void **vec = kmalloc(pages * sizeof(void *), GFP_KERNEL);
+ void **vec = kmalloc_array(pages, sizeof(void *), GFP_KERNEL);
int i;
if (!vec)
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 68728de12864..0ff424c6d17c 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -2140,6 +2140,7 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode)
struct ocfs2_inode_info *oi = OCFS2_I(inode);
struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres;
struct ocfs2_meta_lvb *lvb;
+ struct timespec ts;
lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
@@ -2160,12 +2161,15 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode)
lvb->lvb_igid = cpu_to_be32(i_gid_read(inode));
lvb->lvb_imode = cpu_to_be16(inode->i_mode);
lvb->lvb_inlink = cpu_to_be16(inode->i_nlink);
+ ts = timespec64_to_timespec(inode->i_atime);
lvb->lvb_iatime_packed =
- cpu_to_be64(ocfs2_pack_timespec(&inode->i_atime));
+ cpu_to_be64(ocfs2_pack_timespec(&ts));
+ ts = timespec64_to_timespec(inode->i_ctime);
lvb->lvb_ictime_packed =
- cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime));
+ cpu_to_be64(ocfs2_pack_timespec(&ts));
+ ts = timespec64_to_timespec(inode->i_mtime);
lvb->lvb_imtime_packed =
- cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime));
+ cpu_to_be64(ocfs2_pack_timespec(&ts));
lvb->lvb_iattr = cpu_to_be32(oi->ip_attr);
lvb->lvb_idynfeatures = cpu_to_be16(oi->ip_dyn_features);
lvb->lvb_igeneration = cpu_to_be32(inode->i_generation);
@@ -2183,6 +2187,7 @@ static void ocfs2_unpack_timespec(struct timespec *spec,
static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
{
+ struct timespec ts;
struct ocfs2_inode_info *oi = OCFS2_I(inode);
struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres;
struct ocfs2_meta_lvb *lvb;
@@ -2210,12 +2215,15 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
i_gid_write(inode, be32_to_cpu(lvb->lvb_igid));
inode->i_mode = be16_to_cpu(lvb->lvb_imode);
set_nlink(inode, be16_to_cpu(lvb->lvb_inlink));
- ocfs2_unpack_timespec(&inode->i_atime,
+ ocfs2_unpack_timespec(&ts,
be64_to_cpu(lvb->lvb_iatime_packed));
- ocfs2_unpack_timespec(&inode->i_mtime,
+ inode->i_atime = timespec_to_timespec64(ts);
+ ocfs2_unpack_timespec(&ts,
be64_to_cpu(lvb->lvb_imtime_packed));
- ocfs2_unpack_timespec(&inode->i_ctime,
+ inode->i_mtime = timespec_to_timespec64(ts);
+ ocfs2_unpack_timespec(&ts,
be64_to_cpu(lvb->lvb_ictime_packed));
+ inode->i_ctime = timespec_to_timespec64(ts);
spin_unlock(&oi->ip_lock);
}
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index a2a8603d27e0..255f758af03a 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -222,7 +222,7 @@ static int ocfs2_sync_file(struct file *file, loff_t start, loff_t end,
int ocfs2_should_update_atime(struct inode *inode,
struct vfsmount *vfsmnt)
{
- struct timespec now;
+ struct timespec64 now;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
@@ -248,8 +248,8 @@ int ocfs2_should_update_atime(struct inode *inode,
return 0;
if (vfsmnt->mnt_flags & MNT_RELATIME) {
- if ((timespec_compare(&inode->i_atime, &inode->i_mtime) <= 0) ||
- (timespec_compare(&inode->i_atime, &inode->i_ctime) <= 0))
+ if ((timespec64_compare(&inode->i_atime, &inode->i_mtime) <= 0) ||
+ (timespec64_compare(&inode->i_atime, &inode->i_ctime) <= 0))
return 1;
return 0;
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index e5dcea6cee5f..bd3475694e83 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -1383,7 +1383,7 @@ static int __ocfs2_recovery_thread(void *arg)
goto bail;
}
- rm_quota = kzalloc(osb->max_slots * sizeof(int), GFP_NOFS);
+ rm_quota = kcalloc(osb->max_slots, sizeof(int), GFP_NOFS);
if (!rm_quota) {
status = -ENOMEM;
goto bail;
diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c
index af155c183123..5965f3878d49 100644
--- a/fs/ocfs2/sysfile.c
+++ b/fs/ocfs2/sysfile.c
@@ -69,10 +69,11 @@ static struct inode **get_local_system_inode(struct ocfs2_super *osb,
spin_unlock(&osb->osb_lock);
if (unlikely(!local_system_inodes)) {
- local_system_inodes = kzalloc(sizeof(struct inode *) *
- NUM_LOCAL_SYSTEM_INODES *
- osb->max_slots,
- GFP_NOFS);
+ local_system_inodes =
+ kzalloc(array3_size(sizeof(struct inode *),
+ NUM_LOCAL_SYSTEM_INODES,
+ osb->max_slots),
+ GFP_NOFS);
if (!local_system_inodes) {
mlog_errno(-ENOMEM);
/*
diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c
index 74b37cbbd5d4..33ee8cb32f83 100644
--- a/fs/orangefs/devorangefs-req.c
+++ b/fs/orangefs/devorangefs-req.c
@@ -719,37 +719,6 @@ struct ORANGEFS_dev_map_desc32 {
__s32 count;
};
-static unsigned long translate_dev_map26(unsigned long args, long *error)
-{
- struct ORANGEFS_dev_map_desc32 __user *p32 = (void __user *)args;
- /*
- * Depending on the architecture, allocate some space on the
- * user-call-stack based on our expected layout.
- */
- struct ORANGEFS_dev_map_desc __user *p =
- compat_alloc_user_space(sizeof(*p));
- compat_uptr_t addr;
-
- *error = 0;
- /* get the ptr from the 32 bit user-space */
- if (get_user(addr, &p32->ptr))
- goto err;
- /* try to put that into a 64-bit layout */
- if (put_user(compat_ptr(addr), &p->ptr))
- goto err;
- /* copy the remaining fields */
- if (copy_in_user(&p->total_size, &p32->total_size, sizeof(__s32)))
- goto err;
- if (copy_in_user(&p->size, &p32->size, sizeof(__s32)))
- goto err;
- if (copy_in_user(&p->count, &p32->count, sizeof(__s32)))
- goto err;
- return (unsigned long)p;
-err:
- *error = -EFAULT;
- return 0;
-}
-
/*
* 32 bit user-space apps' ioctl handlers when kernel modules
* is compiled as a 64 bit one
@@ -758,25 +727,26 @@ static long orangefs_devreq_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long args)
{
long ret;
- unsigned long arg = args;
/* Check for properly constructed commands */
ret = check_ioctl_command(cmd);
if (ret < 0)
return ret;
if (cmd == ORANGEFS_DEV_MAP) {
- /*
- * convert the arguments to what we expect internally
- * in kernel space
- */
- arg = translate_dev_map26(args, &ret);
- if (ret < 0) {
- gossip_err("Could not translate dev map\n");
- return ret;
- }
+ struct ORANGEFS_dev_map_desc desc;
+ struct ORANGEFS_dev_map_desc32 d32;
+
+ if (copy_from_user(&d32, (void __user *)args, sizeof(d32)))
+ return -EFAULT;
+
+ desc.ptr = compat_ptr(d32.ptr);
+ desc.total_size = d32.total_size;
+ desc.size = d32.size;
+ desc.count = d32.count;
+ return orangefs_bufmap_initialize(&desc);
}
/* no other ioctl requires translation */
- return dispatch_ioctl_command(cmd, arg);
+ return dispatch_ioctl_command(cmd, args);
}
#endif /* CONFIG_COMPAT is in .config */
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index d6db252e6200..6e4d2af8f5bc 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -297,7 +297,7 @@ int orangefs_permission(struct inode *inode, int mask)
return generic_permission(inode, mask);
}
-int orangefs_update_time(struct inode *inode, struct timespec *time, int flags)
+int orangefs_update_time(struct inode *inode, struct timespec64 *time, int flags)
{
struct iattr iattr;
gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_update_time: %pU\n",
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 004511617b6d..17b24ad6b264 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -342,7 +342,7 @@ int orangefs_getattr(const struct path *path, struct kstat *stat,
int orangefs_permission(struct inode *inode, int mask);
-int orangefs_update_time(struct inode *, struct timespec *, int);
+int orangefs_update_time(struct inode *, struct timespec64 *, int);
/*
* defined in xattr.c
diff --git a/fs/orangefs/orangefs-sysfs.c b/fs/orangefs/orangefs-sysfs.c
index 079a465796f3..dd28079f518c 100644
--- a/fs/orangefs/orangefs-sysfs.c
+++ b/fs/orangefs/orangefs-sysfs.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Documentation/ABI/stable/orangefs-sysfs:
+ * Documentation/ABI/stable/sysfs-fs-orangefs:
*
* What: /sys/fs/orangefs/perf_counter_reset
* Date: June 2015
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 1db5b3b458a1..ed16a898caeb 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -416,7 +416,7 @@ int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags)
return err;
}
-int ovl_update_time(struct inode *inode, struct timespec *ts, int flags)
+int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags)
{
if (flags & S_ATIME) {
struct ovl_fs *ofs = inode->i_sb->s_fs_info;
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index 08801b45df00..c993dd8db739 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -612,7 +612,7 @@ static int ovl_get_index_name_fh(struct ovl_fh *fh, struct qstr *name)
{
char *n, *s;
- n = kzalloc(fh->len * 2, GFP_KERNEL);
+ n = kcalloc(fh->len, 2, GFP_KERNEL);
if (!n)
return -ENOMEM;
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 3c5e9f18b0d9..7538b9b56237 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -325,7 +325,7 @@ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
struct posix_acl *ovl_get_acl(struct inode *inode, int type);
int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags);
-int ovl_update_time(struct inode *inode, struct timespec *ts, int flags);
+int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags);
bool ovl_is_private_xattr(const char *name);
struct ovl_inode_params {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 4aa9ce5df02f..b6572944efc3 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -389,7 +389,8 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns,
unsigned long *entries;
int err;
- entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries), GFP_KERNEL);
+ entries = kmalloc_array(MAX_STACK_TRACE_DEPTH, sizeof(*entries),
+ GFP_KERNEL);
if (!entries)
return -ENOMEM;
@@ -2438,14 +2439,11 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
for (p = ents; p < last; p++) {
if (p->len != dentry->d_name.len)
continue;
- if (!memcmp(dentry->d_name.name, p->name, p->len))
+ if (!memcmp(dentry->d_name.name, p->name, p->len)) {
+ res = proc_pident_instantiate(dentry, task, p);
break;
+ }
}
- if (p >= last)
- goto out;
-
- res = proc_pident_instantiate(dentry, task, p);
-out:
put_task_struct(task);
out_no_task:
return res;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 7b4d9714f248..6ac1c92997ea 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -409,7 +409,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
if (!ent)
goto out;
- if (qstr.len + 1 <= sizeof(ent->inline_name)) {
+ if (qstr.len + 1 <= SIZEOF_PDE_INLINE_NAME) {
ent->name = ent->inline_name;
} else {
ent->name = kmalloc(qstr.len + 1, GFP_KERNEL);
@@ -740,3 +740,27 @@ void *PDE_DATA(const struct inode *inode)
return __PDE_DATA(inode);
}
EXPORT_SYMBOL(PDE_DATA);
+
+/*
+ * Pull a user buffer into memory and pass it to the file's write handler if
+ * one is supplied. The ->write() method is permitted to modify the
+ * kernel-side buffer.
+ */
+ssize_t proc_simple_write(struct file *f, const char __user *ubuf, size_t size,
+ loff_t *_pos)
+{
+ struct proc_dir_entry *pde = PDE(file_inode(f));
+ char *buf;
+ int ret;
+
+ if (!pde->write)
+ return -EACCES;
+ if (size == 0 || size > PAGE_SIZE - 1)
+ return -EINVAL;
+ buf = memdup_user_nul(ubuf, size);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+ ret = pde->write(f, buf, size);
+ kfree(buf);
+ return ret == 0 ? size : ret;
+}
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 2cf3b74391ca..85ffbd27f288 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -105,9 +105,8 @@ void __init proc_init_kmemcache(void)
kmem_cache_create("pde_opener", sizeof(struct pde_opener), 0,
SLAB_ACCOUNT|SLAB_PANIC, NULL);
proc_dir_entry_cache = kmem_cache_create_usercopy(
- "proc_dir_entry", sizeof(struct proc_dir_entry), 0, SLAB_PANIC,
- offsetof(struct proc_dir_entry, inline_name),
- sizeof_field(struct proc_dir_entry, inline_name), NULL);
+ "proc_dir_entry", SIZEOF_PDE_SLOT, 0, SLAB_PANIC,
+ OFFSETOF_PDE_NAME, SIZEOF_PDE_INLINE_NAME, NULL);
}
static int proc_show_options(struct seq_file *seq, struct dentry *root)
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 50cb22a08c2f..da3dbfa09e79 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -48,6 +48,7 @@ struct proc_dir_entry {
const struct seq_operations *seq_ops;
int (*single_show)(struct seq_file *, void *);
};
+ proc_write_t write;
void *data;
unsigned int state_size;
unsigned int low_ino;
@@ -61,14 +62,20 @@ struct proc_dir_entry {
char *name;
umode_t mode;
u8 namelen;
-#ifdef CONFIG_64BIT
-#define SIZEOF_PDE_INLINE_NAME (192-155)
-#else
-#define SIZEOF_PDE_INLINE_NAME (128-95)
-#endif
- char inline_name[SIZEOF_PDE_INLINE_NAME];
+ char inline_name[];
} __randomize_layout;
+#define OFFSETOF_PDE_NAME offsetof(struct proc_dir_entry, inline_name)
+#define SIZEOF_PDE_SLOT \
+ (OFFSETOF_PDE_NAME + 34 <= 64 ? 64 : \
+ OFFSETOF_PDE_NAME + 34 <= 128 ? 128 : \
+ OFFSETOF_PDE_NAME + 34 <= 192 ? 192 : \
+ OFFSETOF_PDE_NAME + 34 <= 256 ? 256 : \
+ OFFSETOF_PDE_NAME + 34 <= 512 ? 512 : \
+ 0)
+
+#define SIZEOF_PDE_INLINE_NAME (SIZEOF_PDE_SLOT - OFFSETOF_PDE_NAME)
+
extern struct kmem_cache *proc_dir_entry_cache;
void pde_free(struct proc_dir_entry *pde);
@@ -189,6 +196,7 @@ static inline bool is_empty_pde(const struct proc_dir_entry *pde)
{
return S_ISDIR(pde->mode) && !pde->proc_iops;
}
+extern ssize_t proc_simple_write(struct file *, const char __user *, size_t, loff_t *);
/*
* inode.c
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 7d94fa005b0d..d5e0fcb3439e 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -46,6 +46,9 @@ static int seq_open_net(struct inode *inode, struct file *file)
WARN_ON_ONCE(state_size < sizeof(*p));
+ if (file->f_mode & FMODE_WRITE && !PDE(inode)->write)
+ return -EACCES;
+
net = get_proc_net(inode);
if (!net)
return -ENXIO;
@@ -73,6 +76,7 @@ static int seq_release_net(struct inode *ino, struct file *f)
static const struct file_operations proc_net_seq_fops = {
.open = seq_open_net,
.read = seq_read,
+ .write = proc_simple_write,
.llseek = seq_lseek,
.release = seq_release_net,
};
@@ -93,6 +97,50 @@ struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
}
EXPORT_SYMBOL_GPL(proc_create_net_data);
+/**
+ * proc_create_net_data_write - Create a writable net_ns-specific proc file
+ * @name: The name of the file.
+ * @mode: The file's access mode.
+ * @parent: The parent directory in which to create.
+ * @ops: The seq_file ops with which to read the file.
+ * @write: The write method which which to 'modify' the file.
+ * @data: Data for retrieval by PDE_DATA().
+ *
+ * Create a network namespaced proc file in the @parent directory with the
+ * specified @name and @mode that allows reading of a file that displays a
+ * series of elements and also provides for the file accepting writes that have
+ * some arbitrary effect.
+ *
+ * The functions in the @ops table are used to iterate over items to be
+ * presented and extract the readable content using the seq_file interface.
+ *
+ * The @write function is called with the data copied into a kernel space
+ * scratch buffer and has a NUL appended for convenience. The buffer may be
+ * modified by the @write function. @write should return 0 on success.
+ *
+ * The @data value is accessible from the @show and @write functions by calling
+ * PDE_DATA() on the file inode. The network namespace must be accessed by
+ * calling seq_file_net() on the seq_file struct.
+ */
+struct proc_dir_entry *proc_create_net_data_write(const char *name, umode_t mode,
+ struct proc_dir_entry *parent,
+ const struct seq_operations *ops,
+ proc_write_t write,
+ unsigned int state_size, void *data)
+{
+ struct proc_dir_entry *p;
+
+ p = proc_create_reg(name, mode, &parent, data);
+ if (!p)
+ return NULL;
+ p->proc_fops = &proc_net_seq_fops;
+ p->seq_ops = ops;
+ p->state_size = state_size;
+ p->write = write;
+ return proc_register(parent, p);
+}
+EXPORT_SYMBOL_GPL(proc_create_net_data_write);
+
static int single_open_net(struct inode *inode, struct file *file)
{
struct proc_dir_entry *de = PDE(inode);
@@ -119,6 +167,7 @@ static int single_release_net(struct inode *ino, struct file *f)
static const struct file_operations proc_net_single_fops = {
.open = single_open_net,
.read = seq_read,
+ .write = proc_simple_write,
.llseek = seq_lseek,
.release = single_release_net,
};
@@ -138,6 +187,49 @@ struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
}
EXPORT_SYMBOL_GPL(proc_create_net_single);
+/**
+ * proc_create_net_single_write - Create a writable net_ns-specific proc file
+ * @name: The name of the file.
+ * @mode: The file's access mode.
+ * @parent: The parent directory in which to create.
+ * @show: The seqfile show method with which to read the file.
+ * @write: The write method which which to 'modify' the file.
+ * @data: Data for retrieval by PDE_DATA().
+ *
+ * Create a network-namespaced proc file in the @parent directory with the
+ * specified @name and @mode that allows reading of a file that displays a
+ * single element rather than a series and also provides for the file accepting
+ * writes that have some arbitrary effect.
+ *
+ * The @show function is called to extract the readable content via the
+ * seq_file interface.
+ *
+ * The @write function is called with the data copied into a kernel space
+ * scratch buffer and has a NUL appended for convenience. The buffer may be
+ * modified by the @write function. @write should return 0 on success.
+ *
+ * The @data value is accessible from the @show and @write functions by calling
+ * PDE_DATA() on the file inode. The network namespace must be accessed by
+ * calling seq_file_single_net() on the seq_file struct.
+ */
+struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mode,
+ struct proc_dir_entry *parent,
+ int (*show)(struct seq_file *, void *),
+ proc_write_t write,
+ void *data)
+{
+ struct proc_dir_entry *p;
+
+ p = proc_create_reg(name, mode, &parent, data);
+ if (!p)
+ return NULL;
+ p->proc_fops = &proc_net_single_fops;
+ p->single_show = show;
+ p->write = write;
+ return proc_register(parent, p);
+}
+EXPORT_SYMBOL_GPL(proc_create_net_single_write);
+
static struct net *get_proc_task_net(struct inode *dir)
{
struct task_struct *task;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 4d765e5e91ed..89921a0d2ebb 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -1426,7 +1426,7 @@ static int register_leaf_sysctl_tables(const char *path, char *pos,
/* If there are mixed files and directories we need a new table */
if (nr_dirs && nr_files) {
struct ctl_table *new;
- files = kzalloc(sizeof(struct ctl_table) * (nr_files + 1),
+ files = kcalloc(nr_files + 1, sizeof(struct ctl_table),
GFP_KERNEL);
if (!files)
goto out;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 61b7340b357a..f4b1a9d2eca6 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -204,8 +204,7 @@ struct proc_dir_entry proc_root = {
.proc_fops = &proc_root_operations,
.parent = &proc_root,
.subdir = RB_ROOT,
- .name = proc_root.inline_name,
- .inline_name = "/proc",
+ .name = "/proc",
};
int pid_ns_prepare_proc(struct pid_namespace *ns)
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 597969db9e90..e9679016271f 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1473,7 +1473,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
pm.show_pfn = file_ns_capable(file, &init_user_ns, CAP_SYS_ADMIN);
pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
- pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_KERNEL);
+ pm.buffer = kmalloc_array(pm.len, PM_ENTRY_BYTES, GFP_KERNEL);
ret = -ENOMEM;
if (!pm.buffer)
goto out_mm;
diff --git a/fs/proc/uptime.c b/fs/proc/uptime.c
index 3bd12f955867..3f723cb478af 100644
--- a/fs/proc/uptime.c
+++ b/fs/proc/uptime.c
@@ -10,7 +10,7 @@
static int uptime_proc_show(struct seq_file *m, void *v)
{
struct timespec uptime;
- struct timespec idle;
+ struct timespec64 idle;
u64 nsec;
u32 rem;
int i;
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index dc720573fd53..c238ab8ba31d 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -328,7 +328,7 @@ void pstore_record_init(struct pstore_record *record,
record->psi = psinfo;
/* Report zeroed timestamp if called before timekeeping has resumed. */
- record->time = ns_to_timespec(ktime_get_real_fast_ns());
+ record->time = ns_to_timespec64(ktime_get_real_fast_ns());
}
/*
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 49b2bc114868..bbd1e357c23d 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -153,21 +153,23 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], uint *c, uint max,
return prz;
}
-static int ramoops_read_kmsg_hdr(char *buffer, struct timespec *time,
+static int ramoops_read_kmsg_hdr(char *buffer, struct timespec64 *time,
bool *compressed)
{
char data_type;
int header_length = 0;
- if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lu.%lu-%c\n%n", &time->tv_sec,
- &time->tv_nsec, &data_type, &header_length) == 3) {
+ if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lld.%lu-%c\n%n",
+ (time64_t *)&time->tv_sec, &time->tv_nsec, &data_type,
+ &header_length) == 3) {
if (data_type == 'C')
*compressed = true;
else
*compressed = false;
- } else if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lu.%lu\n%n",
- &time->tv_sec, &time->tv_nsec, &header_length) == 2) {
- *compressed = false;
+ } else if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lld.%lu\n%n",
+ (time64_t *)&time->tv_sec, &time->tv_nsec,
+ &header_length) == 2) {
+ *compressed = false;
} else {
time->tv_sec = 0;
time->tv_nsec = 0;
@@ -360,8 +362,8 @@ static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz,
char *hdr;
size_t len;
- hdr = kasprintf(GFP_ATOMIC, RAMOOPS_KERNMSG_HDR "%lu.%lu-%c\n",
- record->time.tv_sec,
+ hdr = kasprintf(GFP_ATOMIC, RAMOOPS_KERNMSG_HDR "%lld.%06lu-%c\n",
+ (time64_t)record->time.tv_sec,
record->time.tv_nsec / 1000,
record->compressed ? 'C' : 'D');
WARN_ON_ONCE(!hdr);
diff --git a/fs/read_write.c b/fs/read_write.c
index e83bd9744b5d..153f8f690490 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -778,7 +778,7 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
goto out;
}
if (nr_segs > fast_segs) {
- iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
+ iov = kmalloc_array(nr_segs, sizeof(struct iovec), GFP_KERNEL);
if (iov == NULL) {
ret = -ENOMEM;
goto out;
@@ -849,7 +849,7 @@ ssize_t compat_rw_copy_check_uvector(int type,
goto out;
if (nr_segs > fast_segs) {
ret = -ENOMEM;
- iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
+ iov = kmalloc_array(nr_segs, sizeof(struct iovec), GFP_KERNEL);
if (iov == NULL)
goto out;
}
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index edc8ef78b63f..bf708ac287b4 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -1456,7 +1456,7 @@ int reiserfs_init_bitmap_cache(struct super_block *sb)
struct reiserfs_bitmap_info *bitmap;
unsigned int bmap_nr = reiserfs_bmap_count(sb);
- bitmap = vmalloc(sizeof(*bitmap) * bmap_nr);
+ bitmap = vmalloc(array_size(bmap_nr, sizeof(*bitmap)));
if (bitmap == NULL)
return -ENOMEM;
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index b13fc024d2ee..132ec4406ed0 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1044,7 +1044,8 @@ research:
if (blocks_needed == 1) {
un = &unf_single;
} else {
- un = kzalloc(min(blocks_needed, max_to_insert) * UNFM_P_SIZE, GFP_NOFS);
+ un = kcalloc(min(blocks_needed, max_to_insert),
+ UNFM_P_SIZE, GFP_NOFS);
if (!un) {
un = &unf_single;
blocks_needed = 1;
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 23148c3ed675..52eb5d293a34 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -350,7 +350,8 @@ static struct reiserfs_journal_cnode *allocate_cnodes(int num_cnodes)
if (num_cnodes <= 0) {
return NULL;
}
- head = vzalloc(num_cnodes * sizeof(struct reiserfs_journal_cnode));
+ head = vzalloc(array_size(num_cnodes,
+ sizeof(struct reiserfs_journal_cnode)));
if (!head) {
return NULL;
}
@@ -2192,10 +2193,12 @@ static int journal_read_transaction(struct super_block *sb,
* now we know we've got a good transaction, and it was
* inside the valid time ranges
*/
- log_blocks = kmalloc(get_desc_trans_len(desc) *
- sizeof(struct buffer_head *), GFP_NOFS);
- real_blocks = kmalloc(get_desc_trans_len(desc) *
- sizeof(struct buffer_head *), GFP_NOFS);
+ log_blocks = kmalloc_array(get_desc_trans_len(desc),
+ sizeof(struct buffer_head *),
+ GFP_NOFS);
+ real_blocks = kmalloc_array(get_desc_trans_len(desc),
+ sizeof(struct buffer_head *),
+ GFP_NOFS);
if (!log_blocks || !real_blocks) {
brelse(c_bh);
brelse(d_bh);
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 5089dac02660..97f3fc4fdd79 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -1316,7 +1316,7 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
int jbegin_count;
umode_t old_inode_mode;
unsigned long savelink = 1;
- struct timespec ctime;
+ struct timespec64 ctime;
if (flags & ~RENAME_NOREPLACE)
return -EINVAL;
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c
index 6052d323bc9a..8096c74c38ac 100644
--- a/fs/reiserfs/resize.c
+++ b/fs/reiserfs/resize.c
@@ -120,7 +120,8 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
* array of bitmap block pointers
*/
bitmap =
- vzalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new);
+ vzalloc(array_size(bmap_nr_new,
+ sizeof(struct reiserfs_bitmap_info)));
if (!bitmap) {
/*
* Journal bitmaps are still supersized, but the
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 5dbf5324bdda..ff94fad477e4 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -451,10 +451,10 @@ int reiserfs_commit_write(struct file *f, struct page *page,
static void update_ctime(struct inode *inode)
{
- struct timespec now = current_time(inode);
+ struct timespec64 now = current_time(inode);
if (inode_unhashed(inode) || !inode->i_nlink ||
- timespec_equal(&inode->i_ctime, &now))
+ timespec64_equal(&inode->i_ctime, &now))
return;
inode->i_ctime = current_time(inode);
diff --git a/fs/select.c b/fs/select.c
index bc3cc0f98896..317891ff8165 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -1236,7 +1236,7 @@ static int compat_core_sys_select(int n, compat_ulong_t __user *inp,
size = FDS_BYTES(n);
bits = stack_fds;
if (size > sizeof(stack_fds) / 6) {
- bits = kmalloc(6 * size, GFP_KERNEL);
+ bits = kmalloc_array(6, size, GFP_KERNEL);
ret = -ENOMEM;
if (!bits)
goto out_nofds;
diff --git a/fs/signalfd.c b/fs/signalfd.c
index cbb42f77a2bd..4fcd1498acf5 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -259,10 +259,8 @@ static const struct file_operations signalfd_fops = {
.llseek = noop_llseek,
};
-static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
- int flags)
+static int do_signalfd4(int ufd, sigset_t *mask, int flags)
{
- sigset_t sigmask;
struct signalfd_ctx *ctx;
/* Check the SFD_* constants for consistency. */
@@ -272,18 +270,15 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK))
return -EINVAL;
- if (sizemask != sizeof(sigset_t) ||
- copy_from_user(&sigmask, user_mask, sizeof(sigmask)))
- return -EINVAL;
- sigdelsetmask(&sigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
- signotset(&sigmask);
+ sigdelsetmask(mask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+ signotset(mask);
if (ufd == -1) {
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
- ctx->sigmask = sigmask;
+ ctx->sigmask = *mask;
/*
* When we call this, the initialization must be complete, since
@@ -303,7 +298,7 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
return -EINVAL;
}
spin_lock_irq(&current->sighand->siglock);
- ctx->sigmask = sigmask;
+ ctx->sigmask = *mask;
spin_unlock_irq(&current->sighand->siglock);
wake_up(&current->sighand->signalfd_wqh);
@@ -316,46 +311,51 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask,
size_t, sizemask, int, flags)
{
- return do_signalfd4(ufd, user_mask, sizemask, flags);
+ sigset_t mask;
+
+ if (sizemask != sizeof(sigset_t) ||
+ copy_from_user(&mask, user_mask, sizeof(mask)))
+ return -EINVAL;
+ return do_signalfd4(ufd, &mask, flags);
}
SYSCALL_DEFINE3(signalfd, int, ufd, sigset_t __user *, user_mask,
size_t, sizemask)
{
- return do_signalfd4(ufd, user_mask, sizemask, 0);
+ sigset_t mask;
+
+ if (sizemask != sizeof(sigset_t) ||
+ copy_from_user(&mask, user_mask, sizeof(mask)))
+ return -EINVAL;
+ return do_signalfd4(ufd, &mask, 0);
}
#ifdef CONFIG_COMPAT
static long do_compat_signalfd4(int ufd,
- const compat_sigset_t __user *sigmask,
+ const compat_sigset_t __user *user_mask,
compat_size_t sigsetsize, int flags)
{
- sigset_t tmp;
- sigset_t __user *ksigmask;
+ sigset_t mask;
if (sigsetsize != sizeof(compat_sigset_t))
return -EINVAL;
- if (get_compat_sigset(&tmp, sigmask))
- return -EFAULT;
- ksigmask = compat_alloc_user_space(sizeof(sigset_t));
- if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
+ if (get_compat_sigset(&mask, user_mask))
return -EFAULT;
-
- return do_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags);
+ return do_signalfd4(ufd, &mask, flags);
}
COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd,
- const compat_sigset_t __user *, sigmask,
+ const compat_sigset_t __user *, user_mask,
compat_size_t, sigsetsize,
int, flags)
{
- return do_compat_signalfd4(ufd, sigmask, sigsetsize, flags);
+ return do_compat_signalfd4(ufd, user_mask, sigsetsize, flags);
}
COMPAT_SYSCALL_DEFINE3(signalfd, int, ufd,
- const compat_sigset_t __user *,sigmask,
+ const compat_sigset_t __user *, user_mask,
compat_size_t, sigsetsize)
{
- return do_compat_signalfd4(ufd, sigmask, sigsetsize, 0);
+ return do_compat_signalfd4(ufd, user_mask, sigsetsize, 0);
}
#endif
diff --git a/fs/splice.c b/fs/splice.c
index 005d09cf3fa8..b3daa971f597 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -259,8 +259,9 @@ int splice_grow_spd(const struct pipe_inode_info *pipe, struct splice_pipe_desc
if (buffers <= PIPE_DEF_BUFFERS)
return 0;
- spd->pages = kmalloc(buffers * sizeof(struct page *), GFP_KERNEL);
- spd->partial = kmalloc(buffers * sizeof(struct partial_page), GFP_KERNEL);
+ spd->pages = kmalloc_array(buffers, sizeof(struct page *), GFP_KERNEL);
+ spd->partial = kmalloc_array(buffers, sizeof(struct partial_page),
+ GFP_KERNEL);
if (spd->pages && spd->partial)
return 0;
@@ -395,7 +396,7 @@ static ssize_t default_file_splice_read(struct file *in, loff_t *ppos,
vec = __vec;
if (nr_pages > PIPE_DEF_BUFFERS) {
- vec = kmalloc(nr_pages * sizeof(struct kvec), GFP_KERNEL);
+ vec = kmalloc_array(nr_pages, sizeof(struct kvec), GFP_KERNEL);
if (unlikely(!vec)) {
res = -ENOMEM;
goto out;
@@ -1242,38 +1243,26 @@ static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
* For lack of a better implementation, implement vmsplice() to userspace
* as a simple copy of the pipes pages to the user iov.
*/
-static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
- unsigned long nr_segs, unsigned int flags)
+static long vmsplice_to_user(struct file *file, struct iov_iter *iter,
+ unsigned int flags)
{
- struct pipe_inode_info *pipe;
- struct splice_desc sd;
- long ret;
- struct iovec iovstack[UIO_FASTIOV];
- struct iovec *iov = iovstack;
- struct iov_iter iter;
+ struct pipe_inode_info *pipe = get_pipe_info(file);
+ struct splice_desc sd = {
+ .total_len = iov_iter_count(iter),
+ .flags = flags,
+ .u.data = iter
+ };
+ long ret = 0;
- pipe = get_pipe_info(file);
if (!pipe)
return -EBADF;
- ret = import_iovec(READ, uiov, nr_segs,
- ARRAY_SIZE(iovstack), &iov, &iter);
- if (ret < 0)
- return ret;
-
- sd.total_len = iov_iter_count(&iter);
- sd.len = 0;
- sd.flags = flags;
- sd.u.data = &iter;
- sd.pos = 0;
-
if (sd.total_len) {
pipe_lock(pipe);
ret = __splice_from_pipe(pipe, &sd, pipe_to_user);
pipe_unlock(pipe);
}
- kfree(iov);
return ret;
}
@@ -1282,14 +1271,11 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
* as splice-from-memory, where the regular splice is splice-from-file (or
* to file). In both cases the output is a pipe, naturally.
*/
-static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov,
- unsigned long nr_segs, unsigned int flags)
+static long vmsplice_to_pipe(struct file *file, struct iov_iter *iter,
+ unsigned int flags)
{
struct pipe_inode_info *pipe;
- struct iovec iovstack[UIO_FASTIOV];
- struct iovec *iov = iovstack;
- struct iov_iter from;
- long ret;
+ long ret = 0;
unsigned buf_flag = 0;
if (flags & SPLICE_F_GIFT)
@@ -1299,22 +1285,31 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov,
if (!pipe)
return -EBADF;
- ret = import_iovec(WRITE, uiov, nr_segs,
- ARRAY_SIZE(iovstack), &iov, &from);
- if (ret < 0)
- return ret;
-
pipe_lock(pipe);
ret = wait_for_space(pipe, flags);
if (!ret)
- ret = iter_to_pipe(&from, pipe, buf_flag);
+ ret = iter_to_pipe(iter, pipe, buf_flag);
pipe_unlock(pipe);
if (ret > 0)
wakeup_pipe_readers(pipe);
- kfree(iov);
return ret;
}
+static int vmsplice_type(struct fd f, int *type)
+{
+ if (!f.file)
+ return -EBADF;
+ if (f.file->f_mode & FMODE_WRITE) {
+ *type = WRITE;
+ } else if (f.file->f_mode & FMODE_READ) {
+ *type = READ;
+ } else {
+ fdput(f);
+ return -EBADF;
+ }
+ return 0;
+}
+
/*
* Note that vmsplice only really supports true splicing _from_ user memory
* to a pipe, not the other way around. Splicing from user memory is a simple
@@ -1331,57 +1326,69 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov,
* Currently we punt and implement it as a normal copy, see pipe_to_user().
*
*/
-static long do_vmsplice(int fd, const struct iovec __user *iov,
- unsigned long nr_segs, unsigned int flags)
+static long do_vmsplice(struct file *f, struct iov_iter *iter, unsigned int flags)
{
- struct fd f;
- long error;
-
if (unlikely(flags & ~SPLICE_F_ALL))
return -EINVAL;
- if (unlikely(nr_segs > UIO_MAXIOV))
- return -EINVAL;
- else if (unlikely(!nr_segs))
- return 0;
- error = -EBADF;
- f = fdget(fd);
- if (f.file) {
- if (f.file->f_mode & FMODE_WRITE)
- error = vmsplice_to_pipe(f.file, iov, nr_segs, flags);
- else if (f.file->f_mode & FMODE_READ)
- error = vmsplice_to_user(f.file, iov, nr_segs, flags);
-
- fdput(f);
- }
+ if (!iov_iter_count(iter))
+ return 0;
- return error;
+ if (iov_iter_rw(iter) == WRITE)
+ return vmsplice_to_pipe(f, iter, flags);
+ else
+ return vmsplice_to_user(f, iter, flags);
}
-SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, iov,
+SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov,
unsigned long, nr_segs, unsigned int, flags)
{
- return do_vmsplice(fd, iov, nr_segs, flags);
+ struct iovec iovstack[UIO_FASTIOV];
+ struct iovec *iov = iovstack;
+ struct iov_iter iter;
+ long error;
+ struct fd f;
+ int type;
+
+ f = fdget(fd);
+ error = vmsplice_type(f, &type);
+ if (error)
+ return error;
+
+ error = import_iovec(type, uiov, nr_segs,
+ ARRAY_SIZE(iovstack), &iov, &iter);
+ if (!error) {
+ error = do_vmsplice(f.file, &iter, flags);
+ kfree(iov);
+ }
+ fdput(f);
+ return error;
}
#ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, iov32,
unsigned int, nr_segs, unsigned int, flags)
{
- unsigned i;
- struct iovec __user *iov;
- if (nr_segs > UIO_MAXIOV)
- return -EINVAL;
- iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
- for (i = 0; i < nr_segs; i++) {
- struct compat_iovec v;
- if (get_user(v.iov_base, &iov32[i].iov_base) ||
- get_user(v.iov_len, &iov32[i].iov_len) ||
- put_user(compat_ptr(v.iov_base), &iov[i].iov_base) ||
- put_user(v.iov_len, &iov[i].iov_len))
- return -EFAULT;
+ struct iovec iovstack[UIO_FASTIOV];
+ struct iovec *iov = iovstack;
+ struct iov_iter iter;
+ long error;
+ struct fd f;
+ int type;
+
+ f = fdget(fd);
+ error = vmsplice_type(f, &type);
+ if (error)
+ return error;
+
+ error = compat_import_iovec(type, iov32, nr_segs,
+ ARRAY_SIZE(iovstack), &iov, &iter);
+ if (!error) {
+ error = do_vmsplice(f.file, &iter, flags);
+ kfree(iov);
}
- return do_vmsplice(fd, iov, nr_segs, flags);
+ fdput(f);
+ return error;
}
#endif
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 4e267cc21c77..9da224d4f2da 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1276,7 +1276,7 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
.dirtied_ino = 3 };
struct ubifs_budget_req ino_req = { .dirtied_ino = 1,
.dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) };
- struct timespec time;
+ struct timespec64 time;
unsigned int uninitialized_var(saved_nlink);
struct fscrypt_name old_nm, new_nm;
@@ -1504,7 +1504,7 @@ static int ubifs_xrename(struct inode *old_dir, struct dentry *old_dentry,
int sync = IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir);
struct inode *fst_inode = d_inode(old_dentry);
struct inode *snd_inode = d_inode(new_dentry);
- struct timespec time;
+ struct timespec64 time;
int err;
struct fscrypt_name fst_nm, snd_nm;
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 28b80713a163..fd7eb6fe9090 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1089,14 +1089,14 @@ static void do_attr_changes(struct inode *inode, const struct iattr *attr)
if (attr->ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
if (attr->ia_valid & ATTR_ATIME)
- inode->i_atime = timespec_trunc(attr->ia_atime,
- inode->i_sb->s_time_gran);
+ inode->i_atime = timespec64_trunc(attr->ia_atime,
+ inode->i_sb->s_time_gran);
if (attr->ia_valid & ATTR_MTIME)
- inode->i_mtime = timespec_trunc(attr->ia_mtime,
- inode->i_sb->s_time_gran);
+ inode->i_mtime = timespec64_trunc(attr->ia_mtime,
+ inode->i_sb->s_time_gran);
if (attr->ia_valid & ATTR_CTIME)
- inode->i_ctime = timespec_trunc(attr->ia_ctime,
- inode->i_sb->s_time_gran);
+ inode->i_ctime = timespec64_trunc(attr->ia_ctime,
+ inode->i_sb->s_time_gran);
if (attr->ia_valid & ATTR_MODE) {
umode_t mode = attr->ia_mode;
@@ -1367,8 +1367,9 @@ out:
static inline int mctime_update_needed(const struct inode *inode,
const struct timespec *now)
{
- if (!timespec_equal(&inode->i_mtime, now) ||
- !timespec_equal(&inode->i_ctime, now))
+ struct timespec64 now64 = timespec_to_timespec64(*now);
+ if (!timespec64_equal(&inode->i_mtime, &now64) ||
+ !timespec64_equal(&inode->i_ctime, &now64))
return 1;
return 0;
}
@@ -1380,7 +1381,7 @@ static inline int mctime_update_needed(const struct inode *inode,
*
* This function updates time of the inode.
*/
-int ubifs_update_time(struct inode *inode, struct timespec *time,
+int ubifs_update_time(struct inode *inode, struct timespec64 *time,
int flags)
{
struct ubifs_inode *ui = ubifs_inode(inode);
@@ -1424,7 +1425,7 @@ int ubifs_update_time(struct inode *inode, struct timespec *time,
*/
static int update_mctime(struct inode *inode)
{
- struct timespec now = current_time(inode);
+ struct timespec now = timespec64_to_timespec(current_time(inode));
struct ubifs_inode *ui = ubifs_inode(inode);
struct ubifs_info *c = inode->i_sb->s_fs_info;
@@ -1518,7 +1519,7 @@ static vm_fault_t ubifs_vm_page_mkwrite(struct vm_fault *vmf)
struct page *page = vmf->page;
struct inode *inode = file_inode(vmf->vma->vm_file);
struct ubifs_info *c = inode->i_sb->s_fs_info;
- struct timespec now = current_time(inode);
+ struct timespec now = timespec64_to_timespec(current_time(inode));
struct ubifs_budget_req req = { .new_page = 1 };
int err, update_time;
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index da8afdfccaa6..07b4956e0425 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -1282,10 +1282,11 @@ static int truncate_data_node(const struct ubifs_info *c, const struct inode *in
int *new_len)
{
void *buf;
- int err, dlen, compr_type, out_len, old_dlen;
+ int err, compr_type;
+ u32 dlen, out_len, old_dlen;
out_len = le32_to_cpu(dn->size);
- buf = kmalloc(out_len * WORST_COMPR_FACTOR, GFP_NOFS);
+ buf = kmalloc_array(out_len, WORST_COMPR_FACTOR, GFP_NOFS);
if (!buf)
return -ENOMEM;
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index 9a517109da0f..8e99dad18880 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -628,11 +628,12 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
/* Needed by 'ubifs_pack_lsave()' */
c->main_first = c->leb_cnt - *main_lebs;
- lsave = kmalloc(sizeof(int) * c->lsave_cnt, GFP_KERNEL);
+ lsave = kmalloc_array(c->lsave_cnt, sizeof(int), GFP_KERNEL);
pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_KERNEL);
nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_KERNEL);
buf = vmalloc(c->leb_size);
- ltab = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
+ ltab = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops),
+ c->lpt_lebs));
if (!pnode || !nnode || !buf || !ltab || !lsave) {
err = -ENOMEM;
goto out;
@@ -1626,7 +1627,8 @@ static int lpt_init_rd(struct ubifs_info *c)
{
int err, i;
- c->ltab = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
+ c->ltab = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops),
+ c->lpt_lebs));
if (!c->ltab)
return -ENOMEM;
@@ -1636,15 +1638,17 @@ static int lpt_init_rd(struct ubifs_info *c)
return -ENOMEM;
for (i = 0; i < LPROPS_HEAP_CNT; i++) {
- c->lpt_heap[i].arr = kmalloc(sizeof(void *) * LPT_HEAP_SZ,
- GFP_KERNEL);
+ c->lpt_heap[i].arr = kmalloc_array(LPT_HEAP_SZ,
+ sizeof(void *),
+ GFP_KERNEL);
if (!c->lpt_heap[i].arr)
return -ENOMEM;
c->lpt_heap[i].cnt = 0;
c->lpt_heap[i].max_cnt = LPT_HEAP_SZ;
}
- c->dirty_idx.arr = kmalloc(sizeof(void *) * LPT_HEAP_SZ, GFP_KERNEL);
+ c->dirty_idx.arr = kmalloc_array(LPT_HEAP_SZ, sizeof(void *),
+ GFP_KERNEL);
if (!c->dirty_idx.arr)
return -ENOMEM;
c->dirty_idx.cnt = 0;
@@ -1688,7 +1692,8 @@ static int lpt_init_wr(struct ubifs_info *c)
{
int err, i;
- c->ltab_cmt = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
+ c->ltab_cmt = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops),
+ c->lpt_lebs));
if (!c->ltab_cmt)
return -ENOMEM;
@@ -1697,7 +1702,7 @@ static int lpt_init_wr(struct ubifs_info *c)
return -ENOMEM;
if (c->big_lpt) {
- c->lsave = kmalloc(sizeof(int) * c->lsave_cnt, GFP_NOFS);
+ c->lsave = kmalloc_array(c->lsave_cnt, sizeof(int), GFP_NOFS);
if (!c->lsave)
return -ENOMEM;
err = read_lsave(c);
@@ -1939,8 +1944,8 @@ int ubifs_lpt_scan_nolock(struct ubifs_info *c, int start_lnum, int end_lnum,
return err;
}
- path = kmalloc(sizeof(struct lpt_scan_node) * (c->lpt_hght + 1),
- GFP_NOFS);
+ path = kmalloc_array(c->lpt_hght + 1, sizeof(struct lpt_scan_node),
+ GFP_NOFS);
if (!path)
return -ENOMEM;
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 6c397a389105..c5466c70d620 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1196,7 +1196,8 @@ static int mount_ubifs(struct ubifs_info *c)
* never exceed 64.
*/
err = -ENOMEM;
- c->bottom_up_buf = kmalloc(BOTTOM_UP_HEIGHT * sizeof(int), GFP_KERNEL);
+ c->bottom_up_buf = kmalloc_array(BOTTOM_UP_HEIGHT, sizeof(int),
+ GFP_KERNEL);
if (!c->bottom_up_buf)
goto out_free;
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index ba3d0e0f8615..4a21e7f75e7a 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -1104,8 +1104,9 @@ static struct ubifs_znode *dirty_cow_bottom_up(struct ubifs_info *c,
ubifs_assert(znode);
if (c->zroot.znode->level > BOTTOM_UP_HEIGHT) {
kfree(c->bottom_up_buf);
- c->bottom_up_buf = kmalloc(c->zroot.znode->level * sizeof(int),
- GFP_NOFS);
+ c->bottom_up_buf = kmalloc_array(c->zroot.znode->level,
+ sizeof(int),
+ GFP_NOFS);
if (!c->bottom_up_buf)
return ERR_PTR(-ENOMEM);
path = c->bottom_up_buf;
diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
index aa31f60220ef..a9df94ad46a3 100644
--- a/fs/ubifs/tnc_commit.c
+++ b/fs/ubifs/tnc_commit.c
@@ -366,7 +366,8 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt)
dbg_gc("%d znodes to write", cnt);
- c->gap_lebs = kmalloc(sizeof(int) * (c->lst.idx_lebs + 1), GFP_NOFS);
+ c->gap_lebs = kmalloc_array(c->lst.idx_lebs + 1, sizeof(int),
+ GFP_NOFS);
if (!c->gap_lebs)
return -ENOMEM;
@@ -674,7 +675,7 @@ static int alloc_idx_lebs(struct ubifs_info *c, int cnt)
dbg_cmt("need about %d empty LEBS for TNC commit", leb_cnt);
if (!leb_cnt)
return 0;
- c->ilebs = kmalloc(leb_cnt * sizeof(int), GFP_NOFS);
+ c->ilebs = kmalloc_array(leb_cnt, sizeof(int), GFP_NOFS);
if (!c->ilebs)
return -ENOMEM;
for (i = 0; i < leb_cnt; i++) {
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 209d6369ae71..04bf84d71e7b 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1738,7 +1738,7 @@ int ubifs_calc_dark(const struct ubifs_info *c, int spc);
int ubifs_fsync(struct file *file, loff_t start, loff_t end, int datasync);
int ubifs_setattr(struct dentry *dentry, struct iattr *attr);
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
-int ubifs_update_time(struct inode *inode, struct timespec *time, int flags);
+int ubifs_update_time(struct inode *inode, struct timespec64 *time, int flags);
#endif
/* dir.c */
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index b7a0d4b4bda1..56569023783b 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -124,8 +124,8 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode)
iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
else
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
- inode->i_mtime = inode->i_atime = inode->i_ctime =
- iinfo->i_crtime = current_time(inode);
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ iinfo->i_crtime = timespec64_to_timespec(inode->i_mtime);
if (unlikely(insert_inode_locked(inode) < 0)) {
make_bad_inode(inode);
iput(inode);
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index c80765d62f7e..7f39d17352c9 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1271,6 +1271,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
struct udf_inode_info *iinfo = UDF_I(inode);
struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
struct kernel_lb_addr *iloc = &iinfo->i_location;
+ struct timespec ts;
unsigned int link_count;
unsigned int indirections = 0;
int bs = inode->i_sb->s_blocksize;
@@ -1443,15 +1444,12 @@ reread:
inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
(inode->i_sb->s_blocksize_bits - 9);
- if (!udf_disk_stamp_to_time(&inode->i_atime, fe->accessTime))
- inode->i_atime = sbi->s_record_time;
-
- if (!udf_disk_stamp_to_time(&inode->i_mtime,
- fe->modificationTime))
- inode->i_mtime = sbi->s_record_time;
-
- if (!udf_disk_stamp_to_time(&inode->i_ctime, fe->attrTime))
- inode->i_ctime = sbi->s_record_time;
+ udf_disk_stamp_to_time(&ts, fe->accessTime);
+ inode->i_atime = timespec_to_timespec64(ts);
+ udf_disk_stamp_to_time(&ts, fe->modificationTime);
+ inode->i_mtime = timespec_to_timespec64(ts);
+ udf_disk_stamp_to_time(&ts, fe->attrTime);
+ inode->i_ctime = timespec_to_timespec64(ts);
iinfo->i_unique = le64_to_cpu(fe->uniqueID);
iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr);
@@ -1461,18 +1459,13 @@ reread:
inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
(inode->i_sb->s_blocksize_bits - 9);
- if (!udf_disk_stamp_to_time(&inode->i_atime, efe->accessTime))
- inode->i_atime = sbi->s_record_time;
-
- if (!udf_disk_stamp_to_time(&inode->i_mtime,
- efe->modificationTime))
- inode->i_mtime = sbi->s_record_time;
-
- if (!udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime))
- iinfo->i_crtime = sbi->s_record_time;
-
- if (!udf_disk_stamp_to_time(&inode->i_ctime, efe->attrTime))
- inode->i_ctime = sbi->s_record_time;
+ udf_disk_stamp_to_time(&ts, efe->accessTime);
+ inode->i_atime = timespec_to_timespec64(ts);
+ udf_disk_stamp_to_time(&ts, efe->modificationTime);
+ inode->i_mtime = timespec_to_timespec64(ts);
+ udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime);
+ udf_disk_stamp_to_time(&ts, efe->attrTime);
+ inode->i_ctime = timespec_to_timespec64(ts);
iinfo->i_unique = le64_to_cpu(efe->uniqueID);
iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr);
@@ -1722,9 +1715,12 @@ static int udf_update_inode(struct inode *inode, int do_sync)
inode->i_sb->s_blocksize - sizeof(struct fileEntry));
fe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);
- udf_time_to_disk_stamp(&fe->accessTime, inode->i_atime);
- udf_time_to_disk_stamp(&fe->modificationTime, inode->i_mtime);
- udf_time_to_disk_stamp(&fe->attrTime, inode->i_ctime);
+ udf_time_to_disk_stamp(&fe->accessTime,
+ timespec64_to_timespec(inode->i_atime));
+ udf_time_to_disk_stamp(&fe->modificationTime,
+ timespec64_to_timespec(inode->i_mtime));
+ udf_time_to_disk_stamp(&fe->attrTime,
+ timespec64_to_timespec(inode->i_ctime));
memset(&(fe->impIdent), 0, sizeof(struct regid));
strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
@@ -1743,14 +1739,17 @@ static int udf_update_inode(struct inode *inode, int do_sync)
efe->objectSize = cpu_to_le64(inode->i_size);
efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);
- udf_adjust_time(iinfo, inode->i_atime);
- udf_adjust_time(iinfo, inode->i_mtime);
- udf_adjust_time(iinfo, inode->i_ctime);
+ udf_adjust_time(iinfo, timespec64_to_timespec(inode->i_atime));
+ udf_adjust_time(iinfo, timespec64_to_timespec(inode->i_mtime));
+ udf_adjust_time(iinfo, timespec64_to_timespec(inode->i_ctime));
- udf_time_to_disk_stamp(&efe->accessTime, inode->i_atime);
- udf_time_to_disk_stamp(&efe->modificationTime, inode->i_mtime);
+ udf_time_to_disk_stamp(&efe->accessTime,
+ timespec64_to_timespec(inode->i_atime));
+ udf_time_to_disk_stamp(&efe->modificationTime,
+ timespec64_to_timespec(inode->i_mtime));
udf_time_to_disk_stamp(&efe->createTime, iinfo->i_crtime);
- udf_time_to_disk_stamp(&efe->attrTime, inode->i_ctime);
+ udf_time_to_disk_stamp(&efe->attrTime,
+ timespec64_to_timespec(inode->i_ctime));
memset(&(efe->impIdent), 0, sizeof(efe->impIdent));
strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 0d27d41f5c6e..0c504c8031d3 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -862,6 +862,9 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
struct buffer_head *bh;
uint16_t ident;
int ret = -ENOMEM;
+#ifdef UDFFS_DEBUG
+ struct timestamp *ts;
+#endif
outstr = kmalloc(128, GFP_NOFS);
if (!outstr)
@@ -880,15 +883,15 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
pvoldesc = (struct primaryVolDesc *)bh->b_data;
- if (udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time,
- pvoldesc->recordingDateAndTime)) {
+ udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time,
+ pvoldesc->recordingDateAndTime);
#ifdef UDFFS_DEBUG
- struct timestamp *ts = &pvoldesc->recordingDateAndTime;
- udf_debug("recording time %04u/%02u/%02u %02u:%02u (%x)\n",
- le16_to_cpu(ts->year), ts->month, ts->day, ts->hour,
- ts->minute, le16_to_cpu(ts->typeAndTimezone));
+ ts = &pvoldesc->recordingDateAndTime;
+ udf_debug("recording time %04u/%02u/%02u %02u:%02u (%x)\n",
+ le16_to_cpu(ts->year), ts->month, ts->day, ts->hour,
+ ts->minute, le16_to_cpu(ts->typeAndTimezone));
#endif
- }
+
ret = udf_dstrCS0toChar(sb, outstr, 31, pvoldesc->volIdent, 32);
if (ret < 0)
@@ -1585,7 +1588,7 @@ static struct udf_vds_record *handle_partition_descriptor(
struct udf_vds_record *new_loc;
unsigned int new_size = ALIGN(partnum, PART_DESC_ALLOC_STEP);
- new_loc = kzalloc(sizeof(*new_loc) * new_size, GFP_KERNEL);
+ new_loc = kcalloc(new_size, sizeof(*new_loc), GFP_KERNEL);
if (!new_loc)
return ERR_PTR(-ENOMEM);
memcpy(new_loc, data->part_descs_loc,
@@ -1644,8 +1647,9 @@ static noinline int udf_process_sequence(
memset(data.vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
data.size_part_descs = PART_DESC_ALLOC_STEP;
- data.part_descs_loc = kzalloc(sizeof(*data.part_descs_loc) *
- data.size_part_descs, GFP_KERNEL);
+ data.part_descs_loc = kcalloc(data.size_part_descs,
+ sizeof(*data.part_descs_loc),
+ GFP_KERNEL);
if (!data.part_descs_loc)
return -ENOMEM;
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index fc8d1b3384d2..bae311b59400 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -253,8 +253,8 @@ extern struct long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int);
extern struct short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int);
/* udftime.c */
-extern struct timespec *udf_disk_stamp_to_time(struct timespec *dest,
+extern void udf_disk_stamp_to_time(struct timespec *dest,
struct timestamp src);
-extern struct timestamp *udf_time_to_disk_stamp(struct timestamp *dest, struct timespec src);
+extern void udf_time_to_disk_stamp(struct timestamp *dest, struct timespec src);
#endif /* __UDF_DECL_H */
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c
index 0927a4b2ecaf..67b33ac5d41b 100644
--- a/fs/udf/udftime.c
+++ b/fs/udf/udftime.c
@@ -40,7 +40,7 @@
#include <linux/kernel.h>
#include <linux/time.h>
-struct timespec *
+void
udf_disk_stamp_to_time(struct timespec *dest, struct timestamp src)
{
u16 typeAndTimezone = le16_to_cpu(src.typeAndTimezone);
@@ -67,10 +67,9 @@ udf_disk_stamp_to_time(struct timespec *dest, struct timestamp src)
* recorded with bogus sub-second values.
*/
dest->tv_nsec %= NSEC_PER_SEC;
- return dest;
}
-struct timestamp *
+void
udf_time_to_disk_stamp(struct timestamp *dest, struct timespec ts)
{
long seconds;
@@ -79,9 +78,6 @@ udf_time_to_disk_stamp(struct timestamp *dest, struct timespec ts)
offset = -sys_tz.tz_minuteswest;
- if (!dest)
- return NULL;
-
dest->typeAndTimezone = cpu_to_le16(0x1000 | (offset & 0x0FFF));
seconds = ts.tv_sec + offset * 60;
@@ -97,7 +93,6 @@ udf_time_to_disk_stamp(struct timestamp *dest, struct timespec ts)
dest->centiseconds * 10000) / 100;
dest->microseconds = (ts.tv_nsec / 1000 - dest->centiseconds * 10000 -
dest->hundredsOfMicroseconds * 100);
- return dest;
}
/* EOF */
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 8254b8b3690f..488088141451 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -541,7 +541,9 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
* Read cylinder group (we read only first fragment from block
* at this time) and prepare internal data structures for cg caching.
*/
- if (!(sbi->s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_NOFS)))
+ sbi->s_ucg = kmalloc_array(uspi->s_ncg, sizeof(struct buffer_head *),
+ GFP_NOFS);
+ if (!sbi->s_ucg)
goto failed;
for (i = 0; i < uspi->s_ncg; i++)
sbi->s_ucg[i] = NULL;
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index e8d67a443bd7..2f3f75a7f180 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -1,20 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
#
# Copyright (c) 2000-2005 Silicon Graphics, Inc.
# All Rights Reserved.
#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it would be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
ccflags-y += -I$(src) # needed for trace events
ccflags-y += -I$(src)/libxfs
@@ -62,6 +50,7 @@ xfs-y += $(addprefix libxfs/, \
xfs_sb.o \
xfs_symlink_remote.o \
xfs_trans_resv.o \
+ xfs_types.o \
)
# xfs_rtbitmap is shared with libxfs
xfs-$(CONFIG_XFS_RT) += $(addprefix libxfs/, \
diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c
index 7bace03dc9dc..fdd9d6ede25c 100644
--- a/fs/xfs/kmem.c
+++ b/fs/xfs/kmem.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/mm.h>
#include <linux/sched/mm.h>
diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h
index 6023b594ead7..8e6b3ba81c03 100644
--- a/fs/xfs/kmem.h
+++ b/fs/xfs/kmem.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SUPPORT_KMEM_H__
#define __XFS_SUPPORT_KMEM_H__
diff --git a/fs/xfs/libxfs/xfs_ag_resv.c b/fs/xfs/libxfs/xfs_ag_resv.c
index 03885a968de8..84db76e0e3e3 100644
--- a/fs/xfs/libxfs/xfs_ag_resv.c
+++ b/fs/xfs/libxfs/xfs_ag_resv.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_ag_resv.h b/fs/xfs/libxfs/xfs_ag_resv.h
index 938f2f96c5e8..4619b554ee90 100644
--- a/fs/xfs/libxfs/xfs_ag_resv.h
+++ b/fs/xfs/libxfs/xfs_ag_resv.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_AG_RESV_H__
#define __XFS_AG_RESV_H__
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index dc9dd3805d97..eef466260d43 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -227,15 +215,37 @@ xfs_alloc_get_rec(
xfs_extlen_t *len, /* output: length of extent */
int *stat) /* output: success/failure */
{
+ struct xfs_mount *mp = cur->bc_mp;
+ xfs_agnumber_t agno = cur->bc_private.a.agno;
union xfs_btree_rec *rec;
int error;
error = xfs_btree_get_rec(cur, &rec, stat);
- if (!error && *stat == 1) {
- *bno = be32_to_cpu(rec->alloc.ar_startblock);
- *len = be32_to_cpu(rec->alloc.ar_blockcount);
- }
- return error;
+ if (error || !(*stat))
+ return error;
+ if (rec->alloc.ar_blockcount == 0)
+ goto out_bad_rec;
+
+ *bno = be32_to_cpu(rec->alloc.ar_startblock);
+ *len = be32_to_cpu(rec->alloc.ar_blockcount);
+
+ /* check for valid extent range, including overflow */
+ if (!xfs_verify_agbno(mp, agno, *bno))
+ goto out_bad_rec;
+ if (*bno > *bno + *len)
+ goto out_bad_rec;
+ if (!xfs_verify_agbno(mp, agno, *bno + *len - 1))
+ goto out_bad_rec;
+
+ return 0;
+
+out_bad_rec:
+ xfs_warn(mp,
+ "%s Freespace BTree record corruption in AG %d detected!",
+ cur->bc_btnum == XFS_BTNUM_BNO ? "Block" : "Size", agno);
+ xfs_warn(mp,
+ "start block 0x%x block count 0x%x", *bno, *len);
+ return -EFSCORRUPTED;
}
/*
@@ -3113,55 +3123,6 @@ xfs_alloc_query_all(
return xfs_btree_query_all(cur, xfs_alloc_query_range_helper, &query);
}
-/* Find the size of the AG, in blocks. */
-xfs_agblock_t
-xfs_ag_block_count(
- struct xfs_mount *mp,
- xfs_agnumber_t agno)
-{
- ASSERT(agno < mp->m_sb.sb_agcount);
-
- if (agno < mp->m_sb.sb_agcount - 1)
- return mp->m_sb.sb_agblocks;
- return mp->m_sb.sb_dblocks - (agno * mp->m_sb.sb_agblocks);
-}
-
-/*
- * Verify that an AG block number pointer neither points outside the AG
- * nor points at static metadata.
- */
-bool
-xfs_verify_agbno(
- struct xfs_mount *mp,
- xfs_agnumber_t agno,
- xfs_agblock_t agbno)
-{
- xfs_agblock_t eoag;
-
- eoag = xfs_ag_block_count(mp, agno);
- if (agbno >= eoag)
- return false;
- if (agbno <= XFS_AGFL_BLOCK(mp))
- return false;
- return true;
-}
-
-/*
- * Verify that an FS block number pointer neither points outside the
- * filesystem nor points at static AG metadata.
- */
-bool
-xfs_verify_fsbno(
- struct xfs_mount *mp,
- xfs_fsblock_t fsbno)
-{
- xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, fsbno);
-
- if (agno >= mp->m_sb.sb_agcount)
- return false;
- return xfs_verify_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno));
-}
-
/* Is there a record covering a given extent? */
int
xfs_alloc_has_record(
diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h
index 0747adcd57d6..e716c993ac4c 100644
--- a/fs/xfs/libxfs/xfs_alloc.h
+++ b/fs/xfs/libxfs/xfs_alloc.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ALLOC_H__
#define __XFS_ALLOC_H__
@@ -254,10 +242,6 @@ int xfs_alloc_query_range(struct xfs_btree_cur *cur,
xfs_alloc_query_range_fn fn, void *priv);
int xfs_alloc_query_all(struct xfs_btree_cur *cur, xfs_alloc_query_range_fn fn,
void *priv);
-xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
-bool xfs_verify_agbno(struct xfs_mount *mp, xfs_agnumber_t agno,
- xfs_agblock_t agbno);
-bool xfs_verify_fsbno(struct xfs_mount *mp, xfs_fsblock_t fsbno);
int xfs_alloc_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
xfs_extlen_t len, bool *exist);
diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c
index 18aec7a0e599..4e59cc8a2802 100644
--- a/fs/xfs/libxfs/xfs_alloc_btree.c
+++ b/fs/xfs/libxfs/xfs_alloc_btree.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -242,7 +230,6 @@ xfs_allocbt_init_ptr_from_cur(
struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno));
- ASSERT(agf->agf_roots[cur->bc_btnum] != 0);
ptr->s = agf->agf_roots[cur->bc_btnum];
}
diff --git a/fs/xfs/libxfs/xfs_alloc_btree.h b/fs/xfs/libxfs/xfs_alloc_btree.h
index 2fd54728871c..c9305ebb69f6 100644
--- a/fs/xfs/libxfs/xfs_alloc_btree.h
+++ b/fs/xfs/libxfs/xfs_alloc_btree.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ALLOC_BTREE_H__
#define __XFS_ALLOC_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index c3d02a66d39d..99590f61d624 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index 2135b8e67dcc..76e90046731c 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -477,7 +465,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
* A data fork btree root must have space for at least
* MINDBTPTRS key/ptr pairs if the data fork is small or empty.
*/
- minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
+ minforkoff = max(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
minforkoff = roundup(minforkoff, 8) >> 3;
/* attr fork btree root can have at least this many key/ptr pairs */
@@ -803,9 +791,8 @@ xfs_attr_shortform_to_leaf(
ASSERT(blkno == 0);
error = xfs_attr3_leaf_create(args, blkno, &bp);
if (error) {
- error = xfs_da_shrink_inode(args, 0, bp);
- bp = NULL;
- if (error)
+ /* xfs_attr3_leaf_create may not have instantiated a block */
+ if (bp && (xfs_da_shrink_inode(args, 0, bp) != 0))
goto out;
xfs_idata_realloc(dp, size, XFS_ATTR_FORK); /* try to put */
memcpy(ifp->if_u1.if_data, tmpbuffer, size); /* it back */
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.h b/fs/xfs/libxfs/xfs_attr_leaf.h
index 4da08af5b134..7b74e18becff 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.h
+++ b/fs/xfs/libxfs/xfs_attr_leaf.h
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ATTR_LEAF_H__
#define __XFS_ATTR_LEAF_H__
diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c
index 83a6d3c7f872..bf2e0371149b 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.c
+++ b/fs/xfs/libxfs/xfs_attr_remote.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_attr_remote.h b/fs/xfs/libxfs/xfs_attr_remote.h
index 5a9acfa156d7..9d20b66ad379 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.h
+++ b/fs/xfs/libxfs/xfs_attr_remote.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ATTR_REMOTE_H__
#define __XFS_ATTR_REMOTE_H__
diff --git a/fs/xfs/libxfs/xfs_attr_sf.h b/fs/xfs/libxfs/xfs_attr_sf.h
index afd684ae3136..aafa4fe70624 100644
--- a/fs/xfs/libxfs/xfs_attr_sf.h
+++ b/fs/xfs/libxfs/xfs_attr_sf.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ATTR_SF_H__
#define __XFS_ATTR_SF_H__
diff --git a/fs/xfs/libxfs/xfs_bit.c b/fs/xfs/libxfs/xfs_bit.c
index 0a94cce5ea35..40ce5f3094d1 100644
--- a/fs/xfs/libxfs/xfs_bit.c
+++ b/fs/xfs/libxfs/xfs_bit.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_log_format.h"
diff --git a/fs/xfs/libxfs/xfs_bit.h b/fs/xfs/libxfs/xfs_bit.h
index 61c6b2025d0c..99017b8df292 100644
--- a/fs/xfs/libxfs/xfs_bit.h
+++ b/fs/xfs/libxfs/xfs_bit.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BIT_H__
#define __XFS_BIT_H__
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 7b0e2b551e23..01628f0c9a0c 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -1248,7 +1236,6 @@ xfs_iread_extents(
num_recs = xfs_btree_get_numrecs(block);
if (unlikely(i + num_recs > nextents)) {
- ASSERT(i + num_recs <= nextents);
xfs_warn(ip->i_mount,
"corrupt dinode %Lu, (btree extents).",
(unsigned long long) ip->i_ino);
@@ -2936,7 +2923,7 @@ xfs_bmap_extsize_align(
* perform this alignment, or if a truncate shot us in the
* foot.
*/
- temp = do_mod(orig_off, extsz);
+ div_u64_rem(orig_off, extsz, &temp);
if (temp) {
align_alen += temp;
align_off -= temp;
@@ -3480,7 +3467,7 @@ xfs_bmap_btalloc(
xfs_rmap_skip_owner_update(&args.oinfo);
/* Trim the allocation back to the maximum an AG can fit. */
- args.maxlen = MIN(ap->length, mp->m_ag_max_usable);
+ args.maxlen = min(ap->length, mp->m_ag_max_usable);
args.firstblock = *ap->firstblock;
blen = 0;
if (nullfb) {
@@ -3510,15 +3497,17 @@ xfs_bmap_btalloc(
/* apply extent size hints if obtained earlier */
if (align) {
args.prod = align;
- if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod)))
- args.mod = (xfs_extlen_t)(args.prod - args.mod);
+ div_u64_rem(ap->offset, args.prod, &args.mod);
+ if (args.mod)
+ args.mod = args.prod - args.mod;
} else if (mp->m_sb.sb_blocksize >= PAGE_SIZE) {
args.prod = 1;
args.mod = 0;
} else {
args.prod = PAGE_SIZE >> mp->m_sb.sb_blocklog;
- if ((args.mod = (xfs_extlen_t)(do_mod(ap->offset, args.prod))))
- args.mod = (xfs_extlen_t)(args.prod - args.mod);
+ div_u64_rem(ap->offset, args.prod, &args.mod);
+ if (args.mod)
+ args.mod = args.prod - args.mod;
}
/*
* If we are not low on available data blocks, and the
@@ -4966,13 +4955,15 @@ xfs_bmap_del_extent_real(
if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
xfs_fsblock_t bno;
xfs_filblks_t len;
+ xfs_extlen_t mod;
+
+ bno = div_u64_rem(del->br_startblock, mp->m_sb.sb_rextsize,
+ &mod);
+ ASSERT(mod == 0);
+ len = div_u64_rem(del->br_blockcount, mp->m_sb.sb_rextsize,
+ &mod);
+ ASSERT(mod == 0);
- ASSERT(do_mod(del->br_blockcount, mp->m_sb.sb_rextsize) == 0);
- ASSERT(do_mod(del->br_startblock, mp->m_sb.sb_rextsize) == 0);
- bno = del->br_startblock;
- len = del->br_blockcount;
- do_div(bno, mp->m_sb.sb_rextsize);
- do_div(len, mp->m_sb.sb_rextsize);
error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len);
if (error)
goto done;
@@ -5309,9 +5300,12 @@ __xfs_bunmapi(
del.br_blockcount = max_len;
}
+ if (!isrt)
+ goto delete;
+
sum = del.br_startblock + del.br_blockcount;
- if (isrt &&
- (mod = do_mod(sum, mp->m_sb.sb_rextsize))) {
+ div_u64_rem(sum, mp->m_sb.sb_rextsize, &mod);
+ if (mod) {
/*
* Realtime extent not lined up at the end.
* The extent could have been split into written
@@ -5358,7 +5352,8 @@ __xfs_bunmapi(
goto error0;
goto nodelete;
}
- if (isrt && (mod = do_mod(del.br_startblock, mp->m_sb.sb_rextsize))) {
+ div_u64_rem(del.br_startblock, mp->m_sb.sb_rextsize, &mod);
+ if (mod) {
/*
* Realtime extent is lined up at the end but not
* at the front. We'll get rid of full extents if
@@ -5427,6 +5422,7 @@ __xfs_bunmapi(
}
}
+delete:
if (wasdel) {
error = xfs_bmap_del_extent_delay(ip, whichfork, &icur,
&got, &del);
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index 2c233f9f1a26..99dddbd0fcc6 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BMAP_H__
#define __XFS_BMAP_H__
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index ac9d4aeedb09..e1a2d9ceb615 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.h b/fs/xfs/libxfs/xfs_bmap_btree.h
index fb3cd2d9e0f8..29b407d053b4 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.h
+++ b/fs/xfs/libxfs/xfs_bmap_btree.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BMAP_BTREE_H__
#define __XFS_BMAP_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index c825c8182b30..34c6d7bd4d18 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -234,7 +222,6 @@ xfs_btree_check_sptr(
return xfs_verify_agbno(cur->bc_mp, cur->bc_private.a.agno, agbno);
}
-#ifdef DEBUG
/*
* Check that a given (indexed) btree pointer at a certain level of a
* btree is valid and doesn't point past where it should.
@@ -247,17 +234,31 @@ xfs_btree_check_ptr(
int level)
{
if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
- XFS_WANT_CORRUPTED_RETURN(cur->bc_mp,
- xfs_btree_check_lptr(cur,
- be64_to_cpu((&ptr->l)[index]), level));
+ if (xfs_btree_check_lptr(cur, be64_to_cpu((&ptr->l)[index]),
+ level))
+ return 0;
+ xfs_err(cur->bc_mp,
+"Inode %llu fork %d: Corrupt btree %d pointer at level %d index %d.",
+ cur->bc_private.b.ip->i_ino,
+ cur->bc_private.b.whichfork, cur->bc_btnum,
+ level, index);
} else {
- XFS_WANT_CORRUPTED_RETURN(cur->bc_mp,
- xfs_btree_check_sptr(cur,
- be32_to_cpu((&ptr->s)[index]), level));
+ if (xfs_btree_check_sptr(cur, be32_to_cpu((&ptr->s)[index]),
+ level))
+ return 0;
+ xfs_err(cur->bc_mp,
+"AG %u: Corrupt btree %d pointer at level %d index %d.",
+ cur->bc_private.a.agno, cur->bc_btnum,
+ level, index);
}
- return 0;
+ return -EFSCORRUPTED;
}
+
+#ifdef DEBUG
+# define xfs_btree_debug_check_ptr xfs_btree_check_ptr
+#else
+# define xfs_btree_debug_check_ptr(...) (0)
#endif
/*
@@ -988,22 +989,30 @@ xfs_btree_readahead(
return xfs_btree_readahead_sblock(cur, lr, block);
}
-STATIC xfs_daddr_t
+STATIC int
xfs_btree_ptr_to_daddr(
struct xfs_btree_cur *cur,
- union xfs_btree_ptr *ptr)
+ union xfs_btree_ptr *ptr,
+ xfs_daddr_t *daddr)
{
- if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
- ASSERT(ptr->l != cpu_to_be64(NULLFSBLOCK));
+ xfs_fsblock_t fsbno;
+ xfs_agblock_t agbno;
+ int error;
- return XFS_FSB_TO_DADDR(cur->bc_mp, be64_to_cpu(ptr->l));
- } else {
- ASSERT(cur->bc_private.a.agno != NULLAGNUMBER);
- ASSERT(ptr->s != cpu_to_be32(NULLAGBLOCK));
+ error = xfs_btree_check_ptr(cur, ptr, 0, 1);
+ if (error)
+ return error;
- return XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno,
- be32_to_cpu(ptr->s));
+ if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
+ fsbno = be64_to_cpu(ptr->l);
+ *daddr = XFS_FSB_TO_DADDR(cur->bc_mp, fsbno);
+ } else {
+ agbno = be32_to_cpu(ptr->s);
+ *daddr = XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno,
+ agbno);
}
+
+ return 0;
}
/*
@@ -1018,8 +1027,11 @@ xfs_btree_readahead_ptr(
union xfs_btree_ptr *ptr,
xfs_extlen_t count)
{
- xfs_buf_readahead(cur->bc_mp->m_ddev_targp,
- xfs_btree_ptr_to_daddr(cur, ptr),
+ xfs_daddr_t daddr;
+
+ if (xfs_btree_ptr_to_daddr(cur, ptr, &daddr))
+ return;
+ xfs_buf_readahead(cur->bc_mp->m_ddev_targp, daddr,
cur->bc_mp->m_bsize * count, cur->bc_ops->buf_ops);
}
@@ -1282,11 +1294,14 @@ xfs_btree_get_buf_block(
{
struct xfs_mount *mp = cur->bc_mp;
xfs_daddr_t d;
+ int error;
/* need to sort out how callers deal with failures first */
ASSERT(!(flags & XBF_TRYLOCK));
- d = xfs_btree_ptr_to_daddr(cur, ptr);
+ error = xfs_btree_ptr_to_daddr(cur, ptr, &d);
+ if (error)
+ return error;
*bpp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d,
mp->m_bsize, flags);
@@ -1317,7 +1332,9 @@ xfs_btree_read_buf_block(
/* need to sort out how callers deal with failures first */
ASSERT(!(flags & XBF_TRYLOCK));
- d = xfs_btree_ptr_to_daddr(cur, ptr);
+ error = xfs_btree_ptr_to_daddr(cur, ptr, &d);
+ if (error)
+ return error;
error = xfs_trans_read_buf(mp, cur->bc_tp, mp->m_ddev_targp, d,
mp->m_bsize, flags, bpp,
cur->bc_ops->buf_ops);
@@ -1764,6 +1781,7 @@ xfs_btree_lookup_get_block(
struct xfs_btree_block **blkp) /* return btree block */
{
struct xfs_buf *bp; /* buffer pointer for btree block */
+ xfs_daddr_t daddr;
int error = 0;
/* special case the root block if in an inode */
@@ -1780,7 +1798,10 @@ xfs_btree_lookup_get_block(
* Otherwise throw it away and get a new one.
*/
bp = cur->bc_bufs[level];
- if (bp && XFS_BUF_ADDR(bp) == xfs_btree_ptr_to_daddr(cur, pp)) {
+ error = xfs_btree_ptr_to_daddr(cur, pp, &daddr);
+ if (error)
+ return error;
+ if (bp && XFS_BUF_ADDR(bp) == daddr) {
*blkp = XFS_BUF_TO_BLOCK(bp);
return 0;
}
@@ -1896,7 +1917,13 @@ xfs_btree_lookup(
high = xfs_btree_get_numrecs(block);
if (!high) {
/* Block is empty, must be an empty leaf. */
- ASSERT(level == 0 && cur->bc_nlevels == 1);
+ if (level != 0 || cur->bc_nlevels != 1) {
+ XFS_CORRUPTION_ERROR(__func__,
+ XFS_ERRLEVEL_LOW,
+ cur->bc_mp, block,
+ sizeof(*block));
+ return -EFSCORRUPTED;
+ }
cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE;
*stat = 0;
@@ -1946,11 +1973,10 @@ xfs_btree_lookup(
keyno = 1;
pp = xfs_btree_ptr_addr(cur, keyno, block);
-#ifdef DEBUG
- error = xfs_btree_check_ptr(cur, pp, 0, level);
+ error = xfs_btree_debug_check_ptr(cur, pp, 0, level);
if (error)
goto error0;
-#endif
+
cur->bc_ptrs[level] = keyno;
}
}
@@ -2354,11 +2380,11 @@ xfs_btree_lshift(
lpp = xfs_btree_ptr_addr(cur, lrecs, left);
rpp = xfs_btree_ptr_addr(cur, 1, right);
-#ifdef DEBUG
- error = xfs_btree_check_ptr(cur, rpp, 0, level);
+
+ error = xfs_btree_debug_check_ptr(cur, rpp, 0, level);
if (error)
goto error0;
-#endif
+
xfs_btree_copy_keys(cur, lkp, rkp, 1);
xfs_btree_copy_ptrs(cur, lpp, rpp, 1);
@@ -2393,15 +2419,14 @@ xfs_btree_lshift(
XFS_BTREE_STATS_ADD(cur, moves, rrecs - 1);
if (level > 0) {
/* It's a nonleaf. operate on keys and ptrs */
-#ifdef DEBUG
int i; /* loop index */
for (i = 0; i < rrecs; i++) {
- error = xfs_btree_check_ptr(cur, rpp, i + 1, level);
+ error = xfs_btree_debug_check_ptr(cur, rpp, i + 1, level);
if (error)
goto error0;
}
-#endif
+
xfs_btree_shift_keys(cur,
xfs_btree_key_addr(cur, 2, right),
-1, rrecs);
@@ -2541,22 +2566,18 @@ xfs_btree_rshift(
rkp = xfs_btree_key_addr(cur, 1, right);
rpp = xfs_btree_ptr_addr(cur, 1, right);
-#ifdef DEBUG
for (i = rrecs - 1; i >= 0; i--) {
- error = xfs_btree_check_ptr(cur, rpp, i, level);
+ error = xfs_btree_debug_check_ptr(cur, rpp, i, level);
if (error)
goto error0;
}
-#endif
xfs_btree_shift_keys(cur, rkp, 1, rrecs);
xfs_btree_shift_ptrs(cur, rpp, 1, rrecs);
-#ifdef DEBUG
- error = xfs_btree_check_ptr(cur, lpp, 0, level);
+ error = xfs_btree_debug_check_ptr(cur, lpp, 0, level);
if (error)
goto error0;
-#endif
/* Now put the new data in, and log it. */
xfs_btree_copy_keys(cur, rkp, lkp, 1);
@@ -2661,9 +2682,7 @@ __xfs_btree_split(
int rrecs;
int src_index;
int error; /* error return value */
-#ifdef DEBUG
int i;
-#endif
XFS_BTREE_STATS_INC(cur, split);
@@ -2729,13 +2748,11 @@ __xfs_btree_split(
rkp = xfs_btree_key_addr(cur, 1, right);
rpp = xfs_btree_ptr_addr(cur, 1, right);
-#ifdef DEBUG
for (i = src_index; i < rrecs; i++) {
- error = xfs_btree_check_ptr(cur, lpp, i, level);
+ error = xfs_btree_debug_check_ptr(cur, lpp, i, level);
if (error)
goto error0;
}
-#endif
/* Copy the keys & pointers to the new block. */
xfs_btree_copy_keys(cur, rkp, lkp, rrecs);
@@ -2923,9 +2940,7 @@ xfs_btree_new_iroot(
union xfs_btree_ptr nptr; /* new block addr */
int level; /* btree level */
int error; /* error return code */
-#ifdef DEBUG
int i; /* loop counter */
-#endif
XFS_BTREE_STATS_INC(cur, newroot);
@@ -2972,20 +2987,18 @@ xfs_btree_new_iroot(
xfs_btree_copy_keys(cur, ckp, kp, xfs_btree_get_numrecs(cblock));
cpp = xfs_btree_ptr_addr(cur, 1, cblock);
-#ifdef DEBUG
for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
- error = xfs_btree_check_ptr(cur, pp, i, level);
+ error = xfs_btree_debug_check_ptr(cur, pp, i, level);
if (error)
goto error0;
}
-#endif
+
xfs_btree_copy_ptrs(cur, cpp, pp, xfs_btree_get_numrecs(cblock));
-#ifdef DEBUG
- error = xfs_btree_check_ptr(cur, &nptr, 0, level);
+ error = xfs_btree_debug_check_ptr(cur, &nptr, 0, level);
if (error)
goto error0;
-#endif
+
xfs_btree_copy_ptrs(cur, pp, &nptr, 1);
xfs_iroot_realloc(cur->bc_private.b.ip,
@@ -3229,9 +3242,7 @@ xfs_btree_insrec(
int ptr; /* key/record index */
int numrecs;/* number of records */
int error; /* error return value */
-#ifdef DEBUG
int i;
-#endif
xfs_daddr_t old_bn;
ncur = NULL;
@@ -3321,22 +3332,18 @@ xfs_btree_insrec(
kp = xfs_btree_key_addr(cur, ptr, block);
pp = xfs_btree_ptr_addr(cur, ptr, block);
-#ifdef DEBUG
for (i = numrecs - ptr; i >= 0; i--) {
- error = xfs_btree_check_ptr(cur, pp, i, level);
+ error = xfs_btree_debug_check_ptr(cur, pp, i, level);
if (error)
return error;
}
-#endif
xfs_btree_shift_keys(cur, kp, 1, numrecs - ptr + 1);
xfs_btree_shift_ptrs(cur, pp, 1, numrecs - ptr + 1);
-#ifdef DEBUG
- error = xfs_btree_check_ptr(cur, ptrp, 0, level);
+ error = xfs_btree_debug_check_ptr(cur, ptrp, 0, level);
if (error)
goto error0;
-#endif
/* Now put the new data in, bump numrecs and log it. */
xfs_btree_copy_keys(cur, kp, key, 1);
@@ -3524,8 +3531,8 @@ xfs_btree_kill_iroot(
int error;
#ifdef DEBUG
union xfs_btree_ptr ptr;
- int i;
#endif
+ int i;
ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE);
ASSERT(cur->bc_nlevels > 1);
@@ -3581,13 +3588,13 @@ xfs_btree_kill_iroot(
pp = xfs_btree_ptr_addr(cur, 1, block);
cpp = xfs_btree_ptr_addr(cur, 1, cblock);
-#ifdef DEBUG
+
for (i = 0; i < numrecs; i++) {
- error = xfs_btree_check_ptr(cur, cpp, i, level - 1);
+ error = xfs_btree_debug_check_ptr(cur, cpp, i, level - 1);
if (error)
return error;
}
-#endif
+
xfs_btree_copy_ptrs(cur, pp, cpp, numrecs);
error = xfs_btree_free_block(cur, cbp);
@@ -3721,13 +3728,11 @@ xfs_btree_delrec(
lkp = xfs_btree_key_addr(cur, ptr + 1, block);
lpp = xfs_btree_ptr_addr(cur, ptr + 1, block);
-#ifdef DEBUG
for (i = 0; i < numrecs - ptr; i++) {
- error = xfs_btree_check_ptr(cur, lpp, i, level);
+ error = xfs_btree_debug_check_ptr(cur, lpp, i, level);
if (error)
goto error0;
}
-#endif
if (ptr < numrecs) {
xfs_btree_shift_keys(cur, lkp, -1, numrecs - ptr);
@@ -4060,13 +4065,13 @@ xfs_btree_delrec(
lpp = xfs_btree_ptr_addr(cur, lrecs + 1, left);
rkp = xfs_btree_key_addr(cur, 1, right);
rpp = xfs_btree_ptr_addr(cur, 1, right);
-#ifdef DEBUG
+
for (i = 1; i < rrecs; i++) {
- error = xfs_btree_check_ptr(cur, rpp, i, level);
+ error = xfs_btree_debug_check_ptr(cur, rpp, i, level);
if (error)
goto error0;
}
-#endif
+
xfs_btree_copy_keys(cur, lkp, rkp, rrecs);
xfs_btree_copy_ptrs(cur, lpp, rpp, rrecs);
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index d7911efee6dc..0a4fdf7f11a7 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BTREE_H__
#define __XFS_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
index ea187b4a7991..8a301402bbc4 100644
--- a/fs/xfs/libxfs/xfs_da_btree.c
+++ b/fs/xfs/libxfs/xfs_da_btree.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -305,9 +293,11 @@ xfs_da3_node_read(
type = XFS_BLFT_DIR_LEAFN_BUF;
break;
default:
- type = 0;
- ASSERT(0);
- break;
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
+ tp->t_mountp, info, sizeof(*info));
+ xfs_trans_brelse(tp, *bpp);
+ *bpp = NULL;
+ return -EFSCORRUPTED;
}
xfs_trans_buf_set_type(tp, *bpp, type);
}
@@ -2091,7 +2081,7 @@ xfs_da_grow_inode_int(
*/
mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
for (b = *bno, mapi = 0; b < *bno + count; ) {
- nmap = MIN(XFS_BMAP_MAX_NMAP, count);
+ nmap = min(XFS_BMAP_MAX_NMAP, count);
c = (int)(*bno + count - b);
error = xfs_bmapi_write(tp, dp, b, c,
xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA,
diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h
index ae6de17467f2..28260073ae71 100644
--- a/fs/xfs/libxfs/xfs_da_btree.h
+++ b/fs/xfs/libxfs/xfs_da_btree.h
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_DA_BTREE_H__
#define __XFS_DA_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_da_format.c b/fs/xfs/libxfs/xfs_da_format.c
index 6d77d1a8498a..b39053dcb643 100644
--- a/fs/xfs/libxfs/xfs_da_format.c
+++ b/fs/xfs/libxfs/xfs_da_format.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h
index 7e77299b7789..5d5bf3bffc78 100644
--- a/fs/xfs/libxfs/xfs_da_format.h
+++ b/fs/xfs/libxfs/xfs_da_format.h
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_DA_FORMAT_H__
#define __XFS_DA_FORMAT_H__
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index 3daf175e2535..c3e5bffda4f5 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
index e70725ba1f5f..a02b2b748b6d 100644
--- a/fs/xfs/libxfs/xfs_defer.h
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_DEFER_H__
#define __XFS_DEFER_H__
diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
index 92f94e190f04..59169aff30fe 100644
--- a/fs/xfs/libxfs/xfs_dir2.c
+++ b/fs/xfs/libxfs/xfs_dir2.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h
index 989e95a53db2..ed385316c7dc 100644
--- a/fs/xfs/libxfs/xfs_dir2.h
+++ b/fs/xfs/libxfs/xfs_dir2.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_DIR2_H__
#define __XFS_DIR2_H__
diff --git a/fs/xfs/libxfs/xfs_dir2_block.c b/fs/xfs/libxfs/xfs_dir2_block.c
index 875893ded514..30ed5919da72 100644
--- a/fs/xfs/libxfs/xfs_dir2_block.c
+++ b/fs/xfs/libxfs/xfs_dir2_block.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -514,8 +502,8 @@ xfs_dir2_block_addname(
if (mid - lowstale)
memmove(&blp[lowstale], &blp[lowstale + 1],
(mid - lowstale) * sizeof(*blp));
- lfloglow = MIN(lowstale, lfloglow);
- lfloghigh = MAX(mid, lfloghigh);
+ lfloglow = min(lowstale, lfloglow);
+ lfloghigh = max(mid, lfloghigh);
}
/*
* Move entries toward the high-numbered stale entry.
@@ -526,8 +514,8 @@ xfs_dir2_block_addname(
if (highstale - mid)
memmove(&blp[mid + 1], &blp[mid],
(highstale - mid) * sizeof(*blp));
- lfloglow = MIN(mid, lfloglow);
- lfloghigh = MAX(highstale, lfloghigh);
+ lfloglow = min(mid, lfloglow);
+ lfloghigh = max(highstale, lfloghigh);
}
be32_add_cpu(&btp->stale, -1);
}
diff --git a/fs/xfs/libxfs/xfs_dir2_data.c b/fs/xfs/libxfs/xfs_dir2_data.c
index cb67ec730b9b..01162c62ec8f 100644
--- a/fs/xfs/libxfs/xfs_dir2_data.c
+++ b/fs/xfs/libxfs/xfs_dir2_data.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -33,6 +21,11 @@
#include "xfs_cksum.h"
#include "xfs_log.h"
+static xfs_failaddr_t xfs_dir2_data_freefind_verify(
+ struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf,
+ struct xfs_dir2_data_unused *dup,
+ struct xfs_dir2_data_free **bf_ent);
+
/*
* Check the consistency of the data block.
* The input can also be a block-format directory.
@@ -147,6 +140,8 @@ __xfs_dir3_data_check(
* doesn't need to be there.
*/
if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
+ xfs_failaddr_t fa;
+
if (lastfree != 0)
return __this_address;
if (endp < p + be16_to_cpu(dup->length))
@@ -154,7 +149,9 @@ __xfs_dir3_data_check(
if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) !=
(char *)dup - (char *)hdr)
return __this_address;
- dfp = xfs_dir2_data_freefind(hdr, bf, dup);
+ fa = xfs_dir2_data_freefind_verify(hdr, bf, dup, &dfp);
+ if (fa)
+ return fa;
if (dfp) {
i = (int)(dfp - bf);
if ((freeseen & (1 << i)) != 0)
@@ -242,7 +239,8 @@ xfs_dir3_data_check(
if (!fa)
return;
xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, dp->i_mount,
- bp->b_addr, __FILE__, __LINE__, fa);
+ bp->b_addr, BBTOB(bp->b_length), __FILE__, __LINE__,
+ fa);
ASSERT(0);
}
#endif
@@ -381,55 +379,79 @@ xfs_dir3_data_readahead(
}
/*
- * Given a data block and an unused entry from that block,
- * return the bestfree entry if any that corresponds to it.
+ * Find the bestfree entry that exactly coincides with unused directory space
+ * or a verifier error because the bestfree data are bad.
*/
-xfs_dir2_data_free_t *
-xfs_dir2_data_freefind(
- struct xfs_dir2_data_hdr *hdr, /* data block header */
- struct xfs_dir2_data_free *bf, /* bestfree table pointer */
- struct xfs_dir2_data_unused *dup) /* unused space */
+static xfs_failaddr_t
+xfs_dir2_data_freefind_verify(
+ struct xfs_dir2_data_hdr *hdr,
+ struct xfs_dir2_data_free *bf,
+ struct xfs_dir2_data_unused *dup,
+ struct xfs_dir2_data_free **bf_ent)
{
- xfs_dir2_data_free_t *dfp; /* bestfree entry */
- xfs_dir2_data_aoff_t off; /* offset value needed */
-#ifdef DEBUG
- int matched; /* matched the value */
- int seenzero; /* saw a 0 bestfree entry */
-#endif
+ struct xfs_dir2_data_free *dfp;
+ xfs_dir2_data_aoff_t off;
+ bool matched = false;
+ bool seenzero = false;
+ *bf_ent = NULL;
off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
-#ifdef DEBUG
/*
* Validate some consistency in the bestfree table.
* Check order, non-overlapping entries, and if we find the
* one we're looking for it has to be exact.
*/
- ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
- hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
- hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
- hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
- for (dfp = &bf[0], seenzero = matched = 0;
- dfp < &bf[XFS_DIR2_DATA_FD_COUNT];
- dfp++) {
+ for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {
if (!dfp->offset) {
- ASSERT(!dfp->length);
- seenzero = 1;
+ if (dfp->length)
+ return __this_address;
+ seenzero = true;
continue;
}
- ASSERT(seenzero == 0);
+ if (seenzero)
+ return __this_address;
if (be16_to_cpu(dfp->offset) == off) {
- matched = 1;
- ASSERT(dfp->length == dup->length);
- } else if (off < be16_to_cpu(dfp->offset))
- ASSERT(off + be16_to_cpu(dup->length) <= be16_to_cpu(dfp->offset));
- else
- ASSERT(be16_to_cpu(dfp->offset) + be16_to_cpu(dfp->length) <= off);
- ASSERT(matched || be16_to_cpu(dfp->length) >= be16_to_cpu(dup->length));
- if (dfp > &bf[0])
- ASSERT(be16_to_cpu(dfp[-1].length) >= be16_to_cpu(dfp[0].length));
+ matched = true;
+ if (dfp->length != dup->length)
+ return __this_address;
+ } else if (be16_to_cpu(dfp->offset) > off) {
+ if (off + be16_to_cpu(dup->length) >
+ be16_to_cpu(dfp->offset))
+ return __this_address;
+ } else {
+ if (be16_to_cpu(dfp->offset) +
+ be16_to_cpu(dfp->length) > off)
+ return __this_address;
+ }
+ if (!matched &&
+ be16_to_cpu(dfp->length) < be16_to_cpu(dup->length))
+ return __this_address;
+ if (dfp > &bf[0] &&
+ be16_to_cpu(dfp[-1].length) < be16_to_cpu(dfp[0].length))
+ return __this_address;
}
-#endif
+
+ /* Looks ok so far; now try to match up with a bestfree entry. */
+ *bf_ent = xfs_dir2_data_freefind(hdr, bf, dup);
+ return NULL;
+}
+
+/*
+ * Given a data block and an unused entry from that block,
+ * return the bestfree entry if any that corresponds to it.
+ */
+xfs_dir2_data_free_t *
+xfs_dir2_data_freefind(
+ struct xfs_dir2_data_hdr *hdr, /* data block header */
+ struct xfs_dir2_data_free *bf, /* bestfree table pointer */
+ struct xfs_dir2_data_unused *dup) /* unused space */
+{
+ xfs_dir2_data_free_t *dfp; /* bestfree entry */
+ xfs_dir2_data_aoff_t off; /* offset value needed */
+
+ off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
+
/*
* If this is smaller than the smallest bestfree entry,
* it can't be there since they're sorted.
@@ -1124,7 +1146,7 @@ xfs_dir2_data_use_free(
return 0;
corrupt:
xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, args->dp->i_mount,
- hdr, __FILE__, __LINE__, fa);
+ hdr, sizeof(*hdr), __FILE__, __LINE__, fa);
return -EFSCORRUPTED;
}
diff --git a/fs/xfs/libxfs/xfs_dir2_leaf.c b/fs/xfs/libxfs/xfs_dir2_leaf.c
index 50fc9c0c5e2b..1728a3e6f5cf 100644
--- a/fs/xfs/libxfs/xfs_dir2_leaf.c
+++ b/fs/xfs/libxfs/xfs_dir2_leaf.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -81,7 +69,8 @@ xfs_dir3_leaf_check(
if (!fa)
return;
xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, dp->i_mount,
- bp->b_addr, __FILE__, __LINE__, fa);
+ bp->b_addr, BBTOB(bp->b_length), __FILE__, __LINE__,
+ fa);
ASSERT(0);
}
#else
@@ -601,8 +590,8 @@ xfs_dir3_leaf_find_entry(
(index - lowstale - 1) *
sizeof(xfs_dir2_leaf_entry_t));
}
- *lfloglow = MIN(lowstale, *lfloglow);
- *lfloghigh = MAX(index - 1, *lfloghigh);
+ *lfloglow = min(lowstale, *lfloglow);
+ *lfloghigh = max(index - 1, *lfloghigh);
leafhdr->stale--;
return &ents[index - 1];
}
@@ -621,8 +610,8 @@ xfs_dir3_leaf_find_entry(
memmove(&ents[index + 1], &ents[index],
(highstale - index) * sizeof(xfs_dir2_leaf_entry_t));
}
- *lfloglow = MIN(index, *lfloglow);
- *lfloghigh = MAX(highstale, *lfloghigh);
+ *lfloglow = min(index, *lfloglow);
+ *lfloghigh = max(highstale, *lfloghigh);
leafhdr->stale--;
return &ents[index];
}
@@ -872,7 +861,6 @@ xfs_dir2_leaf_addname(
*/
dup = (xfs_dir2_data_unused_t *)
((char *)hdr + be16_to_cpu(bf[0].offset));
- ASSERT(be16_to_cpu(dup->length) >= length);
needscan = needlog = 0;
/*
* Mark the initial part of our freespace in use for the new entry.
diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c
index 9df096cc3c37..2daf874969ab 100644
--- a/fs/xfs/libxfs/xfs_dir2_node.c
+++ b/fs/xfs/libxfs/xfs_dir2_node.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -84,7 +72,8 @@ xfs_dir3_leaf_check(
if (!fa)
return;
xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, dp->i_mount,
- bp->b_addr, __FILE__, __LINE__, fa);
+ bp->b_addr, BBTOB(bp->b_length), __FILE__, __LINE__,
+ fa);
ASSERT(0);
}
#else
diff --git a/fs/xfs/libxfs/xfs_dir2_priv.h b/fs/xfs/libxfs/xfs_dir2_priv.h
index 753aeeeffc18..59f9fb2241a5 100644
--- a/fs/xfs/libxfs/xfs_dir2_priv.h
+++ b/fs/xfs/libxfs/xfs_dir2_priv.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_DIR2_PRIV_H__
#define __XFS_DIR2_PRIV_H__
diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c
index 0c75a7f00883..585dfdb7b6b6 100644
--- a/fs/xfs/libxfs/xfs_dir2_sf.c
+++ b/fs/xfs/libxfs/xfs_dir2_sf.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c
index cce520becee4..d293f371dd54 100644
--- a/fs/xfs/libxfs/xfs_dquot_buf.c
+++ b/fs/xfs/libxfs/xfs_dquot_buf.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_errortag.h b/fs/xfs/libxfs/xfs_errortag.h
index d47b91625945..b9974e7a8e6e 100644
--- a/fs/xfs/libxfs/xfs_errortag.h
+++ b/fs/xfs/libxfs/xfs_errortag.h
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* Copyright (C) 2017 Oracle.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_ERRORTAG_H_
#define __XFS_ERRORTAG_H_
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index c1cb29a5f4f6..1c5a8aaf2bfc 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_FORMAT_H__
#define __XFS_FORMAT_H__
diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index dddc75e4f1f6..f3aa59302fef 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: LGPL-2.1
/*
* Copyright (c) 1995-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_FS_H__
#define __XFS_FS_H__
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 4ca4ff7a757d..0d968e8143aa 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -133,16 +121,45 @@ xfs_inobt_get_rec(
struct xfs_inobt_rec_incore *irec,
int *stat)
{
+ struct xfs_mount *mp = cur->bc_mp;
+ xfs_agnumber_t agno = cur->bc_private.a.agno;
union xfs_btree_rec *rec;
int error;
+ uint64_t realfree;
error = xfs_btree_get_rec(cur, &rec, stat);
if (error || *stat == 0)
return error;
- xfs_inobt_btrec_to_irec(cur->bc_mp, rec, irec);
+ xfs_inobt_btrec_to_irec(mp, rec, irec);
+
+ if (!xfs_verify_agino(mp, agno, irec->ir_startino))
+ goto out_bad_rec;
+ if (irec->ir_count < XFS_INODES_PER_HOLEMASK_BIT ||
+ irec->ir_count > XFS_INODES_PER_CHUNK)
+ goto out_bad_rec;
+ if (irec->ir_freecount > XFS_INODES_PER_CHUNK)
+ goto out_bad_rec;
+
+ /* if there are no holes, return the first available offset */
+ if (!xfs_inobt_issparse(irec->ir_holemask))
+ realfree = irec->ir_free;
+ else
+ realfree = irec->ir_free & xfs_inobt_irec_to_allocmask(irec);
+ if (hweight64(realfree) != irec->ir_freecount)
+ goto out_bad_rec;
return 0;
+
+out_bad_rec:
+ xfs_warn(mp,
+ "%s Inode BTree record corruption in AG %d detected!",
+ cur->bc_btnum == XFS_BTNUM_INO ? "Used" : "Free", agno);
+ xfs_warn(mp,
+"start inode 0x%x, count 0x%x, free 0x%x freemask 0x%llx, holemask 0x%x",
+ irec->ir_startino, irec->ir_count, irec->ir_freecount,
+ irec->ir_free, irec->ir_holemask);
+ return -EFSCORRUPTED;
}
/*
@@ -880,6 +897,7 @@ sparse_alloc:
be32_add_cpu(&agi->agi_freecount, newlen);
pag = xfs_perag_get(args.mp, agno);
pag->pagi_freecount += newlen;
+ pag->pagi_count += newlen;
xfs_perag_put(pag);
agi->agi_newino = cpu_to_be32(newino);
@@ -1974,6 +1992,7 @@ xfs_difree_inobt(
xfs_ialloc_log_agi(tp, agbp, XFS_AGI_COUNT | XFS_AGI_FREECOUNT);
pag = xfs_perag_get(mp, agno);
pag->pagi_freecount -= ilen - 1;
+ pag->pagi_count -= ilen;
xfs_perag_put(pag);
xfs_trans_mod_sb(tp, XFS_TRANS_SB_ICOUNT, -ilen);
xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1));
@@ -2477,26 +2496,13 @@ xfs_ialloc_log_agi(
}
}
-#ifdef DEBUG
-STATIC void
-xfs_check_agi_unlinked(
- struct xfs_agi *agi)
-{
- int i;
-
- for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++)
- ASSERT(agi->agi_unlinked[i]);
-}
-#else
-#define xfs_check_agi_unlinked(agi)
-#endif
-
static xfs_failaddr_t
xfs_agi_verify(
struct xfs_buf *bp)
{
struct xfs_mount *mp = bp->b_target->bt_mount;
struct xfs_agi *agi = XFS_BUF_TO_AGI(bp);
+ int i;
if (xfs_sb_version_hascrc(&mp->m_sb)) {
if (!uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid))
@@ -2532,7 +2538,13 @@ xfs_agi_verify(
if (bp->b_pag && be32_to_cpu(agi->agi_seqno) != bp->b_pag->pag_agno)
return __this_address;
- xfs_check_agi_unlinked(agi);
+ for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
+ if (agi->agi_unlinked[i] == NULLAGINO)
+ continue;
+ if (!xfs_verify_ino(mp, be32_to_cpu(agi->agi_unlinked[i])))
+ return __this_address;
+ }
+
return NULL;
}
@@ -2664,96 +2676,6 @@ xfs_ialloc_pagi_init(
return 0;
}
-/* Calculate the first and last possible inode number in an AG. */
-void
-xfs_ialloc_agino_range(
- struct xfs_mount *mp,
- xfs_agnumber_t agno,
- xfs_agino_t *first,
- xfs_agino_t *last)
-{
- xfs_agblock_t bno;
- xfs_agblock_t eoag;
-
- eoag = xfs_ag_block_count(mp, agno);
-
- /*
- * Calculate the first inode, which will be in the first
- * cluster-aligned block after the AGFL.
- */
- bno = round_up(XFS_AGFL_BLOCK(mp) + 1,
- xfs_ialloc_cluster_alignment(mp));
- *first = XFS_OFFBNO_TO_AGINO(mp, bno, 0);
-
- /*
- * Calculate the last inode, which will be at the end of the
- * last (aligned) cluster that can be allocated in the AG.
- */
- bno = round_down(eoag, xfs_ialloc_cluster_alignment(mp));
- *last = XFS_OFFBNO_TO_AGINO(mp, bno, 0) - 1;
-}
-
-/*
- * Verify that an AG inode number pointer neither points outside the AG
- * nor points at static metadata.
- */
-bool
-xfs_verify_agino(
- struct xfs_mount *mp,
- xfs_agnumber_t agno,
- xfs_agino_t agino)
-{
- xfs_agino_t first;
- xfs_agino_t last;
-
- xfs_ialloc_agino_range(mp, agno, &first, &last);
- return agino >= first && agino <= last;
-}
-
-/*
- * Verify that an FS inode number pointer neither points outside the
- * filesystem nor points at static AG metadata.
- */
-bool
-xfs_verify_ino(
- struct xfs_mount *mp,
- xfs_ino_t ino)
-{
- xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ino);
- xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino);
-
- if (agno >= mp->m_sb.sb_agcount)
- return false;
- if (XFS_AGINO_TO_INO(mp, agno, agino) != ino)
- return false;
- return xfs_verify_agino(mp, agno, agino);
-}
-
-/* Is this an internal inode number? */
-bool
-xfs_internal_inum(
- struct xfs_mount *mp,
- xfs_ino_t ino)
-{
- return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
- (xfs_sb_version_hasquota(&mp->m_sb) &&
- xfs_is_quota_inode(&mp->m_sb, ino));
-}
-
-/*
- * Verify that a directory entry's inode number doesn't point at an internal
- * inode, empty space, or static AG metadata.
- */
-bool
-xfs_verify_dir_ino(
- struct xfs_mount *mp,
- xfs_ino_t ino)
-{
- if (xfs_internal_inum(mp, ino))
- return false;
- return xfs_verify_ino(mp, ino);
-}
-
/* Is there an inode record covering a given range of inode numbers? */
int
xfs_ialloc_has_inode_record(
diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h
index 77fffced8bac..90b09c5f163b 100644
--- a/fs/xfs/libxfs/xfs_ialloc.h
+++ b/fs/xfs/libxfs/xfs_ialloc.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_IALLOC_H__
#define __XFS_IALLOC_H__
@@ -181,12 +169,5 @@ int xfs_inobt_insert_rec(struct xfs_btree_cur *cur, uint16_t holemask,
int *stat);
int xfs_ialloc_cluster_alignment(struct xfs_mount *mp);
-void xfs_ialloc_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
- xfs_agino_t *first, xfs_agino_t *last);
-bool xfs_verify_agino(struct xfs_mount *mp, xfs_agnumber_t agno,
- xfs_agino_t agino);
-bool xfs_verify_ino(struct xfs_mount *mp, xfs_ino_t ino);
-bool xfs_internal_inum(struct xfs_mount *mp, xfs_ino_t ino);
-bool xfs_verify_dir_ino(struct xfs_mount *mp, xfs_ino_t ino);
#endif /* __XFS_IALLOC_H__ */
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
index b04c55512159..a5237afec5ab 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.h b/fs/xfs/libxfs/xfs_ialloc_btree.h
index 4acdd5458d59..bf8f0c405e7d 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.h
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_IALLOC_BTREE_H__
#define __XFS_IALLOC_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_iext_tree.c b/fs/xfs/libxfs/xfs_iext_tree.c
index b0f31791c7e6..b80c63faace2 100644
--- a/fs/xfs/libxfs/xfs_iext_tree.c
+++ b/fs/xfs/libxfs/xfs_iext_tree.c
@@ -1,14 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2017 Christoph Hellwig.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
*/
#include <linux/cache.h>
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index 1201107eabc6..d38d724534c4 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -201,11 +189,6 @@ xfs_imap_to_bp(
ASSERT(buf_flags & XBF_TRYLOCK);
return error;
}
-
- if (error == -EFSCORRUPTED &&
- (iget_flags & XFS_IGET_UNTRUSTED))
- return -EINVAL;
-
xfs_warn(mp, "%s: xfs_trans_read_buf() returned error %d.",
__func__, error);
return error;
@@ -397,6 +380,7 @@ xfs_dinode_verify(
xfs_ino_t ino,
struct xfs_dinode *dip)
{
+ xfs_failaddr_t fa;
uint16_t mode;
uint16_t flags;
uint64_t flags2;
@@ -513,6 +497,12 @@ xfs_dinode_verify(
return __this_address;
}
+ /* extent size hint validation */
+ fa = xfs_inode_validate_extsize(mp, be32_to_cpu(dip->di_extsize),
+ mode, flags);
+ if (fa)
+ return fa;
+
/* only version 3 or greater inodes are extensively verified here */
if (dip->di_version < 3)
return NULL;
@@ -521,7 +511,7 @@ xfs_dinode_verify(
/* don't allow reflink/cowextsize if we don't have reflink */
if ((flags2 & (XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE)) &&
- !xfs_sb_version_hasreflink(&mp->m_sb))
+ !xfs_sb_version_hasreflink(&mp->m_sb))
return __this_address;
/* only regular files get reflink */
@@ -536,6 +526,12 @@ xfs_dinode_verify(
if ((flags2 & XFS_DIFLAG2_REFLINK) && (flags2 & XFS_DIFLAG2_DAX))
return __this_address;
+ /* COW extent size hint validation */
+ fa = xfs_inode_validate_cowextsize(mp, be32_to_cpu(dip->di_cowextsize),
+ mode, flags, flags2);
+ if (fa)
+ return fa;
+
return NULL;
}
diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h
index d9a376a78ee2..ab0f84165317 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.h
+++ b/fs/xfs/libxfs/xfs_inode_buf.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_INODE_BUF_H__
#define __XFS_INODE_BUF_H__
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 701c42a28d05..183ec0cb8921 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/log2.h>
diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
index dd8aba0dd119..781b1603df5e 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.h
+++ b/fs/xfs/libxfs/xfs_inode_fork.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_INODE_FORK_H__
#define __XFS_INODE_FORK_H__
diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h
index 349d9f8edb89..79bb79853c9f 100644
--- a/fs/xfs/libxfs/xfs_log_format.h
+++ b/fs/xfs/libxfs/xfs_log_format.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_LOG_FORMAT_H__
#define __XFS_LOG_FORMAT_H__
diff --git a/fs/xfs/libxfs/xfs_log_recover.h b/fs/xfs/libxfs/xfs_log_recover.h
index 66948a9fd486..f3d18eaecebb 100644
--- a/fs/xfs/libxfs/xfs_log_recover.h
+++ b/fs/xfs/libxfs/xfs_log_recover.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_LOG_RECOVER_H__
#define __XFS_LOG_RECOVER_H__
diff --git a/fs/xfs/libxfs/xfs_log_rlimit.c b/fs/xfs/libxfs/xfs_log_rlimit.c
index cc4cbe290939..1b542ec11d5d 100644
--- a/fs/xfs/libxfs/xfs_log_rlimit.c
+++ b/fs/xfs/libxfs/xfs_log_rlimit.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2013 Jie Liu.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_quota_defs.h b/fs/xfs/libxfs/xfs_quota_defs.h
index d4af2804b178..4bfdd5f4c6af 100644
--- a/fs/xfs/libxfs/xfs_quota_defs.h
+++ b/fs/xfs/libxfs/xfs_quota_defs.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_QUOTA_DEFS_H__
#define __XFS_QUOTA_DEFS_H__
diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c
index 418d53295893..9dda6fd0bb13 100644
--- a/fs/xfs/libxfs/xfs_refcount.c
+++ b/fs/xfs/libxfs/xfs_refcount.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -125,16 +111,53 @@ xfs_refcount_get_rec(
struct xfs_refcount_irec *irec,
int *stat)
{
+ struct xfs_mount *mp = cur->bc_mp;
+ xfs_agnumber_t agno = cur->bc_private.a.agno;
union xfs_btree_rec *rec;
int error;
+ xfs_agblock_t realstart;
error = xfs_btree_get_rec(cur, &rec, stat);
- if (!error && *stat == 1) {
- xfs_refcount_btrec_to_irec(rec, irec);
- trace_xfs_refcount_get(cur->bc_mp, cur->bc_private.a.agno,
- irec);
+ if (error || !*stat)
+ return error;
+
+ xfs_refcount_btrec_to_irec(rec, irec);
+
+ agno = cur->bc_private.a.agno;
+ if (irec->rc_blockcount == 0 || irec->rc_blockcount > MAXREFCEXTLEN)
+ goto out_bad_rec;
+
+ /* handle special COW-staging state */
+ realstart = irec->rc_startblock;
+ if (realstart & XFS_REFC_COW_START) {
+ if (irec->rc_refcount != 1)
+ goto out_bad_rec;
+ realstart &= ~XFS_REFC_COW_START;
+ } else if (irec->rc_refcount < 2) {
+ goto out_bad_rec;
}
- return error;
+
+ /* check for valid extent range, including overflow */
+ if (!xfs_verify_agbno(mp, agno, realstart))
+ goto out_bad_rec;
+ if (realstart > realstart + irec->rc_blockcount)
+ goto out_bad_rec;
+ if (!xfs_verify_agbno(mp, agno, realstart + irec->rc_blockcount - 1))
+ goto out_bad_rec;
+
+ if (irec->rc_refcount == 0 || irec->rc_refcount > MAXREFCOUNT)
+ goto out_bad_rec;
+
+ trace_xfs_refcount_get(cur->bc_mp, cur->bc_private.a.agno, irec);
+ return 0;
+
+out_bad_rec:
+ xfs_warn(mp,
+ "Refcount BTree record corruption in AG %d detected!", agno);
+ xfs_warn(mp,
+ "Start block 0x%x, block count 0x%x, references 0x%x",
+ irec->rc_startblock, irec->rc_blockcount, irec->rc_refcount);
+ return -EFSCORRUPTED;
}
/*
diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h
index a92ad9078bc1..5fef74412727 100644
--- a/fs/xfs/libxfs/xfs_refcount.h
+++ b/fs/xfs/libxfs/xfs_refcount.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_REFCOUNT_H__
#define __XFS_REFCOUNT_H__
diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c
index 375abfeb6267..b71937982c5b 100644
--- a/fs/xfs/libxfs/xfs_refcount_btree.c
+++ b/fs/xfs/libxfs/xfs_refcount_btree.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -192,7 +178,6 @@ xfs_refcountbt_init_ptr_from_cur(
struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno));
- ASSERT(agf->agf_refcount_root != 0);
ptr->s = agf->agf_refcount_root;
}
diff --git a/fs/xfs/libxfs/xfs_refcount_btree.h b/fs/xfs/libxfs/xfs_refcount_btree.h
index 2bc4694ef146..d2852b6e1fa8 100644
--- a/fs/xfs/libxfs/xfs_refcount_btree.h
+++ b/fs/xfs/libxfs/xfs_refcount_btree.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_REFCOUNT_BTREE_H__
#define __XFS_REFCOUNT_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
index c0644f1be8a8..d4460b0d2d81 100644
--- a/fs/xfs/libxfs/xfs_rmap.c
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -39,6 +27,7 @@
#include "xfs_extent_busy.h"
#include "xfs_bmap.h"
#include "xfs_inode.h"
+#include "xfs_ialloc.h"
/*
* Lookup the first record less than or equal to [bno, len, owner, offset]
@@ -203,6 +192,8 @@ xfs_rmap_get_rec(
struct xfs_rmap_irec *irec,
int *stat)
{
+ struct xfs_mount *mp = cur->bc_mp;
+ xfs_agnumber_t agno = cur->bc_private.a.agno;
union xfs_btree_rec *rec;
int error;
@@ -210,7 +201,43 @@ xfs_rmap_get_rec(
if (error || !*stat)
return error;
- return xfs_rmap_btrec_to_irec(rec, irec);
+ if (xfs_rmap_btrec_to_irec(rec, irec))
+ goto out_bad_rec;
+
+ if (irec->rm_blockcount == 0)
+ goto out_bad_rec;
+ if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
+ if (irec->rm_owner != XFS_RMAP_OWN_FS)
+ goto out_bad_rec;
+ if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
+ goto out_bad_rec;
+ } else {
+ /* check for valid extent range, including overflow */
+ if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
+ goto out_bad_rec;
+ if (irec->rm_startblock >
+ irec->rm_startblock + irec->rm_blockcount)
+ goto out_bad_rec;
+ if (!xfs_verify_agbno(mp, agno,
+ irec->rm_startblock + irec->rm_blockcount - 1))
+ goto out_bad_rec;
+ }
+
+ if (!(xfs_verify_ino(mp, irec->rm_owner) ||
+ (irec->rm_owner <= XFS_RMAP_OWN_FS &&
+ irec->rm_owner >= XFS_RMAP_OWN_MIN)))
+ goto out_bad_rec;
+
+ return 0;
+out_bad_rec:
+ xfs_warn(mp,
+ "Reverse Mapping BTree record corruption in AG %d detected!",
+ agno);
+ xfs_warn(mp,
+ "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
+ irec->rm_owner, irec->rm_flags, irec->rm_startblock,
+ irec->rm_blockcount);
+ return -EFSCORRUPTED;
}
struct xfs_find_left_neighbor_info {
diff --git a/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h
index 43e506f67680..9f19454768b2 100644
--- a/fs/xfs/libxfs/xfs_rmap.h
+++ b/fs/xfs/libxfs/xfs_rmap.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_RMAP_H__
#define __XFS_RMAP_H__
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c
index d756e0b84abf..221a88ea60bb 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rmap_btree.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -234,7 +222,6 @@ xfs_rmapbt_init_ptr_from_cur(
struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno));
- ASSERT(agf->agf_roots[cur->bc_btnum] != 0);
ptr->s = agf->agf_roots[cur->bc_btnum];
}
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h
index d68d96eed7ea..50198b6c3bb2 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.h
+++ b/fs/xfs/libxfs/xfs_rmap_btree.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_RMAP_BTREE_H__
#define __XFS_RMAP_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c
index 369eeb7a52ec..65fc4ed2e9a1 100644
--- a/fs/xfs/libxfs/xfs_rtbitmap.c
+++ b/fs/xfs/libxfs/xfs_rtbitmap.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -1092,18 +1080,6 @@ xfs_rtalloc_query_all(
return xfs_rtalloc_query_range(tp, &keys[0], &keys[1], fn, priv);
}
-/*
- * Verify that an realtime block number pointer doesn't point off the
- * end of the realtime device.
- */
-bool
-xfs_verify_rtbno(
- struct xfs_mount *mp,
- xfs_rtblock_t rtbno)
-{
- return rtbno < mp->m_sb.sb_rblocks;
-}
-
/* Is the given extent all free? */
int
xfs_rtalloc_extent_is_free(
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index d485e14313c6..350119eeaecb 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -278,6 +266,22 @@ xfs_mount_validate_sb(
return -EFSCORRUPTED;
}
+ if (sbp->sb_unit) {
+ if (!xfs_sb_version_hasdalign(sbp) ||
+ sbp->sb_unit > sbp->sb_width ||
+ (sbp->sb_width % sbp->sb_unit) != 0) {
+ xfs_notice(mp, "SB stripe unit sanity check failed");
+ return -EFSCORRUPTED;
+ }
+ } else if (xfs_sb_version_hasdalign(sbp)) {
+ xfs_notice(mp, "SB stripe alignment sanity check failed");
+ return -EFSCORRUPTED;
+ } else if (sbp->sb_width) {
+ xfs_notice(mp, "SB stripe width sanity check failed");
+ return -EFSCORRUPTED;
+ }
+
+
if (xfs_sb_version_hascrc(&mp->m_sb) &&
sbp->sb_blocksize < XFS_MIN_CRC_BLOCKSIZE) {
xfs_notice(mp, "v5 SB sanity check failed");
@@ -767,7 +771,7 @@ xfs_sb_mount_common(
mp->m_refc_mnr[1] = mp->m_refc_mxr[1] / 2;
mp->m_bsize = XFS_FSB_TO_BB(mp, 1);
- mp->m_ialloc_inos = (int)MAX((uint16_t)XFS_INODES_PER_CHUNK,
+ mp->m_ialloc_inos = max_t(uint16_t, XFS_INODES_PER_CHUNK,
sbp->sb_inopblock);
mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog;
@@ -970,14 +974,16 @@ xfs_sync_sb_buf(
struct xfs_mount *mp)
{
struct xfs_trans *tp;
+ struct xfs_buf *bp;
int error;
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, 0, &tp);
if (error)
return error;
+ bp = xfs_trans_getsb(tp, mp, 0);
xfs_log_sb(tp);
- xfs_trans_bhold(tp, mp->m_sb_bp);
+ xfs_trans_bhold(tp, bp);
xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp);
if (error)
@@ -985,9 +991,9 @@ xfs_sync_sb_buf(
/*
* write out the sb buffer to get the changes to disk
*/
- error = xfs_bwrite(mp->m_sb_bp);
+ error = xfs_bwrite(bp);
out:
- xfs_buf_relse(mp->m_sb_bp);
+ xfs_buf_relse(bp);
return error;
}
diff --git a/fs/xfs/libxfs/xfs_sb.h b/fs/xfs/libxfs/xfs_sb.h
index 244e0162c49e..13564d69800a 100644
--- a/fs/xfs/libxfs/xfs_sb.h
+++ b/fs/xfs/libxfs/xfs_sb.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SB_H__
#define __XFS_SB_H__
diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h
index ae99c260adb1..22089f1c880a 100644
--- a/fs/xfs/libxfs/xfs_shared.h
+++ b/fs/xfs/libxfs/xfs_shared.h
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SHARED_H__
#define __XFS_SHARED_H__
diff --git a/fs/xfs/libxfs/xfs_symlink_remote.c b/fs/xfs/libxfs/xfs_symlink_remote.c
index 5ef5f354587e..95374ab2dee7 100644
--- a/fs/xfs/libxfs/xfs_symlink_remote.c
+++ b/fs/xfs/libxfs/xfs_symlink_remote.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* Copyright (c) 2012-2013 Red Hat, Inc.
* All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c
index 3bccdf73e141..f99a7aefe418 100644
--- a/fs/xfs/libxfs/xfs_trans_resv.c
+++ b/fs/xfs/libxfs/xfs_trans_resv.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* Copyright (C) 2010 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -248,7 +236,7 @@ xfs_calc_write_reservation(
struct xfs_mount *mp)
{
return XFS_DQUOT_LOGRES(mp) +
- MAX((xfs_calc_inode_res(mp, 1) +
+ max((xfs_calc_inode_res(mp, 1) +
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
XFS_FSB_TO_B(mp, 1)) +
xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
@@ -275,7 +263,7 @@ xfs_calc_itruncate_reservation(
struct xfs_mount *mp)
{
return XFS_DQUOT_LOGRES(mp) +
- MAX((xfs_calc_inode_res(mp, 1) +
+ max((xfs_calc_inode_res(mp, 1) +
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1,
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
@@ -300,7 +288,7 @@ xfs_calc_rename_reservation(
struct xfs_mount *mp)
{
return XFS_DQUOT_LOGRES(mp) +
- MAX((xfs_calc_inode_res(mp, 4) +
+ max((xfs_calc_inode_res(mp, 4) +
xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp),
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) +
@@ -340,7 +328,7 @@ xfs_calc_link_reservation(
{
return XFS_DQUOT_LOGRES(mp) +
xfs_calc_iunlink_remove_reservation(mp) +
- MAX((xfs_calc_inode_res(mp, 2) +
+ max((xfs_calc_inode_res(mp, 2) +
xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
@@ -378,7 +366,7 @@ xfs_calc_remove_reservation(
{
return XFS_DQUOT_LOGRES(mp) +
xfs_calc_iunlink_add_reservation(mp) +
- MAX((xfs_calc_inode_res(mp, 1) +
+ max((xfs_calc_inode_res(mp, 1) +
xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) +
@@ -436,7 +424,7 @@ STATIC uint
xfs_calc_icreate_reservation(xfs_mount_t *mp)
{
return XFS_DQUOT_LOGRES(mp) +
- MAX(xfs_calc_icreate_resv_alloc(mp),
+ max(xfs_calc_icreate_resv_alloc(mp),
xfs_calc_create_resv_modify(mp));
}
@@ -644,7 +632,7 @@ STATIC uint
xfs_calc_attrinval_reservation(
struct xfs_mount *mp)
{
- return MAX((xfs_calc_inode_res(mp, 1) +
+ return max((xfs_calc_inode_res(mp, 1) +
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
@@ -708,7 +696,7 @@ xfs_calc_attrrm_reservation(
struct xfs_mount *mp)
{
return XFS_DQUOT_LOGRES(mp) +
- MAX((xfs_calc_inode_res(mp, 1) +
+ max((xfs_calc_inode_res(mp, 1) +
xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH,
XFS_FSB_TO_B(mp, 1)) +
(uint)XFS_FSB_TO_B(mp,
diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h
index b7e5357d060a..7241ab28cf84 100644
--- a/fs/xfs/libxfs/xfs_trans_resv.h
+++ b/fs/xfs/libxfs/xfs_trans_resv.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_TRANS_RESV_H__
#define __XFS_TRANS_RESV_H__
diff --git a/fs/xfs/libxfs/xfs_trans_space.h b/fs/xfs/libxfs/xfs_trans_space.h
index d787c677d2a3..a62fb950bef1 100644
--- a/fs/xfs/libxfs/xfs_trans_space.h
+++ b/fs/xfs/libxfs/xfs_trans_space.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_TRANS_SPACE_H__
#define __XFS_TRANS_SPACE_H__
diff --git a/fs/xfs/libxfs/xfs_types.c b/fs/xfs/libxfs/xfs_types.c
new file mode 100644
index 000000000000..2e2a243cef2e
--- /dev/null
+++ b/fs/xfs/libxfs/xfs_types.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
+ * Copyright (C) 2017 Oracle.
+ * All Rights Reserved.
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_format.h"
+#include "xfs_log_format.h"
+#include "xfs_shared.h"
+#include "xfs_trans_resv.h"
+#include "xfs_bit.h"
+#include "xfs_sb.h"
+#include "xfs_mount.h"
+#include "xfs_defer.h"
+#include "xfs_inode.h"
+#include "xfs_btree.h"
+#include "xfs_rmap.h"
+#include "xfs_alloc_btree.h"
+#include "xfs_alloc.h"
+#include "xfs_ialloc.h"
+
+/* Find the size of the AG, in blocks. */
+xfs_agblock_t
+xfs_ag_block_count(
+ struct xfs_mount *mp,
+ xfs_agnumber_t agno)
+{
+ ASSERT(agno < mp->m_sb.sb_agcount);
+
+ if (agno < mp->m_sb.sb_agcount - 1)
+ return mp->m_sb.sb_agblocks;
+ return mp->m_sb.sb_dblocks - (agno * mp->m_sb.sb_agblocks);
+}
+
+/*
+ * Verify that an AG block number pointer neither points outside the AG
+ * nor points at static metadata.
+ */
+bool
+xfs_verify_agbno(
+ struct xfs_mount *mp,
+ xfs_agnumber_t agno,
+ xfs_agblock_t agbno)
+{
+ xfs_agblock_t eoag;
+
+ eoag = xfs_ag_block_count(mp, agno);
+ if (agbno >= eoag)
+ return false;
+ if (agbno <= XFS_AGFL_BLOCK(mp))
+ return false;
+ return true;
+}
+
+/*
+ * Verify that an FS block number pointer neither points outside the
+ * filesystem nor points at static AG metadata.
+ */
+bool
+xfs_verify_fsbno(
+ struct xfs_mount *mp,
+ xfs_fsblock_t fsbno)
+{
+ xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, fsbno);
+
+ if (agno >= mp->m_sb.sb_agcount)
+ return false;
+ return xfs_verify_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno));
+}
+
+/* Calculate the first and last possible inode number in an AG. */
+void
+xfs_agino_range(
+ struct xfs_mount *mp,
+ xfs_agnumber_t agno,
+ xfs_agino_t *first,
+ xfs_agino_t *last)
+{
+ xfs_agblock_t bno;
+ xfs_agblock_t eoag;
+
+ eoag = xfs_ag_block_count(mp, agno);
+
+ /*
+ * Calculate the first inode, which will be in the first
+ * cluster-aligned block after the AGFL.
+ */
+ bno = round_up(XFS_AGFL_BLOCK(mp) + 1,
+ xfs_ialloc_cluster_alignment(mp));
+ *first = XFS_OFFBNO_TO_AGINO(mp, bno, 0);
+
+ /*
+ * Calculate the last inode, which will be at the end of the
+ * last (aligned) cluster that can be allocated in the AG.
+ */
+ bno = round_down(eoag, xfs_ialloc_cluster_alignment(mp));
+ *last = XFS_OFFBNO_TO_AGINO(mp, bno, 0) - 1;
+}
+
+/*
+ * Verify that an AG inode number pointer neither points outside the AG
+ * nor points at static metadata.
+ */
+bool
+xfs_verify_agino(
+ struct xfs_mount *mp,
+ xfs_agnumber_t agno,
+ xfs_agino_t agino)
+{
+ xfs_agino_t first;
+ xfs_agino_t last;
+
+ xfs_agino_range(mp, agno, &first, &last);
+ return agino >= first && agino <= last;
+}
+
+/*
+ * Verify that an FS inode number pointer neither points outside the
+ * filesystem nor points at static AG metadata.
+ */
+bool
+xfs_verify_ino(
+ struct xfs_mount *mp,
+ xfs_ino_t ino)
+{
+ xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ino);
+ xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino);
+
+ if (agno >= mp->m_sb.sb_agcount)
+ return false;
+ if (XFS_AGINO_TO_INO(mp, agno, agino) != ino)
+ return false;
+ return xfs_verify_agino(mp, agno, agino);
+}
+
+/* Is this an internal inode number? */
+bool
+xfs_internal_inum(
+ struct xfs_mount *mp,
+ xfs_ino_t ino)
+{
+ return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
+ (xfs_sb_version_hasquota(&mp->m_sb) &&
+ xfs_is_quota_inode(&mp->m_sb, ino));
+}
+
+/*
+ * Verify that a directory entry's inode number doesn't point at an internal
+ * inode, empty space, or static AG metadata.
+ */
+bool
+xfs_verify_dir_ino(
+ struct xfs_mount *mp,
+ xfs_ino_t ino)
+{
+ if (xfs_internal_inum(mp, ino))
+ return false;
+ return xfs_verify_ino(mp, ino);
+}
+
+/*
+ * Verify that an realtime block number pointer doesn't point off the
+ * end of the realtime device.
+ */
+bool
+xfs_verify_rtbno(
+ struct xfs_mount *mp,
+ xfs_rtblock_t rtbno)
+{
+ return rtbno < mp->m_sb.sb_rblocks;
+}
diff --git a/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h
index ea18449bd732..4055d62f690c 100644
--- a/fs/xfs/libxfs/xfs_types.h
+++ b/fs/xfs/libxfs/xfs_types.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_TYPES_H__
#define __XFS_TYPES_H__
@@ -159,4 +147,23 @@ typedef struct xfs_bmbt_irec
xfs_exntst_t br_state; /* extent state */
} xfs_bmbt_irec_t;
+/*
+ * Type verifier functions
+ */
+struct xfs_mount;
+
+xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
+bool xfs_verify_agbno(struct xfs_mount *mp, xfs_agnumber_t agno,
+ xfs_agblock_t agbno);
+bool xfs_verify_fsbno(struct xfs_mount *mp, xfs_fsblock_t fsbno);
+
+void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
+ xfs_agino_t *first, xfs_agino_t *last);
+bool xfs_verify_agino(struct xfs_mount *mp, xfs_agnumber_t agno,
+ xfs_agino_t agino);
+bool xfs_verify_ino(struct xfs_mount *mp, xfs_ino_t ino);
+bool xfs_internal_inum(struct xfs_mount *mp, xfs_ino_t ino);
+bool xfs_verify_dir_ino(struct xfs_mount *mp, xfs_ino_t ino);
+bool xfs_verify_rtbno(struct xfs_mount *mp, xfs_rtblock_t rtbno);
+
#endif /* __XFS_TYPES_H__ */
diff --git a/fs/xfs/mrlock.h b/fs/xfs/mrlock.h
index e3c92d19e540..79155eec341b 100644
--- a/fs/xfs/mrlock.h
+++ b/fs/xfs/mrlock.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SUPPORT_MRLOCK_H__
#define __XFS_SUPPORT_MRLOCK_H__
diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c
index 1f71793f7db4..9bb0745f1ad2 100644
--- a/fs/xfs/scrub/agheader.c
+++ b/fs/xfs/scrub/agheader.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -881,7 +867,7 @@ xfs_scrub_agi(
}
/* Check inode counters */
- xfs_ialloc_agino_range(mp, agno, &first_agino, &last_agino);
+ xfs_agino_range(mp, agno, &first_agino, &last_agino);
icount = be32_to_cpu(agi->agi_count);
if (icount > last_agino - first_agino + 1 ||
icount < be32_to_cpu(agi->agi_freecount))
diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c
index 8b91e9ebe1e7..117eedac53df 100644
--- a/fs/xfs/scrub/agheader_repair.c
+++ b/fs/xfs/scrub/agheader_repair.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2018 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/alloc.c b/fs/xfs/scrub/alloc.c
index 941a0a55224e..50e4f7fa06f0 100644
--- a/fs/xfs/scrub/alloc.c
+++ b/fs/xfs/scrub/alloc.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/attr.c b/fs/xfs/scrub/attr.c
index 84b6d6b66578..de51cf8a8516 100644
--- a/fs/xfs/scrub/attr.c
+++ b/fs/xfs/scrub/attr.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index eeadb33a701c..3d08589f5c60 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c
index 2d29dceaa00e..5b472045f036 100644
--- a/fs/xfs/scrub/btree.c
+++ b/fs/xfs/scrub/btree.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/btree.h b/fs/xfs/scrub/btree.h
index e2b868ede70b..956627500f2c 100644
--- a/fs/xfs/scrub/btree.h
+++ b/fs/xfs/scrub/btree.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_SCRUB_BTREE_H__
#define __XFS_SCRUB_BTREE_H__
diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
index 41198a5f872c..70e70c69f83f 100644
--- a/fs/xfs/scrub/common.c
+++ b/fs/xfs/scrub/common.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h
index 76bb2d1d808c..2172bd5361e2 100644
--- a/fs/xfs/scrub/common.h
+++ b/fs/xfs/scrub/common.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_SCRUB_COMMON_H__
#define __XFS_SCRUB_COMMON_H__
diff --git a/fs/xfs/scrub/dabtree.c b/fs/xfs/scrub/dabtree.c
index bffdb7dc09bf..d700c4d4d4ef 100644
--- a/fs/xfs/scrub/dabtree.c
+++ b/fs/xfs/scrub/dabtree.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/dabtree.h b/fs/xfs/scrub/dabtree.h
index d31468d68cef..365f9f0019e6 100644
--- a/fs/xfs/scrub/dabtree.h
+++ b/fs/xfs/scrub/dabtree.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_SCRUB_DABTREE_H__
#define __XFS_SCRUB_DABTREE_H__
diff --git a/fs/xfs/scrub/dir.c b/fs/xfs/scrub/dir.c
index 1a4309b3e786..86324775fc9b 100644
--- a/fs/xfs/scrub/dir.c
+++ b/fs/xfs/scrub/dir.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/ialloc.c b/fs/xfs/scrub/ialloc.c
index 00a834d3b56d..13d43d108574 100644
--- a/fs/xfs/scrub/ialloc.c
+++ b/fs/xfs/scrub/ialloc.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c
index 0c696f7018de..7a6208505980 100644
--- a/fs/xfs/scrub/inode.c
+++ b/fs/xfs/scrub/inode.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/parent.c b/fs/xfs/scrub/parent.c
index 77c6b22c6bfd..e2bda58c32f0 100644
--- a/fs/xfs/scrub/parent.c
+++ b/fs/xfs/scrub/parent.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/quota.c b/fs/xfs/scrub/quota.c
index 15ae4d23d6ac..6ff906aa0a3b 100644
--- a/fs/xfs/scrub/quota.c
+++ b/fs/xfs/scrub/quota.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/refcount.c b/fs/xfs/scrub/refcount.c
index 324a5f159145..607a9faa8ecc 100644
--- a/fs/xfs/scrub/refcount.c
+++ b/fs/xfs/scrub/refcount.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c
index e3e8fba1c99c..326be4e8b71e 100644
--- a/fs/xfs/scrub/repair.c
+++ b/fs/xfs/scrub/repair.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2018 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/repair.h b/fs/xfs/scrub/repair.h
index f2b0895294db..ef47826b6725 100644
--- a/fs/xfs/scrub/repair.h
+++ b/fs/xfs/scrub/repair.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2018 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_SCRUB_REPAIR_H__
#define __XFS_SCRUB_REPAIR_H__
diff --git a/fs/xfs/scrub/rmap.c b/fs/xfs/scrub/rmap.c
index b376a9a77c04..c6d763236ba7 100644
--- a/fs/xfs/scrub/rmap.c
+++ b/fs/xfs/scrub/rmap.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/rtbitmap.c b/fs/xfs/scrub/rtbitmap.c
index 40f462a11ea5..1f86e02a07ca 100644
--- a/fs/xfs/scrub/rtbitmap.c
+++ b/fs/xfs/scrub/rtbitmap.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c
index 36db098ba583..58ae76b3a421 100644
--- a/fs/xfs/scrub/scrub.c
+++ b/fs/xfs/scrub/scrub.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h
index 636424d5e2ee..b295edd5fc0e 100644
--- a/fs/xfs/scrub/scrub.h
+++ b/fs/xfs/scrub/scrub.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_SCRUB_SCRUB_H__
#define __XFS_SCRUB_SCRUB_H__
diff --git a/fs/xfs/scrub/symlink.c b/fs/xfs/scrub/symlink.c
index 3aa3d60f7c16..570a89812116 100644
--- a/fs/xfs/scrub/symlink.c
+++ b/fs/xfs/scrub/symlink.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/trace.c b/fs/xfs/scrub/trace.c
index 86daed0e3a45..7c76d8b5cb05 100644
--- a/fs/xfs/scrub/trace.c
+++ b/fs/xfs/scrub/trace.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h
index 794d56bb1af8..cec3e5ece5a1 100644
--- a/fs/xfs/scrub/trace.h
+++ b/fs/xfs/scrub/trace.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM xfs_scrub
diff --git a/fs/xfs/scrub/xfs_scrub.h b/fs/xfs/scrub/xfs_scrub.h
index e00e0eadac6a..2897ba3a17e6 100644
--- a/fs/xfs/scrub/xfs_scrub.h
+++ b/fs/xfs/scrub/xfs_scrub.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_SCRUB_H__
#define __XFS_SCRUB_H__
diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h
index 5ff7f228d616..583a9f539bf1 100644
--- a/fs/xfs/xfs.h
+++ b/fs/xfs/xfs.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_H__
#define __XFS_H__
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 3354140de07e..8039e35147dd 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2008, Christoph Hellwig
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_format.h"
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 04327318ef67..94615e34bc86 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2001-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ACL_H__
#define __XFS_ACL_H__
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index ca6903726689..8eb3ba3d4d00 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_shared.h"
@@ -543,8 +531,19 @@ xfs_submit_ioend(
{
/* Convert CoW extents to regular */
if (!status && ioend->io_type == XFS_IO_COW) {
+ /*
+ * Yuk. This can do memory allocation, but is not a
+ * transactional operation so everything is done in GFP_KERNEL
+ * context. That can deadlock, because we hold pages in
+ * writeback state and GFP_KERNEL allocations can block on them.
+ * Hence we must operate in nofs conditions here.
+ */
+ unsigned nofs_flag;
+
+ nofs_flag = memalloc_nofs_save();
status = xfs_reflink_convert_cow(XFS_I(ioend->io_inode),
ioend->io_offset, ioend->io_size);
+ memalloc_nofs_restore(nofs_flag);
}
/* Reserve log space if we might write beyond the on-disk inode size. */
diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h
index 694c85b03813..25bc6d4a1231 100644
--- a/fs/xfs/xfs_aops.h
+++ b/fs/xfs/xfs_aops.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2005-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_AOPS_H__
#define __XFS_AOPS_H__
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
index d07bf27451c9..033ff8c478e2 100644
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ATTR_H__
#define __XFS_ATTR_H__
diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
index 52818ea2eb50..7ce10055f275 100644
--- a/fs/xfs/xfs_attr_inactive.c
+++ b/fs/xfs/xfs_attr_inactive.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c
index 3e59a348ea71..f9ca80154c9c 100644
--- a/fs/xfs/xfs_attr_list.c
+++ b/fs/xfs/xfs_attr_list.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -139,7 +127,8 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
((char *)sfe >= ((char *)sf + dp->i_afp->if_bytes)))) {
XFS_CORRUPTION_ERROR("xfs_attr_shortform_list",
XFS_ERRLEVEL_LOW,
- context->dp->i_mount, sfe);
+ context->dp->i_mount, sfe,
+ sizeof(*sfe));
kmem_free(sbuf);
return -EFSCORRUPTED;
}
@@ -241,7 +230,7 @@ xfs_attr_node_list_lookup(
if (magic != XFS_DA_NODE_MAGIC &&
magic != XFS_DA3_NODE_MAGIC) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
- node);
+ node, sizeof(*node));
goto out_corruptbuf;
}
diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index 618bb71535c8..956ebd583e27 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_bmap_item.h b/fs/xfs/xfs_bmap_item.h
index 24b354a2c836..fd1a1b13df51 100644
--- a/fs/xfs/xfs_bmap_item.h
+++ b/fs/xfs/xfs_bmap_item.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_BMAP_ITEM_H__
#define __XFS_BMAP_ITEM_H__
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 06badcbadeb4..c35009a86699 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* Copyright (c) 2012 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -92,6 +80,7 @@ xfs_bmap_rtalloc(
int error; /* error return value */
xfs_mount_t *mp; /* mount point structure */
xfs_extlen_t prod = 0; /* product factor for allocators */
+ xfs_extlen_t mod = 0; /* product factor for allocators */
xfs_extlen_t ralen = 0; /* realtime allocation length */
xfs_extlen_t align; /* minimum allocation alignment */
xfs_rtblock_t rtb;
@@ -111,7 +100,8 @@ xfs_bmap_rtalloc(
* If the offset & length are not perfectly aligned
* then kill prod, it will just get us in trouble.
*/
- if (do_mod(ap->offset, align) || ap->length % align)
+ div_u64_rem(ap->offset, align, &mod);
+ if (mod || ap->length % align)
prod = 1;
/*
* Set ralen to be the actual requested length in rtextents.
@@ -948,9 +938,11 @@ xfs_alloc_file_space(
do_div(s, extsz);
s *= extsz;
e = startoffset_fsb + allocatesize_fsb;
- if ((temp = do_mod(startoffset_fsb, extsz)))
+ div_u64_rem(startoffset_fsb, extsz, &temp);
+ if (temp)
e += temp;
- if ((temp = do_mod(e, extsz)))
+ div_u64_rem(e, extsz, &temp);
+ if (temp)
e += extsz - temp;
} else {
s = 0;
@@ -1111,7 +1103,7 @@ xfs_adjust_extent_unmap_boundaries(
if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
- mod = do_mod(imap.br_startblock, mp->m_sb.sb_rextsize);
+ div_u64_rem(imap.br_startblock, mp->m_sb.sb_rextsize, &mod);
if (mod)
*startoffset_fsb += mp->m_sb.sb_rextsize - mod;
}
diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h
index 4d4ae48bd4f6..87363d136bb6 100644
--- a/fs/xfs/xfs_bmap_util.h
+++ b/fs/xfs/xfs_bmap_util.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BMAP_UTIL_H__
#define __XFS_BMAP_UTIL_H__
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 5179ab9e3d6a..e9c058e3761c 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include <linux/stddef.h>
@@ -33,7 +21,6 @@
#include <linux/migrate.h>
#include <linux/backing-dev.h>
#include <linux/freezer.h>
-#include <linux/sched/mm.h>
#include "xfs_format.h"
#include "xfs_log_format.h"
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index f5f2b71c2fde..d24dbd4dac39 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BUF_H__
#define __XFS_BUF_H__
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index c2311379d1c3..1c9d1398980b 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -842,7 +830,7 @@ xfs_buf_item_log_segment(
* of the last bit to be set in this word plus one.
*/
if (bit) {
- end_bit = MIN(bit + bits_to_set, (uint)NBWORD);
+ end_bit = min(bit + bits_to_set, (uint)NBWORD);
mask = ((1U << (end_bit - bit)) - 1) << bit;
*wordp |= mask;
wordp++;
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index 643f53dcfe51..3f7d7b72e7e6 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BUF_ITEM_H__
#define __XFS_BUF_ITEM_H__
diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c
index b6ae3597bfb0..5142e64e2345 100644
--- a/fs/xfs/xfs_dir2_readdir.c
+++ b/fs/xfs/xfs_dir2_readdir.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c
index 7b68e6c9a474..678a5fcd7576 100644
--- a/fs/xfs/xfs_discard.c
+++ b/fs/xfs/xfs_discard.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2010 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_format.h"
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 2567391489bd..0973a0423bed 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index bdd6bd921528..64bd8640f6e8 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_DQUOT_H__
#define __XFS_DQUOT_H__
diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c
index 8eb7415474d6..7dedd17c4813 100644
--- a/fs/xfs/xfs_dquot_item.c
+++ b/fs/xfs/xfs_dquot_item.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_dquot_item.h b/fs/xfs/xfs_dquot_item.h
index 502e9464634a..db9df710a308 100644
--- a/fs/xfs/xfs_dquot_item.h
+++ b/fs/xfs/xfs_dquot_item.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_DQUOT_ITEM_H__
#define __XFS_DQUOT_ITEM_H__
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 7975634cb8fe..0470114a8d80 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_format.h"
@@ -334,13 +322,14 @@ xfs_corruption_error(
const char *tag,
int level,
struct xfs_mount *mp,
- void *p,
+ void *buf,
+ size_t bufsize,
const char *filename,
int linenum,
xfs_failaddr_t failaddr)
{
if (level <= xfs_error_level)
- xfs_hex_dump(p, XFS_CORRUPTION_DUMP_LEN);
+ xfs_hex_dump(buf, bufsize);
xfs_error_report(tag, level, mp, filename, linenum, failaddr);
xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair");
}
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index ce391349e78b..246d3e989c6c 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ERROR_H__
#define __XFS_ERROR_H__
@@ -24,8 +12,9 @@ extern void xfs_error_report(const char *tag, int level, struct xfs_mount *mp,
const char *filename, int linenum,
xfs_failaddr_t failaddr);
extern void xfs_corruption_error(const char *tag, int level,
- struct xfs_mount *mp, void *p, const char *filename,
- int linenum, xfs_failaddr_t failaddr);
+ struct xfs_mount *mp, void *buf, size_t bufsize,
+ const char *filename, int linenum,
+ xfs_failaddr_t failaddr);
extern void xfs_buf_verifier_error(struct xfs_buf *bp, int error,
const char *name, void *buf, size_t bufsz,
xfs_failaddr_t failaddr);
@@ -37,8 +26,8 @@ extern void xfs_inode_verifier_error(struct xfs_inode *ip, int error,
#define XFS_ERROR_REPORT(e, lvl, mp) \
xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address)
-#define XFS_CORRUPTION_ERROR(e, lvl, mp, mem) \
- xfs_corruption_error(e, lvl, mp, mem, \
+#define XFS_CORRUPTION_ERROR(e, lvl, mp, buf, bufsize) \
+ xfs_corruption_error(e, lvl, mp, buf, bufsize, \
__FILE__, __LINE__, __return_address)
#define XFS_ERRLEVEL_OFF 0
diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c
index eed698aa9f16..3cf4682e2510 100644
--- a/fs/xfs/xfs_export.c
+++ b/fs/xfs/xfs_export.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2004-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_format.h"
@@ -140,15 +128,24 @@ xfs_nfs_get_inode(
*/
error = xfs_iget(mp, NULL, ino, XFS_IGET_UNTRUSTED, 0, &ip);
if (error) {
+
/*
* EINVAL means the inode cluster doesn't exist anymore.
- * This implies the filehandle is stale, so we should
- * translate it here.
+ * EFSCORRUPTED means the metadata pointing to the inode cluster
+ * or the inode cluster itself is corrupt. This implies the
+ * filehandle is stale, so we should translate it here.
* We don't use ESTALE directly down the chain to not
* confuse applications using bulkstat that expect EINVAL.
*/
- if (error == -EINVAL || error == -ENOENT)
+ switch (error) {
+ case -EINVAL:
+ case -ENOENT:
+ case -EFSCORRUPTED:
error = -ESTALE;
+ break;
+ default:
+ break;
+ }
return ERR_PTR(error);
}
diff --git a/fs/xfs/xfs_export.h b/fs/xfs/xfs_export.h
index 3272b6ae7a35..64471a3ddb04 100644
--- a/fs/xfs/xfs_export.h
+++ b/fs/xfs/xfs_export.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_EXPORT_H__
#define __XFS_EXPORT_H__
diff --git a/fs/xfs/xfs_extent_busy.c b/fs/xfs/xfs_extent_busy.c
index 13e3d1a69e76..0ed68379e551 100644
--- a/fs/xfs/xfs_extent_busy.c
+++ b/fs/xfs/xfs_extent_busy.c
@@ -1,21 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* Copyright (c) 2010 David Chinner.
* Copyright (c) 2011 Christoph Hellwig.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_extent_busy.h b/fs/xfs/xfs_extent_busy.h
index 60195ea1b84a..990ab3891971 100644
--- a/fs/xfs/xfs_extent_busy.h
+++ b/fs/xfs/xfs_extent_busy.h
@@ -1,21 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* Copyright (c) 2010 David Chinner.
* Copyright (c) 2011 Christoph Hellwig.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_EXTENT_BUSY_H__
#define __XFS_EXTENT_BUSY_H__
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index a889b550979a..d9da66c718bb 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h
index a32c794a86b7..2a6a895ca73e 100644
--- a/fs/xfs/xfs_extfree_item.h
+++ b/fs/xfs/xfs_extfree_item.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_EXTFREE_ITEM_H__
#define __XFS_EXTFREE_ITEM_H__
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index bed07dfbb85e..a3e7767a5715 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
index 3f8722e51dbe..2d2c5ab9143c 100644
--- a/fs/xfs/xfs_filestream.c
+++ b/fs/xfs/xfs_filestream.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2006-2007 Silicon Graphics, Inc.
* Copyright (c) 2014 Christoph Hellwig.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_format.h"
diff --git a/fs/xfs/xfs_filestream.h b/fs/xfs/xfs_filestream.h
index 2ef43406e53b..5cc7665e93c9 100644
--- a/fs/xfs/xfs_filestream.h
+++ b/fs/xfs/xfs_filestream.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2006-2007 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_FILESTREAM_H__
#define __XFS_FILESTREAM_H__
diff --git a/fs/xfs/xfs_fsmap.c b/fs/xfs/xfs_fsmap.c
index 0299febece9c..c34fa9c342f2 100644
--- a/fs/xfs/xfs_fsmap.c
+++ b/fs/xfs/xfs_fsmap.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_fsmap.h b/fs/xfs/xfs_fsmap.h
index 0b9bf822595c..c6c57739b862 100644
--- a/fs/xfs/xfs_fsmap.h
+++ b/fs/xfs/xfs_fsmap.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_FSMAP_H__
#define __XFS_FSMAP_H__
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index bc7ef18da243..a7afcad6b711 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_fsops.h b/fs/xfs/xfs_fsops.h
index 20484ed5e919..d023db0862c2 100644
--- a/fs/xfs/xfs_fsops.h
+++ b/fs/xfs/xfs_fsops.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_FSOPS_H__
#define __XFS_FSOPS_H__
diff --git a/fs/xfs/xfs_globals.c b/fs/xfs/xfs_globals.c
index fdde17a2333c..5169e84ae382 100644
--- a/fs/xfs/xfs_globals.c
+++ b/fs/xfs/xfs_globals.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_sysctl.h"
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 164350d91efc..47f417d20a30 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index d69a0f5a6a73..26c0626f1f75 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef XFS_SYNC_H
#define XFS_SYNC_H 1
diff --git a/fs/xfs/xfs_icreate_item.c b/fs/xfs/xfs_icreate_item.c
index 5da9599156ed..8381d34cb102 100644
--- a/fs/xfs/xfs_icreate_item.c
+++ b/fs/xfs/xfs_icreate_item.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2008-2010, 2013 Dave Chinner
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_icreate_item.h b/fs/xfs/xfs_icreate_item.h
index 59e89f87c09b..a50d0b01e15a 100644
--- a/fs/xfs/xfs_icreate_item.h
+++ b/fs/xfs/xfs_icreate_item.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2008-2010, Dave Chinner
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef XFS_ICREATE_ITEM_H
#define XFS_ICREATE_ITEM_H 1
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 05207a64dd53..7a96c4e0ab5c 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/log2.h>
#include <linux/iversion.h>
@@ -773,7 +761,7 @@ xfs_ialloc(
xfs_inode_t *ip;
uint flags;
int error;
- struct timespec tv;
+ struct timespec64 tv;
struct inode *inode;
/*
@@ -2090,10 +2078,15 @@ xfs_iunlink_remove(
* list this inode will go on.
*/
agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
- ASSERT(agino != 0);
+ if (!xfs_verify_agino(mp, agno, agino))
+ return -EFSCORRUPTED;
bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS;
- ASSERT(agi->agi_unlinked[bucket_index] != cpu_to_be32(NULLAGINO));
- ASSERT(agi->agi_unlinked[bucket_index]);
+ if (!xfs_verify_agino(mp, agno,
+ be32_to_cpu(agi->agi_unlinked[bucket_index]))) {
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+ agi, sizeof(*agi));
+ return -EFSCORRUPTED;
+ }
if (be32_to_cpu(agi->agi_unlinked[bucket_index]) == agino) {
/*
@@ -2171,8 +2164,12 @@ xfs_iunlink_remove(
last_offset = imap.im_boffset;
next_agino = be32_to_cpu(last_dip->di_next_unlinked);
- ASSERT(next_agino != NULLAGINO);
- ASSERT(next_agino != 0);
+ if (!xfs_verify_agino(mp, agno, next_agino)) {
+ XFS_CORRUPTION_ERROR(__func__,
+ XFS_ERRLEVEL_LOW, mp,
+ last_dip, sizeof(*last_dip));
+ return -EFSCORRUPTED;
+ }
}
/*
@@ -2261,7 +2258,7 @@ xfs_ifree_cluster(
*/
ioffset = inum - xic->first_ino;
if ((xic->alloc & XFS_INOBT_MASK(ioffset)) == 0) {
- ASSERT(do_mod(ioffset, inodes_per_cluster) == 0);
+ ASSERT(ioffset % inodes_per_cluster == 0);
continue;
}
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index a91d9fb1effc..2ed63a49e890 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_INODE_H__
#define __XFS_INODE_H__
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 3e5b8574818e..2389c34c172d 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h
index b72373a33cd9..27081eba220c 100644
--- a/fs/xfs/xfs_inode_item.h
+++ b/fs/xfs/xfs_inode_item.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_INODE_ITEM_H__
#define __XFS_INODE_ITEM_H__
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 32b680522abd..0ef5ece5634c 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -1094,12 +1082,14 @@ xfs_ioctl_setattr_dax_invalidate(
/*
* It is only valid to set the DAX flag on regular files and
* directories on filesystems where the block size is equal to the page
- * size. On directories it serves as an inherit hint.
+ * size. On directories it serves as an inherited hint so we don't
+ * have to check the device for dax support or flush pagecache.
*/
if (fa->fsx_xflags & FS_XFLAG_DAX) {
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
return -EINVAL;
- if (!bdev_dax_supported(xfs_find_bdev_for_inode(VFS_I(ip)),
+ if (S_ISREG(inode->i_mode) &&
+ !bdev_dax_supported(xfs_find_bdev_for_inode(VFS_I(ip)),
sb->s_blocksize))
return -EINVAL;
}
@@ -1110,6 +1100,9 @@ xfs_ioctl_setattr_dax_invalidate(
if (!(fa->fsx_xflags & FS_XFLAG_DAX) && !IS_DAX(inode))
return 0;
+ if (S_ISDIR(inode->i_mode))
+ return 0;
+
/* lock, flush and invalidate mapping in preparation for flag change */
xfs_ilock(ip, XFS_MMAPLOCK_EXCL | XFS_IOLOCK_EXCL);
error = filemap_write_and_wait(inode->i_mapping);
@@ -1819,13 +1812,13 @@ xfs_ioc_getlabel(
/* Paranoia */
BUILD_BUG_ON(sizeof(sbp->sb_fname) > FSLABEL_MAX);
+ /* 1 larger than sb_fname, so this ensures a trailing NUL char */
+ memset(label, 0, sizeof(label));
spin_lock(&mp->m_sb_lock);
- strncpy(label, sbp->sb_fname, sizeof(sbp->sb_fname));
+ strncpy(label, sbp->sb_fname, XFSLABEL_MAX);
spin_unlock(&mp->m_sb_lock);
- /* xfs on-disk label is 12 chars, be sure we send a null to user */
- label[XFSLABEL_MAX] = '\0';
- if (copy_to_user(user_label, label, sizeof(sbp->sb_fname)))
+ if (copy_to_user(user_label, label, sizeof(label)))
return -EFAULT;
return 0;
}
@@ -1861,7 +1854,7 @@ xfs_ioc_setlabel(
spin_lock(&mp->m_sb_lock);
memset(sbp->sb_fname, 0, sizeof(sbp->sb_fname));
- strncpy(sbp->sb_fname, label, sizeof(sbp->sb_fname));
+ memcpy(sbp->sb_fname, label, len);
spin_unlock(&mp->m_sb_lock);
/*
diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
index 8de879f0c7d5..4b17f67c888a 100644
--- a/fs/xfs/xfs_ioctl.h
+++ b/fs/xfs/xfs_ioctl.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2008 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_IOCTL_H__
#define __XFS_IOCTL_H__
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index 10fbde359649..fba115f4103a 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2004-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/compat.h>
#include <linux/ioctl.h>
diff --git a/fs/xfs/xfs_ioctl32.h b/fs/xfs/xfs_ioctl32.h
index 5492bcf6f442..d28fa824284a 100644
--- a/fs/xfs/xfs_ioctl32.h
+++ b/fs/xfs/xfs_ioctl32.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2004-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_IOCTL32_H__
#define __XFS_IOCTL32_H__
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index c6ce6f9335b6..49f5492eed3b 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* Copyright (c) 2016 Christoph Hellwig.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/iomap.h>
#include "xfs.h"
@@ -200,7 +188,7 @@ xfs_iomap_write_direct(
goto out_unlock;
} else {
if (nmaps && (imap->br_startblock == HOLESTARTBLOCK))
- last_fsb = MIN(last_fsb, (xfs_fileoff_t)
+ last_fsb = min(last_fsb, (xfs_fileoff_t)
imap->br_blockcount +
imap->br_startoff);
}
@@ -488,8 +476,8 @@ xfs_iomap_prealloc_size(
* The shift throttle value is set to the maximum value as determined by
* the global low free space values and per-quota low free space values.
*/
- alloc_blocks = MIN(alloc_blocks, qblocks);
- shift = MAX(shift, qshift);
+ alloc_blocks = min(alloc_blocks, qblocks);
+ shift = max(shift, qshift);
if (shift)
alloc_blocks >>= shift;
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
index ee535065c5d0..83474c9cede9 100644
--- a/fs/xfs/xfs_iomap.h
+++ b/fs/xfs/xfs_iomap.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2003-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_IOMAP_H__
#define __XFS_IOMAP_H__
@@ -42,10 +30,10 @@ xfs_aligned_fsb_count(
if (extsz) {
xfs_extlen_t align;
- align = do_mod(offset_fsb, extsz);
+ div_u64_rem(offset_fsb, extsz, &align);
if (align)
count_fsb += align;
- align = do_mod(count_fsb, extsz);
+ div_u64_rem(count_fsb, extsz, &align);
if (align)
count_fsb += extsz - align;
}
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 3b4be06fdaa5..0fa29f39d658 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -1054,7 +1042,7 @@ xfs_vn_setattr(
STATIC int
xfs_vn_update_time(
struct inode *inode,
- struct timespec *now,
+ struct timespec64 *now,
int flags)
{
struct xfs_inode *ip = XFS_I(inode);
@@ -1274,6 +1262,14 @@ xfs_setup_inode(
xfs_diflags_to_iflags(inode, ip);
if (S_ISDIR(inode->i_mode)) {
+ /*
+ * We set the i_rwsem class here to avoid potential races with
+ * lockdep_annotate_inode_mutex_key() reinitialising the lock
+ * after a filehandle lookup has already found the inode in
+ * cache before it has been unlocked via unlock_new_inode().
+ */
+ lockdep_set_class(&inode->i_rwsem,
+ &inode->i_sb->s_type->i_mutex_dir_key);
lockdep_set_class(&ip->i_lock.mr_lock, &xfs_dir_ilock_class);
ip->d_ops = ip->i_mount->m_dir_inode_ops;
} else {
diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h
index 0259a383721a..4d24ff309f59 100644
--- a/fs/xfs/xfs_iops.h
+++ b/fs/xfs/xfs_iops.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_IOPS_H__
#define __XFS_IOPS_H__
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index d58310514423..24f4f1c555b5 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -571,7 +559,7 @@ xfs_inumbers(
*lastino != XFS_AGINO_TO_INO(mp, agno, agino))
return error;
- bcount = MIN(left, (int)(PAGE_SIZE / sizeof(*buffer)));
+ bcount = min(left, (int)(PAGE_SIZE / sizeof(*buffer)));
buffer = kmem_zalloc(bcount * sizeof(*buffer), KM_SLEEP);
do {
struct xfs_inobt_rec_incore r;
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index 6ea8b3912fa4..8a822285b671 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -1,18 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ITABLE_H__
#define __XFS_ITABLE_H__
diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h
index bee51a14a906..edbd5a210df2 100644
--- a/fs/xfs/xfs_linux.h
+++ b/fs/xfs/xfs_linux.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_LINUX__
#define __XFS_LINUX__
@@ -38,6 +26,7 @@ typedef __u32 xfs_nlink_t;
#include <linux/semaphore.h>
#include <linux/mm.h>
+#include <linux/sched/mm.h>
#include <linux/kernel.h>
#include <linux/blkdev.h>
#include <linux/slab.h>
@@ -151,8 +140,6 @@ typedef __u32 xfs_nlink_t;
#define XFS_PROJID_DEFAULT 0
-#define MIN(a,b) (min(a,b))
-#define MAX(a,b) (max(a,b))
#define howmany(x, y) (((x)+((y)-1))/(y))
static inline void delay(long ticks)
@@ -220,25 +207,6 @@ static inline xfs_dev_t linux_to_xfs_dev_t(dev_t dev)
#define xfs_sort(a,n,s,fn) sort(a,n,s,fn,NULL)
#define xfs_stack_trace() dump_stack()
-/* Side effect free 64 bit mod operation */
-static inline __u32 xfs_do_mod(void *a, __u32 b, int n)
-{
- switch (n) {
- case 4:
- return *(__u32 *)a % b;
- case 8:
- {
- __u64 c = *(__u64 *)a;
- return do_div(c, b);
- }
- }
-
- /* NOTREACHED */
- return 0;
-}
-
-#define do_mod(a, b) xfs_do_mod(&(a), (b), sizeof(a))
-
static inline uint64_t roundup_64(uint64_t x, uint32_t y)
{
x += y - 1;
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index c21039f27e39..5e56f3b93d4b 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -1641,8 +1629,8 @@ xlog_grant_push_ail(
* log, and 256 blocks.
*/
free_threshold = BTOBB(need_bytes);
- free_threshold = MAX(free_threshold, (log->l_logBBsize >> 2));
- free_threshold = MAX(free_threshold, 256);
+ free_threshold = max(free_threshold, (log->l_logBBsize >> 2));
+ free_threshold = max(free_threshold, 256);
if (free_blocks >= free_threshold)
return;
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index fa8ad31d587f..3c1f6a8b4b70 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_LOG_H__
#define __XFS_LOG_H__
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index c15687724728..d3884e08b43c 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -1,18 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2010 Red Hat, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 129975970d99..b5f82cb36202 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_LOG_PRIV_H__
#define __XFS_LOG_PRIV_H__
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 06a09cb948b5..b181b5f57a19 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -1248,6 +1236,25 @@ xlog_verify_head(
}
/*
+ * We need to make sure we handle log wrapping properly, so we can't use the
+ * calculated logbno directly. Make sure it wraps to the correct bno inside the
+ * log.
+ *
+ * The log is limited to 32 bit sizes, so we use the appropriate modulus
+ * operation here and cast it back to a 64 bit daddr on return.
+ */
+static inline xfs_daddr_t
+xlog_wrap_logbno(
+ struct xlog *log,
+ xfs_daddr_t bno)
+{
+ int mod;
+
+ div_s64_rem(bno, log->l_logBBsize, &mod);
+ return mod;
+}
+
+/*
* Check whether the head of the log points to an unmount record. In other
* words, determine whether the log is clean. If so, update the in-core state
* appropriately.
@@ -1295,12 +1302,13 @@ xlog_check_unmount_rec(
} else {
hblks = 1;
}
- after_umount_blk = rhead_blk + hblks + BTOBB(be32_to_cpu(rhead->h_len));
- after_umount_blk = do_mod(after_umount_blk, log->l_logBBsize);
+
+ after_umount_blk = xlog_wrap_logbno(log,
+ rhead_blk + hblks + BTOBB(be32_to_cpu(rhead->h_len)));
+
if (*head_blk == after_umount_blk &&
be32_to_cpu(rhead->h_num_logops) == 1) {
- umount_data_blk = rhead_blk + hblks;
- umount_data_blk = do_mod(umount_data_blk, log->l_logBBsize);
+ umount_data_blk = xlog_wrap_logbno(log, rhead_blk + hblks);
error = xlog_bread(log, umount_data_blk, 1, bp, &offset);
if (error)
return error;
@@ -1816,7 +1824,7 @@ xlog_clear_stale_blocks(
* we don't waste all day writing from the head to the tail
* for no reason.
*/
- max_distance = MIN(max_distance, tail_distance);
+ max_distance = min(max_distance, tail_distance);
if ((head_block + max_distance) <= log->l_logBBsize) {
/*
@@ -2884,14 +2892,14 @@ xlog_recover_buffer_pass2(
* buffers in the log can be a different size if the log was generated
* by an older kernel using unclustered inode buffers or a newer kernel
* running with a different inode cluster size. Regardless, if the
- * the inode buffer size isn't MAX(blocksize, mp->m_inode_cluster_size)
+ * the inode buffer size isn't max(blocksize, mp->m_inode_cluster_size)
* for *our* value of mp->m_inode_cluster_size, then we need to keep
* the buffer out of the buffer cache so that the buffer won't
* overlap with future reads of those inodes.
*/
if (XFS_DINODE_MAGIC ==
be16_to_cpu(*((__be16 *)xfs_buf_offset(bp, 0))) &&
- (BBTOB(bp->b_io_length) != MAX(log->l_mp->m_sb.sb_blocksize,
+ (BBTOB(bp->b_io_length) != max(log->l_mp->m_sb.sb_blocksize,
(uint32_t)log->l_mp->m_inode_cluster_size))) {
xfs_buf_stale(bp);
error = xfs_bwrite(bp);
@@ -3115,7 +3123,8 @@ xlog_recover_inode_pass2(
if ((ldip->di_format != XFS_DINODE_FMT_EXTENTS) &&
(ldip->di_format != XFS_DINODE_FMT_BTREE)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)",
- XFS_ERRLEVEL_LOW, mp, ldip);
+ XFS_ERRLEVEL_LOW, mp, ldip,
+ sizeof(*ldip));
xfs_alert(mp,
"%s: Bad regular inode log record, rec ptr "PTR_FMT", "
"ino ptr = "PTR_FMT", ino bp = "PTR_FMT", ino %Ld",
@@ -3128,7 +3137,8 @@ xlog_recover_inode_pass2(
(ldip->di_format != XFS_DINODE_FMT_BTREE) &&
(ldip->di_format != XFS_DINODE_FMT_LOCAL)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)",
- XFS_ERRLEVEL_LOW, mp, ldip);
+ XFS_ERRLEVEL_LOW, mp, ldip,
+ sizeof(*ldip));
xfs_alert(mp,
"%s: Bad dir inode log record, rec ptr "PTR_FMT", "
"ino ptr = "PTR_FMT", ino bp = "PTR_FMT", ino %Ld",
@@ -3139,7 +3149,8 @@ xlog_recover_inode_pass2(
}
if (unlikely(ldip->di_nextents + ldip->di_anextents > ldip->di_nblocks)){
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)",
- XFS_ERRLEVEL_LOW, mp, ldip);
+ XFS_ERRLEVEL_LOW, mp, ldip,
+ sizeof(*ldip));
xfs_alert(mp,
"%s: Bad inode log record, rec ptr "PTR_FMT", dino ptr "PTR_FMT", "
"dino bp "PTR_FMT", ino %Ld, total extents = %d, nblocks = %Ld",
@@ -3151,7 +3162,8 @@ xlog_recover_inode_pass2(
}
if (unlikely(ldip->di_forkoff > mp->m_sb.sb_inodesize)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)",
- XFS_ERRLEVEL_LOW, mp, ldip);
+ XFS_ERRLEVEL_LOW, mp, ldip,
+ sizeof(*ldip));
xfs_alert(mp,
"%s: Bad inode log record, rec ptr "PTR_FMT", dino ptr "PTR_FMT", "
"dino bp "PTR_FMT", ino %Ld, forkoff 0x%x", __func__,
@@ -3162,7 +3174,8 @@ xlog_recover_inode_pass2(
isize = xfs_log_dinode_size(ldip->di_version);
if (unlikely(item->ri_buf[1].i_len > isize)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)",
- XFS_ERRLEVEL_LOW, mp, ldip);
+ XFS_ERRLEVEL_LOW, mp, ldip,
+ sizeof(*ldip));
xfs_alert(mp,
"%s: Bad inode log record length %d, rec ptr "PTR_FMT,
__func__, item->ri_buf[1].i_len, item);
@@ -5466,9 +5479,7 @@ xlog_do_recovery_pass(
*/
if (blk_no + bblks <= log->l_logBBsize ||
blk_no >= log->l_logBBsize) {
- /* mod blk_no in case the header wrapped and
- * pushed it beyond the end of the log */
- rblk_no = do_mod(blk_no, log->l_logBBsize);
+ rblk_no = xlog_wrap_logbno(log, blk_no);
error = xlog_bread(log, rblk_no, bblks, dbp,
&offset);
if (error)
diff --git a/fs/xfs/xfs_message.c b/fs/xfs/xfs_message.c
index e68bd1050eab..576c375ce12a 100644
--- a/fs/xfs/xfs_message.c
+++ b/fs/xfs/xfs_message.c
@@ -1,18 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2011 Red Hat, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 73ed8fec0328..a3378252baa1 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -874,9 +862,12 @@ xfs_mountfs(
* Get and sanity-check the root inode.
* Save the pointer to it in the mount structure.
*/
- error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip);
+ error = xfs_iget(mp, NULL, sbp->sb_rootino, XFS_IGET_UNTRUSTED,
+ XFS_ILOCK_EXCL, &rip);
if (error) {
- xfs_warn(mp, "failed to read root inode");
+ xfs_warn(mp,
+ "Failed to read root inode 0x%llx, error %d",
+ sbp->sb_rootino, -error);
goto out_log_dealloc;
}
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 10b90bbc5162..245349d1e23f 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_MOUNT_H__
#define __XFS_MOUNT_H__
@@ -283,7 +271,7 @@ xfs_preferred_iosize(xfs_mount_t *mp)
return (mp->m_swidth ?
(mp->m_swidth << mp->m_sb.sb_blocklog) :
((mp->m_flags & XFS_MOUNT_DFLT_IOSIZE) ?
- (1 << (int)MAX(mp->m_readio_log, mp->m_writeio_log)) :
+ (1 << (int)max(mp->m_readio_log, mp->m_writeio_log)) :
PAGE_SIZE));
}
diff --git a/fs/xfs/xfs_mru_cache.c b/fs/xfs/xfs_mru_cache.c
index 70eea7ae2876..74738813f60d 100644
--- a/fs/xfs/xfs_mru_cache.c
+++ b/fs/xfs/xfs_mru_cache.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2006-2007 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_mru_cache.h"
diff --git a/fs/xfs/xfs_mru_cache.h b/fs/xfs/xfs_mru_cache.h
index b3f3fbdfcc47..f1fde1ecf730 100644
--- a/fs/xfs/xfs_mru_cache.h
+++ b/fs/xfs/xfs_mru_cache.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2006-2007 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_MRU_CACHE_H__
#define __XFS_MRU_CACHE_H__
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index 0492436a053f..d3e04d20d8d4 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2016 Oracle.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ONDISK_H
#define __XFS_ONDISK_H
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index c3e014bfc848..9ceb85cce33a 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index e3129b280423..3ccf0fbc9071 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_QM_H__
#define __XFS_QM_H__
diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c
index 36b89e2c5eb9..73a1d77ec187 100644
--- a/fs/xfs/xfs_qm_bhv.c
+++ b/fs/xfs/xfs_qm_bhv.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 3e05d300b14e..abc8a21e3a82 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/capability.h>
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 3edf52b14919..55b798265ef7 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_QUOTA_H__
#define __XFS_QUOTA_H__
diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
index c93fc913dffb..205fbb2a77e4 100644
--- a/fs/xfs/xfs_quotaops.c
+++ b/fs/xfs/xfs_quotaops.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2008, Christoph Hellwig
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_format.h"
diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
index e5866b714d5f..472a73e9d331 100644
--- a/fs/xfs/xfs_refcount_item.c
+++ b/fs/xfs/xfs_refcount_item.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_refcount_item.h b/fs/xfs/xfs_refcount_item.h
index 0e5327349a13..dd830b69cd1e 100644
--- a/fs/xfs/xfs_refcount_item.h
+++ b/fs/xfs/xfs_refcount_item.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_REFCOUNT_ITEM_H__
#define __XFS_REFCOUNT_ITEM_H__
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 713e857d9ffa..592fb2071a03 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h
index 701487bab468..1532827ba911 100644
--- a/fs/xfs/xfs_reflink.h
+++ b/fs/xfs/xfs_reflink.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_REFLINK_H
#define __XFS_REFLINK_H 1
diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
index e5b5b3e7ef82..127dc9c32a54 100644
--- a/fs/xfs/xfs_rmap_item.c
+++ b/fs/xfs/xfs_rmap_item.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_rmap_item.h b/fs/xfs/xfs_rmap_item.h
index 340c968e1f9c..7e482baa27f5 100644
--- a/fs/xfs/xfs_rmap_item.h
+++ b/fs/xfs/xfs_rmap_item.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_RMAP_ITEM_H__
#define __XFS_RMAP_ITEM_H__
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 488719d43ca8..329d4d26c13e 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -313,8 +301,12 @@ xfs_rtallocate_extent_block(
/*
* If size should be a multiple of prod, make that so.
*/
- if (prod > 1 && (p = do_mod(bestlen, prod)))
- bestlen -= p;
+ if (prod > 1) {
+ div_u64_rem(bestlen, prod, &p);
+ if (p)
+ bestlen -= p;
+ }
+
/*
* Allocate besti for bestlen & return that.
*/
@@ -1275,7 +1267,7 @@ xfs_rtpick_extent(
b = (mp->m_sb.sb_rextents * ((resid << 1) + 1ULL)) >>
(log2 + 1);
if (b >= mp->m_sb.sb_rextents)
- b = do_mod(b, mp->m_sb.sb_rextents);
+ div64_u64_rem(b, mp->m_sb.sb_rextents, &b);
if (b + len > mp->m_sb.sb_rextents)
b = mp->m_sb.sb_rextents - len;
}
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h
index 52632ab727f7..93e77b221355 100644
--- a/fs/xfs/xfs_rtalloc.h
+++ b/fs/xfs/xfs_rtalloc.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_RTALLOC_H__
#define __XFS_RTALLOC_H__
diff --git a/fs/xfs/xfs_stats.c b/fs/xfs/xfs_stats.c
index 1cc79907b377..4e4423153071 100644
--- a/fs/xfs/xfs_stats.c
+++ b/fs/xfs/xfs_stats.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include <linux/proc_fs.h>
diff --git a/fs/xfs/xfs_stats.h b/fs/xfs/xfs_stats.h
index f64d0ae345c4..130db070e4d8 100644
--- a/fs/xfs/xfs_stats.h
+++ b/fs/xfs/xfs_stats.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_STATS_H__
#define __XFS_STATS_H__
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index ed67389f4948..9d791f158dfe 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
@@ -1148,7 +1136,7 @@ xfs_fs_statfs(
statp->f_bavail = statp->f_bfree;
fakeinos = statp->f_bfree << sbp->sb_inopblog;
- statp->f_files = MIN(icount + fakeinos, (uint64_t)XFS_MAXINUMBER);
+ statp->f_files = min(icount + fakeinos, (uint64_t)XFS_MAXINUMBER);
if (mp->m_maxicount)
statp->f_files = min_t(typeof(statp->f_files),
statp->f_files,
diff --git a/fs/xfs/xfs_super.h b/fs/xfs/xfs_super.h
index 8cee8e8050e3..21cb49a43d7c 100644
--- a/fs/xfs/xfs_super.h
+++ b/fs/xfs/xfs_super.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SUPER_H__
#define __XFS_SUPER_H__
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index aed03da637d4..3783afcb68d2 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* Copyright (c) 2012-2013 Red Hat, Inc.
* All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_shared.h"
diff --git a/fs/xfs/xfs_symlink.h b/fs/xfs/xfs_symlink.h
index aeaee8923617..9743d8c9394b 100644
--- a/fs/xfs/xfs_symlink.h
+++ b/fs/xfs/xfs_symlink.h
@@ -1,18 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2012 Red Hat, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SYMLINK_H
#define __XFS_SYMLINK_H 1
diff --git a/fs/xfs/xfs_sysctl.c b/fs/xfs/xfs_sysctl.c
index afe1f66aaa69..0cc034dfb786 100644
--- a/fs/xfs/xfs_sysctl.c
+++ b/fs/xfs/xfs_sysctl.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2001-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include <linux/sysctl.h>
diff --git a/fs/xfs/xfs_sysctl.h b/fs/xfs/xfs_sysctl.h
index b53a33e69932..168488130a19 100644
--- a/fs/xfs/xfs_sysctl.h
+++ b/fs/xfs/xfs_sysctl.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2001-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SYSCTL_H__
#define __XFS_SYSCTL_H__
diff --git a/fs/xfs/xfs_sysfs.c b/fs/xfs/xfs_sysfs.c
index 2d5cd2529f8e..cd6a994a7250 100644
--- a/fs/xfs/xfs_sysfs.c
+++ b/fs/xfs/xfs_sysfs.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
diff --git a/fs/xfs/xfs_sysfs.h b/fs/xfs/xfs_sysfs.h
index d04637181ef2..e9f810fc6731 100644
--- a/fs/xfs/xfs_sysfs.h
+++ b/fs/xfs/xfs_sysfs.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SYSFS_H__
diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c
index 35f3546b6af5..cb6489c22cad 100644
--- a/fs/xfs/xfs_trace.c
+++ b/fs/xfs/xfs_trace.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2009, Christoph Hellwig
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 9d4c4ca24fe6..972d45d28097 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2009, Christoph Hellwig
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM xfs
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index fc7ba75b8b69..e040af120b69 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* Copyright (C) 2010 Red Hat, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 29706b8b3bd4..6526314f0b8f 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_TRANS_H__
#define __XFS_TRANS_H__
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 41e280ef1483..55326f971cb3 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* Copyright (c) 2008 Dave Chinner
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans_bmap.c b/fs/xfs/xfs_trans_bmap.c
index 230a21df4b12..a15a5cd867f9 100644
--- a/fs/xfs/xfs_trans_bmap.c
+++ b/fs/xfs/xfs_trans_bmap.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index a8ddb4eed279..15919f67a88f 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index c381c02cca45..c23257a26c2b 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c
index 2f44a08bdf65..bd66c76f55e6 100644
--- a/fs/xfs/xfs_trans_extfree.c
+++ b/fs/xfs/xfs_trans_extfree.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index f7bd7960a90f..542927321a61 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -70,7 +58,7 @@ xfs_trans_ichgtime(
int flags)
{
struct inode *inode = VFS_I(ip);
- struct timespec tv;
+ struct timespec64 tv;
ASSERT(tp);
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index 9717ae74b36d..091eae9f4e74 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_TRANS_PRIV_H__
#define __XFS_TRANS_PRIV_H__
diff --git a/fs/xfs/xfs_trans_refcount.c b/fs/xfs/xfs_trans_refcount.c
index c7f8e82f5bda..46dd4fca8aa7 100644
--- a/fs/xfs/xfs_trans_refcount.c
+++ b/fs/xfs/xfs_trans_refcount.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans_rmap.c b/fs/xfs/xfs_trans_rmap.c
index 5831ca0c270b..726d8e2c0558 100644
--- a/fs/xfs/xfs_trans_rmap.c
+++ b/fs/xfs/xfs_trans_rmap.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
index 0594db435972..63ee1d5bf1d7 100644
--- a/fs/xfs/xfs_xattr.c
+++ b/fs/xfs/xfs_xattr.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2008 Christoph Hellwig.
* Portions Copyright (C) 2000-2008 Silicon Graphics, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"