summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/acl.c40
-rw-r--r--fs/9p/v9fs.h3
-rw-r--r--fs/9p/vfs_inode.c10
-rw-r--r--fs/9p/vfs_inode_dotl.c11
-rw-r--r--fs/Kconfig4
-rw-r--r--fs/Kconfig.binfmt2
-rw-r--r--fs/adfs/inode.c4
-rw-r--r--fs/affs/affs.h3
-rw-r--r--fs/affs/amigaffs.c6
-rw-r--r--fs/affs/inode.c4
-rw-r--r--fs/affs/namei.c6
-rw-r--r--fs/afs/callback.c4
-rw-r--r--fs/afs/cmservice.c168
-rw-r--r--fs/afs/dir.c9
-rw-r--r--fs/afs/flock.c4
-rw-r--r--fs/afs/fsclient.c148
-rw-r--r--fs/afs/internal.h38
-rw-r--r--fs/afs/main.c1
-rw-r--r--fs/afs/rxrpc.c522
-rw-r--r--fs/afs/server.c11
-rw-r--r--fs/afs/vlclient.c7
-rw-r--r--fs/afs/vlocation.c4
-rw-r--r--fs/afs/write.c5
-rw-r--r--fs/aio.c9
-rw-r--r--fs/attr.c52
-rw-r--r--fs/autofs4/autofs_i.h9
-rw-r--r--fs/autofs4/dev-ioctl.c77
-rw-r--r--fs/autofs4/inode.c47
-rw-r--r--fs/autofs4/root.c10
-rw-r--r--fs/autofs4/waitq.c4
-rw-r--r--fs/bad_inode.c25
-rw-r--r--fs/befs/linuxvfs.c2
-rw-r--r--fs/bfs/dir.c20
-rw-r--r--fs/binfmt_elf.c23
-rw-r--r--fs/binfmt_misc.c2
-rw-r--r--fs/block_dev.c95
-rw-r--r--fs/btrfs/acl.c6
-rw-r--r--fs/btrfs/backref.c409
-rw-r--r--fs/btrfs/btrfs_inode.h11
-rw-r--r--fs/btrfs/check-integrity.c342
-rw-r--r--fs/btrfs/compression.c6
-rw-r--r--fs/btrfs/ctree.c56
-rw-r--r--fs/btrfs/ctree.h120
-rw-r--r--fs/btrfs/delayed-inode.c25
-rw-r--r--fs/btrfs/delayed-ref.c15
-rw-r--r--fs/btrfs/dev-replace.c21
-rw-r--r--fs/btrfs/dir-item.c7
-rw-r--r--fs/btrfs/disk-io.c270
-rw-r--r--fs/btrfs/disk-io.h2
-rw-r--r--fs/btrfs/extent-tree.c198
-rw-r--r--fs/btrfs/extent_io.c234
-rw-r--r--fs/btrfs/extent_io.h26
-rw-r--r--fs/btrfs/file.c51
-rw-r--r--fs/btrfs/free-space-cache.c21
-rw-r--r--fs/btrfs/free-space-cache.h6
-rw-r--r--fs/btrfs/free-space-tree.c39
-rw-r--r--fs/btrfs/inode-map.c31
-rw-r--r--fs/btrfs/inode.c130
-rw-r--r--fs/btrfs/ioctl.c22
-rw-r--r--fs/btrfs/lzo.c6
-rw-r--r--fs/btrfs/ordered-data.c4
-rw-r--r--fs/btrfs/print-tree.c93
-rw-r--r--fs/btrfs/qgroup.c77
-rw-r--r--fs/btrfs/raid56.c5
-rw-r--r--fs/btrfs/reada.c32
-rw-r--r--fs/btrfs/relocation.c47
-rw-r--r--fs/btrfs/root-tree.c18
-rw-r--r--fs/btrfs/scrub.c58
-rw-r--r--fs/btrfs/send.c81
-rw-r--r--fs/btrfs/super.c62
-rw-r--r--fs/btrfs/sysfs.c19
-rw-r--r--fs/btrfs/tests/extent-io-tests.c87
-rw-r--r--fs/btrfs/tests/free-space-tree-tests.c189
-rw-r--r--fs/btrfs/tests/inode-tests.c12
-rw-r--r--fs/btrfs/tests/qgroup-tests.c2
-rw-r--r--fs/btrfs/transaction.c53
-rw-r--r--fs/btrfs/transaction.h1
-rw-r--r--fs/btrfs/tree-log.c16
-rw-r--r--fs/btrfs/uuid-tree.c27
-rw-r--r--fs/btrfs/volumes.c197
-rw-r--r--fs/btrfs/volumes.h2
-rw-r--r--fs/btrfs/xattr.c2
-rw-r--r--fs/btrfs/zlib.c8
-rw-r--r--fs/buffer.c7
-rw-r--r--fs/cachefiles/bind.c4
-rw-r--r--fs/cachefiles/interface.c8
-rw-r--r--fs/cachefiles/internal.h3
-rw-r--r--fs/cachefiles/namei.c15
-rw-r--r--fs/ceph/acl.c11
-rw-r--r--fs/ceph/addr.c24
-rw-r--r--fs/ceph/dir.c9
-rw-r--r--fs/ceph/file.c8
-rw-r--r--fs/ceph/inode.c27
-rw-r--r--fs/ceph/locks.c4
-rw-r--r--fs/ceph/mds_client.c30
-rw-r--r--fs/ceph/mds_client.h1
-rw-r--r--fs/ceph/strings.c2
-rw-r--r--fs/ceph/super.c49
-rw-r--r--fs/ceph/xattr.c2
-rw-r--r--fs/char_dev.c1
-rw-r--r--fs/cifs/cifs_debug.c1
-rw-r--r--fs/cifs/cifs_fs_sb.h1
-rw-r--r--fs/cifs/cifs_ioctl.h8
-rw-r--r--fs/cifs/cifsacl.c123
-rw-r--r--fs/cifs/cifsfs.c22
-rw-r--r--fs/cifs/cifsfs.h10
-rw-r--r--fs/cifs/cifsglob.h50
-rw-r--r--fs/cifs/cifsproto.h5
-rw-r--r--fs/cifs/cifssmb.c31
-rw-r--r--fs/cifs/connect.c43
-rw-r--r--fs/cifs/dir.c6
-rw-r--r--fs/cifs/file.c123
-rw-r--r--fs/cifs/inode.c6
-rw-r--r--fs/cifs/ioctl.c16
-rw-r--r--fs/cifs/link.c2
-rw-r--r--fs/cifs/misc.c15
-rw-r--r--fs/cifs/readdir.c6
-rw-r--r--fs/cifs/smb2inode.c6
-rw-r--r--fs/cifs/smb2misc.c16
-rw-r--r--fs/cifs/smb2ops.c62
-rw-r--r--fs/cifs/smb2pdu.c587
-rw-r--r--fs/cifs/smb2pdu.h2
-rw-r--r--fs/cifs/xattr.c62
-rw-r--r--fs/coda/dir.c8
-rw-r--r--fs/coda/file.c25
-rw-r--r--fs/coda/inode.c2
-rw-r--r--fs/compat.c16
-rw-r--r--fs/compat_ioctl.c2
-rw-r--r--fs/configfs/inode.c6
-rw-r--r--fs/crypto/crypto.c11
-rw-r--r--fs/crypto/fname.c85
-rw-r--r--fs/crypto/keyinfo.c71
-rw-r--r--fs/dax.c254
-rw-r--r--fs/debugfs/file.c15
-rw-r--r--fs/debugfs/inode.c4
-rw-r--r--fs/debugfs/internal.h4
-rw-r--r--fs/devpts/inode.c77
-rw-r--r--fs/direct-io.c3
-rw-r--r--fs/dlm/lowcomms.c8
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h2
-rw-r--r--fs/ecryptfs/inode.c75
-rw-r--r--fs/ecryptfs/main.c1
-rw-r--r--fs/ecryptfs/mmap.c13
-rw-r--r--fs/efivarfs/inode.c7
-rw-r--r--fs/efivarfs/super.c13
-rw-r--r--fs/exofs/dir.c6
-rw-r--r--fs/exofs/inode.c8
-rw-r--r--fs/exofs/namei.c14
-rw-r--r--fs/exportfs/expfs.c10
-rw-r--r--fs/ext2/Kconfig1
-rw-r--r--fs/ext2/acl.c12
-rw-r--r--fs/ext2/dir.c6
-rw-r--r--fs/ext2/ext2.h1
-rw-r--r--fs/ext2/file.c80
-rw-r--r--fs/ext2/ialloc.c7
-rw-r--r--fs/ext2/inode.c116
-rw-r--r--fs/ext2/ioctl.c4
-rw-r--r--fs/ext2/namei.c18
-rw-r--r--fs/ext2/super.c2
-rw-r--r--fs/ext2/symlink.c6
-rw-r--r--fs/ext2/xattr.c2
-rw-r--r--fs/ext4/acl.c12
-rw-r--r--fs/ext4/dir.c8
-rw-r--r--fs/ext4/ext4.h35
-rw-r--r--fs/ext4/extents.c27
-rw-r--r--fs/ext4/file.c14
-rw-r--r--fs/ext4/fsync.c9
-rw-r--r--fs/ext4/ialloc.c2
-rw-r--r--fs/ext4/inode.c73
-rw-r--r--fs/ext4/ioctl.c11
-rw-r--r--fs/ext4/move_extent.c7
-rw-r--r--fs/ext4/namei.c30
-rw-r--r--fs/ext4/page-io.c6
-rw-r--r--fs/ext4/super.c126
-rw-r--r--fs/ext4/symlink.c19
-rw-r--r--fs/ext4/xattr.c340
-rw-r--r--fs/f2fs/acl.c18
-rw-r--r--fs/f2fs/acl.h1
-rw-r--r--fs/f2fs/checkpoint.c205
-rw-r--r--fs/f2fs/data.c133
-rw-r--r--fs/f2fs/debug.c17
-rw-r--r--fs/f2fs/dir.c124
-rw-r--r--fs/f2fs/f2fs.h175
-rw-r--r--fs/f2fs/file.c33
-rw-r--r--fs/f2fs/gc.c90
-rw-r--r--fs/f2fs/inline.c27
-rw-r--r--fs/f2fs/inode.c17
-rw-r--r--fs/f2fs/namei.c47
-rw-r--r--fs/f2fs/node.c40
-rw-r--r--fs/f2fs/node.h77
-rw-r--r--fs/f2fs/recovery.c124
-rw-r--r--fs/f2fs/segment.c219
-rw-r--r--fs/f2fs/segment.h11
-rw-r--r--fs/f2fs/super.c93
-rw-r--r--fs/f2fs/xattr.c41
-rw-r--r--fs/fat/dir.c2
-rw-r--r--fs/fat/file.c8
-rw-r--r--fs/fat/inode.c2
-rw-r--r--fs/fat/namei_msdos.c18
-rw-r--r--fs/fat/namei_vfat.c35
-rw-r--r--fs/file.c34
-rw-r--r--fs/fuse/Kconfig1
-rw-r--r--fs/fuse/Makefile2
-rw-r--r--fs/fuse/acl.c99
-rw-r--r--fs/fuse/control.c2
-rw-r--r--fs/fuse/dev.c64
-rw-r--r--fs/fuse/dir.c288
-rw-r--r--fs/fuse/file.c70
-rw-r--r--fs/fuse/fuse_i.h42
-rw-r--r--fs/fuse/inode.c28
-rw-r--r--fs/fuse/xattr.c211
-rw-r--r--fs/gfs2/acl.c12
-rw-r--r--fs/gfs2/aops.c19
-rw-r--r--fs/gfs2/bmap.c14
-rw-r--r--fs/gfs2/dir.c32
-rw-r--r--fs/gfs2/file.c34
-rw-r--r--fs/gfs2/glock.c10
-rw-r--r--fs/gfs2/inode.c25
-rw-r--r--fs/gfs2/inode.h2
-rw-r--r--fs/gfs2/main.c4
-rw-r--r--fs/gfs2/meta_io.c35
-rw-r--r--fs/gfs2/ops_fstype.c8
-rw-r--r--fs/gfs2/quota.c6
-rw-r--r--fs/gfs2/super.c2
-rw-r--r--fs/gfs2/xattr.c8
-rw-r--r--fs/hfs/attr.c83
-rw-r--r--fs/hfs/catalog.c8
-rw-r--r--fs/hfs/dir.c8
-rw-r--r--fs/hfs/hfs_fs.h6
-rw-r--r--fs/hfs/inode.c9
-rw-r--r--fs/hfs/super.c1
-rw-r--r--fs/hfsplus/catalog.c8
-rw-r--r--fs/hfsplus/dir.c15
-rw-r--r--fs/hfsplus/inode.c7
-rw-r--r--fs/hfsplus/ioctl.c2
-rw-r--r--fs/hfsplus/posix_acl.c4
-rw-r--r--fs/hostfs/hostfs_kern.c4
-rw-r--r--fs/hpfs/file.c6
-rw-r--r--fs/hpfs/inode.c2
-rw-r--r--fs/hpfs/namei.c6
-rw-r--r--fs/hugetlbfs/inode.c24
-rw-r--r--fs/inode.c105
-rw-r--r--fs/internal.h22
-rw-r--r--fs/iomap.c89
-rw-r--r--fs/jbd2/commit.c3
-rw-r--r--fs/jbd2/journal.c131
-rw-r--r--fs/jbd2/transaction.c6
-rw-r--r--fs/jffs2/acl.c11
-rw-r--r--fs/jffs2/dir.c12
-rw-r--r--fs/jffs2/file.c3
-rw-r--r--fs/jffs2/fs.c4
-rw-r--r--fs/jffs2/symlink.c3
-rw-r--r--fs/jffs2/xattr.h6
-rw-r--r--fs/jfs/acl.c8
-rw-r--r--fs/jfs/file.c5
-rw-r--r--fs/jfs/inode.c2
-rw-r--r--fs/jfs/jfs_inode.c2
-rw-r--r--fs/jfs/jfs_txnmgr.c3
-rw-r--r--fs/jfs/namei.c32
-rw-r--r--fs/jfs/resize.c10
-rw-r--r--fs/jfs/super.c2
-rw-r--r--fs/jfs/symlink.c6
-rw-r--r--fs/jfs/xattr.c2
-rw-r--r--fs/kernfs/dir.c93
-rw-r--r--fs/kernfs/inode.c159
-rw-r--r--fs/kernfs/kernfs-internal.h7
-rw-r--r--fs/kernfs/mount.c1
-rw-r--r--fs/kernfs/symlink.c3
-rw-r--r--fs/libfs.c51
-rw-r--r--fs/lockd/procfs.h2
-rw-r--r--fs/locks.c144
-rw-r--r--fs/logfs/dir.c12
-rw-r--r--fs/logfs/file.c4
-rw-r--r--fs/logfs/inode.c4
-rw-r--r--fs/logfs/readwrite.c4
-rw-r--r--fs/mbcache.c6
-rw-r--r--fs/minix/bitmap.c2
-rw-r--r--fs/minix/dir.c6
-rw-r--r--fs/minix/file.c2
-rw-r--r--fs/minix/itree_common.c4
-rw-r--r--fs/minix/namei.c10
-rw-r--r--fs/mount.h3
-rw-r--r--fs/namei.c42
-rw-r--r--fs/namespace.c79
-rw-r--r--fs/ncpfs/dir.c11
-rw-r--r--fs/ncpfs/inode.c2
-rw-r--r--fs/nfs/cache_lib.c2
-rw-r--r--fs/nfs/callback.c136
-rw-r--r--fs/nfs/callback.h12
-rw-r--r--fs/nfs/callback_proc.c16
-rw-r--r--fs/nfs/callback_xdr.c53
-rw-r--r--fs/nfs/client.c10
-rw-r--r--fs/nfs/delegation.c213
-rw-r--r--fs/nfs/delegation.h8
-rw-r--r--fs/nfs/dir.c30
-rw-r--r--fs/nfs/direct.c2
-rw-r--r--fs/nfs/file.c36
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c2
-rw-r--r--fs/nfs/internal.h18
-rw-r--r--fs/nfs/netns.h2
-rw-r--r--fs/nfs/nfs3proc.c6
-rw-r--r--fs/nfs/nfs42proc.c1
-rw-r--r--fs/nfs/nfs4_fs.h15
-rw-r--r--fs/nfs/nfs4client.c118
-rw-r--r--fs/nfs/nfs4file.c2
-rw-r--r--fs/nfs/nfs4proc.c907
-rw-r--r--fs/nfs/nfs4session.h2
-rw-r--r--fs/nfs/nfs4state.c84
-rw-r--r--fs/nfs/nfs4xdr.c42
-rw-r--r--fs/nfs/pagelist.c2
-rw-r--r--fs/nfs/pnfs.c73
-rw-r--r--fs/nfs/pnfs.h5
-rw-r--r--fs/nfs/pnfs_nfs.c58
-rw-r--r--fs/nfs/read.c2
-rw-r--r--fs/nfs/super.c10
-rw-r--r--fs/nfs/write.c4
-rw-r--r--fs/nfsd/auth.c6
-rw-r--r--fs/nfsd/blocklayout.c2
-rw-r--r--fs/nfsd/flexfilelayout.c1
-rw-r--r--fs/nfsd/netns.h1
-rw-r--r--fs/nfsd/nfs4callback.c64
-rw-r--r--fs/nfsd/nfs4layouts.c6
-rw-r--r--fs/nfsd/nfs4proc.c90
-rw-r--r--fs/nfsd/nfs4state.c239
-rw-r--r--fs/nfsd/nfs4xdr.c65
-rw-r--r--fs/nfsd/nfsctl.c2
-rw-r--r--fs/nfsd/nfsproc.c11
-rw-r--r--fs/nfsd/nfssvc.c18
-rw-r--r--fs/nfsd/pnfs.h1
-rw-r--r--fs/nfsd/state.h22
-rw-r--r--fs/nfsd/vfs.c16
-rw-r--r--fs/nfsd/vfs.h2
-rw-r--r--fs/nfsd/xdr4.h23
-rw-r--r--fs/nfsd/xdr4cb.h9
-rw-r--r--fs/nilfs2/dir.c6
-rw-r--r--fs/nilfs2/inode.c6
-rw-r--r--fs/nilfs2/ioctl.c2
-rw-r--r--fs/nilfs2/namei.c12
-rw-r--r--fs/notify/fanotify/fanotify_user.c39
-rw-r--r--fs/notify/group.c6
-rw-r--r--fs/notify/inotify/inotify_user.c16
-rw-r--r--fs/notify/notification.c35
-rw-r--r--fs/nsfs.c107
-rw-r--r--fs/ntfs/file.c2
-rw-r--r--fs/ntfs/inode.c4
-rw-r--r--fs/ntfs/mft.c2
-rw-r--r--fs/ocfs2/acl.c12
-rw-r--r--fs/ocfs2/alloc.c2
-rw-r--r--fs/ocfs2/aops.c2
-rw-r--r--fs/ocfs2/cluster/tcp.c2
-rw-r--r--fs/ocfs2/dir.c4
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c2
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c3
-rw-r--r--fs/ocfs2/dlmfs/dlmfs.c8
-rw-r--r--fs/ocfs2/file.c51
-rw-r--r--fs/ocfs2/inode.h2
-rw-r--r--fs/ocfs2/move_extents.c2
-rw-r--r--fs/ocfs2/namei.c19
-rw-r--r--fs/ocfs2/ocfs2_trace.h2
-rw-r--r--fs/ocfs2/refcounttree.c4
-rw-r--r--fs/ocfs2/super.c2
-rw-r--r--fs/ocfs2/symlink.c3
-rw-r--r--fs/ocfs2/xattr.c2
-rw-r--r--fs/omfs/dir.c10
-rw-r--r--fs/omfs/file.c2
-rw-r--r--fs/omfs/inode.c2
-rw-r--r--fs/open.c25
-rw-r--r--fs/openpromfs/inode.c2
-rw-r--r--fs/orangefs/acl.c15
-rw-r--r--fs/orangefs/dcache.c2
-rw-r--r--fs/orangefs/devorangefs-req.c164
-rw-r--r--fs/orangefs/dir.c4
-rw-r--r--fs/orangefs/downcall.h11
-rw-r--r--fs/orangefs/file.c51
-rw-r--r--fs/orangefs/inode.c19
-rw-r--r--fs/orangefs/namei.c71
-rw-r--r--fs/orangefs/orangefs-cache.c6
-rw-r--r--fs/orangefs/orangefs-debugfs.c765
-rw-r--r--fs/orangefs/orangefs-debugfs.h8
-rw-r--r--fs/orangefs/orangefs-dev-proto.h6
-rw-r--r--fs/orangefs/orangefs-kernel.h51
-rw-r--r--fs/orangefs/orangefs-mod.c86
-rw-r--r--fs/orangefs/orangefs-sysfs.c1287
-rw-r--r--fs/orangefs/orangefs-utils.c403
-rw-r--r--fs/orangefs/protocol.h25
-rw-r--r--fs/orangefs/super.c31
-rw-r--r--fs/orangefs/symlink.c1
-rw-r--r--fs/orangefs/upcall.h18
-rw-r--r--fs/orangefs/waitqueue.c10
-rw-r--r--fs/orangefs/xattr.c3
-rw-r--r--fs/overlayfs/copy_up.c93
-rw-r--r--fs/overlayfs/dir.c20
-rw-r--r--fs/overlayfs/inode.c52
-rw-r--r--fs/overlayfs/overlayfs.h4
-rw-r--r--fs/overlayfs/super.c44
-rw-r--r--fs/pipe.c181
-rw-r--r--fs/pnode.c2
-rw-r--r--fs/pnode.h1
-rw-r--r--fs/posix_acl.c62
-rw-r--r--fs/proc/array.c189
-rw-r--r--fs/proc/base.c103
-rw-r--r--fs/proc/fd.c8
-rw-r--r--fs/proc/fd.h2
-rw-r--r--fs/proc/generic.c4
-rw-r--r--fs/proc/inode.c3
-rw-r--r--fs/proc/internal.h2
-rw-r--r--fs/proc/meminfo.c211
-rw-r--r--fs/proc/proc_net.c13
-rw-r--r--fs/proc/proc_sysctl.c23
-rw-r--r--fs/proc/self.c2
-rw-r--r--fs/proc/stat.c49
-rw-r--r--fs/proc/task_mmu.c10
-rw-r--r--fs/proc/thread_self.c2
-rw-r--r--fs/pstore/inode.c2
-rw-r--r--fs/pstore/platform.c53
-rw-r--r--fs/pstore/pmsg.c35
-rw-r--r--fs/pstore/ram.c46
-rw-r--r--fs/pstore/ram_core.c96
-rw-r--r--fs/quota/quota.c18
-rw-r--r--fs/ramfs/file-nommu.c2
-rw-r--r--fs/ramfs/inode.c6
-rw-r--r--fs/read_write.c29
-rw-r--r--fs/reiserfs/file.c3
-rw-r--r--fs/reiserfs/inode.c4
-rw-r--r--fs/reiserfs/ioctl.c4
-rw-r--r--fs/reiserfs/namei.c27
-rw-r--r--fs/reiserfs/stree.c8
-rw-r--r--fs/reiserfs/super.c14
-rw-r--r--fs/reiserfs/xattr.c6
-rw-r--r--fs/reiserfs/xattr_acl.c10
-rw-r--r--fs/select.c14
-rw-r--r--fs/seq_file.c57
-rw-r--r--fs/splice.c677
-rw-r--r--fs/squashfs/inode.c1
-rw-r--r--fs/squashfs/namei.c1
-rw-r--r--fs/squashfs/symlink.c1
-rw-r--r--fs/squashfs/xattr.h1
-rw-r--r--fs/super.c43
-rw-r--r--fs/sysfs/dir.c6
-rw-r--r--fs/sysfs/group.c4
-rw-r--r--fs/sysv/dir.c6
-rw-r--r--fs/sysv/file.c2
-rw-r--r--fs/sysv/ialloc.c2
-rw-r--r--fs/sysv/itree.c4
-rw-r--r--fs/sysv/namei.c10
-rw-r--r--fs/tracefs/inode.c2
-rw-r--r--fs/ubifs/dir.c248
-rw-r--r--fs/ubifs/file.c10
-rw-r--r--fs/ubifs/gc.c2
-rw-r--r--fs/ubifs/journal.c188
-rw-r--r--fs/ubifs/lprops.c2
-rw-r--r--fs/ubifs/lpt_commit.c4
-rw-r--r--fs/ubifs/replay.c2
-rw-r--r--fs/ubifs/ubifs.h8
-rw-r--r--fs/ubifs/xattr.c6
-rw-r--r--fs/udf/file.c20
-rw-r--r--fs/udf/ialloc.c2
-rw-r--r--fs/udf/inode.c4
-rw-r--r--fs/udf/namei.c26
-rw-r--r--fs/ufs/dir.c6
-rw-r--r--fs/ufs/ialloc.c2
-rw-r--r--fs/ufs/inode.c8
-rw-r--r--fs/ufs/namei.c12
-rw-r--r--fs/utimes.c19
-rw-r--r--fs/xattr.c250
-rw-r--r--fs/xfs/Makefile8
-rw-r--r--fs/xfs/libxfs/xfs_ag_resv.c338
-rw-r--r--fs/xfs/libxfs/xfs_ag_resv.h35
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c158
-rw-r--r--fs/xfs/libxfs/xfs_alloc.h25
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c709
-rw-r--r--fs/xfs/libxfs/xfs_bmap.h73
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.c18
-rw-r--r--fs/xfs/libxfs/xfs_btree.c67
-rw-r--r--fs/xfs/libxfs/xfs_btree.h44
-rw-r--r--fs/xfs/libxfs/xfs_defer.c79
-rw-r--r--fs/xfs/libxfs/xfs_defer.h2
-rw-r--r--fs/xfs/libxfs/xfs_format.h97
-rw-r--r--fs/xfs/libxfs/xfs_fs.h10
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.c2
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.c24
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.h1
-rw-r--r--fs/xfs/libxfs/xfs_inode_fork.c70
-rw-r--r--fs/xfs/libxfs/xfs_inode_fork.h28
-rw-r--r--fs/xfs/libxfs/xfs_log_format.h128
-rw-r--r--fs/xfs/libxfs/xfs_refcount.c1698
-rw-r--r--fs/xfs/libxfs/xfs_refcount.h70
-rw-r--r--fs/xfs/libxfs/xfs_refcount_btree.c451
-rw-r--r--fs/xfs/libxfs/xfs_refcount_btree.h74
-rw-r--r--fs/xfs/libxfs/xfs_rmap.c914
-rw-r--r--fs/xfs/libxfs/xfs_rmap.h7
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.c82
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.h7
-rw-r--r--fs/xfs/libxfs/xfs_sb.c9
-rw-r--r--fs/xfs/libxfs/xfs_shared.h2
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.c23
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.h3
-rw-r--r--fs/xfs/libxfs/xfs_trans_space.h9
-rw-r--r--fs/xfs/libxfs/xfs_types.h3
-rw-r--r--fs/xfs/xfs_acl.c15
-rw-r--r--fs/xfs/xfs_aops.c253
-rw-r--r--fs/xfs/xfs_aops.h5
-rw-r--r--fs/xfs/xfs_bmap_item.c508
-rw-r--r--fs/xfs/xfs_bmap_item.h98
-rw-r--r--fs/xfs/xfs_bmap_util.c591
-rw-r--r--fs/xfs/xfs_buf_item.c9
-rw-r--r--fs/xfs/xfs_dir2_readdir.c3
-rw-r--r--fs/xfs/xfs_error.h10
-rw-r--r--fs/xfs/xfs_extent_busy.c2
-rw-r--r--fs/xfs/xfs_file.c349
-rw-r--r--fs/xfs/xfs_filestream.c13
-rw-r--r--fs/xfs/xfs_fsops.c109
-rw-r--r--fs/xfs/xfs_fsops.h3
-rw-r--r--fs/xfs/xfs_globals.c5
-rw-r--r--fs/xfs/xfs_icache.c257
-rw-r--r--fs/xfs/xfs_icache.h7
-rw-r--r--fs/xfs/xfs_inode.c55
-rw-r--r--fs/xfs/xfs_inode.h20
-rw-r--r--fs/xfs/xfs_inode_item.c2
-rw-r--r--fs/xfs/xfs_ioctl.c77
-rw-r--r--fs/xfs/xfs_iomap.c521
-rw-r--r--fs/xfs/xfs_iomap.h5
-rw-r--r--fs/xfs/xfs_iops.c114
-rw-r--r--fs/xfs/xfs_iops.h3
-rw-r--r--fs/xfs/xfs_itable.c8
-rw-r--r--fs/xfs/xfs_linux.h1
-rw-r--r--fs/xfs/xfs_log_priv.h3
-rw-r--r--fs/xfs/xfs_log_recover.c548
-rw-r--r--fs/xfs/xfs_mount.c46
-rw-r--r--fs/xfs/xfs_mount.h52
-rw-r--r--fs/xfs/xfs_ondisk.h3
-rw-r--r--fs/xfs/xfs_pnfs.c7
-rw-r--r--fs/xfs/xfs_refcount_item.c539
-rw-r--r--fs/xfs/xfs_refcount_item.h101
-rw-r--r--fs/xfs/xfs_reflink.c1688
-rw-r--r--fs/xfs/xfs_reflink.h58
-rw-r--r--fs/xfs/xfs_rmap_item.c48
-rw-r--r--fs/xfs/xfs_rmap_item.h8
-rw-r--r--fs/xfs/xfs_stats.c1
-rw-r--r--fs/xfs/xfs_stats.h18
-rw-r--r--fs/xfs/xfs_super.c94
-rw-r--r--fs/xfs/xfs_super.h1
-rw-r--r--fs/xfs/xfs_sysctl.c9
-rw-r--r--fs/xfs/xfs_sysctl.h1
-rw-r--r--fs/xfs/xfs_sysfs.c47
-rw-r--r--fs/xfs/xfs_trace.h857
-rw-r--r--fs/xfs/xfs_trans.c3
-rw-r--r--fs/xfs/xfs_trans.h29
-rw-r--r--fs/xfs/xfs_trans_bmap.c249
-rw-r--r--fs/xfs/xfs_trans_extfree.c3
-rw-r--r--fs/xfs/xfs_trans_inode.c2
-rw-r--r--fs/xfs/xfs_trans_refcount.c264
-rw-r--r--fs/xfs/xfs_trans_rmap.c9
-rw-r--r--fs/xfs/xfs_xattr.c1
554 files changed, 23910 insertions, 9646 deletions
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index 5b6a1743ea17..b3c2cc79c20d 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -276,32 +276,26 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
switch (handler->flags) {
case ACL_TYPE_ACCESS:
if (acl) {
- umode_t mode = inode->i_mode;
- retval = posix_acl_equiv_mode(acl, &mode);
- if (retval < 0)
+ struct iattr iattr;
+
+ retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
+ if (retval)
goto err_out;
- else {
- struct iattr iattr;
- if (retval == 0) {
- /*
- * ACL can be represented
- * by the mode bits. So don't
- * update ACL.
- */
- acl = NULL;
- value = NULL;
- size = 0;
- }
- /* Updte the mode bits */
- iattr.ia_mode = ((mode & S_IALLUGO) |
- (inode->i_mode & ~S_IALLUGO));
- iattr.ia_valid = ATTR_MODE;
- /* FIXME should we update ctime ?
- * What is the following setxattr update the
- * mode ?
+ if (!acl) {
+ /*
+ * ACL can be represented
+ * by the mode bits. So don't
+ * update ACL.
*/
- v9fs_vfs_setattr_dotl(dentry, &iattr);
+ value = NULL;
+ size = 0;
}
+ iattr.ia_valid = ATTR_MODE;
+ /* FIXME should we update ctime ?
+ * What is the following setxattr update the
+ * mode ?
+ */
+ v9fs_vfs_setattr_dotl(dentry, &iattr);
}
break;
case ACL_TYPE_DEFAULT:
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 6877050384a1..443d12e02043 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -148,7 +148,8 @@ extern struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d);
extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d);
extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry);
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags);
extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
struct p9_fid *fid,
struct super_block *sb, int new);
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 8b1999b528e9..30ca770c5e0b 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -276,7 +276,7 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses,
inode_init_owner(inode, NULL, mode);
inode->i_blocks = 0;
inode->i_rdev = rdev;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
inode->i_mapping->a_ops = &v9fs_addr_operations;
switch (mode & S_IFMT) {
@@ -955,7 +955,8 @@ int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
int
v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags)
{
int retval;
struct inode *old_inode;
@@ -966,6 +967,9 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct p9_fid *newdirfid;
struct p9_wstat wstat;
+ if (flags)
+ return -EINVAL;
+
p9_debug(P9_DEBUG_VFS, "\n");
retval = 0;
old_inode = d_inode(old_dentry);
@@ -1094,7 +1098,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
struct p9_wstat wstat;
p9_debug(P9_DEBUG_VFS, "\n");
- retval = inode_change_ok(d_inode(dentry), iattr);
+ retval = setattr_prepare(dentry, iattr);
if (retval)
return retval;
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index eeabcb0bad12..afaa4b6de801 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -558,7 +558,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
p9_debug(P9_DEBUG_VFS, "\n");
- retval = inode_change_ok(inode, iattr);
+ retval = setattr_prepare(dentry, iattr);
if (retval)
return retval;
@@ -967,9 +967,6 @@ const struct inode_operations v9fs_dir_inode_operations_dotl = {
.rename = v9fs_vfs_rename,
.getattr = v9fs_vfs_getattr_dotl,
.setattr = v9fs_vfs_setattr_dotl,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .removexattr = generic_removexattr,
.listxattr = v9fs_listxattr,
.get_acl = v9fs_iop_get_acl,
};
@@ -977,9 +974,6 @@ const struct inode_operations v9fs_dir_inode_operations_dotl = {
const struct inode_operations v9fs_file_inode_operations_dotl = {
.getattr = v9fs_vfs_getattr_dotl,
.setattr = v9fs_vfs_setattr_dotl,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .removexattr = generic_removexattr,
.listxattr = v9fs_listxattr,
.get_acl = v9fs_iop_get_acl,
};
@@ -989,8 +983,5 @@ const struct inode_operations v9fs_symlink_inode_operations_dotl = {
.get_link = v9fs_vfs_get_link_dotl,
.getattr = v9fs_vfs_getattr_dotl,
.setattr = v9fs_vfs_setattr_dotl,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .removexattr = generic_removexattr,
.listxattr = v9fs_listxattr,
};
diff --git a/fs/Kconfig b/fs/Kconfig
index 2bc7ad775842..4bd03a2b0518 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -79,6 +79,7 @@ config EXPORTFS_BLOCK_OPS
config FILE_LOCKING
bool "Enable POSIX file locking API" if EXPERT
default y
+ select PERCPU_RWSEM
help
This option enables standard file locking support, required
for filesystems like NFS and for the flock() system
@@ -199,6 +200,9 @@ config HUGETLBFS
config HUGETLB_PAGE
def_bool HUGETLBFS
+config ARCH_HAS_GIGANTIC_PAGE
+ bool
+
source "fs/configfs/Kconfig"
source "fs/efivarfs/Kconfig"
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index c7efddf6e038..4c09d93d9569 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -89,7 +89,7 @@ config BINFMT_SCRIPT
config BINFMT_FLAT
bool "Kernel support for flat binaries"
- depends on !MMU || M68K
+ depends on !MMU || ARM || M68K
depends on !FRV || BROKEN
help
Support uClinux FLAT format binaries.
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index 335055d828e4..8dbd36f5e581 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;
+ *tv = current_time(inode);
return;
too_early:
@@ -303,7 +303,7 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr)
unsigned int ia_valid = attr->ia_valid;
int error;
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
/*
* we can't change the UID or GID of any file -
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index cc2b2efc9211..2f088773f1c0 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -173,7 +173,8 @@ extern int affs_link(struct dentry *olddentry, struct inode *dir,
extern int affs_symlink(struct inode *dir, struct dentry *dentry,
const char *symname);
extern int affs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry);
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags);
/* inode.c */
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
index d8f217c711d3..0ec65c133b93 100644
--- a/fs/affs/amigaffs.c
+++ b/fs/affs/amigaffs.c
@@ -58,7 +58,7 @@ affs_insert_hash(struct inode *dir, struct buffer_head *bh)
mark_buffer_dirty_inode(dir_bh, dir);
affs_brelse(dir_bh);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
dir->i_version++;
mark_inode_dirty(dir);
@@ -112,7 +112,7 @@ affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh)
affs_brelse(bh);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
dir->i_version++;
mark_inode_dirty(dir);
@@ -313,7 +313,7 @@ affs_remove_header(struct dentry *dentry)
else
clear_nlink(inode);
affs_unlock_link(inode);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
done:
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 0fdb0f5b2239..fe4e1290dbb5 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -219,7 +219,7 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr)
pr_debug("notify_change(%lu,0x%x)\n", inode->i_ino, attr->ia_valid);
- error = inode_change_ok(inode,attr);
+ error = setattr_prepare(dentry, attr);
if (error)
goto out;
@@ -309,7 +309,7 @@ affs_new_inode(struct inode *dir)
inode->i_gid = current_fsgid();
inode->i_ino = block;
set_nlink(inode, 1);
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
atomic_set(&AFFS_I(inode)->i_opencnt, 0);
AFFS_I(inode)->i_blkcnt = 0;
AFFS_I(inode)->i_lc = NULL;
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index a2d68f828d53..29186d29a3b6 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -414,12 +414,16 @@ affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
int
affs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags)
{
struct super_block *sb = old_dir->i_sb;
struct buffer_head *bh = NULL;
int retval;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__,
old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry);
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index 7ef637d7f3a5..1e9d2f84e5b5 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -461,8 +461,8 @@ static void afs_callback_updater(struct work_struct *work)
*/
int __init afs_callback_update_init(void)
{
- afs_callback_update_worker =
- create_singlethread_workqueue("kafs_callbackd");
+ afs_callback_update_worker = alloc_ordered_workqueue("kafs_callbackd",
+ WQ_MEM_RECLAIM);
return afs_callback_update_worker ? 0 : -ENOMEM;
}
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index 85737e96ab8b..2037e7a77a37 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -17,19 +17,12 @@
#include "internal.h"
#include "afs_cm.h"
-#if 0
-struct workqueue_struct *afs_cm_workqueue;
-#endif /* 0 */
-
-static int afs_deliver_cb_init_call_back_state(struct afs_call *,
- struct sk_buff *, bool);
-static int afs_deliver_cb_init_call_back_state3(struct afs_call *,
- struct sk_buff *, bool);
-static int afs_deliver_cb_probe(struct afs_call *, struct sk_buff *, bool);
-static int afs_deliver_cb_callback(struct afs_call *, struct sk_buff *, bool);
-static int afs_deliver_cb_probe_uuid(struct afs_call *, struct sk_buff *, bool);
-static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *,
- struct sk_buff *, bool);
+static int afs_deliver_cb_init_call_back_state(struct afs_call *);
+static int afs_deliver_cb_init_call_back_state3(struct afs_call *);
+static int afs_deliver_cb_probe(struct afs_call *);
+static int afs_deliver_cb_callback(struct afs_call *);
+static int afs_deliver_cb_probe_uuid(struct afs_call *);
+static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *);
static void afs_cm_destructor(struct afs_call *);
/*
@@ -134,7 +127,7 @@ static void afs_cm_destructor(struct afs_call *call)
* received. The step number here must match the final number in
* afs_deliver_cb_callback().
*/
- if (call->unmarshall == 6) {
+ if (call->unmarshall == 5) {
ASSERT(call->server && call->count && call->request);
afs_break_callbacks(call->server, call->count, call->request);
}
@@ -168,27 +161,27 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
/*
* deliver request data to a CB.CallBack call
*/
-static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
- bool last)
+static int afs_deliver_cb_callback(struct afs_call *call)
{
+ struct sockaddr_rxrpc srx;
struct afs_callback *cb;
struct afs_server *server;
- struct in_addr addr;
__be32 *bp;
u32 tmp;
int ret, loop;
- _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+ _enter("{%u}", call->unmarshall);
switch (call->unmarshall) {
case 0:
+ rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);
call->offset = 0;
call->unmarshall++;
/* extract the FID array and its count in two steps */
case 1:
_debug("extract FID count");
- ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+ ret = afs_extract_data(call, &call->tmp, 4, true);
if (ret < 0)
return ret;
@@ -205,8 +198,8 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
case 2:
_debug("extract FID array");
- ret = afs_extract_data(call, skb, last, call->buffer,
- call->count * 3 * 4);
+ ret = afs_extract_data(call, call->buffer,
+ call->count * 3 * 4, true);
if (ret < 0)
return ret;
@@ -232,7 +225,7 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
/* extract the callback array and its count in two steps */
case 3:
_debug("extract CB count");
- ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+ ret = afs_extract_data(call, &call->tmp, 4, true);
if (ret < 0)
return ret;
@@ -242,13 +235,11 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
return -EBADMSG;
call->offset = 0;
call->unmarshall++;
- if (tmp == 0)
- goto empty_cb_array;
case 4:
_debug("extract CB array");
- ret = afs_extract_data(call, skb, last, call->request,
- call->count * 3 * 4);
+ ret = afs_extract_data(call, call->buffer,
+ call->count * 3 * 4, false);
if (ret < 0)
return ret;
@@ -261,15 +252,9 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
cb->type = ntohl(*bp++);
}
- empty_cb_array:
call->offset = 0;
call->unmarshall++;
- case 5:
- ret = afs_data_complete(call, skb, last);
- if (ret < 0)
- return ret;
-
/* Record that the message was unmarshalled successfully so
* that the call destructor can know do the callback breaking
* work, even if the final ACK isn't received.
@@ -278,17 +263,15 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
* updated also.
*/
call->unmarshall++;
- case 6:
+ case 5:
break;
}
-
call->state = AFS_CALL_REPLYING;
/* we'll need the file server record as that tells us which set of
* vnodes to operate upon */
- memcpy(&addr, &ip_hdr(skb)->saddr, 4);
- server = afs_find_server(&addr);
+ server = afs_find_server(&srx);
if (!server)
return -ENOTCONN;
call->server = server;
@@ -315,17 +298,17 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work)
/*
* deliver request data to a CB.InitCallBackState call
*/
-static int afs_deliver_cb_init_call_back_state(struct afs_call *call,
- struct sk_buff *skb,
- bool last)
+static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
{
+ struct sockaddr_rxrpc srx;
struct afs_server *server;
- struct in_addr addr;
int ret;
- _enter(",{%u},%d", skb->len, last);
+ _enter("");
+
+ rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);
- ret = afs_data_complete(call, skb, last);
+ ret = afs_extract_data(call, NULL, 0, false);
if (ret < 0)
return ret;
@@ -334,8 +317,7 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call,
/* we'll need the file server record as that tells us which set of
* vnodes to operate upon */
- memcpy(&addr, &ip_hdr(skb)->saddr, 4);
- server = afs_find_server(&addr);
+ server = afs_find_server(&srx);
if (!server)
return -ENOTCONN;
call->server = server;
@@ -348,27 +330,68 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call,
/*
* deliver request data to a CB.InitCallBackState3 call
*/
-static int afs_deliver_cb_init_call_back_state3(struct afs_call *call,
- struct sk_buff *skb,
- bool last)
+static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
{
+ struct sockaddr_rxrpc srx;
struct afs_server *server;
- struct in_addr addr;
+ struct afs_uuid *r;
+ unsigned loop;
+ __be32 *b;
+ int ret;
+
+ _enter("");
+
+ rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);
+
+ _enter("{%u}", call->unmarshall);
- _enter(",{%u},%d", skb->len, last);
+ switch (call->unmarshall) {
+ case 0:
+ call->offset = 0;
+ call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL);
+ if (!call->buffer)
+ return -ENOMEM;
+ call->unmarshall++;
- /* There are some arguments that we ignore */
- afs_data_consumed(call, skb);
- if (!last)
- return -EAGAIN;
+ case 1:
+ _debug("extract UUID");
+ ret = afs_extract_data(call, call->buffer,
+ 11 * sizeof(__be32), false);
+ switch (ret) {
+ case 0: break;
+ case -EAGAIN: return 0;
+ default: return ret;
+ }
+
+ _debug("unmarshall UUID");
+ call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL);
+ if (!call->request)
+ return -ENOMEM;
+
+ b = call->buffer;
+ r = call->request;
+ r->time_low = ntohl(b[0]);
+ r->time_mid = ntohl(b[1]);
+ r->time_hi_and_version = ntohl(b[2]);
+ r->clock_seq_hi_and_reserved = ntohl(b[3]);
+ r->clock_seq_low = ntohl(b[4]);
+
+ for (loop = 0; loop < 6; loop++)
+ r->node[loop] = ntohl(b[loop + 5]);
+
+ call->offset = 0;
+ call->unmarshall++;
+
+ case 2:
+ break;
+ }
/* no unmarshalling required */
call->state = AFS_CALL_REPLYING;
/* we'll need the file server record as that tells us which set of
* vnodes to operate upon */
- memcpy(&addr, &ip_hdr(skb)->saddr, 4);
- server = afs_find_server(&addr);
+ server = afs_find_server(&srx);
if (!server)
return -ENOTCONN;
call->server = server;
@@ -393,14 +416,13 @@ static void SRXAFSCB_Probe(struct work_struct *work)
/*
* deliver request data to a CB.Probe call
*/
-static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb,
- bool last)
+static int afs_deliver_cb_probe(struct afs_call *call)
{
int ret;
- _enter(",{%u},%d", skb->len, last);
+ _enter("");
- ret = afs_data_complete(call, skb, last);
+ ret = afs_extract_data(call, NULL, 0, false);
if (ret < 0)
return ret;
@@ -426,7 +448,6 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work)
_enter("");
-
if (memcmp(r, &afs_uuid, sizeof(afs_uuid)) == 0)
reply.match = htonl(0);
else
@@ -439,19 +460,14 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work)
/*
* deliver request data to a CB.ProbeUuid call
*/
-static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb,
- bool last)
+static int afs_deliver_cb_probe_uuid(struct afs_call *call)
{
struct afs_uuid *r;
unsigned loop;
__be32 *b;
int ret;
- _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
-
- ret = afs_data_complete(call, skb, last);
- if (ret < 0)
- return ret;
+ _enter("{%u}", call->unmarshall);
switch (call->unmarshall) {
case 0:
@@ -463,8 +479,8 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb,
case 1:
_debug("extract UUID");
- ret = afs_extract_data(call, skb, last, call->buffer,
- 11 * sizeof(__be32));
+ ret = afs_extract_data(call, call->buffer,
+ 11 * sizeof(__be32), false);
switch (ret) {
case 0: break;
case -EAGAIN: return 0;
@@ -491,16 +507,9 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb,
call->unmarshall++;
case 2:
- _debug("trailer");
- if (skb->len != 0)
- return -EBADMSG;
break;
}
- ret = afs_data_complete(call, skb, last);
- if (ret < 0)
- return ret;
-
call->state = AFS_CALL_REPLYING;
INIT_WORK(&call->work, SRXAFSCB_ProbeUuid);
@@ -574,14 +583,13 @@ static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
/*
* deliver request data to a CB.TellMeAboutYourself call
*/
-static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call)
{
int ret;
- _enter(",{%u},%d", skb->len, last);
+ _enter("");
- ret = afs_data_complete(call, skb, last);
+ ret = afs_extract_data(call, NULL, 0, false);
if (ret < 0)
return ret;
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index eba541004d90..51a241e09fbb 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -38,7 +38,8 @@ static int afs_link(struct dentry *from, struct inode *dir,
static int afs_symlink(struct inode *dir, struct dentry *dentry,
const char *content);
static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry);
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags);
const struct file_operations afs_dir_file_operations = {
.open = afs_dir_open,
@@ -1083,12 +1084,16 @@ error:
* rename a file in an AFS filesystem and/or move it between directories
*/
static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags)
{
struct afs_vnode *orig_dvnode, *new_dvnode, *vnode;
struct key *key;
int ret;
+ if (flags)
+ return -EINVAL;
+
vnode = AFS_FS_I(d_inode(old_dentry));
orig_dvnode = AFS_FS_I(old_dir);
new_dvnode = AFS_FS_I(new_dir);
diff --git a/fs/afs/flock.c b/fs/afs/flock.c
index d91a9c9cfbd0..3191dff2c156 100644
--- a/fs/afs/flock.c
+++ b/fs/afs/flock.c
@@ -36,8 +36,8 @@ static int afs_init_lock_manager(void)
if (!afs_lock_manager) {
mutex_lock(&afs_lock_manager_mutex);
if (!afs_lock_manager) {
- afs_lock_manager =
- create_singlethread_workqueue("kafs_lockd");
+ afs_lock_manager = alloc_workqueue("kafs_lockd",
+ WQ_MEM_RECLAIM, 0);
if (!afs_lock_manager)
ret = -ENOMEM;
}
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 9312b92e54be..96f4d764d1a6 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -235,16 +235,15 @@ static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
/*
* deliver reply data to an FS.FetchStatus
*/
-static int afs_deliver_fs_fetch_status(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_fs_fetch_status(struct afs_call *call)
{
struct afs_vnode *vnode = call->reply;
const __be32 *bp;
int ret;
- _enter(",,%u", last);
+ _enter("");
- ret = afs_transfer_reply(call, skb, last);
+ ret = afs_transfer_reply(call);
if (ret < 0)
return ret;
@@ -307,8 +306,7 @@ int afs_fs_fetch_file_status(struct afs_server *server,
/*
* deliver reply data to an FS.FetchData
*/
-static int afs_deliver_fs_fetch_data(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_fs_fetch_data(struct afs_call *call)
{
struct afs_vnode *vnode = call->reply;
const __be32 *bp;
@@ -316,7 +314,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
void *buffer;
int ret;
- _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+ _enter("{%u}", call->unmarshall);
switch (call->unmarshall) {
case 0:
@@ -332,7 +330,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
* client) */
case 1:
_debug("extract data length (MSW)");
- ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+ ret = afs_extract_data(call, &call->tmp, 4, true);
if (ret < 0)
return ret;
@@ -347,7 +345,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
/* extract the returned data length */
case 2:
_debug("extract data length");
- ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+ ret = afs_extract_data(call, &call->tmp, 4, true);
if (ret < 0)
return ret;
@@ -363,10 +361,10 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
_debug("extract data");
if (call->count > 0) {
page = call->reply3;
- buffer = kmap_atomic(page);
- ret = afs_extract_data(call, skb, last, buffer,
- call->count);
- kunmap_atomic(buffer);
+ buffer = kmap(page);
+ ret = afs_extract_data(call, buffer,
+ call->count, true);
+ kunmap(buffer);
if (ret < 0)
return ret;
}
@@ -376,8 +374,8 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
/* extract the metadata */
case 4:
- ret = afs_extract_data(call, skb, last, call->buffer,
- (21 + 3 + 6) * 4);
+ ret = afs_extract_data(call, call->buffer,
+ (21 + 3 + 6) * 4, false);
if (ret < 0)
return ret;
@@ -391,18 +389,15 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
call->unmarshall++;
case 5:
- ret = afs_data_complete(call, skb, last);
- if (ret < 0)
- return ret;
break;
}
if (call->count < PAGE_SIZE) {
_debug("clear");
page = call->reply3;
- buffer = kmap_atomic(page);
+ buffer = kmap(page);
memset(buffer + call->count, 0, PAGE_SIZE - call->count);
- kunmap_atomic(buffer);
+ kunmap(buffer);
}
_leave(" = 0 [done]");
@@ -515,13 +510,12 @@ int afs_fs_fetch_data(struct afs_server *server,
/*
* deliver reply data to an FS.GiveUpCallBacks
*/
-static int afs_deliver_fs_give_up_callbacks(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_fs_give_up_callbacks(struct afs_call *call)
{
- _enter(",{%u},%d", skb->len, last);
+ _enter("");
/* shouldn't be any reply data */
- return afs_data_complete(call, skb, last);
+ return afs_extract_data(call, NULL, 0, false);
}
/*
@@ -599,16 +593,15 @@ int afs_fs_give_up_callbacks(struct afs_server *server,
/*
* deliver reply data to an FS.CreateFile or an FS.MakeDir
*/
-static int afs_deliver_fs_create_vnode(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_fs_create_vnode(struct afs_call *call)
{
struct afs_vnode *vnode = call->reply;
const __be32 *bp;
int ret;
- _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+ _enter("{%u}", call->unmarshall);
- ret = afs_transfer_reply(call, skb, last);
+ ret = afs_transfer_reply(call);
if (ret < 0)
return ret;
@@ -696,16 +689,15 @@ int afs_fs_create(struct afs_server *server,
/*
* deliver reply data to an FS.RemoveFile or FS.RemoveDir
*/
-static int afs_deliver_fs_remove(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_fs_remove(struct afs_call *call)
{
struct afs_vnode *vnode = call->reply;
const __be32 *bp;
int ret;
- _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+ _enter("{%u}", call->unmarshall);
- ret = afs_transfer_reply(call, skb, last);
+ ret = afs_transfer_reply(call);
if (ret < 0)
return ret;
@@ -777,16 +769,15 @@ int afs_fs_remove(struct afs_server *server,
/*
* deliver reply data to an FS.Link
*/
-static int afs_deliver_fs_link(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_fs_link(struct afs_call *call)
{
struct afs_vnode *dvnode = call->reply, *vnode = call->reply2;
const __be32 *bp;
int ret;
- _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+ _enter("{%u}", call->unmarshall);
- ret = afs_transfer_reply(call, skb, last);
+ ret = afs_transfer_reply(call);
if (ret < 0)
return ret;
@@ -863,16 +854,15 @@ int afs_fs_link(struct afs_server *server,
/*
* deliver reply data to an FS.Symlink
*/
-static int afs_deliver_fs_symlink(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_fs_symlink(struct afs_call *call)
{
struct afs_vnode *vnode = call->reply;
const __be32 *bp;
int ret;
- _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+ _enter("{%u}", call->unmarshall);
- ret = afs_transfer_reply(call, skb, last);
+ ret = afs_transfer_reply(call);
if (ret < 0)
return ret;
@@ -968,16 +958,15 @@ int afs_fs_symlink(struct afs_server *server,
/*
* deliver reply data to an FS.Rename
*/
-static int afs_deliver_fs_rename(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_fs_rename(struct afs_call *call)
{
struct afs_vnode *orig_dvnode = call->reply, *new_dvnode = call->reply2;
const __be32 *bp;
int ret;
- _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+ _enter("{%u}", call->unmarshall);
- ret = afs_transfer_reply(call, skb, last);
+ ret = afs_transfer_reply(call);
if (ret < 0)
return ret;
@@ -1072,16 +1061,15 @@ int afs_fs_rename(struct afs_server *server,
/*
* deliver reply data to an FS.StoreData
*/
-static int afs_deliver_fs_store_data(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_fs_store_data(struct afs_call *call)
{
struct afs_vnode *vnode = call->reply;
const __be32 *bp;
int ret;
- _enter(",,%u", last);
+ _enter("");
- ret = afs_transfer_reply(call, skb, last);
+ ret = afs_transfer_reply(call);
if (ret < 0)
return ret;
@@ -1251,17 +1239,16 @@ int afs_fs_store_data(struct afs_server *server, struct afs_writeback *wb,
/*
* deliver reply data to an FS.StoreStatus
*/
-static int afs_deliver_fs_store_status(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_fs_store_status(struct afs_call *call)
{
afs_dataversion_t *store_version;
struct afs_vnode *vnode = call->reply;
const __be32 *bp;
int ret;
- _enter(",,%u", last);
+ _enter("");
- ret = afs_transfer_reply(call, skb, last);
+ ret = afs_transfer_reply(call);
if (ret < 0)
return ret;
@@ -1443,14 +1430,13 @@ int afs_fs_setattr(struct afs_server *server, struct key *key,
/*
* deliver reply data to an FS.GetVolumeStatus
*/
-static int afs_deliver_fs_get_volume_status(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_fs_get_volume_status(struct afs_call *call)
{
const __be32 *bp;
char *p;
int ret;
- _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+ _enter("{%u}", call->unmarshall);
switch (call->unmarshall) {
case 0:
@@ -1460,8 +1446,8 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call,
/* extract the returned status record */
case 1:
_debug("extract status");
- ret = afs_extract_data(call, skb, last, call->buffer,
- 12 * 4);
+ ret = afs_extract_data(call, call->buffer,
+ 12 * 4, true);
if (ret < 0)
return ret;
@@ -1472,7 +1458,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call,
/* extract the volume name length */
case 2:
- ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+ ret = afs_extract_data(call, &call->tmp, 4, true);
if (ret < 0)
return ret;
@@ -1487,8 +1473,8 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call,
case 3:
_debug("extract volname");
if (call->count > 0) {
- ret = afs_extract_data(call, skb, last, call->reply3,
- call->count);
+ ret = afs_extract_data(call, call->reply3,
+ call->count, true);
if (ret < 0)
return ret;
}
@@ -1508,8 +1494,8 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call,
call->count = 4 - (call->count & 3);
case 4:
- ret = afs_extract_data(call, skb, last, call->buffer,
- call->count);
+ ret = afs_extract_data(call, call->buffer,
+ call->count, true);
if (ret < 0)
return ret;
@@ -1519,7 +1505,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call,
/* extract the offline message length */
case 5:
- ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+ ret = afs_extract_data(call, &call->tmp, 4, true);
if (ret < 0)
return ret;
@@ -1534,8 +1520,8 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call,
case 6:
_debug("extract offline");
if (call->count > 0) {
- ret = afs_extract_data(call, skb, last, call->reply3,
- call->count);
+ ret = afs_extract_data(call, call->reply3,
+ call->count, true);
if (ret < 0)
return ret;
}
@@ -1555,8 +1541,8 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call,
call->count = 4 - (call->count & 3);
case 7:
- ret = afs_extract_data(call, skb, last, call->buffer,
- call->count);
+ ret = afs_extract_data(call, call->buffer,
+ call->count, true);
if (ret < 0)
return ret;
@@ -1566,7 +1552,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call,
/* extract the message of the day length */
case 8:
- ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+ ret = afs_extract_data(call, &call->tmp, 4, true);
if (ret < 0)
return ret;
@@ -1581,8 +1567,8 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call,
case 9:
_debug("extract motd");
if (call->count > 0) {
- ret = afs_extract_data(call, skb, last, call->reply3,
- call->count);
+ ret = afs_extract_data(call, call->reply3,
+ call->count, true);
if (ret < 0)
return ret;
}
@@ -1595,26 +1581,17 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call,
call->unmarshall++;
/* extract the message of the day padding */
- if ((call->count & 3) == 0) {
- call->unmarshall++;
- goto no_motd_padding;
- }
- call->count = 4 - (call->count & 3);
+ call->count = (4 - (call->count & 3)) & 3;
case 10:
- ret = afs_extract_data(call, skb, last, call->buffer,
- call->count);
+ ret = afs_extract_data(call, call->buffer,
+ call->count, false);
if (ret < 0)
return ret;
call->offset = 0;
call->unmarshall++;
- no_motd_padding:
-
case 11:
- ret = afs_data_complete(call, skb, last);
- if (ret < 0)
- return ret;
break;
}
@@ -1685,15 +1662,14 @@ int afs_fs_get_volume_status(struct afs_server *server,
/*
* deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
*/
-static int afs_deliver_fs_xxxx_lock(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
{
const __be32 *bp;
int ret;
- _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+ _enter("{%u}", call->unmarshall);
- ret = afs_transfer_reply(call, skb, last);
+ ret = afs_transfer_reply(call);
if (ret < 0)
return ret;
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index df976b2a7f40..5497c8496055 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -13,13 +13,13 @@
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
-#include <linux/skbuff.h>
#include <linux/rxrpc.h>
#include <linux/key.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/fscache.h>
#include <linux/backing-dev.h>
+#include <net/af_rxrpc.h>
#include "afs.h"
#include "afs_vl.h"
@@ -56,7 +56,7 @@ struct afs_mount_params {
*/
struct afs_wait_mode {
/* RxRPC received message notification */
- void (*rx_wakeup)(struct afs_call *call);
+ rxrpc_notify_rx_t notify_rx;
/* synchronous call waiter and call dispatched notification */
int (*wait)(struct afs_call *call);
@@ -75,10 +75,8 @@ struct afs_call {
const struct afs_call_type *type; /* type of call */
const struct afs_wait_mode *wait_mode; /* completion wait mode */
wait_queue_head_t waitq; /* processes awaiting completion */
- void (*async_workfn)(struct afs_call *call); /* asynchronous work function */
struct work_struct async_work; /* asynchronous work processor */
struct work_struct work; /* actual work processor */
- struct sk_buff_head rx_queue; /* received packets */
struct rxrpc_call *rxcall; /* RxRPC call handle */
struct key *key; /* security for this call */
struct afs_server *server; /* server affected by incoming CM call */
@@ -92,6 +90,7 @@ struct afs_call {
void *reply4; /* reply buffer (fourth part) */
pgoff_t first; /* first page in mapping to deal with */
pgoff_t last; /* last page in mapping to deal with */
+ size_t offset; /* offset into received data store */
enum { /* call state */
AFS_CALL_REQUESTING, /* request is being sent for outgoing call */
AFS_CALL_AWAIT_REPLY, /* awaiting reply to outgoing call */
@@ -99,21 +98,18 @@ struct afs_call {
AFS_CALL_AWAIT_REQUEST, /* awaiting request data on incoming call */
AFS_CALL_REPLYING, /* replying to incoming call */
AFS_CALL_AWAIT_ACK, /* awaiting final ACK of incoming call */
- AFS_CALL_COMPLETE, /* successfully completed */
- AFS_CALL_BUSY, /* server was busy */
- AFS_CALL_ABORTED, /* call was aborted */
- AFS_CALL_ERROR, /* call failed due to error */
+ AFS_CALL_COMPLETE, /* Completed or failed */
} state;
int error; /* error code */
+ u32 abort_code; /* Remote abort ID or 0 */
unsigned request_size; /* size of request data */
unsigned reply_max; /* maximum size of reply */
- unsigned reply_size; /* current size of reply */
unsigned first_offset; /* offset into mapping[first] */
unsigned last_to; /* amount of mapping[last] */
- unsigned offset; /* offset into received data store */
unsigned char unmarshall; /* unmarshalling phase */
bool incoming; /* T if incoming call */
bool send_pages; /* T if data from mapping should be sent */
+ bool need_attention; /* T if RxRPC poked us */
u16 service_id; /* RxRPC service ID to call */
__be16 port; /* target UDP port */
__be32 operation_ID; /* operation ID for an incoming call */
@@ -128,8 +124,7 @@ struct afs_call_type {
/* deliver request or reply data to an call
* - returning an error will cause the call to be aborted
*/
- int (*deliver)(struct afs_call *call, struct sk_buff *skb,
- bool last);
+ int (*deliver)(struct afs_call *call);
/* map an abort code to an error number */
int (*abort_to_error)(u32 abort_code);
@@ -607,29 +602,22 @@ extern void afs_proc_cell_remove(struct afs_cell *);
/*
* rxrpc.c
*/
+extern struct socket *afs_socket;
+
extern int afs_open_socket(void);
extern void afs_close_socket(void);
-extern void afs_data_consumed(struct afs_call *, struct sk_buff *);
extern int afs_make_call(struct in_addr *, struct afs_call *, gfp_t,
const struct afs_wait_mode *);
extern struct afs_call *afs_alloc_flat_call(const struct afs_call_type *,
size_t, size_t);
extern void afs_flat_call_destructor(struct afs_call *);
-extern int afs_transfer_reply(struct afs_call *, struct sk_buff *, bool);
extern void afs_send_empty_reply(struct afs_call *);
extern void afs_send_simple_reply(struct afs_call *, const void *, size_t);
-extern int afs_extract_data(struct afs_call *, struct sk_buff *, bool, void *,
- size_t);
+extern int afs_extract_data(struct afs_call *, void *, size_t, bool);
-static inline int afs_data_complete(struct afs_call *call, struct sk_buff *skb,
- bool last)
+static inline int afs_transfer_reply(struct afs_call *call)
{
- if (skb->len > 0)
- return -EBADMSG;
- afs_data_consumed(call, skb);
- if (!last)
- return -EAGAIN;
- return 0;
+ return afs_extract_data(call, call->buffer, call->reply_max, false);
}
/*
@@ -654,7 +642,7 @@ do { \
extern struct afs_server *afs_lookup_server(struct afs_cell *,
const struct in_addr *);
-extern struct afs_server *afs_find_server(const struct in_addr *);
+extern struct afs_server *afs_find_server(const struct sockaddr_rxrpc *);
extern void afs_put_server(struct afs_server *);
extern void __exit afs_purge_servers(void);
diff --git a/fs/afs/main.c b/fs/afs/main.c
index 35de0c04729f..0b187ef3b5b7 100644
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/completion.h>
#include <linux/sched.h>
+#include <linux/random.h>
#include "internal.h"
MODULE_DESCRIPTION("AFS Client File System");
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index 14d04c848465..477928b25940 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -16,34 +16,36 @@
#include "internal.h"
#include "afs_cm.h"
-static struct socket *afs_socket; /* my RxRPC socket */
+struct socket *afs_socket; /* my RxRPC socket */
static struct workqueue_struct *afs_async_calls;
+static struct afs_call *afs_spare_incoming_call;
static atomic_t afs_outstanding_calls;
-static atomic_t afs_outstanding_skbs;
-static void afs_wake_up_call_waiter(struct afs_call *);
+static void afs_free_call(struct afs_call *);
+static void afs_wake_up_call_waiter(struct sock *, struct rxrpc_call *, unsigned long);
static int afs_wait_for_call_to_complete(struct afs_call *);
-static void afs_wake_up_async_call(struct afs_call *);
+static void afs_wake_up_async_call(struct sock *, struct rxrpc_call *, unsigned long);
static int afs_dont_wait_for_call_to_complete(struct afs_call *);
-static void afs_process_async_call(struct afs_call *);
-static void afs_rx_interceptor(struct sock *, unsigned long, struct sk_buff *);
-static int afs_deliver_cm_op_id(struct afs_call *, struct sk_buff *, bool);
+static void afs_process_async_call(struct work_struct *);
+static void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned long);
+static void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long);
+static int afs_deliver_cm_op_id(struct afs_call *);
/* synchronous call management */
const struct afs_wait_mode afs_sync_call = {
- .rx_wakeup = afs_wake_up_call_waiter,
+ .notify_rx = afs_wake_up_call_waiter,
.wait = afs_wait_for_call_to_complete,
};
/* asynchronous call management */
const struct afs_wait_mode afs_async_call = {
- .rx_wakeup = afs_wake_up_async_call,
+ .notify_rx = afs_wake_up_async_call,
.wait = afs_dont_wait_for_call_to_complete,
};
/* asynchronous incoming call management */
static const struct afs_wait_mode afs_async_incoming_call = {
- .rx_wakeup = afs_wake_up_async_call,
+ .notify_rx = afs_wake_up_async_call,
};
/* asynchronous incoming call initial processing */
@@ -53,17 +55,9 @@ static const struct afs_call_type afs_RXCMxxxx = {
.abort_to_error = afs_abort_to_error,
};
-static void afs_collect_incoming_call(struct work_struct *);
+static void afs_charge_preallocation(struct work_struct *);
-static struct sk_buff_head afs_incoming_calls;
-static DECLARE_WORK(afs_collect_incoming_call_work, afs_collect_incoming_call);
-
-static void afs_async_workfn(struct work_struct *work)
-{
- struct afs_call *call = container_of(work, struct afs_call, async_work);
-
- call->async_workfn(call);
-}
+static DECLARE_WORK(afs_charge_preallocation_work, afs_charge_preallocation);
static int afs_wait_atomic_t(atomic_t *p)
{
@@ -83,10 +77,8 @@ int afs_open_socket(void)
_enter("");
- skb_queue_head_init(&afs_incoming_calls);
-
ret = -ENOMEM;
- afs_async_calls = create_singlethread_workqueue("kafsd");
+ afs_async_calls = alloc_workqueue("kafsd", WQ_MEM_RECLAIM, 0);
if (!afs_async_calls)
goto error_0;
@@ -110,13 +102,15 @@ int afs_open_socket(void)
if (ret < 0)
goto error_2;
+ rxrpc_kernel_new_call_notification(socket, afs_rx_new_call,
+ afs_rx_discard_new_call);
+
ret = kernel_listen(socket, INT_MAX);
if (ret < 0)
goto error_2;
- rxrpc_kernel_intercept_rx_messages(socket, afs_rx_interceptor);
-
afs_socket = socket;
+ afs_charge_preallocation(NULL);
_leave(" = 0");
return 0;
@@ -136,52 +130,28 @@ void afs_close_socket(void)
{
_enter("");
+ if (afs_spare_incoming_call) {
+ atomic_inc(&afs_outstanding_calls);
+ afs_free_call(afs_spare_incoming_call);
+ afs_spare_incoming_call = NULL;
+ }
+
+ _debug("outstanding %u", atomic_read(&afs_outstanding_calls));
wait_on_atomic_t(&afs_outstanding_calls, afs_wait_atomic_t,
TASK_UNINTERRUPTIBLE);
_debug("no outstanding calls");
+ flush_workqueue(afs_async_calls);
+ kernel_sock_shutdown(afs_socket, SHUT_RDWR);
+ flush_workqueue(afs_async_calls);
sock_release(afs_socket);
_debug("dework");
destroy_workqueue(afs_async_calls);
-
- ASSERTCMP(atomic_read(&afs_outstanding_skbs), ==, 0);
_leave("");
}
/*
- * Note that the data in a socket buffer is now consumed.
- */
-void afs_data_consumed(struct afs_call *call, struct sk_buff *skb)
-{
- if (!skb) {
- _debug("DLVR NULL [%d]", atomic_read(&afs_outstanding_skbs));
- dump_stack();
- } else {
- _debug("DLVR %p{%u} [%d]",
- skb, skb->mark, atomic_read(&afs_outstanding_skbs));
- rxrpc_kernel_data_consumed(call->rxcall, skb);
- }
-}
-
-/*
- * free a socket buffer
- */
-static void afs_free_skb(struct sk_buff *skb)
-{
- if (!skb) {
- _debug("FREE NULL [%d]", atomic_read(&afs_outstanding_skbs));
- dump_stack();
- } else {
- _debug("FREE %p{%u} [%d]",
- skb, skb->mark, atomic_read(&afs_outstanding_skbs));
- if (atomic_dec_return(&afs_outstanding_skbs) == -1)
- BUG();
- rxrpc_kernel_free_skb(skb);
- }
-}
-
-/*
* free a call
*/
static void afs_free_call(struct afs_call *call)
@@ -191,7 +161,6 @@ static void afs_free_call(struct afs_call *call)
ASSERTCMP(call->rxcall, ==, NULL);
ASSERT(!work_pending(&call->async_work));
- ASSERT(skb_queue_empty(&call->rx_queue));
ASSERT(call->type->name != NULL);
kfree(call->request);
@@ -207,7 +176,7 @@ static void afs_free_call(struct afs_call *call)
static void afs_end_call_nofree(struct afs_call *call)
{
if (call->rxcall) {
- rxrpc_kernel_end_call(call->rxcall);
+ rxrpc_kernel_end_call(afs_socket, call->rxcall);
call->rxcall = NULL;
}
if (call->type->destructor)
@@ -227,7 +196,7 @@ static void afs_end_call(struct afs_call *call)
* allocate a call with flat request and reply buffers
*/
struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type,
- size_t request_size, size_t reply_size)
+ size_t request_size, size_t reply_max)
{
struct afs_call *call;
@@ -241,7 +210,7 @@ struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type,
call->type = type;
call->request_size = request_size;
- call->reply_max = reply_size;
+ call->reply_max = reply_max;
if (request_size) {
call->request = kmalloc(request_size, GFP_NOFS);
@@ -249,14 +218,13 @@ struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type,
goto nomem_free;
}
- if (reply_size) {
- call->buffer = kmalloc(reply_size, GFP_NOFS);
+ if (reply_max) {
+ call->buffer = kmalloc(reply_max, GFP_NOFS);
if (!call->buffer)
goto nomem_free;
}
init_waitqueue_head(&call->waitq);
- skb_queue_head_init(&call->rx_queue);
return call;
nomem_free:
@@ -325,8 +293,8 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg,
* returns from sending the request */
if (first + loop >= last)
call->state = AFS_CALL_AWAIT_REPLY;
- ret = rxrpc_kernel_send_data(call->rxcall, msg,
- to - offset);
+ ret = rxrpc_kernel_send_data(afs_socket, call->rxcall,
+ msg, to - offset);
kunmap(pages[loop]);
if (ret < 0)
break;
@@ -354,7 +322,6 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
struct msghdr msg;
struct kvec iov[1];
int ret;
- struct sk_buff *skb;
_enter("%x,{%d},", addr->s_addr, ntohs(call->port));
@@ -366,8 +333,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
atomic_read(&afs_outstanding_calls));
call->wait_mode = wait_mode;
- call->async_workfn = afs_process_async_call;
- INIT_WORK(&call->async_work, afs_async_workfn);
+ INIT_WORK(&call->async_work, afs_process_async_call);
memset(&srx, 0, sizeof(srx));
srx.srx_family = AF_RXRPC;
@@ -380,7 +346,8 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
/* create a call */
rxcall = rxrpc_kernel_begin_call(afs_socket, &srx, call->key,
- (unsigned long) call, gfp);
+ (unsigned long) call, gfp,
+ wait_mode->notify_rx);
call->key = NULL;
if (IS_ERR(rxcall)) {
ret = PTR_ERR(rxcall);
@@ -406,7 +373,8 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
* request */
if (!call->send_pages)
call->state = AFS_CALL_AWAIT_REPLY;
- ret = rxrpc_kernel_send_data(rxcall, &msg, call->request_size);
+ ret = rxrpc_kernel_send_data(afs_socket, rxcall,
+ &msg, call->request_size);
if (ret < 0)
goto error_do_abort;
@@ -421,9 +389,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
return wait_mode->wait(call);
error_do_abort:
- rxrpc_kernel_abort_call(rxcall, RX_USER_ABORT);
- while ((skb = skb_dequeue(&call->rx_queue)))
- afs_free_skb(skb);
+ rxrpc_kernel_abort_call(afs_socket, rxcall, RX_USER_ABORT, -ret, "KSD");
error_kill_call:
afs_end_call(call);
_leave(" = %d", ret);
@@ -431,140 +397,77 @@ error_kill_call:
}
/*
- * Handles intercepted messages that were arriving in the socket's Rx queue.
- *
- * Called from the AF_RXRPC call processor in waitqueue process context. For
- * each call, it is guaranteed this will be called in order of packet to be
- * delivered.
- */
-static void afs_rx_interceptor(struct sock *sk, unsigned long user_call_ID,
- struct sk_buff *skb)
-{
- struct afs_call *call = (struct afs_call *) user_call_ID;
-
- _enter("%p,,%u", call, skb->mark);
-
- _debug("ICPT %p{%u} [%d]",
- skb, skb->mark, atomic_read(&afs_outstanding_skbs));
-
- ASSERTCMP(sk, ==, afs_socket->sk);
- atomic_inc(&afs_outstanding_skbs);
-
- if (!call) {
- /* its an incoming call for our callback service */
- skb_queue_tail(&afs_incoming_calls, skb);
- queue_work(afs_wq, &afs_collect_incoming_call_work);
- } else {
- /* route the messages directly to the appropriate call */
- skb_queue_tail(&call->rx_queue, skb);
- call->wait_mode->rx_wakeup(call);
- }
-
- _leave("");
-}
-
-/*
* deliver messages to a call
*/
static void afs_deliver_to_call(struct afs_call *call)
{
- struct sk_buff *skb;
- bool last;
u32 abort_code;
int ret;
- _enter("");
-
- while ((call->state == AFS_CALL_AWAIT_REPLY ||
- call->state == AFS_CALL_AWAIT_OP_ID ||
- call->state == AFS_CALL_AWAIT_REQUEST ||
- call->state == AFS_CALL_AWAIT_ACK) &&
- (skb = skb_dequeue(&call->rx_queue))) {
- switch (skb->mark) {
- case RXRPC_SKB_MARK_DATA:
- _debug("Rcv DATA");
- last = rxrpc_kernel_is_data_last(skb);
- ret = call->type->deliver(call, skb, last);
- switch (ret) {
- case -EAGAIN:
- if (last) {
- _debug("short data");
- goto unmarshal_error;
- }
- break;
- case 0:
- ASSERT(last);
- if (call->state == AFS_CALL_AWAIT_REPLY)
- call->state = AFS_CALL_COMPLETE;
- break;
- case -ENOTCONN:
- abort_code = RX_CALL_DEAD;
- goto do_abort;
- case -ENOTSUPP:
- abort_code = RX_INVALID_OPERATION;
- goto do_abort;
- default:
- unmarshal_error:
- abort_code = RXGEN_CC_UNMARSHAL;
- if (call->state != AFS_CALL_AWAIT_REPLY)
- abort_code = RXGEN_SS_UNMARSHAL;
- do_abort:
- rxrpc_kernel_abort_call(call->rxcall,
- abort_code);
- call->error = ret;
- call->state = AFS_CALL_ERROR;
- break;
+ _enter("%s", call->type->name);
+
+ while (call->state == AFS_CALL_AWAIT_REPLY ||
+ call->state == AFS_CALL_AWAIT_OP_ID ||
+ call->state == AFS_CALL_AWAIT_REQUEST ||
+ call->state == AFS_CALL_AWAIT_ACK
+ ) {
+ if (call->state == AFS_CALL_AWAIT_ACK) {
+ size_t offset = 0;
+ ret = rxrpc_kernel_recv_data(afs_socket, call->rxcall,
+ NULL, 0, &offset, false,
+ &call->abort_code);
+ if (ret == -EINPROGRESS || ret == -EAGAIN)
+ return;
+ if (ret == 1 || ret < 0) {
+ call->state = AFS_CALL_COMPLETE;
+ goto done;
}
- break;
- case RXRPC_SKB_MARK_FINAL_ACK:
- _debug("Rcv ACK");
- call->state = AFS_CALL_COMPLETE;
- break;
- case RXRPC_SKB_MARK_BUSY:
- _debug("Rcv BUSY");
- call->error = -EBUSY;
- call->state = AFS_CALL_BUSY;
- break;
- case RXRPC_SKB_MARK_REMOTE_ABORT:
- abort_code = rxrpc_kernel_get_abort_code(skb);
- call->error = call->type->abort_to_error(abort_code);
- call->state = AFS_CALL_ABORTED;
- _debug("Rcv ABORT %u -> %d", abort_code, call->error);
- break;
- case RXRPC_SKB_MARK_LOCAL_ABORT:
- abort_code = rxrpc_kernel_get_abort_code(skb);
- call->error = call->type->abort_to_error(abort_code);
- call->state = AFS_CALL_ABORTED;
- _debug("Loc ABORT %u -> %d", abort_code, call->error);
- break;
- case RXRPC_SKB_MARK_NET_ERROR:
- call->error = -rxrpc_kernel_get_error_number(skb);
- call->state = AFS_CALL_ERROR;
- _debug("Rcv NET ERROR %d", call->error);
- break;
- case RXRPC_SKB_MARK_LOCAL_ERROR:
- call->error = -rxrpc_kernel_get_error_number(skb);
- call->state = AFS_CALL_ERROR;
- _debug("Rcv LOCAL ERROR %d", call->error);
- break;
- default:
- BUG();
- break;
+ return;
}
- afs_free_skb(skb);
- }
-
- /* make sure the queue is empty if the call is done with (we might have
- * aborted the call early because of an unmarshalling error) */
- if (call->state >= AFS_CALL_COMPLETE) {
- while ((skb = skb_dequeue(&call->rx_queue)))
- afs_free_skb(skb);
- if (call->incoming)
- afs_end_call(call);
+ ret = call->type->deliver(call);
+ switch (ret) {
+ case 0:
+ if (call->state == AFS_CALL_AWAIT_REPLY)
+ call->state = AFS_CALL_COMPLETE;
+ goto done;
+ case -EINPROGRESS:
+ case -EAGAIN:
+ goto out;
+ case -ENOTCONN:
+ abort_code = RX_CALL_DEAD;
+ rxrpc_kernel_abort_call(afs_socket, call->rxcall,
+ abort_code, -ret, "KNC");
+ goto do_abort;
+ case -ENOTSUPP:
+ abort_code = RX_INVALID_OPERATION;
+ rxrpc_kernel_abort_call(afs_socket, call->rxcall,
+ abort_code, -ret, "KIV");
+ goto do_abort;
+ case -ENODATA:
+ case -EBADMSG:
+ case -EMSGSIZE:
+ default:
+ abort_code = RXGEN_CC_UNMARSHAL;
+ if (call->state != AFS_CALL_AWAIT_REPLY)
+ abort_code = RXGEN_SS_UNMARSHAL;
+ rxrpc_kernel_abort_call(afs_socket, call->rxcall,
+ abort_code, EBADMSG, "KUM");
+ goto do_abort;
+ }
}
+done:
+ if (call->state == AFS_CALL_COMPLETE && call->incoming)
+ afs_end_call(call);
+out:
_leave("");
+ return;
+
+do_abort:
+ call->error = ret;
+ call->state = AFS_CALL_COMPLETE;
+ goto done;
}
/*
@@ -572,7 +475,7 @@ static void afs_deliver_to_call(struct afs_call *call)
*/
static int afs_wait_for_call_to_complete(struct afs_call *call)
{
- struct sk_buff *skb;
+ const char *abort_why;
int ret;
DECLARE_WAITQUEUE(myself, current);
@@ -584,15 +487,18 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
set_current_state(TASK_INTERRUPTIBLE);
/* deliver any messages that are in the queue */
- if (!skb_queue_empty(&call->rx_queue)) {
+ if (call->state < AFS_CALL_COMPLETE && call->need_attention) {
+ call->need_attention = false;
__set_current_state(TASK_RUNNING);
afs_deliver_to_call(call);
continue;
}
+ abort_why = "KWC";
ret = call->error;
- if (call->state >= AFS_CALL_COMPLETE)
+ if (call->state == AFS_CALL_COMPLETE)
break;
+ abort_why = "KWI";
ret = -EINTR;
if (signal_pending(current))
break;
@@ -605,9 +511,8 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
/* kill the call */
if (call->state < AFS_CALL_COMPLETE) {
_debug("call incomplete");
- rxrpc_kernel_abort_call(call->rxcall, RX_CALL_DEAD);
- while ((skb = skb_dequeue(&call->rx_queue)))
- afs_free_skb(skb);
+ rxrpc_kernel_abort_call(afs_socket, call->rxcall,
+ RX_CALL_DEAD, -ret, abort_why);
}
_debug("call complete");
@@ -619,17 +524,24 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
/*
* wake up a waiting call
*/
-static void afs_wake_up_call_waiter(struct afs_call *call)
+static void afs_wake_up_call_waiter(struct sock *sk, struct rxrpc_call *rxcall,
+ unsigned long call_user_ID)
{
+ struct afs_call *call = (struct afs_call *)call_user_ID;
+
+ call->need_attention = true;
wake_up(&call->waitq);
}
/*
* wake up an asynchronous call
*/
-static void afs_wake_up_async_call(struct afs_call *call)
+static void afs_wake_up_async_call(struct sock *sk, struct rxrpc_call *rxcall,
+ unsigned long call_user_ID)
{
- _enter("");
+ struct afs_call *call = (struct afs_call *)call_user_ID;
+
+ call->need_attention = true;
queue_work(afs_async_calls, &call->async_work);
}
@@ -647,8 +559,10 @@ static int afs_dont_wait_for_call_to_complete(struct afs_call *call)
/*
* delete an asynchronous call
*/
-static void afs_delete_async_call(struct afs_call *call)
+static void afs_delete_async_call(struct work_struct *work)
{
+ struct afs_call *call = container_of(work, struct afs_call, async_work);
+
_enter("");
afs_free_call(call);
@@ -658,17 +572,19 @@ static void afs_delete_async_call(struct afs_call *call)
/*
* perform processing on an asynchronous call
- * - on a multiple-thread workqueue this work item may try to run on several
- * CPUs at the same time
*/
-static void afs_process_async_call(struct afs_call *call)
+static void afs_process_async_call(struct work_struct *work)
{
+ struct afs_call *call = container_of(work, struct afs_call, async_work);
+
_enter("");
- if (!skb_queue_empty(&call->rx_queue))
+ if (call->state < AFS_CALL_COMPLETE && call->need_attention) {
+ call->need_attention = false;
afs_deliver_to_call(call);
+ }
- if (call->state >= AFS_CALL_COMPLETE && call->wait_mode) {
+ if (call->state == AFS_CALL_COMPLETE && call->wait_mode) {
if (call->wait_mode->async_complete)
call->wait_mode->async_complete(call->reply,
call->error);
@@ -679,122 +595,93 @@ static void afs_process_async_call(struct afs_call *call)
/* we can't just delete the call because the work item may be
* queued */
- call->async_workfn = afs_delete_async_call;
+ call->async_work.func = afs_delete_async_call;
queue_work(afs_async_calls, &call->async_work);
}
_leave("");
}
-/*
- * Empty a socket buffer into a flat reply buffer.
- */
-int afs_transfer_reply(struct afs_call *call, struct sk_buff *skb, bool last)
+static void afs_rx_attach(struct rxrpc_call *rxcall, unsigned long user_call_ID)
{
- size_t len = skb->len;
-
- if (len > call->reply_max - call->reply_size) {
- _leave(" = -EBADMSG [%zu > %u]",
- len, call->reply_max - call->reply_size);
- return -EBADMSG;
- }
+ struct afs_call *call = (struct afs_call *)user_call_ID;
- if (len > 0) {
- if (skb_copy_bits(skb, 0, call->buffer + call->reply_size,
- len) < 0)
- BUG();
- call->reply_size += len;
- }
-
- afs_data_consumed(call, skb);
- if (!last)
- return -EAGAIN;
-
- if (call->reply_size != call->reply_max) {
- _leave(" = -EBADMSG [%u != %u]",
- call->reply_size, call->reply_max);
- return -EBADMSG;
- }
- return 0;
+ call->rxcall = rxcall;
}
/*
- * accept the backlog of incoming calls
+ * Charge the incoming call preallocation.
*/
-static void afs_collect_incoming_call(struct work_struct *work)
+static void afs_charge_preallocation(struct work_struct *work)
{
- struct rxrpc_call *rxcall;
- struct afs_call *call = NULL;
- struct sk_buff *skb;
-
- while ((skb = skb_dequeue(&afs_incoming_calls))) {
- _debug("new call");
-
- /* don't need the notification */
- afs_free_skb(skb);
+ struct afs_call *call = afs_spare_incoming_call;
+ for (;;) {
if (!call) {
call = kzalloc(sizeof(struct afs_call), GFP_KERNEL);
- if (!call) {
- rxrpc_kernel_reject_call(afs_socket);
- return;
- }
+ if (!call)
+ break;
- call->async_workfn = afs_process_async_call;
- INIT_WORK(&call->async_work, afs_async_workfn);
+ INIT_WORK(&call->async_work, afs_process_async_call);
call->wait_mode = &afs_async_incoming_call;
call->type = &afs_RXCMxxxx;
init_waitqueue_head(&call->waitq);
- skb_queue_head_init(&call->rx_queue);
call->state = AFS_CALL_AWAIT_OP_ID;
-
- _debug("CALL %p{%s} [%d]",
- call, call->type->name,
- atomic_read(&afs_outstanding_calls));
- atomic_inc(&afs_outstanding_calls);
}
- rxcall = rxrpc_kernel_accept_call(afs_socket,
- (unsigned long) call);
- if (!IS_ERR(rxcall)) {
- call->rxcall = rxcall;
- call = NULL;
- }
+ if (rxrpc_kernel_charge_accept(afs_socket,
+ afs_wake_up_async_call,
+ afs_rx_attach,
+ (unsigned long)call,
+ GFP_KERNEL) < 0)
+ break;
+ call = NULL;
}
+ afs_spare_incoming_call = call;
+}
+
+/*
+ * Discard a preallocated call when a socket is shut down.
+ */
+static void afs_rx_discard_new_call(struct rxrpc_call *rxcall,
+ unsigned long user_call_ID)
+{
+ struct afs_call *call = (struct afs_call *)user_call_ID;
- if (call)
- afs_free_call(call);
+ atomic_inc(&afs_outstanding_calls);
+ call->rxcall = NULL;
+ afs_free_call(call);
+}
+
+/*
+ * Notification of an incoming call.
+ */
+static void afs_rx_new_call(struct sock *sk, struct rxrpc_call *rxcall,
+ unsigned long user_call_ID)
+{
+ atomic_inc(&afs_outstanding_calls);
+ queue_work(afs_wq, &afs_charge_preallocation_work);
}
/*
* Grab the operation ID from an incoming cache manager call. The socket
* buffer is discarded on error or if we don't yet have sufficient data.
*/
-static int afs_deliver_cm_op_id(struct afs_call *call, struct sk_buff *skb,
- bool last)
+static int afs_deliver_cm_op_id(struct afs_call *call)
{
- size_t len = skb->len;
- void *oibuf = (void *) &call->operation_ID;
+ int ret;
- _enter("{%u},{%zu},%d", call->offset, len, last);
+ _enter("{%zu}", call->offset);
ASSERTCMP(call->offset, <, 4);
/* the operation ID forms the first four bytes of the request data */
- len = min_t(size_t, len, 4 - call->offset);
- if (skb_copy_bits(skb, 0, oibuf + call->offset, len) < 0)
- BUG();
- if (!pskb_pull(skb, len))
- BUG();
- call->offset += len;
-
- if (call->offset < 4) {
- afs_data_consumed(call, skb);
- _leave(" = -EAGAIN");
- return -EAGAIN;
- }
+ ret = afs_extract_data(call, &call->operation_ID, 4, true);
+ if (ret < 0)
+ return ret;
call->state = AFS_CALL_AWAIT_REQUEST;
+ call->offset = 0;
/* ask the cache manager to route the call (it'll change the call type
* if successful) */
@@ -803,7 +690,7 @@ static int afs_deliver_cm_op_id(struct afs_call *call, struct sk_buff *skb,
/* pass responsibility for the remainer of this message off to the
* cache manager op */
- return call->type->deliver(call, skb, last);
+ return call->type->deliver(call);
}
/*
@@ -823,14 +710,15 @@ void afs_send_empty_reply(struct afs_call *call)
msg.msg_flags = 0;
call->state = AFS_CALL_AWAIT_ACK;
- switch (rxrpc_kernel_send_data(call->rxcall, &msg, 0)) {
+ switch (rxrpc_kernel_send_data(afs_socket, call->rxcall, &msg, 0)) {
case 0:
_leave(" [replied]");
return;
case -ENOMEM:
_debug("oom");
- rxrpc_kernel_abort_call(call->rxcall, RX_USER_ABORT);
+ rxrpc_kernel_abort_call(afs_socket, call->rxcall,
+ RX_USER_ABORT, ENOMEM, "KOO");
default:
afs_end_call(call);
_leave(" [error]");
@@ -859,7 +747,7 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
msg.msg_flags = 0;
call->state = AFS_CALL_AWAIT_ACK;
- n = rxrpc_kernel_send_data(call->rxcall, &msg, len);
+ n = rxrpc_kernel_send_data(afs_socket, call->rxcall, &msg, len);
if (n >= 0) {
/* Success */
_leave(" [replied]");
@@ -868,7 +756,8 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
if (n == -ENOMEM) {
_debug("oom");
- rxrpc_kernel_abort_call(call->rxcall, RX_USER_ABORT);
+ rxrpc_kernel_abort_call(afs_socket, call->rxcall,
+ RX_USER_ABORT, ENOMEM, "KOO");
}
afs_end_call(call);
_leave(" [error]");
@@ -877,25 +766,40 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
/*
* Extract a piece of data from the received data socket buffers.
*/
-int afs_extract_data(struct afs_call *call, struct sk_buff *skb,
- bool last, void *buf, size_t count)
+int afs_extract_data(struct afs_call *call, void *buf, size_t count,
+ bool want_more)
{
- size_t len = skb->len;
+ int ret;
- _enter("{%u},{%zu},%d,,%zu", call->offset, len, last, count);
+ _enter("{%s,%zu},,%zu,%d",
+ call->type->name, call->offset, count, want_more);
- ASSERTCMP(call->offset, <, count);
+ ASSERTCMP(call->offset, <=, count);
- len = min_t(size_t, len, count - call->offset);
- if (skb_copy_bits(skb, 0, buf + call->offset, len) < 0 ||
- !pskb_pull(skb, len))
- BUG();
- call->offset += len;
+ ret = rxrpc_kernel_recv_data(afs_socket, call->rxcall,
+ buf, count, &call->offset,
+ want_more, &call->abort_code);
+ if (ret == 0 || ret == -EAGAIN)
+ return ret;
- if (call->offset < count) {
- afs_data_consumed(call, skb);
- _leave(" = -EAGAIN");
- return -EAGAIN;
+ if (ret == 1) {
+ switch (call->state) {
+ case AFS_CALL_AWAIT_REPLY:
+ call->state = AFS_CALL_COMPLETE;
+ break;
+ case AFS_CALL_AWAIT_REQUEST:
+ call->state = AFS_CALL_REPLYING;
+ break;
+ default:
+ break;
+ }
+ return 0;
}
- return 0;
+
+ if (ret == -ECONNABORTED)
+ call->error = call->type->abort_to_error(call->abort_code);
+ else
+ call->error = ret;
+ call->state = AFS_CALL_COMPLETE;
+ return ret;
}
diff --git a/fs/afs/server.c b/fs/afs/server.c
index f342acf3547d..d4066ab7dd55 100644
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -178,13 +178,18 @@ server_in_two_cells:
/*
* look up a server by its IP address
*/
-struct afs_server *afs_find_server(const struct in_addr *_addr)
+struct afs_server *afs_find_server(const struct sockaddr_rxrpc *srx)
{
struct afs_server *server = NULL;
struct rb_node *p;
- struct in_addr addr = *_addr;
+ struct in_addr addr = srx->transport.sin.sin_addr;
- _enter("%pI4", &addr.s_addr);
+ _enter("{%d,%pI4}", srx->transport.family, &addr.s_addr);
+
+ if (srx->transport.family != AF_INET) {
+ WARN(true, "AFS does not yes support non-IPv4 addresses\n");
+ return NULL;
+ }
read_lock(&afs_servers_lock);
diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c
index f94d1abdc3eb..94bcd97d22b8 100644
--- a/fs/afs/vlclient.c
+++ b/fs/afs/vlclient.c
@@ -58,17 +58,16 @@ static int afs_vl_abort_to_error(u32 abort_code)
/*
* deliver reply data to a VL.GetEntryByXXX call
*/
-static int afs_deliver_vl_get_entry_by_xxx(struct afs_call *call,
- struct sk_buff *skb, bool last)
+static int afs_deliver_vl_get_entry_by_xxx(struct afs_call *call)
{
struct afs_cache_vlocation *entry;
__be32 *bp;
u32 tmp;
int loop, ret;
- _enter(",,%u", last);
+ _enter("");
- ret = afs_transfer_reply(call, skb, last);
+ ret = afs_transfer_reply(call);
if (ret < 0)
return ret;
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c
index 52976785a32c..45a86396fd2d 100644
--- a/fs/afs/vlocation.c
+++ b/fs/afs/vlocation.c
@@ -594,8 +594,8 @@ static void afs_vlocation_reaper(struct work_struct *work)
*/
int __init afs_vlocation_update_init(void)
{
- afs_vlocation_update_worker =
- create_singlethread_workqueue("kafs_vlupdated");
+ afs_vlocation_update_worker = alloc_workqueue("kafs_vlupdated",
+ WQ_MEM_RECLAIM, 0);
return afs_vlocation_update_worker ? 0 : -ENOMEM;
}
diff --git a/fs/afs/write.c b/fs/afs/write.c
index 14d506efd1aa..f865c3f05bea 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -398,8 +398,7 @@ no_more:
switch (ret) {
case -EDQUOT:
case -ENOSPC:
- set_bit(AS_ENOSPC,
- &wb->vnode->vfs_inode.i_mapping->flags);
+ mapping_set_error(wb->vnode->vfs_inode.i_mapping, -ENOSPC);
break;
case -EROFS:
case -EIO:
@@ -409,7 +408,7 @@ no_more:
case -ENOMEDIUM:
case -ENXIO:
afs_kill_pages(wb->vnode, true, first, last);
- set_bit(AS_EIO, &wb->vnode->vfs_inode.i_mapping->flags);
+ mapping_set_error(wb->vnode->vfs_inode.i_mapping, -EIO);
break;
case -EACCES:
case -EPERM:
diff --git a/fs/aio.c b/fs/aio.c
index 4fe81d1c60f9..1157e13a36d6 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -274,14 +274,17 @@ __initcall(aio_setup);
static void put_aio_ring_file(struct kioctx *ctx)
{
struct file *aio_ring_file = ctx->aio_ring_file;
+ struct address_space *i_mapping;
+
if (aio_ring_file) {
truncate_setsize(aio_ring_file->f_inode, 0);
/* Prevent further access to the kioctx from migratepages */
- spin_lock(&aio_ring_file->f_inode->i_mapping->private_lock);
- aio_ring_file->f_inode->i_mapping->private_data = NULL;
+ i_mapping = aio_ring_file->f_inode->i_mapping;
+ spin_lock(&i_mapping->private_lock);
+ i_mapping->private_data = NULL;
ctx->aio_ring_file = NULL;
- spin_unlock(&aio_ring_file->f_inode->i_mapping->private_lock);
+ spin_unlock(&i_mapping->private_lock);
fput(aio_ring_file);
}
diff --git a/fs/attr.c b/fs/attr.c
index 42bb42bb3c72..c902b3d53508 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -17,19 +17,22 @@
#include <linux/ima.h>
/**
- * inode_change_ok - check if attribute changes to an inode are allowed
- * @inode: inode to check
+ * setattr_prepare - check if attribute changes to a dentry are allowed
+ * @dentry: dentry to check
* @attr: attributes to change
*
* Check if we are allowed to change the attributes contained in @attr
- * in the given inode. This includes the normal unix access permission
- * checks, as well as checks for rlimits and others.
+ * in the given dentry. This includes the normal unix access permission
+ * checks, as well as checks for rlimits and others. The function also clears
+ * SGID bit from mode if user is not allowed to set it. Also file capabilities
+ * and IMA extended attributes are cleared if ATTR_KILL_PRIV is set.
*
* Should be called as the first thing in ->setattr implementations,
* possibly after taking additional locks.
*/
-int inode_change_ok(const struct inode *inode, struct iattr *attr)
+int setattr_prepare(struct dentry *dentry, struct iattr *attr)
{
+ struct inode *inode = d_inode(dentry);
unsigned int ia_valid = attr->ia_valid;
/*
@@ -44,7 +47,7 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
/* If force is set do it anyway. */
if (ia_valid & ATTR_FORCE)
- return 0;
+ goto kill_priv;
/* Make sure a caller can chown. */
if ((ia_valid & ATTR_UID) &&
@@ -77,9 +80,19 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
return -EPERM;
}
+kill_priv:
+ /* User has permission for the change */
+ if (ia_valid & ATTR_KILL_PRIV) {
+ int error;
+
+ error = security_inode_killpriv(dentry);
+ if (error)
+ return error;
+ }
+
return 0;
}
-EXPORT_SYMBOL(inode_change_ok);
+EXPORT_SYMBOL(setattr_prepare);
/**
* inode_newsize_ok - may this inode be truncated to a given size
@@ -202,6 +215,21 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
return -EPERM;
}
+ /*
+ * If utimes(2) and friends are called with times == NULL (or both
+ * times are UTIME_NOW), then we need to check for write permission
+ */
+ if (ia_valid & ATTR_TOUCH) {
+ if (IS_IMMUTABLE(inode))
+ return -EPERM;
+
+ if (!inode_owner_or_capable(inode)) {
+ error = inode_permission(inode, MAY_WRITE);
+ if (error)
+ return error;
+ }
+ }
+
if ((ia_valid & ATTR_MODE)) {
umode_t amode = attr->ia_mode;
/* Flag setting protected by i_mutex */
@@ -209,7 +237,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
inode->i_flags &= ~S_NOSEC;
}
- now = current_fs_time(inode->i_sb);
+ now = current_time(inode);
attr->ia_ctime = now;
if (!(ia_valid & ATTR_ATIME_SET))
@@ -217,13 +245,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
if (!(ia_valid & ATTR_MTIME_SET))
attr->ia_mtime = now;
if (ia_valid & ATTR_KILL_PRIV) {
- attr->ia_valid &= ~ATTR_KILL_PRIV;
- ia_valid &= ~ATTR_KILL_PRIV;
error = security_inode_need_killpriv(dentry);
- if (error > 0)
- error = security_inode_killpriv(dentry);
- if (error)
+ if (error < 0)
return error;
+ if (error == 0)
+ ia_valid = attr->ia_valid &= ~ATTR_KILL_PRIV;
}
/*
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index a439548de785..a1fba4285277 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -20,7 +20,8 @@
#define AUTOFS_IOC_COUNT 32
#define AUTOFS_DEV_IOCTL_IOC_FIRST (AUTOFS_DEV_IOCTL_VERSION)
-#define AUTOFS_DEV_IOCTL_IOC_COUNT (AUTOFS_IOC_COUNT - 11)
+#define AUTOFS_DEV_IOCTL_IOC_COUNT \
+ (AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD - AUTOFS_DEV_IOCTL_VERSION_CMD)
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -33,8 +34,6 @@
#include <asm/current.h>
#include <linux/uaccess.h>
-/* #define DEBUG */
-
#ifdef pr_fmt
#undef pr_fmt
#endif
@@ -111,8 +110,6 @@ struct autofs_sb_info {
int max_proto;
unsigned long exp_timeout;
unsigned int type;
- int reghost_enabled;
- int needs_reghost;
struct super_block *sb;
struct mutex wq_mutex;
struct mutex pipe_mutex;
@@ -271,4 +268,4 @@ static inline void autofs4_del_expiring(struct dentry *dentry)
}
}
-extern void autofs4_kill_sb(struct super_block *);
+void autofs4_kill_sb(struct super_block *);
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index c7fcc7438843..fc09eb77ddf3 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -75,7 +75,7 @@ static int check_dev_ioctl_version(int cmd, struct autofs_dev_ioctl *param)
if ((param->ver_major != AUTOFS_DEV_IOCTL_VERSION_MAJOR) ||
(param->ver_minor > AUTOFS_DEV_IOCTL_VERSION_MINOR)) {
pr_warn("ioctl control interface version mismatch: "
- "kernel(%u.%u), user(%u.%u), cmd(%d)\n",
+ "kernel(%u.%u), user(%u.%u), cmd(0x%08x)\n",
AUTOFS_DEV_IOCTL_VERSION_MAJOR,
AUTOFS_DEV_IOCTL_VERSION_MINOR,
param->ver_major, param->ver_minor, cmd);
@@ -172,6 +172,17 @@ static struct autofs_sb_info *autofs_dev_ioctl_sbi(struct file *f)
return sbi;
}
+/* Return autofs dev ioctl version */
+static int autofs_dev_ioctl_version(struct file *fp,
+ struct autofs_sb_info *sbi,
+ struct autofs_dev_ioctl *param)
+{
+ /* This should have already been set. */
+ param->ver_major = AUTOFS_DEV_IOCTL_VERSION_MAJOR;
+ param->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR;
+ return 0;
+}
+
/* Return autofs module protocol version */
static int autofs_dev_ioctl_protover(struct file *fp,
struct autofs_sb_info *sbi,
@@ -586,41 +597,25 @@ out:
static ioctl_fn lookup_dev_ioctl(unsigned int cmd)
{
- static struct {
- int cmd;
- ioctl_fn fn;
- } _ioctls[] = {
- {cmd_idx(AUTOFS_DEV_IOCTL_VERSION_CMD), NULL},
- {cmd_idx(AUTOFS_DEV_IOCTL_PROTOVER_CMD),
- autofs_dev_ioctl_protover},
- {cmd_idx(AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD),
- autofs_dev_ioctl_protosubver},
- {cmd_idx(AUTOFS_DEV_IOCTL_OPENMOUNT_CMD),
- autofs_dev_ioctl_openmount},
- {cmd_idx(AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD),
- autofs_dev_ioctl_closemount},
- {cmd_idx(AUTOFS_DEV_IOCTL_READY_CMD),
- autofs_dev_ioctl_ready},
- {cmd_idx(AUTOFS_DEV_IOCTL_FAIL_CMD),
- autofs_dev_ioctl_fail},
- {cmd_idx(AUTOFS_DEV_IOCTL_SETPIPEFD_CMD),
- autofs_dev_ioctl_setpipefd},
- {cmd_idx(AUTOFS_DEV_IOCTL_CATATONIC_CMD),
- autofs_dev_ioctl_catatonic},
- {cmd_idx(AUTOFS_DEV_IOCTL_TIMEOUT_CMD),
- autofs_dev_ioctl_timeout},
- {cmd_idx(AUTOFS_DEV_IOCTL_REQUESTER_CMD),
- autofs_dev_ioctl_requester},
- {cmd_idx(AUTOFS_DEV_IOCTL_EXPIRE_CMD),
- autofs_dev_ioctl_expire},
- {cmd_idx(AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD),
- autofs_dev_ioctl_askumount},
- {cmd_idx(AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD),
- autofs_dev_ioctl_ismountpoint}
+ static ioctl_fn _ioctls[] = {
+ autofs_dev_ioctl_version,
+ autofs_dev_ioctl_protover,
+ autofs_dev_ioctl_protosubver,
+ autofs_dev_ioctl_openmount,
+ autofs_dev_ioctl_closemount,
+ autofs_dev_ioctl_ready,
+ autofs_dev_ioctl_fail,
+ autofs_dev_ioctl_setpipefd,
+ autofs_dev_ioctl_catatonic,
+ autofs_dev_ioctl_timeout,
+ autofs_dev_ioctl_requester,
+ autofs_dev_ioctl_expire,
+ autofs_dev_ioctl_askumount,
+ autofs_dev_ioctl_ismountpoint,
};
unsigned int idx = cmd_idx(cmd);
- return (idx >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[idx].fn;
+ return (idx >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[idx];
}
/* ioctl dispatcher */
@@ -642,7 +637,7 @@ static int _autofs_dev_ioctl(unsigned int command,
cmd = _IOC_NR(command);
if (_IOC_TYPE(command) != _IOC_TYPE(AUTOFS_DEV_IOCTL_IOC_FIRST) ||
- cmd - cmd_first >= AUTOFS_DEV_IOCTL_IOC_COUNT) {
+ cmd - cmd_first > AUTOFS_DEV_IOCTL_IOC_COUNT) {
return -ENOTTY;
}
@@ -655,14 +650,11 @@ static int _autofs_dev_ioctl(unsigned int command,
if (err)
goto out;
- /* The validate routine above always sets the version */
- if (cmd == AUTOFS_DEV_IOCTL_VERSION_CMD)
- goto done;
-
fn = lookup_dev_ioctl(cmd);
if (!fn) {
pr_warn("unknown command 0x%08x\n", command);
- return -ENOTTY;
+ err = -ENOTTY;
+ goto out;
}
fp = NULL;
@@ -671,9 +663,11 @@ static int _autofs_dev_ioctl(unsigned int command,
/*
* For obvious reasons the openmount can't have a file
* descriptor yet. We don't take a reference to the
- * file during close to allow for immediate release.
+ * file during close to allow for immediate release,
+ * and the same for retrieving ioctl version.
*/
- if (cmd != AUTOFS_DEV_IOCTL_OPENMOUNT_CMD &&
+ if (cmd != AUTOFS_DEV_IOCTL_VERSION_CMD &&
+ cmd != AUTOFS_DEV_IOCTL_OPENMOUNT_CMD &&
cmd != AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD) {
fp = fget(param->ioctlfd);
if (!fp) {
@@ -706,7 +700,6 @@ cont:
if (fp)
fput(fp);
-done:
if (err >= 0 && copy_to_user(user, param, AUTOFS_DEV_IOCTL_SIZE))
err = -EFAULT;
out:
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 61b21051bd5a..438b5bf675b6 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -274,6 +274,23 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
goto fail_dput;
}
+ /* Test versions first */
+ if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION ||
+ sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) {
+ pr_err("kernel does not match daemon version "
+ "daemon (%d, %d) kernel (%d, %d)\n",
+ sbi->min_proto, sbi->max_proto,
+ AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION);
+ goto fail_dput;
+ }
+
+ /* Establish highest kernel protocol version */
+ if (sbi->max_proto > AUTOFS_MAX_PROTO_VERSION)
+ sbi->version = AUTOFS_MAX_PROTO_VERSION;
+ else
+ sbi->version = sbi->max_proto;
+ sbi->sub_version = AUTOFS_PROTO_SUBVERSION;
+
if (pgrp_set) {
sbi->oz_pgrp = find_get_pid(pgrp);
if (!sbi->oz_pgrp) {
@@ -291,29 +308,12 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
root_inode->i_fop = &autofs4_root_operations;
root_inode->i_op = &autofs4_dir_inode_operations;
- /* Couldn't this be tested earlier? */
- if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION ||
- sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) {
- pr_err("kernel does not match daemon version "
- "daemon (%d, %d) kernel (%d, %d)\n",
- sbi->min_proto, sbi->max_proto,
- AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION);
- goto fail_dput;
- }
-
- /* Establish highest kernel protocol version */
- if (sbi->max_proto > AUTOFS_MAX_PROTO_VERSION)
- sbi->version = AUTOFS_MAX_PROTO_VERSION;
- else
- sbi->version = sbi->max_proto;
- sbi->sub_version = AUTOFS_PROTO_SUBVERSION;
-
pr_debug("pipe fd = %d, pgrp = %u\n", pipefd, pid_nr(sbi->oz_pgrp));
pipe = fget(pipefd);
if (!pipe) {
pr_err("could not open pipe file descriptor\n");
- goto fail_dput;
+ goto fail_put_pid;
}
ret = autofs_prepare_pipe(pipe);
if (ret < 0)
@@ -334,14 +334,14 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
fail_fput:
pr_err("pipe file descriptor does not contain proper ops\n");
fput(pipe);
- /* fall through */
+fail_put_pid:
+ put_pid(sbi->oz_pgrp);
fail_dput:
dput(root);
goto fail_free;
fail_ino:
- kfree(ino);
+ autofs4_free_ino(ino);
fail_free:
- put_pid(sbi->oz_pgrp);
kfree(sbi);
s->s_fs_info = NULL;
return ret;
@@ -359,7 +359,7 @@ struct inode *autofs4_get_inode(struct super_block *sb, umode_t mode)
inode->i_uid = d_inode(sb->s_root)->i_uid;
inode->i_gid = d_inode(sb->s_root)->i_gid;
}
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
inode->i_ino = get_next_ino();
if (S_ISDIR(mode)) {
@@ -368,7 +368,8 @@ struct inode *autofs4_get_inode(struct super_block *sb, umode_t mode)
inode->i_fop = &autofs4_dir_operations;
} else if (S_ISLNK(mode)) {
inode->i_op = &autofs4_symlink_inode_operations;
- }
+ } else
+ WARN_ON(1);
return inode;
}
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index fa84bb8832e0..a11f73174877 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -577,8 +577,6 @@ static int autofs4_dir_symlink(struct inode *dir,
inode = autofs4_get_inode(dir->i_sb, S_IFLNK | 0555);
if (!inode) {
kfree(cp);
- if (!dentry->d_fsdata)
- kfree(ino);
return -ENOMEM;
}
inode->i_private = cp;
@@ -591,7 +589,7 @@ static int autofs4_dir_symlink(struct inode *dir,
if (p_ino && !IS_ROOT(dentry))
atomic_inc(&p_ino->count);
- dir->i_mtime = CURRENT_TIME;
+ dir->i_mtime = current_time(dir);
return 0;
}
@@ -631,7 +629,7 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
d_inode(dentry)->i_size = 0;
clear_nlink(d_inode(dentry));
- dir->i_mtime = CURRENT_TIME;
+ dir->i_mtime = current_time(dir);
spin_lock(&sbi->lookup_lock);
__autofs4_add_expiring(dentry);
@@ -762,7 +760,7 @@ static int autofs4_dir_mkdir(struct inode *dir,
if (p_ino && !IS_ROOT(dentry))
atomic_inc(&p_ino->count);
inc_nlink(dir);
- dir->i_mtime = CURRENT_TIME;
+ dir->i_mtime = current_time(dir);
return 0;
}
@@ -842,7 +840,7 @@ static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p)
if (may_umount(mnt))
status = 1;
- pr_debug("returning %d\n", status);
+ pr_debug("may umount %d\n", status);
status = put_user(status, p);
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 431fd7ee3488..e44271dfceb6 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -431,8 +431,8 @@ int autofs4_wait(struct autofs_sb_info *sbi,
memcpy(&wq->name, &qstr, sizeof(struct qstr));
wq->dev = autofs4_get_dev(sbi);
wq->ino = autofs4_get_ino(sbi);
- wq->uid = current_uid();
- wq->gid = current_gid();
+ wq->uid = current_real_cred()->uid;
+ wq->gid = current_real_cred()->gid;
wq->pid = pid;
wq->tgid = tgid;
wq->status = -EINTR; /* Status return if interrupted */
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 3ba385eaa26e..8712062275b8 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -100,29 +100,12 @@ static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs)
return -EIO;
}
-static int bad_inode_setxattr(struct dentry *dentry, struct inode *inode,
- const char *name, const void *value, size_t size, int flags)
-{
- return -EIO;
-}
-
-static ssize_t bad_inode_getxattr(struct dentry *dentry, struct inode *inode,
- const char *name, void *buffer, size_t size)
-{
- return -EIO;
-}
-
static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer,
size_t buffer_size)
{
return -EIO;
}
-static int bad_inode_removexattr(struct dentry *dentry, const char *name)
-{
- return -EIO;
-}
-
static const struct inode_operations bad_inode_ops =
{
.create = bad_inode_create,
@@ -133,7 +116,7 @@ static const struct inode_operations bad_inode_ops =
.mkdir = bad_inode_mkdir,
.rmdir = bad_inode_rmdir,
.mknod = bad_inode_mknod,
- .rename2 = bad_inode_rename2,
+ .rename = bad_inode_rename2,
.readlink = bad_inode_readlink,
/* follow_link must be no-op, otherwise unmounting this inode
won't work */
@@ -142,10 +125,7 @@ static const struct inode_operations bad_inode_ops =
.permission = bad_inode_permission,
.getattr = bad_inode_getattr,
.setattr = bad_inode_setattr,
- .setxattr = bad_inode_setxattr,
- .getxattr = bad_inode_getxattr,
.listxattr = bad_inode_listxattr,
- .removexattr = bad_inode_removexattr,
};
@@ -173,8 +153,9 @@ void make_bad_inode(struct inode *inode)
inode->i_mode = S_IFREG;
inode->i_atime = inode->i_mtime = inode->i_ctime =
- current_fs_time(inode->i_sb);
+ current_time(inode);
inode->i_op = &bad_inode_ops;
+ inode->i_opflags &= ~IOP_XATTR;
inode->i_fop = &bad_file_ops;
}
EXPORT_SYMBOL(make_bad_inode);
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 7da05b159ade..bfe9f9994935 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -789,7 +789,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
* Will be set to real fs blocksize later.
*
* Linux 2.4.10 and later refuse to read blocks smaller than
- * the hardsect size for the device. But we also need to read at
+ * the logical block size for the device. But we also need to read at
* least 1k to get the second 512 bytes of the volume.
* -WD 10-26-01
*/
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 34a5bc2f1290..3e5ac30e8b6f 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -97,7 +97,7 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
set_bit(ino, info->si_imap);
info->si_freei--;
inode_init_owner(inode, dir, mode);
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
inode->i_blocks = 0;
inode->i_op = &bfs_file_inops;
inode->i_fop = &bfs_file_operations;
@@ -165,7 +165,7 @@ static int bfs_link(struct dentry *old, struct inode *dir,
return err;
}
inc_nlink(inode);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
ihold(inode);
d_instantiate(new, inode);
@@ -194,7 +194,7 @@ static int bfs_unlink(struct inode *dir, struct dentry *dentry)
}
de->ino = 0;
mark_buffer_dirty_inode(bh, dir);
- dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+ dir->i_ctime = dir->i_mtime = current_time(dir);
mark_inode_dirty(dir);
inode->i_ctime = dir->i_ctime;
inode_dec_link_count(inode);
@@ -207,7 +207,8 @@ out_brelse:
}
static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags)
{
struct inode *old_inode, *new_inode;
struct buffer_head *old_bh, *new_bh;
@@ -215,6 +216,9 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct bfs_sb_info *info;
int error = -ENOENT;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
old_bh = new_bh = NULL;
old_inode = d_inode(old_dentry);
if (S_ISDIR(old_inode->i_mode))
@@ -249,10 +253,10 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
goto end_rename;
}
old_de->ino = 0;
- old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
+ old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
mark_inode_dirty(old_dir);
if (new_inode) {
- new_inode->i_ctime = CURRENT_TIME_SEC;
+ new_inode->i_ctime = current_time(new_inode);
inode_dec_link_count(new_inode);
}
mark_buffer_dirty_inode(old_bh, old_dir);
@@ -300,9 +304,9 @@ static int bfs_add_entry(struct inode *dir, const unsigned char *name,
pos = (block - sblock) * BFS_BSIZE + off;
if (pos >= dir->i_size) {
dir->i_size += BFS_DIRENT_SIZE;
- dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_ctime = current_time(dir);
}
- dir->i_mtime = CURRENT_TIME_SEC;
+ dir->i_mtime = current_time(dir);
mark_inode_dirty(dir);
de->ino = cpu_to_le16((u16)ino);
for (i = 0; i < BFS_NAMELEN; i++)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index e5495f37c6ed..2472af2798c7 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1624,20 +1624,12 @@ static void do_thread_regset_writeback(struct task_struct *task,
regset->writeback(task, regset, 1);
}
-#ifndef PR_REG_SIZE
-#define PR_REG_SIZE(S) sizeof(S)
-#endif
-
#ifndef PRSTATUS_SIZE
-#define PRSTATUS_SIZE(S) sizeof(S)
-#endif
-
-#ifndef PR_REG_PTR
-#define PR_REG_PTR(S) (&((S)->pr_reg))
+#define PRSTATUS_SIZE(S, R) sizeof(S)
#endif
#ifndef SET_PR_FPVALID
-#define SET_PR_FPVALID(S, V) ((S)->pr_fpvalid = (V))
+#define SET_PR_FPVALID(S, V, R) ((S)->pr_fpvalid = (V))
#endif
static int fill_thread_core_info(struct elf_thread_core_info *t,
@@ -1645,6 +1637,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
long signr, size_t *total)
{
unsigned int i;
+ unsigned int regset_size = view->regsets[0].n * view->regsets[0].size;
/*
* NT_PRSTATUS is the one special case, because the regset data
@@ -1653,12 +1646,11 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
* We assume that regset 0 is NT_PRSTATUS.
*/
fill_prstatus(&t->prstatus, t->task, signr);
- (void) view->regsets[0].get(t->task, &view->regsets[0],
- 0, PR_REG_SIZE(t->prstatus.pr_reg),
- PR_REG_PTR(&t->prstatus), NULL);
+ (void) view->regsets[0].get(t->task, &view->regsets[0], 0, regset_size,
+ &t->prstatus.pr_reg, NULL);
fill_note(&t->notes[0], "CORE", NT_PRSTATUS,
- PRSTATUS_SIZE(t->prstatus), &t->prstatus);
+ PRSTATUS_SIZE(t->prstatus, regset_size), &t->prstatus);
*total += notesize(&t->notes[0]);
do_thread_regset_writeback(t->task, &view->regsets[0]);
@@ -1688,7 +1680,8 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
regset->core_note_type,
size, data);
else {
- SET_PR_FPVALID(&t->prstatus, 1);
+ SET_PR_FPVALID(&t->prstatus,
+ 1, regset_size);
fill_note(&t->notes[i], "CORE",
NT_PRFPREG, size, data);
}
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 6103a6362ccd..9b4688ab1d8e 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -584,7 +584,7 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
inode->i_ino = get_next_ino();
inode->i_mode = mode;
inode->i_atime = inode->i_mtime = inode->i_ctime =
- current_fs_time(inode->i_sb);
+ current_time(inode);
}
return inode;
}
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 08ae99343d92..05b553368bb4 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -30,6 +30,7 @@
#include <linux/cleancache.h>
#include <linux/dax.h>
#include <linux/badblocks.h>
+#include <linux/falloc.h>
#include <asm/uaccess.h>
#include "internal.h"
@@ -180,9 +181,6 @@ blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
struct file *file = iocb->ki_filp;
struct inode *inode = bdev_file_inode(file);
- if (IS_DAX(inode))
- return dax_do_io(iocb, inode, iter, blkdev_get_block,
- NULL, DIO_SKIP_DIO_COUNT);
return __blockdev_direct_IO(iocb, inode, I_BDEV(inode), iter,
blkdev_get_block, NULL, NULL,
DIO_SKIP_DIO_COUNT);
@@ -302,14 +300,11 @@ int thaw_bdev(struct block_device *bdev, struct super_block *sb)
error = sb->s_op->thaw_super(sb);
else
error = thaw_super(sb);
- if (error) {
+ if (error)
bdev->bd_fsfreeze_count++;
- mutex_unlock(&bdev->bd_fsfreeze_mutex);
- return error;
- }
out:
mutex_unlock(&bdev->bd_fsfreeze_mutex);
- return 0;
+ return error;
}
EXPORT_SYMBOL(thaw_bdev);
@@ -1275,7 +1270,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
bdev->bd_disk = disk;
bdev->bd_queue = disk->queue;
bdev->bd_contains = bdev;
- bdev->bd_inode->i_flags = 0;
if (!partno) {
ret = -ENXIO;
@@ -1303,11 +1297,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
}
}
- if (!ret) {
+ if (!ret)
bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
- if (!bdev_dax_capable(bdev))
- bdev->bd_inode->i_flags &= ~S_DAX;
- }
/*
* If the device is invalidated, rescan partition
@@ -1342,8 +1333,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
goto out_clear;
}
bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);
- if (!bdev_dax_capable(bdev))
- bdev->bd_inode->i_flags &= ~S_DAX;
}
} else {
if (bdev->bd_contains == bdev) {
@@ -1787,6 +1776,81 @@ static const struct address_space_operations def_blk_aops = {
.is_dirty_writeback = buffer_check_dirty_writeback,
};
+#define BLKDEV_FALLOC_FL_SUPPORTED \
+ (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | \
+ FALLOC_FL_ZERO_RANGE | FALLOC_FL_NO_HIDE_STALE)
+
+static long blkdev_fallocate(struct file *file, int mode, loff_t start,
+ loff_t len)
+{
+ struct block_device *bdev = I_BDEV(bdev_file_inode(file));
+ struct request_queue *q = bdev_get_queue(bdev);
+ struct address_space *mapping;
+ loff_t end = start + len - 1;
+ loff_t isize;
+ int error;
+
+ /* Fail if we don't recognize the flags. */
+ if (mode & ~BLKDEV_FALLOC_FL_SUPPORTED)
+ return -EOPNOTSUPP;
+
+ /* Don't go off the end of the device. */
+ isize = i_size_read(bdev->bd_inode);
+ if (start >= isize)
+ return -EINVAL;
+ if (end >= isize) {
+ if (mode & FALLOC_FL_KEEP_SIZE) {
+ len = isize - start;
+ end = start + len - 1;
+ } else
+ return -EINVAL;
+ }
+
+ /*
+ * Don't allow IO that isn't aligned to logical block size.
+ */
+ if ((start | len) & (bdev_logical_block_size(bdev) - 1))
+ return -EINVAL;
+
+ /* Invalidate the page cache, including dirty pages. */
+ mapping = bdev->bd_inode->i_mapping;
+ truncate_inode_pages_range(mapping, start, end);
+
+ switch (mode) {
+ case FALLOC_FL_ZERO_RANGE:
+ case FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE:
+ error = blkdev_issue_zeroout(bdev, start >> 9, len >> 9,
+ GFP_KERNEL, false);
+ break;
+ case FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE:
+ /* Only punch if the device can do zeroing discard. */
+ if (!blk_queue_discard(q) || !q->limits.discard_zeroes_data)
+ return -EOPNOTSUPP;
+ error = blkdev_issue_discard(bdev, start >> 9, len >> 9,
+ GFP_KERNEL, 0);
+ break;
+ case FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE | FALLOC_FL_NO_HIDE_STALE:
+ if (!blk_queue_discard(q))
+ return -EOPNOTSUPP;
+ error = blkdev_issue_discard(bdev, start >> 9, len >> 9,
+ GFP_KERNEL, 0);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ if (error)
+ return error;
+
+ /*
+ * Invalidate again; if someone wandered in and dirtied a page,
+ * the caller will be given -EBUSY. The third argument is
+ * inclusive, so the rounding here is safe.
+ */
+ return invalidate_inode_pages2_range(mapping,
+ start >> PAGE_SHIFT,
+ end >> PAGE_SHIFT);
+}
+
const struct file_operations def_blk_fops = {
.open = blkdev_open,
.release = blkdev_close,
@@ -1801,6 +1865,7 @@ const struct file_operations def_blk_fops = {
#endif
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
+ .fallocate = blkdev_fallocate,
};
int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 53bb7af4e5f0..247b8dfaf6e5 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -79,11 +79,9 @@ static int __btrfs_set_acl(struct btrfs_trans_handle *trans,
case ACL_TYPE_ACCESS:
name = XATTR_NAME_POSIX_ACL_ACCESS;
if (acl) {
- ret = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (ret < 0)
+ ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (ret)
return ret;
- if (ret == 0)
- acl = NULL;
}
ret = 0;
break;
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 455a6b2fd539..85dc7ab8f89e 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -17,6 +17,7 @@
*/
#include <linux/vmalloc.h>
+#include <linux/rbtree.h>
#include "ctree.h"
#include "disk-io.h"
#include "backref.h"
@@ -34,6 +35,265 @@ struct extent_inode_elem {
struct extent_inode_elem *next;
};
+/*
+ * ref_root is used as the root of the ref tree that hold a collection
+ * of unique references.
+ */
+struct ref_root {
+ struct rb_root rb_root;
+
+ /*
+ * The unique_refs represents the number of ref_nodes with a positive
+ * count stored in the tree. Even if a ref_node (the count is greater
+ * than one) is added, the unique_refs will only increase by one.
+ */
+ unsigned int unique_refs;
+};
+
+/* ref_node is used to store a unique reference to the ref tree. */
+struct ref_node {
+ struct rb_node rb_node;
+
+ /* For NORMAL_REF, otherwise all these fields should be set to 0 */
+ u64 root_id;
+ u64 object_id;
+ u64 offset;
+
+ /* For SHARED_REF, otherwise parent field should be set to 0 */
+ u64 parent;
+
+ /* Ref to the ref_mod of btrfs_delayed_ref_node */
+ int ref_mod;
+};
+
+/* Dynamically allocate and initialize a ref_root */
+static struct ref_root *ref_root_alloc(void)
+{
+ struct ref_root *ref_tree;
+
+ ref_tree = kmalloc(sizeof(*ref_tree), GFP_NOFS);
+ if (!ref_tree)
+ return NULL;
+
+ ref_tree->rb_root = RB_ROOT;
+ ref_tree->unique_refs = 0;
+
+ return ref_tree;
+}
+
+/* Free all nodes in the ref tree, and reinit ref_root */
+static void ref_root_fini(struct ref_root *ref_tree)
+{
+ struct ref_node *node;
+ struct rb_node *next;
+
+ while ((next = rb_first(&ref_tree->rb_root)) != NULL) {
+ node = rb_entry(next, struct ref_node, rb_node);
+ rb_erase(next, &ref_tree->rb_root);
+ kfree(node);
+ }
+
+ ref_tree->rb_root = RB_ROOT;
+ ref_tree->unique_refs = 0;
+}
+
+static void ref_root_free(struct ref_root *ref_tree)
+{
+ if (!ref_tree)
+ return;
+
+ ref_root_fini(ref_tree);
+ kfree(ref_tree);
+}
+
+/*
+ * Compare ref_node with (root_id, object_id, offset, parent)
+ *
+ * The function compares two ref_node a and b. It returns an integer less
+ * than, equal to, or greater than zero , respectively, to be less than, to
+ * equal, or be greater than b.
+ */
+static int ref_node_cmp(struct ref_node *a, struct ref_node *b)
+{
+ if (a->root_id < b->root_id)
+ return -1;
+ else if (a->root_id > b->root_id)
+ return 1;
+
+ if (a->object_id < b->object_id)
+ return -1;
+ else if (a->object_id > b->object_id)
+ return 1;
+
+ if (a->offset < b->offset)
+ return -1;
+ else if (a->offset > b->offset)
+ return 1;
+
+ if (a->parent < b->parent)
+ return -1;
+ else if (a->parent > b->parent)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Search ref_node with (root_id, object_id, offset, parent) in the tree
+ *
+ * if found, the pointer of the ref_node will be returned;
+ * if not found, NULL will be returned and pos will point to the rb_node for
+ * insert, pos_parent will point to pos'parent for insert;
+*/
+static struct ref_node *__ref_tree_search(struct ref_root *ref_tree,
+ struct rb_node ***pos,
+ struct rb_node **pos_parent,
+ u64 root_id, u64 object_id,
+ u64 offset, u64 parent)
+{
+ struct ref_node *cur = NULL;
+ struct ref_node entry;
+ int ret;
+
+ entry.root_id = root_id;
+ entry.object_id = object_id;
+ entry.offset = offset;
+ entry.parent = parent;
+
+ *pos = &ref_tree->rb_root.rb_node;
+
+ while (**pos) {
+ *pos_parent = **pos;
+ cur = rb_entry(*pos_parent, struct ref_node, rb_node);
+
+ ret = ref_node_cmp(cur, &entry);
+ if (ret > 0)
+ *pos = &(**pos)->rb_left;
+ else if (ret < 0)
+ *pos = &(**pos)->rb_right;
+ else
+ return cur;
+ }
+
+ return NULL;
+}
+
+/*
+ * Insert a ref_node to the ref tree
+ * @pos used for specifiy the position to insert
+ * @pos_parent for specifiy pos's parent
+ *
+ * success, return 0;
+ * ref_node already exists, return -EEXIST;
+*/
+static int ref_tree_insert(struct ref_root *ref_tree, struct rb_node **pos,
+ struct rb_node *pos_parent, struct ref_node *ins)
+{
+ struct rb_node **p = NULL;
+ struct rb_node *parent = NULL;
+ struct ref_node *cur = NULL;
+
+ if (!pos) {
+ cur = __ref_tree_search(ref_tree, &p, &parent, ins->root_id,
+ ins->object_id, ins->offset,
+ ins->parent);
+ if (cur)
+ return -EEXIST;
+ } else {
+ p = pos;
+ parent = pos_parent;
+ }
+
+ rb_link_node(&ins->rb_node, parent, p);
+ rb_insert_color(&ins->rb_node, &ref_tree->rb_root);
+
+ return 0;
+}
+
+/* Erase and free ref_node, caller should update ref_root->unique_refs */
+static void ref_tree_remove(struct ref_root *ref_tree, struct ref_node *node)
+{
+ rb_erase(&node->rb_node, &ref_tree->rb_root);
+ kfree(node);
+}
+
+/*
+ * Update ref_root->unique_refs
+ *
+ * Call __ref_tree_search
+ * 1. if ref_node doesn't exist, ref_tree_insert this node, and update
+ * ref_root->unique_refs:
+ * if ref_node->ref_mod > 0, ref_root->unique_refs++;
+ * if ref_node->ref_mod < 0, do noting;
+ *
+ * 2. if ref_node is found, then get origin ref_node->ref_mod, and update
+ * ref_node->ref_mod.
+ * if ref_node->ref_mod is equal to 0,then call ref_tree_remove
+ *
+ * according to origin_mod and new_mod, update ref_root->items
+ * +----------------+--------------+-------------+
+ * | |new_count <= 0|new_count > 0|
+ * +----------------+--------------+-------------+
+ * |origin_count < 0| 0 | 1 |
+ * +----------------+--------------+-------------+
+ * |origin_count > 0| -1 | 0 |
+ * +----------------+--------------+-------------+
+ *
+ * In case of allocation failure, -ENOMEM is returned and the ref_tree stays
+ * unaltered.
+ * Success, return 0
+ */
+static int ref_tree_add(struct ref_root *ref_tree, u64 root_id, u64 object_id,
+ u64 offset, u64 parent, int count)
+{
+ struct ref_node *node = NULL;
+ struct rb_node **pos = NULL;
+ struct rb_node *pos_parent = NULL;
+ int origin_count;
+ int ret;
+
+ if (!count)
+ return 0;
+
+ node = __ref_tree_search(ref_tree, &pos, &pos_parent, root_id,
+ object_id, offset, parent);
+ if (node == NULL) {
+ node = kmalloc(sizeof(*node), GFP_NOFS);
+ if (!node)
+ return -ENOMEM;
+
+ node->root_id = root_id;
+ node->object_id = object_id;
+ node->offset = offset;
+ node->parent = parent;
+ node->ref_mod = count;
+
+ ret = ref_tree_insert(ref_tree, pos, pos_parent, node);
+ ASSERT(!ret);
+ if (ret) {
+ kfree(node);
+ return ret;
+ }
+
+ ref_tree->unique_refs += node->ref_mod > 0 ? 1 : 0;
+
+ return 0;
+ }
+
+ origin_count = node->ref_mod;
+ node->ref_mod += count;
+
+ if (node->ref_mod > 0)
+ ref_tree->unique_refs += origin_count > 0 ? 0 : 1;
+ else if (node->ref_mod <= 0)
+ ref_tree->unique_refs += origin_count > 0 ? -1 : 0;
+
+ if (!node->ref_mod)
+ ref_tree_remove(ref_tree, node);
+
+ return 0;
+}
+
static int check_extent_in_eb(struct btrfs_key *key, struct extent_buffer *eb,
struct btrfs_file_extent_item *fi,
u64 extent_item_pos,
@@ -390,8 +650,8 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
/* root node has been locked, we can release @subvol_srcu safely here */
srcu_read_unlock(&fs_info->subvol_srcu, index);
- pr_debug("search slot in root %llu (level %d, ref count %d) returned "
- "%d for key (%llu %u %llu)\n",
+ btrfs_debug(fs_info,
+ "search slot in root %llu (level %d, ref count %d) returned %d for key (%llu %u %llu)",
ref->root_id, level, ref->count, ret,
ref->key_for_search.objectid, ref->key_for_search.type,
ref->key_for_search.offset);
@@ -700,6 +960,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq,
static int __add_inline_refs(struct btrfs_fs_info *fs_info,
struct btrfs_path *path, u64 bytenr,
int *info_level, struct list_head *prefs,
+ struct ref_root *ref_tree,
u64 *total_refs, u64 inum)
{
int ret = 0;
@@ -767,6 +1028,13 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info,
count = btrfs_shared_data_ref_count(leaf, sdref);
ret = __add_prelim_ref(prefs, 0, NULL, 0, offset,
bytenr, count, GFP_NOFS);
+ if (ref_tree) {
+ if (!ret)
+ ret = ref_tree_add(ref_tree, 0, 0, 0,
+ bytenr, count);
+ if (!ret && ref_tree->unique_refs > 1)
+ ret = BACKREF_FOUND_SHARED;
+ }
break;
}
case BTRFS_TREE_BLOCK_REF_KEY:
@@ -794,6 +1062,15 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info,
root = btrfs_extent_data_ref_root(leaf, dref);
ret = __add_prelim_ref(prefs, root, &key, 0, 0,
bytenr, count, GFP_NOFS);
+ if (ref_tree) {
+ if (!ret)
+ ret = ref_tree_add(ref_tree, root,
+ key.objectid,
+ key.offset, 0,
+ count);
+ if (!ret && ref_tree->unique_refs > 1)
+ ret = BACKREF_FOUND_SHARED;
+ }
break;
}
default:
@@ -812,7 +1089,8 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info,
*/
static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
struct btrfs_path *path, u64 bytenr,
- int info_level, struct list_head *prefs, u64 inum)
+ int info_level, struct list_head *prefs,
+ struct ref_root *ref_tree, u64 inum)
{
struct btrfs_root *extent_root = fs_info->extent_root;
int ret;
@@ -855,6 +1133,13 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
count = btrfs_shared_data_ref_count(leaf, sdref);
ret = __add_prelim_ref(prefs, 0, NULL, 0, key.offset,
bytenr, count, GFP_NOFS);
+ if (ref_tree) {
+ if (!ret)
+ ret = ref_tree_add(ref_tree, 0, 0, 0,
+ bytenr, count);
+ if (!ret && ref_tree->unique_refs > 1)
+ ret = BACKREF_FOUND_SHARED;
+ }
break;
}
case BTRFS_TREE_BLOCK_REF_KEY:
@@ -883,6 +1168,15 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
root = btrfs_extent_data_ref_root(leaf, dref);
ret = __add_prelim_ref(prefs, root, &key, 0, 0,
bytenr, count, GFP_NOFS);
+ if (ref_tree) {
+ if (!ret)
+ ret = ref_tree_add(ref_tree, root,
+ key.objectid,
+ key.offset, 0,
+ count);
+ if (!ret && ref_tree->unique_refs > 1)
+ ret = BACKREF_FOUND_SHARED;
+ }
break;
}
default:
@@ -909,13 +1203,16 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
* commit root.
* The special case is for qgroup to search roots in commit_transaction().
*
+ * If check_shared is set to 1, any extent has more than one ref item, will
+ * be returned BACKREF_FOUND_SHARED immediately.
+ *
* FIXME some caching might speed things up
*/
static int find_parent_nodes(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 bytenr,
u64 time_seq, struct ulist *refs,
struct ulist *roots, const u64 *extent_item_pos,
- u64 root_objectid, u64 inum)
+ u64 root_objectid, u64 inum, int check_shared)
{
struct btrfs_key key;
struct btrfs_path *path;
@@ -927,6 +1224,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
struct list_head prefs;
struct __prelim_ref *ref;
struct extent_inode_elem *eie = NULL;
+ struct ref_root *ref_tree = NULL;
u64 total_refs = 0;
INIT_LIST_HEAD(&prefs);
@@ -958,6 +1256,18 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
again:
head = NULL;
+ if (check_shared) {
+ if (!ref_tree) {
+ ref_tree = ref_root_alloc();
+ if (!ref_tree) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ } else {
+ ref_root_fini(ref_tree);
+ }
+ }
+
ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 0);
if (ret < 0)
goto out;
@@ -1002,6 +1312,36 @@ again:
} else {
spin_unlock(&delayed_refs->lock);
}
+
+ if (check_shared && !list_empty(&prefs_delayed)) {
+ /*
+ * Add all delay_ref to the ref_tree and check if there
+ * are multiple ref items added.
+ */
+ list_for_each_entry(ref, &prefs_delayed, list) {
+ if (ref->key_for_search.type) {
+ ret = ref_tree_add(ref_tree,
+ ref->root_id,
+ ref->key_for_search.objectid,
+ ref->key_for_search.offset,
+ 0, ref->count);
+ if (ret)
+ goto out;
+ } else {
+ ret = ref_tree_add(ref_tree, 0, 0, 0,
+ ref->parent, ref->count);
+ if (ret)
+ goto out;
+ }
+
+ }
+
+ if (ref_tree->unique_refs > 1) {
+ ret = BACKREF_FOUND_SHARED;
+ goto out;
+ }
+
+ }
}
if (path->slots[0]) {
@@ -1017,11 +1357,13 @@ again:
key.type == BTRFS_METADATA_ITEM_KEY)) {
ret = __add_inline_refs(fs_info, path, bytenr,
&info_level, &prefs,
- &total_refs, inum);
+ ref_tree, &total_refs,
+ inum);
if (ret)
goto out;
ret = __add_keyed_refs(fs_info, path, bytenr,
- info_level, &prefs, inum);
+ info_level, &prefs,
+ ref_tree, inum);
if (ret)
goto out;
}
@@ -1106,6 +1448,7 @@ again:
out:
btrfs_free_path(path);
+ ref_root_free(ref_tree);
while (!list_empty(&prefs)) {
ref = list_first_entry(&prefs, struct __prelim_ref, list);
list_del(&ref->list);
@@ -1159,8 +1502,8 @@ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans,
if (!*leafs)
return -ENOMEM;
- ret = find_parent_nodes(trans, fs_info, bytenr,
- time_seq, *leafs, NULL, extent_item_pos, 0, 0);
+ ret = find_parent_nodes(trans, fs_info, bytenr, time_seq,
+ *leafs, NULL, extent_item_pos, 0, 0, 0);
if (ret < 0 && ret != -ENOENT) {
free_leaf_list(*leafs);
return ret;
@@ -1202,8 +1545,8 @@ static int __btrfs_find_all_roots(struct btrfs_trans_handle *trans,
ULIST_ITER_INIT(&uiter);
while (1) {
- ret = find_parent_nodes(trans, fs_info, bytenr,
- time_seq, tmp, *roots, NULL, 0, 0);
+ ret = find_parent_nodes(trans, fs_info, bytenr, time_seq,
+ tmp, *roots, NULL, 0, 0, 0);
if (ret < 0 && ret != -ENOENT) {
ulist_free(tmp);
ulist_free(*roots);
@@ -1273,7 +1616,7 @@ int btrfs_check_shared(struct btrfs_trans_handle *trans,
ULIST_ITER_INIT(&uiter);
while (1) {
ret = find_parent_nodes(trans, fs_info, bytenr, elem.seq, tmp,
- roots, NULL, root_objectid, inum);
+ roots, NULL, root_objectid, inum, 1);
if (ret == BACKREF_FOUND_SHARED) {
/* this is the only condition under which we return 1 */
ret = 1;
@@ -1492,7 +1835,8 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
if (found_key->objectid > logical ||
found_key->objectid + size <= logical) {
- pr_debug("logical %llu is not within any extent\n", logical);
+ btrfs_debug(fs_info,
+ "logical %llu is not within any extent", logical);
return -ENOENT;
}
@@ -1503,8 +1847,8 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
flags = btrfs_extent_flags(eb, ei);
- pr_debug("logical %llu is at position %llu within the extent (%llu "
- "EXTENT_ITEM %llu) flags %#llx size %u\n",
+ btrfs_debug(fs_info,
+ "logical %llu is at position %llu within the extent (%llu EXTENT_ITEM %llu) flags %#llx size %u",
logical, logical - found_key->objectid, found_key->objectid,
found_key->offset, flags, item_size);
@@ -1625,21 +1969,24 @@ int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb,
return 0;
}
-static int iterate_leaf_refs(struct extent_inode_elem *inode_list,
- u64 root, u64 extent_item_objectid,
- iterate_extent_inodes_t *iterate, void *ctx)
+static int iterate_leaf_refs(struct btrfs_fs_info *fs_info,
+ struct extent_inode_elem *inode_list,
+ u64 root, u64 extent_item_objectid,
+ iterate_extent_inodes_t *iterate, void *ctx)
{
struct extent_inode_elem *eie;
int ret = 0;
for (eie = inode_list; eie; eie = eie->next) {
- pr_debug("ref for %llu resolved, key (%llu EXTEND_DATA %llu), "
- "root %llu\n", extent_item_objectid,
- eie->inum, eie->offset, root);
+ btrfs_debug(fs_info,
+ "ref for %llu resolved, key (%llu EXTEND_DATA %llu), root %llu",
+ extent_item_objectid, eie->inum,
+ eie->offset, root);
ret = iterate(eie->inum, eie->offset, root, ctx);
if (ret) {
- pr_debug("stopping iteration for %llu due to ret=%d\n",
- extent_item_objectid, ret);
+ btrfs_debug(fs_info,
+ "stopping iteration for %llu due to ret=%d",
+ extent_item_objectid, ret);
break;
}
}
@@ -1667,7 +2014,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
struct ulist_iterator ref_uiter;
struct ulist_iterator root_uiter;
- pr_debug("resolving all inodes for extent %llu\n",
+ btrfs_debug(fs_info, "resolving all inodes for extent %llu",
extent_item_objectid);
if (!search_commit_root) {
@@ -1693,10 +2040,12 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
break;
ULIST_ITER_INIT(&root_uiter);
while (!ret && (root_node = ulist_next(roots, &root_uiter))) {
- pr_debug("root %llu references leaf %llu, data list "
- "%#llx\n", root_node->val, ref_node->val,
- ref_node->aux);
- ret = iterate_leaf_refs((struct extent_inode_elem *)
+ btrfs_debug(fs_info,
+ "root %llu references leaf %llu, data list %#llx",
+ root_node->val, ref_node->val,
+ ref_node->aux);
+ ret = iterate_leaf_refs(fs_info,
+ (struct extent_inode_elem *)
(uintptr_t)ref_node->aux,
root_node->val,
extent_item_objectid,
@@ -1792,9 +2141,9 @@ static int iterate_inode_refs(u64 inum, struct btrfs_root *fs_root,
for (cur = 0; cur < btrfs_item_size(eb, item); cur += len) {
name_len = btrfs_inode_ref_name_len(eb, iref);
/* path must be released before calling iterate()! */
- pr_debug("following ref at offset %u for inode %llu in "
- "tree %llu\n", cur, found_key.objectid,
- fs_root->objectid);
+ btrfs_debug(fs_root->fs_info,
+ "following ref at offset %u for inode %llu in tree %llu",
+ cur, found_key.objectid, fs_root->objectid);
ret = iterate(parent, name_len,
(unsigned long)(iref + 1), eb, ctx);
if (ret)
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index 4919aedb5fc1..1a8fa46ff87e 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -44,17 +44,6 @@
#define BTRFS_INODE_IN_DELALLOC_LIST 9
#define BTRFS_INODE_READDIO_NEED_LOCK 10
#define BTRFS_INODE_HAS_PROPS 11
-/*
- * The following 3 bits are meant only for the btree inode.
- * When any of them is set, it means an error happened while writing an
- * extent buffer belonging to:
- * 1) a non-log btree
- * 2) a log btree and first log sub-transaction
- * 3) a log btree and second log sub-transaction
- */
-#define BTRFS_INODE_BTREE_ERR 12
-#define BTRFS_INODE_BTREE_LOG1_ERR 13
-#define BTRFS_INODE_BTREE_LOG2_ERR 14
/* in memory btrfs inode */
struct btrfs_inode {
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c
index 66789471b49d..8e99251650b3 100644
--- a/fs/btrfs/check-integrity.c
+++ b/fs/btrfs/check-integrity.c
@@ -656,7 +656,7 @@ static int btrfsic_process_superblock(struct btrfsic_state *state,
BUG_ON(NULL == state);
selected_super = kzalloc(sizeof(*selected_super), GFP_NOFS);
if (NULL == selected_super) {
- printk(KERN_INFO "btrfsic: error, kmalloc failed!\n");
+ pr_info("btrfsic: error, kmalloc failed!\n");
return -ENOMEM;
}
@@ -681,7 +681,7 @@ static int btrfsic_process_superblock(struct btrfsic_state *state,
}
if (NULL == state->latest_superblock) {
- printk(KERN_INFO "btrfsic: no superblock found!\n");
+ pr_info("btrfsic: no superblock found!\n");
kfree(selected_super);
return -1;
}
@@ -698,13 +698,13 @@ static int btrfsic_process_superblock(struct btrfsic_state *state,
next_bytenr = btrfs_super_root(selected_super);
if (state->print_mask &
BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
- printk(KERN_INFO "root@%llu\n", next_bytenr);
+ pr_info("root@%llu\n", next_bytenr);
break;
case 1:
next_bytenr = btrfs_super_chunk_root(selected_super);
if (state->print_mask &
BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
- printk(KERN_INFO "chunk@%llu\n", next_bytenr);
+ pr_info("chunk@%llu\n", next_bytenr);
break;
case 2:
next_bytenr = btrfs_super_log_root(selected_super);
@@ -712,7 +712,7 @@ static int btrfsic_process_superblock(struct btrfsic_state *state,
continue;
if (state->print_mask &
BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
- printk(KERN_INFO "log@%llu\n", next_bytenr);
+ pr_info("log@%llu\n", next_bytenr);
break;
}
@@ -720,7 +720,7 @@ static int btrfsic_process_superblock(struct btrfsic_state *state,
btrfs_num_copies(state->root->fs_info,
next_bytenr, state->metablock_size);
if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
- printk(KERN_INFO "num_copies(log_bytenr=%llu) = %d\n",
+ pr_info("num_copies(log_bytenr=%llu) = %d\n",
next_bytenr, num_copies);
for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
@@ -733,9 +733,7 @@ static int btrfsic_process_superblock(struct btrfsic_state *state,
&tmp_next_block_ctx,
mirror_num);
if (ret) {
- printk(KERN_INFO "btrfsic:"
- " btrfsic_map_block(root @%llu,"
- " mirror %d) failed!\n",
+ pr_info("btrfsic: btrfsic_map_block(root @%llu, mirror %d) failed!\n",
next_bytenr, mirror_num);
kfree(selected_super);
return -1;
@@ -758,8 +756,7 @@ static int btrfsic_process_superblock(struct btrfsic_state *state,
ret = btrfsic_read_block(state, &tmp_next_block_ctx);
if (ret < (int)PAGE_SIZE) {
- printk(KERN_INFO
- "btrfsic: read @logical %llu failed!\n",
+ pr_info("btrfsic: read @logical %llu failed!\n",
tmp_next_block_ctx.start);
btrfsic_release_block_ctx(&tmp_next_block_ctx);
kfree(selected_super);
@@ -820,7 +817,7 @@ static int btrfsic_process_superblock_dev_mirror(
if (NULL == superblock_tmp) {
superblock_tmp = btrfsic_block_alloc();
if (NULL == superblock_tmp) {
- printk(KERN_INFO "btrfsic: error, kmalloc failed!\n");
+ pr_info("btrfsic: error, kmalloc failed!\n");
brelse(bh);
return -1;
}
@@ -894,7 +891,7 @@ static int btrfsic_process_superblock_dev_mirror(
btrfs_num_copies(state->root->fs_info,
next_bytenr, state->metablock_size);
if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
- printk(KERN_INFO "num_copies(log_bytenr=%llu) = %d\n",
+ pr_info("num_copies(log_bytenr=%llu) = %d\n",
next_bytenr, num_copies);
for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
struct btrfsic_block *next_block;
@@ -905,8 +902,7 @@ static int btrfsic_process_superblock_dev_mirror(
state->metablock_size,
&tmp_next_block_ctx,
mirror_num)) {
- printk(KERN_INFO "btrfsic: btrfsic_map_block("
- "bytenr @%llu, mirror %d) failed!\n",
+ pr_info("btrfsic: btrfsic_map_block(bytenr @%llu, mirror %d) failed!\n",
next_bytenr, mirror_num);
brelse(bh);
return -1;
@@ -948,7 +944,7 @@ static struct btrfsic_stack_frame *btrfsic_stack_frame_alloc(void)
sf = kzalloc(sizeof(*sf), GFP_NOFS);
if (NULL == sf)
- printk(KERN_INFO "btrfsic: alloc memory failed!\n");
+ pr_info("btrfsic: alloc memory failed!\n");
else
sf->magic = BTRFSIC_BLOCK_STACK_FRAME_MAGIC_NUMBER;
return sf;
@@ -994,9 +990,7 @@ continue_with_new_stack_frame:
sf->nr = btrfs_stack_header_nritems(&leafhdr->header);
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO
- "leaf %llu items %d generation %llu"
- " owner %llu\n",
+ pr_info("leaf %llu items %d generation %llu owner %llu\n",
sf->block_ctx->start, sf->nr,
btrfs_stack_header_generation(
&leafhdr->header),
@@ -1023,8 +1017,7 @@ continue_with_current_leaf_stack_frame:
if (disk_item_offset + sizeof(struct btrfs_item) >
sf->block_ctx->len) {
leaf_item_out_of_bounce_error:
- printk(KERN_INFO
- "btrfsic: leaf item out of bounce at logical %llu, dev %s\n",
+ pr_info("btrfsic: leaf item out of bounce at logical %llu, dev %s\n",
sf->block_ctx->start,
sf->block_ctx->dev->name);
goto one_stack_frame_backwards;
@@ -1120,8 +1113,7 @@ leaf_item_out_of_bounce_error:
sf->nr = btrfs_stack_header_nritems(&nodehdr->header);
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO "node %llu level %d items %d"
- " generation %llu owner %llu\n",
+ pr_info("node %llu level %d items %d generation %llu owner %llu\n",
sf->block_ctx->start,
nodehdr->header.level, sf->nr,
btrfs_stack_header_generation(
@@ -1145,8 +1137,7 @@ continue_with_current_node_stack_frame:
(uintptr_t)nodehdr;
if (key_ptr_offset + sizeof(struct btrfs_key_ptr) >
sf->block_ctx->len) {
- printk(KERN_INFO
- "btrfsic: node item out of bounce at logical %llu, dev %s\n",
+ pr_info("btrfsic: node item out of bounce at logical %llu, dev %s\n",
sf->block_ctx->start,
sf->block_ctx->dev->name);
goto one_stack_frame_backwards;
@@ -1275,7 +1266,7 @@ static int btrfsic_create_link_to_next_block(
btrfs_num_copies(state->root->fs_info,
next_bytenr, state->metablock_size);
if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
- printk(KERN_INFO "num_copies(log_bytenr=%llu) = %d\n",
+ pr_info("num_copies(log_bytenr=%llu) = %d\n",
next_bytenr, *num_copiesp);
*mirror_nump = 1;
}
@@ -1284,15 +1275,13 @@ static int btrfsic_create_link_to_next_block(
return 0;
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO
- "btrfsic_create_link_to_next_block(mirror_num=%d)\n",
+ pr_info("btrfsic_create_link_to_next_block(mirror_num=%d)\n",
*mirror_nump);
ret = btrfsic_map_block(state, next_bytenr,
state->metablock_size,
next_block_ctx, *mirror_nump);
if (ret) {
- printk(KERN_INFO
- "btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n",
+ pr_info("btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n",
next_bytenr, *mirror_nump);
btrfsic_release_block_ctx(next_block_ctx);
*next_blockp = NULL;
@@ -1318,16 +1307,14 @@ static int btrfsic_create_link_to_next_block(
if (next_block->logical_bytenr != next_bytenr &&
!(!next_block->is_metadata &&
0 == next_block->logical_bytenr))
- printk(KERN_INFO
- "Referenced block @%llu (%s/%llu/%d) found in hash table, %c, bytenr mismatch (!= stored %llu).\n",
+ pr_info("Referenced block @%llu (%s/%llu/%d) found in hash table, %c, bytenr mismatch (!= stored %llu).\n",
next_bytenr, next_block_ctx->dev->name,
next_block_ctx->dev_bytenr, *mirror_nump,
btrfsic_get_block_type(state,
next_block),
next_block->logical_bytenr);
else
- printk(KERN_INFO
- "Referenced block @%llu (%s/%llu/%d) found in hash table, %c.\n",
+ pr_info("Referenced block @%llu (%s/%llu/%d) found in hash table, %c.\n",
next_bytenr, next_block_ctx->dev->name,
next_block_ctx->dev_bytenr, *mirror_nump,
btrfsic_get_block_type(state,
@@ -1348,7 +1335,7 @@ static int btrfsic_create_link_to_next_block(
if (NULL == l) {
l = btrfsic_block_link_alloc();
if (NULL == l) {
- printk(KERN_INFO "btrfsic: error, kmalloc failed!\n");
+ pr_info("btrfsic: error, kmalloc failed!\n");
btrfsic_release_block_ctx(next_block_ctx);
*next_blockp = NULL;
return -1;
@@ -1381,8 +1368,7 @@ static int btrfsic_create_link_to_next_block(
if (limit_nesting > 0 && did_alloc_block_link) {
ret = btrfsic_read_block(state, next_block_ctx);
if (ret < (int)next_block_ctx->len) {
- printk(KERN_INFO
- "btrfsic: read block @logical %llu failed!\n",
+ pr_info("btrfsic: read block @logical %llu failed!\n",
next_bytenr);
btrfsic_release_block_ctx(next_block_ctx);
*next_blockp = NULL;
@@ -1417,8 +1403,7 @@ static int btrfsic_handle_extent_data(
if (file_extent_item_offset +
offsetof(struct btrfs_file_extent_item, disk_num_bytes) >
block_ctx->len) {
- printk(KERN_INFO
- "btrfsic: file item out of bounce at logical %llu, dev %s\n",
+ pr_info("btrfsic: file item out of bounce at logical %llu, dev %s\n",
block_ctx->start, block_ctx->dev->name);
return -1;
}
@@ -1429,7 +1414,7 @@ static int btrfsic_handle_extent_data(
if (BTRFS_FILE_EXTENT_REG != file_extent_item.type ||
btrfs_stack_file_extent_disk_bytenr(&file_extent_item) == 0) {
if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE)
- printk(KERN_INFO "extent_data: type %u, disk_bytenr = %llu\n",
+ pr_info("extent_data: type %u, disk_bytenr = %llu\n",
file_extent_item.type,
btrfs_stack_file_extent_disk_bytenr(
&file_extent_item));
@@ -1438,8 +1423,7 @@ static int btrfsic_handle_extent_data(
if (file_extent_item_offset + sizeof(struct btrfs_file_extent_item) >
block_ctx->len) {
- printk(KERN_INFO
- "btrfsic: file item out of bounce at logical %llu, dev %s\n",
+ pr_info("btrfsic: file item out of bounce at logical %llu, dev %s\n",
block_ctx->start, block_ctx->dev->name);
return -1;
}
@@ -1457,8 +1441,7 @@ static int btrfsic_handle_extent_data(
generation = btrfs_stack_file_extent_generation(&file_extent_item);
if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE)
- printk(KERN_INFO "extent_data: type %u, disk_bytenr = %llu,"
- " offset = %llu, num_bytes = %llu\n",
+ pr_info("extent_data: type %u, disk_bytenr = %llu, offset = %llu, num_bytes = %llu\n",
file_extent_item.type,
btrfs_stack_file_extent_disk_bytenr(&file_extent_item),
btrfs_stack_file_extent_offset(&file_extent_item),
@@ -1477,7 +1460,7 @@ static int btrfsic_handle_extent_data(
btrfs_num_copies(state->root->fs_info,
next_bytenr, state->datablock_size);
if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
- printk(KERN_INFO "num_copies(log_bytenr=%llu) = %d\n",
+ pr_info("num_copies(log_bytenr=%llu) = %d\n",
next_bytenr, num_copies);
for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
struct btrfsic_block_data_ctx next_block_ctx;
@@ -1485,19 +1468,16 @@ static int btrfsic_handle_extent_data(
int block_was_created;
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO "btrfsic_handle_extent_data("
- "mirror_num=%d)\n", mirror_num);
+ pr_info("btrfsic_handle_extent_data(mirror_num=%d)\n",
+ mirror_num);
if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE)
- printk(KERN_INFO
- "\tdisk_bytenr = %llu, num_bytes %u\n",
+ pr_info("\tdisk_bytenr = %llu, num_bytes %u\n",
next_bytenr, chunk_len);
ret = btrfsic_map_block(state, next_bytenr,
chunk_len, &next_block_ctx,
mirror_num);
if (ret) {
- printk(KERN_INFO
- "btrfsic: btrfsic_map_block(@%llu,"
- " mirror=%d) failed!\n",
+ pr_info("btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n",
next_bytenr, mirror_num);
return -1;
}
@@ -1512,8 +1492,7 @@ static int btrfsic_handle_extent_data(
mirror_num,
&block_was_created);
if (NULL == next_block) {
- printk(KERN_INFO
- "btrfsic: error, kmalloc failed!\n");
+ pr_info("btrfsic: error, kmalloc failed!\n");
btrfsic_release_block_ctx(&next_block_ctx);
return -1;
}
@@ -1523,12 +1502,7 @@ static int btrfsic_handle_extent_data(
next_block->logical_bytenr != next_bytenr &&
!(!next_block->is_metadata &&
0 == next_block->logical_bytenr)) {
- printk(KERN_INFO
- "Referenced block"
- " @%llu (%s/%llu/%d)"
- " found in hash table, D,"
- " bytenr mismatch"
- " (!= stored %llu).\n",
+ pr_info("Referenced block @%llu (%s/%llu/%d) found in hash table, D, bytenr mismatch (!= stored %llu).\n",
next_bytenr,
next_block_ctx.dev->name,
next_block_ctx.dev_bytenr,
@@ -1592,7 +1566,7 @@ static int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len,
kfree(multi);
if (NULL == block_ctx_out->dev) {
ret = -ENXIO;
- printk(KERN_INFO "btrfsic: error, cannot lookup dev (#1)!\n");
+ pr_info("btrfsic: error, cannot lookup dev (#1)!\n");
}
return ret;
@@ -1638,8 +1612,7 @@ static int btrfsic_read_block(struct btrfsic_state *state,
BUG_ON(block_ctx->pagev);
BUG_ON(block_ctx->mem_to_free);
if (block_ctx->dev_bytenr & ((u64)PAGE_SIZE - 1)) {
- printk(KERN_INFO
- "btrfsic: read_block() with unaligned bytenr %llu\n",
+ pr_info("btrfsic: read_block() with unaligned bytenr %llu\n",
block_ctx->dev_bytenr);
return -1;
}
@@ -1666,8 +1639,7 @@ static int btrfsic_read_block(struct btrfsic_state *state,
bio = btrfs_io_bio_alloc(GFP_NOFS, num_pages - i);
if (!bio) {
- printk(KERN_INFO
- "btrfsic: bio_alloc() for %u pages failed!\n",
+ pr_info("btrfsic: bio_alloc() for %u pages failed!\n",
num_pages - i);
return -1;
}
@@ -1682,13 +1654,11 @@ static int btrfsic_read_block(struct btrfsic_state *state,
break;
}
if (j == i) {
- printk(KERN_INFO
- "btrfsic: error, failed to add a single page!\n");
+ pr_info("btrfsic: error, failed to add a single page!\n");
return -1;
}
if (submit_bio_wait(bio)) {
- printk(KERN_INFO
- "btrfsic: read error at logical %llu dev %s!\n",
+ pr_info("btrfsic: read error at logical %llu dev %s!\n",
block_ctx->start, block_ctx->dev->name);
bio_put(bio);
return -1;
@@ -1700,7 +1670,7 @@ static int btrfsic_read_block(struct btrfsic_state *state,
for (i = 0; i < num_pages; i++) {
block_ctx->datav[i] = kmap(block_ctx->pagev[i]);
if (!block_ctx->datav[i]) {
- printk(KERN_INFO "btrfsic: kmap() failed (dev %s)!\n",
+ pr_info("btrfsic: kmap() failed (dev %s)!\n",
block_ctx->dev->name);
return -1;
}
@@ -1715,19 +1685,17 @@ static void btrfsic_dump_database(struct btrfsic_state *state)
BUG_ON(NULL == state);
- printk(KERN_INFO "all_blocks_list:\n");
+ pr_info("all_blocks_list:\n");
list_for_each_entry(b_all, &state->all_blocks_list, all_blocks_node) {
const struct btrfsic_block_link *l;
- printk(KERN_INFO "%c-block @%llu (%s/%llu/%d)\n",
+ pr_info("%c-block @%llu (%s/%llu/%d)\n",
btrfsic_get_block_type(state, b_all),
b_all->logical_bytenr, b_all->dev_state->name,
b_all->dev_bytenr, b_all->mirror_num);
list_for_each_entry(l, &b_all->ref_to_list, node_ref_to) {
- printk(KERN_INFO " %c @%llu (%s/%llu/%d)"
- " refers %u* to"
- " %c @%llu (%s/%llu/%d)\n",
+ pr_info(" %c @%llu (%s/%llu/%d) refers %u* to %c @%llu (%s/%llu/%d)\n",
btrfsic_get_block_type(state, b_all),
b_all->logical_bytenr, b_all->dev_state->name,
b_all->dev_bytenr, b_all->mirror_num,
@@ -1740,9 +1708,7 @@ static void btrfsic_dump_database(struct btrfsic_state *state)
}
list_for_each_entry(l, &b_all->ref_from_list, node_ref_from) {
- printk(KERN_INFO " %c @%llu (%s/%llu/%d)"
- " is ref %u* from"
- " %c @%llu (%s/%llu/%d)\n",
+ pr_info(" %c @%llu (%s/%llu/%d) is ref %u* from %c @%llu (%s/%llu/%d)\n",
btrfsic_get_block_type(state, b_all),
b_all->logical_bytenr, b_all->dev_state->name,
b_all->dev_bytenr, b_all->mirror_num,
@@ -1754,7 +1720,7 @@ static void btrfsic_dump_database(struct btrfsic_state *state)
l->block_ref_from->mirror_num);
}
- printk(KERN_INFO "\n");
+ pr_info("\n");
}
}
@@ -1829,8 +1795,7 @@ again:
mapped_datav[0]);
if (num_pages * PAGE_SIZE <
BTRFS_SUPER_INFO_SIZE) {
- printk(KERN_INFO
- "btrfsic: cannot work with too short bios!\n");
+ pr_info("btrfsic: cannot work with too short bios!\n");
return;
}
is_metadata = 1;
@@ -1838,8 +1803,7 @@ again:
processed_len = BTRFS_SUPER_INFO_SIZE;
if (state->print_mask &
BTRFSIC_PRINT_MASK_TREE_BEFORE_SB_WRITE) {
- printk(KERN_INFO
- "[before new superblock is written]:\n");
+ pr_info("[before new superblock is written]:\n");
btrfsic_dump_tree_sub(state, block, 0);
}
}
@@ -1847,8 +1811,7 @@ again:
if (!block->is_superblock) {
if (num_pages * PAGE_SIZE <
state->metablock_size) {
- printk(KERN_INFO
- "btrfsic: cannot work with too short bios!\n");
+ pr_info("btrfsic: cannot work with too short bios!\n");
return;
}
processed_len = state->metablock_size;
@@ -1863,8 +1826,7 @@ again:
if (block->logical_bytenr != bytenr &&
!(!block->is_metadata &&
block->logical_bytenr == 0))
- printk(KERN_INFO
- "Written block @%llu (%s/%llu/%d) found in hash table, %c, bytenr mismatch (!= stored %llu).\n",
+ pr_info("Written block @%llu (%s/%llu/%d) found in hash table, %c, bytenr mismatch (!= stored %llu).\n",
bytenr, dev_state->name,
dev_bytenr,
block->mirror_num,
@@ -1872,8 +1834,7 @@ again:
block),
block->logical_bytenr);
else
- printk(KERN_INFO
- "Written block @%llu (%s/%llu/%d) found in hash table, %c.\n",
+ pr_info("Written block @%llu (%s/%llu/%d) found in hash table, %c.\n",
bytenr, dev_state->name,
dev_bytenr, block->mirror_num,
btrfsic_get_block_type(state,
@@ -1883,33 +1844,24 @@ again:
} else {
if (num_pages * PAGE_SIZE <
state->datablock_size) {
- printk(KERN_INFO
- "btrfsic: cannot work with too short bios!\n");
+ pr_info("btrfsic: cannot work with too short bios!\n");
return;
}
processed_len = state->datablock_size;
bytenr = block->logical_bytenr;
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO
- "Written block @%llu (%s/%llu/%d)"
- " found in hash table, %c.\n",
+ pr_info("Written block @%llu (%s/%llu/%d) found in hash table, %c.\n",
bytenr, dev_state->name, dev_bytenr,
block->mirror_num,
btrfsic_get_block_type(state, block));
}
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO
- "ref_to_list: %cE, ref_from_list: %cE\n",
+ pr_info("ref_to_list: %cE, ref_from_list: %cE\n",
list_empty(&block->ref_to_list) ? ' ' : '!',
list_empty(&block->ref_from_list) ? ' ' : '!');
if (btrfsic_is_block_ref_by_superblock(state, block, 0)) {
- printk(KERN_INFO "btrfs: attempt to overwrite %c-block"
- " @%llu (%s/%llu/%d), old(gen=%llu,"
- " objectid=%llu, type=%d, offset=%llu),"
- " new(gen=%llu),"
- " which is referenced by most recent superblock"
- " (superblockgen=%llu)!\n",
+ pr_info("btrfs: attempt to overwrite %c-block @%llu (%s/%llu/%d), old(gen=%llu, objectid=%llu, type=%d, offset=%llu), new(gen=%llu), which is referenced by most recent superblock (superblockgen=%llu)!\n",
btrfsic_get_block_type(state, block), bytenr,
dev_state->name, dev_bytenr, block->mirror_num,
block->generation,
@@ -1923,9 +1875,7 @@ again:
}
if (!block->is_iodone && !block->never_written) {
- printk(KERN_INFO "btrfs: attempt to overwrite %c-block"
- " @%llu (%s/%llu/%d), oldgen=%llu, newgen=%llu,"
- " which is not yet iodone!\n",
+ pr_info("btrfs: attempt to overwrite %c-block @%llu (%s/%llu/%d), oldgen=%llu, newgen=%llu, which is not yet iodone!\n",
btrfsic_get_block_type(state, block), bytenr,
dev_state->name, dev_bytenr, block->mirror_num,
block->generation,
@@ -2023,8 +1973,7 @@ again:
mapped_datav[0]);
if (state->print_mask &
BTRFSIC_PRINT_MASK_TREE_AFTER_SB_WRITE) {
- printk(KERN_INFO
- "[after new superblock is written]:\n");
+ pr_info("[after new superblock is written]:\n");
btrfsic_dump_tree_sub(state, block, 0);
}
} else {
@@ -2036,9 +1985,7 @@ again:
0, 0);
}
if (ret)
- printk(KERN_INFO
- "btrfsic: btrfsic_process_metablock"
- "(root @%llu) failed!\n",
+ pr_info("btrfsic: btrfsic_process_metablock(root @%llu) failed!\n",
dev_bytenr);
} else {
block->is_metadata = 0;
@@ -2065,8 +2012,7 @@ again:
if (!is_metadata) {
processed_len = state->datablock_size;
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO "Written block (%s/%llu/?)"
- " !found in hash table, D.\n",
+ pr_info("Written block (%s/%llu/?) !found in hash table, D.\n",
dev_state->name, dev_bytenr);
if (!state->include_extent_data) {
/* ignore that written D block */
@@ -2084,9 +2030,7 @@ again:
btrfsic_cmp_log_and_dev_bytenr(state, bytenr, dev_state,
dev_bytenr);
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO
- "Written block @%llu (%s/%llu/?)"
- " !found in hash table, M.\n",
+ pr_info("Written block @%llu (%s/%llu/?) !found in hash table, M.\n",
bytenr, dev_state->name, dev_bytenr);
}
@@ -2100,7 +2044,7 @@ again:
block = btrfsic_block_alloc();
if (NULL == block) {
- printk(KERN_INFO "btrfsic: error, kmalloc failed!\n");
+ pr_info("btrfsic: error, kmalloc failed!\n");
btrfsic_release_block_ctx(&block_ctx);
goto continue_loop;
}
@@ -2150,8 +2094,7 @@ again:
block->next_in_same_bio = NULL;
}
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO
- "New written %c-block @%llu (%s/%llu/%d)\n",
+ pr_info("New written %c-block @%llu (%s/%llu/%d)\n",
is_metadata ? 'M' : 'D',
block->logical_bytenr, block->dev_state->name,
block->dev_bytenr, block->mirror_num);
@@ -2162,9 +2105,7 @@ again:
ret = btrfsic_process_metablock(state, block,
&block_ctx, 0, 0);
if (ret)
- printk(KERN_INFO
- "btrfsic: process_metablock(root @%llu)"
- " failed!\n",
+ pr_info("btrfsic: process_metablock(root @%llu) failed!\n",
dev_bytenr);
}
btrfsic_release_block_ctx(&block_ctx);
@@ -2199,8 +2140,7 @@ static void btrfsic_bio_end_io(struct bio *bp)
if ((dev_state->state->print_mask &
BTRFSIC_PRINT_MASK_END_IO_BIO_BH))
- printk(KERN_INFO
- "bio_end_io(err=%d) for %c @%llu (%s/%llu/%d)\n",
+ pr_info("bio_end_io(err=%d) for %c @%llu (%s/%llu/%d)\n",
bp->bi_error,
btrfsic_get_block_type(dev_state->state, block),
block->logical_bytenr, dev_state->name,
@@ -2211,8 +2151,7 @@ static void btrfsic_bio_end_io(struct bio *bp)
dev_state->last_flush_gen++;
if ((dev_state->state->print_mask &
BTRFSIC_PRINT_MASK_END_IO_BIO_BH))
- printk(KERN_INFO
- "bio_end_io() new %s flush_gen=%llu\n",
+ pr_info("bio_end_io() new %s flush_gen=%llu\n",
dev_state->name,
dev_state->last_flush_gen);
}
@@ -2235,8 +2174,7 @@ static void btrfsic_bh_end_io(struct buffer_head *bh, int uptodate)
BUG_ON(NULL == block);
dev_state = block->dev_state;
if ((dev_state->state->print_mask & BTRFSIC_PRINT_MASK_END_IO_BIO_BH))
- printk(KERN_INFO
- "bh_end_io(error=%d) for %c @%llu (%s/%llu/%d)\n",
+ pr_info("bh_end_io(error=%d) for %c @%llu (%s/%llu/%d)\n",
iodone_w_error,
btrfsic_get_block_type(dev_state->state, block),
block->logical_bytenr, block->dev_state->name,
@@ -2247,8 +2185,7 @@ static void btrfsic_bh_end_io(struct buffer_head *bh, int uptodate)
dev_state->last_flush_gen++;
if ((dev_state->state->print_mask &
BTRFSIC_PRINT_MASK_END_IO_BIO_BH))
- printk(KERN_INFO
- "bh_end_io() new %s flush_gen=%llu\n",
+ pr_info("bh_end_io() new %s flush_gen=%llu\n",
dev_state->name, dev_state->last_flush_gen);
}
if (block->submit_bio_bh_rw & REQ_FUA)
@@ -2271,9 +2208,7 @@ static int btrfsic_process_written_superblock(
if (!(superblock->generation > state->max_superblock_generation ||
0 == state->max_superblock_generation)) {
if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
- printk(KERN_INFO
- "btrfsic: superblock @%llu (%s/%llu/%d)"
- " with old gen %llu <= %llu\n",
+ pr_info("btrfsic: superblock @%llu (%s/%llu/%d) with old gen %llu <= %llu\n",
superblock->logical_bytenr,
superblock->dev_state->name,
superblock->dev_bytenr, superblock->mirror_num,
@@ -2281,9 +2216,7 @@ static int btrfsic_process_written_superblock(
state->max_superblock_generation);
} else {
if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
- printk(KERN_INFO
- "btrfsic: got new superblock @%llu (%s/%llu/%d)"
- " with new gen %llu > %llu\n",
+ pr_info("btrfsic: got new superblock @%llu (%s/%llu/%d) with new gen %llu > %llu\n",
superblock->logical_bytenr,
superblock->dev_state->name,
superblock->dev_bytenr, superblock->mirror_num,
@@ -2318,7 +2251,7 @@ static int btrfsic_process_written_superblock(
next_bytenr = btrfs_super_root(super_hdr);
if (state->print_mask &
BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
- printk(KERN_INFO "root@%llu\n", next_bytenr);
+ pr_info("root@%llu\n", next_bytenr);
break;
case 1:
btrfs_set_disk_key_objectid(&tmp_disk_key,
@@ -2327,7 +2260,7 @@ static int btrfsic_process_written_superblock(
next_bytenr = btrfs_super_chunk_root(super_hdr);
if (state->print_mask &
BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
- printk(KERN_INFO "chunk@%llu\n", next_bytenr);
+ pr_info("chunk@%llu\n", next_bytenr);
break;
case 2:
btrfs_set_disk_key_objectid(&tmp_disk_key,
@@ -2338,7 +2271,7 @@ static int btrfsic_process_written_superblock(
continue;
if (state->print_mask &
BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
- printk(KERN_INFO "log@%llu\n", next_bytenr);
+ pr_info("log@%llu\n", next_bytenr);
break;
}
@@ -2346,23 +2279,19 @@ static int btrfsic_process_written_superblock(
btrfs_num_copies(state->root->fs_info,
next_bytenr, BTRFS_SUPER_INFO_SIZE);
if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
- printk(KERN_INFO "num_copies(log_bytenr=%llu) = %d\n",
+ pr_info("num_copies(log_bytenr=%llu) = %d\n",
next_bytenr, num_copies);
for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
int was_created;
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO
- "btrfsic_process_written_superblock("
- "mirror_num=%d)\n", mirror_num);
+ pr_info("btrfsic_process_written_superblock(mirror_num=%d)\n", mirror_num);
ret = btrfsic_map_block(state, next_bytenr,
BTRFS_SUPER_INFO_SIZE,
&tmp_next_block_ctx,
mirror_num);
if (ret) {
- printk(KERN_INFO
- "btrfsic: btrfsic_map_block(@%llu,"
- " mirror=%d) failed!\n",
+ pr_info("btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n",
next_bytenr, mirror_num);
return -1;
}
@@ -2375,8 +2304,7 @@ static int btrfsic_process_written_superblock(
mirror_num,
&was_created);
if (NULL == next_block) {
- printk(KERN_INFO
- "btrfsic: error, kmalloc failed!\n");
+ pr_info("btrfsic: error, kmalloc failed!\n");
btrfsic_release_block_ctx(&tmp_next_block_ctx);
return -1;
}
@@ -2425,8 +2353,7 @@ static int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
* by the most recent super block.
*/
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO
- "btrfsic: abort cyclic linkage (case 1).\n");
+ pr_info("btrfsic: abort cyclic linkage (case 1).\n");
return ret;
}
@@ -2437,9 +2364,7 @@ static int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
*/
list_for_each_entry(l, &block->ref_to_list, node_ref_to) {
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO
- "rl=%d, %c @%llu (%s/%llu/%d)"
- " %u* refers to %c @%llu (%s/%llu/%d)\n",
+ pr_info("rl=%d, %c @%llu (%s/%llu/%d) %u* refers to %c @%llu (%s/%llu/%d)\n",
recursion_level,
btrfsic_get_block_type(state, block),
block->logical_bytenr, block->dev_state->name,
@@ -2451,9 +2376,7 @@ static int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
l->block_ref_to->dev_bytenr,
l->block_ref_to->mirror_num);
if (l->block_ref_to->never_written) {
- printk(KERN_INFO "btrfs: attempt to write superblock"
- " which references block %c @%llu (%s/%llu/%d)"
- " which is never written!\n",
+ pr_info("btrfs: attempt to write superblock which references block %c @%llu (%s/%llu/%d) which is never written!\n",
btrfsic_get_block_type(state, l->block_ref_to),
l->block_ref_to->logical_bytenr,
l->block_ref_to->dev_state->name,
@@ -2461,9 +2384,7 @@ static int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
l->block_ref_to->mirror_num);
ret = -1;
} else if (!l->block_ref_to->is_iodone) {
- printk(KERN_INFO "btrfs: attempt to write superblock"
- " which references block %c @%llu (%s/%llu/%d)"
- " which is not yet iodone!\n",
+ pr_info("btrfs: attempt to write superblock which references block %c @%llu (%s/%llu/%d) which is not yet iodone!\n",
btrfsic_get_block_type(state, l->block_ref_to),
l->block_ref_to->logical_bytenr,
l->block_ref_to->dev_state->name,
@@ -2471,9 +2392,7 @@ static int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
l->block_ref_to->mirror_num);
ret = -1;
} else if (l->block_ref_to->iodone_w_error) {
- printk(KERN_INFO "btrfs: attempt to write superblock"
- " which references block %c @%llu (%s/%llu/%d)"
- " which has write error!\n",
+ pr_info("btrfs: attempt to write superblock which references block %c @%llu (%s/%llu/%d) which has write error!\n",
btrfsic_get_block_type(state, l->block_ref_to),
l->block_ref_to->logical_bytenr,
l->block_ref_to->dev_state->name,
@@ -2486,10 +2405,7 @@ static int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
l->parent_generation &&
BTRFSIC_GENERATION_UNKNOWN !=
l->block_ref_to->generation) {
- printk(KERN_INFO "btrfs: attempt to write superblock"
- " which references block %c @%llu (%s/%llu/%d)"
- " with generation %llu !="
- " parent generation %llu!\n",
+ pr_info("btrfs: attempt to write superblock which references block %c @%llu (%s/%llu/%d) with generation %llu != parent generation %llu!\n",
btrfsic_get_block_type(state, l->block_ref_to),
l->block_ref_to->logical_bytenr,
l->block_ref_to->dev_state->name,
@@ -2500,11 +2416,7 @@ static int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
ret = -1;
} else if (l->block_ref_to->flush_gen >
l->block_ref_to->dev_state->last_flush_gen) {
- printk(KERN_INFO "btrfs: attempt to write superblock"
- " which references block %c @%llu (%s/%llu/%d)"
- " which is not flushed out of disk's write cache"
- " (block flush_gen=%llu,"
- " dev->flush_gen=%llu)!\n",
+ pr_info("btrfs: attempt to write superblock which references block %c @%llu (%s/%llu/%d) which is not flushed out of disk's write cache (block flush_gen=%llu, dev->flush_gen=%llu)!\n",
btrfsic_get_block_type(state, l->block_ref_to),
l->block_ref_to->logical_bytenr,
l->block_ref_to->dev_state->name,
@@ -2533,8 +2445,7 @@ static int btrfsic_is_block_ref_by_superblock(
if (recursion_level >= 3 + BTRFS_MAX_LEVEL) {
/* refer to comment at "abort cyclic linkage (case 1)" */
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO
- "btrfsic: abort cyclic linkage (case 2).\n");
+ pr_info("btrfsic: abort cyclic linkage (case 2).\n");
return 0;
}
@@ -2545,9 +2456,7 @@ static int btrfsic_is_block_ref_by_superblock(
*/
list_for_each_entry(l, &block->ref_from_list, node_ref_from) {
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO
- "rl=%d, %c @%llu (%s/%llu/%d)"
- " is ref %u* from %c @%llu (%s/%llu/%d)\n",
+ pr_info("rl=%d, %c @%llu (%s/%llu/%d) is ref %u* from %c @%llu (%s/%llu/%d)\n",
recursion_level,
btrfsic_get_block_type(state, block),
block->logical_bytenr, block->dev_state->name,
@@ -2577,9 +2486,7 @@ static int btrfsic_is_block_ref_by_superblock(
static void btrfsic_print_add_link(const struct btrfsic_state *state,
const struct btrfsic_block_link *l)
{
- printk(KERN_INFO
- "Add %u* link from %c @%llu (%s/%llu/%d)"
- " to %c @%llu (%s/%llu/%d).\n",
+ pr_info("Add %u* link from %c @%llu (%s/%llu/%d) to %c @%llu (%s/%llu/%d).\n",
l->ref_cnt,
btrfsic_get_block_type(state, l->block_ref_from),
l->block_ref_from->logical_bytenr,
@@ -2594,9 +2501,7 @@ static void btrfsic_print_add_link(const struct btrfsic_state *state,
static void btrfsic_print_rem_link(const struct btrfsic_state *state,
const struct btrfsic_block_link *l)
{
- printk(KERN_INFO
- "Rem %u* link from %c @%llu (%s/%llu/%d)"
- " to %c @%llu (%s/%llu/%d).\n",
+ pr_info("Rem %u* link from %c @%llu (%s/%llu/%d) to %c @%llu (%s/%llu/%d).\n",
l->ref_cnt,
btrfsic_get_block_type(state, l->block_ref_from),
l->block_ref_from->logical_bytenr,
@@ -2708,8 +2613,7 @@ static struct btrfsic_block_link *btrfsic_block_link_lookup_or_add(
if (NULL == l) {
l = btrfsic_block_link_alloc();
if (NULL == l) {
- printk(KERN_INFO
- "btrfsic: error, kmalloc" " failed!\n");
+ pr_info("btrfsic: error, kmalloc failed!\n");
return NULL;
}
@@ -2756,13 +2660,12 @@ static struct btrfsic_block *btrfsic_block_lookup_or_add(
block = btrfsic_block_alloc();
if (NULL == block) {
- printk(KERN_INFO "btrfsic: error, kmalloc failed!\n");
+ pr_info("btrfsic: error, kmalloc failed!\n");
return NULL;
}
dev_state = btrfsic_dev_state_lookup(block_ctx->dev->bdev);
if (NULL == dev_state) {
- printk(KERN_INFO
- "btrfsic: error, lookup dev_state failed!\n");
+ pr_info("btrfsic: error, lookup dev_state failed!\n");
btrfsic_block_free(block);
return NULL;
}
@@ -2774,8 +2677,7 @@ static struct btrfsic_block *btrfsic_block_lookup_or_add(
block->never_written = never_written;
block->mirror_num = mirror_num;
if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
- printk(KERN_INFO
- "New %s%c-block @%llu (%s/%llu/%d)\n",
+ pr_info("New %s%c-block @%llu (%s/%llu/%d)\n",
additional_string,
btrfsic_get_block_type(state, block),
block->logical_bytenr, dev_state->name,
@@ -2810,9 +2712,7 @@ static void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state,
ret = btrfsic_map_block(state, bytenr, state->metablock_size,
&block_ctx, mirror_num);
if (ret) {
- printk(KERN_INFO "btrfsic:"
- " btrfsic_map_block(logical @%llu,"
- " mirror %d) failed!\n",
+ pr_info("btrfsic: btrfsic_map_block(logical @%llu, mirror %d) failed!\n",
bytenr, mirror_num);
continue;
}
@@ -2827,9 +2727,7 @@ static void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state,
}
if (WARN_ON(!match)) {
- printk(KERN_INFO "btrfs: attempt to write M-block which contains logical bytenr that doesn't map to dev+physical bytenr of submit_bio,"
- " buffer->log_bytenr=%llu, submit_bio(bdev=%s,"
- " phys_bytenr=%llu)!\n",
+ pr_info("btrfs: attempt to write M-block which contains logical bytenr that doesn't map to dev+physical bytenr of submit_bio, buffer->log_bytenr=%llu, submit_bio(bdev=%s, phys_bytenr=%llu)!\n",
bytenr, dev_state->name, dev_bytenr);
for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
ret = btrfsic_map_block(state, bytenr,
@@ -2838,8 +2736,7 @@ static void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state,
if (ret)
continue;
- printk(KERN_INFO "Read logical bytenr @%llu maps to"
- " (%s/%llu/%d)\n",
+ pr_info("Read logical bytenr @%llu maps to (%s/%llu/%d)\n",
bytenr, block_ctx.dev->name,
block_ctx.dev_bytenr, mirror_num);
}
@@ -2849,11 +2746,8 @@ static void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state,
static struct btrfsic_dev_state *btrfsic_dev_state_lookup(
struct block_device *bdev)
{
- struct btrfsic_dev_state *ds;
-
- ds = btrfsic_dev_state_hashtable_lookup(bdev,
- &btrfsic_dev_state_hashtable);
- return ds;
+ return btrfsic_dev_state_hashtable_lookup(bdev,
+ &btrfsic_dev_state_hashtable);
}
int btrfsic_submit_bh(int op, int op_flags, struct buffer_head *bh)
@@ -2876,9 +2770,7 @@ int btrfsic_submit_bh(int op, int op_flags, struct buffer_head *bh)
dev_bytenr = 4096 * bh->b_blocknr;
if (dev_state->state->print_mask &
BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
- printk(KERN_INFO
- "submit_bh(op=0x%x,0x%x, blocknr=%llu "
- "(bytenr %llu), size=%zu, data=%p, bdev=%p)\n",
+ pr_info("submit_bh(op=0x%x,0x%x, blocknr=%llu (bytenr %llu), size=%zu, data=%p, bdev=%p)\n",
op, op_flags, (unsigned long long)bh->b_blocknr,
dev_bytenr, bh->b_size, bh->b_data, bh->b_bdev);
btrfsic_process_written_block(dev_state, dev_bytenr,
@@ -2887,17 +2779,13 @@ int btrfsic_submit_bh(int op, int op_flags, struct buffer_head *bh)
} else if (NULL != dev_state && (op_flags & REQ_PREFLUSH)) {
if (dev_state->state->print_mask &
BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
- printk(KERN_INFO
- "submit_bh(op=0x%x,0x%x FLUSH, bdev=%p)\n",
+ pr_info("submit_bh(op=0x%x,0x%x FLUSH, bdev=%p)\n",
op, op_flags, bh->b_bdev);
if (!dev_state->dummy_block_for_bio_bh_flush.is_iodone) {
if ((dev_state->state->print_mask &
(BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH |
BTRFSIC_PRINT_MASK_VERBOSE)))
- printk(KERN_INFO
- "btrfsic_submit_bh(%s) with FLUSH"
- " but dummy block already in use"
- " (ignored)!\n",
+ pr_info("btrfsic_submit_bh(%s) with FLUSH but dummy block already in use (ignored)!\n",
dev_state->name);
} else {
struct btrfsic_block *const block =
@@ -2942,9 +2830,7 @@ static void __btrfsic_submit_bio(struct bio *bio)
bio_is_patched = 0;
if (dev_state->state->print_mask &
BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
- printk(KERN_INFO
- "submit_bio(rw=%d,0x%x, bi_vcnt=%u,"
- " bi_sector=%llu (bytenr %llu), bi_bdev=%p)\n",
+ pr_info("submit_bio(rw=%d,0x%x, bi_vcnt=%u, bi_sector=%llu (bytenr %llu), bi_bdev=%p)\n",
bio_op(bio), bio->bi_opf, bio->bi_vcnt,
(unsigned long long)bio->bi_iter.bi_sector,
dev_bytenr, bio->bi_bdev);
@@ -2967,8 +2853,7 @@ static void __btrfsic_submit_bio(struct bio *bio)
}
if (dev_state->state->print_mask &
BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH_VERBOSE)
- printk(KERN_INFO
- "#%u: bytenr=%llu, len=%u, offset=%u\n",
+ pr_info("#%u: bytenr=%llu, len=%u, offset=%u\n",
i, cur_bytenr, bio->bi_io_vec[i].bv_len,
bio->bi_io_vec[i].bv_offset);
cur_bytenr += bio->bi_io_vec[i].bv_len;
@@ -2985,17 +2870,13 @@ static void __btrfsic_submit_bio(struct bio *bio)
} else if (NULL != dev_state && (bio->bi_opf & REQ_PREFLUSH)) {
if (dev_state->state->print_mask &
BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
- printk(KERN_INFO
- "submit_bio(rw=%d,0x%x FLUSH, bdev=%p)\n",
+ pr_info("submit_bio(rw=%d,0x%x FLUSH, bdev=%p)\n",
bio_op(bio), bio->bi_opf, bio->bi_bdev);
if (!dev_state->dummy_block_for_bio_bh_flush.is_iodone) {
if ((dev_state->state->print_mask &
(BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH |
BTRFSIC_PRINT_MASK_VERBOSE)))
- printk(KERN_INFO
- "btrfsic_submit_bio(%s) with FLUSH"
- " but dummy block already in use"
- " (ignored)!\n",
+ pr_info("btrfsic_submit_bio(%s) with FLUSH but dummy block already in use (ignored)!\n",
dev_state->name);
} else {
struct btrfsic_block *const block =
@@ -3039,14 +2920,12 @@ int btrfsic_mount(struct btrfs_root *root,
struct btrfs_device *device;
if (root->nodesize & ((u64)PAGE_SIZE - 1)) {
- printk(KERN_INFO
- "btrfsic: cannot handle nodesize %d not being a multiple of PAGE_SIZE %ld!\n",
+ pr_info("btrfsic: cannot handle nodesize %d not being a multiple of PAGE_SIZE %ld!\n",
root->nodesize, PAGE_SIZE);
return -1;
}
if (root->sectorsize & ((u64)PAGE_SIZE - 1)) {
- printk(KERN_INFO
- "btrfsic: cannot handle sectorsize %d not being a multiple of PAGE_SIZE %ld!\n",
+ pr_info("btrfsic: cannot handle sectorsize %d not being a multiple of PAGE_SIZE %ld!\n",
root->sectorsize, PAGE_SIZE);
return -1;
}
@@ -3054,7 +2933,7 @@ int btrfsic_mount(struct btrfs_root *root,
if (!state) {
state = vzalloc(sizeof(*state));
if (!state) {
- printk(KERN_INFO "btrfs check-integrity: vzalloc() failed!\n");
+ pr_info("btrfs check-integrity: vzalloc() failed!\n");
return -1;
}
}
@@ -3086,8 +2965,7 @@ int btrfsic_mount(struct btrfs_root *root,
ds = btrfsic_dev_state_alloc();
if (NULL == ds) {
- printk(KERN_INFO
- "btrfs check-integrity: kmalloc() failed!\n");
+ pr_info("btrfs check-integrity: kmalloc() failed!\n");
mutex_unlock(&btrfsic_mutex);
return -1;
}
@@ -3148,9 +3026,7 @@ void btrfsic_unmount(struct btrfs_root *root,
}
if (NULL == state) {
- printk(KERN_INFO
- "btrfsic: error, cannot find state information"
- " on umount!\n");
+ pr_info("btrfsic: error, cannot find state information on umount!\n");
mutex_unlock(&btrfsic_mutex);
return;
}
@@ -3177,9 +3053,7 @@ void btrfsic_unmount(struct btrfs_root *root,
if (b_all->is_iodone || b_all->never_written)
btrfsic_block_free(b_all);
else
- printk(KERN_INFO "btrfs: attempt to free %c-block"
- " @%llu (%s/%llu/%d) on umount which is"
- " not yet iodone!\n",
+ pr_info("btrfs: attempt to free %c-block @%llu (%s/%llu/%d) on umount which is not yet iodone!\n",
btrfsic_get_block_type(state, b_all),
b_all->logical_bytenr, b_all->dev_state->name,
b_all->dev_bytenr, b_all->mirror_num);
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index 029db6e1105c..ccc70d96958d 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -783,8 +783,7 @@ void __init btrfs_init_compress(void)
*/
workspace = btrfs_compress_op[i]->alloc_workspace();
if (IS_ERR(workspace)) {
- printk(KERN_WARNING
- "BTRFS: cannot preallocate compression workspace, will try later");
+ pr_warn("BTRFS: cannot preallocate compression workspace, will try later\n");
} else {
atomic_set(&btrfs_comp_ws[i].total_ws, 1);
btrfs_comp_ws[i].free_ws = 1;
@@ -854,8 +853,7 @@ again:
/* no burst */ 1);
if (__ratelimit(&_rs)) {
- printk(KERN_WARNING
- "no compression workspaces, low memory, retrying");
+ pr_warn("BTRFS: no compression workspaces, low memory, retrying\n");
}
}
goto again;
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index d1c56c94dd5a..f6ba165d3f81 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -45,9 +45,7 @@ static int tree_mod_log_free_eb(struct btrfs_fs_info *fs_info,
struct btrfs_path *btrfs_alloc_path(void)
{
- struct btrfs_path *path;
- path = kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS);
- return path;
+ return kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS);
}
/*
@@ -1102,7 +1100,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
int level, ret;
int last_ref = 0;
int unlock_orig = 0;
- u64 parent_start;
+ u64 parent_start = 0;
if (*cow_ret == buf)
unlock_orig = 1;
@@ -1121,13 +1119,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
else
btrfs_node_key(buf, &disk_key, 0);
- if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) {
- if (parent)
- parent_start = parent->start;
- else
- parent_start = 0;
- } else
- parent_start = 0;
+ if ((root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && parent)
+ parent_start = parent->start;
cow = btrfs_alloc_tree_block(trans, root, parent_start,
root->root_key.objectid, &disk_key, level,
@@ -1170,8 +1163,6 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID ||
btrfs_header_backref_rev(buf) < BTRFS_MIXED_BACKREF_REV)
parent_start = buf->start;
- else
- parent_start = 0;
extent_buffer_get(cow);
tree_mod_log_set_root_pointer(root, cow, 1);
@@ -1182,11 +1173,6 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
free_extent_buffer(buf);
add_root_to_dirty_list(root);
} else {
- if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID)
- parent_start = parent->start;
- else
- parent_start = 0;
-
WARN_ON(trans->transid != btrfs_header_generation(parent));
tree_mod_log_insert_key(root->fs_info, parent, parent_slot,
MOD_LOG_KEY_REPLACE, GFP_NOFS);
@@ -1729,20 +1715,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
return err;
}
-/*
- * The leaf data grows from end-to-front in the node.
- * this returns the address of the start of the last item,
- * which is the stop of the leaf data stack
- */
-static inline unsigned int leaf_data_end(struct btrfs_root *root,
- struct extent_buffer *leaf)
-{
- u32 nr = btrfs_header_nritems(leaf);
- if (nr == 0)
- return BTRFS_LEAF_DATA_SIZE(root);
- return btrfs_item_offset_nr(leaf, nr - 1);
-}
-
/*
* search for key in the extent_buffer. The items start at offset p,
@@ -2268,7 +2240,6 @@ static void reada_for_search(struct btrfs_root *root,
u64 search;
u64 target;
u64 nread = 0;
- u64 gen;
struct extent_buffer *eb;
u32 nr;
u32 blocksize;
@@ -2313,7 +2284,6 @@ static void reada_for_search(struct btrfs_root *root,
search = btrfs_node_blockptr(node, nr);
if ((search <= target && target - search <= 65536) ||
(search > target && search - target <= 65536)) {
- gen = btrfs_node_ptr_generation(node, nr);
readahead_tree_block(root, search);
nread += blocksize;
}
@@ -4341,7 +4311,11 @@ again:
if (path->slots[1] == 0)
fixup_low_keys(fs_info, path, &disk_key, 1);
}
- btrfs_mark_buffer_dirty(right);
+ /*
+ * We create a new leaf 'right' for the required ins_len and
+ * we'll do btrfs_mark_buffer_dirty() on this leaf after copying
+ * the content of ins_len to 'right'.
+ */
return ret;
}
@@ -4772,8 +4746,9 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path,
if (btrfs_leaf_free_space(root, leaf) < total_size) {
btrfs_print_leaf(root, leaf);
- btrfs_crit(root->fs_info, "not enough freespace need %u have %d",
- total_size, btrfs_leaf_free_space(root, leaf));
+ btrfs_crit(root->fs_info,
+ "not enough freespace need %u have %d",
+ total_size, btrfs_leaf_free_space(root, leaf));
BUG();
}
@@ -4782,8 +4757,9 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path,
if (old_data < data_end) {
btrfs_print_leaf(root, leaf);
- btrfs_crit(root->fs_info, "slot %d old_data %d data_end %d",
- slot, old_data, data_end);
+ btrfs_crit(root->fs_info,
+ "slot %d old_data %d data_end %d",
+ slot, old_data, data_end);
BUG_ON(1);
}
/*
@@ -4793,7 +4769,7 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path,
for (i = slot; i < nritems; i++) {
u32 ioff;
- item = btrfs_item_nr( i);
+ item = btrfs_item_nr(i);
ioff = btrfs_token_item_offset(leaf, item, &token);
btrfs_set_token_item_offset(leaf, item,
ioff - total_data, &token);
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 33fe03551105..0b8ce2b9f7d0 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -37,6 +37,7 @@
#include <linux/workqueue.h>
#include <linux/security.h>
#include <linux/sizes.h>
+#include <linux/dynamic_debug.h>
#include "extent_io.h"
#include "extent_map.h"
#include "async-thread.h"
@@ -251,7 +252,8 @@ struct btrfs_super_block {
#define BTRFS_FEATURE_COMPAT_SAFE_CLEAR 0ULL
#define BTRFS_FEATURE_COMPAT_RO_SUPP \
- (BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE)
+ (BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE | \
+ BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID)
#define BTRFS_FEATURE_COMPAT_RO_SAFE_SET 0ULL
#define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR 0ULL
@@ -676,9 +678,25 @@ struct btrfs_device;
struct btrfs_fs_devices;
struct btrfs_balance_control;
struct btrfs_delayed_root;
+
+#define BTRFS_FS_BARRIER 1
+#define BTRFS_FS_CLOSING_START 2
+#define BTRFS_FS_CLOSING_DONE 3
+#define BTRFS_FS_LOG_RECOVERING 4
+#define BTRFS_FS_OPEN 5
+#define BTRFS_FS_QUOTA_ENABLED 6
+#define BTRFS_FS_QUOTA_ENABLING 7
+#define BTRFS_FS_QUOTA_DISABLING 8
+#define BTRFS_FS_UPDATE_UUID_TREE_GEN 9
+#define BTRFS_FS_CREATING_FREE_SPACE_TREE 10
+#define BTRFS_FS_BTREE_ERR 11
+#define BTRFS_FS_LOG1_ERR 12
+#define BTRFS_FS_LOG2_ERR 13
+
struct btrfs_fs_info {
u8 fsid[BTRFS_FSID_SIZE];
u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
+ unsigned long flags;
struct btrfs_root *extent_root;
struct btrfs_root *tree_root;
struct btrfs_root *chunk_root;
@@ -907,10 +925,6 @@ struct btrfs_fs_info {
int thread_pool_size;
struct kobject *space_info_kobj;
- int do_barriers;
- int closing;
- int log_root_recovering;
- int open;
u64 total_pinned;
@@ -987,17 +1001,6 @@ struct btrfs_fs_info {
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
u32 check_integrity_print_mask;
#endif
- /*
- * quota information
- */
- unsigned int quota_enabled:1;
-
- /*
- * quota_enabled only changes state after a commit. This holds the
- * next state.
- */
- unsigned int pending_quota_state:1;
-
/* is qgroup tracking in a consistent state? */
u64 qgroup_flags;
@@ -1061,7 +1064,6 @@ struct btrfs_fs_info {
wait_queue_head_t replace_wait;
struct semaphore uuid_tree_rescan_sem;
- unsigned int update_uuid_tree_gen:1;
/* Used to reclaim the metadata space in the background. */
struct work_struct async_reclaim_work;
@@ -1080,7 +1082,6 @@ struct btrfs_fs_info {
*/
struct list_head pinned_chunks;
- int creating_free_space_tree;
/* Used to record internally whether fs has been frozen */
int fs_frozen;
};
@@ -1435,13 +1436,13 @@ static inline void btrfs_init_map_token (struct btrfs_map_token *token)
#define cpu_to_le8(v) (v)
#define __le8 u8
-#define read_eb_member(eb, ptr, type, member, result) ( \
+#define read_eb_member(eb, ptr, type, member, result) (\
read_extent_buffer(eb, (char *)(result), \
((unsigned long)(ptr)) + \
offsetof(type, member), \
sizeof(((type *)0)->member)))
-#define write_eb_member(eb, ptr, type, member, result) ( \
+#define write_eb_member(eb, ptr, type, member, result) (\
write_extent_buffer(eb, (char *)(result), \
((unsigned long)(ptr)) + \
offsetof(type, member), \
@@ -2293,6 +2294,21 @@ static inline unsigned long btrfs_leaf_data(struct extent_buffer *l)
return offsetof(struct btrfs_leaf, items);
}
+/*
+ * The leaf data grows from end-to-front in the node.
+ * this returns the address of the start of the last item,
+ * which is the stop of the leaf data stack
+ */
+static inline unsigned int leaf_data_end(struct btrfs_root *root,
+ struct extent_buffer *leaf)
+{
+ u32 nr = btrfs_header_nritems(leaf);
+
+ if (nr == 0)
+ return BTRFS_LEAF_DATA_SIZE(root);
+ return btrfs_item_offset_nr(leaf, nr - 1);
+}
+
/* struct btrfs_file_extent_item */
BTRFS_SETGET_FUNCS(file_extent_type, struct btrfs_file_extent_item, type, 8);
BTRFS_SETGET_STACK_FUNCS(stack_file_extent_disk_bytenr,
@@ -2867,10 +2883,14 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
static inline int btrfs_fs_closing(struct btrfs_fs_info *fs_info)
{
/*
- * Get synced with close_ctree()
+ * Do it this way so we only ever do one test_bit in the normal case.
*/
- smp_mb();
- return fs_info->closing;
+ if (test_bit(BTRFS_FS_CLOSING_START, &fs_info->flags)) {
+ if (test_bit(BTRFS_FS_CLOSING_DONE, &fs_info->flags))
+ return 2;
+ return 1;
+ }
+ return 0;
}
/*
@@ -3118,7 +3138,7 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput);
int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput,
int nr);
int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end,
- struct extent_state **cached_state);
+ struct extent_state **cached_state, int dedupe);
int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
struct btrfs_root *new_root,
struct btrfs_root *parent_root,
@@ -3161,7 +3181,6 @@ int btrfs_prealloc_file_range_trans(struct inode *inode,
struct btrfs_trans_handle *trans, int mode,
u64 start, u64 num_bytes, u64 min_size,
loff_t actual_len, u64 *alloc_hint);
-int btrfs_inode_check_errors(struct inode *inode);
extern const struct dentry_operations btrfs_dentry_operations;
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
void btrfs_test_inode_set_ops(struct inode *inode);
@@ -3237,14 +3256,17 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
unsigned long new_flags);
int btrfs_sync_fs(struct super_block *sb, int wait);
+static inline __printf(2, 3)
+void btrfs_no_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...)
+{
+}
+
#ifdef CONFIG_PRINTK
__printf(2, 3)
void btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...);
#else
-static inline __printf(2, 3)
-void btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...)
-{
-}
+#define btrfs_printk(fs_info, fmt, args...) \
+ btrfs_no_printk(fs_info, fmt, ##args)
#endif
#define btrfs_emerg(fs_info, fmt, args...) \
@@ -3315,7 +3337,35 @@ void btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...)
btrfs_printk_ratelimited(fs_info, KERN_NOTICE fmt, ##args)
#define btrfs_info_rl(fs_info, fmt, args...) \
btrfs_printk_ratelimited(fs_info, KERN_INFO fmt, ##args)
-#ifdef DEBUG
+
+#if defined(CONFIG_DYNAMIC_DEBUG)
+#define btrfs_debug(fs_info, fmt, args...) \
+do { \
+ DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
+ if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \
+ btrfs_printk(fs_info, KERN_DEBUG fmt, ##args); \
+} while (0)
+#define btrfs_debug_in_rcu(fs_info, fmt, args...) \
+do { \
+ DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
+ if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \
+ btrfs_printk_in_rcu(fs_info, KERN_DEBUG fmt, ##args); \
+} while (0)
+#define btrfs_debug_rl_in_rcu(fs_info, fmt, args...) \
+do { \
+ DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
+ if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \
+ btrfs_printk_rl_in_rcu(fs_info, KERN_DEBUG fmt, \
+ ##args);\
+} while (0)
+#define btrfs_debug_rl(fs_info, fmt, args...) \
+do { \
+ DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
+ if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \
+ btrfs_printk_ratelimited(fs_info, KERN_DEBUG fmt, \
+ ##args); \
+} while (0)
+#elif defined(DEBUG)
#define btrfs_debug(fs_info, fmt, args...) \
btrfs_printk(fs_info, KERN_DEBUG fmt, ##args)
#define btrfs_debug_in_rcu(fs_info, fmt, args...) \
@@ -3326,13 +3376,13 @@ void btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...)
btrfs_printk_ratelimited(fs_info, KERN_DEBUG fmt, ##args)
#else
#define btrfs_debug(fs_info, fmt, args...) \
- no_printk(KERN_DEBUG fmt, ##args)
+ btrfs_no_printk(fs_info, KERN_DEBUG fmt, ##args)
#define btrfs_debug_in_rcu(fs_info, fmt, args...) \
- no_printk(KERN_DEBUG fmt, ##args)
+ btrfs_no_printk(fs_info, KERN_DEBUG fmt, ##args)
#define btrfs_debug_rl_in_rcu(fs_info, fmt, args...) \
- no_printk(KERN_DEBUG fmt, ##args)
+ btrfs_no_printk(fs_info, KERN_DEBUG fmt, ##args)
#define btrfs_debug_rl(fs_info, fmt, args...) \
- no_printk(KERN_DEBUG fmt, ##args)
+ btrfs_no_printk(fs_info, KERN_DEBUG fmt, ##args)
#endif
#define btrfs_printk_in_rcu(fs_info, fmt, args...) \
@@ -3363,7 +3413,7 @@ do { \
__cold
static inline void assfail(char *expr, char *file, int line)
{
- pr_err("BTRFS: assertion failed: %s, file: %s, line: %d",
+ pr_err("assertion failed: %s, file: %s, line: %d\n",
expr, file, line);
BUG();
}
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index 3eeb9cd8cfa5..0fcf5f25d524 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -385,11 +385,8 @@ static struct btrfs_delayed_item *__btrfs_lookup_delayed_insertion_item(
struct btrfs_delayed_node *delayed_node,
struct btrfs_key *key)
{
- struct btrfs_delayed_item *item;
-
- item = __btrfs_lookup_delayed_item(&delayed_node->ins_root, key,
+ return __btrfs_lookup_delayed_item(&delayed_node->ins_root, key,
NULL, NULL);
- return item;
}
static int __btrfs_add_delayed_item(struct btrfs_delayed_node *delayed_node,
@@ -1481,11 +1478,10 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
mutex_lock(&delayed_node->mutex);
ret = __btrfs_add_delayed_insertion_item(delayed_node, delayed_item);
if (unlikely(ret)) {
- btrfs_err(root->fs_info, "err add delayed dir index item(name: %.*s) "
- "into the insertion tree of the delayed node"
- "(root id: %llu, inode id: %llu, errno: %d)",
- name_len, name, delayed_node->root->objectid,
- delayed_node->inode_id, ret);
+ btrfs_err(root->fs_info,
+ "err add delayed dir index item(name: %.*s) into the insertion tree of the delayed node(root id: %llu, inode id: %llu, errno: %d)",
+ name_len, name, delayed_node->root->objectid,
+ delayed_node->inode_id, ret);
BUG();
}
mutex_unlock(&delayed_node->mutex);
@@ -1553,11 +1549,9 @@ int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans,
mutex_lock(&node->mutex);
ret = __btrfs_add_delayed_deletion_item(node, item);
if (unlikely(ret)) {
- btrfs_err(root->fs_info, "err add delayed dir index item(index: %llu) "
- "into the deletion tree of the delayed node"
- "(root id: %llu, inode id: %llu, errno: %d)",
- index, node->root->objectid, node->inode_id,
- ret);
+ btrfs_err(root->fs_info,
+ "err add delayed dir index item(index: %llu) into the deletion tree of the delayed node(root id: %llu, inode id: %llu, errno: %d)",
+ index, node->root->objectid, node->inode_id, ret);
BUG();
}
mutex_unlock(&node->mutex);
@@ -1874,7 +1868,8 @@ int btrfs_delayed_delete_inode_ref(struct inode *inode)
* leads to enospc problems. This means we also can't do
* delayed inode refs
*/
- if (BTRFS_I(inode)->root->fs_info->log_root_recovering)
+ if (test_bit(BTRFS_FS_LOG_RECOVERING,
+ &BTRFS_I(inode)->root->fs_info->flags))
return -EAGAIN;
delayed_node = btrfs_get_or_create_delayed_node(inode);
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
index ac02e041464b..8d93854a4b4f 100644
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -322,10 +322,11 @@ int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info,
elem = list_first_entry(&fs_info->tree_mod_seq_list,
struct seq_list, list);
if (seq >= elem->seq) {
- pr_debug("holding back delayed_ref %#x.%x, lowest is %#x.%x (%p)\n",
- (u32)(seq >> 32), (u32)seq,
- (u32)(elem->seq >> 32), (u32)elem->seq,
- delayed_refs);
+ btrfs_debug(fs_info,
+ "holding back delayed_ref %#x.%x, lowest is %#x.%x (%p)",
+ (u32)(seq >> 32), (u32)seq,
+ (u32)(elem->seq >> 32), (u32)elem->seq,
+ delayed_refs);
ret = 1;
}
}
@@ -770,7 +771,8 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
if (!head_ref)
goto free_ref;
- if (fs_info->quota_enabled && is_fstree(ref_root)) {
+ if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) &&
+ is_fstree(ref_root)) {
record = kmalloc(sizeof(*record), GFP_NOFS);
if (!record)
goto free_head_ref;
@@ -828,7 +830,8 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
return -ENOMEM;
}
- if (fs_info->quota_enabled && is_fstree(ref_root)) {
+ if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) &&
+ is_fstree(ref_root)) {
record = kmalloc(sizeof(*record), GFP_NOFS);
if (!record) {
kmem_cache_free(btrfs_delayed_data_ref_cachep, ref);
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index e9bbff3c0029..05169ef30596 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -218,8 +218,9 @@ int btrfs_run_dev_replace(struct btrfs_trans_handle *trans,
}
ret = btrfs_search_slot(trans, dev_root, &key, path, -1, 1);
if (ret < 0) {
- btrfs_warn(fs_info, "error %d while searching for dev_replace item!",
- ret);
+ btrfs_warn(fs_info,
+ "error %d while searching for dev_replace item!",
+ ret);
goto out;
}
@@ -238,8 +239,9 @@ int btrfs_run_dev_replace(struct btrfs_trans_handle *trans,
*/
ret = btrfs_del_item(trans, dev_root, path);
if (ret != 0) {
- btrfs_warn(fs_info, "delete too small dev_replace item failed %d!",
- ret);
+ btrfs_warn(fs_info,
+ "delete too small dev_replace item failed %d!",
+ ret);
goto out;
}
ret = 1;
@@ -251,8 +253,8 @@ int btrfs_run_dev_replace(struct btrfs_trans_handle *trans,
ret = btrfs_insert_empty_item(trans, dev_root, path,
&key, sizeof(*ptr));
if (ret < 0) {
- btrfs_warn(fs_info, "insert dev_replace item failed %d!",
- ret);
+ btrfs_warn(fs_info,
+ "insert dev_replace item failed %d!", ret);
goto out;
}
}
@@ -383,7 +385,7 @@ int btrfs_dev_replace_start(struct btrfs_root *root, char *tgtdev_name,
ret = btrfs_sysfs_add_device_link(tgt_device->fs_devices, tgt_device);
if (ret)
- btrfs_err(fs_info, "kobj add dev failed %d\n", ret);
+ btrfs_err(fs_info, "kobj add dev failed %d", ret);
btrfs_wait_ordered_roots(root->fs_info, -1, 0, (u64)-1);
@@ -772,9 +774,10 @@ int btrfs_resume_dev_replace_async(struct btrfs_fs_info *fs_info)
break;
}
if (!dev_replace->tgtdev || !dev_replace->tgtdev->bdev) {
- btrfs_info(fs_info, "cannot continue dev_replace, tgtdev is missing");
btrfs_info(fs_info,
- "you may cancel the operation after 'mount -o degraded'");
+ "cannot continue dev_replace, tgtdev is missing");
+ btrfs_info(fs_info,
+ "you may cancel the operation after 'mount -o degraded'");
btrfs_dev_replace_unlock(dev_replace, 1);
return 0;
}
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index 1752625fb4dd..0dc1a033275e 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -472,9 +472,10 @@ int verify_dir_item(struct btrfs_root *root,
/* BTRFS_MAX_XATTR_SIZE is the same for all dir items */
if ((btrfs_dir_data_len(leaf, dir_item) +
btrfs_dir_name_len(leaf, dir_item)) > BTRFS_MAX_XATTR_SIZE(root)) {
- btrfs_crit(root->fs_info, "invalid dir item name + data len: %u + %u",
- (unsigned)btrfs_dir_name_len(leaf, dir_item),
- (unsigned)btrfs_dir_data_len(leaf, dir_item));
+ btrfs_crit(root->fs_info,
+ "invalid dir item name + data len: %u + %u",
+ (unsigned)btrfs_dir_name_len(leaf, dir_item),
+ (unsigned)btrfs_dir_data_len(leaf, dir_item));
return 1;
}
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 54bc8c7c6bcd..3a57f99d96aa 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -326,8 +326,7 @@ static int csum_tree_block(struct btrfs_fs_info *fs_info,
read_extent_buffer(buf, &val, 0, csum_size);
btrfs_warn_rl(fs_info,
- "%s checksum verify failed on %llu wanted %X found %X "
- "level %d",
+ "%s checksum verify failed on %llu wanted %X found %X level %d",
fs_info->sb->s_id, buf->start,
val, found, btrfs_header_level(buf));
if (result != (char *)&inline_result)
@@ -402,7 +401,8 @@ out:
* Return 0 if the superblock checksum type matches the checksum value of that
* algorithm. Pass the raw disk superblock data.
*/
-static int btrfs_check_super_csum(char *raw_disk_sb)
+static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info,
+ char *raw_disk_sb)
{
struct btrfs_super_block *disk_sb =
(struct btrfs_super_block *)raw_disk_sb;
@@ -428,7 +428,7 @@ static int btrfs_check_super_csum(char *raw_disk_sb)
}
if (csum_type >= ARRAY_SIZE(btrfs_csum_sizes)) {
- printk(KERN_ERR "BTRFS: unsupported checksum algorithm %u\n",
+ btrfs_err(fs_info, "unsupported checksum algorithm %u",
csum_type);
ret = 1;
}
@@ -442,7 +442,7 @@ static int btrfs_check_super_csum(char *raw_disk_sb)
*/
static int btree_read_extent_buffer_pages(struct btrfs_root *root,
struct extent_buffer *eb,
- u64 start, u64 parent_transid)
+ u64 parent_transid)
{
struct extent_io_tree *io_tree;
int failed = 0;
@@ -454,8 +454,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree;
while (1) {
- ret = read_extent_buffer_pages(io_tree, eb, start,
- WAIT_COMPLETE,
+ ret = read_extent_buffer_pages(io_tree, eb, WAIT_COMPLETE,
btree_get_extent, mirror_num);
if (!ret) {
if (!verify_parent_transid(io_tree, eb,
@@ -547,9 +546,10 @@ static int check_tree_block_fsid(struct btrfs_fs_info *fs_info,
}
#define CORRUPT(reason, eb, root, slot) \
- btrfs_crit(root->fs_info, "corrupt leaf, %s: block=%llu," \
- "root=%llu, slot=%d", reason, \
- btrfs_header_bytenr(eb), root->objectid, slot)
+ btrfs_crit(root->fs_info, "corrupt %s, %s: block=%llu," \
+ " root=%llu, slot=%d", \
+ btrfs_header_level(eb) == 0 ? "leaf" : "node",\
+ reason, btrfs_header_bytenr(eb), root->objectid, slot)
static noinline int check_leaf(struct btrfs_root *root,
struct extent_buffer *leaf)
@@ -636,6 +636,10 @@ static noinline int check_leaf(struct btrfs_root *root,
static int check_node(struct btrfs_root *root, struct extent_buffer *node)
{
unsigned long nr = btrfs_header_nritems(node);
+ struct btrfs_key key, next_key;
+ int slot;
+ u64 bytenr;
+ int ret = 0;
if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) {
btrfs_crit(root->fs_info,
@@ -643,7 +647,26 @@ static int check_node(struct btrfs_root *root, struct extent_buffer *node)
node->start, root->objectid, nr);
return -EIO;
}
- return 0;
+
+ for (slot = 0; slot < nr - 1; slot++) {
+ bytenr = btrfs_node_blockptr(node, slot);
+ btrfs_node_key_to_cpu(node, &key, slot);
+ btrfs_node_key_to_cpu(node, &next_key, slot + 1);
+
+ if (!bytenr) {
+ CORRUPT("invalid item slot", node, root, slot);
+ ret = -EIO;
+ goto out;
+ }
+
+ if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) {
+ CORRUPT("bad key order", node, root, slot);
+ ret = -EIO;
+ goto out;
+ }
+ }
+out:
+ return ret;
}
static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
@@ -1132,7 +1155,7 @@ void readahead_tree_block(struct btrfs_root *root, u64 bytenr)
if (IS_ERR(buf))
return;
read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree,
- buf, 0, WAIT_NONE, btree_get_extent, 0);
+ buf, WAIT_NONE, btree_get_extent, 0);
free_extent_buffer(buf);
}
@@ -1150,7 +1173,7 @@ int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr,
set_bit(EXTENT_BUFFER_READAHEAD, &buf->bflags);
- ret = read_extent_buffer_pages(io_tree, buf, 0, WAIT_PAGE_LOCK,
+ ret = read_extent_buffer_pages(io_tree, buf, WAIT_PAGE_LOCK,
btree_get_extent, mirror_num);
if (ret) {
free_extent_buffer(buf);
@@ -1206,7 +1229,7 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
if (IS_ERR(buf))
return buf;
- ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
+ ret = btree_read_extent_buffer_pages(root, buf, parent_transid);
if (ret) {
free_extent_buffer(buf);
return ERR_PTR(ret);
@@ -1839,7 +1862,7 @@ static int cleaner_kthread(void *arg)
* Do not do anything if we might cause open_ctree() to block
* before we have finished mounting the filesystem.
*/
- if (!root->fs_info->open)
+ if (!test_bit(BTRFS_FS_OPEN, &root->fs_info->flags))
goto sleep;
if (!mutex_trylock(&root->fs_info->cleaner_mutex))
@@ -2332,8 +2355,6 @@ static void btrfs_init_qgroup(struct btrfs_fs_info *fs_info)
fs_info->qgroup_op_tree = RB_ROOT;
INIT_LIST_HEAD(&fs_info->dirty_qgroups);
fs_info->qgroup_seq = 1;
- fs_info->quota_enabled = 0;
- fs_info->pending_quota_state = 0;
fs_info->qgroup_ulist = NULL;
fs_info->qgroup_rescan_running = false;
mutex_init(&fs_info->qgroup_rescan_lock);
@@ -2518,8 +2539,7 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info,
root = btrfs_read_tree_root(tree_root, &location);
if (!IS_ERR(root)) {
set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
- fs_info->quota_enabled = 1;
- fs_info->pending_quota_state = 1;
+ set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
fs_info->quota_root = root;
}
@@ -2566,6 +2586,7 @@ int open_ctree(struct super_block *sb,
int num_backups_tried = 0;
int backup_index = 0;
int max_active;
+ int clear_free_space_tree = 0;
tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
@@ -2710,8 +2731,7 @@ int open_ctree(struct super_block *sb,
extent_io_tree_init(&fs_info->freed_extents[1],
fs_info->btree_inode->i_mapping);
fs_info->pinned_extents = &fs_info->freed_extents[0];
- fs_info->do_barriers = 1;
-
+ set_bit(BTRFS_FS_BARRIER, &fs_info->flags);
mutex_init(&fs_info->ordered_operations_mutex);
mutex_init(&fs_info->tree_log_mutex);
@@ -2762,7 +2782,7 @@ int open_ctree(struct super_block *sb,
* We want to check superblock checksum, the type is stored inside.
* Pass the whole disk block of size BTRFS_SUPER_INFO_SIZE (4k).
*/
- if (btrfs_check_super_csum(bh->b_data)) {
+ if (btrfs_check_super_csum(fs_info, bh->b_data)) {
btrfs_err(fs_info, "superblock checksum mismatch");
err = -EINVAL;
brelse(bh);
@@ -3129,6 +3149,26 @@ retry_root_backup:
if (sb->s_flags & MS_RDONLY)
return 0;
+ if (btrfs_test_opt(fs_info, CLEAR_CACHE) &&
+ btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
+ clear_free_space_tree = 1;
+ } else if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
+ !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID)) {
+ btrfs_warn(fs_info, "free space tree is invalid");
+ clear_free_space_tree = 1;
+ }
+
+ if (clear_free_space_tree) {
+ btrfs_info(fs_info, "clearing free space tree");
+ ret = btrfs_clear_free_space_tree(fs_info);
+ if (ret) {
+ btrfs_warn(fs_info,
+ "failed to clear free space tree: %d", ret);
+ close_ctree(tree_root);
+ return ret;
+ }
+ }
+
if (btrfs_test_opt(tree_root->fs_info, FREE_SPACE_TREE) &&
!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
btrfs_info(fs_info, "creating free space tree");
@@ -3166,18 +3206,6 @@ retry_root_backup:
btrfs_qgroup_rescan_resume(fs_info);
- if (btrfs_test_opt(tree_root->fs_info, CLEAR_CACHE) &&
- btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
- btrfs_info(fs_info, "clearing free space tree");
- ret = btrfs_clear_free_space_tree(fs_info);
- if (ret) {
- btrfs_warn(fs_info,
- "failed to clear free space tree: %d", ret);
- close_ctree(tree_root);
- return ret;
- }
- }
-
if (!fs_info->uuid_root) {
btrfs_info(fs_info, "creating UUID tree");
ret = btrfs_create_uuid_tree(fs_info);
@@ -3199,10 +3227,9 @@ retry_root_backup:
return ret;
}
} else {
- fs_info->update_uuid_tree_gen = 1;
+ set_bit(BTRFS_FS_UPDATE_UUID_TREE_GEN, &fs_info->flags);
}
-
- fs_info->open = 1;
+ set_bit(BTRFS_FS_OPEN, &fs_info->flags);
/*
* backuproot only affect mount behavior, and if open_ctree succeeded,
@@ -3607,7 +3634,7 @@ int btrfs_get_num_tolerated_disk_barrier_failures(u64 flags)
}
if (min_tolerated == INT_MAX) {
- pr_warn("BTRFS: unknown raid flag: %llu\n", flags);
+ pr_warn("BTRFS: unknown raid flag: %llu", flags);
min_tolerated = 0;
}
@@ -3893,8 +3920,7 @@ void close_ctree(struct btrfs_root *root)
struct btrfs_fs_info *fs_info = root->fs_info;
int ret;
- fs_info->closing = 1;
- smp_mb();
+ set_bit(BTRFS_FS_CLOSING_START, &fs_info->flags);
/* wait for the qgroup rescan worker to stop */
btrfs_qgroup_wait_for_completion(fs_info, false);
@@ -3939,8 +3965,7 @@ void close_ctree(struct btrfs_root *root)
kthread_stop(fs_info->transaction_kthread);
kthread_stop(fs_info->cleaner_kthread);
- fs_info->closing = 2;
- smp_mb();
+ set_bit(BTRFS_FS_CLOSING_DONE, &fs_info->flags);
btrfs_free_qgroup_config(fs_info);
@@ -3965,7 +3990,7 @@ void close_ctree(struct btrfs_root *root)
invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
btrfs_stop_all_workers(fs_info);
- fs_info->open = 0;
+ clear_bit(BTRFS_FS_OPEN, &fs_info->flags);
free_root_pointers(fs_info, 1);
iput(fs_info->btree_inode);
@@ -4036,8 +4061,7 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
root = BTRFS_I(buf->pages[0]->mapping->host)->root;
btrfs_assert_tree_locked(buf);
if (transid != root->fs_info->generation)
- WARN(1, KERN_CRIT "btrfs transid mismatch buffer %llu, "
- "found %llu running %llu\n",
+ WARN(1, KERN_CRIT "btrfs transid mismatch buffer %llu, found %llu running %llu\n",
buf->start, transid, root->fs_info->generation);
was_dirty = set_extent_buffer_dirty(buf);
if (!was_dirty)
@@ -4088,7 +4112,7 @@ void btrfs_btree_balance_dirty_nodelay(struct btrfs_root *root)
int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid)
{
struct btrfs_root *root = BTRFS_I(buf->pages[0]->mapping->host)->root;
- return btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
+ return btree_read_extent_buffer_pages(root, buf, parent_transid);
}
static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
@@ -4100,24 +4124,24 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
int ret = 0;
if (btrfs_super_magic(sb) != BTRFS_MAGIC) {
- printk(KERN_ERR "BTRFS: no valid FS found\n");
+ btrfs_err(fs_info, "no valid FS found");
ret = -EINVAL;
}
if (btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP)
- printk(KERN_WARNING "BTRFS: unrecognized super flag: %llu\n",
+ btrfs_warn(fs_info, "unrecognized super flag: %llu",
btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP);
if (btrfs_super_root_level(sb) >= BTRFS_MAX_LEVEL) {
- printk(KERN_ERR "BTRFS: tree_root level too big: %d >= %d\n",
+ btrfs_err(fs_info, "tree_root level too big: %d >= %d",
btrfs_super_root_level(sb), BTRFS_MAX_LEVEL);
ret = -EINVAL;
}
if (btrfs_super_chunk_root_level(sb) >= BTRFS_MAX_LEVEL) {
- printk(KERN_ERR "BTRFS: chunk_root level too big: %d >= %d\n",
+ btrfs_err(fs_info, "chunk_root level too big: %d >= %d",
btrfs_super_chunk_root_level(sb), BTRFS_MAX_LEVEL);
ret = -EINVAL;
}
if (btrfs_super_log_root_level(sb) >= BTRFS_MAX_LEVEL) {
- printk(KERN_ERR "BTRFS: log_root level too big: %d >= %d\n",
+ btrfs_err(fs_info, "log_root level too big: %d >= %d",
btrfs_super_log_root_level(sb), BTRFS_MAX_LEVEL);
ret = -EINVAL;
}
@@ -4128,47 +4152,48 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
*/
if (!is_power_of_2(sectorsize) || sectorsize < 4096 ||
sectorsize > BTRFS_MAX_METADATA_BLOCKSIZE) {
- printk(KERN_ERR "BTRFS: invalid sectorsize %llu\n", sectorsize);
+ btrfs_err(fs_info, "invalid sectorsize %llu", sectorsize);
ret = -EINVAL;
}
/* Only PAGE SIZE is supported yet */
if (sectorsize != PAGE_SIZE) {
- printk(KERN_ERR "BTRFS: sectorsize %llu not supported yet, only support %lu\n",
- sectorsize, PAGE_SIZE);
+ btrfs_err(fs_info,
+ "sectorsize %llu not supported yet, only support %lu",
+ sectorsize, PAGE_SIZE);
ret = -EINVAL;
}
if (!is_power_of_2(nodesize) || nodesize < sectorsize ||
nodesize > BTRFS_MAX_METADATA_BLOCKSIZE) {
- printk(KERN_ERR "BTRFS: invalid nodesize %llu\n", nodesize);
+ btrfs_err(fs_info, "invalid nodesize %llu", nodesize);
ret = -EINVAL;
}
if (nodesize != le32_to_cpu(sb->__unused_leafsize)) {
- printk(KERN_ERR "BTRFS: invalid leafsize %u, should be %llu\n",
- le32_to_cpu(sb->__unused_leafsize),
- nodesize);
+ btrfs_err(fs_info, "invalid leafsize %u, should be %llu",
+ le32_to_cpu(sb->__unused_leafsize), nodesize);
ret = -EINVAL;
}
/* Root alignment check */
if (!IS_ALIGNED(btrfs_super_root(sb), sectorsize)) {
- printk(KERN_WARNING "BTRFS: tree_root block unaligned: %llu\n",
- btrfs_super_root(sb));
+ btrfs_warn(fs_info, "tree_root block unaligned: %llu",
+ btrfs_super_root(sb));
ret = -EINVAL;
}
if (!IS_ALIGNED(btrfs_super_chunk_root(sb), sectorsize)) {
- printk(KERN_WARNING "BTRFS: chunk_root block unaligned: %llu\n",
- btrfs_super_chunk_root(sb));
+ btrfs_warn(fs_info, "chunk_root block unaligned: %llu",
+ btrfs_super_chunk_root(sb));
ret = -EINVAL;
}
if (!IS_ALIGNED(btrfs_super_log_root(sb), sectorsize)) {
- printk(KERN_WARNING "BTRFS: log_root block unaligned: %llu\n",
- btrfs_super_log_root(sb));
+ btrfs_warn(fs_info, "log_root block unaligned: %llu",
+ btrfs_super_log_root(sb));
ret = -EINVAL;
}
if (memcmp(fs_info->fsid, sb->dev_item.fsid, BTRFS_UUID_SIZE) != 0) {
- printk(KERN_ERR "BTRFS: dev_item UUID does not match fsid: %pU != %pU\n",
- fs_info->fsid, sb->dev_item.fsid);
+ btrfs_err(fs_info,
+ "dev_item UUID does not match fsid: %pU != %pU",
+ fs_info->fsid, sb->dev_item.fsid);
ret = -EINVAL;
}
@@ -4178,25 +4203,25 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
*/
if (btrfs_super_bytes_used(sb) < 6 * btrfs_super_nodesize(sb)) {
btrfs_err(fs_info, "bytes_used is too small %llu",
- btrfs_super_bytes_used(sb));
+ btrfs_super_bytes_used(sb));
ret = -EINVAL;
}
if (!is_power_of_2(btrfs_super_stripesize(sb))) {
btrfs_err(fs_info, "invalid stripesize %u",
- btrfs_super_stripesize(sb));
+ btrfs_super_stripesize(sb));
ret = -EINVAL;
}
if (btrfs_super_num_devices(sb) > (1UL << 31))
- printk(KERN_WARNING "BTRFS: suspicious number of devices: %llu\n",
- btrfs_super_num_devices(sb));
+ btrfs_warn(fs_info, "suspicious number of devices: %llu",
+ btrfs_super_num_devices(sb));
if (btrfs_super_num_devices(sb) == 0) {
- printk(KERN_ERR "BTRFS: number of devices is 0\n");
+ btrfs_err(fs_info, "number of devices is 0");
ret = -EINVAL;
}
if (btrfs_super_bytenr(sb) != BTRFS_SUPER_INFO_OFFSET) {
- printk(KERN_ERR "BTRFS: super offset mismatch %llu != %u\n",
- btrfs_super_bytenr(sb), BTRFS_SUPER_INFO_OFFSET);
+ btrfs_err(fs_info, "super offset mismatch %llu != %u",
+ btrfs_super_bytenr(sb), BTRFS_SUPER_INFO_OFFSET);
ret = -EINVAL;
}
@@ -4205,17 +4230,17 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
* and one chunk
*/
if (btrfs_super_sys_array_size(sb) > BTRFS_SYSTEM_CHUNK_ARRAY_SIZE) {
- printk(KERN_ERR "BTRFS: system chunk array too big %u > %u\n",
- btrfs_super_sys_array_size(sb),
- BTRFS_SYSTEM_CHUNK_ARRAY_SIZE);
+ btrfs_err(fs_info, "system chunk array too big %u > %u",
+ btrfs_super_sys_array_size(sb),
+ BTRFS_SYSTEM_CHUNK_ARRAY_SIZE);
ret = -EINVAL;
}
if (btrfs_super_sys_array_size(sb) < sizeof(struct btrfs_disk_key)
+ sizeof(struct btrfs_chunk)) {
- printk(KERN_ERR "BTRFS: system chunk array too small %u < %zu\n",
- btrfs_super_sys_array_size(sb),
- sizeof(struct btrfs_disk_key)
- + sizeof(struct btrfs_chunk));
+ btrfs_err(fs_info, "system chunk array too small %u < %zu",
+ btrfs_super_sys_array_size(sb),
+ sizeof(struct btrfs_disk_key)
+ + sizeof(struct btrfs_chunk));
ret = -EINVAL;
}
@@ -4224,14 +4249,16 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
* but it's still possible that it's the one that's wrong.
*/
if (btrfs_super_generation(sb) < btrfs_super_chunk_root_generation(sb))
- printk(KERN_WARNING
- "BTRFS: suspicious: generation < chunk_root_generation: %llu < %llu\n",
- btrfs_super_generation(sb), btrfs_super_chunk_root_generation(sb));
+ btrfs_warn(fs_info,
+ "suspicious: generation < chunk_root_generation: %llu < %llu",
+ btrfs_super_generation(sb),
+ btrfs_super_chunk_root_generation(sb));
if (btrfs_super_generation(sb) < btrfs_super_cache_generation(sb)
&& btrfs_super_cache_generation(sb) != (u64)-1)
- printk(KERN_WARNING
- "BTRFS: suspicious: generation < cache_generation: %llu < %llu\n",
- btrfs_super_generation(sb), btrfs_super_cache_generation(sb));
+ btrfs_warn(fs_info,
+ "suspicious: generation < cache_generation: %llu < %llu",
+ btrfs_super_generation(sb),
+ btrfs_super_cache_generation(sb));
return ret;
}
@@ -4475,9 +4502,80 @@ again:
return 0;
}
+static void btrfs_cleanup_bg_io(struct btrfs_block_group_cache *cache)
+{
+ struct inode *inode;
+
+ inode = cache->io_ctl.inode;
+ if (inode) {
+ invalidate_inode_pages2(inode->i_mapping);
+ BTRFS_I(inode)->generation = 0;
+ cache->io_ctl.inode = NULL;
+ iput(inode);
+ }
+ btrfs_put_block_group(cache);
+}
+
+void btrfs_cleanup_dirty_bgs(struct btrfs_transaction *cur_trans,
+ struct btrfs_root *root)
+{
+ struct btrfs_block_group_cache *cache;
+
+ spin_lock(&cur_trans->dirty_bgs_lock);
+ while (!list_empty(&cur_trans->dirty_bgs)) {
+ cache = list_first_entry(&cur_trans->dirty_bgs,
+ struct btrfs_block_group_cache,
+ dirty_list);
+ if (!cache) {
+ btrfs_err(root->fs_info,
+ "orphan block group dirty_bgs list");
+ spin_unlock(&cur_trans->dirty_bgs_lock);
+ return;
+ }
+
+ if (!list_empty(&cache->io_list)) {
+ spin_unlock(&cur_trans->dirty_bgs_lock);
+ list_del_init(&cache->io_list);
+ btrfs_cleanup_bg_io(cache);
+ spin_lock(&cur_trans->dirty_bgs_lock);
+ }
+
+ list_del_init(&cache->dirty_list);
+ spin_lock(&cache->lock);
+ cache->disk_cache_state = BTRFS_DC_ERROR;
+ spin_unlock(&cache->lock);
+
+ spin_unlock(&cur_trans->dirty_bgs_lock);
+ btrfs_put_block_group(cache);
+ spin_lock(&cur_trans->dirty_bgs_lock);
+ }
+ spin_unlock(&cur_trans->dirty_bgs_lock);
+
+ while (!list_empty(&cur_trans->io_bgs)) {
+ cache = list_first_entry(&cur_trans->io_bgs,
+ struct btrfs_block_group_cache,
+ io_list);
+ if (!cache) {
+ btrfs_err(root->fs_info,
+ "orphan block group on io_bgs list");
+ return;
+ }
+
+ list_del_init(&cache->io_list);
+ spin_lock(&cache->lock);
+ cache->disk_cache_state = BTRFS_DC_ERROR;
+ spin_unlock(&cache->lock);
+ btrfs_cleanup_bg_io(cache);
+ }
+}
+
void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
struct btrfs_root *root)
{
+ btrfs_cleanup_dirty_bgs(cur_trans, root);
+ ASSERT(list_empty(&cur_trans->dirty_bgs));
+ ASSERT(list_empty(&cur_trans->io_bgs));
+
btrfs_destroy_delayed_refs(cur_trans, root);
cur_trans->state = TRANS_STATE_COMMIT_START;
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index f19a982f5a4f..1a3237e5700f 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -136,6 +136,8 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info);
int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
struct btrfs_root *root);
+void btrfs_cleanup_dirty_bgs(struct btrfs_transaction *trans,
+ struct btrfs_root *root);
void btrfs_cleanup_one_transaction(struct btrfs_transaction *trans,
struct btrfs_root *root);
struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 665da8f66ff1..210c94ac8818 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -87,7 +87,8 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
int force);
static int find_next_key(struct btrfs_path *path, int level,
struct btrfs_key *key);
-static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
+static void dump_space_info(struct btrfs_fs_info *fs_info,
+ struct btrfs_space_info *info, u64 bytes,
int dump_block_groups);
static int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache,
u64 ram_bytes, u64 num_bytes, int delalloc);
@@ -266,9 +267,8 @@ static int exclude_super_stripes(struct btrfs_root *root,
for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
bytenr = btrfs_sb_offset(i);
- ret = btrfs_rmap_block(&root->fs_info->mapping_tree,
- cache->key.objectid, bytenr,
- 0, &logical, &nr, &stripe_len);
+ ret = btrfs_rmap_block(root->fs_info, cache->key.objectid,
+ bytenr, 0, &logical, &nr, &stripe_len);
if (ret)
return ret;
@@ -730,11 +730,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
static struct btrfs_block_group_cache *
btrfs_lookup_first_block_group(struct btrfs_fs_info *info, u64 bytenr)
{
- struct btrfs_block_group_cache *cache;
-
- cache = block_group_cache_tree_search(info, bytenr, 0);
-
- return cache;
+ return block_group_cache_tree_search(info, bytenr, 0);
}
/*
@@ -744,11 +740,7 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(
struct btrfs_fs_info *info,
u64 bytenr)
{
- struct btrfs_block_group_cache *cache;
-
- cache = block_group_cache_tree_search(info, bytenr, 1);
-
- return cache;
+ return block_group_cache_tree_search(info, bytenr, 1);
}
static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
@@ -2360,7 +2352,13 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
ins.type = BTRFS_EXTENT_ITEM_KEY;
}
- BUG_ON(node->ref_mod != 1);
+ if (node->ref_mod != 1) {
+ btrfs_err(root->fs_info,
+ "btree block(%llu) has %d references rather than 1: action %d ref_root %llu parent %llu",
+ node->bytenr, node->ref_mod, node->action, ref_root,
+ parent);
+ return -EIO;
+ }
if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
BUG_ON(!extent_op || !extent_op->update_flags);
ret = alloc_reserved_tree_block(trans, root,
@@ -2590,7 +2588,9 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
if (must_insert_reserved)
locked_ref->must_insert_reserved = 1;
locked_ref->processing = 0;
- btrfs_debug(fs_info, "run_delayed_extent_op returned %d", ret);
+ btrfs_debug(fs_info,
+ "run_delayed_extent_op returned %d",
+ ret);
btrfs_delayed_ref_unlock(locked_ref);
return ret;
}
@@ -2650,7 +2650,8 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
locked_ref->processing = 0;
btrfs_delayed_ref_unlock(locked_ref);
btrfs_put_delayed_ref(ref);
- btrfs_debug(fs_info, "run_one_delayed_ref returned %d", ret);
+ btrfs_debug(fs_info, "run_one_delayed_ref returned %d",
+ ret);
return ret;
}
@@ -2940,7 +2941,7 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
if (trans->aborted)
return 0;
- if (root->fs_info->creating_free_space_tree)
+ if (test_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &root->fs_info->flags))
return 0;
if (root == root->fs_info->extent_root)
@@ -2971,7 +2972,6 @@ again:
spin_unlock(&delayed_refs->lock);
goto out;
}
- count = (unsigned long)-1;
while (node) {
head = rb_entry(node, struct btrfs_delayed_ref_head,
@@ -3694,6 +3694,8 @@ again:
goto again;
}
spin_unlock(&cur_trans->dirty_bgs_lock);
+ } else if (ret < 0) {
+ btrfs_cleanup_dirty_bgs(cur_trans, root);
}
btrfs_free_path(path);
@@ -4429,7 +4431,7 @@ void check_system_chunk(struct btrfs_trans_handle *trans,
if (left < thresh && btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) {
btrfs_info(root->fs_info, "left=%llu, need=%llu, flags=%llu",
left, thresh, type);
- dump_space_info(info, 0, 0);
+ dump_space_info(root->fs_info, info, 0, 0);
}
if (left < thresh) {
@@ -5186,7 +5188,7 @@ static int __reserve_metadata_bytes(struct btrfs_root *root,
* which means we won't have fs_info->fs_root set, so don't do
* the async reclaim as we will panic.
*/
- if (!root->fs_info->log_root_recovering &&
+ if (!test_bit(BTRFS_FS_LOG_RECOVERING, &root->fs_info->flags) &&
need_do_async_reclaim(space_info, root, used) &&
!work_busy(&root->fs_info->async_reclaim_work)) {
trace_btrfs_trigger_flush(root->fs_info,
@@ -5792,7 +5794,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
int ret;
struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv;
- if (root->fs_info->quota_enabled) {
+ if (test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags)) {
/* One for parent inode, two for dir entries */
num_bytes = 3 * root->nodesize;
ret = btrfs_qgroup_reserve_meta(root, num_bytes);
@@ -5970,7 +5972,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
csum_bytes = BTRFS_I(inode)->csum_bytes;
spin_unlock(&BTRFS_I(inode)->lock);
- if (root->fs_info->quota_enabled) {
+ if (test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags)) {
ret = btrfs_qgroup_reserve_meta(root,
nr_extents * root->nodesize);
if (ret)
@@ -6110,8 +6112,6 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
* @start: start range we are writing to
* @len: how long the range we are writing to
*
- * TODO: This function will finally replace old btrfs_delalloc_reserve_space()
- *
* This will do the following things
*
* o reserve space in data space info for num bytes
@@ -6930,8 +6930,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
}
if (ret) {
- btrfs_err(info, "umm, got %d back from search, was looking for %llu",
- ret, bytenr);
+ btrfs_err(info,
+ "umm, got %d back from search, was looking for %llu",
+ ret, bytenr);
if (ret > 0)
btrfs_print_leaf(extent_root,
path->nodes[0]);
@@ -6977,7 +6978,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
ret = btrfs_search_slot(trans, extent_root, &key, path,
-1, 1);
if (ret) {
- btrfs_err(info, "umm, got %d back from search, was looking for %llu",
+ btrfs_err(info,
+ "umm, got %d back from search, was looking for %llu",
ret, bytenr);
btrfs_print_leaf(extent_root, path->nodes[0]);
}
@@ -7004,8 +7006,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
refs = btrfs_extent_refs(leaf, ei);
if (refs < refs_to_drop) {
- btrfs_err(info, "trying to drop %d refs but we only have %Lu "
- "for bytenr %Lu", refs_to_drop, refs, bytenr);
+ btrfs_err(info,
+ "trying to drop %d refs but we only have %Lu for bytenr %Lu",
+ refs_to_drop, refs, bytenr);
ret = -EINVAL;
btrfs_abort_transaction(trans, ret);
goto out;
@@ -7901,23 +7904,24 @@ out:
return ret;
}
-static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
+static void dump_space_info(struct btrfs_fs_info *fs_info,
+ struct btrfs_space_info *info, u64 bytes,
int dump_block_groups)
{
struct btrfs_block_group_cache *cache;
int index = 0;
spin_lock(&info->lock);
- printk(KERN_INFO "BTRFS: space_info %llu has %llu free, is %sfull\n",
- info->flags,
- info->total_bytes - info->bytes_used - info->bytes_pinned -
- info->bytes_reserved - info->bytes_readonly -
- info->bytes_may_use, (info->full) ? "" : "not ");
- printk(KERN_INFO "BTRFS: space_info total=%llu, used=%llu, pinned=%llu, "
- "reserved=%llu, may_use=%llu, readonly=%llu\n",
- info->total_bytes, info->bytes_used, info->bytes_pinned,
- info->bytes_reserved, info->bytes_may_use,
- info->bytes_readonly);
+ btrfs_info(fs_info, "space_info %llu has %llu free, is %sfull",
+ info->flags,
+ info->total_bytes - info->bytes_used - info->bytes_pinned -
+ info->bytes_reserved - info->bytes_readonly -
+ info->bytes_may_use, (info->full) ? "" : "not ");
+ btrfs_info(fs_info,
+ "space_info total=%llu, used=%llu, pinned=%llu, reserved=%llu, may_use=%llu, readonly=%llu",
+ info->total_bytes, info->bytes_used, info->bytes_pinned,
+ info->bytes_reserved, info->bytes_may_use,
+ info->bytes_readonly);
spin_unlock(&info->lock);
if (!dump_block_groups)
@@ -7927,12 +7931,11 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
again:
list_for_each_entry(cache, &info->block_groups[index], list) {
spin_lock(&cache->lock);
- printk(KERN_INFO "BTRFS: "
- "block group %llu has %llu bytes, "
- "%llu used %llu pinned %llu reserved %s\n",
- cache->key.objectid, cache->key.offset,
- btrfs_block_group_used(&cache->item), cache->pinned,
- cache->reserved, cache->ro ? "[readonly]" : "");
+ btrfs_info(fs_info,
+ "block group %llu has %llu bytes, %llu used %llu pinned %llu reserved %s",
+ cache->key.objectid, cache->key.offset,
+ btrfs_block_group_used(&cache->item), cache->pinned,
+ cache->reserved, cache->ro ? "[readonly]" : "");
btrfs_dump_free_space(cache, bytes);
spin_unlock(&cache->lock);
}
@@ -7946,6 +7949,7 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes,
u64 empty_size, u64 hint_byte,
struct btrfs_key *ins, int is_data, int delalloc)
{
+ struct btrfs_fs_info *fs_info = root->fs_info;
bool final_tried = num_bytes == min_alloc_size;
u64 flags;
int ret;
@@ -7956,8 +7960,7 @@ again:
ret = find_free_extent(root, ram_bytes, num_bytes, empty_size,
hint_byte, ins, flags, delalloc);
if (!ret && !is_data) {
- btrfs_dec_block_group_reservations(root->fs_info,
- ins->objectid);
+ btrfs_dec_block_group_reservations(fs_info, ins->objectid);
} else if (ret == -ENOSPC) {
if (!final_tried && ins->offset) {
num_bytes = min(num_bytes >> 1, ins->offset);
@@ -7967,14 +7970,15 @@ again:
if (num_bytes == min_alloc_size)
final_tried = true;
goto again;
- } else if (btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) {
+ } else if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) {
struct btrfs_space_info *sinfo;
- sinfo = __find_space_info(root->fs_info, flags);
- btrfs_err(root->fs_info, "allocation failed flags %llu, wanted %llu",
- flags, num_bytes);
+ sinfo = __find_space_info(fs_info, flags);
+ btrfs_err(root->fs_info,
+ "allocation failed flags %llu, wanted %llu",
+ flags, num_bytes);
if (sinfo)
- dump_space_info(sinfo, num_bytes, 1);
+ dump_space_info(fs_info, sinfo, num_bytes, 1);
}
}
@@ -8462,7 +8466,6 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
u64 refs;
u64 flags;
u32 nritems;
- u32 blocksize;
struct btrfs_key key;
struct extent_buffer *eb;
int ret;
@@ -8480,7 +8483,6 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
eb = path->nodes[wc->level];
nritems = btrfs_header_nritems(eb);
- blocksize = root->nodesize;
for (slot = path->slots[wc->level]; slot < nritems; slot++) {
if (nread >= wc->reada_count)
@@ -8544,7 +8546,7 @@ static int account_leaf_items(struct btrfs_trans_handle *trans,
u64 bytenr, num_bytes;
/* We can be called directly from walk_up_proc() */
- if (!root->fs_info->quota_enabled)
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags))
return 0;
for (i = 0; i < nr; i++) {
@@ -8653,7 +8655,7 @@ static int account_shared_subtree(struct btrfs_trans_handle *trans,
BUG_ON(root_level < 0 || root_level > BTRFS_MAX_LEVEL);
BUG_ON(root_eb == NULL);
- if (!root->fs_info->quota_enabled)
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags))
return 0;
if (!extent_buffer_uptodate(root_eb)) {
@@ -8884,14 +8886,13 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
ret = btrfs_lookup_extent_info(trans, root, bytenr, level - 1, 1,
&wc->refs[level - 1],
&wc->flags[level - 1]);
- if (ret < 0) {
- btrfs_tree_unlock(next);
- return ret;
- }
+ if (ret < 0)
+ goto out_unlock;
if (unlikely(wc->refs[level - 1] == 0)) {
btrfs_err(root->fs_info, "Missing references.");
- BUG();
+ ret = -EIO;
+ goto out_unlock;
}
*lookup_info = 0;
@@ -8943,7 +8944,12 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
}
level--;
- BUG_ON(level != btrfs_header_level(next));
+ ASSERT(level == btrfs_header_level(next));
+ if (level != btrfs_header_level(next)) {
+ btrfs_err(root->fs_info, "mismatched level");
+ ret = -EIO;
+ goto out_unlock;
+ }
path->nodes[level] = next;
path->slots[level] = 0;
path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
@@ -8958,8 +8964,15 @@ skip:
if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
parent = path->nodes[level]->start;
} else {
- BUG_ON(root->root_key.objectid !=
+ ASSERT(root->root_key.objectid ==
btrfs_header_owner(path->nodes[level]));
+ if (root->root_key.objectid !=
+ btrfs_header_owner(path->nodes[level])) {
+ btrfs_err(root->fs_info,
+ "mismatched block owner");
+ ret = -EIO;
+ goto out_unlock;
+ }
parent = 0;
}
@@ -8968,20 +8981,24 @@ skip:
generation, level - 1);
if (ret) {
btrfs_err_rl(root->fs_info,
- "Error "
- "%d accounting shared subtree. Quota "
- "is out of sync, rescan required.",
- ret);
+ "Error %d accounting shared subtree. Quota is out of sync, rescan required.",
+ ret);
}
}
ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent,
root->root_key.objectid, level - 1, 0);
- BUG_ON(ret); /* -ENOMEM */
+ if (ret)
+ goto out_unlock;
}
+
+ *lookup_info = 1;
+ ret = 1;
+
+out_unlock:
btrfs_tree_unlock(next);
free_extent_buffer(next);
- *lookup_info = 1;
- return 1;
+
+ return ret;
}
/*
@@ -9061,10 +9078,8 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
ret = account_leaf_items(trans, root, eb);
if (ret) {
btrfs_err_rl(root->fs_info,
- "error "
- "%d accounting leaf items. Quota "
- "is out of sync, rescan required.",
- ret);
+ "error %d accounting leaf items. Quota is out of sync, rescan required.",
+ ret);
}
}
/* make block locked assertion in clean_tree_block happy */
@@ -9180,9 +9195,10 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
struct btrfs_block_rsv *block_rsv, int update_ref,
int for_reloc)
{
+ struct btrfs_fs_info *fs_info = root->fs_info;
struct btrfs_path *path;
struct btrfs_trans_handle *trans;
- struct btrfs_root *tree_root = root->fs_info->tree_root;
+ struct btrfs_root *tree_root = fs_info->tree_root;
struct btrfs_root_item *root_item = &root->root_item;
struct walk_control *wc;
struct btrfs_key key;
@@ -9191,7 +9207,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
int level;
bool root_dropped = false;
- btrfs_debug(root->fs_info, "Drop subvolume %llu", root->objectid);
+ btrfs_debug(fs_info, "Drop subvolume %llu", root->objectid);
path = btrfs_alloc_path();
if (!path) {
@@ -9320,7 +9336,8 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
btrfs_end_transaction_throttle(trans, tree_root);
if (!for_reloc && btrfs_need_cleaner_sleep(root)) {
- pr_debug("BTRFS: drop snapshot early exit\n");
+ btrfs_debug(fs_info,
+ "drop snapshot early exit");
err = -EAGAIN;
goto out_free;
}
@@ -9386,7 +9403,7 @@ out:
if (!for_reloc && root_dropped == false)
btrfs_add_dead_root(root);
if (err && err != -EAGAIN)
- btrfs_handle_fs_error(root->fs_info, err, NULL);
+ btrfs_handle_fs_error(fs_info, err, NULL);
return err;
}
@@ -10020,7 +10037,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
if (WARN_ON(space_info->bytes_pinned > 0 ||
space_info->bytes_reserved > 0 ||
space_info->bytes_may_use > 0))
- dump_space_info(space_info, 0, 0);
+ dump_space_info(info, space_info, 0, 0);
list_del(&space_info->list);
for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) {
struct kobject *kobj;
@@ -10069,7 +10086,8 @@ static void __link_block_group(struct btrfs_space_info *space_info,
return;
out_err:
- pr_warn("BTRFS: failed to add kobject for block cache. ignoring.\n");
+ btrfs_warn(cache->fs_info,
+ "failed to add kobject for block cache, ignoring");
}
static struct btrfs_block_group_cache *
@@ -10127,6 +10145,11 @@ int btrfs_read_block_groups(struct btrfs_root *root)
struct extent_buffer *leaf;
int need_clear = 0;
u64 cache_gen;
+ u64 feature;
+ int mixed;
+
+ feature = btrfs_super_incompat_flags(info->super_copy);
+ mixed = !!(feature & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS);
root = info->extent_root;
key.objectid = 0;
@@ -10180,6 +10203,15 @@ int btrfs_read_block_groups(struct btrfs_root *root)
btrfs_item_ptr_offset(leaf, path->slots[0]),
sizeof(cache->item));
cache->flags = btrfs_block_group_flags(&cache->item);
+ if (!mixed &&
+ ((cache->flags & BTRFS_BLOCK_GROUP_METADATA) &&
+ (cache->flags & BTRFS_BLOCK_GROUP_DATA))) {
+ btrfs_err(info,
+"bg %llu is a mixed block group but filesystem hasn't enabled mixed block groups",
+ cache->key.objectid);
+ ret = -EINVAL;
+ goto error;
+ }
key.objectid = found_key.objectid + found_key.offset;
btrfs_release_path(path);
@@ -10789,7 +10821,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
struct btrfs_trans_handle *trans;
int ret = 0;
- if (!fs_info->open)
+ if (!test_bit(BTRFS_FS_OPEN, &fs_info->flags))
return;
spin_lock(&fs_info->unused_bgs_lock);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 44fe66b53c8b..66a755150056 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -20,6 +20,7 @@
#include "locking.h"
#include "rcu-string.h"
#include "backref.h"
+#include "transaction.h"
static struct kmem_cache *extent_state_cache;
static struct kmem_cache *extent_buffer_cache;
@@ -74,8 +75,7 @@ void btrfs_leak_debug_check(void)
while (!list_empty(&buffers)) {
eb = list_entry(buffers.next, struct extent_buffer, leak_list);
- printk(KERN_ERR "BTRFS: buffer leak start %llu len %lu "
- "refs %d\n",
+ pr_err("BTRFS: buffer leak start %llu len %lu refs %d\n",
eb->start, eb->len, atomic_read(&eb->refs));
list_del(&eb->leak_list);
kmem_cache_free(extent_buffer_cache, eb);
@@ -460,8 +460,7 @@ static int insert_state(struct extent_io_tree *tree,
if (node) {
struct extent_state *found;
found = rb_entry(node, struct extent_state, rb_node);
- printk(KERN_ERR "BTRFS: found node %llu %llu on insert of "
- "%llu %llu\n",
+ pr_err("BTRFS: found node %llu %llu on insert of %llu %llu\n",
found->start, found->end, start, end);
return -EEXIST;
}
@@ -572,9 +571,8 @@ alloc_extent_state_atomic(struct extent_state *prealloc)
static void extent_io_tree_panic(struct extent_io_tree *tree, int err)
{
- btrfs_panic(tree_fs_info(tree), err, "Locking error: "
- "Extent tree was modified by another "
- "thread while locked.");
+ btrfs_panic(tree_fs_info(tree), err,
+ "Locking error: Extent tree was modified by another thread while locked.");
}
/*
@@ -1729,7 +1727,7 @@ out_failed:
}
void extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
- struct page *locked_page,
+ u64 delalloc_end, struct page *locked_page,
unsigned clear_bits,
unsigned long page_ops)
{
@@ -2122,8 +2120,9 @@ int clean_io_failure(struct inode *inode, u64 start, struct page *page,
if (failrec->in_validation) {
/* there was no real error, just free the record */
- pr_debug("clean_io_failure: freeing dummy error at %llu\n",
- failrec->start);
+ btrfs_debug(fs_info,
+ "clean_io_failure: freeing dummy error at %llu",
+ failrec->start);
goto out;
}
if (fs_info->sb->s_flags & MS_RDONLY)
@@ -2189,6 +2188,7 @@ void btrfs_free_io_failure_record(struct inode *inode, u64 start, u64 end)
int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
struct io_failure_record **failrec_ret)
{
+ struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
struct io_failure_record *failrec;
struct extent_map *em;
struct extent_io_tree *failure_tree = &BTRFS_I(inode)->io_failure_tree;
@@ -2236,8 +2236,9 @@ int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
em->compress_type);
}
- pr_debug("Get IO Failure Record: (new) logical=%llu, start=%llu, len=%llu\n",
- logical, start, failrec->len);
+ btrfs_debug(fs_info,
+ "Get IO Failure Record: (new) logical=%llu, start=%llu, len=%llu",
+ logical, start, failrec->len);
failrec->logical = logical;
free_extent_map(em);
@@ -2255,9 +2256,10 @@ int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
return ret;
}
} else {
- pr_debug("Get IO Failure Record: (found) logical=%llu, start=%llu, len=%llu, validation=%d\n",
- failrec->logical, failrec->start, failrec->len,
- failrec->in_validation);
+ btrfs_debug(fs_info,
+ "Get IO Failure Record: (found) logical=%llu, start=%llu, len=%llu, validation=%d",
+ failrec->logical, failrec->start, failrec->len,
+ failrec->in_validation);
/*
* when data can be on disk more than twice, add to failrec here
* (e.g. with a list for failed_mirror) to make
@@ -2273,18 +2275,19 @@ int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
int btrfs_check_repairable(struct inode *inode, struct bio *failed_bio,
struct io_failure_record *failrec, int failed_mirror)
{
+ struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
int num_copies;
- num_copies = btrfs_num_copies(BTRFS_I(inode)->root->fs_info,
- failrec->logical, failrec->len);
+ num_copies = btrfs_num_copies(fs_info, failrec->logical, failrec->len);
if (num_copies == 1) {
/*
* we only have a single copy of the data, so don't bother with
* all the retry and error correction code that follows. no
* matter what the error is, it is very likely to persist.
*/
- pr_debug("Check Repairable: cannot repair, num_copies=%d, next_mirror %d, failed_mirror %d\n",
- num_copies, failrec->this_mirror, failed_mirror);
+ btrfs_debug(fs_info,
+ "Check Repairable: cannot repair, num_copies=%d, next_mirror %d, failed_mirror %d",
+ num_copies, failrec->this_mirror, failed_mirror);
return 0;
}
@@ -2323,8 +2326,9 @@ int btrfs_check_repairable(struct inode *inode, struct bio *failed_bio,
}
if (failrec->this_mirror > num_copies) {
- pr_debug("Check Repairable: (fail) num_copies=%d, next_mirror %d, failed_mirror %d\n",
- num_copies, failrec->this_mirror, failed_mirror);
+ btrfs_debug(fs_info,
+ "Check Repairable: (fail) num_copies=%d, next_mirror %d, failed_mirror %d",
+ num_copies, failrec->this_mirror, failed_mirror);
return 0;
}
@@ -2415,8 +2419,9 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset,
}
bio_set_op_attrs(bio, REQ_OP_READ, read_mode);
- pr_debug("Repair Read Error: submitting new read[%#x] to this_mirror=%d, in_validation=%d\n",
- read_mode, failrec->this_mirror, failrec->in_validation);
+ btrfs_debug(btrfs_sb(inode->i_sb),
+ "Repair Read Error: submitting new read[%#x] to this_mirror=%d, in_validation=%d",
+ read_mode, failrec->this_mirror, failrec->in_validation);
ret = tree->ops->submit_bio_hook(inode, bio, failrec->this_mirror,
failrec->bio_flags, 0);
@@ -2484,8 +2489,7 @@ static void end_bio_extent_writepage(struct bio *bio)
bvec->bv_offset, bvec->bv_len);
else
btrfs_info(BTRFS_I(page->mapping->host)->root->fs_info,
- "incomplete page write in btrfs with offset %u and "
- "length %u",
+ "incomplete page write in btrfs with offset %u and length %u",
bvec->bv_offset, bvec->bv_len);
}
@@ -2541,10 +2545,12 @@ static void end_bio_extent_readpage(struct bio *bio)
bio_for_each_segment_all(bvec, bio, i) {
struct page *page = bvec->bv_page;
struct inode *inode = page->mapping->host;
+ struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
- pr_debug("end_bio_extent_readpage: bi_sector=%llu, err=%d, "
- "mirror=%u\n", (u64)bio->bi_iter.bi_sector,
- bio->bi_error, io_bio->mirror_num);
+ btrfs_debug(fs_info,
+ "end_bio_extent_readpage: bi_sector=%llu, err=%d, mirror=%u",
+ (u64)bio->bi_iter.bi_sector, bio->bi_error,
+ io_bio->mirror_num);
tree = &BTRFS_I(inode)->io_tree;
/* We always issue full-page reads, but if some block
@@ -2554,13 +2560,12 @@ static void end_bio_extent_readpage(struct bio *bio)
* if they don't add up to a full page. */
if (bvec->bv_offset || bvec->bv_len != PAGE_SIZE) {
if (bvec->bv_offset + bvec->bv_len != PAGE_SIZE)
- btrfs_err(BTRFS_I(page->mapping->host)->root->fs_info,
- "partial page read in btrfs with offset %u and length %u",
+ btrfs_err(fs_info,
+ "partial page read in btrfs with offset %u and length %u",
bvec->bv_offset, bvec->bv_len);
else
- btrfs_info(BTRFS_I(page->mapping->host)->root->fs_info,
- "incomplete page read in btrfs with offset %u and "
- "length %u",
+ btrfs_info(fs_info,
+ "incomplete page read in btrfs with offset %u and length %u",
bvec->bv_offset, bvec->bv_len);
}
@@ -3624,7 +3629,6 @@ static void end_extent_buffer_writeback(struct extent_buffer *eb)
static void set_btree_ioerr(struct page *page)
{
struct extent_buffer *eb = (struct extent_buffer *)page->private;
- struct btrfs_inode *btree_ino = BTRFS_I(eb->fs_info->btree_inode);
SetPageError(page);
if (test_and_set_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags))
@@ -3670,13 +3674,13 @@ static void set_btree_ioerr(struct page *page)
*/
switch (eb->log_index) {
case -1:
- set_bit(BTRFS_INODE_BTREE_ERR, &btree_ino->runtime_flags);
+ set_bit(BTRFS_FS_BTREE_ERR, &eb->fs_info->flags);
break;
case 0:
- set_bit(BTRFS_INODE_BTREE_LOG1_ERR, &btree_ino->runtime_flags);
+ set_bit(BTRFS_FS_LOG1_ERR, &eb->fs_info->flags);
break;
case 1:
- set_bit(BTRFS_INODE_BTREE_LOG2_ERR, &btree_ino->runtime_flags);
+ set_bit(BTRFS_FS_LOG2_ERR, &eb->fs_info->flags);
break;
default:
BUG(); /* unexpected, logic error */
@@ -3721,8 +3725,10 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
struct block_device *bdev = fs_info->fs_devices->latest_bdev;
struct extent_io_tree *tree = &BTRFS_I(fs_info->btree_inode)->io_tree;
u64 offset = eb->start;
+ u32 nritems;
unsigned long i, num_pages;
unsigned long bio_flags = 0;
+ unsigned long start, end;
int write_flags = (epd->sync_io ? WRITE_SYNC : 0) | REQ_META;
int ret = 0;
@@ -3732,6 +3738,23 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
if (btrfs_header_owner(eb) == BTRFS_TREE_LOG_OBJECTID)
bio_flags = EXTENT_BIO_TREE_LOG;
+ /* set btree blocks beyond nritems with 0 to avoid stale content. */
+ nritems = btrfs_header_nritems(eb);
+ if (btrfs_header_level(eb) > 0) {
+ end = btrfs_node_key_ptr_offset(nritems);
+
+ memset_extent_buffer(eb, 0, end, eb->len - end);
+ } else {
+ /*
+ * leaf:
+ * header 0 1 2 .. N ... data_N .. data_2 data_1 data_0
+ */
+ start = btrfs_item_nr_offset(nritems);
+ end = btrfs_leaf_data(eb) +
+ leaf_data_end(fs_info->tree_root, eb);
+ memset_extent_buffer(eb, 0, start, end - start);
+ }
+
for (i = 0; i < num_pages; i++) {
struct page *p = eb->pages[i];
@@ -4487,21 +4510,36 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
flags |= (FIEMAP_EXTENT_DELALLOC |
FIEMAP_EXTENT_UNKNOWN);
} else if (fieinfo->fi_extents_max) {
+ struct btrfs_trans_handle *trans;
+
u64 bytenr = em->block_start -
(em->start - em->orig_start);
disko = em->block_start + offset_in_extent;
/*
+ * We need a trans handle to get delayed refs
+ */
+ trans = btrfs_join_transaction(root);
+ /*
+ * It's OK if we can't start a trans we can still check
+ * from commit_root
+ */
+ if (IS_ERR(trans))
+ trans = NULL;
+
+ /*
* As btrfs supports shared space, this information
* can be exported to userspace tools via
* flag FIEMAP_EXTENT_SHARED. If fi_extents_max == 0
* then we're just getting a count and we can skip the
* lookup stuff.
*/
- ret = btrfs_check_shared(NULL, root->fs_info,
+ ret = btrfs_check_shared(trans, root->fs_info,
root->objectid,
btrfs_ino(inode), bytenr);
+ if (trans)
+ btrfs_end_transaction(trans, root);
if (ret < 0)
goto out_free;
if (ret)
@@ -5173,11 +5211,10 @@ int extent_buffer_uptodate(struct extent_buffer *eb)
}
int read_extent_buffer_pages(struct extent_io_tree *tree,
- struct extent_buffer *eb, u64 start, int wait,
+ struct extent_buffer *eb, int wait,
get_extent_t *get_extent, int mirror_num)
{
unsigned long i;
- unsigned long start_i;
struct page *page;
int err;
int ret = 0;
@@ -5191,16 +5228,8 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
return 0;
- if (start) {
- WARN_ON(start < eb->start);
- start_i = (start >> PAGE_SHIFT) -
- (eb->start >> PAGE_SHIFT);
- } else {
- start_i = 0;
- }
-
num_pages = num_extent_pages(eb->start, eb->len);
- for (i = start_i; i < num_pages; i++) {
+ for (i = 0; i < num_pages; i++) {
page = eb->pages[i];
if (wait == WAIT_NONE) {
if (!trylock_page(page))
@@ -5209,21 +5238,29 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
lock_page(page);
}
locked_pages++;
+ }
+ /*
+ * We need to firstly lock all pages to make sure that
+ * the uptodate bit of our pages won't be affected by
+ * clear_extent_buffer_uptodate().
+ */
+ for (i = 0; i < num_pages; i++) {
+ page = eb->pages[i];
if (!PageUptodate(page)) {
num_reads++;
all_uptodate = 0;
}
}
+
if (all_uptodate) {
- if (start_i == 0)
- set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
+ set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
goto unlock_exit;
}
clear_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags);
eb->read_mirror = 0;
atomic_set(&eb->io_pages, num_reads);
- for (i = start_i; i < num_pages; i++) {
+ for (i = 0; i < num_pages; i++) {
page = eb->pages[i];
if (!PageUptodate(page)) {
@@ -5264,7 +5301,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
if (ret || wait != WAIT_COMPLETE)
return ret;
- for (i = start_i; i < num_pages; i++) {
+ for (i = 0; i < num_pages; i++) {
page = eb->pages[i];
wait_on_page_locked(page);
if (!PageUptodate(page))
@@ -5274,12 +5311,10 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
return ret;
unlock_exit:
- i = start_i;
while (locked_pages > 0) {
- page = eb->pages[i];
- i++;
- unlock_page(page);
locked_pages--;
+ page = eb->pages[locked_pages];
+ unlock_page(page);
}
return ret;
}
@@ -5382,8 +5417,7 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
}
if (start + min_len > eb->len) {
- WARN(1, KERN_ERR "btrfs bad mapping eb start %llu len %lu, "
- "wanted %lu %lu\n",
+ WARN(1, KERN_ERR "btrfs bad mapping eb start %llu len %lu, wanted %lu %lu\n",
eb->start, eb->len, start, min_len);
return -EINVAL;
}
@@ -5524,17 +5558,45 @@ void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
}
}
-/*
- * The extent buffer bitmap operations are done with byte granularity because
- * bitmap items are not guaranteed to be aligned to a word and therefore a
- * single word in a bitmap may straddle two pages in the extent buffer.
- */
-#define BIT_BYTE(nr) ((nr) / BITS_PER_BYTE)
-#define BYTE_MASK ((1 << BITS_PER_BYTE) - 1)
-#define BITMAP_FIRST_BYTE_MASK(start) \
- ((BYTE_MASK << ((start) & (BITS_PER_BYTE - 1))) & BYTE_MASK)
-#define BITMAP_LAST_BYTE_MASK(nbits) \
- (BYTE_MASK >> (-(nbits) & (BITS_PER_BYTE - 1)))
+void le_bitmap_set(u8 *map, unsigned int start, int len)
+{
+ u8 *p = map + BIT_BYTE(start);
+ const unsigned int size = start + len;
+ int bits_to_set = BITS_PER_BYTE - (start % BITS_PER_BYTE);
+ u8 mask_to_set = BITMAP_FIRST_BYTE_MASK(start);
+
+ while (len - bits_to_set >= 0) {
+ *p |= mask_to_set;
+ len -= bits_to_set;
+ bits_to_set = BITS_PER_BYTE;
+ mask_to_set = ~(u8)0;
+ p++;
+ }
+ if (len) {
+ mask_to_set &= BITMAP_LAST_BYTE_MASK(size);
+ *p |= mask_to_set;
+ }
+}
+
+void le_bitmap_clear(u8 *map, unsigned int start, int len)
+{
+ u8 *p = map + BIT_BYTE(start);
+ const unsigned int size = start + len;
+ int bits_to_clear = BITS_PER_BYTE - (start % BITS_PER_BYTE);
+ u8 mask_to_clear = BITMAP_FIRST_BYTE_MASK(start);
+
+ while (len - bits_to_clear >= 0) {
+ *p &= ~mask_to_clear;
+ len -= bits_to_clear;
+ bits_to_clear = BITS_PER_BYTE;
+ mask_to_clear = ~(u8)0;
+ p++;
+ }
+ if (len) {
+ mask_to_clear &= BITMAP_LAST_BYTE_MASK(size);
+ *p &= ~mask_to_clear;
+ }
+}
/*
* eb_bitmap_offset() - calculate the page and offset of the byte containing the
@@ -5578,7 +5640,7 @@ static inline void eb_bitmap_offset(struct extent_buffer *eb,
int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start,
unsigned long nr)
{
- char *kaddr;
+ u8 *kaddr;
struct page *page;
unsigned long i;
size_t offset;
@@ -5600,13 +5662,13 @@ int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start,
void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start,
unsigned long pos, unsigned long len)
{
- char *kaddr;
+ u8 *kaddr;
struct page *page;
unsigned long i;
size_t offset;
const unsigned int size = pos + len;
int bits_to_set = BITS_PER_BYTE - (pos % BITS_PER_BYTE);
- unsigned int mask_to_set = BITMAP_FIRST_BYTE_MASK(pos);
+ u8 mask_to_set = BITMAP_FIRST_BYTE_MASK(pos);
eb_bitmap_offset(eb, start, pos, &i, &offset);
page = eb->pages[i];
@@ -5617,7 +5679,7 @@ void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start,
kaddr[offset] |= mask_to_set;
len -= bits_to_set;
bits_to_set = BITS_PER_BYTE;
- mask_to_set = ~0U;
+ mask_to_set = ~(u8)0;
if (++offset >= PAGE_SIZE && len > 0) {
offset = 0;
page = eb->pages[++i];
@@ -5642,13 +5704,13 @@ void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start,
void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start,
unsigned long pos, unsigned long len)
{
- char *kaddr;
+ u8 *kaddr;
struct page *page;
unsigned long i;
size_t offset;
const unsigned int size = pos + len;
int bits_to_clear = BITS_PER_BYTE - (pos % BITS_PER_BYTE);
- unsigned int mask_to_clear = BITMAP_FIRST_BYTE_MASK(pos);
+ u8 mask_to_clear = BITMAP_FIRST_BYTE_MASK(pos);
eb_bitmap_offset(eb, start, pos, &i, &offset);
page = eb->pages[i];
@@ -5659,7 +5721,7 @@ void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start,
kaddr[offset] &= ~mask_to_clear;
len -= bits_to_clear;
bits_to_clear = BITS_PER_BYTE;
- mask_to_clear = ~0U;
+ mask_to_clear = ~(u8)0;
if (++offset >= PAGE_SIZE && len > 0) {
offset = 0;
page = eb->pages[++i];
@@ -5713,14 +5775,14 @@ void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
if (src_offset + len > dst->len) {
btrfs_err(dst->fs_info,
- "memmove bogus src_offset %lu move "
- "len %lu dst len %lu", src_offset, len, dst->len);
+ "memmove bogus src_offset %lu move len %lu dst len %lu",
+ src_offset, len, dst->len);
BUG_ON(1);
}
if (dst_offset + len > dst->len) {
btrfs_err(dst->fs_info,
- "memmove bogus dst_offset %lu move "
- "len %lu dst len %lu", dst_offset, len, dst->len);
+ "memmove bogus dst_offset %lu move len %lu dst len %lu",
+ dst_offset, len, dst->len);
BUG_ON(1);
}
@@ -5760,13 +5822,15 @@ void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
unsigned long src_i;
if (src_offset + len > dst->len) {
- btrfs_err(dst->fs_info, "memmove bogus src_offset %lu move "
- "len %lu len %lu", src_offset, len, dst->len);
+ btrfs_err(dst->fs_info,
+ "memmove bogus src_offset %lu move len %lu len %lu",
+ src_offset, len, dst->len);
BUG_ON(1);
}
if (dst_offset + len > dst->len) {
- btrfs_err(dst->fs_info, "memmove bogus dst_offset %lu move "
- "len %lu len %lu", dst_offset, len, dst->len);
+ btrfs_err(dst->fs_info,
+ "memmove bogus dst_offset %lu move len %lu len %lu",
+ dst_offset, len, dst->len);
BUG_ON(1);
}
if (dst_offset < src_offset) {
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 28cd88fccc7e..ab31d145227e 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -59,6 +59,28 @@
*/
#define EXTENT_PAGE_PRIVATE 1
+/*
+ * The extent buffer bitmap operations are done with byte granularity instead of
+ * word granularity for two reasons:
+ * 1. The bitmaps must be little-endian on disk.
+ * 2. Bitmap items are not guaranteed to be aligned to a word and therefore a
+ * single word in a bitmap may straddle two pages in the extent buffer.
+ */
+#define BIT_BYTE(nr) ((nr) / BITS_PER_BYTE)
+#define BYTE_MASK ((1 << BITS_PER_BYTE) - 1)
+#define BITMAP_FIRST_BYTE_MASK(start) \
+ ((BYTE_MASK << ((start) & (BITS_PER_BYTE - 1))) & BYTE_MASK)
+#define BITMAP_LAST_BYTE_MASK(nbits) \
+ (BYTE_MASK >> (-(nbits) & (BITS_PER_BYTE - 1)))
+
+static inline int le_test_bit(int nr, const u8 *addr)
+{
+ return 1U & (addr[BIT_BYTE(nr)] >> (nr & (BITS_PER_BYTE-1)));
+}
+
+extern void le_bitmap_set(u8 *map, unsigned int start, int len);
+extern void le_bitmap_clear(u8 *map, unsigned int start, int len);
+
struct extent_state;
struct btrfs_root;
struct btrfs_io_bio;
@@ -359,7 +381,7 @@ void free_extent_buffer_stale(struct extent_buffer *eb);
#define WAIT_COMPLETE 1
#define WAIT_PAGE_LOCK 2
int read_extent_buffer_pages(struct extent_io_tree *tree,
- struct extent_buffer *eb, u64 start, int wait,
+ struct extent_buffer *eb, int wait,
get_extent_t *get_extent, int mirror_num);
void wait_on_extent_buffer_writeback(struct extent_buffer *eb);
@@ -413,7 +435,7 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset,
void extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end);
void extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end);
void extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
- struct page *locked_page,
+ u64 delalloc_end, struct page *locked_page,
unsigned bits_to_clear,
unsigned long page_ops);
struct bio *
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index fea31a4a6e36..3a14c87d9c92 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -503,7 +503,7 @@ int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
end_of_last_block = start_pos + num_bytes - 1;
err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block,
- cached);
+ cached, 0);
if (err)
return err;
@@ -1110,13 +1110,25 @@ again:
leaf = path->nodes[0];
btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
- BUG_ON(key.objectid != ino || key.type != BTRFS_EXTENT_DATA_KEY);
+ if (key.objectid != ino ||
+ key.type != BTRFS_EXTENT_DATA_KEY) {
+ ret = -EINVAL;
+ btrfs_abort_transaction(trans, ret);
+ goto out;
+ }
fi = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_file_extent_item);
- BUG_ON(btrfs_file_extent_type(leaf, fi) !=
- BTRFS_FILE_EXTENT_PREALLOC);
+ if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_PREALLOC) {
+ ret = -EINVAL;
+ btrfs_abort_transaction(trans, ret);
+ goto out;
+ }
extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi);
- BUG_ON(key.offset > start || extent_end < end);
+ if (key.offset > start || extent_end < end) {
+ ret = -EINVAL;
+ btrfs_abort_transaction(trans, ret);
+ goto out;
+ }
bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi);
@@ -1213,12 +1225,19 @@ again:
ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
root->root_key.objectid,
ino, orig_offset);
- BUG_ON(ret); /* -ENOMEM */
+ if (ret) {
+ btrfs_abort_transaction(trans, ret);
+ goto out;
+ }
if (split == start) {
key.offset = start;
} else {
- BUG_ON(start != key.offset);
+ if (start != key.offset) {
+ ret = -EINVAL;
+ btrfs_abort_transaction(trans, ret);
+ goto out;
+ }
path->slots[0]--;
extent_end = end;
}
@@ -1240,7 +1259,10 @@ again:
ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
0, root->root_key.objectid,
ino, orig_offset);
- BUG_ON(ret); /* -ENOMEM */
+ if (ret) {
+ btrfs_abort_transaction(trans, ret);
+ goto out;
+ }
}
other_start = 0;
other_end = start;
@@ -1257,7 +1279,10 @@ again:
ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
0, root->root_key.objectid,
ino, orig_offset);
- BUG_ON(ret); /* -ENOMEM */
+ if (ret) {
+ btrfs_abort_transaction(trans, ret);
+ goto out;
+ }
}
if (del_nr == 0) {
fi = btrfs_item_ptr(leaf, path->slots[0],
@@ -1757,7 +1782,7 @@ static void update_time_for_write(struct inode *inode)
if (IS_NOCMTIME(inode))
return;
- now = current_fs_time(inode->i_sb);
+ now = current_time(inode);
if (!timespec_equal(&inode->i_mtime, &now))
inode->i_mtime = now;
@@ -2040,7 +2065,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
* flags for any errors that might have happened while doing
* writeback of file data.
*/
- ret = btrfs_inode_check_errors(inode);
+ ret = filemap_check_errors(inode->i_mapping);
inode_unlock(inode);
goto out;
}
@@ -2578,7 +2603,7 @@ out_trans:
goto out_free;
inode_inc_iversion(inode);
- inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_mtime = inode->i_ctime = current_time(inode);
trans->block_rsv = &root->fs_info->trans_block_rsv;
ret = btrfs_update_inode(trans, root, inode);
@@ -2842,7 +2867,7 @@ static long btrfs_fallocate(struct file *file, int mode,
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
} else {
- inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_ctime = current_time(inode);
i_size_write(inode, actual_end);
btrfs_ordered_update_i_size(inode, actual_end, NULL);
ret = btrfs_update_inode(trans, root, inode);
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index d571bd2b697b..e4b48f377d3a 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -716,8 +716,7 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
if (BTRFS_I(inode)->generation != generation) {
btrfs_err(root->fs_info,
- "free space inode generation (%llu) "
- "did not match free space cache generation (%llu)",
+ "free space inode generation (%llu) did not match free space cache generation (%llu)",
BTRFS_I(inode)->generation, generation);
return 0;
}
@@ -879,8 +878,9 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
if (!matched) {
__btrfs_remove_free_space_cache(ctl);
- btrfs_warn(fs_info, "block group %llu has wrong amount of free space",
- block_group->key.objectid);
+ btrfs_warn(fs_info,
+ "block group %llu has wrong amount of free space",
+ block_group->key.objectid);
ret = -1;
}
out:
@@ -891,8 +891,9 @@ out:
spin_unlock(&block_group->lock);
ret = 0;
- btrfs_warn(fs_info, "failed to load free space cache for block group %llu, rebuilding it now",
- block_group->key.objectid);
+ btrfs_warn(fs_info,
+ "failed to load free space cache for block group %llu, rebuilding it now",
+ block_group->key.objectid);
}
iput(inode);
@@ -2298,7 +2299,8 @@ static void steal_from_bitmap(struct btrfs_free_space_ctl *ctl,
}
}
-int __btrfs_add_free_space(struct btrfs_free_space_ctl *ctl,
+int __btrfs_add_free_space(struct btrfs_fs_info *fs_info,
+ struct btrfs_free_space_ctl *ctl,
u64 offset, u64 bytes)
{
struct btrfs_free_space *info;
@@ -2345,7 +2347,7 @@ out:
spin_unlock(&ctl->tree_lock);
if (ret) {
- printk(KERN_CRIT "BTRFS: unable to add free space :%d\n", ret);
+ btrfs_crit(fs_info, "unable to add free space :%d", ret);
ASSERT(ret != -EEXIST);
}
@@ -2621,7 +2623,8 @@ out:
spin_unlock(&ctl->tree_lock);
if (align_gap_len)
- __btrfs_add_free_space(ctl, align_gap, align_gap_len);
+ __btrfs_add_free_space(block_group->fs_info, ctl,
+ align_gap, align_gap_len);
return ret;
}
diff --git a/fs/btrfs/free-space-cache.h b/fs/btrfs/free-space-cache.h
index 3af651c2bbc7..363fdd955e5d 100644
--- a/fs/btrfs/free-space-cache.h
+++ b/fs/btrfs/free-space-cache.h
@@ -89,13 +89,15 @@ int btrfs_write_out_ino_cache(struct btrfs_root *root,
struct inode *inode);
void btrfs_init_free_space_ctl(struct btrfs_block_group_cache *block_group);
-int __btrfs_add_free_space(struct btrfs_free_space_ctl *ctl,
+int __btrfs_add_free_space(struct btrfs_fs_info *fs_info,
+ struct btrfs_free_space_ctl *ctl,
u64 bytenr, u64 size);
static inline int
btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
u64 bytenr, u64 size)
{
- return __btrfs_add_free_space(block_group->free_space_ctl,
+ return __btrfs_add_free_space(block_group->fs_info,
+ block_group->free_space_ctl,
bytenr, size);
}
int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c
index 87e7e3d3e676..57401b474ec6 100644
--- a/fs/btrfs/free-space-tree.c
+++ b/fs/btrfs/free-space-tree.c
@@ -107,7 +107,7 @@ search_free_space_info(struct btrfs_trans_handle *trans,
if (ret < 0)
return ERR_PTR(ret);
if (ret != 0) {
- btrfs_warn(fs_info, "missing free space info for %llu\n",
+ btrfs_warn(fs_info, "missing free space info for %llu",
block_group->key.objectid);
ASSERT(0);
return ERR_PTR(-ENOENT);
@@ -151,7 +151,7 @@ static inline u32 free_space_bitmap_size(u64 size, u32 sectorsize)
return DIV_ROUND_UP((u32)div_u64(size, sectorsize), BITS_PER_BYTE);
}
-static unsigned long *alloc_bitmap(u32 bitmap_size)
+static u8 *alloc_bitmap(u32 bitmap_size)
{
void *mem;
@@ -180,8 +180,7 @@ int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
struct btrfs_free_space_info *info;
struct btrfs_key key, found_key;
struct extent_buffer *leaf;
- unsigned long *bitmap;
- char *bitmap_cursor;
+ u8 *bitmap, *bitmap_cursor;
u64 start, end;
u64 bitmap_range, i;
u32 bitmap_size, flags, expected_extent_count;
@@ -231,7 +230,7 @@ int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
block_group->sectorsize);
last = div_u64(found_key.objectid + found_key.offset - start,
block_group->sectorsize);
- bitmap_set(bitmap, first, last - first);
+ le_bitmap_set(bitmap, first, last - first);
extent_count++;
nr++;
@@ -261,7 +260,8 @@ int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
btrfs_release_path(path);
if (extent_count != expected_extent_count) {
- btrfs_err(fs_info, "incorrect extent count for %llu; counted %u, expected %u",
+ btrfs_err(fs_info,
+ "incorrect extent count for %llu; counted %u, expected %u",
block_group->key.objectid, extent_count,
expected_extent_count);
ASSERT(0);
@@ -269,7 +269,7 @@ int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
goto out;
}
- bitmap_cursor = (char *)bitmap;
+ bitmap_cursor = bitmap;
bitmap_range = block_group->sectorsize * BTRFS_FREE_SPACE_BITMAP_BITS;
i = start;
while (i < end) {
@@ -318,7 +318,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
struct btrfs_free_space_info *info;
struct btrfs_key key, found_key;
struct extent_buffer *leaf;
- unsigned long *bitmap;
+ u8 *bitmap;
u64 start, end;
/* Initialize to silence GCC. */
u64 extent_start = 0;
@@ -362,7 +362,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
break;
} else if (found_key.type == BTRFS_FREE_SPACE_BITMAP_KEY) {
unsigned long ptr;
- char *bitmap_cursor;
+ u8 *bitmap_cursor;
u32 bitmap_pos, data_size;
ASSERT(found_key.objectid >= start);
@@ -372,7 +372,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
bitmap_pos = div_u64(found_key.objectid - start,
block_group->sectorsize *
BITS_PER_BYTE);
- bitmap_cursor = ((char *)bitmap) + bitmap_pos;
+ bitmap_cursor = bitmap + bitmap_pos;
data_size = free_space_bitmap_size(found_key.offset,
block_group->sectorsize);
@@ -409,7 +409,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
offset = start;
bitnr = 0;
while (offset < end) {
- bit = !!test_bit(bitnr, bitmap);
+ bit = !!le_test_bit(bitnr, bitmap);
if (prev_bit == 0 && bit == 1) {
extent_start = offset;
} else if (prev_bit == 1 && bit == 0) {
@@ -442,7 +442,8 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
}
if (extent_count != expected_extent_count) {
- btrfs_err(fs_info, "incorrect extent count for %llu; counted %u, expected %u",
+ btrfs_err(fs_info,
+ "incorrect extent count for %llu; counted %u, expected %u",
block_group->key.objectid, extent_count,
expected_extent_count);
ASSERT(0);
@@ -1163,7 +1164,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
if (IS_ERR(trans))
return PTR_ERR(trans);
- fs_info->creating_free_space_tree = 1;
+ set_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags);
free_space_root = btrfs_create_tree(trans, fs_info,
BTRFS_FREE_SPACE_TREE_OBJECTID);
if (IS_ERR(free_space_root)) {
@@ -1183,7 +1184,8 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
}
btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE);
- fs_info->creating_free_space_tree = 0;
+ btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID);
+ clear_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags);
ret = btrfs_commit_transaction(trans, tree_root);
if (ret)
@@ -1192,7 +1194,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
return 0;
abort:
- fs_info->creating_free_space_tree = 0;
+ clear_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags);
btrfs_abort_transaction(trans, ret);
btrfs_end_transaction(trans, tree_root);
return ret;
@@ -1251,6 +1253,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
return PTR_ERR(trans);
btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE);
+ btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID);
fs_info->free_space_root = NULL;
ret = clear_free_space_tree(trans, free_space_root);
@@ -1480,7 +1483,8 @@ static int load_free_space_bitmaps(struct btrfs_caching_control *caching_ctl,
}
if (extent_count != expected_extent_count) {
- btrfs_err(fs_info, "incorrect extent count for %llu; counted %u, expected %u",
+ btrfs_err(fs_info,
+ "incorrect extent count for %llu; counted %u, expected %u",
block_group->key.objectid, extent_count,
expected_extent_count);
ASSERT(0);
@@ -1542,7 +1546,8 @@ static int load_free_space_extents(struct btrfs_caching_control *caching_ctl,
}
if (extent_count != expected_extent_count) {
- btrfs_err(fs_info, "incorrect extent count for %llu; counted %u, expected %u",
+ btrfs_err(fs_info,
+ "incorrect extent count for %llu; counted %u, expected %u",
block_group->key.objectid, extent_count,
expected_extent_count);
ASSERT(0);
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c
index 359ee861b5a4..d27014b8bf72 100644
--- a/fs/btrfs/inode-map.c
+++ b/fs/btrfs/inode-map.c
@@ -104,7 +104,7 @@ again:
break;
if (last != (u64)-1 && last + 1 != key.objectid) {
- __btrfs_add_free_space(ctl, last + 1,
+ __btrfs_add_free_space(fs_info, ctl, last + 1,
key.objectid - last - 1);
wake_up(&root->ino_cache_wait);
}
@@ -115,7 +115,7 @@ next:
}
if (last < root->highest_objectid - 1) {
- __btrfs_add_free_space(ctl, last + 1,
+ __btrfs_add_free_space(fs_info, ctl, last + 1,
root->highest_objectid - last - 1);
}
@@ -136,12 +136,13 @@ out:
static void start_caching(struct btrfs_root *root)
{
+ struct btrfs_fs_info *fs_info = root->fs_info;
struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
struct task_struct *tsk;
int ret;
u64 objectid;
- if (!btrfs_test_opt(root->fs_info, INODE_MAP_CACHE))
+ if (!btrfs_test_opt(fs_info, INODE_MAP_CACHE))
return;
spin_lock(&root->ino_cache_lock);
@@ -153,7 +154,7 @@ static void start_caching(struct btrfs_root *root)
root->ino_cache_state = BTRFS_CACHE_STARTED;
spin_unlock(&root->ino_cache_lock);
- ret = load_free_ino_cache(root->fs_info, root);
+ ret = load_free_ino_cache(fs_info, root);
if (ret == 1) {
spin_lock(&root->ino_cache_lock);
root->ino_cache_state = BTRFS_CACHE_FINISHED;
@@ -170,15 +171,15 @@ static void start_caching(struct btrfs_root *root)
*/
ret = btrfs_find_free_objectid(root, &objectid);
if (!ret && objectid <= BTRFS_LAST_FREE_OBJECTID) {
- __btrfs_add_free_space(ctl, objectid,
+ __btrfs_add_free_space(fs_info, ctl, objectid,
BTRFS_LAST_FREE_OBJECTID - objectid + 1);
}
tsk = kthread_run(caching_kthread, root, "btrfs-ino-cache-%llu",
root->root_key.objectid);
if (IS_ERR(tsk)) {
- btrfs_warn(root->fs_info, "failed to start inode caching task");
- btrfs_clear_pending_and_info(root->fs_info, INODE_MAP_CACHE,
+ btrfs_warn(fs_info, "failed to start inode caching task");
+ btrfs_clear_pending_and_info(fs_info, INODE_MAP_CACHE,
"disabling inode map caching");
}
}
@@ -209,28 +210,29 @@ again:
void btrfs_return_ino(struct btrfs_root *root, u64 objectid)
{
+ struct btrfs_fs_info *fs_info = root->fs_info;
struct btrfs_free_space_ctl *pinned = root->free_ino_pinned;
- if (!btrfs_test_opt(root->fs_info, INODE_MAP_CACHE))
+ if (!btrfs_test_opt(fs_info, INODE_MAP_CACHE))
return;
again:
if (root->ino_cache_state == BTRFS_CACHE_FINISHED) {
- __btrfs_add_free_space(pinned, objectid, 1);
+ __btrfs_add_free_space(fs_info, pinned, objectid, 1);
} else {
- down_write(&root->fs_info->commit_root_sem);
+ down_write(&fs_info->commit_root_sem);
spin_lock(&root->ino_cache_lock);
if (root->ino_cache_state == BTRFS_CACHE_FINISHED) {
spin_unlock(&root->ino_cache_lock);
- up_write(&root->fs_info->commit_root_sem);
+ up_write(&fs_info->commit_root_sem);
goto again;
}
spin_unlock(&root->ino_cache_lock);
start_caching(root);
- __btrfs_add_free_space(pinned, objectid, 1);
+ __btrfs_add_free_space(fs_info, pinned, objectid, 1);
- up_write(&root->fs_info->commit_root_sem);
+ up_write(&fs_info->commit_root_sem);
}
}
@@ -277,7 +279,8 @@ void btrfs_unpin_free_ino(struct btrfs_root *root)
rb_erase(&info->offset_index, rbroot);
spin_unlock(rbroot_lock);
if (add_to_ctl)
- __btrfs_add_free_space(ctl, info->offset, count);
+ __btrfs_add_free_space(root->fs_info, ctl,
+ info->offset, count);
kmem_cache_free(btrfs_free_space_cachep, info);
}
}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index e6811c42e41e..2b790bda7998 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -560,8 +560,9 @@ cont:
* we don't need to create any more async work items.
* Unlock and free up our temp pages.
*/
- extent_clear_unlock_delalloc(inode, start, end, NULL,
- clear_flags, PAGE_UNLOCK |
+ extent_clear_unlock_delalloc(inode, start, end, end,
+ NULL, clear_flags,
+ PAGE_UNLOCK |
PAGE_CLEAR_DIRTY |
PAGE_SET_WRITEBACK |
page_error_op |
@@ -837,6 +838,8 @@ retry:
extent_clear_unlock_delalloc(inode, async_extent->start,
async_extent->start +
async_extent->ram_size - 1,
+ async_extent->start +
+ async_extent->ram_size - 1,
NULL, EXTENT_LOCKED | EXTENT_DELALLOC,
PAGE_UNLOCK | PAGE_CLEAR_DIRTY |
PAGE_SET_WRITEBACK);
@@ -856,7 +859,8 @@ retry:
tree->ops->writepage_end_io_hook(p, start, end,
NULL, 0);
p->mapping = NULL;
- extent_clear_unlock_delalloc(inode, start, end, NULL, 0,
+ extent_clear_unlock_delalloc(inode, start, end, end,
+ NULL, 0,
PAGE_END_WRITEBACK |
PAGE_SET_ERROR);
free_async_extent_pages(async_extent);
@@ -873,6 +877,8 @@ out_free:
extent_clear_unlock_delalloc(inode, async_extent->start,
async_extent->start +
async_extent->ram_size - 1,
+ async_extent->start +
+ async_extent->ram_size - 1,
NULL, EXTENT_LOCKED | EXTENT_DELALLOC |
EXTENT_DEFRAG | EXTENT_DO_ACCOUNTING,
PAGE_UNLOCK | PAGE_CLEAR_DIRTY |
@@ -966,7 +972,8 @@ static noinline int cow_file_range(struct inode *inode,
ret = cow_file_range_inline(root, inode, start, end, 0, 0,
NULL);
if (ret == 0) {
- extent_clear_unlock_delalloc(inode, start, end, NULL,
+ extent_clear_unlock_delalloc(inode, start, end,
+ delalloc_end, NULL,
EXTENT_LOCKED | EXTENT_DELALLOC |
EXTENT_DEFRAG, PAGE_UNLOCK |
PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK |
@@ -1062,7 +1069,8 @@ static noinline int cow_file_range(struct inode *inode,
op |= PAGE_SET_PRIVATE2;
extent_clear_unlock_delalloc(inode, start,
- start + ram_size - 1, locked_page,
+ start + ram_size - 1,
+ delalloc_end, locked_page,
EXTENT_LOCKED | EXTENT_DELALLOC,
op);
disk_num_bytes -= cur_alloc_size;
@@ -1079,7 +1087,8 @@ out_reserve:
btrfs_dec_block_group_reservations(root->fs_info, ins.objectid);
btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1);
out_unlock:
- extent_clear_unlock_delalloc(inode, start, end, locked_page,
+ extent_clear_unlock_delalloc(inode, start, end, delalloc_end,
+ locked_page,
EXTENT_LOCKED | EXTENT_DO_ACCOUNTING |
EXTENT_DELALLOC | EXTENT_DEFRAG,
PAGE_UNLOCK | PAGE_CLEAR_DIRTY |
@@ -1258,7 +1267,8 @@ static noinline int run_delalloc_nocow(struct inode *inode,
path = btrfs_alloc_path();
if (!path) {
- extent_clear_unlock_delalloc(inode, start, end, locked_page,
+ extent_clear_unlock_delalloc(inode, start, end, end,
+ locked_page,
EXTENT_LOCKED | EXTENT_DELALLOC |
EXTENT_DO_ACCOUNTING |
EXTENT_DEFRAG, PAGE_UNLOCK |
@@ -1276,7 +1286,8 @@ static noinline int run_delalloc_nocow(struct inode *inode,
trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) {
- extent_clear_unlock_delalloc(inode, start, end, locked_page,
+ extent_clear_unlock_delalloc(inode, start, end, end,
+ locked_page,
EXTENT_LOCKED | EXTENT_DELALLOC |
EXTENT_DO_ACCOUNTING |
EXTENT_DEFRAG, PAGE_UNLOCK |
@@ -1490,7 +1501,7 @@ out_check:
}
extent_clear_unlock_delalloc(inode, cur_offset,
- cur_offset + num_bytes - 1,
+ cur_offset + num_bytes - 1, end,
locked_page, EXTENT_LOCKED |
EXTENT_DELALLOC |
EXTENT_CLEAR_DATA_RESV,
@@ -1522,7 +1533,7 @@ error:
ret = err;
if (ret && cur_offset < end)
- extent_clear_unlock_delalloc(inode, cur_offset, end,
+ extent_clear_unlock_delalloc(inode, cur_offset, end, end,
locked_page, EXTENT_LOCKED |
EXTENT_DELALLOC | EXTENT_DEFRAG |
EXTENT_DO_ACCOUNTING, PAGE_UNLOCK |
@@ -1988,7 +1999,7 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans,
}
int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end,
- struct extent_state **cached_state)
+ struct extent_state **cached_state, int dedupe)
{
WARN_ON((end & (PAGE_SIZE - 1)) == 0);
return set_extent_delalloc(&BTRFS_I(inode)->io_tree, start, end,
@@ -2052,7 +2063,8 @@ again:
goto out;
}
- btrfs_set_extent_delalloc(inode, page_start, page_end, &cached_state);
+ btrfs_set_extent_delalloc(inode, page_start, page_end, &cached_state,
+ 0);
ClearPageChecked(page);
set_page_dirty(page);
out:
@@ -2309,7 +2321,7 @@ static noinline int record_one_backref(u64 inum, u64 offset, u64 root_id,
if (PTR_ERR(root) == -ENOENT)
return 0;
WARN_ON(1);
- pr_debug("inum=%llu, offset=%llu, root_id=%llu\n",
+ btrfs_debug(fs_info, "inum=%llu, offset=%llu, root_id=%llu",
inum, offset, root_id);
return PTR_ERR(root);
}
@@ -3936,7 +3948,7 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
*/
if (!btrfs_is_free_space_inode(inode)
&& root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID
- && !root->fs_info->log_root_recovering) {
+ && !test_bit(BTRFS_FS_LOG_RECOVERING, &root->fs_info->flags)) {
btrfs_update_root_times(trans, root);
ret = btrfs_delayed_update_inode(trans, root, inode);
@@ -4059,7 +4071,7 @@ err:
inode_inc_iversion(inode);
inode_inc_iversion(dir);
inode->i_ctime = dir->i_mtime =
- dir->i_ctime = current_fs_time(inode->i_sb);
+ dir->i_ctime = current_time(inode);
ret = btrfs_update_inode(trans, root, dir);
out:
return ret;
@@ -4202,7 +4214,7 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
btrfs_i_size_write(dir, dir->i_size - name_len * 2);
inode_inc_iversion(dir);
- dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
+ dir->i_mtime = dir->i_ctime = current_time(dir);
ret = btrfs_update_inode_fallback(trans, root, dir);
if (ret)
btrfs_abort_transaction(trans, ret);
@@ -4757,7 +4769,7 @@ again:
0, 0, &cached_state, GFP_NOFS);
ret = btrfs_set_extent_delalloc(inode, block_start, block_end,
- &cached_state);
+ &cached_state, 0);
if (ret) {
unlock_extent_cached(io_tree, block_start, block_end,
&cached_state, GFP_NOFS);
@@ -4965,7 +4977,7 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
inode_inc_iversion(inode);
if (!(mask & (ATTR_CTIME | ATTR_MTIME)))
inode->i_ctime = inode->i_mtime =
- current_fs_time(inode->i_sb);
+ current_time(inode);
}
if (newsize > oldsize) {
@@ -5072,7 +5084,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
if (btrfs_root_readonly(root))
return -EROFS;
- err = inode_change_ok(inode, attr);
+ err = setattr_prepare(dentry, attr);
if (err)
return err;
@@ -5223,7 +5235,7 @@ void btrfs_evict_inode(struct inode *inode)
btrfs_free_io_failure_record(inode, 0, (u64)-1);
- if (root->fs_info->log_root_recovering) {
+ if (test_bit(BTRFS_FS_LOG_RECOVERING, &root->fs_info->flags)) {
BUG_ON(test_bit(BTRFS_INODE_HAS_ORPHAN_ITEM,
&BTRFS_I(inode)->runtime_flags));
goto no_delete;
@@ -5672,7 +5684,7 @@ static struct inode *new_simple_dir(struct super_block *s,
inode->i_op = &btrfs_dir_ro_inode_operations;
inode->i_fop = &simple_dir_operations;
inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
- inode->i_mtime = current_fs_time(inode->i_sb);
+ 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;
@@ -6258,7 +6270,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
inode_init_owner(inode, dir, mode);
inode_set_bytes(inode, 0);
- inode->i_mtime = current_fs_time(inode->i_sb);
+ 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;
@@ -6372,7 +6384,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
name_len * 2);
inode_inc_iversion(parent_inode);
parent_inode->i_mtime = parent_inode->i_ctime =
- current_fs_time(parent_inode->i_sb);
+ current_time(parent_inode);
ret = btrfs_update_inode(trans, root, parent_inode);
if (ret)
btrfs_abort_transaction(trans, ret);
@@ -6590,7 +6602,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
BTRFS_I(inode)->dir_index = 0ULL;
inc_nlink(inode);
inode_inc_iversion(inode);
- inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_ctime = current_time(inode);
ihold(inode);
set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags);
@@ -7012,8 +7024,9 @@ not_found_em:
insert:
btrfs_release_path(path);
if (em->start > start || extent_map_end(em) <= start) {
- btrfs_err(root->fs_info, "bad extent! em: [%llu %llu] passed [%llu %llu]",
- em->start, em->len, start, len);
+ btrfs_err(root->fs_info,
+ "bad extent! em: [%llu %llu] passed [%llu %llu]",
+ em->start, em->len, start, len);
err = -EIO;
goto out;
}
@@ -7865,18 +7878,19 @@ static int btrfs_check_dio_repairable(struct inode *inode,
struct io_failure_record *failrec,
int failed_mirror)
{
+ struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
int num_copies;
- num_copies = btrfs_num_copies(BTRFS_I(inode)->root->fs_info,
- failrec->logical, failrec->len);
+ num_copies = btrfs_num_copies(fs_info, failrec->logical, failrec->len);
if (num_copies == 1) {
/*
* we only have a single copy of the data, so don't bother with
* all the retry and error correction code that follows. no
* matter what the error is, it is very likely to persist.
*/
- pr_debug("Check DIO Repairable: cannot repair, num_copies=%d, next_mirror %d, failed_mirror %d\n",
- num_copies, failrec->this_mirror, failed_mirror);
+ btrfs_debug(fs_info,
+ "Check DIO Repairable: cannot repair, num_copies=%d, next_mirror %d, failed_mirror %d",
+ num_copies, failrec->this_mirror, failed_mirror);
return 0;
}
@@ -7886,8 +7900,9 @@ static int btrfs_check_dio_repairable(struct inode *inode,
failrec->this_mirror++;
if (failrec->this_mirror > num_copies) {
- pr_debug("Check DIO Repairable: (fail) num_copies=%d, next_mirror %d, failed_mirror %d\n",
- num_copies, failrec->this_mirror, failed_mirror);
+ btrfs_debug(fs_info,
+ "Check DIO Repairable: (fail) num_copies=%d, next_mirror %d, failed_mirror %d",
+ num_copies, failrec->this_mirror, failed_mirror);
return 0;
}
@@ -8412,7 +8427,7 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip,
if (!bio)
return -ENOMEM;
- bio_set_op_attrs(bio, bio_op(orig_bio), orig_bio->bi_opf);
+ bio_set_op_attrs(bio, bio_op(orig_bio), bio_flags(orig_bio));
bio->bi_private = dip;
bio->bi_end_io = btrfs_end_dio_bio;
btrfs_io_bio(bio)->logical = file_offset;
@@ -8450,7 +8465,8 @@ next_block:
start_sector, GFP_NOFS);
if (!bio)
goto out_err;
- bio_set_op_attrs(bio, bio_op(orig_bio), orig_bio->bi_opf);
+ bio_set_op_attrs(bio, bio_op(orig_bio),
+ bio_flags(orig_bio));
bio->bi_private = dip;
bio->bi_end_io = btrfs_end_dio_bio;
btrfs_io_bio(bio)->logical = file_offset;
@@ -8618,7 +8634,7 @@ static ssize_t check_direct_IO(struct btrfs_root *root, struct kiocb *iocb,
goto out;
/* If this is a write we don't need to check anymore */
- if (iov_iter_rw(iter) == WRITE)
+ if (iov_iter_rw(iter) != READ || !iter_is_iovec(iter))
return 0;
/*
* Check to make sure we don't have duplicate iov_base's in this
@@ -9054,7 +9070,7 @@ again:
0, 0, &cached_state, GFP_NOFS);
ret = btrfs_set_extent_delalloc(inode, page_start, end,
- &cached_state);
+ &cached_state, 0);
if (ret) {
unlock_extent_cached(io_tree, page_start, page_end,
&cached_state, GFP_NOFS);
@@ -9376,8 +9392,9 @@ void btrfs_destroy_inode(struct inode *inode)
if (!ordered)
break;
else {
- btrfs_err(root->fs_info, "found ordered extent %llu %llu on inode cleanup",
- ordered->file_offset, ordered->len);
+ btrfs_err(root->fs_info,
+ "found ordered extent %llu %llu on inode cleanup",
+ ordered->file_offset, ordered->len);
btrfs_remove_ordered_extent(inode, ordered);
btrfs_put_ordered_extent(ordered);
btrfs_put_ordered_extent(ordered);
@@ -9492,7 +9509,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;
+ struct timespec ctime = current_time(old_inode);
struct dentry *parent;
u64 old_ino = btrfs_ino(old_inode);
u64 new_ino = btrfs_ino(new_inode);
@@ -9860,7 +9877,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
inode_inc_iversion(old_inode);
old_dir->i_ctime = old_dir->i_mtime =
new_dir->i_ctime = new_dir->i_mtime =
- old_inode->i_ctime = current_fs_time(old_dir->i_sb);
+ old_inode->i_ctime = current_time(old_dir);
if (old_dentry->d_parent != new_dentry->d_parent)
btrfs_record_unlink_dir(trans, old_dir, old_inode, 1);
@@ -9885,7 +9902,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (new_inode) {
inode_inc_iversion(new_inode);
- new_inode->i_ctime = current_fs_time(new_inode->i_sb);
+ new_inode->i_ctime = current_time(new_inode);
if (unlikely(btrfs_ino(new_inode) ==
BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {
root_objectid = BTRFS_I(new_inode)->location.objectid;
@@ -10403,7 +10420,7 @@ next:
*alloc_hint = ins.objectid + ins.offset;
inode_inc_iversion(inode);
- inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_ctime = current_time(inode);
BTRFS_I(inode)->flags |= BTRFS_INODE_PREALLOC;
if (!(mode & FALLOC_FL_KEEP_SIZE) &&
(actual_len > inode->i_size) &&
@@ -10543,21 +10560,6 @@ out_inode:
}
-/* Inspired by filemap_check_errors() */
-int btrfs_inode_check_errors(struct inode *inode)
-{
- int ret = 0;
-
- if (test_bit(AS_ENOSPC, &inode->i_mapping->flags) &&
- test_and_clear_bit(AS_ENOSPC, &inode->i_mapping->flags))
- ret = -ENOSPC;
- if (test_bit(AS_EIO, &inode->i_mapping->flags) &&
- test_and_clear_bit(AS_EIO, &inode->i_mapping->flags))
- ret = -EIO;
-
- return ret;
-}
-
static const struct inode_operations btrfs_dir_inode_operations = {
.getattr = btrfs_getattr,
.lookup = btrfs_lookup,
@@ -10566,14 +10568,11 @@ static const struct inode_operations btrfs_dir_inode_operations = {
.link = btrfs_link,
.mkdir = btrfs_mkdir,
.rmdir = btrfs_rmdir,
- .rename2 = btrfs_rename2,
+ .rename = btrfs_rename2,
.symlink = btrfs_symlink,
.setattr = btrfs_setattr,
.mknod = btrfs_mknod,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = btrfs_listxattr,
- .removexattr = generic_removexattr,
.permission = btrfs_permission,
.get_acl = btrfs_get_acl,
.set_acl = btrfs_set_acl,
@@ -10647,10 +10646,7 @@ static const struct address_space_operations btrfs_symlink_aops = {
static const struct inode_operations btrfs_file_inode_operations = {
.getattr = btrfs_getattr,
.setattr = btrfs_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = btrfs_listxattr,
- .removexattr = generic_removexattr,
.permission = btrfs_permission,
.fiemap = btrfs_fiemap,
.get_acl = btrfs_get_acl,
@@ -10661,10 +10657,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
.getattr = btrfs_getattr,
.setattr = btrfs_setattr,
.permission = btrfs_permission,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = btrfs_listxattr,
- .removexattr = generic_removexattr,
.get_acl = btrfs_get_acl,
.set_acl = btrfs_set_acl,
.update_time = btrfs_update_time,
@@ -10675,10 +10668,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
.getattr = btrfs_getattr,
.setattr = btrfs_setattr,
.permission = btrfs_permission,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = btrfs_listxattr,
- .removexattr = generic_removexattr,
.update_time = btrfs_update_time,
};
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 7fd939bfbd99..18e1aa0f85f5 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -349,7 +349,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
btrfs_update_iflags(inode);
inode_inc_iversion(inode);
- inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_ctime = current_time(inode);
ret = btrfs_update_inode(trans, root, inode);
btrfs_end_transaction(trans, root);
@@ -445,7 +445,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_fs_time(dir->i_sb);
+ struct timespec cur_time = current_time(dir);
struct inode *inode;
int ret;
int err;
@@ -1903,8 +1903,9 @@ static noinline int may_destroy_subvol(struct btrfs_root *root)
btrfs_dir_item_key_to_cpu(path->nodes[0], di, &key);
if (key.objectid == root->root_key.objectid) {
ret = -EPERM;
- btrfs_err(root->fs_info, "deleting default subvolume "
- "%llu is not allowed", key.objectid);
+ btrfs_err(root->fs_info,
+ "deleting default subvolume %llu is not allowed",
+ key.objectid);
goto out;
}
btrfs_release_path(path);
@@ -3291,7 +3292,7 @@ static int clone_finish_inode_update(struct btrfs_trans_handle *trans,
inode_inc_iversion(inode);
if (!no_time_update)
- inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_mtime = inode->i_ctime = current_time(inode);
/*
* We round up to the block size at eof when determining which
* extents to clone above, but shouldn't round up the file size.
@@ -4097,8 +4098,8 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
if (IS_ERR_OR_NULL(di)) {
btrfs_free_path(path);
btrfs_end_transaction(trans, root);
- btrfs_err(new_root->fs_info, "Umm, you don't have the default dir"
- "item, this isn't going to work");
+ btrfs_err(new_root->fs_info,
+ "Umm, you don't have the default diritem, this isn't going to work");
ret = -ENOENT;
goto out;
}
@@ -5106,7 +5107,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_fs_time(inode->i_sb);
+ struct timespec ct = current_time(inode);
int ret = 0;
int received_uuid_changed;
@@ -5307,8 +5308,9 @@ static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg)
return -EFAULT;
if (strnlen(label, BTRFS_LABEL_SIZE) == BTRFS_LABEL_SIZE) {
- btrfs_err(root->fs_info, "unable to set label with more than %d bytes",
- BTRFS_LABEL_SIZE - 1);
+ btrfs_err(root->fs_info,
+ "unable to set label with more than %d bytes",
+ BTRFS_LABEL_SIZE - 1);
return -EINVAL;
}
diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c
index 1adfbe7be6b8..48655da0f4ca 100644
--- a/fs/btrfs/lzo.c
+++ b/fs/btrfs/lzo.c
@@ -141,7 +141,7 @@ static int lzo_compress_pages(struct list_head *ws,
ret = lzo1x_1_compress(data_in, in_len, workspace->cbuf,
&out_len, workspace->mem);
if (ret != LZO_E_OK) {
- printk(KERN_DEBUG "BTRFS: deflate in loop returned %d\n",
+ pr_debug("BTRFS: deflate in loop returned %d\n",
ret);
ret = -EIO;
goto out;
@@ -356,7 +356,7 @@ cont:
if (need_unmap)
kunmap(pages_in[page_in_index - 1]);
if (ret != LZO_E_OK) {
- printk(KERN_WARNING "BTRFS: decompress failed\n");
+ pr_warn("BTRFS: decompress failed\n");
ret = -EIO;
break;
}
@@ -402,7 +402,7 @@ static int lzo_decompress(struct list_head *ws, unsigned char *data_in,
out_len = PAGE_SIZE;
ret = lzo1x_decompress_safe(data_in, in_len, workspace->buf, &out_len);
if (ret != LZO_E_OK) {
- printk(KERN_WARNING "BTRFS: decompress failed!\n");
+ pr_warn("BTRFS: decompress failed!\n");
ret = -EIO;
goto out;
}
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index 3b78d38173b3..b2d1e95de7be 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -67,8 +67,8 @@ static void ordered_data_tree_panic(struct inode *inode, int errno,
u64 offset)
{
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
- btrfs_panic(fs_info, errno, "Inconsistency in ordered tree at offset "
- "%llu", offset);
+ btrfs_panic(fs_info, errno,
+ "Inconsistency in ordered tree at offset %llu", offset);
}
/*
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c
index 147dc6ca5de1..438575ea8d25 100644
--- a/fs/btrfs/print-tree.c
+++ b/fs/btrfs/print-tree.c
@@ -24,12 +24,11 @@ static void print_chunk(struct extent_buffer *eb, struct btrfs_chunk *chunk)
{
int num_stripes = btrfs_chunk_num_stripes(eb, chunk);
int i;
- printk(KERN_INFO "\t\tchunk length %llu owner %llu type %llu "
- "num_stripes %d\n",
+ pr_info("\t\tchunk length %llu owner %llu type %llu num_stripes %d\n",
btrfs_chunk_length(eb, chunk), btrfs_chunk_owner(eb, chunk),
btrfs_chunk_type(eb, chunk), num_stripes);
for (i = 0 ; i < num_stripes ; i++) {
- printk(KERN_INFO "\t\t\tstripe %d devid %llu offset %llu\n", i,
+ pr_info("\t\t\tstripe %d devid %llu offset %llu\n", i,
btrfs_stripe_devid_nr(eb, chunk, i),
btrfs_stripe_offset_nr(eb, chunk, i));
}
@@ -37,8 +36,7 @@ static void print_chunk(struct extent_buffer *eb, struct btrfs_chunk *chunk)
static void print_dev_item(struct extent_buffer *eb,
struct btrfs_dev_item *dev_item)
{
- printk(KERN_INFO "\t\tdev item devid %llu "
- "total_bytes %llu bytes used %llu\n",
+ pr_info("\t\tdev item devid %llu total_bytes %llu bytes used %llu\n",
btrfs_device_id(eb, dev_item),
btrfs_device_total_bytes(eb, dev_item),
btrfs_device_bytes_used(eb, dev_item));
@@ -46,8 +44,7 @@ static void print_dev_item(struct extent_buffer *eb,
static void print_extent_data_ref(struct extent_buffer *eb,
struct btrfs_extent_data_ref *ref)
{
- printk(KERN_INFO "\t\textent data backref root %llu "
- "objectid %llu offset %llu count %u\n",
+ pr_info("\t\textent data backref root %llu objectid %llu offset %llu count %u\n",
btrfs_extent_data_ref_root(eb, ref),
btrfs_extent_data_ref_objectid(eb, ref),
btrfs_extent_data_ref_offset(eb, ref),
@@ -72,7 +69,7 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
struct btrfs_extent_item_v0 *ei0;
BUG_ON(item_size != sizeof(*ei0));
ei0 = btrfs_item_ptr(eb, slot, struct btrfs_extent_item_v0);
- printk(KERN_INFO "\t\textent refs %u\n",
+ pr_info("\t\textent refs %u\n",
btrfs_extent_refs_v0(eb, ei0));
return;
#else
@@ -83,7 +80,7 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
ei = btrfs_item_ptr(eb, slot, struct btrfs_extent_item);
flags = btrfs_extent_flags(eb, ei);
- printk(KERN_INFO "\t\textent refs %llu gen %llu flags %llu\n",
+ pr_info("\t\textent refs %llu gen %llu flags %llu\n",
btrfs_extent_refs(eb, ei), btrfs_extent_generation(eb, ei),
flags);
@@ -92,8 +89,7 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
struct btrfs_tree_block_info *info;
info = (struct btrfs_tree_block_info *)(ei + 1);
btrfs_tree_block_key(eb, info, &key);
- printk(KERN_INFO "\t\ttree block key (%llu %u %llu) "
- "level %d\n",
+ pr_info("\t\ttree block key (%llu %u %llu) level %d\n",
btrfs_disk_key_objectid(&key), key.type,
btrfs_disk_key_offset(&key),
btrfs_tree_block_level(eb, info));
@@ -110,12 +106,10 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
offset = btrfs_extent_inline_ref_offset(eb, iref);
switch (type) {
case BTRFS_TREE_BLOCK_REF_KEY:
- printk(KERN_INFO "\t\ttree block backref "
- "root %llu\n", offset);
+ pr_info("\t\ttree block backref root %llu\n", offset);
break;
case BTRFS_SHARED_BLOCK_REF_KEY:
- printk(KERN_INFO "\t\tshared block backref "
- "parent %llu\n", offset);
+ pr_info("\t\tshared block backref parent %llu\n", offset);
break;
case BTRFS_EXTENT_DATA_REF_KEY:
dref = (struct btrfs_extent_data_ref *)(&iref->offset);
@@ -123,8 +117,7 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
break;
case BTRFS_SHARED_DATA_REF_KEY:
sref = (struct btrfs_shared_data_ref *)(iref + 1);
- printk(KERN_INFO "\t\tshared data backref "
- "parent %llu count %u\n",
+ pr_info("\t\tshared data backref parent %llu count %u\n",
offset, btrfs_shared_data_ref_count(eb, sref));
break;
default:
@@ -141,8 +134,7 @@ static void print_extent_ref_v0(struct extent_buffer *eb, int slot)
struct btrfs_extent_ref_v0 *ref0;
ref0 = btrfs_item_ptr(eb, slot, struct btrfs_extent_ref_v0);
- printk("\t\textent back ref root %llu gen %llu "
- "owner %llu num_refs %lu\n",
+ printk("\t\textent back ref root %llu gen %llu owner %llu num_refs %lu\n",
btrfs_ref_root_v0(eb, ref0),
btrfs_ref_generation_v0(eb, ref0),
btrfs_ref_objectid_v0(eb, ref0),
@@ -162,7 +154,7 @@ static void print_uuid_item(struct extent_buffer *l, unsigned long offset,
__le64 subvol_id;
read_extent_buffer(l, &subvol_id, offset, sizeof(subvol_id));
- printk(KERN_INFO "\t\tsubvol_id %llu\n",
+ pr_info("\t\tsubvol_id %llu\n",
(unsigned long long)le64_to_cpu(subvol_id));
item_size -= sizeof(u64);
offset += sizeof(u64);
@@ -196,15 +188,13 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
item = btrfs_item_nr(i);
btrfs_item_key_to_cpu(l, &key, i);
type = key.type;
- printk(KERN_INFO "\titem %d key (%llu %u %llu) itemoff %d "
- "itemsize %d\n",
+ pr_info("\titem %d key (%llu %u %llu) itemoff %d itemsize %d\n",
i, key.objectid, type, key.offset,
btrfs_item_offset(l, item), btrfs_item_size(l, item));
switch (type) {
case BTRFS_INODE_ITEM_KEY:
ii = btrfs_item_ptr(l, i, struct btrfs_inode_item);
- printk(KERN_INFO "\t\tinode generation %llu size %llu "
- "mode %o\n",
+ pr_info("\t\tinode generation %llu size %llu mode %o\n",
btrfs_inode_generation(l, ii),
btrfs_inode_size(l, ii),
btrfs_inode_mode(l, ii));
@@ -212,13 +202,13 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
case BTRFS_DIR_ITEM_KEY:
di = btrfs_item_ptr(l, i, struct btrfs_dir_item);
btrfs_dir_item_key_to_cpu(l, di, &found_key);
- printk(KERN_INFO "\t\tdir oid %llu type %u\n",
+ pr_info("\t\tdir oid %llu type %u\n",
found_key.objectid,
btrfs_dir_type(l, di));
break;
case BTRFS_ROOT_ITEM_KEY:
ri = btrfs_item_ptr(l, i, struct btrfs_root_item);
- printk(KERN_INFO "\t\troot data bytenr %llu refs %u\n",
+ pr_info("\t\troot data bytenr %llu refs %u\n",
btrfs_disk_root_bytenr(l, ri),
btrfs_disk_root_refs(l, ri));
break;
@@ -227,10 +217,10 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
print_extent_item(l, i, type);
break;
case BTRFS_TREE_BLOCK_REF_KEY:
- printk(KERN_INFO "\t\ttree block backref\n");
+ pr_info("\t\ttree block backref\n");
break;
case BTRFS_SHARED_BLOCK_REF_KEY:
- printk(KERN_INFO "\t\tshared block backref\n");
+ pr_info("\t\tshared block backref\n");
break;
case BTRFS_EXTENT_DATA_REF_KEY:
dref = btrfs_item_ptr(l, i,
@@ -240,7 +230,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
case BTRFS_SHARED_DATA_REF_KEY:
sref = btrfs_item_ptr(l, i,
struct btrfs_shared_data_ref);
- printk(KERN_INFO "\t\tshared data backref count %u\n",
+ pr_info("\t\tshared data backref count %u\n",
btrfs_shared_data_ref_count(l, sref));
break;
case BTRFS_EXTENT_DATA_KEY:
@@ -248,17 +238,14 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
struct btrfs_file_extent_item);
if (btrfs_file_extent_type(l, fi) ==
BTRFS_FILE_EXTENT_INLINE) {
- printk(KERN_INFO "\t\tinline extent data "
- "size %u\n",
+ pr_info("\t\tinline extent data size %u\n",
btrfs_file_extent_inline_len(l, i, fi));
break;
}
- printk(KERN_INFO "\t\textent data disk bytenr %llu "
- "nr %llu\n",
+ pr_info("\t\textent data disk bytenr %llu nr %llu\n",
btrfs_file_extent_disk_bytenr(l, fi),
btrfs_file_extent_disk_num_bytes(l, fi));
- printk(KERN_INFO "\t\textent data offset %llu "
- "nr %llu ram %llu\n",
+ pr_info("\t\textent data offset %llu nr %llu ram %llu\n",
btrfs_file_extent_offset(l, fi),
btrfs_file_extent_num_bytes(l, fi),
btrfs_file_extent_ram_bytes(l, fi));
@@ -273,7 +260,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
case BTRFS_BLOCK_GROUP_ITEM_KEY:
bi = btrfs_item_ptr(l, i,
struct btrfs_block_group_item);
- printk(KERN_INFO "\t\tblock group used %llu\n",
+ pr_info("\t\tblock group used %llu\n",
btrfs_disk_block_group_used(l, bi));
break;
case BTRFS_CHUNK_ITEM_KEY:
@@ -287,38 +274,36 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
case BTRFS_DEV_EXTENT_KEY:
dev_extent = btrfs_item_ptr(l, i,
struct btrfs_dev_extent);
- printk(KERN_INFO "\t\tdev extent chunk_tree %llu\n"
- "\t\tchunk objectid %llu chunk offset %llu "
- "length %llu\n",
+ pr_info("\t\tdev extent chunk_tree %llu\n\t\tchunk objectid %llu chunk offset %llu length %llu\n",
btrfs_dev_extent_chunk_tree(l, dev_extent),
btrfs_dev_extent_chunk_objectid(l, dev_extent),
btrfs_dev_extent_chunk_offset(l, dev_extent),
btrfs_dev_extent_length(l, dev_extent));
break;
case BTRFS_PERSISTENT_ITEM_KEY:
- printk(KERN_INFO "\t\tpersistent item objectid %llu offset %llu\n",
+ pr_info("\t\tpersistent item objectid %llu offset %llu\n",
key.objectid, key.offset);
switch (key.objectid) {
case BTRFS_DEV_STATS_OBJECTID:
- printk(KERN_INFO "\t\tdevice stats\n");
+ pr_info("\t\tdevice stats\n");
break;
default:
- printk(KERN_INFO "\t\tunknown persistent item\n");
+ pr_info("\t\tunknown persistent item\n");
}
break;
case BTRFS_TEMPORARY_ITEM_KEY:
- printk(KERN_INFO "\t\ttemporary item objectid %llu offset %llu\n",
+ pr_info("\t\ttemporary item objectid %llu offset %llu\n",
key.objectid, key.offset);
switch (key.objectid) {
case BTRFS_BALANCE_OBJECTID:
- printk(KERN_INFO "\t\tbalance status\n");
+ pr_info("\t\tbalance status\n");
break;
default:
- printk(KERN_INFO "\t\tunknown temporary item\n");
+ pr_info("\t\tunknown temporary item\n");
}
break;
case BTRFS_DEV_REPLACE_KEY:
- printk(KERN_INFO "\t\tdev replace\n");
+ pr_info("\t\tdev replace\n");
break;
case BTRFS_UUID_KEY_SUBVOL:
case BTRFS_UUID_KEY_RECEIVED_SUBVOL:
@@ -343,12 +328,13 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c)
btrfs_print_leaf(root, c);
return;
}
- btrfs_info(root->fs_info, "node %llu level %d total ptrs %d free spc %u",
- btrfs_header_bytenr(c), level, nr,
- (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr);
+ btrfs_info(root->fs_info,
+ "node %llu level %d total ptrs %d free spc %u",
+ btrfs_header_bytenr(c), level, nr,
+ (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr);
for (i = 0; i < nr; i++) {
btrfs_node_key_to_cpu(c, &key, i);
- printk(KERN_INFO "\tkey %d (%llu %u %llu) block %llu\n",
+ pr_info("\tkey %d (%llu %u %llu) block %llu\n",
i, key.objectid, key.type, key.offset,
btrfs_node_blockptr(c, i));
}
@@ -356,6 +342,13 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c)
struct extent_buffer *next = read_tree_block(root,
btrfs_node_blockptr(c, i),
btrfs_node_ptr_generation(c, i));
+ if (IS_ERR(next)) {
+ continue;
+ } else if (!extent_buffer_uptodate(next)) {
+ free_extent_buffer(next);
+ continue;
+ }
+
if (btrfs_is_leaf(next) &&
level != 1)
BUG();
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 8db2e29fdcf4..11f4fffe503e 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -309,7 +309,7 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info)
u64 flags = 0;
u64 rescan_progress = 0;
- if (!fs_info->quota_enabled)
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
return 0;
fs_info->qgroup_ulist = ulist_alloc(GFP_NOFS);
@@ -360,8 +360,7 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info)
fs_info->generation) {
flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
btrfs_err(fs_info,
- "qgroup generation mismatch, "
- "marked as inconsistent");
+ "qgroup generation mismatch, marked as inconsistent");
}
fs_info->qgroup_flags = btrfs_qgroup_status_flags(l,
ptr);
@@ -463,13 +462,11 @@ next2:
}
out:
fs_info->qgroup_flags |= flags;
- if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON)) {
- fs_info->quota_enabled = 0;
- fs_info->pending_quota_state = 0;
- } else if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN &&
- ret >= 0) {
+ if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON))
+ clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
+ else if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN &&
+ ret >= 0)
ret = qgroup_rescan_init(fs_info, rescan_progress, 0);
- }
btrfs_free_path(path);
if (ret < 0) {
@@ -847,7 +844,7 @@ static int btrfs_clean_quota_tree(struct btrfs_trans_handle *trans,
}
ret = 0;
out:
- root->fs_info->pending_quota_state = 0;
+ set_bit(BTRFS_FS_QUOTA_DISABLING, &root->fs_info->flags);
btrfs_free_path(path);
return ret;
}
@@ -868,7 +865,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
mutex_lock(&fs_info->qgroup_ioctl_lock);
if (fs_info->quota_root) {
- fs_info->pending_quota_state = 1;
+ set_bit(BTRFS_FS_QUOTA_ENABLING, &fs_info->flags);
goto out;
}
@@ -964,7 +961,7 @@ out_add_root:
}
spin_lock(&fs_info->qgroup_lock);
fs_info->quota_root = quota_root;
- fs_info->pending_quota_state = 1;
+ set_bit(BTRFS_FS_QUOTA_ENABLING, &fs_info->flags);
spin_unlock(&fs_info->qgroup_lock);
out_free_path:
btrfs_free_path(path);
@@ -993,8 +990,8 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans,
mutex_lock(&fs_info->qgroup_ioctl_lock);
if (!fs_info->quota_root)
goto out;
- fs_info->quota_enabled = 0;
- fs_info->pending_quota_state = 0;
+ clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
+ set_bit(BTRFS_FS_QUOTA_DISABLING, &fs_info->flags);
btrfs_qgroup_wait_for_completion(fs_info, false);
spin_lock(&fs_info->qgroup_lock);
quota_root = fs_info->quota_root;
@@ -1490,7 +1487,8 @@ int btrfs_qgroup_insert_dirty_extent(struct btrfs_trans_handle *trans,
struct btrfs_delayed_ref_root *delayed_refs;
int ret;
- if (!fs_info->quota_enabled || bytenr == 0 || num_bytes == 0)
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)
+ || bytenr == 0 || num_bytes == 0)
return 0;
if (WARN_ON(trans == NULL))
return -EINVAL;
@@ -1713,7 +1711,7 @@ btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans,
if (old_roots)
nr_old_roots = old_roots->nnodes;
- if (!fs_info->quota_enabled)
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
goto out_free;
BUG_ON(!fs_info->quota_root);
@@ -1833,10 +1831,14 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans,
if (!quota_root)
goto out;
- if (!fs_info->quota_enabled && fs_info->pending_quota_state)
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) &&
+ test_bit(BTRFS_FS_QUOTA_ENABLING, &fs_info->flags))
start_rescan_worker = 1;
- fs_info->quota_enabled = fs_info->pending_quota_state;
+ if (test_and_clear_bit(BTRFS_FS_QUOTA_ENABLING, &fs_info->flags))
+ set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
+ if (test_and_clear_bit(BTRFS_FS_QUOTA_DISABLING, &fs_info->flags))
+ clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
spin_lock(&fs_info->qgroup_lock);
while (!list_empty(&fs_info->dirty_qgroups)) {
@@ -1855,7 +1857,7 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans,
BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
spin_lock(&fs_info->qgroup_lock);
}
- if (fs_info->quota_enabled)
+ if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_ON;
else
fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_ON;
@@ -1900,7 +1902,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
u64 nums;
mutex_lock(&fs_info->qgroup_ioctl_lock);
- if (!fs_info->quota_enabled)
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
goto out;
if (!quota_root) {
@@ -1991,8 +1993,9 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
ret = update_qgroup_limit_item(trans, quota_root, dstgroup);
if (ret) {
fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
- btrfs_info(fs_info, "unable to update quota limit for %llu",
- dstgroup->qgroupid);
+ btrfs_info(fs_info,
+ "unable to update quota limit for %llu",
+ dstgroup->qgroupid);
goto unlock;
}
}
@@ -2226,8 +2229,7 @@ void assert_qgroups_uptodate(struct btrfs_trans_handle *trans)
if (list_empty(&trans->qgroup_ref_list) && !trans->delayed_ref_elem.seq)
return;
btrfs_err(trans->fs_info,
- "qgroups not uptodate in trans handle %p: list is%s empty, "
- "seq is %#x.%x",
+ "qgroups not uptodate in trans handle %p: list is%s empty, seq is %#x.%x",
trans, list_empty(&trans->qgroup_ref_list) ? "" : " not",
(u32)(trans->delayed_ref_elem.seq >> 32),
(u32)trans->delayed_ref_elem.seq);
@@ -2255,10 +2257,11 @@ qgroup_rescan_leaf(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
&fs_info->qgroup_rescan_progress,
path, 1, 0);
- pr_debug("current progress key (%llu %u %llu), search_slot ret %d\n",
- fs_info->qgroup_rescan_progress.objectid,
- fs_info->qgroup_rescan_progress.type,
- fs_info->qgroup_rescan_progress.offset, ret);
+ btrfs_debug(fs_info,
+ "current progress key (%llu %u %llu), search_slot ret %d",
+ fs_info->qgroup_rescan_progress.objectid,
+ fs_info->qgroup_rescan_progress.type,
+ fs_info->qgroup_rescan_progress.offset, ret);
if (ret) {
/*
@@ -2347,7 +2350,7 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
err = PTR_ERR(trans);
break;
}
- if (!fs_info->quota_enabled) {
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) {
err = -EINTR;
} else {
err = qgroup_rescan_leaf(fs_info, path, trans);
@@ -2388,7 +2391,7 @@ out:
ret = update_qgroup_status_item(trans, fs_info, fs_info->quota_root);
if (ret < 0) {
err = ret;
- btrfs_err(fs_info, "fail to update qgroup status: %d\n", err);
+ btrfs_err(fs_info, "fail to update qgroup status: %d", err);
}
btrfs_end_transaction(trans, fs_info->quota_root);
@@ -2578,8 +2581,8 @@ int btrfs_qgroup_reserve_data(struct inode *inode, u64 start, u64 len)
struct ulist_iterator uiter;
int ret;
- if (!root->fs_info->quota_enabled || !is_fstree(root->objectid) ||
- len == 0)
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags) ||
+ !is_fstree(root->objectid) || len == 0)
return 0;
changeset.bytes_changed = 0;
@@ -2676,8 +2679,8 @@ int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes)
{
int ret;
- if (!root->fs_info->quota_enabled || !is_fstree(root->objectid) ||
- num_bytes == 0)
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags) ||
+ !is_fstree(root->objectid) || num_bytes == 0)
return 0;
BUG_ON(num_bytes != round_down(num_bytes, root->nodesize));
@@ -2692,7 +2695,8 @@ void btrfs_qgroup_free_meta_all(struct btrfs_root *root)
{
int reserved;
- if (!root->fs_info->quota_enabled || !is_fstree(root->objectid))
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags) ||
+ !is_fstree(root->objectid))
return;
reserved = atomic_xchg(&root->qgroup_meta_rsv, 0);
@@ -2703,7 +2707,8 @@ void btrfs_qgroup_free_meta_all(struct btrfs_root *root)
void btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes)
{
- if (!root->fs_info->quota_enabled || !is_fstree(root->objectid))
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags) ||
+ !is_fstree(root->objectid))
return;
BUG_ON(num_bytes != round_down(num_bytes, root->nodesize));
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index cd8d302a1f61..d016d4a79864 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -2143,7 +2143,10 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio,
rbio->faila = find_logical_bio_stripe(rbio, bio);
if (rbio->faila == -1) {
- BUG();
+ btrfs_warn(root->fs_info,
+ "%s could not find the bad stripe in raid56 so that we cannot recover any more (bio has logical %llu len %llu, bbio has map_type %llu)",
+ __func__, (u64)bio->bi_iter.bi_sector << 9,
+ (u64)bio->bi_iter.bi_size, bbio->map_type);
if (generic_io)
btrfs_put_bbio(bbio);
kfree(rbio);
diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index 8428db7cd88f..75bab76739be 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -820,7 +820,7 @@ static void dump_devs(struct btrfs_fs_info *fs_info, int all)
spin_lock(&fs_info->reada_lock);
list_for_each_entry(device, &fs_devices->devices, dev_list) {
- printk(KERN_DEBUG "dev %lld has %d in flight\n", device->devid,
+ btrfs_debug(fs_info, "dev %lld has %d in flight", device->devid,
atomic_read(&device->reada_in_flight));
index = 0;
while (1) {
@@ -829,17 +829,17 @@ static void dump_devs(struct btrfs_fs_info *fs_info, int all)
(void **)&zone, index, 1);
if (ret == 0)
break;
- printk(KERN_DEBUG " zone %llu-%llu elems %llu locked "
- "%d devs", zone->start, zone->end, zone->elems,
- zone->locked);
+ pr_debug(" zone %llu-%llu elems %llu locked %d devs",
+ zone->start, zone->end, zone->elems,
+ zone->locked);
for (j = 0; j < zone->ndevs; ++j) {
- printk(KERN_CONT " %lld",
+ pr_cont(" %lld",
zone->devs[j]->devid);
}
if (device->reada_curr_zone == zone)
- printk(KERN_CONT " curr off %llu",
+ pr_cont(" curr off %llu",
device->reada_next - zone->start);
- printk(KERN_CONT "\n");
+ pr_cont("\n");
index = (zone->end >> PAGE_SHIFT) + 1;
}
cnt = 0;
@@ -851,21 +851,20 @@ static void dump_devs(struct btrfs_fs_info *fs_info, int all)
(void **)&re, index, 1);
if (ret == 0)
break;
- printk(KERN_DEBUG
- " re: logical %llu size %u empty %d scheduled %d",
+ pr_debug(" re: logical %llu size %u empty %d scheduled %d",
re->logical, fs_info->tree_root->nodesize,
list_empty(&re->extctl), re->scheduled);
for (i = 0; i < re->nzones; ++i) {
- printk(KERN_CONT " zone %llu-%llu devs",
+ pr_cont(" zone %llu-%llu devs",
re->zones[i]->start,
re->zones[i]->end);
for (j = 0; j < re->zones[i]->ndevs; ++j) {
- printk(KERN_CONT " %lld",
+ pr_cont(" %lld",
re->zones[i]->devs[j]->devid);
}
}
- printk(KERN_CONT "\n");
+ pr_cont("\n");
index = (re->logical >> PAGE_SHIFT) + 1;
if (++cnt > 15)
break;
@@ -885,20 +884,19 @@ static void dump_devs(struct btrfs_fs_info *fs_info, int all)
index = (re->logical >> PAGE_SHIFT) + 1;
continue;
}
- printk(KERN_DEBUG
- "re: logical %llu size %u list empty %d scheduled %d",
+ pr_debug("re: logical %llu size %u list empty %d scheduled %d",
re->logical, fs_info->tree_root->nodesize,
list_empty(&re->extctl), re->scheduled);
for (i = 0; i < re->nzones; ++i) {
- printk(KERN_CONT " zone %llu-%llu devs",
+ pr_cont(" zone %llu-%llu devs",
re->zones[i]->start,
re->zones[i]->end);
for (j = 0; j < re->zones[i]->ndevs; ++j) {
- printk(KERN_CONT " %lld",
+ pr_cont(" %lld",
re->zones[i]->devs[j]->devid);
}
}
- printk(KERN_CONT "\n");
+ pr_cont("\n");
index = (re->logical >> PAGE_SHIFT) + 1;
}
spin_unlock(&fs_info->reada_lock);
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index c0c13dc6fe12..0ec8ffa37ab0 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -337,8 +337,9 @@ static void backref_tree_panic(struct rb_node *rb_node, int errno, u64 bytenr)
rb_node);
if (bnode->root)
fs_info = bnode->root->fs_info;
- btrfs_panic(fs_info, errno, "Inconsistency in backref cache "
- "found at offset %llu", bytenr);
+ btrfs_panic(fs_info, errno,
+ "Inconsistency in backref cache found at offset %llu",
+ bytenr);
}
/*
@@ -923,9 +924,16 @@ again:
path2->slots[level]--;
eb = path2->nodes[level];
- WARN_ON(btrfs_node_blockptr(eb, path2->slots[level]) !=
- cur->bytenr);
-
+ if (btrfs_node_blockptr(eb, path2->slots[level]) !=
+ cur->bytenr) {
+ btrfs_err(root->fs_info,
+ "couldn't find block (%llu) (level %d) in tree (%llu) with key (%llu %u %llu)",
+ cur->bytenr, level - 1, root->objectid,
+ node_key->objectid, node_key->type,
+ node_key->offset);
+ err = -ENOENT;
+ goto out;
+ }
lower = cur;
need_check = true;
for (; level < BTRFS_MAX_LEVEL; level++) {
@@ -1296,9 +1304,9 @@ static int __must_check __add_reloc_root(struct btrfs_root *root)
node->bytenr, &node->rb_node);
spin_unlock(&rc->reloc_root_tree.lock);
if (rb_node) {
- btrfs_panic(root->fs_info, -EEXIST, "Duplicate root found "
- "for start=%llu while inserting into relocation "
- "tree", node->bytenr);
+ btrfs_panic(root->fs_info, -EEXIST,
+ "Duplicate root found for start=%llu while inserting into relocation tree",
+ node->bytenr);
kfree(node);
return -EEXIST;
}
@@ -2350,6 +2358,10 @@ void free_reloc_roots(struct list_head *list)
while (!list_empty(list)) {
reloc_root = list_entry(list->next, struct btrfs_root,
root_list);
+ free_extent_buffer(reloc_root->node);
+ free_extent_buffer(reloc_root->commit_root);
+ reloc_root->node = NULL;
+ reloc_root->commit_root = NULL;
__del_reloc_root(reloc_root);
}
}
@@ -2686,11 +2698,15 @@ static int do_relocation(struct btrfs_trans_handle *trans,
if (!upper->eb) {
ret = btrfs_search_slot(trans, root, key, path, 0, 1);
- if (ret < 0) {
- err = ret;
+ if (ret) {
+ if (ret < 0)
+ err = ret;
+ else
+ err = -ENOENT;
+
+ btrfs_release_path(path);
break;
}
- BUG_ON(ret > 0);
if (!upper->eb) {
upper->eb = path->nodes[upper->level];
@@ -3203,7 +3219,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
nr++;
}
- btrfs_set_extent_delalloc(inode, page_start, page_end, NULL);
+ btrfs_set_extent_delalloc(inode, page_start, page_end, NULL, 0);
set_page_dirty(page);
unlock_extent(&BTRFS_I(inode)->io_tree,
@@ -3952,7 +3968,7 @@ static int qgroup_fix_relocated_data_extents(struct btrfs_trans_handle *trans,
struct btrfs_key key;
int ret = 0;
- if (!fs_info->quota_enabled)
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
return 0;
/*
@@ -4365,8 +4381,9 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
goto out;
}
- btrfs_info(extent_root->fs_info, "relocating block group %llu flags %llu",
- rc->block_group->key.objectid, rc->block_group->flags);
+ btrfs_info(extent_root->fs_info,
+ "relocating block group %llu flags %llu",
+ rc->block_group->key.objectid, rc->block_group->flags);
btrfs_wait_block_group_reservations(rc->block_group);
btrfs_wait_nocow_writers(rc->block_group);
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
index 091296062456..edae751e870c 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -46,12 +46,7 @@ static void btrfs_read_root_item(struct extent_buffer *eb, int slot,
!= btrfs_root_generation_v2(item)) {
if (btrfs_root_generation_v2(item) != 0) {
btrfs_warn(eb->fs_info,
- "mismatching "
- "generation and generation_v2 "
- "found in root item. This root "
- "was probably mounted with an "
- "older kernel. Resetting all "
- "new fields.");
+ "mismatching generation and generation_v2 found in root item. This root was probably mounted with an older kernel. Resetting all new fields.");
}
need_reset = 1;
}
@@ -156,8 +151,9 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
if (ret != 0) {
btrfs_print_leaf(root, path->nodes[0]);
- btrfs_crit(root->fs_info, "unable to update root key %llu %u %llu",
- key->objectid, key->type, key->offset);
+ btrfs_crit(root->fs_info,
+ "unable to update root key %llu %u %llu",
+ key->objectid, key->type, key->offset);
BUG_ON(1);
}
@@ -302,8 +298,7 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
if (IS_ERR(trans)) {
err = PTR_ERR(trans);
btrfs_handle_fs_error(tree_root->fs_info, err,
- "Failed to start trans to delete "
- "orphan item");
+ "Failed to start trans to delete orphan item");
break;
}
err = btrfs_del_orphan_item(trans, tree_root,
@@ -311,8 +306,7 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
btrfs_end_transaction(trans, tree_root);
if (err) {
btrfs_handle_fs_error(tree_root->fs_info, err,
- "Failed to delete root orphan "
- "item");
+ "Failed to delete root orphan item");
break;
}
continue;
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 1d195d2b32c6..fffb9ab8526e 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -575,23 +575,25 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root,
* hold all of the paths here
*/
for (i = 0; i < ipath->fspath->elem_cnt; ++i)
- btrfs_warn_in_rcu(fs_info, "%s at logical %llu on dev "
- "%s, sector %llu, root %llu, inode %llu, offset %llu, "
- "length %llu, links %u (path: %s)", swarn->errstr,
- swarn->logical, rcu_str_deref(swarn->dev->name),
- (unsigned long long)swarn->sector, root, inum, offset,
- min(isize - offset, (u64)PAGE_SIZE), nlink,
- (char *)(unsigned long)ipath->fspath->val[i]);
+ btrfs_warn_in_rcu(fs_info,
+ "%s at logical %llu on dev %s, sector %llu, root %llu, inode %llu, offset %llu, length %llu, links %u (path: %s)",
+ swarn->errstr, swarn->logical,
+ rcu_str_deref(swarn->dev->name),
+ (unsigned long long)swarn->sector,
+ root, inum, offset,
+ min(isize - offset, (u64)PAGE_SIZE), nlink,
+ (char *)(unsigned long)ipath->fspath->val[i]);
free_ipath(ipath);
return 0;
err:
- btrfs_warn_in_rcu(fs_info, "%s at logical %llu on dev "
- "%s, sector %llu, root %llu, inode %llu, offset %llu: path "
- "resolving failed with ret=%d", swarn->errstr,
- swarn->logical, rcu_str_deref(swarn->dev->name),
- (unsigned long long)swarn->sector, root, inum, offset, ret);
+ btrfs_warn_in_rcu(fs_info,
+ "%s at logical %llu on dev %s, sector %llu, root %llu, inode %llu, offset %llu: path resolving failed with ret=%d",
+ swarn->errstr, swarn->logical,
+ rcu_str_deref(swarn->dev->name),
+ (unsigned long long)swarn->sector,
+ root, inum, offset, ret);
free_ipath(ipath);
return 0;
@@ -645,9 +647,8 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
item_size, &ref_root,
&ref_level);
btrfs_warn_in_rcu(fs_info,
- "%s at logical %llu on dev %s, "
- "sector %llu: metadata %s (level %d) in tree "
- "%llu", errstr, swarn.logical,
+ "%s at logical %llu on dev %s, sector %llu: metadata %s (level %d) in tree %llu",
+ errstr, swarn.logical,
rcu_str_deref(dev->name),
(unsigned long long)swarn.sector,
ref_level ? "node" : "leaf",
@@ -1574,8 +1575,7 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad,
if (!page_bad->dev->bdev) {
btrfs_warn_rl(sblock_bad->sctx->dev_root->fs_info,
- "scrub_repair_page_from_good_copy(bdev == NULL) "
- "is unexpected");
+ "scrub_repair_page_from_good_copy(bdev == NULL) is unexpected");
return -EIO;
}
@@ -2961,7 +2961,8 @@ static noinline_for_stack int scrub_raid56_parity(struct scrub_ctx *sctx,
(key.objectid < logic_start ||
key.objectid + bytes >
logic_start + map->stripe_len)) {
- btrfs_err(fs_info, "scrub: tree block %llu spanning stripes, ignored. logical=%llu",
+ btrfs_err(fs_info,
+ "scrub: tree block %llu spanning stripes, ignored. logical=%llu",
key.objectid, logic_start);
spin_lock(&sctx->stat_lock);
sctx->stat.uncorrectable_errors++;
@@ -3312,8 +3313,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
key.objectid + bytes >
logical + map->stripe_len)) {
btrfs_err(fs_info,
- "scrub: tree block %llu spanning "
- "stripes, ignored. logical=%llu",
+ "scrub: tree block %llu spanning stripes, ignored. logical=%llu",
key.objectid, logical);
spin_lock(&sctx->stat_lock);
sctx->stat.uncorrectable_errors++;
@@ -3640,7 +3640,8 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
*/
ro_set = 0;
} else {
- btrfs_warn(fs_info, "failed setting block group ro, ret=%d\n",
+ btrfs_warn(fs_info,
+ "failed setting block group ro, ret=%d\n",
ret);
btrfs_put_block_group(cache);
break;
@@ -3861,8 +3862,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
if (fs_info->chunk_root->sectorsize != PAGE_SIZE) {
/* not supported for data w/o checksums */
btrfs_err_rl(fs_info,
- "scrub: size assumption sectorsize != PAGE_SIZE "
- "(%d != %lu) fails",
+ "scrub: size assumption sectorsize != PAGE_SIZE (%d != %lu) fails",
fs_info->chunk_root->sectorsize, PAGE_SIZE);
return -EINVAL;
}
@@ -3875,8 +3875,8 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
* would exhaust the array bounds of pagev member in
* struct scrub_block
*/
- btrfs_err(fs_info, "scrub: size assumption nodesize and sectorsize "
- "<= SCRUB_MAX_PAGES_PER_BLOCK (%d <= %d && %d <= %d) fails",
+ btrfs_err(fs_info,
+ "scrub: size assumption nodesize and sectorsize <= SCRUB_MAX_PAGES_PER_BLOCK (%d <= %d && %d <= %d) fails",
fs_info->chunk_root->nodesize,
SCRUB_MAX_PAGES_PER_BLOCK,
fs_info->chunk_root->sectorsize,
@@ -4202,10 +4202,10 @@ static void copy_nocow_pages_worker(struct btrfs_work *work)
ret = iterate_inodes_from_logical(logical, fs_info, path,
record_inode_for_nocow, nocow_ctx);
if (ret != 0 && ret != -ENOENT) {
- btrfs_warn(fs_info, "iterate_inodes_from_logical() failed: log %llu, "
- "phys %llu, len %llu, mir %u, ret %d",
- logical, physical_for_dev_replace, len, mirror_num,
- ret);
+ btrfs_warn(fs_info,
+ "iterate_inodes_from_logical() failed: log %llu, phys %llu, len %llu, mir %u, ret %d",
+ logical, physical_for_dev_replace, len, mirror_num,
+ ret);
not_written = 1;
goto out;
}
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index a87675ffd02b..01bc36cec26e 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -36,10 +36,6 @@
#include "transaction.h"
#include "compression.h"
-static int g_verbose = 0;
-
-#define verbose_printk(...) if (g_verbose) printk(__VA_ARGS__)
-
/*
* A fs_path is a helper to dynamically build path names with unknown size.
* It reallocates the internal buffer on demand.
@@ -727,9 +723,10 @@ static int send_cmd(struct send_ctx *sctx)
static int send_rename(struct send_ctx *sctx,
struct fs_path *from, struct fs_path *to)
{
+ struct btrfs_fs_info *fs_info = sctx->send_root->fs_info;
int ret;
-verbose_printk("btrfs: send_rename %s -> %s\n", from->start, to->start);
+ btrfs_debug(fs_info, "send_rename %s -> %s", from->start, to->start);
ret = begin_cmd(sctx, BTRFS_SEND_C_RENAME);
if (ret < 0)
@@ -751,9 +748,10 @@ out:
static int send_link(struct send_ctx *sctx,
struct fs_path *path, struct fs_path *lnk)
{
+ struct btrfs_fs_info *fs_info = sctx->send_root->fs_info;
int ret;
-verbose_printk("btrfs: send_link %s -> %s\n", path->start, lnk->start);
+ btrfs_debug(fs_info, "send_link %s -> %s", path->start, lnk->start);
ret = begin_cmd(sctx, BTRFS_SEND_C_LINK);
if (ret < 0)
@@ -774,9 +772,10 @@ out:
*/
static int send_unlink(struct send_ctx *sctx, struct fs_path *path)
{
+ struct btrfs_fs_info *fs_info = sctx->send_root->fs_info;
int ret;
-verbose_printk("btrfs: send_unlink %s\n", path->start);
+ btrfs_debug(fs_info, "send_unlink %s", path->start);
ret = begin_cmd(sctx, BTRFS_SEND_C_UNLINK);
if (ret < 0)
@@ -796,9 +795,10 @@ out:
*/
static int send_rmdir(struct send_ctx *sctx, struct fs_path *path)
{
+ struct btrfs_fs_info *fs_info = sctx->send_root->fs_info;
int ret;
-verbose_printk("btrfs: send_rmdir %s\n", path->start);
+ btrfs_debug(fs_info, "send_rmdir %s", path->start);
ret = begin_cmd(sctx, BTRFS_SEND_C_RMDIR);
if (ret < 0)
@@ -1313,6 +1313,7 @@ static int find_extent_clone(struct send_ctx *sctx,
u64 ino_size,
struct clone_root **found)
{
+ struct btrfs_fs_info *fs_info = sctx->send_root->fs_info;
int ret;
int extent_type;
u64 logical;
@@ -1371,10 +1372,10 @@ static int find_extent_clone(struct send_ctx *sctx,
}
logical = disk_byte + btrfs_file_extent_offset(eb, fi);
- down_read(&sctx->send_root->fs_info->commit_root_sem);
- ret = extent_from_logical(sctx->send_root->fs_info, disk_byte, tmp_path,
+ down_read(&fs_info->commit_root_sem);
+ ret = extent_from_logical(fs_info, disk_byte, tmp_path,
&found_key, &flags);
- up_read(&sctx->send_root->fs_info->commit_root_sem);
+ up_read(&fs_info->commit_root_sem);
btrfs_release_path(tmp_path);
if (ret < 0)
@@ -1429,7 +1430,7 @@ static int find_extent_clone(struct send_ctx *sctx,
extent_item_pos = logical - found_key.objectid;
else
extent_item_pos = 0;
- ret = iterate_extent_inodes(sctx->send_root->fs_info,
+ ret = iterate_extent_inodes(fs_info,
found_key.objectid, extent_item_pos, 1,
__iterate_backrefs, backref_ctx);
@@ -1439,20 +1440,18 @@ static int find_extent_clone(struct send_ctx *sctx,
if (!backref_ctx->found_itself) {
/* found a bug in backref code? */
ret = -EIO;
- btrfs_err(sctx->send_root->fs_info, "did not find backref in "
- "send_root. inode=%llu, offset=%llu, "
- "disk_byte=%llu found extent=%llu",
- ino, data_offset, disk_byte, found_key.objectid);
+ btrfs_err(fs_info,
+ "did not find backref in send_root. inode=%llu, offset=%llu, disk_byte=%llu found extent=%llu",
+ ino, data_offset, disk_byte, found_key.objectid);
goto out;
}
-verbose_printk(KERN_DEBUG "btrfs: find_extent_clone: data_offset=%llu, "
- "ino=%llu, "
- "num_bytes=%llu, logical=%llu\n",
- data_offset, ino, num_bytes, logical);
+ btrfs_debug(fs_info,
+ "find_extent_clone: data_offset=%llu, ino=%llu, num_bytes=%llu, logical=%llu",
+ data_offset, ino, num_bytes, logical);
if (!backref_ctx->found)
- verbose_printk("btrfs: no clones found\n");
+ btrfs_debug(fs_info, "no clones found");
cur_clone_root = NULL;
for (i = 0; i < sctx->clone_roots_cnt; i++) {
@@ -2423,10 +2422,11 @@ out:
static int send_truncate(struct send_ctx *sctx, u64 ino, u64 gen, u64 size)
{
+ struct btrfs_fs_info *fs_info = sctx->send_root->fs_info;
int ret = 0;
struct fs_path *p;
-verbose_printk("btrfs: send_truncate %llu size=%llu\n", ino, size);
+ btrfs_debug(fs_info, "send_truncate %llu size=%llu", ino, size);
p = fs_path_alloc();
if (!p)
@@ -2452,10 +2452,11 @@ out:
static int send_chmod(struct send_ctx *sctx, u64 ino, u64 gen, u64 mode)
{
+ struct btrfs_fs_info *fs_info = sctx->send_root->fs_info;
int ret = 0;
struct fs_path *p;
-verbose_printk("btrfs: send_chmod %llu mode=%llu\n", ino, mode);
+ btrfs_debug(fs_info, "send_chmod %llu mode=%llu", ino, mode);
p = fs_path_alloc();
if (!p)
@@ -2481,10 +2482,12 @@ out:
static int send_chown(struct send_ctx *sctx, u64 ino, u64 gen, u64 uid, u64 gid)
{
+ struct btrfs_fs_info *fs_info = sctx->send_root->fs_info;
int ret = 0;
struct fs_path *p;
-verbose_printk("btrfs: send_chown %llu uid=%llu, gid=%llu\n", ino, uid, gid);
+ btrfs_debug(fs_info, "send_chown %llu uid=%llu, gid=%llu",
+ ino, uid, gid);
p = fs_path_alloc();
if (!p)
@@ -2511,6 +2514,7 @@ out:
static int send_utimes(struct send_ctx *sctx, u64 ino, u64 gen)
{
+ struct btrfs_fs_info *fs_info = sctx->send_root->fs_info;
int ret = 0;
struct fs_path *p = NULL;
struct btrfs_inode_item *ii;
@@ -2519,7 +2523,7 @@ static int send_utimes(struct send_ctx *sctx, u64 ino, u64 gen)
struct btrfs_key key;
int slot;
-verbose_printk("btrfs: send_utimes %llu\n", ino);
+ btrfs_debug(fs_info, "send_utimes %llu", ino);
p = fs_path_alloc();
if (!p)
@@ -2573,6 +2577,7 @@ out:
*/
static int send_create_inode(struct send_ctx *sctx, u64 ino)
{
+ struct btrfs_fs_info *fs_info = sctx->send_root->fs_info;
int ret = 0;
struct fs_path *p;
int cmd;
@@ -2580,7 +2585,7 @@ static int send_create_inode(struct send_ctx *sctx, u64 ino)
u64 mode;
u64 rdev;
-verbose_printk("btrfs: send_create_inode %llu\n", ino);
+ btrfs_debug(fs_info, "send_create_inode %llu", ino);
p = fs_path_alloc();
if (!p)
@@ -3638,6 +3643,7 @@ out:
*/
static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
{
+ struct btrfs_fs_info *fs_info = sctx->send_root->fs_info;
int ret = 0;
struct recorded_ref *cur;
struct recorded_ref *cur2;
@@ -3650,7 +3656,7 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
u64 last_dir_ino_rm = 0;
bool can_rename = true;
-verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
+ btrfs_debug(fs_info, "process_recorded_refs %llu", sctx->cur_ino);
/*
* This should never happen as the root dir always has the same ref
@@ -4329,7 +4335,7 @@ static int __process_new_xattr(int num, struct btrfs_key *di_key,
int ret;
struct send_ctx *sctx = ctx;
struct fs_path *p;
- posix_acl_xattr_header dummy_acl;
+ struct posix_acl_xattr_header dummy_acl;
p = fs_path_alloc();
if (!p)
@@ -4398,12 +4404,8 @@ static int process_new_xattr(struct send_ctx *sctx)
static int process_deleted_xattr(struct send_ctx *sctx)
{
- int ret;
-
- ret = iterate_dir_item(sctx->parent_root, sctx->right_path,
- sctx->cmp_key, __process_deleted_xattr, sctx);
-
- return ret;
+ return iterate_dir_item(sctx->parent_root, sctx->right_path,
+ sctx->cmp_key, __process_deleted_xattr, sctx);
}
struct find_xattr_ctx {
@@ -4664,6 +4666,7 @@ out:
*/
static int send_write(struct send_ctx *sctx, u64 offset, u32 len)
{
+ struct btrfs_fs_info *fs_info = sctx->send_root->fs_info;
int ret = 0;
struct fs_path *p;
ssize_t num_read = 0;
@@ -4672,7 +4675,7 @@ static int send_write(struct send_ctx *sctx, u64 offset, u32 len)
if (!p)
return -ENOMEM;
-verbose_printk("btrfs: send_write offset=%llu, len=%d\n", offset, len);
+ btrfs_debug(fs_info, "send_write offset=%llu, len=%d", offset, len);
num_read = fill_read_buf(sctx, offset, len);
if (num_read <= 0) {
@@ -4714,10 +4717,10 @@ static int send_clone(struct send_ctx *sctx,
struct fs_path *p;
u64 gen;
-verbose_printk("btrfs: send_clone offset=%llu, len=%d, clone_root=%llu, "
- "clone_inode=%llu, clone_offset=%llu\n", offset, len,
- clone_root->root->objectid, clone_root->ino,
- clone_root->offset);
+ btrfs_debug(sctx->send_root->fs_info,
+ "send_clone offset=%llu, len=%d, clone_root=%llu, clone_inode=%llu, clone_offset=%llu",
+ offset, len, clone_root->root->objectid, clone_root->ino,
+ clone_root->offset);
p = fs_path_alloc();
if (!p)
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 4071fe2bd098..74ed5aae6cea 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -151,12 +151,11 @@ void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function
vaf.fmt = fmt;
vaf.va = &args;
- printk(KERN_CRIT
- "BTRFS: error (device %s) in %s:%d: errno=%d %s (%pV)\n",
+ pr_crit("BTRFS: error (device %s) in %s:%d: errno=%d %s (%pV)\n",
sb->s_id, function, line, errno, errstr, &vaf);
va_end(args);
} else {
- printk(KERN_CRIT "BTRFS: error (device %s) in %s:%d: errno=%d %s\n",
+ pr_crit("BTRFS: error (device %s) in %s:%d: errno=%d %s\n",
sb->s_id, function, line, errno, errstr);
}
#endif
@@ -462,9 +461,11 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
case Opt_datasum:
if (btrfs_test_opt(info, NODATASUM)) {
if (btrfs_test_opt(info, NODATACOW))
- btrfs_info(root->fs_info, "setting datasum, datacow enabled");
+ btrfs_info(root->fs_info,
+ "setting datasum, datacow enabled");
else
- btrfs_info(root->fs_info, "setting datasum");
+ btrfs_info(root->fs_info,
+ "setting datasum");
}
btrfs_clear_opt(info->mount_opt, NODATACOW);
btrfs_clear_opt(info->mount_opt, NODATASUM);
@@ -476,7 +477,8 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
btrfs_info(root->fs_info,
"setting nodatacow, compression disabled");
} else {
- btrfs_info(root->fs_info, "setting nodatacow");
+ btrfs_info(root->fs_info,
+ "setting nodatacow");
}
}
btrfs_clear_opt(info->mount_opt, COMPRESS);
@@ -608,8 +610,9 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
info->alloc_start = memparse(num, NULL);
mutex_unlock(&info->chunk_mutex);
kfree(num);
- btrfs_info(root->fs_info, "allocations start at %llu",
- info->alloc_start);
+ btrfs_info(root->fs_info,
+ "allocations start at %llu",
+ info->alloc_start);
} else {
ret = -ENOMEM;
goto out;
@@ -762,8 +765,9 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
goto out;
} else if (intarg >= 0) {
info->check_integrity_print_mask = intarg;
- btrfs_info(root->fs_info, "check_integrity_print_mask 0x%x",
- info->check_integrity_print_mask);
+ btrfs_info(root->fs_info,
+ "check_integrity_print_mask 0x%x",
+ info->check_integrity_print_mask);
} else {
ret = -EINVAL;
goto out;
@@ -794,19 +798,22 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
intarg = 0;
ret = match_int(&args[0], &intarg);
if (ret < 0) {
- btrfs_err(root->fs_info, "invalid commit interval");
+ btrfs_err(root->fs_info,
+ "invalid commit interval");
ret = -EINVAL;
goto out;
}
if (intarg > 0) {
if (intarg > 300) {
- btrfs_warn(root->fs_info, "excessive commit interval %d",
- intarg);
+ btrfs_warn(root->fs_info,
+ "excessive commit interval %d",
+ intarg);
}
info->commit_interval = intarg;
} else {
- btrfs_info(root->fs_info, "using default commit interval %ds",
- BTRFS_DEFAULT_COMMIT_INTERVAL);
+ btrfs_info(root->fs_info,
+ "using default commit interval %ds",
+ BTRFS_DEFAULT_COMMIT_INTERVAL);
info->commit_interval = BTRFS_DEFAULT_COMMIT_INTERVAL;
}
break;
@@ -827,7 +834,8 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
break;
#endif
case Opt_err:
- btrfs_info(root->fs_info, "unrecognized mount option '%s'", p);
+ btrfs_info(root->fs_info,
+ "unrecognized mount option '%s'", p);
ret = -EINVAL;
goto out;
default:
@@ -916,9 +924,7 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
}
break;
case Opt_subvolrootid:
- printk(KERN_WARNING
- "BTRFS: 'subvolrootid' mount option is deprecated and has "
- "no effect\n");
+ pr_warn("BTRFS: 'subvolrootid' mount option is deprecated and has no effect\n");
break;
case Opt_device:
device_name = match_strdup(&args[0]);
@@ -1142,7 +1148,7 @@ static int btrfs_fill_super(struct super_block *sb,
sb->s_iflags |= SB_I_CGROUPWB;
err = open_ctree(sb, fs_devices, (char *)data);
if (err) {
- printk(KERN_ERR "BTRFS: open_ctree failed\n");
+ btrfs_err(fs_info, "open_ctree failed");
return err;
}
@@ -1440,12 +1446,13 @@ static struct dentry *mount_subvol(const char *subvol_name, u64 subvol_objectid,
if (!IS_ERR(root)) {
struct super_block *s = root->d_sb;
+ struct btrfs_fs_info *fs_info = btrfs_sb(s);
struct inode *root_inode = d_inode(root);
u64 root_objectid = BTRFS_I(root_inode)->root->root_key.objectid;
ret = 0;
if (!is_subvolume_inode(root_inode)) {
- pr_err("BTRFS: '%s' is not a valid subvolume\n",
+ btrfs_err(fs_info, "'%s' is not a valid subvolume",
subvol_name);
ret = -EINVAL;
}
@@ -1455,8 +1462,9 @@ static struct dentry *mount_subvol(const char *subvol_name, u64 subvol_objectid,
* subvolume which was passed by ID is renamed and
* another subvolume is renamed over the old location.
*/
- pr_err("BTRFS: subvol '%s' does not match subvolid %llu\n",
- subvol_name, subvol_objectid);
+ btrfs_err(fs_info,
+ "subvol '%s' does not match subvolid %llu",
+ subvol_name, subvol_objectid);
ret = -EINVAL;
}
if (ret) {
@@ -1830,13 +1838,15 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
btrfs_info(fs_info, "creating UUID tree");
ret = btrfs_create_uuid_tree(fs_info);
if (ret) {
- btrfs_warn(fs_info, "failed to create the UUID tree %d", ret);
+ btrfs_warn(fs_info,
+ "failed to create the UUID tree %d",
+ ret);
goto restore;
}
}
sb->s_flags &= ~MS_RDONLY;
- fs_info->open = 1;
+ set_bit(BTRFS_FS_OPEN, &fs_info->flags);
}
out:
wake_up_process(fs_info->transaction_kthread);
@@ -2346,7 +2356,7 @@ static void btrfs_interface_exit(void)
static void btrfs_print_mod_info(void)
{
- printk(KERN_INFO "Btrfs loaded, crc32c=%s"
+ pr_info("Btrfs loaded, crc32c=%s"
#ifdef CONFIG_BTRFS_DEBUG
", debug=on"
#endif
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index c6569905d3d1..1f157fba8940 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -77,7 +77,7 @@ static int can_modify_feature(struct btrfs_feature_attr *fa)
clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR;
break;
default:
- printk(KERN_WARNING "btrfs: sysfs: unknown feature set %d\n",
+ pr_warn("btrfs: sysfs: unknown feature set %d\n",
fa->feature_set);
return 0;
}
@@ -430,7 +430,8 @@ static ssize_t btrfs_sectorsize_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
- return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->sectorsize);
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ fs_info->super_copy->sectorsize);
}
BTRFS_ATTR(sectorsize, btrfs_sectorsize_show);
@@ -440,7 +441,8 @@ static ssize_t btrfs_clone_alignment_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
- return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->sectorsize);
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ fs_info->super_copy->sectorsize);
}
BTRFS_ATTR(clone_alignment, btrfs_clone_alignment_show);
@@ -836,9 +838,18 @@ static int btrfs_init_debugfs(void)
if (!btrfs_debugfs_root_dentry)
return -ENOMEM;
- debugfs_create_u64("test", S_IRUGO | S_IWUGO, btrfs_debugfs_root_dentry,
+ /*
+ * Example code, how to export data through debugfs.
+ *
+ * file: /sys/kernel/debug/btrfs/test
+ * contents of: btrfs_debugfs_test
+ */
+#ifdef CONFIG_BTRFS_DEBUG
+ debugfs_create_u64("test", S_IRUGO | S_IWUSR, btrfs_debugfs_root_dentry,
&btrfs_debugfs_test);
#endif
+
+#endif
return 0;
}
diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c
index d19ab0317283..caad80bb9bd0 100644
--- a/fs/btrfs/tests/extent-io-tests.c
+++ b/fs/btrfs/tests/extent-io-tests.c
@@ -273,20 +273,37 @@ out:
return ret;
}
-/**
- * test_bit_in_byte - Determine whether a bit is set in a byte
- * @nr: bit number to test
- * @addr: Address to start counting from
- */
-static inline int test_bit_in_byte(int nr, const u8 *addr)
+static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb,
+ unsigned long len)
{
- return 1UL & (addr[nr / BITS_PER_BYTE] >> (nr & (BITS_PER_BYTE - 1)));
+ unsigned long i;
+
+ for (i = 0; i < len * BITS_PER_BYTE; i++) {
+ int bit, bit1;
+
+ bit = !!test_bit(i, bitmap);
+ bit1 = !!extent_buffer_test_bit(eb, 0, i);
+ if (bit1 != bit) {
+ test_msg("Bits do not match\n");
+ return -EINVAL;
+ }
+
+ bit1 = !!extent_buffer_test_bit(eb, i / BITS_PER_BYTE,
+ i % BITS_PER_BYTE);
+ if (bit1 != bit) {
+ test_msg("Offset bits do not match\n");
+ return -EINVAL;
+ }
+ }
+ return 0;
}
static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
unsigned long len)
{
- unsigned long i, x;
+ unsigned long i, j;
+ u32 x;
+ int ret;
memset(bitmap, 0, len);
memset_extent_buffer(eb, 0, 0, len);
@@ -297,16 +314,18 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
bitmap_set(bitmap, 0, len * BITS_PER_BYTE);
extent_buffer_bitmap_set(eb, 0, 0, len * BITS_PER_BYTE);
- if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
+ ret = check_eb_bitmap(bitmap, eb, len);
+ if (ret) {
test_msg("Setting all bits failed\n");
- return -EINVAL;
+ return ret;
}
bitmap_clear(bitmap, 0, len * BITS_PER_BYTE);
extent_buffer_bitmap_clear(eb, 0, 0, len * BITS_PER_BYTE);
- if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
+ ret = check_eb_bitmap(bitmap, eb, len);
+ if (ret) {
test_msg("Clearing all bits failed\n");
- return -EINVAL;
+ return ret;
}
/* Straddling pages test */
@@ -316,9 +335,10 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
sizeof(long) * BITS_PER_BYTE);
extent_buffer_bitmap_set(eb, PAGE_SIZE - sizeof(long) / 2, 0,
sizeof(long) * BITS_PER_BYTE);
- if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
+ ret = check_eb_bitmap(bitmap, eb, len);
+ if (ret) {
test_msg("Setting straddling pages failed\n");
- return -EINVAL;
+ return ret;
}
bitmap_set(bitmap, 0, len * BITS_PER_BYTE);
@@ -328,9 +348,10 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
extent_buffer_bitmap_set(eb, 0, 0, len * BITS_PER_BYTE);
extent_buffer_bitmap_clear(eb, PAGE_SIZE - sizeof(long) / 2, 0,
sizeof(long) * BITS_PER_BYTE);
- if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
+ ret = check_eb_bitmap(bitmap, eb, len);
+ if (ret) {
test_msg("Clearing straddling pages failed\n");
- return -EINVAL;
+ return ret;
}
}
@@ -339,28 +360,22 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
* something repetitive that could miss some hypothetical off-by-n bug.
*/
x = 0;
- for (i = 0; i < len / sizeof(long); i++) {
- x = (0x19660dULL * (u64)x + 0x3c6ef35fULL) & 0xffffffffUL;
- bitmap[i] = x;
- }
- write_extent_buffer(eb, bitmap, 0, len);
-
- for (i = 0; i < len * BITS_PER_BYTE; i++) {
- int bit, bit1;
-
- bit = !!test_bit_in_byte(i, (u8 *)bitmap);
- bit1 = !!extent_buffer_test_bit(eb, 0, i);
- if (bit1 != bit) {
- test_msg("Testing bit pattern failed\n");
- return -EINVAL;
+ bitmap_clear(bitmap, 0, len * BITS_PER_BYTE);
+ extent_buffer_bitmap_clear(eb, 0, 0, len * BITS_PER_BYTE);
+ for (i = 0; i < len * BITS_PER_BYTE / 32; i++) {
+ x = (0x19660dULL * (u64)x + 0x3c6ef35fULL) & 0xffffffffU;
+ for (j = 0; j < 32; j++) {
+ if (x & (1U << j)) {
+ bitmap_set(bitmap, i * 32 + j, 1);
+ extent_buffer_bitmap_set(eb, 0, i * 32 + j, 1);
+ }
}
+ }
- bit1 = !!extent_buffer_test_bit(eb, i / BITS_PER_BYTE,
- i % BITS_PER_BYTE);
- if (bit1 != bit) {
- test_msg("Testing bit pattern with offset failed\n");
- return -EINVAL;
- }
+ ret = check_eb_bitmap(bitmap, eb, len);
+ if (ret) {
+ test_msg("Random bit pattern failed\n");
+ return ret;
}
return 0;
diff --git a/fs/btrfs/tests/free-space-tree-tests.c b/fs/btrfs/tests/free-space-tree-tests.c
index 7508d3b42780..6e144048a72e 100644
--- a/fs/btrfs/tests/free-space-tree-tests.c
+++ b/fs/btrfs/tests/free-space-tree-tests.c
@@ -24,20 +24,15 @@
#include "../transaction.h"
struct free_space_extent {
- u64 start, length;
+ u64 start;
+ u64 length;
};
-/*
- * The test cases align their operations to this in order to hit some of the
- * edge cases in the bitmap code.
- */
-#define BITMAP_RANGE (BTRFS_FREE_SPACE_BITMAP_BITS * PAGE_SIZE)
-
static int __check_free_space_extents(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache,
struct btrfs_path *path,
- struct free_space_extent *extents,
+ const struct free_space_extent * const extents,
unsigned int num_extents)
{
struct btrfs_free_space_info *info;
@@ -126,7 +121,7 @@ static int check_free_space_extents(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache,
struct btrfs_path *path,
- struct free_space_extent *extents,
+ const struct free_space_extent * const extents,
unsigned int num_extents)
{
struct btrfs_free_space_info *info;
@@ -168,9 +163,10 @@ static int check_free_space_extents(struct btrfs_trans_handle *trans,
static int test_empty_block_group(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache,
- struct btrfs_path *path)
+ struct btrfs_path *path,
+ u32 alignment)
{
- struct free_space_extent extents[] = {
+ const struct free_space_extent extents[] = {
{cache->key.objectid, cache->key.offset},
};
@@ -181,9 +177,10 @@ static int test_empty_block_group(struct btrfs_trans_handle *trans,
static int test_remove_all(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache,
- struct btrfs_path *path)
+ struct btrfs_path *path,
+ u32 alignment)
{
- struct free_space_extent extents[] = {};
+ const struct free_space_extent extents[] = {};
int ret;
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
@@ -201,16 +198,17 @@ static int test_remove_all(struct btrfs_trans_handle *trans,
static int test_remove_beginning(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache,
- struct btrfs_path *path)
+ struct btrfs_path *path,
+ u32 alignment)
{
- struct free_space_extent extents[] = {
- {cache->key.objectid + BITMAP_RANGE,
- cache->key.offset - BITMAP_RANGE},
+ const struct free_space_extent extents[] = {
+ {cache->key.objectid + alignment,
+ cache->key.offset - alignment},
};
int ret;
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
- cache->key.objectid, BITMAP_RANGE);
+ cache->key.objectid, alignment);
if (ret) {
test_msg("Could not remove free space\n");
return ret;
@@ -224,17 +222,18 @@ static int test_remove_beginning(struct btrfs_trans_handle *trans,
static int test_remove_end(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache,
- struct btrfs_path *path)
+ struct btrfs_path *path,
+ u32 alignment)
{
- struct free_space_extent extents[] = {
- {cache->key.objectid, cache->key.offset - BITMAP_RANGE},
+ const struct free_space_extent extents[] = {
+ {cache->key.objectid, cache->key.offset - alignment},
};
int ret;
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
cache->key.objectid +
- cache->key.offset - BITMAP_RANGE,
- BITMAP_RANGE);
+ cache->key.offset - alignment,
+ alignment);
if (ret) {
test_msg("Could not remove free space\n");
return ret;
@@ -247,18 +246,19 @@ static int test_remove_end(struct btrfs_trans_handle *trans,
static int test_remove_middle(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache,
- struct btrfs_path *path)
+ struct btrfs_path *path,
+ u32 alignment)
{
- struct free_space_extent extents[] = {
- {cache->key.objectid, BITMAP_RANGE},
- {cache->key.objectid + 2 * BITMAP_RANGE,
- cache->key.offset - 2 * BITMAP_RANGE},
+ const struct free_space_extent extents[] = {
+ {cache->key.objectid, alignment},
+ {cache->key.objectid + 2 * alignment,
+ cache->key.offset - 2 * alignment},
};
int ret;
ret = __remove_from_free_space_tree(trans, fs_info, cache, path,
- cache->key.objectid + BITMAP_RANGE,
- BITMAP_RANGE);
+ cache->key.objectid + alignment,
+ alignment);
if (ret) {
test_msg("Could not remove free space\n");
return ret;
@@ -271,10 +271,11 @@ static int test_remove_middle(struct btrfs_trans_handle *trans,
static int test_merge_left(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache,
- struct btrfs_path *path)
+ struct btrfs_path *path,
+ u32 alignment)
{
- struct free_space_extent extents[] = {
- {cache->key.objectid, 2 * BITMAP_RANGE},
+ const struct free_space_extent extents[] = {
+ {cache->key.objectid, 2 * alignment},
};
int ret;
@@ -287,15 +288,15 @@ static int test_merge_left(struct btrfs_trans_handle *trans,
}
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
- cache->key.objectid, BITMAP_RANGE);
+ cache->key.objectid, alignment);
if (ret) {
test_msg("Could not add free space\n");
return ret;
}
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
- cache->key.objectid + BITMAP_RANGE,
- BITMAP_RANGE);
+ cache->key.objectid + alignment,
+ alignment);
if (ret) {
test_msg("Could not add free space\n");
return ret;
@@ -308,10 +309,11 @@ static int test_merge_left(struct btrfs_trans_handle *trans,
static int test_merge_right(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache,
- struct btrfs_path *path)
+ struct btrfs_path *path,
+ u32 alignment)
{
- struct free_space_extent extents[] = {
- {cache->key.objectid + BITMAP_RANGE, 2 * BITMAP_RANGE},
+ const struct free_space_extent extents[] = {
+ {cache->key.objectid + alignment, 2 * alignment},
};
int ret;
@@ -324,16 +326,16 @@ static int test_merge_right(struct btrfs_trans_handle *trans,
}
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
- cache->key.objectid + 2 * BITMAP_RANGE,
- BITMAP_RANGE);
+ cache->key.objectid + 2 * alignment,
+ alignment);
if (ret) {
test_msg("Could not add free space\n");
return ret;
}
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
- cache->key.objectid + BITMAP_RANGE,
- BITMAP_RANGE);
+ cache->key.objectid + alignment,
+ alignment);
if (ret) {
test_msg("Could not add free space\n");
return ret;
@@ -346,10 +348,11 @@ static int test_merge_right(struct btrfs_trans_handle *trans,
static int test_merge_both(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache,
- struct btrfs_path *path)
+ struct btrfs_path *path,
+ u32 alignment)
{
- struct free_space_extent extents[] = {
- {cache->key.objectid, 3 * BITMAP_RANGE},
+ const struct free_space_extent extents[] = {
+ {cache->key.objectid, 3 * alignment},
};
int ret;
@@ -362,23 +365,23 @@ static int test_merge_both(struct btrfs_trans_handle *trans,
}
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
- cache->key.objectid, BITMAP_RANGE);
+ cache->key.objectid, alignment);
if (ret) {
test_msg("Could not add free space\n");
return ret;
}
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
- cache->key.objectid + 2 * BITMAP_RANGE,
- BITMAP_RANGE);
+ cache->key.objectid + 2 * alignment,
+ alignment);
if (ret) {
test_msg("Could not add free space\n");
return ret;
}
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
- cache->key.objectid + BITMAP_RANGE,
- BITMAP_RANGE);
+ cache->key.objectid + alignment,
+ alignment);
if (ret) {
test_msg("Could not add free space\n");
return ret;
@@ -391,12 +394,13 @@ static int test_merge_both(struct btrfs_trans_handle *trans,
static int test_merge_none(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache,
- struct btrfs_path *path)
+ struct btrfs_path *path,
+ u32 alignment)
{
- struct free_space_extent extents[] = {
- {cache->key.objectid, BITMAP_RANGE},
- {cache->key.objectid + 2 * BITMAP_RANGE, BITMAP_RANGE},
- {cache->key.objectid + 4 * BITMAP_RANGE, BITMAP_RANGE},
+ const struct free_space_extent extents[] = {
+ {cache->key.objectid, alignment},
+ {cache->key.objectid + 2 * alignment, alignment},
+ {cache->key.objectid + 4 * alignment, alignment},
};
int ret;
@@ -409,23 +413,23 @@ static int test_merge_none(struct btrfs_trans_handle *trans,
}
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
- cache->key.objectid, BITMAP_RANGE);
+ cache->key.objectid, alignment);
if (ret) {
test_msg("Could not add free space\n");
return ret;
}
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
- cache->key.objectid + 4 * BITMAP_RANGE,
- BITMAP_RANGE);
+ cache->key.objectid + 4 * alignment,
+ alignment);
if (ret) {
test_msg("Could not add free space\n");
return ret;
}
ret = __add_to_free_space_tree(trans, fs_info, cache, path,
- cache->key.objectid + 2 * BITMAP_RANGE,
- BITMAP_RANGE);
+ cache->key.objectid + 2 * alignment,
+ alignment);
if (ret) {
test_msg("Could not add free space\n");
return ret;
@@ -438,10 +442,11 @@ static int test_merge_none(struct btrfs_trans_handle *trans,
typedef int (*test_func_t)(struct btrfs_trans_handle *,
struct btrfs_fs_info *,
struct btrfs_block_group_cache *,
- struct btrfs_path *);
+ struct btrfs_path *,
+ u32 alignment);
-static int run_test(test_func_t test_func, int bitmaps,
- u32 sectorsize, u32 nodesize)
+static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize,
+ u32 nodesize, u32 alignment)
{
struct btrfs_fs_info *fs_info;
struct btrfs_root *root = NULL;
@@ -480,7 +485,7 @@ static int run_test(test_func_t test_func, int bitmaps,
btrfs_set_header_nritems(root->node, 0);
root->alloc_bytenr += 2 * nodesize;
- cache = btrfs_alloc_dummy_block_group(8 * BITMAP_RANGE, sectorsize);
+ cache = btrfs_alloc_dummy_block_group(8 * alignment, sectorsize);
if (!cache) {
test_msg("Couldn't allocate dummy block group cache\n");
ret = -ENOMEM;
@@ -514,7 +519,7 @@ static int run_test(test_func_t test_func, int bitmaps,
}
}
- ret = test_func(&trans, root->fs_info, cache, path);
+ ret = test_func(&trans, root->fs_info, cache, path, alignment);
if (ret)
goto out;
@@ -539,15 +544,27 @@ out:
return ret;
}
-static int run_test_both_formats(test_func_t test_func,
- u32 sectorsize, u32 nodesize)
+static int run_test_both_formats(test_func_t test_func, u32 sectorsize,
+ u32 nodesize, u32 alignment)
{
+ int test_ret = 0;
int ret;
- ret = run_test(test_func, 0, sectorsize, nodesize);
- if (ret)
- return ret;
- return run_test(test_func, 1, sectorsize, nodesize);
+ ret = run_test(test_func, 0, sectorsize, nodesize, alignment);
+ if (ret) {
+ test_msg("%pf failed with extents, sectorsize=%u, nodesize=%u, alignment=%u\n",
+ test_func, sectorsize, nodesize, alignment);
+ test_ret = ret;
+ }
+
+ ret = run_test(test_func, 1, sectorsize, nodesize, alignment);
+ if (ret) {
+ test_msg("%pf failed with bitmaps, sectorsize=%u, nodesize=%u, alignment=%u\n",
+ test_func, sectorsize, nodesize, alignment);
+ test_ret = ret;
+ }
+
+ return test_ret;
}
int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize)
@@ -563,18 +580,30 @@ int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize)
test_merge_both,
test_merge_none,
};
+ u32 bitmap_alignment;
+ int test_ret = 0;
int i;
+ /*
+ * Align some operations to a page to flush out bugs in the extent
+ * buffer bitmap handling of highmem.
+ */
+ bitmap_alignment = BTRFS_FREE_SPACE_BITMAP_BITS * PAGE_SIZE;
+
test_msg("Running free space tree tests\n");
for (i = 0; i < ARRAY_SIZE(tests); i++) {
- int ret = run_test_both_formats(tests[i], sectorsize,
- nodesize);
- if (ret) {
- test_msg("%pf : sectorsize %u failed\n",
- tests[i], sectorsize);
- return ret;
- }
+ int ret;
+
+ ret = run_test_both_formats(tests[i], sectorsize, nodesize,
+ sectorsize);
+ if (ret)
+ test_ret = ret;
+
+ ret = run_test_both_formats(tests[i], sectorsize, nodesize,
+ bitmap_alignment);
+ if (ret)
+ test_ret = ret;
}
- return 0;
+ return test_ret;
}
diff --git a/fs/btrfs/tests/inode-tests.c b/fs/btrfs/tests/inode-tests.c
index 9f72aeda9220..0bf46808ce8f 100644
--- a/fs/btrfs/tests/inode-tests.c
+++ b/fs/btrfs/tests/inode-tests.c
@@ -968,7 +968,7 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
/* [BTRFS_MAX_EXTENT_SIZE] */
BTRFS_I(inode)->outstanding_extents++;
ret = btrfs_set_extent_delalloc(inode, 0, BTRFS_MAX_EXTENT_SIZE - 1,
- NULL);
+ NULL, 0);
if (ret) {
test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
goto out;
@@ -984,7 +984,7 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
BTRFS_I(inode)->outstanding_extents++;
ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE,
BTRFS_MAX_EXTENT_SIZE + sectorsize - 1,
- NULL);
+ NULL, 0);
if (ret) {
test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
goto out;
@@ -1019,7 +1019,7 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE >> 1,
(BTRFS_MAX_EXTENT_SIZE >> 1)
+ sectorsize - 1,
- NULL);
+ NULL, 0);
if (ret) {
test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
goto out;
@@ -1042,7 +1042,7 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
ret = btrfs_set_extent_delalloc(inode,
BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize,
(BTRFS_MAX_EXTENT_SIZE << 1) + 3 * sectorsize - 1,
- NULL);
+ NULL, 0);
if (ret) {
test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
goto out;
@@ -1060,7 +1060,7 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
BTRFS_I(inode)->outstanding_extents++;
ret = btrfs_set_extent_delalloc(inode,
BTRFS_MAX_EXTENT_SIZE + sectorsize,
- BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, NULL);
+ BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, NULL, 0);
if (ret) {
test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
goto out;
@@ -1097,7 +1097,7 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
BTRFS_I(inode)->outstanding_extents++;
ret = btrfs_set_extent_delalloc(inode,
BTRFS_MAX_EXTENT_SIZE + sectorsize,
- BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, NULL);
+ BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, NULL, 0);
if (ret) {
test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
goto out;
diff --git a/fs/btrfs/tests/qgroup-tests.c b/fs/btrfs/tests/qgroup-tests.c
index 4407fef7c16c..ca7cb5e6d385 100644
--- a/fs/btrfs/tests/qgroup-tests.c
+++ b/fs/btrfs/tests/qgroup-tests.c
@@ -480,7 +480,7 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
*/
root->fs_info->tree_root = root;
root->fs_info->quota_root = root;
- root->fs_info->quota_enabled = 1;
+ set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
/*
* Can't use bytenr 0, some things freak out
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 95d41919d034..9517de0e668c 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -65,8 +65,9 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction)
BUG_ON(!list_empty(&transaction->list));
WARN_ON(!RB_EMPTY_ROOT(&transaction->delayed_refs.href_root));
if (transaction->delayed_refs.pending_csums)
- printk(KERN_ERR "pending csums is %llu\n",
- transaction->delayed_refs.pending_csums);
+ btrfs_err(transaction->fs_info,
+ "pending csums is %llu",
+ transaction->delayed_refs.pending_csums);
while (!list_empty(&transaction->pending_chunks)) {
struct extent_map *em;
@@ -245,6 +246,7 @@ loop:
return -EROFS;
}
+ cur_trans->fs_info = fs_info;
atomic_set(&cur_trans->num_writers, 1);
extwriter_counter_init(cur_trans, type);
init_waitqueue_head(&cur_trans->writer_wait);
@@ -272,11 +274,9 @@ loop:
*/
smp_mb();
if (!list_empty(&fs_info->tree_mod_seq_list))
- WARN(1, KERN_ERR "BTRFS: tree_mod_seq_list not empty when "
- "creating a fresh transaction\n");
+ WARN(1, KERN_ERR "BTRFS: tree_mod_seq_list not empty when creating a fresh transaction\n");
if (!RB_EMPTY_ROOT(&fs_info->tree_mod_log))
- WARN(1, KERN_ERR "BTRFS: tree_mod_log rb tree not empty when "
- "creating a fresh transaction\n");
+ WARN(1, KERN_ERR "BTRFS: tree_mod_log rb tree not empty when creating a fresh transaction\n");
atomic64_set(&fs_info->tree_mod_seq, 0);
spin_lock_init(&cur_trans->delayed_refs.lock);
@@ -441,7 +441,7 @@ static void wait_current_trans(struct btrfs_root *root)
static int may_wait_transaction(struct btrfs_root *root, int type)
{
- if (root->fs_info->log_root_recovering)
+ if (test_bit(BTRFS_FS_LOG_RECOVERING, &root->fs_info->flags))
return 0;
if (type == TRANS_USERSPACE)
@@ -549,11 +549,8 @@ again:
}
} while (ret == -EBUSY);
- if (ret < 0) {
- /* We must get the transaction if we are JOIN_NOLOCK. */
- BUG_ON(type == TRANS_JOIN_NOLOCK);
+ if (ret < 0)
goto join_fail;
- }
cur_trans = root->fs_info->running_transaction;
@@ -993,7 +990,6 @@ int btrfs_wait_marked_extents(struct btrfs_root *root,
struct extent_state *cached_state = NULL;
u64 start = 0;
u64 end;
- struct btrfs_inode *btree_ino = BTRFS_I(root->fs_info->btree_inode);
bool errors = false;
while (!find_first_extent_bit(dirty_pages, start, &start, &end,
@@ -1025,17 +1021,17 @@ int btrfs_wait_marked_extents(struct btrfs_root *root,
if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
if ((mark & EXTENT_DIRTY) &&
- test_and_clear_bit(BTRFS_INODE_BTREE_LOG1_ERR,
- &btree_ino->runtime_flags))
+ test_and_clear_bit(BTRFS_FS_LOG1_ERR,
+ &root->fs_info->flags))
errors = true;
if ((mark & EXTENT_NEW) &&
- test_and_clear_bit(BTRFS_INODE_BTREE_LOG2_ERR,
- &btree_ino->runtime_flags))
+ test_and_clear_bit(BTRFS_FS_LOG2_ERR,
+ &root->fs_info->flags))
errors = true;
} else {
- if (test_and_clear_bit(BTRFS_INODE_BTREE_ERR,
- &btree_ino->runtime_flags))
+ if (test_and_clear_bit(BTRFS_FS_BTREE_ERR,
+ &root->fs_info->flags))
errors = true;
}
@@ -1300,11 +1296,11 @@ int btrfs_defrag_root(struct btrfs_root *root)
btrfs_btree_balance_dirty(info->tree_root);
cond_resched();
- if (btrfs_fs_closing(root->fs_info) || ret != -EAGAIN)
+ if (btrfs_fs_closing(info) || ret != -EAGAIN)
break;
- if (btrfs_defrag_cancelled(root->fs_info)) {
- pr_debug("BTRFS: defrag_root cancelled\n");
+ if (btrfs_defrag_cancelled(info)) {
+ btrfs_debug(info, "defrag_root cancelled");
ret = -EAGAIN;
break;
}
@@ -1335,7 +1331,7 @@ static int qgroup_account_snapshot(struct btrfs_trans_handle *trans,
* kick in anyway.
*/
mutex_lock(&fs_info->qgroup_ioctl_lock);
- if (!fs_info->quota_enabled) {
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) {
mutex_unlock(&fs_info->qgroup_ioctl_lock);
return 0;
}
@@ -1474,7 +1470,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
parent_root = BTRFS_I(parent_inode)->root;
record_root_in_trans(trans, parent_root, 0);
- cur_time = current_fs_time(parent_inode->i_sb);
+ cur_time = current_time(parent_inode);
/*
* insert the directory item
@@ -1630,7 +1626,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
btrfs_i_size_write(parent_inode, parent_inode->i_size +
dentry->d_name.len * 2);
parent_inode->i_mtime = parent_inode->i_ctime =
- current_fs_time(parent_inode->i_sb);
+ current_time(parent_inode);
ret = btrfs_update_inode_fallback(trans, parent_root, parent_inode);
if (ret) {
btrfs_abort_transaction(trans, ret);
@@ -1712,7 +1708,7 @@ static void update_super_roots(struct btrfs_root *root)
super->root_level = root_item->level;
if (btrfs_test_opt(root->fs_info, SPACE_CACHE))
super->cache_generation = root_item->generation;
- if (root->fs_info->update_uuid_tree_gen)
+ if (test_bit(BTRFS_FS_UPDATE_UUID_TREE_GEN, &root->fs_info->flags))
super->uuid_tree_generation = root_item->generation;
}
@@ -1919,7 +1915,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
{
struct btrfs_transaction *cur_trans = trans->transaction;
struct btrfs_transaction *prev_trans = NULL;
- struct btrfs_inode *btree_ino = BTRFS_I(root->fs_info->btree_inode);
int ret;
/* Stop the commit early if ->aborted is set */
@@ -2213,8 +2208,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
btrfs_update_commit_device_size(root->fs_info);
btrfs_update_commit_device_bytes_used(root, cur_trans);
- clear_bit(BTRFS_INODE_BTREE_LOG1_ERR, &btree_ino->runtime_flags);
- clear_bit(BTRFS_INODE_BTREE_LOG2_ERR, &btree_ino->runtime_flags);
+ clear_bit(BTRFS_FS_LOG1_ERR, &root->fs_info->flags);
+ clear_bit(BTRFS_FS_LOG2_ERR, &root->fs_info->flags);
btrfs_trans_release_chunk_metadata(trans);
@@ -2328,7 +2323,7 @@ int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root)
list_del_init(&root->root_list);
spin_unlock(&fs_info->trans_lock);
- pr_debug("BTRFS: cleaner removing %llu\n", root->objectid);
+ btrfs_debug(fs_info, "cleaner removing %llu", root->objectid);
btrfs_kill_all_delayed_nodes(root);
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index efb122643380..6cf0d37d4f76 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -82,6 +82,7 @@ struct btrfs_transaction {
spinlock_t dropped_roots_lock;
struct btrfs_delayed_ref_root delayed_refs;
int aborted;
+ struct btrfs_fs_info *fs_info;
};
#define __TRANS_FREEZABLE (1U << 0)
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index ef9c55bc7907..528cae123dc9 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -3961,7 +3961,7 @@ static int wait_ordered_extents(struct btrfs_trans_handle *trans,
* i_mapping flags, so that the next fsync won't get
* an outdated io error too.
*/
- btrfs_inode_check_errors(inode);
+ filemap_check_errors(inode->i_mapping);
*ordered_io_error = true;
break;
}
@@ -4198,7 +4198,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
* without writing to the log tree and the fsync must report the
* file data write error and not commit the current transaction.
*/
- ret = btrfs_inode_check_errors(inode);
+ ret = filemap_check_errors(inode->i_mapping);
if (ret)
ctx->io_err = ret;
process:
@@ -5579,7 +5579,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
if (!path)
return -ENOMEM;
- fs_info->log_root_recovering = 1;
+ set_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags);
trans = btrfs_start_transaction(fs_info->tree_root, 0);
if (IS_ERR(trans)) {
@@ -5592,8 +5592,8 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
ret = walk_log_tree(trans, log_root_tree, &wc);
if (ret) {
- btrfs_handle_fs_error(fs_info, ret, "Failed to pin buffers while "
- "recovering log root tree.");
+ btrfs_handle_fs_error(fs_info, ret,
+ "Failed to pin buffers while recovering log root tree.");
goto error;
}
@@ -5639,8 +5639,8 @@ again:
free_extent_buffer(log->node);
free_extent_buffer(log->commit_root);
kfree(log);
- btrfs_handle_fs_error(fs_info, ret, "Couldn't read target root "
- "for tree log recovery.");
+ btrfs_handle_fs_error(fs_info, ret,
+ "Couldn't read target root for tree log recovery.");
goto error;
}
@@ -5689,7 +5689,7 @@ again:
free_extent_buffer(log_root_tree->node);
log_root_tree->log_root = NULL;
- fs_info->log_root_recovering = 0;
+ clear_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags);
kfree(log_root_tree);
return 0;
diff --git a/fs/btrfs/uuid-tree.c b/fs/btrfs/uuid-tree.c
index 778282944530..7fc89e4adb41 100644
--- a/fs/btrfs/uuid-tree.c
+++ b/fs/btrfs/uuid-tree.c
@@ -69,8 +69,9 @@ static int btrfs_uuid_tree_lookup(struct btrfs_root *uuid_root, u8 *uuid,
ret = -ENOENT;
if (!IS_ALIGNED(item_size, sizeof(u64))) {
- btrfs_warn(uuid_root->fs_info, "uuid item with illegal size %lu!",
- (unsigned long)item_size);
+ btrfs_warn(uuid_root->fs_info,
+ "uuid item with illegal size %lu!",
+ (unsigned long)item_size);
goto out;
}
while (item_size) {
@@ -137,10 +138,10 @@ int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans,
offset = btrfs_item_ptr_offset(eb, slot);
offset += btrfs_item_size_nr(eb, slot) - sizeof(subid_le);
} else if (ret < 0) {
- btrfs_warn(uuid_root->fs_info, "insert uuid item failed %d "
- "(0x%016llx, 0x%016llx) type %u!",
- ret, (unsigned long long)key.objectid,
- (unsigned long long)key.offset, type);
+ btrfs_warn(uuid_root->fs_info,
+ "insert uuid item failed %d (0x%016llx, 0x%016llx) type %u!",
+ ret, (unsigned long long)key.objectid,
+ (unsigned long long)key.offset, type);
goto out;
}
@@ -184,8 +185,8 @@ int btrfs_uuid_tree_rem(struct btrfs_trans_handle *trans,
ret = btrfs_search_slot(trans, uuid_root, &key, path, -1, 1);
if (ret < 0) {
- btrfs_warn(uuid_root->fs_info, "error %d while searching for uuid item!",
- ret);
+ btrfs_warn(uuid_root->fs_info,
+ "error %d while searching for uuid item!", ret);
goto out;
}
if (ret > 0) {
@@ -198,8 +199,9 @@ int btrfs_uuid_tree_rem(struct btrfs_trans_handle *trans,
offset = btrfs_item_ptr_offset(eb, slot);
item_size = btrfs_item_size_nr(eb, slot);
if (!IS_ALIGNED(item_size, sizeof(u64))) {
- btrfs_warn(uuid_root->fs_info, "uuid item with illegal size %lu!",
- (unsigned long)item_size);
+ btrfs_warn(uuid_root->fs_info,
+ "uuid item with illegal size %lu!",
+ (unsigned long)item_size);
ret = -ENOENT;
goto out;
}
@@ -299,8 +301,9 @@ again_search_slot:
offset = btrfs_item_ptr_offset(leaf, slot);
item_size = btrfs_item_size_nr(leaf, slot);
if (!IS_ALIGNED(item_size, sizeof(u64))) {
- btrfs_warn(fs_info, "uuid item with illegal size %lu!",
- (unsigned long)item_size);
+ btrfs_warn(fs_info,
+ "uuid item with illegal size %lu!",
+ (unsigned long)item_size);
goto skip;
}
while (item_size) {
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 035efce603a9..71a60cc01451 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -859,7 +859,7 @@ static void btrfs_close_bdev(struct btrfs_device *device)
blkdev_put(device->bdev, device->mode);
}
-static void btrfs_close_one_device(struct btrfs_device *device)
+static void btrfs_prepare_close_one_device(struct btrfs_device *device)
{
struct btrfs_fs_devices *fs_devices = device->fs_devices;
struct btrfs_device *new_device;
@@ -877,8 +877,6 @@ static void btrfs_close_one_device(struct btrfs_device *device)
if (device->missing)
fs_devices->missing_devices--;
- btrfs_close_bdev(device);
-
new_device = btrfs_alloc_device(NULL, &device->devid,
device->uuid);
BUG_ON(IS_ERR(new_device)); /* -ENOMEM */
@@ -892,23 +890,39 @@ static void btrfs_close_one_device(struct btrfs_device *device)
list_replace_rcu(&device->dev_list, &new_device->dev_list);
new_device->fs_devices = device->fs_devices;
-
- call_rcu(&device->rcu, free_device);
}
static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
{
struct btrfs_device *device, *tmp;
+ struct list_head pending_put;
+
+ INIT_LIST_HEAD(&pending_put);
if (--fs_devices->opened > 0)
return 0;
mutex_lock(&fs_devices->device_list_mutex);
list_for_each_entry_safe(device, tmp, &fs_devices->devices, dev_list) {
- btrfs_close_one_device(device);
+ btrfs_prepare_close_one_device(device);
+ list_add(&device->dev_list, &pending_put);
}
mutex_unlock(&fs_devices->device_list_mutex);
+ /*
+ * btrfs_show_devname() is using the device_list_mutex,
+ * sometimes call to blkdev_put() leads vfs calling
+ * into this func. So do put outside of device_list_mutex,
+ * as of now.
+ */
+ while (!list_empty(&pending_put)) {
+ device = list_first_entry(&pending_put,
+ struct btrfs_device, dev_list);
+ list_del(&device->dev_list);
+ btrfs_close_bdev(device);
+ call_rcu(&device->rcu, free_device);
+ }
+
WARN_ON(fs_devices->open_devices);
WARN_ON(fs_devices->rw_devices);
fs_devices->opened = 0;
@@ -1140,12 +1154,12 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
ret = device_list_add(path, disk_super, devid, fs_devices_ret);
if (ret > 0) {
if (disk_super->label[0]) {
- printk(KERN_INFO "BTRFS: device label %s ", disk_super->label);
+ pr_info("BTRFS: device label %s ", disk_super->label);
} else {
- printk(KERN_INFO "BTRFS: device fsid %pU ", disk_super->fsid);
+ pr_info("BTRFS: device fsid %pU ", disk_super->fsid);
}
- printk(KERN_CONT "devid %llu transid %llu %s\n", devid, transid, path);
+ pr_cont("devid %llu transid %llu %s\n", devid, transid, path);
ret = 0;
}
if (!ret && fs_devices_ret)
@@ -1846,7 +1860,6 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid)
u64 num_devices;
int ret = 0;
bool clear_super = false;
- char *dev_name = NULL;
mutex_lock(&uuid_mutex);
@@ -1882,11 +1895,6 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid)
list_del_init(&device->dev_alloc_list);
device->fs_devices->rw_devices--;
unlock_chunks(root);
- dev_name = kstrdup(device->name->str, GFP_KERNEL);
- if (!dev_name) {
- ret = -ENOMEM;
- goto error_undo;
- }
clear_super = true;
}
@@ -1936,14 +1944,21 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid)
btrfs_sysfs_rm_device_link(root->fs_info->fs_devices, device);
}
- btrfs_close_bdev(device);
-
- call_rcu(&device->rcu, free_device);
-
num_devices = btrfs_super_num_devices(root->fs_info->super_copy) - 1;
btrfs_set_super_num_devices(root->fs_info->super_copy, num_devices);
mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
+ /*
+ * at this point, the device is zero sized and detached from
+ * the devices list. All that's left is to zero out the old
+ * supers and free the device.
+ */
+ if (device->writeable)
+ btrfs_scratch_superblocks(device->bdev, device->name->str);
+
+ btrfs_close_bdev(device);
+ call_rcu(&device->rcu, free_device);
+
if (cur_devices->open_devices == 0) {
struct btrfs_fs_devices *fs_devices;
fs_devices = root->fs_info->fs_devices;
@@ -1962,24 +1977,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid)
root->fs_info->num_tolerated_disk_barrier_failures =
btrfs_calc_num_tolerated_disk_barrier_failures(root->fs_info);
- /*
- * at this point, the device is zero sized. We want to
- * remove it from the devices list and zero out the old super
- */
- if (clear_super) {
- struct block_device *bdev;
-
- bdev = blkdev_get_by_path(dev_name, FMODE_READ | FMODE_EXCL,
- root->fs_info->bdev_holder);
- if (!IS_ERR(bdev)) {
- btrfs_scratch_superblocks(bdev, dev_name);
- blkdev_put(bdev, FMODE_READ | FMODE_EXCL);
- }
- }
-
out:
- kfree(dev_name);
-
mutex_unlock(&uuid_mutex);
return ret;
@@ -2494,9 +2492,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
ret = btrfs_relocate_sys_chunks(root);
if (ret < 0)
btrfs_handle_fs_error(root->fs_info, ret,
- "Failed to relocate sys chunks after "
- "device initialization. This can be fixed "
- "using the \"btrfs balance\" command.");
+ "Failed to relocate sys chunks after device initialization. This can be fixed using the \"btrfs balance\" command.");
trans = btrfs_attach_transaction(root);
if (IS_ERR(trans)) {
if (PTR_ERR(trans) == -ENOENT)
@@ -2555,7 +2551,8 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path,
devices = &fs_info->fs_devices->devices;
list_for_each_entry(device, devices, dev_list) {
if (device->bdev == bdev) {
- btrfs_err(fs_info, "target device is in the filesystem!");
+ btrfs_err(fs_info,
+ "target device is in the filesystem!");
ret = -EEXIST;
goto error;
}
@@ -2564,7 +2561,8 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path,
if (i_size_read(bdev->bd_inode) <
btrfs_device_get_total_bytes(srcdev)) {
- btrfs_err(fs_info, "target device is smaller than source device!");
+ btrfs_err(fs_info,
+ "target device is smaller than source device!");
ret = -EINVAL;
goto error;
}
@@ -3698,7 +3696,7 @@ error:
btrfs_free_path(path);
if (enospc_errors) {
btrfs_info(fs_info, "%d enospc errors during balance",
- enospc_errors);
+ enospc_errors);
if (!ret)
ret = -ENOSPC;
}
@@ -3792,8 +3790,8 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
if (!(bctl->flags & BTRFS_BALANCE_DATA) ||
!(bctl->flags & BTRFS_BALANCE_METADATA) ||
memcmp(&bctl->data, &bctl->meta, sizeof(bctl->data))) {
- btrfs_err(fs_info, "with mixed groups data and "
- "metadata balance options must be the same");
+ btrfs_err(fs_info,
+ "with mixed groups data and metadata balance options must be the same");
ret = -EINVAL;
goto out;
}
@@ -3815,23 +3813,23 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
allowed |= (BTRFS_BLOCK_GROUP_RAID10 |
BTRFS_BLOCK_GROUP_RAID6);
if (validate_convert_profile(&bctl->data, allowed)) {
- btrfs_err(fs_info, "unable to start balance with target "
- "data profile %llu",
- bctl->data.target);
+ btrfs_err(fs_info,
+ "unable to start balance with target data profile %llu",
+ bctl->data.target);
ret = -EINVAL;
goto out;
}
if (validate_convert_profile(&bctl->meta, allowed)) {
btrfs_err(fs_info,
- "unable to start balance with target metadata profile %llu",
- bctl->meta.target);
+ "unable to start balance with target metadata profile %llu",
+ bctl->meta.target);
ret = -EINVAL;
goto out;
}
if (validate_convert_profile(&bctl->sys, allowed)) {
btrfs_err(fs_info,
- "unable to start balance with target system profile %llu",
- bctl->sys.target);
+ "unable to start balance with target system profile %llu",
+ bctl->sys.target);
ret = -EINVAL;
goto out;
}
@@ -3851,10 +3849,11 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
(fs_info->avail_metadata_alloc_bits & allowed) &&
!(bctl->meta.target & allowed))) {
if (bctl->flags & BTRFS_BALANCE_FORCE) {
- btrfs_info(fs_info, "force reducing metadata integrity");
+ btrfs_info(fs_info,
+ "force reducing metadata integrity");
} else {
- btrfs_err(fs_info, "balance will reduce metadata "
- "integrity, use force if you want this");
+ btrfs_err(fs_info,
+ "balance will reduce metadata integrity, use force if you want this");
ret = -EINVAL;
goto out;
}
@@ -3864,8 +3863,8 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
if (btrfs_get_num_tolerated_disk_barrier_failures(bctl->meta.target) <
btrfs_get_num_tolerated_disk_barrier_failures(bctl->data.target)) {
btrfs_warn(fs_info,
- "metadata profile 0x%llx has lower redundancy than data profile 0x%llx",
- bctl->meta.target, bctl->data.target);
+ "metadata profile 0x%llx has lower redundancy than data profile 0x%llx",
+ bctl->meta.target, bctl->data.target);
}
if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
@@ -4221,7 +4220,7 @@ out:
if (ret)
btrfs_warn(fs_info, "btrfs_uuid_scan_kthread failed %d", ret);
else
- fs_info->update_uuid_tree_gen = 1;
+ set_bit(BTRFS_FS_UPDATE_UUID_TREE_GEN, &fs_info->flags);
up(&fs_info->uuid_tree_rescan_sem);
return 0;
}
@@ -4913,15 +4912,16 @@ int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans,
read_unlock(&em_tree->lock);
if (!em) {
- btrfs_crit(extent_root->fs_info, "unable to find logical "
- "%Lu len %Lu", chunk_offset, chunk_size);
+ btrfs_crit(extent_root->fs_info,
+ "unable to find logical %Lu len %Lu",
+ chunk_offset, chunk_size);
return -EINVAL;
}
if (em->start != chunk_offset || em->len != chunk_size) {
- btrfs_crit(extent_root->fs_info, "found a bad mapping, wanted"
- " %Lu-%Lu, found %Lu-%Lu", chunk_offset,
- chunk_size, em->start, em->len);
+ btrfs_crit(extent_root->fs_info,
+ "found a bad mapping, wanted %Lu-%Lu, found %Lu-%Lu",
+ chunk_offset, chunk_size, em->start, em->len);
free_extent_map(em);
return -EINVAL;
}
@@ -5154,9 +5154,9 @@ int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len)
}
if (em->start > logical || em->start + em->len < logical) {
- btrfs_crit(fs_info, "Invalid mapping for %Lu-%Lu, got "
- "%Lu-%Lu", logical, logical+len, em->start,
- em->start + em->len);
+ btrfs_crit(fs_info, "Invalid mapping for %Lu-%Lu, got %Lu-%Lu",
+ logical, logical+len, em->start,
+ em->start + em->len);
free_extent_map(em);
return 1;
}
@@ -5370,9 +5370,9 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int op,
}
if (em->start > logical || em->start + em->len < logical) {
- btrfs_crit(fs_info, "found a bad mapping, wanted %Lu, "
- "found %Lu-%Lu", logical, em->start,
- em->start + em->len);
+ btrfs_crit(fs_info,
+ "found a bad mapping, wanted %Lu, found %Lu-%Lu",
+ logical, em->start, em->start + em->len);
free_extent_map(em);
return -EINVAL;
}
@@ -5390,9 +5390,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int op,
stripe_offset = stripe_nr * stripe_len;
if (offset < stripe_offset) {
- btrfs_crit(fs_info, "stripe math has gone wrong, "
- "stripe_offset=%llu, offset=%llu, start=%llu, "
- "logical=%llu, stripe_len=%llu",
+ btrfs_crit(fs_info,
+ "stripe math has gone wrong, stripe_offset=%llu, offset=%llu, start=%llu, logical=%llu, stripe_len=%llu",
stripe_offset, offset, em->start, logical,
stripe_len);
free_extent_map(em);
@@ -5642,8 +5641,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int op,
mirror_num = stripe_index + 1;
}
if (stripe_index >= map->num_stripes) {
- btrfs_crit(fs_info, "stripe index math went horribly wrong, "
- "got stripe_index=%u, num_stripes=%u",
+ btrfs_crit(fs_info,
+ "stripe index math went horribly wrong, got stripe_index=%u, num_stripes=%u",
stripe_index, map->num_stripes);
ret = -EINVAL;
goto out;
@@ -5907,10 +5906,11 @@ int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int op,
mirror_num, need_raid_map);
}
-int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
+int btrfs_rmap_block(struct btrfs_fs_info *fs_info,
u64 chunk_start, u64 physical, u64 devid,
u64 **logical, int *naddrs, int *stripe_len)
{
+ struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
struct extent_map_tree *em_tree = &map_tree->map_tree;
struct extent_map *em;
struct map_lookup *map;
@@ -5926,13 +5926,13 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
read_unlock(&em_tree->lock);
if (!em) {
- printk(KERN_ERR "BTRFS: couldn't find em for chunk %Lu\n",
- chunk_start);
+ btrfs_err(fs_info, "couldn't find em for chunk %Lu",
+ chunk_start);
return -EIO;
}
if (em->start != chunk_start) {
- printk(KERN_ERR "BTRFS: bad chunk start, em=%Lu, wanted=%Lu\n",
+ btrfs_err(fs_info, "bad chunk start, em=%Lu, wanted=%Lu",
em->start, chunk_start);
free_extent_map(em);
return -EIO;
@@ -6137,10 +6137,12 @@ static void submit_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio,
rcu_read_lock();
name = rcu_dereference(dev->name);
- pr_debug("btrfs_map_bio: rw %d 0x%x, sector=%llu, dev=%lu "
- "(%s id %llu), size=%u\n", bio_op(bio), bio->bi_opf,
- (u64)bio->bi_iter.bi_sector, (u_long)dev->bdev->bd_dev,
- name->str, dev->devid, bio->bi_iter.bi_size);
+ btrfs_debug(fs_info,
+ "btrfs_map_bio: rw %d 0x%x, sector=%llu, dev=%lu (%s id %llu), size=%u",
+ bio_op(bio), bio->bi_opf,
+ (u64)bio->bi_iter.bi_sector,
+ (u_long)dev->bdev->bd_dev, name->str, dev->devid,
+ bio->bi_iter.bi_size);
rcu_read_unlock();
}
#endif
@@ -6215,8 +6217,9 @@ int btrfs_map_bio(struct btrfs_root *root, struct bio *bio,
}
if (map_length < length) {
- btrfs_crit(root->fs_info, "mapping failed logical %llu bio len %llu len %llu",
- logical, length, map_length);
+ btrfs_crit(root->fs_info,
+ "mapping failed logical %llu bio len %llu len %llu",
+ logical, length, map_length);
BUG();
}
@@ -6483,8 +6486,9 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
free_extent_map(em);
return -EIO;
}
- btrfs_warn(root->fs_info, "devid %llu uuid %pU is missing",
- devid, uuid);
+ btrfs_warn(root->fs_info,
+ "devid %llu uuid %pU is missing",
+ devid, uuid);
}
map->stripes[i].dev->in_fs_metadata = 1;
}
@@ -6661,7 +6665,8 @@ static int read_one_dev(struct btrfs_root *root,
int btrfs_read_sys_array(struct btrfs_root *root)
{
- struct btrfs_super_block *super_copy = root->fs_info->super_copy;
+ struct btrfs_fs_info *fs_info = root->fs_info;
+ struct btrfs_super_block *super_copy = fs_info->super_copy;
struct extent_buffer *sb;
struct btrfs_disk_key *disk_key;
struct btrfs_chunk *chunk;
@@ -6732,8 +6737,8 @@ int btrfs_read_sys_array(struct btrfs_root *root)
num_stripes = btrfs_chunk_num_stripes(sb, chunk);
if (!num_stripes) {
- printk(KERN_ERR
- "BTRFS: invalid number of stripes %u in sys_array at offset %u\n",
+ btrfs_err(fs_info,
+ "invalid number of stripes %u in sys_array at offset %u",
num_stripes, cur_offset);
ret = -EIO;
break;
@@ -6741,7 +6746,7 @@ int btrfs_read_sys_array(struct btrfs_root *root)
type = btrfs_chunk_type(sb, chunk);
if ((type & BTRFS_BLOCK_GROUP_SYSTEM) == 0) {
- btrfs_err(root->fs_info,
+ btrfs_err(fs_info,
"invalid chunk type %llu in sys_array at offset %u",
type, cur_offset);
ret = -EIO;
@@ -6756,9 +6761,9 @@ int btrfs_read_sys_array(struct btrfs_root *root)
if (ret)
break;
} else {
- printk(KERN_ERR
- "BTRFS: unexpected item type %u in sys_array at offset %u\n",
- (u32)key.type, cur_offset);
+ btrfs_err(fs_info,
+ "unexpected item type %u in sys_array at offset %u",
+ (u32)key.type, cur_offset);
ret = -EIO;
break;
}
@@ -6771,7 +6776,7 @@ int btrfs_read_sys_array(struct btrfs_root *root)
return ret;
out_short_read:
- printk(KERN_ERR "BTRFS: sys_array too short to read %u bytes at offset %u\n",
+ btrfs_err(fs_info, "sys_array too short to read %u bytes at offset %u",
len, cur_offset);
clear_extent_buffer_uptodate(sb);
free_extent_buffer_stale(sb);
@@ -7095,10 +7100,12 @@ int btrfs_get_dev_stats(struct btrfs_root *root,
mutex_unlock(&fs_devices->device_list_mutex);
if (!dev) {
- btrfs_warn(root->fs_info, "get dev_stats failed, device not found");
+ btrfs_warn(root->fs_info,
+ "get dev_stats failed, device not found");
return -ENODEV;
} else if (!dev->dev_stats_valid) {
- btrfs_warn(root->fs_info, "get dev_stats failed, not yet valid");
+ btrfs_warn(root->fs_info,
+ "get dev_stats failed, not yet valid");
return -ENODEV;
} else if (stats->flags & BTRFS_DEV_STATS_RESET) {
for (i = 0; i < BTRFS_DEV_STAT_VALUES_MAX; i++) {
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 6613e6335ca2..09ed29c67848 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -382,7 +382,7 @@ int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int op,
u64 logical, u64 *length,
struct btrfs_bio **bbio_ret, int mirror_num,
int need_raid_map);
-int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
+int btrfs_rmap_block(struct btrfs_fs_info *fs_info,
u64 chunk_start, u64 physical, u64 devid,
u64 **logical, int *naddrs, int *stripe_len);
int btrfs_read_sys_array(struct btrfs_root *root);
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index d1a177a3dbe8..fccbf5567e78 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -252,7 +252,7 @@ int __btrfs_setxattr(struct btrfs_trans_handle *trans,
goto out;
inode_inc_iversion(inode);
- inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_ctime = current_time(inode);
set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags);
ret = btrfs_update_inode(trans, root, inode);
BUG_ON(ret);
diff --git a/fs/btrfs/zlib.c b/fs/btrfs/zlib.c
index 88d274e8ecf2..441b81a3e545 100644
--- a/fs/btrfs/zlib.c
+++ b/fs/btrfs/zlib.c
@@ -95,7 +95,7 @@ static int zlib_compress_pages(struct list_head *ws,
*total_in = 0;
if (Z_OK != zlib_deflateInit(&workspace->strm, 3)) {
- printk(KERN_WARNING "BTRFS: deflateInit failed\n");
+ pr_warn("BTRFS: deflateInit failed\n");
ret = -EIO;
goto out;
}
@@ -123,7 +123,7 @@ static int zlib_compress_pages(struct list_head *ws,
while (workspace->strm.total_in < len) {
ret = zlib_deflate(&workspace->strm, Z_SYNC_FLUSH);
if (ret != Z_OK) {
- printk(KERN_DEBUG "BTRFS: deflate in loop returned %d\n",
+ pr_debug("BTRFS: deflate in loop returned %d\n",
ret);
zlib_deflateEnd(&workspace->strm);
ret = -EIO;
@@ -249,7 +249,7 @@ static int zlib_decompress_biovec(struct list_head *ws, struct page **pages_in,
}
if (Z_OK != zlib_inflateInit2(&workspace->strm, wbits)) {
- printk(KERN_WARNING "BTRFS: inflateInit failed\n");
+ pr_warn("BTRFS: inflateInit failed\n");
return -EIO;
}
while (workspace->strm.total_in < srclen) {
@@ -339,7 +339,7 @@ static int zlib_decompress(struct list_head *ws, unsigned char *data_in,
}
if (Z_OK != zlib_inflateInit2(&workspace->strm, wbits)) {
- printk(KERN_WARNING "BTRFS: inflateInit failed\n");
+ pr_warn("BTRFS: inflateInit failed\n");
return -EIO;
}
diff --git a/fs/buffer.c b/fs/buffer.c
index 9c8eb9b6db6a..b205a629001d 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -351,7 +351,7 @@ void end_buffer_async_write(struct buffer_head *bh, int uptodate)
set_buffer_uptodate(bh);
} else {
buffer_io_error(bh, ", lost async page write");
- set_bit(AS_EIO, &page->mapping->flags);
+ mapping_set_error(page->mapping, -EIO);
set_buffer_write_io_error(bh);
clear_buffer_uptodate(bh);
SetPageError(page);
@@ -1078,7 +1078,7 @@ grow_buffers(struct block_device *bdev, sector_t block, int size, gfp_t gfp)
return grow_dev_page(bdev, block, index, size, sizebits, gfp);
}
-struct buffer_head *
+static struct buffer_head *
__getblk_slow(struct block_device *bdev, sector_t block,
unsigned size, gfp_t gfp)
{
@@ -1109,7 +1109,6 @@ __getblk_slow(struct block_device *bdev, sector_t block,
free_more_memory();
}
}
-EXPORT_SYMBOL(__getblk_slow);
/*
* The relationship between dirty buffers and dirty pages:
@@ -3250,7 +3249,7 @@ drop_buffers(struct page *page, struct buffer_head **buffers_to_free)
bh = head;
do {
if (buffer_write_io_error(bh) && page->mapping)
- set_bit(AS_EIO, &page->mapping->flags);
+ mapping_set_error(page->mapping, -EIO);
if (buffer_busy(bh))
goto failed;
bh = bh->b_this_page;
diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c
index 6af790fc3df8..3ff867f87d73 100644
--- a/fs/cachefiles/bind.c
+++ b/fs/cachefiles/bind.c
@@ -20,6 +20,7 @@
#include <linux/mount.h>
#include <linux/statfs.h>
#include <linux/ctype.h>
+#include <linux/xattr.h>
#include "internal.h"
static int cachefiles_daemon_add_cache(struct cachefiles_cache *caches);
@@ -126,8 +127,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
if (d_is_negative(root) ||
!d_backing_inode(root)->i_op->lookup ||
!d_backing_inode(root)->i_op->mkdir ||
- !d_backing_inode(root)->i_op->setxattr ||
- !d_backing_inode(root)->i_op->getxattr ||
+ !(d_backing_inode(root)->i_opflags & IOP_XATTR) ||
!root->d_sb->s_op->statfs ||
!root->d_sb->s_op->sync_fs)
goto error_unsupported;
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index ce5f345d70f5..e7f16a77a22a 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -253,6 +253,8 @@ static void cachefiles_drop_object(struct fscache_object *_object)
struct cachefiles_object *object;
struct cachefiles_cache *cache;
const struct cred *saved_cred;
+ struct inode *inode;
+ blkcnt_t i_blocks = 0;
ASSERT(_object);
@@ -279,6 +281,10 @@ static void cachefiles_drop_object(struct fscache_object *_object)
_object != cache->cache.fsdef
) {
_debug("- retire object OBJ%x", object->fscache.debug_id);
+ inode = d_backing_inode(object->dentry);
+ if (inode)
+ i_blocks = inode->i_blocks;
+
cachefiles_begin_secure(cache, &saved_cred);
cachefiles_delete_object(cache, object);
cachefiles_end_secure(cache, saved_cred);
@@ -292,7 +298,7 @@ static void cachefiles_drop_object(struct fscache_object *_object)
/* note that the object is now inactive */
if (test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags))
- cachefiles_mark_object_inactive(cache, object);
+ cachefiles_mark_object_inactive(cache, object, i_blocks);
dput(object->dentry);
object->dentry = NULL;
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index 2fcde1a34b7c..cd1effee8a49 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -160,7 +160,8 @@ extern char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type);
* namei.c
*/
extern void cachefiles_mark_object_inactive(struct cachefiles_cache *cache,
- struct cachefiles_object *object);
+ struct cachefiles_object *object,
+ blkcnt_t i_blocks);
extern int cachefiles_delete_object(struct cachefiles_cache *cache,
struct cachefiles_object *object);
extern int cachefiles_walk_to_object(struct cachefiles_object *parent,
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index 3f7c2cd41f8f..41df8a27d7eb 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -20,6 +20,7 @@
#include <linux/namei.h>
#include <linux/security.h>
#include <linux/slab.h>
+#include <linux/xattr.h>
#include "internal.h"
#define CACHEFILES_KEYBUF_SIZE 512
@@ -261,10 +262,9 @@ requeue:
* Mark an object as being inactive.
*/
void cachefiles_mark_object_inactive(struct cachefiles_cache *cache,
- struct cachefiles_object *object)
+ struct cachefiles_object *object,
+ blkcnt_t i_blocks)
{
- blkcnt_t i_blocks = d_backing_inode(object->dentry)->i_blocks;
-
write_lock(&cache->active_lock);
rb_erase(&object->active_node, &cache->active_nodes);
clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
@@ -707,7 +707,8 @@ mark_active_timed_out:
check_error:
_debug("check error %d", ret);
- cachefiles_mark_object_inactive(cache, object);
+ cachefiles_mark_object_inactive(
+ cache, object, d_backing_inode(object->dentry)->i_blocks);
release_dentry:
dput(object->dentry);
object->dentry = NULL;
@@ -799,13 +800,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
}
ret = -EPERM;
- if (!d_backing_inode(subdir)->i_op->setxattr ||
- !d_backing_inode(subdir)->i_op->getxattr ||
+ if (!(d_backing_inode(subdir)->i_opflags & IOP_XATTR) ||
!d_backing_inode(subdir)->i_op->lookup ||
!d_backing_inode(subdir)->i_op->mkdir ||
!d_backing_inode(subdir)->i_op->create ||
- (!d_backing_inode(subdir)->i_op->rename &&
- !d_backing_inode(subdir)->i_op->rename2) ||
+ !d_backing_inode(subdir)->i_op->rename ||
!d_backing_inode(subdir)->i_op->rmdir ||
!d_backing_inode(subdir)->i_op->unlink)
goto check_error;
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c
index 4f67227f69a5..987044bca1c2 100644
--- a/fs/ceph/acl.c
+++ b/fs/ceph/acl.c
@@ -95,11 +95,9 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
case ACL_TYPE_ACCESS:
name = XATTR_NAME_POSIX_ACL_ACCESS;
if (acl) {
- ret = posix_acl_equiv_mode(acl, &new_mode);
- if (ret < 0)
+ ret = posix_acl_update_mode(inode, &new_mode, &acl);
+ if (ret)
goto out;
- if (ret == 0)
- acl = NULL;
}
break;
case ACL_TYPE_DEFAULT:
@@ -127,6 +125,11 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
goto out_free;
}
+ if (ceph_snap(inode) != CEPH_NOSNAP) {
+ ret = -EROFS;
+ goto out_free;
+ }
+
if (new_mode != old_mode) {
newattrs.ia_mode = new_mode;
newattrs.ia_valid = ATTR_MODE;
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index d5b6f959a3c3..ef3ebd780aff 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -175,9 +175,8 @@ static void ceph_invalidatepage(struct page *page, unsigned int offset,
static int ceph_releasepage(struct page *page, gfp_t g)
{
- dout("%p releasepage %p idx %lu\n", page->mapping->host,
- page, page->index);
- WARN_ON(PageDirty(page));
+ dout("%p releasepage %p idx %lu (%sdirty)\n", page->mapping->host,
+ page, page->index, PageDirty(page) ? "" : "not ");
/* Can we release the page from the cache? */
if (!ceph_release_fscache_page(page, g))
@@ -298,14 +297,6 @@ unlock:
kfree(osd_data->pages);
}
-static void ceph_unlock_page_vector(struct page **pages, int num_pages)
-{
- int i;
-
- for (i = 0; i < num_pages; i++)
- unlock_page(pages[i]);
-}
-
/*
* start an async read(ahead) operation. return nr_pages we submitted
* a read for on success, or negative error code.
@@ -370,6 +361,10 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max)
dout("start_read %p add_to_page_cache failed %p\n",
inode, page);
nr_pages = i;
+ if (nr_pages > 0) {
+ len = nr_pages << PAGE_SHIFT;
+ break;
+ }
goto out_pages;
}
pages[i] = page;
@@ -386,8 +381,11 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max)
return nr_pages;
out_pages:
- ceph_unlock_page_vector(pages, nr_pages);
- ceph_release_page_vector(pages, nr_pages);
+ for (i = 0; i < nr_pages; ++i) {
+ ceph_fscache_readpage_cancel(inode, pages[i]);
+ unlock_page(pages[i]);
+ }
+ ceph_put_page_vector(pages, nr_pages, false);
out:
ceph_osdc_put_request(req);
return ret;
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index df4b3e6fa563..78180d151730 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -1061,7 +1061,8 @@ out:
}
static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags)
{
struct ceph_fs_client *fsc = ceph_sb_to_client(old_dir->i_sb);
struct ceph_mds_client *mdsc = fsc->mdsc;
@@ -1069,6 +1070,9 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
int op = CEPH_MDS_OP_RENAME;
int err;
+ if (flags)
+ return -EINVAL;
+
if (ceph_snap(old_dir) != ceph_snap(new_dir))
return -EXDEV;
if (ceph_snap(old_dir) != CEPH_NOSNAP) {
@@ -1486,10 +1490,7 @@ const struct inode_operations ceph_dir_iops = {
.permission = ceph_permission,
.getattr = ceph_getattr,
.setattr = ceph_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ceph_listxattr,
- .removexattr = generic_removexattr,
.get_acl = ceph_get_acl,
.set_acl = ceph_set_acl,
.mknod = ceph_mknod,
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 0f5375d8e030..7bf08825cc11 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -886,7 +886,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
int num_pages = 0;
int flags;
int ret;
- struct timespec mtime = current_fs_time(inode->i_sb);
+ struct timespec mtime = current_time(inode);
size_t count = iov_iter_count(iter);
loff_t pos = iocb->ki_pos;
bool write = iov_iter_rw(iter) == WRITE;
@@ -902,10 +902,10 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
return ret;
if (write) {
- ret = invalidate_inode_pages2_range(inode->i_mapping,
+ int ret2 = invalidate_inode_pages2_range(inode->i_mapping,
pos >> PAGE_SHIFT,
(pos + count) >> PAGE_SHIFT);
- if (ret < 0)
+ if (ret2 < 0)
dout("invalidate_inode_pages2_range returned %d\n", ret);
flags = CEPH_OSD_FLAG_ORDERSNAP |
@@ -1091,7 +1091,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
int flags;
int check_caps = 0;
int ret;
- struct timespec mtime = current_fs_time(inode->i_sb);
+ struct timespec mtime = current_time(inode);
size_t count = iov_iter_count(from);
if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index dd3a6dbf71eb..bca1b49c1c4b 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -94,10 +94,7 @@ const struct inode_operations ceph_file_iops = {
.permission = ceph_permission,
.setattr = ceph_setattr,
.getattr = ceph_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ceph_listxattr,
- .removexattr = generic_removexattr,
.get_acl = ceph_get_acl,
.set_acl = ceph_set_acl,
};
@@ -1885,10 +1882,7 @@ static const struct inode_operations ceph_symlink_iops = {
.get_link = simple_get_link,
.setattr = ceph_setattr,
.getattr = ceph_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ceph_listxattr,
- .removexattr = generic_removexattr,
};
int __ceph_setattr(struct inode *inode, struct iattr *attr)
@@ -1905,13 +1899,6 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
int inode_dirty_flags = 0;
bool lock_snap_rwsem = false;
- if (ceph_snap(inode) != CEPH_NOSNAP)
- return -EROFS;
-
- err = inode_change_ok(inode, attr);
- if (err != 0)
- return err;
-
prealloc_cf = ceph_alloc_cap_flush();
if (!prealloc_cf)
return -ENOMEM;
@@ -2080,7 +2067,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
if (dirtied) {
inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied,
&prealloc_cf);
- inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_ctime = current_time(inode);
}
release &= issued;
@@ -2124,7 +2111,17 @@ out_put:
*/
int ceph_setattr(struct dentry *dentry, struct iattr *attr)
{
- return __ceph_setattr(d_inode(dentry), attr);
+ struct inode *inode = d_inode(dentry);
+ int err;
+
+ if (ceph_snap(inode) != CEPH_NOSNAP)
+ return -EROFS;
+
+ err = setattr_prepare(dentry, attr);
+ if (err != 0)
+ return err;
+
+ return __ceph_setattr(inode, attr);
}
/*
diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c
index a2cb0c254060..6806dbeaee19 100644
--- a/fs/ceph/locks.c
+++ b/fs/ceph/locks.c
@@ -210,8 +210,8 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
if (!(fl->fl_flags & FL_FLOCK))
return -ENOLCK;
/* No mandatory locks */
- if (__mandatory_lock(file->f_mapping->host) && fl->fl_type != F_UNLCK)
- return -ENOLCK;
+ if (fl->fl_type & LOCK_MAND)
+ return -EOPNOTSUPP;
dout("ceph_flock, fl_file: %p", fl->fl_file);
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index f72d4ae303b2..815acd1a56d4 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -370,6 +370,7 @@ const char *ceph_session_state_name(int s)
case CEPH_MDS_SESSION_CLOSING: return "closing";
case CEPH_MDS_SESSION_RESTARTING: return "restarting";
case CEPH_MDS_SESSION_RECONNECTING: return "reconnecting";
+ case CEPH_MDS_SESSION_REJECTED: return "rejected";
default: return "???";
}
}
@@ -1150,8 +1151,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
while (!list_empty(&ci->i_cap_flush_list)) {
cf = list_first_entry(&ci->i_cap_flush_list,
struct ceph_cap_flush, i_list);
- list_del(&cf->i_list);
- list_add(&cf->i_list, &to_remove);
+ list_move(&cf->i_list, &to_remove);
}
spin_lock(&mdsc->cap_dirty_lock);
@@ -1378,7 +1378,7 @@ static int request_close_session(struct ceph_mds_client *mdsc,
if (!msg)
return -ENOMEM;
ceph_con_send(&session->s_con, msg);
- return 0;
+ return 1;
}
/*
@@ -2131,6 +2131,10 @@ static int __do_request(struct ceph_mds_client *mdsc,
ceph_session_state_name(session->s_state));
if (session->s_state != CEPH_MDS_SESSION_OPEN &&
session->s_state != CEPH_MDS_SESSION_HUNG) {
+ if (session->s_state == CEPH_MDS_SESSION_REJECTED) {
+ err = -EACCES;
+ goto out_session;
+ }
if (session->s_state == CEPH_MDS_SESSION_NEW ||
session->s_state == CEPH_MDS_SESSION_CLOSING)
__open_session(mdsc, session);
@@ -2652,6 +2656,15 @@ static void handle_session(struct ceph_mds_session *session,
wake_up_session_caps(session, 0);
break;
+ case CEPH_SESSION_REJECT:
+ WARN_ON(session->s_state != CEPH_MDS_SESSION_OPENING);
+ pr_info("mds%d rejected session\n", session->s_mds);
+ session->s_state = CEPH_MDS_SESSION_REJECTED;
+ cleanup_session_requests(mdsc, session);
+ remove_session_caps(session);
+ wake = 2; /* for good measure */
+ break;
+
default:
pr_err("mdsc_handle_session bad op %d mds%d\n", op, mds);
WARN_ON(1);
@@ -3557,11 +3570,11 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
/*
* true if all sessions are closed, or we force unmount
*/
-static bool done_closing_sessions(struct ceph_mds_client *mdsc)
+static bool done_closing_sessions(struct ceph_mds_client *mdsc, int skipped)
{
if (ACCESS_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_SHUTDOWN)
return true;
- return atomic_read(&mdsc->num_sessions) == 0;
+ return atomic_read(&mdsc->num_sessions) <= skipped;
}
/*
@@ -3572,6 +3585,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
struct ceph_options *opts = mdsc->fsc->client->options;
struct ceph_mds_session *session;
int i;
+ int skipped = 0;
dout("close_sessions\n");
@@ -3583,7 +3597,8 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
continue;
mutex_unlock(&mdsc->mutex);
mutex_lock(&session->s_mutex);
- __close_session(mdsc, session);
+ if (__close_session(mdsc, session) <= 0)
+ skipped++;
mutex_unlock(&session->s_mutex);
ceph_put_mds_session(session);
mutex_lock(&mdsc->mutex);
@@ -3591,7 +3606,8 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
mutex_unlock(&mdsc->mutex);
dout("waiting for sessions to close\n");
- wait_event_timeout(mdsc->session_close_wq, done_closing_sessions(mdsc),
+ wait_event_timeout(mdsc->session_close_wq,
+ done_closing_sessions(mdsc, skipped),
ceph_timeout_jiffies(opts->mount_timeout));
/* tear down remaining sessions */
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index 6b3679737d4a..3c6f77b7bb02 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -121,6 +121,7 @@ enum {
CEPH_MDS_SESSION_CLOSING = 5,
CEPH_MDS_SESSION_RESTARTING = 6,
CEPH_MDS_SESSION_RECONNECTING = 7,
+ CEPH_MDS_SESSION_REJECTED = 8,
};
struct ceph_mds_session {
diff --git a/fs/ceph/strings.c b/fs/ceph/strings.c
index 89e6bc321df3..913dea163d5c 100644
--- a/fs/ceph/strings.c
+++ b/fs/ceph/strings.c
@@ -43,6 +43,8 @@ const char *ceph_session_op_name(int op)
case CEPH_SESSION_RECALL_STATE: return "recall_state";
case CEPH_SESSION_FLUSHMSG: return "flushmsg";
case CEPH_SESSION_FLUSHMSG_ACK: return "flushmsg_ack";
+ case CEPH_SESSION_FORCE_RO: return "force_ro";
+ case CEPH_SESSION_REJECT: return "reject";
}
return "???";
}
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index e247f6f0feb7..a29ffce98187 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -396,10 +396,12 @@ static int parse_mount_options(struct ceph_mount_options **pfsopt,
*/
dev_name_end = strchr(dev_name, '/');
if (dev_name_end) {
- fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL);
- if (!fsopt->server_path) {
- err = -ENOMEM;
- goto out;
+ if (strlen(dev_name_end) > 1) {
+ fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL);
+ if (!fsopt->server_path) {
+ err = -ENOMEM;
+ goto out;
+ }
}
} else {
dev_name_end = dev_name + strlen(dev_name);
@@ -788,15 +790,10 @@ static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
struct inode *inode = req->r_target_inode;
req->r_target_inode = NULL;
dout("open_root_inode success\n");
- if (ceph_ino(inode) == CEPH_INO_ROOT &&
- fsc->sb->s_root == NULL) {
- root = d_make_root(inode);
- if (!root) {
- root = ERR_PTR(-ENOMEM);
- goto out;
- }
- } else {
- root = d_obtain_root(inode);
+ root = d_make_root(inode);
+ if (!root) {
+ root = ERR_PTR(-ENOMEM);
+ goto out;
}
ceph_init_dentry(root);
dout("open_root_inode success, root dentry is %p\n", root);
@@ -825,17 +822,24 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc)
mutex_lock(&fsc->client->mount_mutex);
if (!fsc->sb->s_root) {
+ const char *path;
err = __ceph_open_session(fsc->client, started);
if (err < 0)
goto out;
- dout("mount opening root\n");
- root = open_root_dentry(fsc, "", started);
+ if (!fsc->mount_options->server_path) {
+ path = "";
+ dout("mount opening path \\t\n");
+ } else {
+ path = fsc->mount_options->server_path + 1;
+ dout("mount opening path %s\n", path);
+ }
+ root = open_root_dentry(fsc, path, started);
if (IS_ERR(root)) {
err = PTR_ERR(root);
goto out;
}
- fsc->sb->s_root = root;
+ fsc->sb->s_root = dget(root);
first = 1;
err = ceph_fs_debugfs_init(fsc);
@@ -843,19 +847,6 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc)
goto fail;
}
- if (!fsc->mount_options->server_path) {
- root = fsc->sb->s_root;
- dget(root);
- } else {
- const char *path = fsc->mount_options->server_path + 1;
- dout("mount opening path %s\n", path);
- root = open_root_dentry(fsc, path, started);
- if (IS_ERR(root)) {
- err = PTR_ERR(root);
- goto fail;
- }
- }
-
fsc->mount_state = CEPH_MOUNT_MOUNTED;
dout("mount success\n");
mutex_unlock(&fsc->client->mount_mutex);
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index adc231892b0d..40b703217977 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -1034,7 +1034,7 @@ retry:
dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL,
&prealloc_cf);
ci->i_xattrs.dirty = true;
- inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_ctime = current_time(inode);
}
spin_unlock(&ci->i_ceph_lock);
diff --git a/fs/char_dev.c b/fs/char_dev.c
index 6edd825231c5..44a240c4bb65 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -406,6 +406,7 @@ void cd_forget(struct inode *inode)
spin_lock(&cdev_lock);
list_del_init(&inode->i_devices);
inode->i_cdev = NULL;
+ inode->i_mapping = &inode->i_data;
spin_unlock(&cdev_lock);
}
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 6c58e13fed2f..3d03e48a9213 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -152,6 +152,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
list_for_each(tmp1, &cifs_tcp_ses_list) {
server = list_entry(tmp1, struct TCP_Server_Info,
tcp_ses_list);
+ seq_printf(m, "\nNumber of credits: %d", server->credits);
i++;
list_for_each(tmp2, &server->smb_ses_list) {
ses = list_entry(tmp2, struct cifs_ses,
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 1418daa03d95..07ed81cf1552 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -49,6 +49,7 @@
#define CIFS_MOUNT_USE_PREFIX_PATH 0x1000000 /* make subpath with unaccessible
* root mountable
*/
+#define CIFS_MOUNT_UID_FROM_ACL 0x2000000 /* try to get UID via special SID */
struct cifs_sb_info {
struct rb_root tlink_tree;
diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
index 0065256881d8..57ff0756e30c 100644
--- a/fs/cifs/cifs_ioctl.h
+++ b/fs/cifs/cifs_ioctl.h
@@ -36,7 +36,15 @@ struct smb_mnt_fs_info {
__u64 cifs_posix_caps;
} __packed;
+struct smb_snapshot_array {
+ __u32 number_of_snapshots;
+ __u32 number_of_snapshots_returned;
+ __u32 snapshot_array_size;
+ /* snapshots[]; */
+} __packed;
+
#define CIFS_IOCTL_MAGIC 0xCF
#define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int)
#define CIFS_IOC_SET_INTEGRITY _IO(CIFS_IOCTL_MAGIC, 4)
#define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
+#define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 71e8a56e9479..15bac390dff9 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -42,6 +42,35 @@ static const struct cifs_sid sid_authusers = {
/* group users */
static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
+/* S-1-22-1 Unmapped Unix users */
+static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
+ {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/* S-1-22-2 Unmapped Unix groups */
+static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
+ {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/*
+ * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
+ */
+
+/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
+
+/* S-1-5-88-1 Unix uid */
+static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
+ {cpu_to_le32(88),
+ cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/* S-1-5-88-2 Unix gid */
+static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
+ {cpu_to_le32(88),
+ cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/* S-1-5-88-3 Unix mode */
+static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
+ {cpu_to_le32(88),
+ cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
static const struct cred *root_cred;
static int
@@ -183,6 +212,62 @@ compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
return 0; /* sids compare/match */
}
+static bool
+is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
+{
+ int i;
+ int num_subauth;
+ const struct cifs_sid *pwell_known_sid;
+
+ if (!psid || (puid == NULL))
+ return false;
+
+ num_subauth = psid->num_subauth;
+
+ /* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
+ if (num_subauth == 2) {
+ if (is_group)
+ pwell_known_sid = &sid_unix_groups;
+ else
+ pwell_known_sid = &sid_unix_users;
+ } else if (num_subauth == 3) {
+ if (is_group)
+ pwell_known_sid = &sid_unix_NFS_groups;
+ else
+ pwell_known_sid = &sid_unix_NFS_users;
+ } else
+ return false;
+
+ /* compare the revision */
+ if (psid->revision != pwell_known_sid->revision)
+ return false;
+
+ /* compare all of the six auth values */
+ for (i = 0; i < NUM_AUTHS; ++i) {
+ if (psid->authority[i] != pwell_known_sid->authority[i]) {
+ cifs_dbg(FYI, "auth %d did not match\n", i);
+ return false;
+ }
+ }
+
+ if (num_subauth == 2) {
+ if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
+ return false;
+
+ *puid = le32_to_cpu(psid->sub_auth[1]);
+ } else /* 3 subauths, ie Windows/Mac style */ {
+ *puid = le32_to_cpu(psid->sub_auth[0]);
+ if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
+ (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
+ return false;
+
+ *puid = le32_to_cpu(psid->sub_auth[2]);
+ }
+
+ cifs_dbg(FYI, "Unix UID %d returned from SID\n", *puid);
+ return true; /* well known sid found, uid returned */
+}
+
static void
cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
{
@@ -276,6 +361,43 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
return -EIO;
}
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) {
+ uint32_t unix_id;
+ bool is_group;
+
+ if (sidtype != SIDOWNER)
+ is_group = true;
+ else
+ is_group = false;
+
+ if (is_well_known_sid(psid, &unix_id, is_group) == false)
+ goto try_upcall_to_get_id;
+
+ if (is_group) {
+ kgid_t gid;
+ gid_t id;
+
+ id = (gid_t)unix_id;
+ gid = make_kgid(&init_user_ns, id);
+ if (gid_valid(gid)) {
+ fgid = gid;
+ goto got_valid_id;
+ }
+ } else {
+ kuid_t uid;
+ uid_t id;
+
+ id = (uid_t)unix_id;
+ uid = make_kuid(&init_user_ns, id);
+ if (uid_valid(uid)) {
+ fuid = uid;
+ goto got_valid_id;
+ }
+ }
+ /* If unable to find uid/gid easily from SID try via upcall */
+ }
+
+try_upcall_to_get_id:
sidstr = sid_to_key_str(psid, sidtype);
if (!sidstr)
return -ENOMEM;
@@ -329,6 +451,7 @@ out_revert_creds:
* Note that we return 0 here unconditionally. If the mapping
* fails then we just fall back to using the mnt_uid/mnt_gid.
*/
+got_valid_id:
if (sidtype == SIDOWNER)
fattr->cf_uid = fuid;
else
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 14ae4b8e1a3c..15261ba464c5 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -64,15 +64,15 @@ unsigned int global_secflags = CIFSSEC_DEF;
unsigned int sign_CIFS_PDUs = 1;
static const struct super_operations cifs_super_ops;
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
-module_param(CIFSMaxBufSize, uint, 0);
+module_param(CIFSMaxBufSize, uint, 0444);
MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). "
"Default: 16384 Range: 8192 to 130048");
unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
-module_param(cifs_min_rcv, uint, 0);
+module_param(cifs_min_rcv, uint, 0444);
MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: "
"1 to 64");
unsigned int cifs_min_small = 30;
-module_param(cifs_min_small, uint, 0);
+module_param(cifs_min_small, uint, 0444);
MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
"Range: 2 to 256");
unsigned int cifs_max_pending = CIFS_MAX_REQ;
@@ -271,7 +271,7 @@ cifs_alloc_inode(struct super_block *sb)
cifs_inode->createtime = 0;
cifs_inode->epoch = 0;
#ifdef CONFIG_CIFS_SMB2
- get_random_bytes(cifs_inode->lease_key, SMB2_LEASE_KEY_SIZE);
+ generate_random_uuid(cifs_inode->lease_key);
#endif
/*
* Can not set i_flags here - they get immediately overwritten to zero
@@ -469,6 +469,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_puts(s, ",posixpaths");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
seq_puts(s, ",setuids");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
+ seq_puts(s, ",idsfromsid");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
seq_puts(s, ",serverino");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
@@ -896,35 +898,26 @@ const struct inode_operations cifs_dir_inode_ops = {
.link = cifs_hardlink,
.mkdir = cifs_mkdir,
.rmdir = cifs_rmdir,
- .rename2 = cifs_rename2,
+ .rename = cifs_rename2,
.permission = cifs_permission,
.setattr = cifs_setattr,
.symlink = cifs_symlink,
.mknod = cifs_mknod,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = cifs_listxattr,
- .removexattr = generic_removexattr,
};
const struct inode_operations cifs_file_inode_ops = {
.setattr = cifs_setattr,
.getattr = cifs_getattr,
.permission = cifs_permission,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = cifs_listxattr,
- .removexattr = generic_removexattr,
};
const struct inode_operations cifs_symlink_inode_ops = {
.readlink = generic_readlink,
.get_link = cifs_get_link,
.permission = cifs_permission,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = cifs_listxattr,
- .removexattr = generic_removexattr,
};
static int cifs_clone_file_range(struct file *src_file, loff_t off,
@@ -1271,7 +1264,6 @@ init_cifs(void)
GlobalTotalActiveXid = 0;
GlobalMaxActiveXid = 0;
spin_lock_init(&cifs_tcp_ses_lock);
- spin_lock_init(&cifs_file_list_lock);
spin_lock_init(&GlobalMid_Lock);
get_random_bytes(&cifs_lock_secret, sizeof(cifs_lock_secret));
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 9dcf974acc47..c9c00a862036 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -41,6 +41,16 @@ cifs_uniqueid_to_ino_t(u64 fileid)
}
+static inline void cifs_set_time(struct dentry *dentry, unsigned long time)
+{
+ dentry->d_fsdata = (void *) time;
+}
+
+static inline unsigned long cifs_get_time(struct dentry *dentry)
+{
+ return (unsigned long) dentry->d_fsdata;
+}
+
extern struct file_system_type cifs_fs_type;
extern const struct address_space_operations cifs_addr_ops;
extern const struct address_space_operations cifs_addr_ops_smallbuf;
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 8f1d8c1e72be..1f17f6bd7a60 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -75,6 +75,18 @@
#define SMB_ECHO_INTERVAL_MAX 600
#define SMB_ECHO_INTERVAL_DEFAULT 60
+/*
+ * Default number of credits to keep available for SMB3.
+ * This value is chosen somewhat arbitrarily. The Windows client
+ * defaults to 128 credits, the Windows server allows clients up to
+ * 512 credits (or 8K for later versions), and the NetApp server
+ * does not limit clients at all. Choose a high enough default value
+ * such that the client shouldn't limit performance, but allow mount
+ * to override (until you approach 64K, where we limit credits to 65000
+ * to reduce possibility of seeing more server credit overflow bugs.
+ */
+#define SMB2_MAX_CREDITS_AVAILABLE 32000
+
#include "cifspdu.h"
#ifndef XATTR_DOS_ATTRIB
@@ -376,6 +388,8 @@ struct smb_version_operations {
int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *);
int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon,
struct cifsFileInfo *src_file);
+ int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *src_file, void __user *);
int (*query_mf_symlink)(unsigned int, struct cifs_tcon *,
struct cifs_sb_info *, const unsigned char *,
char *, unsigned int *);
@@ -464,6 +478,7 @@ struct smb_vol {
bool retry:1;
bool intr:1;
bool setuids:1;
+ bool setuidfromacl:1;
bool override_uid:1;
bool override_gid:1;
bool dynperm:1;
@@ -510,6 +525,7 @@ struct smb_vol {
struct sockaddr_storage srcaddr; /* allow binding to a local IP */
struct nls_table *local_nls;
unsigned int echo_interval; /* echo interval in secs */
+ unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
};
#define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \
@@ -567,7 +583,8 @@ struct TCP_Server_Info {
bool noblocksnd; /* use blocking sendmsg */
bool noautotune; /* do not autotune send buf sizes */
bool tcp_nodelay;
- int credits; /* send no more requests at once */
+ unsigned int credits; /* send no more requests at once */
+ unsigned int max_credits; /* can override large 32000 default at mnt */
unsigned int in_flight; /* number of requests on the wire to server */
spinlock_t req_lock; /* protect the two values above */
struct mutex srv_mutex;
@@ -833,6 +850,7 @@ struct cifs_tcon {
struct list_head tcon_list;
int tc_count;
struct list_head openFileList;
+ spinlock_t open_file_lock; /* protects list above */
struct cifs_ses *ses; /* pointer to session associated with */
char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
char *nativeFileSystem;
@@ -889,7 +907,7 @@ struct cifs_tcon {
#endif /* CONFIG_CIFS_STATS2 */
__u64 bytes_read;
__u64 bytes_written;
- spinlock_t stat_lock;
+ spinlock_t stat_lock; /* protects the two fields above */
#endif /* CONFIG_CIFS_STATS */
FILE_SYSTEM_DEVICE_INFO fsDevInfo;
FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
@@ -1040,20 +1058,24 @@ struct cifs_fid_locks {
};
struct cifsFileInfo {
+ /* following two lists are protected by tcon->open_file_lock */
struct list_head tlist; /* pointer to next fid owned by tcon */
struct list_head flist; /* next fid (file instance) for this inode */
+ /* lock list below protected by cifsi->lock_sem */
struct cifs_fid_locks *llist; /* brlocks held by this fid */
kuid_t uid; /* allows finding which FileInfo structure */
__u32 pid; /* process id who opened file */
struct cifs_fid fid; /* file id from remote */
+ struct list_head rlist; /* reconnect list */
/* BB add lock scope info here if needed */ ;
/* lock scope id (0 if none) */
struct dentry *dentry;
- unsigned int f_flags;
struct tcon_link *tlink;
+ unsigned int f_flags;
bool invalidHandle:1; /* file closed via session abend */
bool oplock_break_cancelled:1;
- int count; /* refcount protected by cifs_file_list_lock */
+ int count;
+ spinlock_t file_info_lock; /* protects four flag/count fields above */
struct mutex fh_mutex; /* prevents reopen race after dead ses*/
struct cifs_search_info srch_inf;
struct work_struct oplock_break; /* work for oplock breaks */
@@ -1120,7 +1142,7 @@ struct cifs_writedata {
/*
* Take a reference on the file private data. Must be called with
- * cifs_file_list_lock held.
+ * cfile->file_info_lock held.
*/
static inline void
cifsFileInfo_get_locked(struct cifsFileInfo *cifs_file)
@@ -1514,8 +1536,10 @@ require use of the stronger protocol */
* GlobalMid_Lock protects:
* list operations on pending_mid_q and oplockQ
* updates to XID counters, multiplex id and SMB sequence numbers
- * cifs_file_list_lock protects:
- * list operations on tcp and SMB session lists and tCon lists
+ * tcp_ses_lock protects:
+ * list operations on tcp and SMB session lists
+ * tcon->open_file_lock protects the list of open files hanging off the tcon
+ * cfile->file_info_lock protects counters and fields in cifs file struct
* f_owner.lock protects certain per file struct operations
* mapping->page_lock protects certain per page operations
*
@@ -1547,18 +1571,12 @@ GLOBAL_EXTERN struct list_head cifs_tcp_ses_list;
* tcp session, and the list of tcon's per smb session. It also protects
* the reference counters for the server, smb session, and tcon. Finally,
* changes to the tcon->tidStatus should be done while holding this lock.
+ * generally the locks should be taken in order tcp_ses_lock before
+ * tcon->open_file_lock and that before file->file_info_lock since the
+ * structure order is cifs_socket-->cifs_ses-->cifs_tcon-->cifs_file
*/
GLOBAL_EXTERN spinlock_t cifs_tcp_ses_lock;
-/*
- * This lock protects the cifs_file->llist and cifs_file->flist
- * list operations, and updates to some flags (cifs_file->invalidHandle)
- * It will be moved to either use the tcon->stat_lock or equivalent later.
- * If cifs_tcp_ses_lock and the lock below are both needed to be held, then
- * the cifs_tcp_ses_lock must be grabbed first and released last.
- */
-GLOBAL_EXTERN spinlock_t cifs_file_list_lock;
-
#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */
/* Outstanding dir notify requests */
GLOBAL_EXTERN struct list_head GlobalDnotifyReqList;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 95dab43646f0..ced0e42ce460 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -193,6 +193,8 @@ extern struct smb_vol *cifs_get_volume_info(char *mount_data,
extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *);
extern void cifs_umount(struct cifs_sb_info *);
extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon);
+extern void cifs_reopen_persistent_handles(struct cifs_tcon *tcon);
+
extern bool cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset,
__u64 length, __u8 type,
struct cifsLockInfo **conf_lock,
@@ -392,8 +394,7 @@ extern int CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
unsigned int *nbytes, char **buf,
int *return_buf_type);
extern int CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
- unsigned int *nbytes, const char *buf,
- const char __user *ubuf, const int long_op);
+ unsigned int *nbytes, const char *buf);
extern int CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
unsigned int *nbytes, struct kvec *iov, const int nvec);
extern int CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index d47197ea4ab6..3f3185febc58 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -98,13 +98,13 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
struct list_head *tmp1;
/* list all files open on tree connection and mark them invalid */
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&tcon->open_file_lock);
list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
open_file = list_entry(tmp, struct cifsFileInfo, tlist);
open_file->invalidHandle = true;
open_file->oplock_break_cancelled = true;
}
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tcon->open_file_lock);
/*
* BB Add call to invalidate_inodes(sb) for all superblocks mounted
* to this tcon.
@@ -1228,7 +1228,6 @@ OldOpenRetry:
inc_rfc1001_len(pSMB, count);
pSMB->ByteCount = cpu_to_le16(count);
- /* long_op set to 1 to allow for oplock break timeouts */
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *)pSMBr, &bytes_returned, 0);
cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
@@ -1768,8 +1767,7 @@ CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
int
CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
- unsigned int *nbytes, const char *buf,
- const char __user *ubuf, const int long_op)
+ unsigned int *nbytes, const char *buf)
{
int rc = -EACCES;
WRITE_REQ *pSMB = NULL;
@@ -1838,12 +1836,7 @@ CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
if (buf)
memcpy(pSMB->Data, buf, bytes_sent);
- else if (ubuf) {
- if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
- cifs_buf_release(pSMB);
- return -EFAULT;
- }
- } else if (count != 0) {
+ else if (count != 0) {
/* No buffer */
cifs_buf_release(pSMB);
return -EINVAL;
@@ -1867,7 +1860,7 @@ CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
}
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
if (rc) {
cifs_dbg(FYI, "Send error in write = %d\n", rc);
@@ -3334,7 +3327,7 @@ CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
#ifdef CONFIG_CIFS_POSIX
/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
-static void cifs_convert_ace(posix_acl_xattr_entry *ace,
+static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
struct cifs_posix_ace *cifs_ace)
{
/* u8 cifs fields do not need le conversion */
@@ -3358,7 +3351,7 @@ static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
__u16 count;
struct cifs_posix_ace *pACE;
struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
- posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
+ struct posix_acl_xattr_header *local_acl = (void *)trgt;
if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
return -EOPNOTSUPP;
@@ -3396,9 +3389,11 @@ static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
} else if (size > buflen) {
return -ERANGE;
} else /* buffer big enough */ {
+ struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
+
local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
for (i = 0; i < count ; i++) {
- cifs_convert_ace(&local_acl->a_entries[i], pACE);
+ cifs_convert_ace(&ace[i], pACE);
pACE++;
}
}
@@ -3406,7 +3401,7 @@ static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
}
static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
- const posix_acl_xattr_entry *local_ace)
+ const struct posix_acl_xattr_entry *local_ace)
{
__u16 rc = 0; /* 0 = ACL converted ok */
@@ -3431,7 +3426,7 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
{
__u16 rc = 0;
struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
- posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
+ struct posix_acl_xattr_header *local_acl = (void *)pACL;
int count;
int i;
@@ -3459,7 +3454,7 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
}
for (i = 0; i < count; i++) {
rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
- &local_acl->a_entries[i]);
+ (struct posix_acl_xattr_entry *)(local_acl + 1));
if (rc != 0) {
/* ACE not converted */
break;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2e4f4bad8b1e..aab5227979e2 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -63,7 +63,6 @@ extern mempool_t *cifs_req_poolp;
#define TLINK_IDLE_EXPIRE (600 * HZ)
enum {
-
/* Mount options that take no arguments */
Opt_user_xattr, Opt_nouser_xattr,
Opt_forceuid, Opt_noforceuid,
@@ -76,7 +75,7 @@ enum {
Opt_noposixpaths, Opt_nounix,
Opt_nocase,
Opt_brl, Opt_nobrl,
- Opt_forcemandatorylock, Opt_setuids,
+ Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
Opt_nohard, Opt_nosoft,
Opt_nointr, Opt_intr,
@@ -95,7 +94,7 @@ enum {
Opt_cruid, Opt_gid, Opt_file_mode,
Opt_dirmode, Opt_port,
Opt_rsize, Opt_wsize, Opt_actimeo,
- Opt_echo_interval,
+ Opt_echo_interval, Opt_max_credits,
/* Mount options which take string value */
Opt_user, Opt_pass, Opt_ip,
@@ -148,6 +147,7 @@ static const match_table_t cifs_mount_option_tokens = {
{ Opt_forcemandatorylock, "forcemand" },
{ Opt_setuids, "setuids" },
{ Opt_nosetuids, "nosetuids" },
+ { Opt_setuidfromacl, "idsfromsid" },
{ Opt_dynperm, "dynperm" },
{ Opt_nodynperm, "nodynperm" },
{ Opt_nohard, "nohard" },
@@ -190,6 +190,7 @@ static const match_table_t cifs_mount_option_tokens = {
{ Opt_wsize, "wsize=%s" },
{ Opt_actimeo, "actimeo=%s" },
{ Opt_echo_interval, "echo_interval=%s" },
+ { Opt_max_credits, "max_credits=%s" },
{ Opt_blank_user, "user=" },
{ Opt_blank_user, "username=" },
@@ -1376,6 +1377,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
case Opt_nosetuids:
vol->setuids = 0;
break;
+ case Opt_setuidfromacl:
+ vol->setuidfromacl = 1;
+ break;
case Opt_dynperm:
vol->dynperm = true;
break;
@@ -1586,6 +1590,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
}
vol->echo_interval = option;
break;
+ case Opt_max_credits:
+ if (get_option_ul(args, &option) || (option < 20) ||
+ (option > 60000)) {
+ cifs_dbg(VFS, "%s: Invalid max_credits value\n",
+ __func__);
+ goto cifs_parse_mount_err;
+ }
+ vol->max_credits = option;
+ break;
/* String Arguments */
@@ -2163,7 +2176,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
sizeof(tcp_ses->dstaddr));
#ifdef CONFIG_CIFS_SMB2
- get_random_bytes(tcp_ses->client_guid, SMB2_CLIENT_GUID_SIZE);
+ generate_random_uuid(tcp_ses->client_guid);
#endif
/*
* at this point we are the only ones with the pointer
@@ -3270,6 +3283,8 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
if (pvolume_info->setuids)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
+ if (pvolume_info->setuidfromacl)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
if (pvolume_info->server_ino)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
if (pvolume_info->remap)
@@ -3598,7 +3613,11 @@ try_mount_again:
bdi_destroy(&cifs_sb->bdi);
goto out;
}
-
+ if ((volume_info->max_credits < 20) ||
+ (volume_info->max_credits > 60000))
+ server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
+ else
+ server->max_credits = volume_info->max_credits;
/* get a reference to a SMB session */
ses = cifs_get_smb_ses(server, volume_info);
if (IS_ERR(ses)) {
@@ -3688,14 +3707,16 @@ remote_path_check:
goto mount_fail_check;
}
- rc = cifs_are_all_path_components_accessible(server,
+ if (rc != -EREMOTE) {
+ rc = cifs_are_all_path_components_accessible(server,
xid, tcon, cifs_sb,
full_path);
- if (rc != 0) {
- cifs_dbg(VFS, "cannot query dirs between root and final path, "
- "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
- rc = 0;
+ if (rc != 0) {
+ cifs_dbg(VFS, "cannot query dirs between root and final path, "
+ "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
+ rc = 0;
+ }
}
kfree(full_path);
}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 4716c54dbfc6..789ff1df2d8d 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -40,7 +40,7 @@ renew_parental_timestamps(struct dentry *direntry)
/* BB check if there is a way to get the kernel to do this or if we
really need this */
do {
- direntry->d_time = jiffies;
+ cifs_set_time(direntry, jiffies);
direntry = direntry->d_parent;
} while (!IS_ROOT(direntry));
}
@@ -802,7 +802,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
} else if (rc == -ENOENT) {
rc = 0;
- direntry->d_time = jiffies;
+ cifs_set_time(direntry, jiffies);
d_add(direntry, NULL);
/* if it was once a directory (but how can we tell?) we could do
shrink_dcache_parent(direntry); */
@@ -862,7 +862,7 @@ cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
return 0;
- if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled)
+ if (time_after(jiffies, cifs_get_time(direntry) + HZ) || !lookupCacheEnabled)
return 0;
return 1;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 579e41b350a2..7f5f6176c6f1 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -305,6 +305,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
cfile->tlink = cifs_get_tlink(tlink);
INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
mutex_init(&cfile->fh_mutex);
+ spin_lock_init(&cfile->file_info_lock);
cifs_sb_active(inode->i_sb);
@@ -317,7 +318,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
oplock = 0;
}
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&tcon->open_file_lock);
if (fid->pending_open->oplock != CIFS_OPLOCK_NO_CHANGE && oplock)
oplock = fid->pending_open->oplock;
list_del(&fid->pending_open->olist);
@@ -326,12 +327,13 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
server->ops->set_fid(cfile, fid, oplock);
list_add(&cfile->tlist, &tcon->openFileList);
+
/* if readable file instance put first in list*/
if (file->f_mode & FMODE_READ)
list_add(&cfile->flist, &cinode->openFileList);
else
list_add_tail(&cfile->flist, &cinode->openFileList);
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tcon->open_file_lock);
if (fid->purge_cache)
cifs_zap_mapping(inode);
@@ -343,16 +345,16 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
struct cifsFileInfo *
cifsFileInfo_get(struct cifsFileInfo *cifs_file)
{
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&cifs_file->file_info_lock);
cifsFileInfo_get_locked(cifs_file);
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&cifs_file->file_info_lock);
return cifs_file;
}
/*
* Release a reference on the file private data. This may involve closing
* the filehandle out on the server. Must be called without holding
- * cifs_file_list_lock.
+ * tcon->open_file_lock and cifs_file->file_info_lock.
*/
void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
{
@@ -367,11 +369,15 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
struct cifs_pending_open open;
bool oplock_break_cancelled;
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&tcon->open_file_lock);
+
+ spin_lock(&cifs_file->file_info_lock);
if (--cifs_file->count > 0) {
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&cifs_file->file_info_lock);
+ spin_unlock(&tcon->open_file_lock);
return;
}
+ spin_unlock(&cifs_file->file_info_lock);
if (server->ops->get_lease_key)
server->ops->get_lease_key(inode, &fid);
@@ -395,7 +401,8 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
set_bit(CIFS_INO_INVALID_MAPPING, &cifsi->flags);
cifs_set_oplock_level(cifsi, 0);
}
- spin_unlock(&cifs_file_list_lock);
+
+ spin_unlock(&tcon->open_file_lock);
oplock_break_cancelled = cancel_work_sync(&cifs_file->oplock_break);
@@ -732,6 +739,15 @@ reopen_success:
* to the server to get the new inode info.
*/
+ /*
+ * If the server returned a read oplock and we have mandatory brlocks,
+ * set oplock level to None.
+ */
+ if (server->ops->is_read_op(oplock) && cifs_has_mand_locks(cinode)) {
+ cifs_dbg(FYI, "Reset oplock val from read to None due to mand locks\n");
+ oplock = 0;
+ }
+
server->ops->set_fid(cfile, &cfile->fid, oplock);
if (oparms.reconnect)
cifs_relock_file(cfile);
@@ -753,6 +769,36 @@ int cifs_close(struct inode *inode, struct file *file)
return 0;
}
+void
+cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
+{
+ struct cifsFileInfo *open_file;
+ struct list_head *tmp;
+ struct list_head *tmp1;
+ struct list_head tmp_list;
+
+ cifs_dbg(FYI, "Reopen persistent handles");
+ INIT_LIST_HEAD(&tmp_list);
+
+ /* list all files open on tree connection, reopen resilient handles */
+ spin_lock(&tcon->open_file_lock);
+ list_for_each(tmp, &tcon->openFileList) {
+ open_file = list_entry(tmp, struct cifsFileInfo, tlist);
+ if (!open_file->invalidHandle)
+ continue;
+ cifsFileInfo_get(open_file);
+ list_add_tail(&open_file->rlist, &tmp_list);
+ }
+ spin_unlock(&tcon->open_file_lock);
+
+ list_for_each_safe(tmp, tmp1, &tmp_list) {
+ open_file = list_entry(tmp, struct cifsFileInfo, rlist);
+ cifs_reopen_file(open_file, false /* do not flush */);
+ list_del_init(&open_file->rlist);
+ cifsFileInfo_put(open_file);
+ }
+}
+
int cifs_closedir(struct inode *inode, struct file *file)
{
int rc = 0;
@@ -772,10 +818,10 @@ int cifs_closedir(struct inode *inode, struct file *file)
server = tcon->ses->server;
cifs_dbg(FYI, "Freeing private data in close dir\n");
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&cfile->file_info_lock);
if (server->ops->dir_needs_close(cfile)) {
cfile->invalidHandle = true;
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&cfile->file_info_lock);
if (server->ops->close_dir)
rc = server->ops->close_dir(xid, tcon, &cfile->fid);
else
@@ -784,7 +830,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
/* not much we can do if it fails anyway, ignore rc */
rc = 0;
} else
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&cfile->file_info_lock);
buf = cfile->srch_inf.ntwrk_buf_start;
if (buf) {
@@ -1728,12 +1774,13 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
{
struct cifsFileInfo *open_file = NULL;
struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
/* only filter by fsuid on multiuser mounts */
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
fsuid_only = false;
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&tcon->open_file_lock);
/* we could simply get the first_list_entry since write-only entries
are always at the end of the list but since the first entry might
have a close pending, we go through the whole list */
@@ -1744,8 +1791,8 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
if (!open_file->invalidHandle) {
/* found a good file */
/* lock it so it will not be closed on us */
- cifsFileInfo_get_locked(open_file);
- spin_unlock(&cifs_file_list_lock);
+ cifsFileInfo_get(open_file);
+ spin_unlock(&tcon->open_file_lock);
return open_file;
} /* else might as well continue, and look for
another, or simply have the caller reopen it
@@ -1753,7 +1800,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
} else /* write only file */
break; /* write only files are last so must be done */
}
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tcon->open_file_lock);
return NULL;
}
@@ -1762,6 +1809,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
{
struct cifsFileInfo *open_file, *inv_file = NULL;
struct cifs_sb_info *cifs_sb;
+ struct cifs_tcon *tcon;
bool any_available = false;
int rc;
unsigned int refind = 0;
@@ -1777,15 +1825,16 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
}
cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
+ tcon = cifs_sb_master_tcon(cifs_sb);
/* only filter by fsuid on multiuser mounts */
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
fsuid_only = false;
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&tcon->open_file_lock);
refind_writable:
if (refind > MAX_REOPEN_ATT) {
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tcon->open_file_lock);
return NULL;
}
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
@@ -1796,8 +1845,8 @@ refind_writable:
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
if (!open_file->invalidHandle) {
/* found a good writable file */
- cifsFileInfo_get_locked(open_file);
- spin_unlock(&cifs_file_list_lock);
+ cifsFileInfo_get(open_file);
+ spin_unlock(&tcon->open_file_lock);
return open_file;
} else {
if (!inv_file)
@@ -1813,24 +1862,24 @@ refind_writable:
if (inv_file) {
any_available = false;
- cifsFileInfo_get_locked(inv_file);
+ cifsFileInfo_get(inv_file);
}
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tcon->open_file_lock);
if (inv_file) {
rc = cifs_reopen_file(inv_file, false);
if (!rc)
return inv_file;
else {
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&tcon->open_file_lock);
list_move_tail(&inv_file->flist,
&cifs_inode->openFileList);
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tcon->open_file_lock);
cifsFileInfo_put(inv_file);
- spin_lock(&cifs_file_list_lock);
++refind;
inv_file = NULL;
+ spin_lock(&tcon->open_file_lock);
goto refind_writable;
}
}
@@ -1878,7 +1927,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
write_data, to - from, &offset);
cifsFileInfo_put(open_file);
/* Does mm or vfs already set times? */
- inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
+ inode->i_atime = inode->i_mtime = current_time(inode);
if ((bytes_written > 0) && (offset))
rc = 0;
else if (bytes_written < 0)
@@ -2478,7 +2527,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
size_t cur_len;
unsigned long nr_pages, num_pages, i;
struct cifs_writedata *wdata;
- struct iov_iter saved_from;
+ struct iov_iter saved_from = *from;
loff_t saved_offset = offset;
pid_t pid;
struct TCP_Server_Info *server;
@@ -2489,7 +2538,6 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
pid = current->tgid;
server = tlink_tcon(open_file->tlink)->ses->server;
- memcpy(&saved_from, from, sizeof(struct iov_iter));
do {
unsigned int wsize, credits;
@@ -2551,8 +2599,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
kref_put(&wdata->refcount,
cifs_uncached_writedata_release);
if (rc == -EAGAIN) {
- memcpy(from, &saved_from,
- sizeof(struct iov_iter));
+ *from = saved_from;
iov_iter_advance(from, offset - saved_offset);
continue;
}
@@ -2576,7 +2623,7 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)
struct cifs_sb_info *cifs_sb;
struct cifs_writedata *wdata, *tmp;
struct list_head wdata_list;
- struct iov_iter saved_from;
+ struct iov_iter saved_from = *from;
int rc;
/*
@@ -2597,8 +2644,6 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)
if (!tcon->ses->server->ops->async_writev)
return -ENOSYS;
- memcpy(&saved_from, from, sizeof(struct iov_iter));
-
rc = cifs_write_from_iter(iocb->ki_pos, iov_iter_count(from), from,
open_file, cifs_sb, &wdata_list);
@@ -2631,13 +2676,11 @@ restart_loop:
/* resend call if it's a retryable error */
if (rc == -EAGAIN) {
struct list_head tmp_list;
- struct iov_iter tmp_from;
+ struct iov_iter tmp_from = saved_from;
INIT_LIST_HEAD(&tmp_list);
list_del_init(&wdata->list);
- memcpy(&tmp_from, &saved_from,
- sizeof(struct iov_iter));
iov_iter_advance(&tmp_from,
wdata->offset - iocb->ki_pos);
@@ -3571,7 +3614,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
cifs_dbg(FYI, "Bytes read %d\n", rc);
file_inode(file)->i_atime =
- current_fs_time(file_inode(file)->i_sb);
+ current_time(file_inode(file));
if (PAGE_SIZE > rc)
memset(read_data + rc, 0, PAGE_SIZE - rc);
@@ -3618,15 +3661,17 @@ static int cifs_readpage(struct file *file, struct page *page)
static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
{
struct cifsFileInfo *open_file;
+ struct cifs_tcon *tcon =
+ cifs_sb_master_tcon(CIFS_SB(cifs_inode->vfs_inode.i_sb));
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&tcon->open_file_lock);
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tcon->open_file_lock);
return 1;
}
}
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tcon->open_file_lock);
return 0;
}
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index b87efd0c92d6..7ab5be7944aa 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1951,7 +1951,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
full_path, inode, inode->i_count.counter,
- dentry, dentry->d_time, jiffies);
+ dentry, cifs_get_time(dentry), jiffies);
if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
@@ -2154,7 +2154,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
attrs->ia_valid |= ATTR_FORCE;
- rc = inode_change_ok(inode, attrs);
+ rc = setattr_prepare(direntry, attrs);
if (rc < 0)
goto out;
@@ -2294,7 +2294,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
attrs->ia_valid |= ATTR_FORCE;
- rc = inode_change_ok(inode, attrs);
+ rc = setattr_prepare(direntry, attrs);
if (rc < 0) {
free_xid(xid);
return rc;
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 7a3b84e300f8..9f51b81119f2 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -189,7 +189,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
xid = get_xid();
cifs_sb = CIFS_SB(inode->i_sb);
-
+ cifs_dbg(VFS, "cifs ioctl 0x%x\n", command);
switch (command) {
case FS_IOC_GETFLAGS:
if (pSMBFile == NULL)
@@ -267,11 +267,23 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
tcon = tlink_tcon(pSMBFile->tlink);
rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg);
break;
+ case CIFS_ENUMERATE_SNAPSHOTS:
+ if (arg == 0) {
+ rc = -EINVAL;
+ goto cifs_ioc_exit;
+ }
+ tcon = tlink_tcon(pSMBFile->tlink);
+ if (tcon->ses->server->ops->enum_snapshots)
+ rc = tcon->ses->server->ops->enum_snapshots(xid, tcon,
+ pSMBFile, (void __user *)arg);
+ else
+ rc = -EOPNOTSUPP;
+ break;
default:
cifs_dbg(FYI, "unsupported ioctl\n");
break;
}
-
+cifs_ioc_exit:
free_xid(xid);
return rc;
}
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 062c2375549a..d031af8d3d4d 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -399,7 +399,7 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
io_parms.offset = 0;
io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
- rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf, NULL, 0);
+ rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf);
CIFSSMBClose(xid, tcon, fid.netfid);
return rc;
}
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 813fe13c2ae1..c6729156f9a0 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -120,6 +120,7 @@ tconInfoAlloc(void)
++ret_buf->tc_count;
INIT_LIST_HEAD(&ret_buf->openFileList);
INIT_LIST_HEAD(&ret_buf->tcon_list);
+ spin_lock_init(&ret_buf->open_file_lock);
#ifdef CONFIG_CIFS_STATS
spin_lock_init(&ret_buf->stat_lock);
#endif
@@ -465,7 +466,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
continue;
cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&tcon->open_file_lock);
list_for_each(tmp2, &tcon->openFileList) {
netfile = list_entry(tmp2, struct cifsFileInfo,
tlist);
@@ -495,11 +496,11 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
&netfile->oplock_break);
netfile->oplock_break_cancelled = false;
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tcon->open_file_lock);
spin_unlock(&cifs_tcp_ses_lock);
return true;
}
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tcon->open_file_lock);
spin_unlock(&cifs_tcp_ses_lock);
cifs_dbg(FYI, "No matching file for oplock break\n");
return true;
@@ -613,9 +614,9 @@ backup_cred(struct cifs_sb_info *cifs_sb)
void
cifs_del_pending_open(struct cifs_pending_open *open)
{
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&tlink_tcon(open->tlink)->open_file_lock);
list_del(&open->olist);
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
}
void
@@ -635,7 +636,7 @@ void
cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
struct cifs_pending_open *open)
{
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&tlink_tcon(tlink)->open_file_lock);
cifs_add_pending_open_locked(fid, tlink, open);
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 65cf85dcda09..8f6a2a5863b9 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -597,14 +597,14 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) {
/* close and restart search */
cifs_dbg(FYI, "search backing up - close and restart search\n");
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&cfile->file_info_lock);
if (server->ops->dir_needs_close(cfile)) {
cfile->invalidHandle = true;
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&cfile->file_info_lock);
if (server->ops->close_dir)
server->ops->close_dir(xid, tcon, &cfile->fid);
} else
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&cfile->file_info_lock);
if (cfile->srch_inf.ntwrk_buf_start) {
cifs_dbg(FYI, "freeing SMB ff cache buf on search rewind\n");
if (cfile->srch_inf.smallBuf)
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index 4f0231e685a9..1238cd3552f9 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -266,9 +266,15 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
struct tcon_link *tlink;
int rc;
+ if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) &&
+ (buf->LastWriteTime == 0) && (buf->ChangeTime) &&
+ (buf->Attributes == 0))
+ return 0; /* would be a no op, no sense sending this */
+
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
+
rc = smb2_open_op_close(xid, tlink_tcon(tlink), cifs_sb, full_path,
FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf,
SMB2_OP_SET_INFO);
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 389fb9f8c84e..3d383489b9cf 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -549,19 +549,19 @@ smb2_is_valid_lease_break(char *buffer)
list_for_each(tmp1, &server->smb_ses_list) {
ses = list_entry(tmp1, struct cifs_ses, smb_ses_list);
- spin_lock(&cifs_file_list_lock);
list_for_each(tmp2, &ses->tcon_list) {
tcon = list_entry(tmp2, struct cifs_tcon,
tcon_list);
+ spin_lock(&tcon->open_file_lock);
cifs_stats_inc(
&tcon->stats.cifs_stats.num_oplock_brks);
if (smb2_tcon_has_lease(tcon, rsp, lw)) {
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tcon->open_file_lock);
spin_unlock(&cifs_tcp_ses_lock);
return true;
}
+ spin_unlock(&tcon->open_file_lock);
}
- spin_unlock(&cifs_file_list_lock);
}
}
spin_unlock(&cifs_tcp_ses_lock);
@@ -603,7 +603,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
tcon = list_entry(tmp1, struct cifs_tcon, tcon_list);
cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
- spin_lock(&cifs_file_list_lock);
+ spin_lock(&tcon->open_file_lock);
list_for_each(tmp2, &tcon->openFileList) {
cfile = list_entry(tmp2, struct cifsFileInfo,
tlist);
@@ -615,7 +615,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
cifs_dbg(FYI, "file id match, oplock break\n");
cinode = CIFS_I(d_inode(cfile->dentry));
-
+ spin_lock(&cfile->file_info_lock);
if (!CIFS_CACHE_WRITE(cinode) &&
rsp->OplockLevel == SMB2_OPLOCK_LEVEL_NONE)
cfile->oplock_break_cancelled = true;
@@ -637,14 +637,14 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
clear_bit(
CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
&cinode->flags);
-
+ spin_unlock(&cfile->file_info_lock);
queue_work(cifsiod_wq, &cfile->oplock_break);
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tcon->open_file_lock);
spin_unlock(&cifs_tcp_ses_lock);
return true;
}
- spin_unlock(&cifs_file_list_lock);
+ spin_unlock(&tcon->open_file_lock);
spin_unlock(&cifs_tcp_ses_lock);
cifs_dbg(FYI, "No matching file for oplock break\n");
return true;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index d203c0329626..5d456ebb3813 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -28,6 +28,7 @@
#include "cifs_unicode.h"
#include "smb2status.h"
#include "smb2glob.h"
+#include "cifs_ioctl.h"
static int
change_conf(struct TCP_Server_Info *server)
@@ -70,6 +71,10 @@ smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
spin_lock(&server->req_lock);
val = server->ops->get_credits_field(server, optype);
*val += add;
+ if (*val > 65000) {
+ *val = 65000; /* Don't get near 64K credits, avoid srv bugs */
+ printk_once(KERN_WARNING "server overflowed SMB3 credits\n");
+ }
server->in_flight--;
if (server->in_flight == 0 && (optype & CIFS_OP_MASK) != CIFS_NEG_OP)
rc = change_conf(server);
@@ -287,7 +292,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
cifs_dbg(FYI, "Link Speed %lld\n",
le64_to_cpu(out_buf->LinkSpeed));
}
-
+ kfree(out_buf);
return rc;
}
#endif /* STATS2 */
@@ -541,6 +546,7 @@ smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
server->ops->set_oplock_level(cinode, oplock, fid->epoch,
&fid->purge_cache);
cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
+ memcpy(cfile->fid.create_guid, fid->create_guid, 16);
}
static void
@@ -699,6 +705,7 @@ smb2_clone_range(const unsigned int xid,
cchunk_out:
kfree(pcchunk);
+ kfree(retbuf);
return rc;
}
@@ -823,7 +830,6 @@ smb2_duplicate_extents(const unsigned int xid,
{
int rc;
unsigned int ret_data_len;
- char *retbuf = NULL;
struct duplicate_extents_to_file dup_ext_buf;
struct cifs_tcon *tcon = tlink_tcon(trgtfile->tlink);
@@ -849,7 +855,7 @@ smb2_duplicate_extents(const unsigned int xid,
FSCTL_DUPLICATE_EXTENTS_TO_FILE,
true /* is_fsctl */, (char *)&dup_ext_buf,
sizeof(struct duplicate_extents_to_file),
- (char **)&retbuf,
+ NULL,
&ret_data_len);
if (ret_data_len > 0)
@@ -872,7 +878,6 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
struct cifsFileInfo *cfile)
{
struct fsctl_set_integrity_information_req integr_info;
- char *retbuf = NULL;
unsigned int ret_data_len;
integr_info.ChecksumAlgorithm = cpu_to_le16(CHECKSUM_TYPE_UNCHANGED);
@@ -884,9 +889,53 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
FSCTL_SET_INTEGRITY_INFORMATION,
true /* is_fsctl */, (char *)&integr_info,
sizeof(struct fsctl_set_integrity_information_req),
+ NULL,
+ &ret_data_len);
+
+}
+
+static int
+smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile, void __user *ioc_buf)
+{
+ char *retbuf = NULL;
+ unsigned int ret_data_len = 0;
+ int rc;
+ struct smb_snapshot_array snapshot_in;
+
+ rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ FSCTL_SRV_ENUMERATE_SNAPSHOTS,
+ true /* is_fsctl */, NULL, 0 /* no input data */,
(char **)&retbuf,
&ret_data_len);
+ cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d\n",
+ rc, ret_data_len);
+ if (rc)
+ return rc;
+ if (ret_data_len && (ioc_buf != NULL) && (retbuf != NULL)) {
+ /* Fixup buffer */
+ if (copy_from_user(&snapshot_in, ioc_buf,
+ sizeof(struct smb_snapshot_array))) {
+ rc = -EFAULT;
+ kfree(retbuf);
+ return rc;
+ }
+ if (snapshot_in.snapshot_array_size < sizeof(struct smb_snapshot_array)) {
+ rc = -ERANGE;
+ return rc;
+ }
+
+ if (ret_data_len > snapshot_in.snapshot_array_size)
+ ret_data_len = snapshot_in.snapshot_array_size;
+
+ if (copy_to_user(ioc_buf, retbuf, ret_data_len))
+ rc = -EFAULT;
+ }
+
+ kfree(retbuf);
+ return rc;
}
static int
@@ -1041,7 +1090,7 @@ smb2_set_lease_key(struct inode *inode, struct cifs_fid *fid)
static void
smb2_new_lease_key(struct cifs_fid *fid)
{
- get_random_bytes(fid->lease_key, SMB2_LEASE_KEY_SIZE);
+ generate_random_uuid(fid->lease_key);
}
#define SMB2_SYMLINK_STRUCT_SIZE \
@@ -1654,6 +1703,7 @@ struct smb_version_operations smb21_operations = {
.clone_range = smb2_clone_range,
.wp_retry_size = smb2_wp_retry_size,
.dir_needs_close = smb2_dir_needs_close,
+ .enum_snapshots = smb3_enum_snapshots,
};
struct smb_version_operations smb30_operations = {
@@ -1740,6 +1790,7 @@ struct smb_version_operations smb30_operations = {
.wp_retry_size = smb2_wp_retry_size,
.dir_needs_close = smb2_dir_needs_close,
.fallocate = smb3_fallocate,
+ .enum_snapshots = smb3_enum_snapshots,
};
#ifdef CONFIG_CIFS_SMB311
@@ -1827,6 +1878,7 @@ struct smb_version_operations smb311_operations = {
.wp_retry_size = smb2_wp_retry_size,
.dir_needs_close = smb2_dir_needs_close,
.fallocate = smb3_fallocate,
+ .enum_snapshots = smb3_enum_snapshots,
};
#endif /* CIFS_SMB311 */
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 29e06db5f187..5ca5ea4668a1 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -100,7 +100,21 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ ,
hdr->ProtocolId = SMB2_PROTO_NUMBER;
hdr->StructureSize = cpu_to_le16(64);
hdr->Command = smb2_cmd;
- hdr->CreditRequest = cpu_to_le16(2); /* BB make this dynamic */
+ if (tcon && tcon->ses && tcon->ses->server) {
+ struct TCP_Server_Info *server = tcon->ses->server;
+
+ spin_lock(&server->req_lock);
+ /* Request up to 2 credits but don't go over the limit. */
+ if (server->credits >= server->max_credits)
+ hdr->CreditRequest = cpu_to_le16(0);
+ else
+ hdr->CreditRequest = cpu_to_le16(
+ min_t(int, server->max_credits -
+ server->credits, 2));
+ spin_unlock(&server->req_lock);
+ } else {
+ hdr->CreditRequest = cpu_to_le16(2);
+ }
hdr->ProcessId = cpu_to_le32((__u16)current->tgid);
if (!tcon)
@@ -236,8 +250,13 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
}
cifs_mark_open_files_invalid(tcon);
+
rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nls_codepage);
mutex_unlock(&tcon->ses->session_mutex);
+
+ if (tcon->use_persistent)
+ cifs_reopen_persistent_handles(tcon);
+
cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
if (rc)
goto out;
@@ -574,59 +593,42 @@ vneg_out:
return -EIO;
}
-int
-SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
- const struct nls_table *nls_cp)
+struct SMB2_sess_data {
+ unsigned int xid;
+ struct cifs_ses *ses;
+ struct nls_table *nls_cp;
+ void (*func)(struct SMB2_sess_data *);
+ int result;
+ u64 previous_session;
+
+ /* we will send the SMB in three pieces:
+ * a fixed length beginning part, an optional
+ * SPNEGO blob (which can be zero length), and a
+ * last part which will include the strings
+ * and rest of bcc area. This allows us to avoid
+ * a large buffer 17K allocation
+ */
+ int buf0_type;
+ struct kvec iov[2];
+};
+
+static int
+SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
{
+ int rc;
+ struct cifs_ses *ses = sess_data->ses;
struct smb2_sess_setup_req *req;
- struct smb2_sess_setup_rsp *rsp = NULL;
- struct kvec iov[2];
- int rc = 0;
- int resp_buftype = CIFS_NO_BUFFER;
- __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
struct TCP_Server_Info *server = ses->server;
- u16 blob_length = 0;
- struct key *spnego_key = NULL;
- char *security_blob = NULL;
- unsigned char *ntlmssp_blob = NULL;
- bool use_spnego = false; /* else use raw ntlmssp */
-
- cifs_dbg(FYI, "Session Setup\n");
-
- if (!server) {
- WARN(1, "%s: server is NULL!\n", __func__);
- return -EIO;
- }
-
- /*
- * If we are here due to reconnect, free per-smb session key
- * in case signing was required.
- */
- kfree(ses->auth_key.response);
- ses->auth_key.response = NULL;
-
- /*
- * If memory allocation is successful, caller of this function
- * frees it.
- */
- ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
- if (!ses->ntlmssp)
- return -ENOMEM;
- ses->ntlmssp->sesskey_per_smbsess = true;
-
- /* FIXME: allow for other auth types besides NTLMSSP (e.g. krb5) */
- if (ses->sectype != Kerberos && ses->sectype != RawNTLMSSP)
- ses->sectype = RawNTLMSSP;
-
-ssetup_ntlmssp_authenticate:
- if (phase == NtLmChallenge)
- phase = NtLmAuthenticate; /* if ntlmssp, now final phase */
rc = small_smb2_init(SMB2_SESSION_SETUP, NULL, (void **) &req);
if (rc)
return rc;
req->hdr.SessionId = 0; /* First session, not a reauthenticate */
+
+ /* if reconnect, we need to send previous sess id, otherwise it is 0 */
+ req->PreviousSessionId = sess_data->previous_session;
+
req->Flags = 0; /* MBZ */
/* to enable echos and oplocks */
req->hdr.CreditRequest = cpu_to_le16(3);
@@ -642,199 +644,368 @@ ssetup_ntlmssp_authenticate:
req->Capabilities = 0;
req->Channel = 0; /* MBZ */
- iov[0].iov_base = (char *)req;
+ sess_data->iov[0].iov_base = (char *)req;
/* 4 for rfc1002 length field and 1 for pad */