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/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/dir.c9
-rw-r--r--fs/afs/rxrpc.c2
-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/bad_inode.c25
-rw-r--r--fs/bfs/dir.c20
-rw-r--r--fs/binfmt_misc.c2
-rw-r--r--fs/block_dev.c77
-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.h117
-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.c237
-rw-r--r--fs/btrfs/disk-io.h2
-rw-r--r--fs/btrfs/extent-tree.c198
-rw-r--r--fs/btrfs/extent_io.c170
-rw-r--r--fs/btrfs/extent_io.h4
-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.c20
-rw-r--r--fs/btrfs/inode-map.c31
-rw-r--r--fs/btrfs/inode.c125
-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/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/cifsfs.c11
-rw-r--r--fs/cifs/cifsfs.h10
-rw-r--r--fs/cifs/cifsproto.h3
-rw-r--r--fs/cifs/cifssmb.c27
-rw-r--r--fs/cifs/dir.c6
-rw-r--r--fs/cifs/file.c18
-rw-r--r--fs/cifs/inode.c6
-rw-r--r--fs/cifs/link.c2
-rw-r--r--fs/coda/dir.c8
-rw-r--r--fs/coda/file.c2
-rw-r--r--fs/coda/inode.c2
-rw-r--r--fs/compat.c16
-rw-r--r--fs/configfs/inode.c6
-rw-r--r--fs/debugfs/inode.c4
-rw-r--r--fs/devpts/inode.c6
-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.c2
-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/ext2/acl.c12
-rw-r--r--fs/ext2/dir.c6
-rw-r--r--fs/ext2/file.c3
-rw-r--r--fs/ext2/ialloc.c2
-rw-r--r--fs/ext2/inode.c6
-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/file.c3
-rw-r--r--fs/ext4/inode.c2
-rw-r--r--fs/ext4/namei.c8
-rw-r--r--fs/ext4/page-io.c2
-rw-r--r--fs/ext4/symlink.c9
-rw-r--r--fs/f2fs/acl.c6
-rw-r--r--fs/f2fs/data.c2
-rw-r--r--fs/f2fs/dir.c8
-rw-r--r--fs/f2fs/file.c13
-rw-r--r--fs/f2fs/inline.c2
-rw-r--r--fs/f2fs/namei.c26
-rw-r--r--fs/f2fs/node.c7
-rw-r--r--fs/f2fs/xattr.c2
-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/control.c2
-rw-r--r--fs/fuse/dir.c20
-rw-r--r--fs/fuse/file.c2
-rw-r--r--fs/fuse/fuse_i.h2
-rw-r--r--fs/gfs2/acl.c12
-rw-r--r--fs/gfs2/bmap.c8
-rw-r--r--fs/gfs2/dir.c12
-rw-r--r--fs/gfs2/inode.c21
-rw-r--r--fs/gfs2/quota.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.c12
-rw-r--r--fs/inode.c105
-rw-r--r--fs/internal.h11
-rw-r--r--fs/jbd2/commit.c3
-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/namei.c32
-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.c9
-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.c55
-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/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/namei.c17
-rw-r--r--fs/namespace.c2
-rw-r--r--fs/ncpfs/dir.c11
-rw-r--r--fs/ncpfs/inode.c2
-rw-r--r--fs/nfs/dir.c6
-rw-r--r--fs/nfs/internal.h3
-rw-r--r--fs/nfs/nfs3proc.c6
-rw-r--r--fs/nfs/nfs4proc.c6
-rw-r--r--fs/nfsd/blocklayout.c2
-rw-r--r--fs/nfsd/nfsproc.c8
-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/nsfs.c2
-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/dir.c4
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c3
-rw-r--r--fs/ocfs2/dlmfs/dlmfs.c6
-rw-r--r--fs/ocfs2/file.c17
-rw-r--r--fs/ocfs2/move_extents.c2
-rw-r--r--fs/ocfs2/namei.c19
-rw-r--r--fs/ocfs2/refcounttree.c4
-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.c20
-rw-r--r--fs/openpromfs/inode.c2
-rw-r--r--fs/orangefs/acl.c15
-rw-r--r--fs/orangefs/dir.c4
-rw-r--r--fs/orangefs/file.c6
-rw-r--r--fs/orangefs/inode.c19
-rw-r--r--fs/orangefs/namei.c63
-rw-r--r--fs/orangefs/orangefs-debugfs.c4
-rw-r--r--fs/orangefs/symlink.c1
-rw-r--r--fs/orangefs/xattr.c3
-rw-r--r--fs/overlayfs/copy_up.c4
-rw-r--r--fs/overlayfs/dir.c5
-rw-r--r--fs/overlayfs/inode.c8
-rw-r--r--fs/overlayfs/overlayfs.h4
-rw-r--r--fs/overlayfs/super.c6
-rw-r--r--fs/pipe.c168
-rw-r--r--fs/posix_acl.c62
-rw-r--r--fs/proc/base.c49
-rw-r--r--fs/proc/fd.c8
-rw-r--r--fs/proc/fd.h2
-rw-r--r--fs/proc/generic.c2
-rw-r--r--fs/proc/inode.c3
-rw-r--r--fs/proc/internal.h2
-rw-r--r--fs/proc/proc_sysctl.c4
-rw-r--r--fs/proc/self.c2
-rw-r--r--fs/proc/thread_self.c2
-rw-r--r--fs/pstore/inode.c2
-rw-r--r--fs/ramfs/file-nommu.c2
-rw-r--r--fs/ramfs/inode.c6
-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.c2
-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/splice.c12
-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/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.c2
-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/xfs_acl.c15
-rw-r--r--fs/xfs/xfs_file.c4
-rw-r--r--fs/xfs/xfs_inode.c4
-rw-r--r--fs/xfs/xfs_ioctl.c2
-rw-r--r--fs/xfs/xfs_iops.c113
-rw-r--r--fs/xfs/xfs_iops.h3
-rw-r--r--fs/xfs/xfs_trans_inode.c2
306 files changed, 3716 insertions, 2715 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/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/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/rxrpc.c b/fs/afs/rxrpc.c
index 59bdaa7527b6..477928b25940 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -418,7 +418,7 @@ static void afs_deliver_to_call(struct afs_call *call)
&call->abort_code);
if (ret == -EINPROGRESS || ret == -EAGAIN)
return;
- if (ret == 1) {
+ if (ret == 1 || ret < 0) {
call->state = AFS_CALL_COMPLETE;
goto done;
}
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/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/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_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 376e4e426324..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"
@@ -1775,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,
@@ -1789,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..6c21bad26a27 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"
@@ -676,9 +677,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 +924,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 +1000,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 +1063,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 +1081,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 +1435,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 +2293,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 +2882,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 +3137,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 +3180,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 +3255,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 +3336,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 +3375,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 +3412,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..e720d3e6ec20 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;
}
@@ -2710,8 +2730,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 +2781,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);
@@ -3199,10 +3218,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 +3625,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 +3911,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 +3956,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 +3981,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 +4052,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 +4103,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 +4115,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 +4143,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 +4194,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 +4221,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 +4240,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 +4493,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..ee40384c394d 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;
}
@@ -5713,14 +5747,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 +5794,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..4a094f1dc7ef 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -359,7 +359,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 +413,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..e4a42a8e4f84 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);
@@ -261,7 +261,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);
@@ -442,7 +443,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 +1165,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 +1185,7 @@ 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;
+ 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;
@@ -1480,7 +1482,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 +1545,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 ca01106795ea..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;
}
@@ -8619,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
@@ -9055,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);
@@ -9377,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);
@@ -9493,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);
@@ -9861,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);
@@ -9886,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;
@@ -10404,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) &&
@@ -10544,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,
@@ -10567,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,
@@ -10648,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,
@@ -10662,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,
@@ -10676,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/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/cifsfs.c b/fs/cifs/cifsfs.c
index 14ae4b8e1a3c..cca04e710421 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -896,35 +896,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,
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/cifsproto.h b/fs/cifs/cifsproto.h
index 95dab43646f0..4ead72a001f9 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -392,8 +392,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..f82d2823622f 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -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/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..a95fe8b1afe9 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1878,7 +1878,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 +2478,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 +2489,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 +2550,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 +2574,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 +2595,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 +2627,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 +3565,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);
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/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/coda/dir.c b/fs/coda/dir.c
index 6fb8672c0892..c0474ac6cbf2 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -109,7 +109,7 @@ static inline void coda_dir_update_mtime(struct inode *dir)
/* optimistically we can also act as if our nose bleeds. The
* granularity of the mtime is coarse anyways so we might actually be
* right most of the time. Note: we only do this for directories. */
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
#endif
}
@@ -291,7 +291,8 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
/* rename */
static int coda_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 char *old_name = old_dentry->d_name.name;
const char *new_name = new_dentry->d_name.name;
@@ -299,6 +300,9 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
int new_length = new_dentry->d_name.len;
int error;
+ if (flags)
+ return -EINVAL;
+
error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
coda_i2f(new_dir), old_length, new_length,
(const char *) old_name, (const char *)new_name);
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 8415d4f8d1a1..6e0154eb6fcc 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -54,7 +54,7 @@ coda_file_write_iter(struct kiocb *iocb, struct iov_iter *to)
ret = vfs_iter_write(cfi->cfi_container, to, &iocb->ki_pos);
coda_inode->i_size = file_inode(host_file)->i_size;
coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9;
- coda_inode->i_mtime = coda_inode->i_ctime = CURRENT_TIME_SEC;
+ coda_inode->i_mtime = coda_inode->i_ctime = current_time(coda_inode);
inode_unlock(coda_inode);
file_end_write(host_file);
return ret;
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 57e81cbba0fa..71dbe7e287ce 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -271,7 +271,7 @@ int coda_setattr(struct dentry *de, struct iattr *iattr)
memset(&vattr, 0, sizeof(vattr));
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
coda_iattr_to_vattr(iattr, &vattr);
vattr.va_type = C_VNON; /* cannot set type */
diff --git a/fs/compat.c b/fs/compat.c
index be6e48b0a46c..bd064a2c3550 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -54,20 +54,6 @@
#include <asm/ioctls.h>
#include "internal.h"
-int compat_log = 1;
-
-int compat_printk(const char *fmt, ...)
-{
- va_list ap;
- int ret;
- if (!compat_log)
- return 0;
- va_start(ap, fmt);
- ret = vprintk(fmt, ap);
- va_end(ap);
- return ret;
-}
-
/*
* Not all architectures have sys_utime, so implement this in terms
* of sys_utimes.
@@ -562,7 +548,7 @@ ssize_t compat_rw_copy_check_uvector(int type,
goto out;
ret = -EINVAL;
- if (nr_segs > UIO_MAXIOV || nr_segs < 0)
+ if (nr_segs > UIO_MAXIOV)
goto out;
if (nr_segs > fast_segs) {
ret = -ENOMEM;
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index 0387968e6f47..ad718e5e37bb 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -76,7 +76,7 @@ int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
sd_iattr->ia_uid = GLOBAL_ROOT_UID;
sd_iattr->ia_gid = GLOBAL_ROOT_GID;
sd_iattr->ia_atime = sd_iattr->ia_mtime =
- sd_iattr->ia_ctime = current_fs_time(inode->i_sb);
+ sd_iattr->ia_ctime = current_time(inode);
sd->s_iattr = sd_iattr;
}
/* attributes were changed atleast once in past */
@@ -113,7 +113,7 @@ static inline void set_default_inode_attr(struct inode * inode, umode_t mode)
{
inode->i_mode = mode;
inode->i_atime = inode->i_mtime =
- inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_ctime = current_time(inode);
}
static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
@@ -197,7 +197,7 @@ int configfs_create(struct dentry * dentry, umode_t mode, void (*init)(struct in
return -ENOMEM;
p_inode = d_inode(dentry->d_parent);
- p_inode->i_mtime = p_inode->i_ctime = current_fs_time(p_inode->i_sb);
+ p_inode->i_mtime = p_inode->i_ctime = current_time(p_inode);
configfs_set_inode_lock_class(sd, inode);
init(inode);
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 72361baf9da7..f17fcf89e18e 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -45,7 +45,7 @@ static struct inode *debugfs_get_inode(struct super_block *sb)
if (inode) {
inode->i_ino = get_next_ino();
inode->i_atime = inode->i_mtime =
- inode->i_ctime = current_fs_time(sb);
+ inode->i_ctime = current_time(inode);
}
return inode;
}
@@ -748,7 +748,7 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
old_name = fsnotify_oldname_init(old_dentry->d_name.name);
error = simple_rename(d_inode(old_dir), old_dentry, d_inode(new_dir),
- dentry);
+ dentry, 0);
if (error) {
fsnotify_oldname_free(old_name);
goto exit;
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 442d1a7e671b..108df2e3602c 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -300,7 +300,7 @@ static int mknod_ptmx(struct super_block *sb)
}
inode->i_ino = 2;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
mode = S_IFCHR|opts->ptmxmode;
init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2));
@@ -412,7 +412,7 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
if (!inode)
goto fail;
inode->i_ino = 1;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
@@ -540,7 +540,7 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv)
inode->i_ino = index + 3;
inode->i_uid = opts->setuid ? opts->uid : current_fsuid();
inode->i_gid = opts->setgid ? opts->gid : current_fsgid();
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
init_special_inode(inode, S_IFCHR|opts->mode, MKDEV(UNIX98_PTY_SLAVE_MAJOR, index));
sprintf(s, "%d", index);
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 963016c8f3d1..609998de533e 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -1656,16 +1656,12 @@ void dlm_lowcomms_stop(void)
mutex_lock(&connections_lock);
dlm_allow_conn = 0;
foreach_conn(stop_conn);
+ clean_writequeues();
+ foreach_conn(free_conn);
mutex_unlock(&connections_lock);
work_stop();
- mutex_lock(&connections_lock);
- clean_writequeues();
-
- foreach_conn(free_conn);
-
- mutex_unlock(&connections_lock);
kmem_cache_destroy(con_cache);
}
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 4ba1547bb9ad..599a29237cfe 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -715,4 +715,6 @@ int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
loff_t offset);
+extern const struct xattr_handler *ecryptfs_xattr_handlers[];
+
#endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 9d153b6a1d72..cf390dceddd2 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -577,7 +577,8 @@ out:
static int
ecryptfs_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 rc;
struct dentry *lower_old_dentry;
@@ -587,6 +588,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct dentry *trap = NULL;
struct inode *target_inode;
+ if (flags)
+ return -EINVAL;
+
lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
dget(lower_old_dentry);
@@ -927,7 +931,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
}
mutex_unlock(&crypt_stat->cs_mutex);
- rc = inode_change_ok(inode, ia);
+ rc = setattr_prepare(dentry, ia);
if (rc)
goto out;
if (ia->ia_valid & ATTR_SIZE) {
@@ -1005,15 +1009,14 @@ ecryptfs_setxattr(struct dentry *dentry, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
- int rc = 0;
+ int rc;
struct dentry *lower_dentry;
lower_dentry = ecryptfs_dentry_to_lower(dentry);
- if (!d_inode(lower_dentry)->i_op->setxattr) {
+ if (!(d_inode(lower_dentry)->i_opflags & IOP_XATTR)) {
rc = -EOPNOTSUPP;
goto out;
}
-
rc = vfs_setxattr(lower_dentry, name, value, size, flags);
if (!rc && inode)
fsstack_copy_attr_all(inode, d_inode(lower_dentry));
@@ -1025,15 +1028,14 @@ ssize_t
ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
const char *name, void *value, size_t size)
{
- int rc = 0;
+ int rc;
- if (!lower_inode->i_op->getxattr) {
+ if (!(lower_inode->i_opflags & IOP_XATTR)) {
rc = -EOPNOTSUPP;
goto out;
}
inode_lock(lower_inode);
- rc = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
- name, value, size);
+ rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size);
inode_unlock(lower_inode);
out:
return rc;
@@ -1066,19 +1068,22 @@ out:
return rc;
}
-static int ecryptfs_removexattr(struct dentry *dentry, const char *name)
+static int ecryptfs_removexattr(struct dentry *dentry, struct inode *inode,
+ const char *name)
{
- int rc = 0;
+ int rc;
struct dentry *lower_dentry;
+ struct inode *lower_inode;
lower_dentry = ecryptfs_dentry_to_lower(dentry);
- if (!d_inode(lower_dentry)->i_op->removexattr) {
+ lower_inode = ecryptfs_inode_to_lower(inode);
+ if (!(lower_inode->i_opflags & IOP_XATTR)) {
rc = -EOPNOTSUPP;
goto out;
}
- inode_lock(d_inode(lower_dentry));
- rc = d_inode(lower_dentry)->i_op->removexattr(lower_dentry, name);
- inode_unlock(d_inode(lower_dentry));
+ inode_lock(lower_inode);
+ rc = __vfs_removexattr(lower_dentry, name);
+ inode_unlock(lower_inode);
out:
return rc;
}
@@ -1089,10 +1094,7 @@ const struct inode_operations ecryptfs_symlink_iops = {
.permission = ecryptfs_permission,
.setattr = ecryptfs_setattr,
.getattr = ecryptfs_getattr_link,
- .setxattr = ecryptfs_setxattr,
- .getxattr = ecryptfs_getxattr,
.listxattr = ecryptfs_listxattr,
- .removexattr = ecryptfs_removexattr
};
const struct inode_operations ecryptfs_dir_iops = {
@@ -1107,18 +1109,43 @@ const struct inode_operations ecryptfs_dir_iops = {
.rename = ecryptfs_rename,
.permission = ecryptfs_permission,
.setattr = ecryptfs_setattr,
- .setxattr = ecryptfs_setxattr,
- .getxattr = ecryptfs_getxattr,
.listxattr = ecryptfs_listxattr,
- .removexattr = ecryptfs_removexattr
};
const struct inode_operations ecryptfs_main_iops = {
.permission = ecryptfs_permission,
.setattr = ecryptfs_setattr,
.getattr = ecryptfs_getattr,
- .setxattr = ecryptfs_setxattr,
- .getxattr = ecryptfs_getxattr,
.listxattr = ecryptfs_listxattr,
- .removexattr = ecryptfs_removexattr
+};
+
+static int ecryptfs_xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, void *buffer, size_t size)
+{
+ return ecryptfs_getxattr(dentry, inode, name, buffer, size);
+}
+
+static int ecryptfs_xattr_set(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, const void *value, size_t size,
+ int flags)
+{
+ if (value)
+ return ecryptfs_setxattr(dentry, inode, name, value, size, flags);
+ else {
+ BUG_ON(flags != XATTR_REPLACE);
+ return ecryptfs_removexattr(dentry, inode, name);
+ }
+}
+
+const struct xattr_handler ecryptfs_xattr_handler = {
+ .prefix = "", /* match anything */
+ .get = ecryptfs_xattr_get,
+ .set = ecryptfs_xattr_set,
+};
+
+const struct xattr_handler *ecryptfs_xattr_handlers[] = {
+ &ecryptfs_xattr_handler,
+ NULL
};
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 612004495141..151872dcc1f4 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -529,6 +529,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
/* ->kill_sb() will take care of sbi after that point */
sbi = NULL;
s->s_op = &ecryptfs_sops;
+ s->s_xattr = ecryptfs_xattr_handlers;
s->s_d_op = &ecryptfs_dops;
err = "Reading sb failed";
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 9c3437c8a5b1..1f0c471b4ba3 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -32,6 +32,7 @@
#include <linux/file.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
+#include <linux/xattr.h>
#include <asm/unaligned.h>
#include "ecryptfs_kernel.h"
@@ -422,7 +423,7 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
struct inode *lower_inode = d_inode(lower_dentry);
int rc;
- if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) {
+ if (!(lower_inode->i_opflags & IOP_XATTR)) {
printk(KERN_WARNING
"No support for setting xattr in lower filesystem\n");
rc = -ENOSYS;
@@ -436,15 +437,13 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
goto out;
}
inode_lock(lower_inode);
- size = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
- ECRYPTFS_XATTR_NAME,
- xattr_virt, PAGE_SIZE);
+ size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
+ xattr_virt, PAGE_SIZE);
if (size < 0)
size = 8;
put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
- rc = lower_inode->i_op->setxattr(lower_dentry, lower_inode,
- ECRYPTFS_XATTR_NAME,
- xattr_virt, size, 0);
+ rc = __vfs_setxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
+ xattr_virt, size, 0);
inode_unlock(lower_inode);
if (rc)
printk(KERN_ERR "Error whilst attempting to write inode size "
diff --git a/fs/efivarfs/inode.c b/fs/efivarfs/inode.c
index cbb50cadcffc..71fccccf317e 100644
--- a/fs/efivarfs/inode.c
+++ b/fs/efivarfs/inode.c
@@ -24,7 +24,7 @@ struct inode *efivarfs_get_inode(struct super_block *sb,
if (inode) {
inode->i_ino = get_next_ino();
inode->i_mode = mode;
- 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_flags = is_removable ? 0 : S_IMMUTABLE;
switch (mode & S_IFMT) {
case S_IFREG:
diff --git a/fs/exofs/dir.c b/fs/exofs/dir.c
index f69a1b5826a5..79101651fe9e 100644
--- a/fs/exofs/dir.c
+++ b/fs/exofs/dir.c
@@ -416,7 +416,7 @@ int exofs_set_link(struct inode *dir, struct exofs_dir_entry *de,
if (likely(!err))
err = exofs_commit_chunk(page, pos, len);
exofs_put_page(page);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty(dir);
return err;
}
@@ -503,7 +503,7 @@ got_it:
de->inode_no = cpu_to_le64(inode->i_ino);
exofs_set_de_type(de, inode);
err = exofs_commit_chunk(page, pos, rec_len);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty(dir);
sbi->s_numfiles++;
@@ -554,7 +554,7 @@ int exofs_delete_entry(struct exofs_dir_entry *dir, struct page *page)
dir->inode_no = 0;
if (likely(!err))
err = exofs_commit_chunk(page, pos, to - from);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
mark_inode_dirty(inode);
sbi->s_numfiles--;
out:
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index 9dc4c6dbf3c9..d8072bc074a4 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -778,7 +778,7 @@ try_again:
fail:
EXOFS_DBGMSG("Error: writepage_strip(0x%lx, 0x%lx)=>%d\n",
inode->i_ino, page->index, ret);
- set_bit(AS_EIO, &page->mapping->flags);
+ mapping_set_error(page->mapping, -EIO);
unlock_page(page);
return ret;
}
@@ -1007,7 +1007,7 @@ static int _do_truncate(struct inode *inode, loff_t newsize)
struct exofs_sb_info *sbi = inode->i_sb->s_fs_info;
int ret;
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
ret = ore_truncate(&sbi->layout, &oi->oc, (u64)newsize);
if (likely(!ret))
@@ -1034,7 +1034,7 @@ int exofs_setattr(struct dentry *dentry, struct iattr *iattr)
if (unlikely(error))
return error;
- error = inode_change_ok(inode, iattr);
+ error = setattr_prepare(dentry, iattr);
if (unlikely(error))
return error;
@@ -1313,7 +1313,7 @@ struct inode *exofs_new_inode(struct inode *dir, umode_t mode)
inode_init_owner(inode, dir, mode);
inode->i_ino = sbi->s_nextid++;
inode->i_blkbits = EXOFS_BLKSHIFT;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
oi->i_commit_size = inode->i_size = 0;
spin_lock(&sbi->s_next_gen_lock);
inode->i_generation = sbi->s_next_generation++;
diff --git a/fs/exofs/namei.c b/fs/exofs/namei.c
index 622a686bb08b..7295cd722770 100644
--- a/fs/exofs/namei.c
+++ b/fs/exofs/namei.c
@@ -142,7 +142,7 @@ static int exofs_link(struct dentry *old_dentry, struct inode *dir,
{
struct inode *inode = d_inode(old_dentry);
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
inode_inc_link_count(inode);
ihold(inode);
@@ -227,7 +227,8 @@ static int exofs_rmdir(struct inode *dir, struct dentry *dentry)
}
static int exofs_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 = d_inode(old_dentry);
struct inode *new_inode = d_inode(new_dentry);
@@ -237,6 +238,9 @@ static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct exofs_dir_entry *old_de;
int err = -ENOENT;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
old_de = exofs_find_entry(old_dir, old_dentry, &old_page);
if (!old_de)
goto out;
@@ -261,7 +265,7 @@ static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (!new_de)
goto out_dir;
err = exofs_set_link(new_dir, new_de, new_page, old_inode);
- new_inode->i_ctime = CURRENT_TIME;
+ new_inode->i_ctime = current_time(new_inode);
if (dir_de)
drop_nlink(new_inode);
inode_dec_link_count(new_inode);
@@ -275,7 +279,7 @@ static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry,
inode_inc_link_count(new_dir);
}
- old_inode->i_ctime = CURRENT_TIME;
+ old_inode->i_ctime = current_time(old_inode);
exofs_delete_entry(old_de, old_page);
mark_inode_dirty(old_inode);
@@ -310,7 +314,7 @@ const struct inode_operations exofs_dir_inode_operations = {
.mkdir = exofs_mkdir,
.rmdir = exofs_rmdir,
.mknod = exofs_mknod,
- .rename = exofs_rename,
+ .rename = exofs_rename,
.setattr = exofs_setattr,
};
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 42f1d1814083..79dafa71effd 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -190,15 +190,11 @@ ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
case ACL_TYPE_ACCESS:
name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (error < 0)
+ error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (error)
return error;
- else {
- inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
- if (error == 0)
- acl = NULL;
- }
+ inode->i_ctime = current_time(inode);
+ mark_inode_dirty(inode);
}
break;
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 61ad490ed67b..d9650c9508e4 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -471,7 +471,7 @@ void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
err = ext2_commit_chunk(page, pos, len);
ext2_put_page(page);
if (update_times)
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
mark_inode_dirty(dir);
}
@@ -561,7 +561,7 @@ got_it:
de->inode = cpu_to_le32(inode->i_ino);
ext2_set_de_type (de, inode);
err = ext2_commit_chunk(page, pos, rec_len);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
mark_inode_dirty(dir);
/* OFFSET_CACHE */
@@ -610,7 +610,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page )
pde->rec_len = ext2_rec_len_to_disk(to - from);
dir->inode = 0;
err = ext2_commit_chunk(page, pos, to - from);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
EXT2_I(inode)->i_flags &= ~EXT2_BTREE_FL;
mark_inode_dirty(inode);
out:
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 0ca363d1341c..a0e1478dfd04 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -241,10 +241,7 @@ const struct file_operations ext2_file_operations = {
const struct inode_operations ext2_file_inode_operations = {
#ifdef CONFIG_EXT2_FS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ext2_listxattr,
- .removexattr = generic_removexattr,
#endif
.setattr = ext2_setattr,
.get_acl = ext2_get_acl,
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index 04e73a99902b..395fc074c0db 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -556,7 +556,7 @@ got:
inode->i_ino = ino;
inode->i_blocks = 0;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
memset(ei->i_data, 0, sizeof(ei->i_data));
ei->i_flags =
ext2_mask_flags(mode, EXT2_I(dir)->i_flags & EXT2_FL_INHERITED);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 1e72d425fd3b..d831e24dc885 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -595,7 +595,7 @@ static void ext2_splice_branch(struct inode *inode,
if (where->bh)
mark_buffer_dirty_inode(where->bh, inode);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
}
@@ -1308,7 +1308,7 @@ static int ext2_setsize(struct inode *inode, loff_t newsize)
__ext2_truncate_blocks(inode, newsize);
dax_sem_up_write(EXT2_I(inode));
- inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
if (inode_needs_sync(inode)) {
sync_mapping_buffers(inode->i_mapping);
sync_inode_metadata(inode, 1);
@@ -1652,7 +1652,7 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
struct inode *inode = d_inode(dentry);
int error;
- error = inode_change_ok(inode, iattr);
+ error = setattr_prepare(dentry, iattr);
if (error)
return error;
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index b386af2e45f4..9d617423e936 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -79,7 +79,7 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
ei->i_flags = flags;
ext2_set_inode_flags(inode);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
inode_unlock(inode);
mark_inode_dirty(inode);
@@ -103,7 +103,7 @@ setflags_out:
}
inode_lock(inode);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
inode->i_generation = generation;
inode_unlock(inode);
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index d446203127fc..814e405a2da6 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -221,7 +221,7 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir,
if (err)
return err;
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
inode_inc_link_count(inode);
ihold(inode);
@@ -328,7 +328,8 @@ static int ext2_rmdir (struct inode * dir, struct dentry *dentry)
}
static int ext2_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 = d_inode(old_dentry);
struct inode * new_inode = d_inode(new_dentry);
@@ -338,6 +339,9 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
struct ext2_dir_entry_2 * old_de;
int err;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
err = dquot_initialize(old_dir);
if (err)
goto out;
@@ -372,7 +376,7 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
if (!new_de)
goto out_dir;
ext2_set_link(new_dir, new_de, new_page, old_inode, 1);
- new_inode->i_ctime = CURRENT_TIME_SEC;
+ new_inode->i_ctime = current_time(new_inode);
if (dir_de)
drop_nlink(new_inode);
inode_dec_link_count(new_inode);
@@ -388,7 +392,7 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
* Like most other Unix systems, set the ctime for inodes on a
* rename.
*/
- old_inode->i_ctime = CURRENT_TIME_SEC;
+ old_inode->i_ctime = current_time(old_inode);
mark_inode_dirty(old_inode);
ext2_delete_entry (old_de, old_page);
@@ -428,10 +432,7 @@ const struct inode_operations ext2_dir_inode_operations = {
.mknod = ext2_mknod,
.rename = ext2_rename,
#ifdef CONFIG_EXT2_FS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ext2_listxattr,
- .removexattr = generic_removexattr,
#endif
.setattr = ext2_setattr,
.get_acl = ext2_get_acl,
@@ -441,10 +442,7 @@ const struct inode_operations ext2_dir_inode_operations = {
const struct inode_operations ext2_special_inode_operations = {
#ifdef CONFIG_EXT2_FS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ext2_listxattr,
- .removexattr = generic_removexattr,
#endif
.setattr = ext2_setattr,
.get_acl = ext2_get_acl,
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 1d9379568aa8..6cb042b53b5b 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -1543,7 +1543,7 @@ out:
if (inode->i_size < off+len-towrite)
i_size_write(inode, off+len-towrite);
inode->i_version++;
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
return len - towrite;
}
diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c
index 3495d8ae4b33..8437b191bf5d 100644
--- a/fs/ext2/symlink.c
+++ b/fs/ext2/symlink.c
@@ -25,10 +25,7 @@ const struct inode_operations ext2_symlink_inode_operations = {
.get_link = page_get_link,
.setattr = ext2_setattr,
#ifdef CONFIG_EXT2_FS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ext2_listxattr,
- .removexattr = generic_removexattr,
#endif
};
@@ -37,9 +34,6 @@ const struct inode_operations ext2_fast_symlink_inode_operations = {
.get_link = simple_get_link,
.setattr = ext2_setattr,
#ifdef CONFIG_EXT2_FS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ext2_listxattr,
- .removexattr = generic_removexattr,
#endif
};
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index b7f896f3f7a7..fbdb8f171893 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -691,7 +691,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
/* Update the inode. */
EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
if (IS_SYNC(inode)) {
error = sync_inode_metadata(inode, 1);
/* In case sync failed due to ENOSPC the inode was actually
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index c6601a476c02..dfa519979038 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -193,15 +193,11 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type,
case ACL_TYPE_ACCESS:
name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (error < 0)
+ error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (error)
return error;
- else {
- inode->i_ctime = ext4_current_time(inode);
- ext4_mark_inode_dirty(handle, inode);
- if (error == 0)
- acl = NULL;
- }
+ inode->i_ctime = ext4_current_time(inode);
+ ext4_mark_inode_dirty(handle, inode);
}
break;
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 36d49cfbf2dc..2a822d30e73f 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -706,10 +706,7 @@ const struct file_operations ext4_file_operations = {
const struct inode_operations ext4_file_inode_operations = {
.setattr = ext4_setattr,
.getattr = ext4_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ext4_listxattr,
- .removexattr = generic_removexattr,
.get_acl = ext4_get_acl,
.set_acl = ext4_set_acl,
.fiemap = ext4_fiemap,
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index cd918823b352..9c064727ed62 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5078,7 +5078,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
int orphan = 0;
const unsigned int ia_valid = attr->ia_valid;
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
if (error)
return error;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index c344b819cffa..f92f10d4f66a 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3878,12 +3878,9 @@ const struct inode_operations ext4_dir_inode_operations = {
.rmdir = ext4_rmdir,
.mknod = ext4_mknod,
.tmpfile = ext4_tmpfile,
- .rename2 = ext4_rename2,
+ .rename = ext4_rename2,
.setattr = ext4_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ext4_listxattr,
- .removexattr = generic_removexattr,
.get_acl = ext4_get_acl,
.set_acl = ext4_set_acl,
.fiemap = ext4_fiemap,
@@ -3891,10 +3888,7 @@ const struct inode_operations ext4_dir_inode_operations = {
const struct inode_operations ext4_special_inode_operations = {
.setattr = ext4_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ext4_listxattr,
- .removexattr = generic_removexattr,
.get_acl = ext4_get_acl,
.set_acl = ext4_set_acl,
};
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index b4cbee936cf8..0094923e5ebf 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -88,7 +88,7 @@ static void ext4_finish_bio(struct bio *bio)
if (bio->bi_error) {
SetPageError(page);
- set_bit(AS_EIO, &page->mapping->flags);
+ mapping_set_error(page->mapping, -EIO);
}
bh = head = page_buffers(page);
/*
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index fdf1c6154745..557b3b0d668c 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -86,28 +86,19 @@ const struct inode_operations ext4_encrypted_symlink_inode_operations = {
.readlink = generic_readlink,
.get_link = ext4_encrypted_get_link,
.setattr = ext4_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ext4_listxattr,
- .removexattr = generic_removexattr,
};
const struct inode_operations ext4_symlink_inode_operations = {
.readlink = generic_readlink,
.get_link = page_get_link,
.setattr = ext4_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ext4_listxattr,
- .removexattr = generic_removexattr,
};
const struct inode_operations ext4_fast_symlink_inode_operations = {
.readlink = generic_readlink,
.get_link = simple_get_link,
.setattr = ext4_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ext4_listxattr,
- .removexattr = generic_removexattr,
};
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index 1e29630f49c1..6fe23af509e1 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -212,12 +212,10 @@ static int __f2fs_set_acl(struct inode *inode, int type,
case ACL_TYPE_ACCESS:
name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (error < 0)
+ error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (error)
return error;
set_acl_inode(inode, inode->i_mode);
- if (error == 0)
- acl = NULL;
}
break;
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 0d0177c9149c..9ae194fd2fdb 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -75,7 +75,7 @@ static void f2fs_write_end_io(struct bio *bio)
fscrypt_pullback_bio_page(&page, true);
if (unlikely(bio->bi_error)) {
- set_bit(AS_EIO, &page->mapping->flags);
+ mapping_set_error(page->mapping, -EIO);
f2fs_stop_checkpoint(sbi, true);
}
end_page_writeback(page);
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 12b5836a1033..369f4513be37 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -312,7 +312,7 @@ void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
f2fs_dentry_kunmap(dir, page);
set_page_dirty(page);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
f2fs_mark_inode_dirty_sync(dir);
f2fs_put_page(page, 1);
}
@@ -465,7 +465,7 @@ void update_parent_metadata(struct inode *dir, struct inode *inode,
f2fs_i_links_write(dir, true);
clear_inode_flag(inode, FI_NEW_INODE);
}
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
f2fs_mark_inode_dirty_sync(dir);
if (F2FS_I(dir)->i_current_depth != current_depth)
@@ -683,7 +683,7 @@ void f2fs_drop_nlink(struct inode *dir, struct inode *inode)
if (S_ISDIR(inode->i_mode))
f2fs_i_links_write(dir, false);
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
f2fs_i_links_write(inode, false);
if (S_ISDIR(inode->i_mode)) {
@@ -730,7 +730,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
kunmap(page); /* kunmap - pair of f2fs_find_entry */
set_page_dirty(page);
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ dir->i_ctime = dir->i_mtime = current_time(dir);
f2fs_mark_inode_dirty_sync(dir);
if (inode)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index f8b4fe05385d..c7865073cd26 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -631,7 +631,7 @@ int f2fs_truncate(struct inode *inode)
if (err)
return err;
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
f2fs_mark_inode_dirty_sync(inode);
return 0;
}
@@ -680,7 +680,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
struct inode *inode = d_inode(dentry);
int err;
- err = inode_change_ok(inode, attr);
+ err = setattr_prepare(dentry, attr);
if (err)
return err;
@@ -708,7 +708,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
if (err)
return err;
}
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
}
}
@@ -732,10 +732,7 @@ const struct inode_operations f2fs_file_inode_operations = {
.get_acl = f2fs_get_acl,
.set_acl = f2fs_set_acl,
#ifdef CONFIG_F2FS_FS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = f2fs_listxattr,
- .removexattr = generic_removexattr,
#endif
.fiemap = f2fs_fiemap,
};
@@ -1395,7 +1392,7 @@ static long f2fs_fallocate(struct file *file, int mode,
}
if (!ret) {
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
f2fs_mark_inode_dirty_sync(inode);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
}
@@ -1487,7 +1484,7 @@ static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)
fi->i_flags = flags;
inode_unlock(inode);
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
f2fs_set_inode_flags(inode);
out:
mnt_drop_write_file(filp);
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 34234d84a38b..5f1a67f756af 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -572,7 +572,7 @@ void f2fs_delete_inline_entry(struct f2fs_dir_entry *dentry, struct page *page,
set_page_dirty(page);
f2fs_put_page(page, 1);
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ dir->i_ctime = dir->i_mtime = current_time(dir);
f2fs_mark_inode_dirty_sync(dir);
if (inode)
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 5625b879c98a..489fa0d5f914 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -46,7 +46,7 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
inode->i_ino = ino;
inode->i_blocks = 0;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
inode->i_generation = sbi->s_next_generation++;
err = insert_inode_locked(inode);
@@ -182,7 +182,7 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
f2fs_balance_fs(sbi, true);
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
ihold(inode);
set_inode_flag(inode, FI_INC_LINK);
@@ -723,7 +723,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
f2fs_set_link(new_dir, new_entry, new_page, old_inode);
- new_inode->i_ctime = CURRENT_TIME;
+ new_inode->i_ctime = current_time(new_inode);
down_write(&F2FS_I(new_inode)->i_sem);
if (old_dir_entry)
f2fs_i_links_write(new_inode, false);
@@ -777,7 +777,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
file_set_enc_name(old_inode);
up_write(&F2FS_I(old_inode)->i_sem);
- old_inode->i_ctime = CURRENT_TIME;
+ old_inode->i_ctime = current_time(old_inode);
f2fs_mark_inode_dirty_sync(old_inode);
f2fs_delete_entry(old_entry, old_page, old_dir, NULL);
@@ -932,7 +932,7 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
file_lost_pino(old_inode);
up_write(&F2FS_I(old_inode)->i_sem);
- old_dir->i_ctime = CURRENT_TIME;
+ old_dir->i_ctime = current_time(old_dir);
if (old_nlink) {
down_write(&F2FS_I(old_dir)->i_sem);
f2fs_i_links_write(old_dir, old_nlink > 0);
@@ -947,7 +947,7 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
file_lost_pino(new_inode);
up_write(&F2FS_I(new_inode)->i_sem);
- new_dir->i_ctime = CURRENT_TIME;
+ new_dir->i_ctime = current_time(new_dir);
if (new_nlink) {
down_write(&F2FS_I(new_dir)->i_sem);
f2fs_i_links_write(new_dir, new_nlink > 0);
@@ -1080,10 +1080,7 @@ const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
.getattr = f2fs_getattr,
.setattr = f2fs_setattr,
#ifdef CONFIG_F2FS_FS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = f2fs_listxattr,
- .removexattr = generic_removexattr,
#endif
};
@@ -1096,17 +1093,14 @@ const struct inode_operations f2fs_dir_inode_operations = {
.mkdir = f2fs_mkdir,
.rmdir = f2fs_rmdir,
.mknod = f2fs_mknod,
- .rename2 = f2fs_rename2,
+ .rename = f2fs_rename2,
.tmpfile = f2fs_tmpfile,
.getattr = f2fs_getattr,
.setattr = f2fs_setattr,
.get_acl = f2fs_get_acl,
.set_acl = f2fs_set_acl,
#ifdef CONFIG_F2FS_FS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = f2fs_listxattr,
- .removexattr = generic_removexattr,
#endif
};
@@ -1116,10 +1110,7 @@ const struct inode_operations f2fs_symlink_inode_operations = {
.getattr = f2fs_getattr,
.setattr = f2fs_setattr,
#ifdef CONFIG_F2FS_FS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = f2fs_listxattr,
- .removexattr = generic_removexattr,
#endif
};
@@ -1129,9 +1120,6 @@ const struct inode_operations f2fs_special_inode_operations = {
.get_acl = f2fs_get_acl,
.set_acl = f2fs_set_acl,
#ifdef CONFIG_F2FS_FS_XATTR
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = f2fs_listxattr,
- .removexattr = generic_removexattr,
#endif
};
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 883103593f33..01177ecdeab8 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1525,7 +1525,7 @@ int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
{
pgoff_t index = 0, end = ULONG_MAX;
struct pagevec pvec;
- int ret2 = 0, ret = 0;
+ int ret2, ret = 0;
pagevec_init(&pvec, 0);
@@ -1554,10 +1554,7 @@ int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
cond_resched();
}
- if (unlikely(test_and_clear_bit(AS_ENOSPC, &NODE_MAPPING(sbi)->flags)))
- ret2 = -ENOSPC;
- if (unlikely(test_and_clear_bit(AS_EIO, &NODE_MAPPING(sbi)->flags)))
- ret2 = -EIO;
+ ret2 = filemap_check_errors(NODE_MAPPING(sbi));
if (!ret)
ret = ret2;
return ret;
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 1f74876233b6..3e1c0280f866 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -548,7 +548,7 @@ static int __f2fs_setxattr(struct inode *inode, int index,
if (is_inode_flag_set(inode, FI_ACL_MODE)) {
inode->i_mode = F2FS_I(inode)->i_acl_mode;
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
clear_inode_flag(inode, FI_ACL_MODE);
}
if (index == F2FS_XATTR_INDEX_ENCRYPTION &&
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 663e428596c6..81cecbe6d7cf 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -1071,7 +1071,7 @@ int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo)
}
}
- dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_atime = current_time(dir);
if (IS_DIRSYNC(dir))
(void)fat_sync_inode(dir);
else
diff --git a/fs/fat/file.c b/fs/fat/file.c
index f70185668832..3d04b124bce0 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -63,7 +63,7 @@ static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr)
/* Equivalent to a chmod() */
ia.ia_valid = ATTR_MODE | ATTR_CTIME;
- ia.ia_ctime = current_fs_time(inode->i_sb);
+ ia.ia_ctime = current_time(inode);
if (is_dir)
ia.ia_mode = fat_make_mode(sbi, attr, S_IRWXUGO);
else {
@@ -194,7 +194,7 @@ static int fat_cont_expand(struct inode *inode, loff_t size)
if (err)
goto out;
- inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
mark_inode_dirty(inode);
if (IS_SYNC(inode)) {
int err2;
@@ -297,7 +297,7 @@ static int fat_free(struct inode *inode, int skip)
MSDOS_I(inode)->i_logstart = 0;
}
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
- inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
if (wait) {
err = fat_sync_inode(inode);
if (err) {
@@ -450,7 +450,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
attr->ia_valid &= ~TIMES_SET_FLAGS;
}
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
attr->ia_valid = ia_valid;
if (error) {
if (sbi->options.quiet)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index da04c0298fab..338d2f73eb29 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -237,7 +237,7 @@ static int fat_write_end(struct file *file, struct address_space *mapping,
if (err < len)
fat_write_failed(mapping, pos + len);
if (!(err < 0) && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) {
- inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
mark_inode_dirty(inode);
}
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 664655b2c55f..7d6a105d601b 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -283,7 +283,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
goto out;
}
- ts = CURRENT_TIME_SEC;
+ ts = current_time(dir);
err = msdos_add_entry(dir, msdos_name, 0, is_hid, 0, &ts, &sinfo);
if (err)
goto out;
@@ -330,7 +330,7 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
drop_nlink(dir);
clear_nlink(inode);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
fat_detach(inode);
out:
mutex_unlock(&MSDOS_SB(sb)->s_lock);
@@ -364,7 +364,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
goto out;
}
- ts = CURRENT_TIME_SEC;
+ ts = current_time(dir);
cluster = fat_alloc_new_dir(dir, &ts);
if (cluster < 0) {
err = cluster;
@@ -416,7 +416,7 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry)
if (err)
goto out;
clear_nlink(inode);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
fat_detach(inode);
out:
mutex_unlock(&MSDOS_SB(sb)->s_lock);
@@ -481,7 +481,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
mark_inode_dirty(old_inode);
old_dir->i_version++;
- old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
+ old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
if (IS_DIRSYNC(old_dir))
(void)fat_sync_inode(old_dir);
else
@@ -490,7 +490,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
}
}
- ts = CURRENT_TIME_SEC;
+ ts = current_time(old_inode);
if (new_inode) {
if (err)
goto out;
@@ -596,12 +596,16 @@ error_inode:
/***** Rename, a wrapper for rename_same_dir & rename_diff_dir */
static int msdos_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;
unsigned char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME];
int err, is_hid;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
mutex_lock(&MSDOS_SB(sb)->s_lock);
err = msdos_format_name(old_dentry->d_name.name,
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 92b7363dafa9..6a7152d0c250 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -21,6 +21,17 @@
#include <linux/namei.h>
#include "fat.h"
+static inline unsigned long vfat_d_version(struct dentry *dentry)
+{
+ return (unsigned long) dentry->d_fsdata;
+}
+
+static inline void vfat_d_version_set(struct dentry *dentry,
+ unsigned long version)
+{
+ dentry->d_fsdata = (void *) version;
+}
+
/*
* If new entry was created in the parent, it could create the 8.3
* alias (the shortname of logname). So, the parent may have the
@@ -33,7 +44,7 @@ static int vfat_revalidate_shortname(struct dentry *dentry)
{
int ret = 1;
spin_lock(&dentry->d_lock);
- if (dentry->d_time != d_inode(dentry->d_parent)->i_version)
+ if (vfat_d_version(dentry) != d_inode(dentry->d_parent)->i_version)
ret = 0;
spin_unlock(&dentry->d_lock);
return ret;
@@ -759,7 +770,7 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
out:
mutex_unlock(&MSDOS_SB(sb)->s_lock);
if (!inode)
- dentry->d_time = dir->i_version;
+ vfat_d_version_set(dentry, dir->i_version);
return d_splice_alias(inode, dentry);
error:
mutex_unlock(&MSDOS_SB(sb)->s_lock);
@@ -777,7 +788,7 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
mutex_lock(&MSDOS_SB(sb)->s_lock);
- ts = CURRENT_TIME_SEC;
+ ts = current_time(dir);
err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo);
if (err)
goto out;
@@ -821,9 +832,9 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
drop_nlink(dir);
clear_nlink(inode);
- inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
+ inode->i_mtime = inode->i_atime = current_time(inode);
fat_detach(inode);
- dentry->d_time = dir->i_version;
+ vfat_d_version_set(dentry, dir->i_version);
out:
mutex_unlock(&MSDOS_SB(sb)->s_lock);
@@ -847,9 +858,9 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry)
if (err)
goto out;
clear_nlink(inode);
- inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
+ inode->i_mtime = inode->i_atime = current_time(inode);
fat_detach(inode);
- dentry->d_time = dir->i_version;
+ vfat_d_version_set(dentry, dir->i_version);
out:
mutex_unlock(&MSDOS_SB(sb)->s_lock);
@@ -866,7 +877,7 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
mutex_lock(&MSDOS_SB(sb)->s_lock);
- ts = CURRENT_TIME_SEC;
+ ts = current_time(dir);
cluster = fat_alloc_new_dir(dir, &ts);
if (cluster < 0) {
err = cluster;
@@ -903,7 +914,8 @@ out:
}
static int vfat_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 buffer_head *dotdot_bh;
struct msdos_dir_entry *dotdot_de;
@@ -914,6 +926,9 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
int err, is_dir, update_dotdot, corrupt = 0;
struct super_block *sb = old_dir->i_sb;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
old_inode = d_inode(old_dentry);
new_inode = d_inode(new_dentry);
@@ -931,7 +946,7 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
}
}
- ts = CURRENT_TIME_SEC;
+ ts = current_time(old_dir);
if (new_inode) {
if (is_dir) {
err = fat_dir_empty(new_inode);
diff --git a/fs/file.c b/fs/file.c
index 6b1acdfe59da..69d6990e3021 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -23,12 +23,12 @@
#include <linux/rcupdate.h>
#include <linux/workqueue.h>
-int sysctl_nr_open __read_mostly = 1024*1024;
-int sysctl_nr_open_min = BITS_PER_LONG;
+unsigned int sysctl_nr_open __read_mostly = 1024*1024;
+unsigned int sysctl_nr_open_min = BITS_PER_LONG;
/* our min() is unusable in constant expressions ;-/ */
#define __const_min(x, y) ((x) < (y) ? (x) : (y))
-int sysctl_nr_open_max = __const_min(INT_MAX, ~(size_t)0/sizeof(void *)) &
- -BITS_PER_LONG;
+unsigned int sysctl_nr_open_max =
+ __const_min(INT_MAX, ~(size_t)0/sizeof(void *)) & -BITS_PER_LONG;
static void *alloc_fdmem(size_t size)
{
@@ -163,7 +163,7 @@ out:
* Return <0 error code on error; 1 on successful completion.
* The files->file_lock should be held on entry, and will be held on exit.
*/
-static int expand_fdtable(struct files_struct *files, int nr)
+static int expand_fdtable(struct files_struct *files, unsigned int nr)
__releases(files->file_lock)
__acquires(files->file_lock)
{
@@ -208,7 +208,7 @@ static int expand_fdtable(struct files_struct *files, int nr)
* expanded and execution may have blocked.
* The files->file_lock should be held on entry, and will be held on exit.
*/
-static int expand_files(struct files_struct *files, int nr)
+static int expand_files(struct files_struct *files, unsigned int nr)
__releases(files->file_lock)
__acquires(files->file_lock)
{
@@ -243,12 +243,12 @@ repeat:
return expanded;
}
-static inline void __set_close_on_exec(int fd, struct fdtable *fdt)
+static inline void __set_close_on_exec(unsigned int fd, struct fdtable *fdt)
{
__set_bit(fd, fdt->close_on_exec);
}
-static inline void __clear_close_on_exec(int fd, struct fdtable *fdt)
+static inline void __clear_close_on_exec(unsigned int fd, struct fdtable *fdt)
{
if (test_bit(fd, fdt->close_on_exec))
__clear_bit(fd, fdt->close_on_exec);
@@ -268,10 +268,10 @@ static inline void __clear_open_fd(unsigned int fd, struct fdtable *fdt)
__clear_bit(fd / BITS_PER_LONG, fdt->full_fds_bits);
}
-static int count_open_files(struct fdtable *fdt)
+static unsigned int count_open_files(struct fdtable *fdt)
{
- int size = fdt->max_fds;
- int i;
+ unsigned int size = fdt->max_fds;
+ unsigned int i;
/* Find the last open fd */
for (i = size / BITS_PER_LONG; i > 0; ) {
@@ -291,7 +291,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
{
struct files_struct *newf;
struct file **old_fds, **new_fds;
- int open_files, i;
+ unsigned int open_files, i;
struct fdtable *old_fdt, *new_fdt;
*errorp = -ENOMEM;
@@ -391,7 +391,7 @@ static struct fdtable *close_files(struct files_struct * files)
* files structure.
*/
struct fdtable *fdt = rcu_dereference_raw(files->fdt);
- int i, j = 0;
+ unsigned int i, j = 0;
for (;;) {
unsigned long set;
@@ -477,11 +477,11 @@ struct files_struct init_files = {
.file_lock = __SPIN_LOCK_UNLOCKED(init_files.file_lock),
};
-static unsigned long find_next_fd(struct fdtable *fdt, unsigned long start)
+static unsigned int find_next_fd(struct fdtable *fdt, unsigned int start)
{
- unsigned long maxfd = fdt->max_fds;
- unsigned long maxbit = maxfd / BITS_PER_LONG;
- unsigned long bitbit = start / BITS_PER_LONG;
+ unsigned int maxfd = fdt->max_fds;
+ unsigned int maxbit = maxfd / BITS_PER_LONG;
+ unsigned int bitbit = start / BITS_PER_LONG;
bitbit = find_next_zero_bit(fdt->full_fds_bits, maxbit, bitbit) * BITS_PER_LONG;
if (bitbit > maxfd)
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index f863ac6647ac..6e22748b0704 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -220,7 +220,7 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
inode->i_mode = mode;
inode->i_uid = fc->user_id;
inode->i_gid = fc->group_id;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
/* setting ->i_op to NULL is not allowed */
if (iop)
inode->i_op = iop;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index f7c84ab835ca..6a4d0e5418a1 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -647,7 +647,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
void fuse_update_ctime(struct inode *inode)
{
if (!IS_NOCMTIME(inode)) {
- inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_ctime = current_time(inode);
mark_inode_dirty_sync(inode);
}
}
@@ -1604,9 +1604,10 @@ int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
* vmtruncate() doesn't allow for this case, so do the rlimit checking
* and the actual truncation by hand.
*/
-int fuse_do_setattr(struct inode *inode, struct iattr *attr,
+int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
struct file *file)
{
+ struct inode *inode = d_inode(dentry);
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_inode *fi = get_fuse_inode(inode);
FUSE_ARGS(args);
@@ -1621,7 +1622,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
if (!fc->default_permissions)
attr->ia_valid |= ATTR_FORCE;
- err = inode_change_ok(inode, attr);
+ err = setattr_prepare(dentry, attr);
if (err)
return err;
@@ -1758,7 +1759,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
if (!attr->ia_valid)
return 0;
- ret = fuse_do_setattr(inode, attr, file);
+ ret = fuse_do_setattr(entry, attr, file);
if (!ret) {
/*
* If filesystem supports acls it may have updated acl xattrs in
@@ -1792,7 +1793,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
.symlink = fuse_symlink,
.unlink = fuse_unlink,
.rmdir = fuse_rmdir,
- .rename2 = fuse_rename2,
+ .rename = fuse_rename2,
.link = fuse_link,
.setattr = fuse_setattr,
.create = fuse_create,
@@ -1800,10 +1801,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
.mknod = fuse_mknod,
.permission = fuse_permission,
.getattr = fuse_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = fuse_listxattr,
- .removexattr = generic_removexattr,
.get_acl = fuse_get_acl,
.set_acl = fuse_set_acl,
};
@@ -1823,10 +1821,7 @@ static const struct inode_operations fuse_common_inode_operations = {
.setattr = fuse_setattr,
.permission = fuse_permission,
.getattr = fuse_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = fuse_listxattr,
- .removexattr = generic_removexattr,
.get_acl = fuse_get_acl,
.set_acl = fuse_set_acl,
};
@@ -1836,10 +1831,7 @@ static const struct inode_operations fuse_symlink_inode_operations = {
.get_link = fuse_get_link,
.readlink = generic_readlink,
.getattr = fuse_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = fuse_listxattr,
- .removexattr = generic_removexattr,
};
void fuse_init_common(struct inode *inode)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index b7beb67bf005..abc66a6237fd 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2810,7 +2810,7 @@ static void fuse_do_truncate(struct file *file)
attr.ia_file = file;
attr.ia_valid |= ATTR_FILE;
- fuse_do_setattr(inode, &attr, file);
+ fuse_do_setattr(file_dentry(file), &attr, file);
}
static inline loff_t fuse_round_up(loff_t off)
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 24ada5dc4dae..0dfbb136e59a 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -961,7 +961,7 @@ bool fuse_write_update_size(struct inode *inode, loff_t pos);
int fuse_flush_times(struct inode *inode, struct fuse_file *ff);
int fuse_write_inode(struct inode *inode, struct writeback_control *wbc);
-int fuse_do_setattr(struct inode *inode, struct iattr *attr,
+int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
struct file *file);
void fuse_set_initialized(struct fuse_conn *fc);
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 363ba9e9d8d0..2524807ee070 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -92,17 +92,11 @@ int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
if (type == ACL_TYPE_ACCESS) {
umode_t mode = inode->i_mode;
- error = posix_acl_equiv_mode(acl, &mode);
- if (error < 0)
+ error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (error)
return error;
-
- if (error == 0)
- acl = NULL;
-
- if (mode != inode->i_mode) {
- inode->i_mode = mode;
+ if (mode != inode->i_mode)
mark_inode_dirty(inode);
- }
}
if (acl) {
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 645721f3ff00..fc5da4cbe88c 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -836,7 +836,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
gfs2_quota_change(ip, -(s64)btotal, ip->i_inode.i_uid,
ip->i_inode.i_gid);
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = current_time(&ip->i_inode);
gfs2_dinode_out(ip, dibh->b_data);
@@ -1063,7 +1063,7 @@ static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
}
i_size_write(inode, newsize);
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = current_time(&ip->i_inode);
gfs2_dinode_out(ip, dibh->b_data);
if (journaled)
@@ -1142,7 +1142,7 @@ static int trunc_end(struct gfs2_inode *ip)
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
gfs2_ordered_del_inode(ip);
}
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = current_time(&ip->i_inode);
ip->i_diskflags &= ~GFS2_DIF_TRUNC_IN_PROG;
gfs2_trans_add_meta(ip->i_gl, dibh);
@@ -1252,7 +1252,7 @@ static int do_grow(struct inode *inode, u64 size)
goto do_end_trans;
i_size_write(inode, size);
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = current_time(&ip->i_inode);
gfs2_trans_add_meta(ip->i_gl, dibh);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index db8fbeb62483..3cdde5f5d399 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -135,7 +135,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
if (ip->i_inode.i_size < offset + size)
i_size_write(&ip->i_inode, offset + size);
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = current_time(&ip->i_inode);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -233,7 +233,7 @@ out:
if (ip->i_inode.i_size < offset + copied)
i_size_write(&ip->i_inode, offset + copied);
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = current_time(&ip->i_inode);
gfs2_trans_add_meta(ip->i_gl, dibh);
gfs2_dinode_out(ip, dibh->b_data);
@@ -872,7 +872,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
struct gfs2_leaf *leaf;
struct gfs2_dirent *dent;
struct qstr name = { .name = "" };
- struct timespec tv = CURRENT_TIME;
+ struct timespec tv = current_time(inode);
error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
if (error)
@@ -1816,7 +1816,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
gfs2_inum_out(nip, dent);
dent->de_type = cpu_to_be16(IF2DT(nip->i_inode.i_mode));
dent->de_rahead = cpu_to_be16(gfs2_inode_ra_len(nip));
- tv = CURRENT_TIME;
+ tv = current_time(&ip->i_inode);
if (ip->i_diskflags & GFS2_DIF_EXHASH) {
leaf = (struct gfs2_leaf *)bh->b_data;
be16_add_cpu(&leaf->lf_entries, 1);
@@ -1878,7 +1878,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry)
const struct qstr *name = &dentry->d_name;
struct gfs2_dirent *dent, *prev = NULL;
struct buffer_head *bh;
- struct timespec tv = CURRENT_TIME;
+ struct timespec tv = current_time(&dip->i_inode);
/* Returns _either_ the entry (if its first in block) or the
previous entry otherwise */
@@ -1960,7 +1960,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
gfs2_trans_add_meta(dip->i_gl, bh);
}
- dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
+ dip->i_inode.i_mtime = dip->i_inode.i_ctime = current_time(&dip->i_inode);
gfs2_dinode_out(dip, bh->b_data);
brelse(bh);
return 0;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index fb3a810b506f..fe3f84995c48 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -656,7 +656,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
set_nlink(inode, S_ISDIR(mode) ? 2 : 1);
inode->i_rdev = dev;
inode->i_size = size;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
gfs2_set_inode_blocks(inode, 1);
munge_mode_uid_gid(dip, inode);
check_and_update_goal(dip);
@@ -983,7 +983,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
gfs2_trans_add_meta(ip->i_gl, dibh);
inc_nlink(&ip->i_inode);
- ip->i_inode.i_ctime = CURRENT_TIME;
+ ip->i_inode.i_ctime = current_time(&ip->i_inode);
ihold(inode);
d_instantiate(dentry, inode);
mark_inode_dirty(inode);
@@ -1067,7 +1067,7 @@ static int gfs2_unlink_inode(struct gfs2_inode *dip,
return error;
ip->i_entries = 0;
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
if (S_ISDIR(inode->i_mode))
clear_nlink(inode);
else
@@ -1330,7 +1330,7 @@ static int update_moved_ino(struct gfs2_inode *ip, struct gfs2_inode *ndip,
error = gfs2_meta_inode_buffer(ip, &dibh);
if (error)
return error;
- ip->i_inode.i_ctime = CURRENT_TIME;
+ ip->i_inode.i_ctime = current_time(&ip->i_inode);
gfs2_trans_add_meta(ip->i_gl, dibh);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -1936,7 +1936,7 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr)
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
goto out;
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
if (error)
goto out;
@@ -2040,10 +2040,7 @@ const struct inode_operations gfs2_file_iops = {
.permission = gfs2_permission,
.setattr = gfs2_setattr,
.getattr = gfs2_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = gfs2_listxattr,
- .removexattr = generic_removexattr,
.fiemap = gfs2_fiemap,
.get_acl = gfs2_get_acl,
.set_acl = gfs2_set_acl,
@@ -2058,14 +2055,11 @@ const struct inode_operations gfs2_dir_iops = {
.mkdir = gfs2_mkdir,
.rmdir = gfs2_unlink,
.mknod = gfs2_mknod,
- .rename2 = gfs2_rename2,
+ .rename = gfs2_rename2,
.permission = gfs2_permission,
.setattr = gfs2_setattr,
.getattr = gfs2_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = gfs2_listxattr,
- .removexattr = generic_removexattr,
.fiemap = gfs2_fiemap,
.get_acl = gfs2_get_acl,
.set_acl = gfs2_set_acl,
@@ -2078,10 +2072,7 @@ const struct inode_operations gfs2_symlink_iops = {
.permission = gfs2_permission,
.setattr = gfs2_setattr,
.getattr = gfs2_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = gfs2_listxattr,
- .removexattr = generic_removexattr,
.fiemap = gfs2_fiemap,
};
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 8af2dfa09236..c2ca9566b764 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -854,7 +854,7 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
size = loc + sizeof(struct gfs2_quota);
if (size > inode->i_size)
i_size_write(inode, size);
- inode->i_mtime = inode->i_atime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = current_time(inode);
mark_inode_dirty(inode);
set_bit(QDF_REFRESH, &qd->qd_flags);
}
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 3a2853504084..a4a577088d19 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -309,7 +309,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
- ip->i_inode.i_ctime = CURRENT_TIME;
+ ip->i_inode.i_ctime = current_time(&ip->i_inode);
gfs2_trans_add_meta(ip->i_gl, dibh);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -775,7 +775,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
- ip->i_inode.i_ctime = CURRENT_TIME;
+ ip->i_inode.i_ctime = current_time(&ip->i_inode);
gfs2_trans_add_meta(ip->i_gl, dibh);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -910,7 +910,7 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh,
error = gfs2_meta_inode_buffer(ip, &dibh);
if (error)
goto out;
- ip->i_inode.i_ctime = CURRENT_TIME;
+ ip->i_inode.i_ctime = current_time(&ip->i_inode);
gfs2_trans_add_meta(ip->i_gl, dibh);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -1133,7 +1133,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el)
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
- ip->i_inode.i_ctime = CURRENT_TIME;
+ ip->i_inode.i_ctime = current_time(&ip->i_inode);
gfs2_trans_add_meta(ip->i_gl, dibh);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
diff --git a/fs/hfs/attr.c b/fs/hfs/attr.c
index d9a86919fdf6..0933600e11c8 100644
--- a/fs/hfs/attr.c
+++ b/fs/hfs/attr.c
@@ -13,9 +13,13 @@
#include "hfs_fs.h"
#include "btree.h"
-int hfs_setxattr(struct dentry *unused, struct inode *inode,
- const char *name, const void *value,
- size_t size, int flags)
+enum hfs_xattr_type {
+ HFS_TYPE,
+ HFS_CREATOR,
+};
+
+static int __hfs_setxattr(struct inode *inode, enum hfs_xattr_type type,
+ const void *value, size_t size, int flags)
{
struct hfs_find_data fd;
hfs_cat_rec rec;
@@ -36,18 +40,22 @@ int hfs_setxattr(struct dentry *unused, struct inode *inode,
sizeof(struct hfs_cat_file));
file = &rec.file;
- if (!strcmp(name, "hfs.type")) {
+ switch (type) {
+ case HFS_TYPE:
if (size == 4)
memcpy(&file->UsrWds.fdType, value, 4);
else
res = -ERANGE;
- } else if (!strcmp(name, "hfs.creator")) {
+ break;
+
+ case HFS_CREATOR:
if (size == 4)
memcpy(&file->UsrWds.fdCreator, value, 4);
else
res = -ERANGE;
- } else
- res = -EOPNOTSUPP;
+ break;
+ }
+
if (!res)
hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
sizeof(struct hfs_cat_file));
@@ -56,8 +64,8 @@ out:
return res;
}
-ssize_t hfs_getxattr(struct dentry *unused, struct inode *inode,
- const char *name, void *value, size_t size)
+static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type,
+ void *value, size_t size)
{
struct hfs_find_data fd;
hfs_cat_rec rec;
@@ -80,41 +88,64 @@ ssize_t hfs_getxattr(struct dentry *unused, struct inode *inode,
}
file = &rec.file;
- if (!strcmp(name, "hfs.type")) {
+ switch (type) {
+ case HFS_TYPE:
if (size >= 4) {
memcpy(value, &file->UsrWds.fdType, 4);
res = 4;
} else
res = size ? -ERANGE : 4;
- } else if (!strcmp(name, "hfs.creator")) {
+ break;
+
+ case HFS_CREATOR:
if (size >= 4) {
memcpy(value, &file->UsrWds.fdCreator, 4);
res = 4;
} else
res = size ? -ERANGE : 4;
- } else
- res = -ENODATA;
+ break;
+ }
+
out:
if (size)
hfs_find_exit(&fd);
return res;
}
-#define HFS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type"))
-
-ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+static int hfs_xattr_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+ const char *name, void *value, size_t size)
{
- struct inode *inode = d_inode(dentry);
+ return __hfs_getxattr(inode, handler->flags, value, size);
+}
- if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
+static int hfs_xattr_set(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+ const char *name, const void *value, size_t size,
+ int flags)
+{
+ if (!value)
return -EOPNOTSUPP;
- if (!buffer || !size)
- return HFS_ATTRLIST_SIZE;
- if (size < HFS_ATTRLIST_SIZE)
- return -ERANGE;
- strcpy(buffer, "hfs.type");
- strcpy(buffer + sizeof("hfs.type"), "hfs.creator");
-
- return HFS_ATTRLIST_SIZE;
+ return __hfs_setxattr(inode, handler->flags, value, size, flags);
}
+
+static const struct xattr_handler hfs_creator_handler = {
+ .name = "hfs.creator",
+ .flags = HFS_CREATOR,
+ .get = hfs_xattr_get,
+ .set = hfs_xattr_set,
+};
+
+static const struct xattr_handler hfs_type_handler = {
+ .name = "hfs.type",
+ .flags = HFS_TYPE,
+ .get = hfs_xattr_get,
+ .set = hfs_xattr_set,
+};
+
+const struct xattr_handler *hfs_xattr_handlers[] = {
+ &hfs_creator_handler,
+ &hfs_type_handler,
+ NULL
+};
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c
index 8f4afd3f5108..8a66405b0f8b 100644
--- a/fs/hfs/catalog.c
+++ b/fs/hfs/catalog.c
@@ -125,7 +125,7 @@ int hfs_cat_create(u32 cnid, struct inode *dir, const struct qstr *str, struct i
goto err1;
dir->i_size++;
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty(dir);
hfs_find_exit(&fd);
return 0;
@@ -261,7 +261,7 @@ int hfs_cat_delete(u32 cnid, struct inode *dir, const struct qstr *str)
}
dir->i_size--;
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty(dir);
res = 0;
out:
@@ -321,7 +321,7 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, const struct qstr *src_name,
if (err)
goto out;
dst_dir->i_size++;
- dst_dir->i_mtime = dst_dir->i_ctime = CURRENT_TIME_SEC;
+ dst_dir->i_mtime = dst_dir->i_ctime = current_time(dst_dir);
mark_inode_dirty(dst_dir);
/* finally remove the old entry */
@@ -333,7 +333,7 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, const struct qstr *src_name,
if (err)
goto out;
src_dir->i_size--;
- src_dir->i_mtime = src_dir->i_ctime = CURRENT_TIME_SEC;
+ src_dir->i_mtime = src_dir->i_ctime = current_time(src_dir);
mark_inode_dirty(src_dir);
type = entry.type;
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index 163190ecc0d2..5de5c48b418d 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -268,7 +268,7 @@ static int hfs_remove(struct inode *dir, struct dentry *dentry)
if (res)
return res;
clear_nlink(inode);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
hfs_delete_inode(inode);
mark_inode_dirty(inode);
return 0;
@@ -286,10 +286,14 @@ static int hfs_remove(struct inode *dir, struct dentry *dentry)
* XXX: how do you handle must_be dir?
*/
static int hfs_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 res;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
/* Unlink destination if it already exists */
if (d_really_is_positive(new_dentry)) {
res = hfs_remove(new_dir, new_dentry);
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 16f5172ee40d..4cdec5a19347 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -212,11 +212,7 @@ extern void hfs_evict_inode(struct inode *);
extern void hfs_delete_inode(struct inode *);
/* attr.c */
-extern int hfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
- const void *value, size_t size, int flags);
-extern ssize_t hfs_getxattr(struct dentry *dentry, struct inode *inode,
- const char *name, void *value, size_t size);
-extern ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
+extern const struct xattr_handler *hfs_xattr_handlers[];
/* mdb.c */
extern int hfs_mdb_get(struct super_block *);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index c6a32415735b..f776acf2378a 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -15,6 +15,7 @@
#include <linux/mpage.h>
#include <linux/sched.h>
#include <linux/uio.h>
+#include <linux/xattr.h>
#include "hfs_fs.h"
#include "btree.h"
@@ -193,7 +194,7 @@ struct inode *hfs_new_inode(struct inode *dir, const struct qstr *name, umode_t
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
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);
HFS_I(inode)->flags = 0;
HFS_I(inode)->rsrc_inode = NULL;
HFS_I(inode)->fs_blocks = 0;
@@ -605,7 +606,7 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
int error;
- error = inode_change_ok(inode, attr); /* basic permission checks */
+ error = setattr_prepare(dentry, attr); /* basic permission checks */
if (error)
return error;
@@ -687,7 +688,5 @@ static const struct file_operations hfs_file_operations = {
static const struct inode_operations hfs_file_inode_operations = {
.lookup = hfs_file_lookup,
.setattr = hfs_inode_setattr,
- .setxattr = hfs_setxattr,
- .getxattr = hfs_getxattr,
- .listxattr = hfs_listxattr,
+ .listxattr = generic_listxattr,
};
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 1ca95c232bb5..bf6304a350a6 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -406,6 +406,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
}
sb->s_op = &hfs_super_operations;
+ sb->s_xattr = hfs_xattr_handlers;
sb->s_flags |= MS_NODIRATIME;
mutex_init(&sbi->bitmap_lock);
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 142534d3c2d5..a5e00f7a4c14 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -303,7 +303,7 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir,
dir->i_size++;
if (S_ISDIR(inode->i_mode))
hfsplus_subfolders_inc(dir);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY);
hfs_find_exit(&fd);
@@ -400,7 +400,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, const struct qstr *str)
dir->i_size--;
if (type == HFSPLUS_FOLDER)
hfsplus_subfolders_dec(dir);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY);
if (type == HFSPLUS_FILE || type == HFSPLUS_FOLDER) {
@@ -469,7 +469,7 @@ int hfsplus_rename_cat(u32 cnid,
dst_dir->i_size++;
if (type == HFSPLUS_FOLDER)
hfsplus_subfolders_inc(dst_dir);
- dst_dir->i_mtime = dst_dir->i_ctime = CURRENT_TIME_SEC;
+ dst_dir->i_mtime = dst_dir->i_ctime = current_time(dst_dir);
/* finally remove the old entry */
err = hfsplus_cat_build_key(sb, src_fd.search_key,
@@ -486,7 +486,7 @@ int hfsplus_rename_cat(u32 cnid,
src_dir->i_size--;
if (type == HFSPLUS_FOLDER)
hfsplus_subfolders_dec(src_dir);
- src_dir->i_mtime = src_dir->i_ctime = CURRENT_TIME_SEC;
+ src_dir->i_mtime = src_dir->i_ctime = current_time(src_dir);
/* remove old thread entry */
hfsplus_cat_build_key_with_cnid(sb, src_fd.search_key, cnid);
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 42e128661dc1..31d5e3f1fe17 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -347,7 +347,7 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
inc_nlink(inode);
hfsplus_instantiate(dst_dentry, inode, cnid);
ihold(inode);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
sbi->file_count++;
hfsplus_mark_mdb_dirty(dst_dir->i_sb);
@@ -406,7 +406,7 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
hfsplus_delete_inode(inode);
} else
sbi->file_count--;
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
out:
mutex_unlock(&sbi->vh_mutex);
@@ -427,7 +427,7 @@ static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
if (res)
goto out;
clear_nlink(inode);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
hfsplus_delete_inode(inode);
mark_inode_dirty(inode);
out:
@@ -530,10 +530,14 @@ static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
}
static int hfsplus_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 res;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
/* Unlink destination if it already exists */
if (d_really_is_positive(new_dentry)) {
if (d_is_dir(new_dentry))
@@ -562,10 +566,7 @@ const struct inode_operations hfsplus_dir_inode_operations = {
.symlink = hfsplus_symlink,
.mknod = hfsplus_mknod,
.rename = hfsplus_rename,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = hfsplus_listxattr,
- .removexattr = generic_removexattr,
#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
.get_acl = hfsplus_get_posix_acl,
.set_acl = hfsplus_set_posix_acl,
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 19462d773fe2..2e796f8302ff 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -245,7 +245,7 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
struct inode *inode = d_inode(dentry);
int error;
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
if (error)
return error;
@@ -333,10 +333,7 @@ int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
static const struct inode_operations hfsplus_file_inode_operations = {
.setattr = hfsplus_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = hfsplus_listxattr,
- .removexattr = generic_removexattr,
#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
.get_acl = hfsplus_get_posix_acl,
.set_acl = hfsplus_set_posix_acl,
@@ -369,7 +366,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode)
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
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);
hip = HFSPLUS_I(inode);
INIT_LIST_HEAD(&hip->open_dir_list);
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
index 32a49e292b6a..99627f8a0a18 100644
--- a/fs/hfsplus/ioctl.c
+++ b/fs/hfsplus/ioctl.c
@@ -122,7 +122,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
else
hip->userflags &= ~HFSPLUS_FLG_NODUMP;
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
out_unlock_inode:
diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c
index ab7ea2506b4d..9b92058a1240 100644
--- a/fs/hfsplus/posix_acl.c
+++ b/fs/hfsplus/posix_acl.c
@@ -65,8 +65,8 @@ int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
case ACL_TYPE_ACCESS:
xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
if (acl) {
- err = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (err < 0)
+ err = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (err)
return err;
}
err = 0;
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 90e46cd752fe..23e15ea53e45 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -812,7 +812,7 @@ static int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
int fd = HOSTFS_I(inode)->fd;
- err = inode_change_ok(inode, attr);
+ err = setattr_prepare(dentry, attr);
if (err)
return err;
@@ -885,7 +885,7 @@ static const struct inode_operations hostfs_dir_iops = {
.mkdir = hostfs_mkdir,
.rmdir = hostfs_rmdir,
.mknod = hostfs_mknod,
- .rename2 = hostfs_rename2,
+ .rename = hostfs_rename2,
.permission = hostfs_permission,
.setattr = hostfs_setattr,
};
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index d3bcdd975700..b3be1b5a62e2 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -189,6 +189,11 @@ static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block)
return generic_block_bmap(mapping, block, hpfs_get_block);
}
+static int hpfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len)
+{
+ return generic_block_fiemap(inode, fieinfo, start, len, hpfs_get_block);
+}
+
const struct address_space_operations hpfs_aops = {
.readpage = hpfs_readpage,
.writepage = hpfs_writepage,
@@ -214,4 +219,5 @@ const struct file_operations hpfs_file_ops =
const struct inode_operations hpfs_file_iops =
{
.setattr = hpfs_setattr,
+ .fiemap = hpfs_fiemap,
};
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index 1f3c6d76200b..b9c724ed1e7e 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -273,7 +273,7 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size)
goto out_unlock;
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
if (error)
goto out_unlock;
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index bb8d67e2740a..f30c14414518 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -507,7 +507,8 @@ const struct address_space_operations hpfs_symlink_aops = {
};
static int hpfs_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 unsigned char *old_name = old_dentry->d_name.name;
unsigned old_len = old_dentry->d_name.len;
@@ -524,6 +525,9 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct fnode *fnode;
int err;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
if ((err = hpfs_chk_name(new_name, &new_len))) return err;
err = 0;
hpfs_adjust_length(old_name, &old_len);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 7337cac29e9e..4fb7b10f3a05 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -655,7 +655,7 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset,
if (!(mode & FALLOC_FL_KEEP_SIZE) && offset + len > inode->i_size)
i_size_write(inode, offset + len);
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
out:
inode_unlock(inode);
return error;
@@ -670,7 +670,7 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
BUG_ON(!inode);
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
if (error)
return error;
@@ -700,7 +700,7 @@ static struct inode *hugetlbfs_get_root(struct super_block *sb,
inode->i_mode = S_IFDIR | config->mode;
inode->i_uid = config->uid;
inode->i_gid = config->gid;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
info = HUGETLBFS_I(inode);
mpol_shared_policy_init(&info->policy, NULL);
inode->i_op = &hugetlbfs_dir_inode_operations;
@@ -739,7 +739,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
lockdep_set_class(&inode->i_mapping->i_mmap_rwsem,
&hugetlbfs_i_mmap_rwsem_key);
inode->i_mapping->a_ops = &hugetlbfs_aops;
- 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->private_data = resv_map;
info = HUGETLBFS_I(inode);
/*
@@ -788,7 +788,7 @@ static int hugetlbfs_mknod(struct inode *dir,
inode = hugetlbfs_get_inode(dir->i_sb, dir, mode, dev);
if (inode) {
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ dir->i_ctime = dir->i_mtime = current_time(dir);
d_instantiate(dentry, inode);
dget(dentry); /* Extra count - pin the dentry in core */
error = 0;
@@ -825,7 +825,7 @@ static int hugetlbfs_symlink(struct inode *dir,
} else
iput(inode);
}
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ dir->i_ctime = dir->i_mtime = current_time(dir);
return error;
}
diff --git a/fs/inode.c b/fs/inode.c
index 7e3ef3af3db9..88110fd0b282 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -140,6 +140,8 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
inode->i_fop = &no_open_fops;
inode->__i_nlink = 1;
inode->i_opflags = 0;
+ if (sb->s_xattr)
+ inode->i_opflags |= IOP_XATTR;
i_uid_write(inode, 0);
i_gid_write(inode, 0);
atomic_set(&inode->i_writecount, 0);
@@ -1021,13 +1023,17 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
{
struct hlist_head *head = inode_hashtable + hash(sb, hashval);
struct inode *inode;
-
+again:
spin_lock(&inode_hash_lock);
inode = find_inode(sb, head, test, data);
spin_unlock(&inode_hash_lock);
if (inode) {
wait_on_inode(inode);
+ if (unlikely(inode_unhashed(inode))) {
+ iput(inode);
+ goto again;
+ }
return inode;
}
@@ -1064,6 +1070,10 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
destroy_inode(inode);
inode = old;
wait_on_inode(inode);
+ if (unlikely(inode_unhashed(inode))) {
+ iput(inode);
+ goto again;
+ }
}
return inode;
@@ -1091,12 +1101,16 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino)
{
struct hlist_head *head = inode_hashtable + hash(sb, ino);
struct inode *inode;
-
+again:
spin_lock(&inode_hash_lock);
inode = find_inode_fast(sb, head, ino);
spin_unlock(&inode_hash_lock);
if (inode) {
wait_on_inode(inode);
+ if (unlikely(inode_unhashed(inode))) {
+ iput(inode);
+ goto again;
+ }
return inode;
}
@@ -1131,6 +1145,10 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino)
destroy_inode(inode);
inode = old;
wait_on_inode(inode);
+ if (unlikely(inode_unhashed(inode))) {
+ iput(inode);
+ goto again;
+ }
}
return inode;
}
@@ -1266,10 +1284,16 @@ EXPORT_SYMBOL(ilookup5_nowait);
struct inode *ilookup5(struct super_block *sb, unsigned long hashval,
int (*test)(struct inode *, void *), void *data)
{
- struct inode *inode = ilookup5_nowait(sb, hashval, test, data);
-
- if (inode)
+ struct inode *inode;
+again:
+ inode = ilookup5_nowait(sb, hashval, test, data);
+ if (inode) {
wait_on_inode(inode);
+ if (unlikely(inode_unhashed(inode))) {
+ iput(inode);
+ goto again;
+ }
+ }
return inode;
}
EXPORT_SYMBOL(ilookup5);
@@ -1286,13 +1310,18 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)
{
struct hlist_head *head = inode_hashtable + hash(sb, ino);
struct inode *inode;
-
+again:
spin_lock(&inode_hash_lock);
inode = find_inode_fast(sb, head, ino);
spin_unlock(&inode_hash_lock);
- if (inode)
+ if (inode) {
wait_on_inode(inode);
+ if (unlikely(inode_unhashed(inode))) {
+ iput(inode);
+ goto again;
+ }
+ }
return inode;
}
EXPORT_SYMBOL(ilookup);
@@ -1536,16 +1565,36 @@ sector_t bmap(struct inode *inode, sector_t block)
EXPORT_SYMBOL(bmap);
/*
+ * Update times in overlayed inode from underlying real inode
+ */
+static void update_ovl_inode_times(struct dentry *dentry, struct inode *inode,
+ bool rcu)
+{
+ if (!rcu) {
+ struct inode *realinode = d_real_inode(dentry);
+
+ if (unlikely(inode != realinode) &&
+ (!timespec_equal(&inode->i_mtime, &realinode->i_mtime) ||
+ !timespec_equal(&inode->i_ctime, &realinode->i_ctime))) {
+ inode->i_mtime = realinode->i_mtime;
+ inode->i_ctime = realinode->i_ctime;
+ }
+ }
+}
+
+/*
* With relative atime, only update atime if the previous atime is
* earlier than either the ctime or mtime or if at least a day has
* passed since the last atime update.
*/
-static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
- struct timespec now)
+static int relatime_need_update(const struct path *path, struct inode *inode,
+ struct timespec now, bool rcu)
{
- if (!(mnt->mnt_flags & MNT_RELATIME))
+ if (!(path->mnt->mnt_flags & MNT_RELATIME))
return 1;
+
+ update_ovl_inode_times(path->dentry, inode, rcu);
/*
* Is mtime younger than atime? If yes, update atime:
*/
@@ -1612,7 +1661,8 @@ static int update_time(struct inode *inode, struct timespec *time, int flags)
* This function automatically handles read only file systems and media,
* as well as the "noatime" flag and inode specific "noatime" markers.
*/
-bool atime_needs_update(const struct path *path, struct inode *inode)
+bool __atime_needs_update(const struct path *path, struct inode *inode,
+ bool rcu)
{
struct vfsmount *mnt = path->mnt;
struct timespec now;
@@ -1636,9 +1686,9 @@ bool atime_needs_update(const struct path *path, struct inode *inode)
if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
return false;
- now = current_fs_time(inode->i_sb);
+ now = current_time(inode);
- if (!relatime_need_update(mnt, inode, now))
+ if (!relatime_need_update(path, inode, now, rcu))
return false;
if (timespec_equal(&inode->i_atime, &now))
@@ -1653,7 +1703,7 @@ void touch_atime(const struct path *path)
struct inode *inode = d_inode(path->dentry);
struct timespec now;
- if (!atime_needs_update(path, inode))
+ if (!__atime_needs_update(path, inode, false))
return;
if (!sb_start_write_trylock(inode->i_sb))
@@ -1670,7 +1720,7 @@ void touch_atime(const struct path *path)
* We may also fail on filesystems that have the ability to make parts
* of the fs read only, e.g. subvolumes in Btrfs.
*/
- now = current_fs_time(inode->i_sb);
+ now = current_time(inode);
update_time(inode, &now, S_ATIME);
__mnt_drop_write(mnt);
skip_update:
@@ -1793,7 +1843,7 @@ int file_update_time(struct file *file)
if (IS_NOCMTIME(inode))
return 0;
- now = current_fs_time(inode->i_sb);
+ now = current_time(inode);
if (!timespec_equal(&inode->i_mtime, &now))
sync_it = S_MTIME;
@@ -2049,3 +2099,26 @@ void inode_nohighmem(struct inode *inode)
mapping_set_gfp_mask(inode->i_mapping, GFP_USER);
}
EXPORT_SYMBOL(inode_nohighmem);
+
+/**
+ * current_time - Return FS time
+ * @inode: inode.
+ *
+ * Return the current time truncated to the time granularity supported by
+ * the fs.
+ *
+ * Note that inode and inode->sb cannot be NULL.
+ * Otherwise, the function warns and returns time without truncation.
+ */
+struct timespec current_time(struct inode *inode)
+{
+ struct timespec now = current_kernel_time();
+
+ if (unlikely(!inode->i_sb)) {
+ WARN(1, "current_time() called with uninitialized super_block in the inode");
+ return now;
+ }
+
+ return timespec_trunc(now, inode->i_sb->s_time_gran);
+}
+EXPORT_SYMBOL(current_time);
diff --git a/fs/internal.h b/fs/internal.h
index 859178692ce4..f4da3341b4a3 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -121,6 +121,15 @@ extern long prune_icache_sb(struct super_block *sb, struct shrink_control *sc);
extern void inode_add_lru(struct inode *inode);
extern int dentry_needs_remove_privs(struct dentry *dentry);
+extern bool __atime_needs_update(const struct path *, struct inode *, bool);
+static inline bool atime_needs_update_rcu(const struct path *path,
+ struct inode *inode)
+{
+ return __atime_needs_update(path, inode, true);
+}
+
+extern bool atime_needs_update_rcu(const struct path *, struct inode *);
+
/*
* fs-writeback.c
*/
@@ -157,7 +166,7 @@ extern void mnt_pin_kill(struct mount *m);
/*
* fs/nsfs.c
*/
-extern struct dentry_operations ns_dentry_operations;
+extern const struct dentry_operations ns_dentry_operations;
/*
* fs/ioctl.c
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 5bb565f9989c..31f8ca046639 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -269,8 +269,7 @@ static int journal_finish_inode_data_buffers(journal_t *journal,
* filemap_fdatawait_range(), set it again so
* that user process can get -EIO from fsync().
*/
- set_bit(AS_EIO,
- &jinode->i_vfs_inode->i_mapping->flags);
+ mapping_set_error(jinode->i_vfs_inode->i_mapping, -EIO);
if (!ret)
ret = err;
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index bc2693d56298..7ebacf14837f 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -233,22 +233,21 @@ int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
case ACL_TYPE_ACCESS:
xprefix = JFFS2_XPREFIX_ACL_ACCESS;
if (acl) {
- umode_t mode = inode->i_mode;
- rc = posix_acl_equiv_mode(acl, &mode);
- if (rc < 0)
+ umode_t mode;
+
+ rc = posix_acl_update_mode(inode, &mode, &acl);
+ if (rc)
return rc;
if (inode->i_mode != mode) {
struct iattr attr;
attr.ia_valid = ATTR_MODE | ATTR_CTIME;
attr.ia_mode = mode;
- attr.ia_ctime = CURRENT_TIME_SEC;
+ attr.ia_ctime = current_time(inode);
rc = jffs2_do_setattr(inode, &attr);
if (rc < 0)
return rc;
}
- if (rc == 0)
- acl = NULL;
}
break;
case ACL_TYPE_DEFAULT:
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 30eb33ff8189..0a754f38462e 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -35,7 +35,8 @@ static int jffs2_mkdir (struct inode *,struct dentry *,umode_t);
static int jffs2_rmdir (struct inode *,struct dentry *);
static int jffs2_mknod (struct inode *,struct dentry *,umode_t,dev_t);
static int jffs2_rename (struct inode *, struct dentry *,
- struct inode *, struct dentry *);
+ struct inode *, struct dentry *,
+ unsigned int);
const struct file_operations jffs2_dir_operations =
{
@@ -61,10 +62,7 @@ const struct inode_operations jffs2_dir_inode_operations =
.get_acl = jffs2_get_acl,
.set_acl = jffs2_set_acl,
.setattr = jffs2_setattr,
- .setxattr = jffs2_setxattr,
- .getxattr = jffs2_getxattr,
.listxattr = jffs2_listxattr,
- .removexattr = jffs2_removexattr
};
/***********************************************************************/
@@ -759,7 +757,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode
}
static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
- struct inode *new_dir_i, struct dentry *new_dentry)
+ struct inode *new_dir_i, struct dentry *new_dentry,
+ unsigned int flags)
{
int ret;
struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
@@ -767,6 +766,9 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
uint8_t type;
uint32_t now;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
/* The VFS will check for us and prevent trying to rename a
* file over a directory and vice versa, but if it's a directory,
* the VFS can't check whether the victim is empty. The filesystem
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 0e62dec3effc..c12476e309c6 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -66,10 +66,7 @@ const struct inode_operations jffs2_file_inode_operations =
.get_acl = jffs2_get_acl,
.set_acl = jffs2_set_acl,
.setattr = jffs2_setattr,
- .setxattr = jffs2_setxattr,
- .getxattr = jffs2_getxattr,
.listxattr = jffs2_listxattr,
- .removexattr = jffs2_removexattr
};
const struct address_space_operations jffs2_file_address_operations =
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index ae2ebb26b446..567653f7c0ce 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -193,7 +193,7 @@ int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
struct inode *inode = d_inode(dentry);
int rc;
- rc = inode_change_ok(inode, iattr);
+ rc = setattr_prepare(dentry, iattr);
if (rc)
return rc;
@@ -472,7 +472,7 @@ struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_r
inode->i_mode = jemode_to_cpu(ri->mode);
i_gid_write(inode, je16_to_cpu(ri->gid));
i_uid_write(inode, je16_to_cpu(ri->uid));
- inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+ inode->i_atime = inode->i_ctime = inode->i_mtime = current_time(inode);
ri->atime = ri->mtime = ri->ctime = cpu_to_je32(I_SEC(inode->i_mtime));
inode->i_blocks = 0;
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index 2cabd649d4fb..8f3f0855fcd2 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -16,8 +16,5 @@ const struct inode_operations jffs2_symlink_inode_operations =
.readlink = generic_readlink,
.get_link = simple_get_link,
.setattr = jffs2_setattr,
- .setxattr = jffs2_setxattr,
- .getxattr = jffs2_getxattr,
.listxattr = jffs2_listxattr,
- .removexattr = jffs2_removexattr
};
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index 467ff376ee26..720007b2fd65 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -99,9 +99,6 @@ extern const struct xattr_handler jffs2_user_xattr_handler;
extern const struct xattr_handler jffs2_trusted_xattr_handler;
extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
-#define jffs2_getxattr generic_getxattr
-#define jffs2_setxattr generic_setxattr
-#define jffs2_removexattr generic_removexattr
#else
@@ -116,9 +113,6 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
#define jffs2_xattr_handlers NULL
#define jffs2_listxattr NULL
-#define jffs2_getxattr NULL
-#define jffs2_setxattr NULL
-#define jffs2_removexattr NULL
#endif /* CONFIG_JFFS2_FS_XATTR */
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 21fa92ba2c19..7bc186f4ed4d 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -78,13 +78,11 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
case ACL_TYPE_ACCESS:
ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
if (acl) {
- rc = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (rc < 0)
+ rc = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (rc)
return rc;
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
- if (rc == 0)
- acl = NULL;
}
break;
case ACL_TYPE_DEFAULT:
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index 7f1a585a0a94..739492c7a3fd 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -103,7 +103,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
struct inode *inode = d_inode(dentry);
int rc;
- rc = inode_change_ok(inode, iattr);
+ rc = setattr_prepare(dentry, iattr);
if (rc)
return rc;
@@ -140,10 +140,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
}
const struct inode_operations jfs_file_inode_operations = {
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = jfs_listxattr,
- .removexattr = generic_removexattr,
.setattr = jfs_setattr,
#ifdef CONFIG_JFS_POSIX_ACL
.get_acl = jfs_get_acl,
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index ad3e7b1effc4..054cc761b426 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -403,7 +403,7 @@ void jfs_truncate_nolock(struct inode *ip, loff_t length)
break;
}
- ip->i_mtime = ip->i_ctime = CURRENT_TIME;
+ ip->i_mtime = ip->i_ctime = current_time(ip);
mark_inode_dirty(ip);
txCommit(tid, 1, &ip, 0);
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index 5e33cb9a190d..375dd257a34f 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -131,7 +131,7 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
jfs_inode->mode2 |= inode->i_mode;
inode->i_blocks = 0;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
jfs_inode->otime = inode->i_ctime.tv_sec;
inode->i_generation = JFS_SBI(sb)->gengen++;
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 814b0c58016c..b41596d71858 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -162,7 +162,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, umode_t mode,
mark_inode_dirty(ip);
- dip->i_ctime = dip->i_mtime = CURRENT_TIME;
+ dip->i_ctime = dip->i_mtime = current_time(dip);
mark_inode_dirty(dip);
@@ -298,7 +298,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
/* update parent directory inode */
inc_nlink(dip); /* for '..' from child directory */
- dip->i_ctime = dip->i_mtime = CURRENT_TIME;
+ dip->i_ctime = dip->i_mtime = current_time(dip);
mark_inode_dirty(dip);
rc = txCommit(tid, 2, &iplist[0], 0);
@@ -406,7 +406,7 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
/* update parent directory's link count corresponding
* to ".." entry of the target directory deleted
*/
- dip->i_ctime = dip->i_mtime = CURRENT_TIME;
+ dip->i_ctime = dip->i_mtime = current_time(dip);
inode_dec_link_count(dip);
/*
@@ -528,7 +528,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
ASSERT(ip->i_nlink);
- ip->i_ctime = dip->i_ctime = dip->i_mtime = CURRENT_TIME;
+ ip->i_ctime = dip->i_ctime = dip->i_mtime = current_time(ip);
mark_inode_dirty(dip);
/* update target's inode */
@@ -838,8 +838,8 @@ static int jfs_link(struct dentry *old_dentry,
/* update object inode */
inc_nlink(ip); /* for new link */
- ip->i_ctime = CURRENT_TIME;
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ ip->i_ctime = current_time(ip);
+ dir->i_ctime = dir->i_mtime = current_time(dir);
mark_inode_dirty(dir);
ihold(ip);
@@ -1039,7 +1039,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
mark_inode_dirty(ip);
- dip->i_ctime = dip->i_mtime = CURRENT_TIME;
+ dip->i_ctime = dip->i_mtime = current_time(dip);
mark_inode_dirty(dip);
/*
* commit update of parent directory and link object
@@ -1078,7 +1078,8 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
* FUNCTION: rename a file or directory
*/
static int jfs_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 btstack btstack;
ino_t ino;
@@ -1097,6 +1098,8 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
s64 new_size = 0;
int commit_flag;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
jfs_info("jfs_rename: %pd %pd", old_dentry, new_dentry);
@@ -1215,7 +1218,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
tblk->xflag |= COMMIT_DELETE;
tblk->u.ip = new_ip;
} else {
- new_ip->i_ctime = CURRENT_TIME;
+ new_ip->i_ctime = current_time(new_ip);
mark_inode_dirty(new_ip);
}
} else {
@@ -1278,10 +1281,10 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
/*
* Update ctime on changed/moved inodes & mark dirty
*/
- old_ip->i_ctime = CURRENT_TIME;
+ old_ip->i_ctime = current_time(old_ip);
mark_inode_dirty(old_ip);
- new_dir->i_ctime = new_dir->i_mtime = current_fs_time(new_dir->i_sb);
+ new_dir->i_ctime = new_dir->i_mtime = current_time(new_dir);
mark_inode_dirty(new_dir);
/* Build list of inodes modified by this transaction */
@@ -1293,7 +1296,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (old_dir != new_dir) {
iplist[ipcount++] = new_dir;
- old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+ old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
mark_inode_dirty(old_dir);
}
@@ -1426,7 +1429,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
mark_inode_dirty(ip);
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ dir->i_ctime = dir->i_mtime = current_time(dir);
mark_inode_dirty(dir);
@@ -1537,10 +1540,7 @@ const struct inode_operations jfs_dir_inode_operations = {
.rmdir = jfs_rmdir,
.mknod = jfs_mknod,
.rename = jfs_rename,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = jfs_listxattr,
- .removexattr = generic_removexattr,
.setattr = jfs_setattr,
#ifdef CONFIG_JFS_POSIX_ACL
.get_acl = jfs_get_acl,
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index cec8814a3b8b..85671f7f8518 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -830,7 +830,7 @@ out:
if (inode->i_size < off+len-towrite)
i_size_write(inode, off+len-towrite);
inode->i_version++;
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
inode_unlock(inode);
return len - towrite;
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c
index c94c7e4a1323..c82404fee6cd 100644
--- a/fs/jfs/symlink.c
+++ b/fs/jfs/symlink.c
@@ -25,19 +25,13 @@ const struct inode_operations jfs_fast_symlink_inode_operations = {
.readlink = generic_readlink,
.get_link = simple_get_link,
.setattr = jfs_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = jfs_listxattr,
- .removexattr = generic_removexattr,
};
const struct inode_operations jfs_symlink_inode_operations = {
.readlink = generic_readlink,
.get_link = page_get_link,
.setattr = jfs_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = jfs_listxattr,
- .removexattr = generic_removexattr,
};
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 0bf3c33aedff..c60f3d32ee91 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -658,7 +658,7 @@ static int ea_put(tid_t tid, struct inode *inode, struct ea_buffer *ea_buf,
if (old_blocks)
dquot_free_block(inode, old_blocks);
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
return 0;
}
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index e57174d43683..dcd96aac02f5 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -1096,13 +1096,17 @@ static int kernfs_iop_rmdir(struct inode *dir, struct dentry *dentry)
}
static int kernfs_iop_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 kernfs_node *kn = old_dentry->d_fsdata;
struct kernfs_node *new_parent = new_dir->i_private;
struct kernfs_syscall_ops *scops = kernfs_root(kn)->syscall_ops;
int ret;
+ if (flags)
+ return -EINVAL;
+
if (!scops || !scops->rename)
return -EPERM;
@@ -1126,9 +1130,6 @@ const struct inode_operations kernfs_dir_iops = {
.permission = kernfs_iop_permission,
.setattr = kernfs_iop_setattr,
.getattr = kernfs_iop_getattr,
- .setxattr = kernfs_iop_setxattr,
- .removexattr = kernfs_iop_removexattr,
- .getxattr = kernfs_iop_getxattr,
.listxattr = kernfs_iop_listxattr,
.mkdir = kernfs_iop_mkdir,
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index 63b925d5ba1e..a1982118f92f 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -28,9 +28,6 @@ static const struct inode_operations kernfs_iops = {
.permission = kernfs_iop_permission,
.setattr = kernfs_iop_setattr,
.getattr = kernfs_iop_getattr,
- .setxattr = kernfs_iop_setxattr,
- .removexattr = kernfs_iop_removexattr,
- .getxattr = kernfs_iop_getxattr,
.listxattr = kernfs_iop_listxattr,
};
@@ -122,7 +119,7 @@ int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
return -EINVAL;
mutex_lock(&kernfs_mutex);
- error = inode_change_ok(inode, iattr);
+ error = setattr_prepare(dentry, iattr);
if (error)
goto out;
@@ -138,17 +135,12 @@ out:
return error;
}
-static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
+static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
u32 *secdata_len)
{
- struct kernfs_iattrs *attrs;
void *old_secdata;
size_t old_secdata_len;
- attrs = kernfs_iattrs(kn);
- if (!attrs)
- return -ENOMEM;
-
old_secdata = attrs->ia_secdata;
old_secdata_len = attrs->ia_secdata_len;
@@ -160,71 +152,6 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
return 0;
}
-int kernfs_iop_setxattr(struct dentry *unused, struct inode *inode,
- const char *name, const void *value,
- size_t size, int flags)
-{
- struct kernfs_node *kn = inode->i_private;
- struct kernfs_iattrs *attrs;
- void *secdata;
- int error;
- u32 secdata_len = 0;
-
- attrs = kernfs_iattrs(kn);
- if (!attrs)
- return -ENOMEM;
-
- if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
- const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
- error = security_inode_setsecurity(inode, suffix,
- value, size, flags);
- if (error)
- return error;
- error = security_inode_getsecctx(inode,
- &secdata, &secdata_len);
- if (error)
- return error;
-
- mutex_lock(&kernfs_mutex);
- error = kernfs_node_setsecdata(kn, &secdata, &secdata_len);
- mutex_unlock(&kernfs_mutex);
-
- if (secdata)
- security_release_secctx(secdata, secdata_len);
- return error;
- } else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
- return simple_xattr_set(&attrs->xattrs, name, value, size,
- flags);
- }
-
- return -EINVAL;
-}
-
-int kernfs_iop_removexattr(struct dentry *dentry, const char *name)
-{
- struct kernfs_node *kn = dentry->d_fsdata;
- struct kernfs_iattrs *attrs;
-
- attrs = kernfs_iattrs(kn);
- if (!attrs)
- return -ENOMEM;
-
- return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE);
-}
-
-ssize_t kernfs_iop_getxattr(struct dentry *unused, struct inode *inode,
- const char *name, void *buf, size_t size)
-{
- struct kernfs_node *kn = inode->i_private;
- struct kernfs_iattrs *attrs;
-
- attrs = kernfs_iattrs(kn);
- if (!attrs)
- return -ENOMEM;
-
- return simple_xattr_get(&attrs->xattrs, name, buf, size);
-}
-
ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
{
struct kernfs_node *kn = dentry->d_fsdata;
@@ -241,7 +168,7 @@ static inline void set_default_inode_attr(struct inode *inode, umode_t mode)
{
inode->i_mode = mode;
inode->i_atime = inode->i_mtime =
- inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_ctime = current_time(inode);
}
static inline void set_inode_attr(struct inode *inode, struct iattr *iattr)
@@ -376,3 +303,83 @@ int kernfs_iop_permission(struct inode *inode, int mask)
return generic_permission(inode, mask);
}
+
+static int kernfs_xattr_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+ const char *suffix, void *value, size_t size)
+{
+ const char *name = xattr_full_name(handler, suffix);
+ struct kernfs_node *kn = inode->i_private;
+ struct kernfs_iattrs *attrs;
+
+ attrs = kernfs_iattrs(kn);
+ if (!attrs)
+ return -ENOMEM;
+
+ return simple_xattr_get(&attrs->xattrs, name, value, size);
+}
+
+static int kernfs_xattr_set(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+ const char *suffix, const void *value,
+ size_t size, int flags)
+{
+ const char *name = xattr_full_name(handler, suffix);
+ struct kernfs_node *kn = inode->i_private;
+ struct kernfs_iattrs *attrs;
+
+ attrs = kernfs_iattrs(kn);
+ if (!attrs)
+ return -ENOMEM;
+
+ return simple_xattr_set(&attrs->xattrs, name, value, size, flags);
+}
+
+const struct xattr_handler kernfs_trusted_xattr_handler = {
+ .prefix = XATTR_TRUSTED_PREFIX,
+ .get = kernfs_xattr_get,
+ .set = kernfs_xattr_set,
+};
+
+static int kernfs_security_xattr_set(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+ const char *suffix, const void *value,
+ size_t size, int flags)
+{
+ struct kernfs_node *kn = inode->i_private;
+ struct kernfs_iattrs *attrs;
+ void *secdata;
+ u32 secdata_len = 0;
+ int error;
+
+ attrs = kernfs_iattrs(kn);
+ if (!attrs)
+ return -ENOMEM;
+
+ error = security_inode_setsecurity(inode, suffix, value, size, flags);
+ if (error)
+ return error;
+ error = security_inode_getsecctx(inode, &secdata, &secdata_len);
+ if (error)
+ return error;
+
+ mutex_lock(&kernfs_mutex);
+ error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len);
+ mutex_unlock(&kernfs_mutex);
+
+ if (secdata)
+ security_release_secctx(secdata, secdata_len);
+ return error;
+}
+
+const struct xattr_handler kernfs_security_xattr_handler = {
+ .prefix = XATTR_SECURITY_PREFIX,
+ .get = kernfs_xattr_get,
+ .set = kernfs_security_xattr_set,
+};
+
+const struct xattr_handler *kernfs_xattr_handlers[] = {
+ &kernfs_trusted_xattr_handler,
+ &kernfs_security_xattr_handler,
+ NULL
+};
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
index 37159235ac10..bfd551bbf231 100644
--- a/fs/kernfs/kernfs-internal.h
+++ b/fs/kernfs/kernfs-internal.h
@@ -76,17 +76,12 @@ extern struct kmem_cache *kernfs_node_cache;
/*
* inode.c
*/
+extern const struct xattr_handler *kernfs_xattr_handlers[];
void kernfs_evict_inode(struct inode *inode);
int kernfs_iop_permission(struct inode *inode, int mask);
int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr);
int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat);
-int kernfs_iop_setxattr(struct dentry *dentry, struct inode *inode,
- const char *name, const void *value,
- size_t size, int flags);
-int kernfs_iop_removexattr(struct dentry *dentry, const char *name);
-ssize_t kernfs_iop_getxattr(struct dentry *dentry, struct inode *inode,
- const char *name, void *buf, size_t size);
ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size);
/*
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index b3d73ad52b22..d5b149a45be1 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -158,6 +158,7 @@ static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
sb->s_blocksize_bits = PAGE_SHIFT;
sb->s_magic = magic;
sb->s_op = &kernfs_sops;
+ sb->s_xattr = kernfs_xattr_handlers;
sb->s_time_gran = 1;
/* get root inode, initialize and unlock it */
diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c
index 117b8b3416f9..9b43ca02b7ab 100644
--- a/fs/kernfs/symlink.c
+++ b/fs/kernfs/symlink.c
@@ -134,9 +134,6 @@ static const char *kernfs_iop_get_link(struct dentry *dentry,
}
const struct inode_operations kernfs_symlink_iops = {
- .setxattr = kernfs_iop_setxattr,
- .removexattr = kernfs_iop_removexattr,
- .getxattr = kernfs_iop_getxattr,
.listxattr = kernfs_iop_listxattr,
.readlink = generic_readlink,
.get_link = kernfs_iop_get_link,
diff --git a/fs/libfs.c b/fs/libfs.c
index 74dc8b9e7f53..48826d4da189 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -236,8 +236,8 @@ static const struct super_operations simple_super_operations = {
* Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
* will never be mountable)
*/
-struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
- const struct super_operations *ops,
+struct dentry *mount_pseudo_xattr(struct file_system_type *fs_type, char *name,
+ const struct super_operations *ops, const struct xattr_handler **xattr,
const struct dentry_operations *dops, unsigned long magic)
{
struct super_block *s;
@@ -254,6 +254,7 @@ struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
s->s_blocksize_bits = PAGE_SHIFT;
s->s_magic = magic;
s->s_op = ops ? ops : &simple_super_operations;
+ s->s_xattr = xattr;
s->s_time_gran = 1;
root = new_inode(s);
if (!root)
@@ -265,7 +266,7 @@ struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
*/
root->i_ino = 1;
root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
- root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
+ root->i_atime = root->i_mtime = root->i_ctime = current_time(root);
dentry = __d_alloc(s, &d_name);
if (!dentry) {
iput(root);
@@ -281,7 +282,7 @@ Enomem:
deactivate_locked_super(s);
return ERR_PTR(-ENOMEM);
}
-EXPORT_SYMBOL(mount_pseudo);
+EXPORT_SYMBOL(mount_pseudo_xattr);
int simple_open(struct inode *inode, struct file *file)
{
@@ -295,7 +296,7 @@ int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *den
{
struct inode *inode = d_inode(old_dentry);
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode);
inc_nlink(inode);
ihold(inode);
dget(dentry);
@@ -329,7 +330,7 @@ int simple_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = d_inode(dentry);
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode);
drop_nlink(inode);
dput(dentry);
return 0;
@@ -349,11 +350,15 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry)
EXPORT_SYMBOL(simple_rmdir);
int simple_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 *inode = d_inode(old_dentry);
int they_are_dirs = d_is_dir(old_dentry);
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
if (!simple_empty(new_dentry))
return -ENOTEMPTY;
@@ -369,7 +374,7 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
}
old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
- new_dir->i_mtime = inode->i_ctime = CURRENT_TIME;
+ new_dir->i_mtime = inode->i_ctime = current_time(old_dir);
return 0;
}
@@ -394,7 +399,7 @@ int simple_setattr(struct dentry *dentry, struct iattr *iattr)
struct inode *inode = d_inode(dentry);
int error;
- error = inode_change_ok(inode, iattr);
+ error = setattr_prepare(dentry, iattr);
if (error)
return error;
@@ -520,7 +525,7 @@ int simple_fill_super(struct super_block *s, unsigned long magic,
*/
inode->i_ino = 1;
inode->i_mode = S_IFDIR | 0755;
- 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_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
set_nlink(inode, 2);
@@ -546,7 +551,7 @@ int simple_fill_super(struct super_block *s, unsigned long magic,
goto out;
}
inode->i_mode = S_IFREG | files->mode;
- 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_fop = files->ops;
inode->i_ino = i;
d_add(dentry, inode);
@@ -1092,7 +1097,7 @@ struct inode *alloc_anon_inode(struct super_block *s)
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
inode->i_flags |= S_PRIVATE;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
return inode;
}
EXPORT_SYMBOL(alloc_anon_inode);
@@ -1149,24 +1154,6 @@ static int empty_dir_setattr(struct dentry *dentry, struct iattr *attr)
return -EPERM;
}
-static int empty_dir_setxattr(struct dentry *dentry, struct inode *inode,
- const char *name, const void *value,
- size_t size, int flags)
-{
- return -EOPNOTSUPP;
-}
-
-static ssize_t empty_dir_getxattr(struct dentry *dentry, struct inode *inode,
- const char *name, void *value, size_t size)
-{
- return -EOPNOTSUPP;
-}
-
-static int empty_dir_removexattr(struct dentry *dentry, const char *name)
-{
- return -EOPNOTSUPP;
-}
-
static ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t size)
{
return -EOPNOTSUPP;
@@ -1177,9 +1164,6 @@ static const struct inode_operations empty_dir_inode_operations = {
.permission = generic_permission,
.setattr = empty_dir_setattr,
.getattr = empty_dir_getattr,
- .setxattr = empty_dir_setxattr,
- .getxattr = empty_dir_getxattr,
- .removexattr = empty_dir_removexattr,
.listxattr = empty_dir_listxattr,
};
@@ -1215,6 +1199,7 @@ void make_empty_dir_inode(struct inode *inode)
inode->i_blocks = 0;
inode->i_op = &empty_dir_inode_operations;
+ inode->i_opflags &= ~IOP_XATTR;
inode->i_fop = &empty_dir_operations;
}
diff --git a/fs/lockd/procfs.h b/fs/lockd/procfs.h
index 2257a1311027..184a15edd18d 100644
--- a/fs/lockd/procfs.h
+++ b/fs/lockd/procfs.h
@@ -6,8 +6,6 @@
#ifndef _LOCKD_PROCFS_H
#define _LOCKD_PROCFS_H
-#include <linux/kconfig.h>
-
#if IS_ENABLED(CONFIG_PROC_FS)
int lockd_create_procfs(void);
void lockd_remove_procfs(void);
diff --git a/fs/locks.c b/fs/locks.c
index 90ec67108b22..ce93b416b490 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -138,6 +138,11 @@
#define IS_LEASE(fl) (fl->fl_flags & (FL_LEASE|FL_DELEG|FL_LAYOUT))
#define IS_OFDLCK(fl) (fl->fl_flags & FL_OFDLCK)
+static inline bool is_remote_lock(struct file *filp)
+{
+ return likely(!(filp->f_path.dentry->d_sb->s_flags & MS_NOREMOTELOCK));
+}
+
static bool lease_breaking(struct file_lock *fl)
{
return fl->fl_flags & (FL_UNLOCK_PENDING | FL_DOWNGRADE_PENDING);
@@ -806,7 +811,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
{
struct file_lock *cfl;
struct file_lock_context *ctx;
- struct inode *inode = file_inode(filp);
+ struct inode *inode = locks_inode(filp);
ctx = smp_load_acquire(&inode->i_flctx);
if (!ctx || list_empty_careful(&ctx->flc_posix)) {
@@ -1211,7 +1216,7 @@ static int posix_lock_inode(struct inode *inode, struct file_lock *request,
int posix_lock_file(struct file *filp, struct file_lock *fl,
struct file_lock *conflock)
{
- return posix_lock_inode(file_inode(filp), fl, conflock);
+ return posix_lock_inode(locks_inode(filp), fl, conflock);
}
EXPORT_SYMBOL(posix_lock_file);
@@ -1251,7 +1256,7 @@ static int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl)
int locks_mandatory_locked(struct file *file)
{
int ret;
- struct inode *inode = file_inode(file);
+ struct inode *inode = locks_inode(file);
struct file_lock_context *ctx;
struct file_lock *fl;
@@ -1564,7 +1569,7 @@ void lease_get_mtime(struct inode *inode, struct timespec *time)
}
if (has_lease)
- *time = current_fs_time(inode->i_sb);
+ *time = current_time(inode);
else
*time = inode->i_mtime;
}
@@ -1597,7 +1602,7 @@ EXPORT_SYMBOL(lease_get_mtime);
int fcntl_getlease(struct file *filp)
{
struct file_lock *fl;
- struct inode *inode = file_inode(filp);
+ struct inode *inode = locks_inode(filp);
struct file_lock_context *ctx;
int type = F_UNLCK;
LIST_HEAD(dispose);
@@ -1605,7 +1610,7 @@ int fcntl_getlease(struct file *filp)
ctx = smp_load_acquire(&inode->i_flctx);
if (ctx && !list_empty_careful(&ctx->flc_lease)) {
spin_lock(&ctx->flc_lock);
- time_out_leases(file_inode(filp), &dispose);
+ time_out_leases(inode, &dispose);
list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
if (fl->fl_file != filp)
continue;
@@ -1638,7 +1643,8 @@ check_conflicting_open(const struct dentry *dentry, const long arg, int flags)
if (flags & FL_LAYOUT)
return 0;
- if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
+ if ((arg == F_RDLCK) &&
+ (atomic_read(&d_real_inode(dentry)->i_writecount) > 0))
return -EAGAIN;
if ((arg == F_WRLCK) && ((d_count(dentry) > 1) ||
@@ -1653,7 +1659,7 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
{
struct file_lock *fl, *my_fl = NULL, *lease;
struct dentry *dentry = filp->f_path.dentry;
- struct inode *inode = file_inode(filp);
+ struct inode *inode = dentry->d_inode;
struct file_lock_context *ctx;
bool is_deleg = (*flp)->fl_flags & FL_DELEG;
int error;
@@ -1769,7 +1775,7 @@ static int generic_delete_lease(struct file *filp, void *owner)
{
int error = -EAGAIN;
struct file_lock *fl, *victim = NULL;
- struct inode *inode = file_inode(filp);
+ struct inode *inode = locks_inode(filp);
struct file_lock_context *ctx;
LIST_HEAD(dispose);
@@ -1811,7 +1817,7 @@ static int generic_delete_lease(struct file *filp, void *owner)
int generic_setlease(struct file *filp, long arg, struct file_lock **flp,
void **priv)
{
- struct inode *inode = file_inode(filp);
+ struct inode *inode = locks_inode(filp);
int error;
if ((!uid_eq(current_fsuid(), inode->i_uid)) && !capable(CAP_LEASE))
@@ -1859,7 +1865,7 @@ EXPORT_SYMBOL(generic_setlease);
int
vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv)
{
- if (filp->f_op->setlease)
+ if (filp->f_op->setlease && is_remote_lock(filp))
return filp->f_op->setlease(filp, arg, lease, priv);
else
return generic_setlease(filp, arg, lease, priv);
@@ -2008,7 +2014,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
if (error)
goto out_free;
- if (f.file->f_op->flock)
+ if (f.file->f_op->flock && is_remote_lock(f.file))
error = f.file->f_op->flock(f.file,
(can_sleep) ? F_SETLKW : F_SETLK,
lock);
@@ -2034,7 +2040,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
*/
int vfs_test_lock(struct file *filp, struct file_lock *fl)
{
- if (filp->f_op->lock)
+ if (filp->f_op->lock && is_remote_lock(filp))
return filp->f_op->lock(filp, F_GETLK, fl);
posix_test_lock(filp, fl);
return 0;
@@ -2158,7 +2164,7 @@ out:
*/
int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
{
- if (filp->f_op->lock)
+ if (filp->f_op->lock && is_remote_lock(filp))
return filp->f_op->lock(filp, cmd, fl);
else
return posix_lock_file(filp, fl, conf);
@@ -2220,7 +2226,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
if (file_lock == NULL)
return -ENOLCK;
- inode = file_inode(filp);
+ inode = locks_inode(filp);
/*
* This might block, so we do it before checking the inode.
@@ -2372,7 +2378,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
if (copy_from_user(&flock, l, sizeof(flock)))
goto out;
- inode = file_inode(filp);
+ inode = locks_inode(filp);
/* Don't allow mandatory locks on files that may be memory mapped
* and shared.
@@ -2455,6 +2461,7 @@ out:
void locks_remove_posix(struct file *filp, fl_owner_t owner)
{
int error;
+ struct inode *inode = locks_inode(filp);
struct file_lock lock;
struct file_lock_context *ctx;
@@ -2463,7 +2470,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
* posix_lock_file(). Another process could be setting a lock on this
* file at the same time, but we wouldn't remove that lock anyway.
*/
- ctx = smp_load_acquire(&file_inode(filp)->i_flctx);
+ ctx = smp_load_acquire(&inode->i_flctx);
if (!ctx || list_empty(&ctx->flc_posix))
return;
@@ -2481,7 +2488,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
if (lock.fl_ops && lock.fl_ops->fl_release_private)
lock.fl_ops->fl_release_private(&lock);
- trace_locks_remove_posix(file_inode(filp), &lock, error);
+ trace_locks_remove_posix(inode, &lock, error);
}
EXPORT_SYMBOL(locks_remove_posix);
@@ -2498,12 +2505,12 @@ locks_remove_flock(struct file *filp, struct file_lock_context *flctx)
.fl_type = F_UNLCK,
.fl_end = OFFSET_MAX,
};
- struct inode *inode = file_inode(filp);
+ struct inode *inode = locks_inode(filp);
if (list_empty(&flctx->flc_flock))
return;
- if (filp->f_op->flock)
+ if (filp->f_op->flock && is_remote_lock(filp))
filp->f_op->flock(filp, F_SETLKW, &fl);
else
flock_lock_inode(inode, &fl);
@@ -2537,7 +2544,7 @@ void locks_remove_file(struct file *filp)
{
struct file_lock_context *ctx;
- ctx = smp_load_acquire(&file_inode(filp)->i_flctx);
+ ctx = smp_load_acquire(&locks_inode(filp)->i_flctx);
if (!ctx)
return;
@@ -2581,7 +2588,7 @@ EXPORT_SYMBOL(posix_unblock_lock);
*/
int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
{
- if (filp->f_op->lock)
+ if (filp->f_op->lock && is_remote_lock(filp))
return filp->f_op->lock(filp, F_CANCELLK, fl);
return 0;
}
@@ -2620,7 +2627,7 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
fl_pid = fl->fl_pid;
if (fl->fl_file != NULL)
- inode = file_inode(fl->fl_file);
+ inode = locks_inode(fl->fl_file);
seq_printf(f, "%lld:%s ", id, pfx);
if (IS_POSIX(fl)) {
@@ -2726,7 +2733,7 @@ static void __show_fd_locks(struct seq_file *f,
void show_fd_locks(struct seq_file *f,
struct file *filp, struct files_struct *files)
{
- struct inode *inode = file_inode(filp);
+ struct inode *inode = locks_inode(filp);
struct file_lock_context *ctx;
int id = 0;
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index 9568064ecadf..c87ea52de3d9 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -226,7 +226,7 @@ static int logfs_unlink(struct inode *dir, struct dentry *dentry)
ta->state = UNLINK_1;
ta->ino = inode->i_ino;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode);
page = logfs_get_dd_page(dir, dentry);
if (!page) {
@@ -540,7 +540,7 @@ static int logfs_link(struct dentry *old_dentry, struct inode *dir,
{
struct inode *inode = d_inode(old_dentry);
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode);
ihold(inode);
inc_nlink(inode);
mark_inode_dirty_sync(inode);
@@ -573,7 +573,7 @@ static int logfs_delete_dd(struct inode *dir, loff_t pos)
* (crc-protected) journal.
*/
BUG_ON(beyond_eof(dir, pos));
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ dir->i_ctime = dir->i_mtime = current_time(dir);
log_dir(" Delete dentry (%lx, %llx)\n", dir->i_ino, pos);
return logfs_delete(dir, pos, NULL);
}
@@ -718,8 +718,12 @@ out:
}
static int logfs_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)
{
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
if (d_really_is_positive(new_dentry))
return logfs_rename_target(old_dir, old_dentry,
new_dir, new_dentry);
diff --git a/fs/logfs/file.c b/fs/logfs/file.c
index f01ddfb1a03b..1db04930ad57 100644
--- a/fs/logfs/file.c
+++ b/fs/logfs/file.c
@@ -211,7 +211,7 @@ long logfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
li->li_flags = flags;
inode_unlock(inode);
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
mark_inode_dirty_sync(inode);
return 0;
@@ -244,7 +244,7 @@ static int logfs_setattr(struct dentry *dentry, struct iattr *attr)
struct inode *inode = d_inode(dentry);
int err = 0;
- err = inode_change_ok(inode, attr);
+ err = setattr_prepare(dentry, attr);
if (err)
return err;
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index db9cfc598883..f440a1525da8 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -213,8 +213,8 @@ static void logfs_init_inode(struct super_block *sb, struct inode *inode)
i_gid_write(inode, 0);
inode->i_size = 0;
inode->i_blocks = 0;
- inode->i_ctime = CURRENT_TIME;
- inode->i_mtime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
+ inode->i_mtime = current_time(inode);
li->li_refcount = 1;
INIT_LIST_HEAD(&li->li_freeing_list);
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
index 3fb8c6d67303..bf19bf4a243f 100644
--- a/fs/logfs/readwrite.c
+++ b/fs/logfs/readwrite.c
@@ -1546,7 +1546,7 @@ static int __logfs_write_buf(struct inode *inode, struct page *page, long flags)
int err;
flags |= WF_WRITE | WF_DELETE;
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
logfs_unpack_index(index, &bix, &level);
if (logfs_block(page) && logfs_block(page)->reserved_bytes)
@@ -1578,7 +1578,7 @@ static int __logfs_delete(struct inode *inode, struct page *page)
long flags = WF_DELETE;
int err;
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
if (page->index < I0_BLOCKS)
return logfs_write_direct(inode, page, flags);
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index 742942a983be..c2c3fd3277b5 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -253,7 +253,7 @@ struct inode *minix_new_inode(const struct inode *dir, umode_t mode, int *error)
}
inode_init_owner(inode, dir, mode);
inode->i_ino = j;
- 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;
memset(&minix_i(inode)->u, 0, sizeof(minix_i(inode)->u));
insert_inode_hash(inode);
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index 31dcd515b9d5..7edc9b395700 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -274,7 +274,7 @@ got_it:
de->inode = inode->i_ino;
}
err = dir_commit_chunk(page, pos, sbi->s_dirsize);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty(dir);
out_put:
dir_put_page(page);
@@ -306,7 +306,7 @@ int minix_delete_entry(struct minix_dir_entry *de, struct page *page)
unlock_page(page);
}
dir_put_page(page);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
mark_inode_dirty(inode);
return err;
}
@@ -430,7 +430,7 @@ void minix_set_link(struct minix_dir_entry *de, struct page *page,
unlock_page(page);
}
dir_put_page(page);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty(dir);
}
diff --git a/fs/minix/file.c b/fs/minix/file.c
index 94f0eb9a6e2c..a6a4797aa0d4 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -26,7 +26,7 @@ static int minix_setattr(struct dentry *dentry, struct iattr *attr)
struct inode *inode = d_inode(dentry);
int error;
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
if (error)
return error;
diff --git a/fs/minix/itree_common.c b/fs/minix/itree_common.c
index a731cabf1540..4c57c9af6946 100644
--- a/fs/minix/itree_common.c
+++ b/fs/minix/itree_common.c
@@ -124,7 +124,7 @@ static inline int splice_branch(struct inode *inode,
/* We are done with atomic stuff, now do the rest of housekeeping */
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
/* had we spliced it onto indirect block? */
if (where->bh)
@@ -343,7 +343,7 @@ do_indirects:
}
first_whole++;
}
- inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
}
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 2887d1d95ce2..1e0f11f5dac9 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -106,7 +106,7 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir,
{
struct inode *inode = d_inode(old_dentry);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
inode_inc_link_count(inode);
ihold(inode);
return add_nondir(dentry, inode);
@@ -185,7 +185,8 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry)
}
static int minix_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 = d_inode(old_dentry);
struct inode * new_inode = d_inode(new_dentry);
@@ -195,6 +196,9 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
struct minix_dir_entry * old_de;
int err = -ENOENT;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
old_de = minix_find_entry(old_dentry, &old_page);
if (!old_de)
goto out;
@@ -219,7 +223,7 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
if (!new_de)
goto out_dir;
minix_set_link(new_de, new_page, old_inode);
- new_inode->i_ctime = CURRENT_TIME_SEC;
+ new_inode->i_ctime = current_time(new_inode);
if (dir_de)
drop_nlink(new_inode);
inode_dec_link_count(new_inode);
diff --git a/fs/namei.c b/fs/namei.c
index adb04146df09..a7f601cd521a 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1015,7 +1015,7 @@ const char *get_link(struct nameidata *nd)
if (!(nd->flags & LOOKUP_RCU)) {
touch_atime(&last->link);
cond_resched();
- } else if (atime_needs_update(&last->link, inode)) {
+ } else if (atime_needs_update_rcu(&last->link, inode)) {
if (unlikely(unlazy_walk(nd, NULL, 0)))
return ERR_PTR(-ECHILD);
touch_atime(&last->link);
@@ -4369,12 +4369,9 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (error)
return error;
- if (!old_dir->i_op->rename && !old_dir->i_op->rename2)
+ if (!old_dir->i_op->rename)
return -EPERM;
- if (flags && !old_dir->i_op->rename2)
- return -EINVAL;
-
/*
* If we are going to change the parent - check write permissions,
* we'll need to flip '..'.
@@ -4428,14 +4425,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (error)
goto out;
}
- if (!old_dir->i_op->rename2) {
- error = old_dir->i_op->rename(old_dir, old_dentry,
- new_dir, new_dentry);
- } else {
- WARN_ON(old_dir->i_op->rename != NULL);
- error = old_dir->i_op->rename2(old_dir, old_dentry,
- new_dir, new_dentry, flags);
- }
+ error = old_dir->i_op->rename(old_dir, old_dentry,
+ new_dir, new_dentry, flags);
if (error)
goto out;
diff --git a/fs/namespace.c b/fs/namespace.c
index db1b5a38864e..58aca9c931ac 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2743,7 +2743,7 @@ long do_mount(const char *dev_name, const char __user *dir_name,
flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN |
MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
- MS_STRICTATIME);
+ MS_STRICTATIME | MS_NOREMOTELOCK);
if (flags & MS_REMOUNT)
retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 17de5c13dfae..6df2a3827574 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -36,7 +36,7 @@ static int ncp_unlink(struct inode *, struct dentry *);
static int ncp_mkdir(struct inode *, struct dentry *, umode_t);
static int ncp_rmdir(struct inode *, struct dentry *);
static int ncp_rename(struct inode *, struct dentry *,
- struct inode *, struct dentry *);
+ struct inode *, struct dentry *, unsigned int);
static int ncp_mknod(struct inode * dir, struct dentry *dentry,
umode_t mode, dev_t rdev);
#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
@@ -133,12 +133,11 @@ ncp_hash_dentry(const struct dentry *dentry, struct qstr *this)
return 0;
if (!ncp_case_sensitive(inode)) {
- struct super_block *sb = dentry->d_sb;
struct nls_table *t;
unsigned long hash;
int i;
- t = NCP_IO_TABLE(sb);
+ t = NCP_IO_TABLE(dentry->d_sb);
hash = init_name_hash(dentry);
for (i=0; i<this->len ; i++)
hash = partial_name_hash(ncp_tolower(t, this->name[i]),
@@ -1106,13 +1105,17 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry)
}
static int ncp_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 ncp_server *server = NCP_SERVER(old_dir);
int error;
int old_len, new_len;
__u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
+ if (flags)
+ return -EINVAL;
+
ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry);
ncp_age_dentry(server, old_dentry);
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 1af15fcbe57b..f6cf4c7e92b1 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -884,7 +884,7 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
/* ageing the dentry to force validation */
ncp_age_dentry(server, dentry);
- result = inode_change_ok(inode, attr);
+ result = setattr_prepare(dentry, attr);
if (result < 0)
goto out;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 177fefb26c18..06e0bf092ba9 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2013,7 +2013,8 @@ EXPORT_SYMBOL_GPL(nfs_link);
* the rename.
*/
int nfs_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 = d_inode(old_dentry);
struct inode *new_inode = d_inode(new_dentry);
@@ -2021,6 +2022,9 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct rpc_task *task;
int error = -EBUSY;
+ if (flags)
+ return -EINVAL;
+
dfprintk(VFS, "NFS: rename(%pd2 -> %pd2, ct=%d)\n",
old_dentry, new_dentry,
d_count(new_dentry));
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 4b308a1487a5..a6acce663219 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -359,7 +359,8 @@ int nfs_unlink(struct inode *, struct dentry *);
int nfs_symlink(struct inode *, struct dentry *, const char *);
int nfs_link(struct dentry *, struct inode *, struct dentry *);
int nfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
-int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
+int nfs_rename(struct inode *, struct dentry *,
+ struct inode *, struct dentry *, unsigned int);
/* file.c */
int nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 698be9361280..dc925b531f32 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -899,9 +899,6 @@ static const struct inode_operations nfs3_dir_inode_operations = {
.setattr = nfs_setattr,
#ifdef CONFIG_NFS_V3_ACL
.listxattr = nfs3_listxattr,
- .getxattr = generic_getxattr,
- .setxattr = generic_setxattr,
- .removexattr = generic_removexattr,
.get_acl = nfs3_get_acl,
.set_acl = nfs3_set_acl,
#endif
@@ -913,9 +910,6 @@ static const struct inode_operations nfs3_file_inode_operations = {
.setattr = nfs_setattr,
#ifdef CONFIG_NFS_V3_ACL
.listxattr = nfs3_listxattr,
- .getxattr = generic_getxattr,
- .setxattr = generic_setxattr,
- .removexattr = generic_removexattr,
.get_acl = nfs3_get_acl,
.set_acl = nfs3_set_acl,
#endif
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a9dec32ba9ba..0e327528a3ce 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -8941,20 +8941,14 @@ static const struct inode_operations nfs4_dir_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
- .getxattr = generic_getxattr,
- .setxattr = generic_setxattr,
.listxattr = nfs4_listxattr,
- .removexattr = generic_removexattr,
};
static const struct inode_operations nfs4_file_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
- .getxattr = generic_getxattr,
- .setxattr = generic_setxattr,
.listxattr = nfs4_listxattr,
- .removexattr = generic_removexattr,
};
const struct nfs_rpc_ops nfs_v4_clientops = {
diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c
index 5a1708441510..0780ff864539 100644
--- a/fs/nfsd/blocklayout.c
+++ b/fs/nfsd/blocklayout.c
@@ -123,7 +123,7 @@ nfsd4_block_commit_blocks(struct inode *inode, struct nfsd4_layoutcommit *lcp,
if (lcp->lc_mtime.tv_nsec == UTIME_NOW ||
timespec_compare(&lcp->lc_mtime, &inode->i_mtime) < 0)
- lcp->lc_mtime = current_fs_time(inode->i_sb);
+ lcp->lc_mtime = current_time(inode);
iattr.ia_valid |= ATTR_ATIME | ATTR_CTIME | ATTR_MTIME;
iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = lcp->lc_mtime;
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index e9214768cde9..08188743db53 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -74,10 +74,10 @@ nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
* which only requires access, and "set-[ac]time-to-X" which
* requires ownership.
* So if it looks like it might be "set both to the same time which
- * is close to now", and if inode_change_ok fails, then we
+ * is close to now", and if setattr_prepare fails, then we
* convert to "set to now" instead of "set to explicit time"
*
- * We only call inode_change_ok as the last test as technically
+ * We only call setattr_prepare as the last test as technically
* it is not an interface that we should be using.
*/
#define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET)
@@ -92,17 +92,15 @@ nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
* request is. We require it be within 30 minutes of now.
*/
time_t delta = iap->ia_atime.tv_sec - get_seconds();
- struct inode *inode;
nfserr = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
if (nfserr)
goto done;
- inode = d_inode(fhp->fh_dentry);
if (delta < 0)
delta = -delta;
if (delta < MAX_TOUCH_TIME_ERROR &&
- inode_change_ok(inode, iap) != 0) {
+ setattr_prepare(fhp->fh_dentry, iap) != 0) {
/*
* Turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME.
* This will cause notify_change to set these times
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 908ebbf0ac7e..582831ab3eb9 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -438,7 +438,7 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
nilfs_set_de_type(de, inode);
nilfs_commit_chunk(page, mapping, from, to);
nilfs_put_page(page);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
}
/*
@@ -528,7 +528,7 @@ got_it:
de->inode = cpu_to_le64(inode->i_ino);
nilfs_set_de_type(de, inode);
nilfs_commit_chunk(page, page->mapping, from, to);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
nilfs_mark_inode_dirty(dir);
/* OFFSET_CACHE */
out_put:
@@ -576,7 +576,7 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
pde->rec_len = nilfs_rec_len_to_disk(to - from);
dir->inode = 0;
nilfs_commit_chunk(page, mapping, from, to);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
out:
nilfs_put_page(page);
return err;
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index af04f553d7c9..c7f4fef9ebf5 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -367,7 +367,7 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t mode)
atomic64_inc(&root->inodes_count);
inode_init_owner(inode, dir, mode);
inode->i_ino = ino;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) {
err = nilfs_bmap_read(ii->i_bmap, NULL);
@@ -749,7 +749,7 @@ void nilfs_truncate(struct inode *inode)
nilfs_truncate_bmap(ii, blkoff);
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
if (IS_SYNC(inode))
nilfs_set_transaction_flag(NILFS_TI_SYNC);
@@ -829,7 +829,7 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr)
struct super_block *sb = inode->i_sb;
int err;
- err = inode_change_ok(inode, iattr);
+ err = setattr_prepare(dentry, iattr);
if (err)
return err;
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index f1d7989459fd..1d2c3d7711fe 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -174,7 +174,7 @@ static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
(flags & FS_FL_USER_MODIFIABLE);
nilfs_set_inode_flags(inode);
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
if (IS_SYNC(inode))
nilfs_set_transaction_flag(NILFS_TI_SYNC);
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index dbcf1dc93a51..2b71c60fe982 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -194,7 +194,7 @@ static int nilfs_link(struct dentry *old_dentry, struct inode *dir,
if (err)
return err;
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
inode_inc_link_count(inode);
ihold(inode);
@@ -350,7 +350,8 @@ static int nilfs_rmdir(struct inode *dir, struct dentry *dentry)
}
static int nilfs_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 = d_inode(old_dentry);
struct inode *new_inode = d_inode(new_dentry);
@@ -361,6 +362,9 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct nilfs_transaction_info ti;
int err;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
err = nilfs_transaction_begin(old_dir->i_sb, &ti, 1);
if (unlikely(err))
return err;
@@ -391,7 +395,7 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
goto out_dir;
nilfs_set_link(new_dir, new_de, new_page, old_inode);
nilfs_mark_inode_dirty(new_dir);
- new_inode->i_ctime = CURRENT_TIME;
+ new_inode->i_ctime = current_time(new_inode);
if (dir_de)
drop_nlink(new_inode);
drop_nlink(new_inode);
@@ -410,7 +414,7 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
* Like most other Unix systems, set the ctime for inodes on a
* rename.
*/
- old_inode->i_ctime = CURRENT_TIME;
+ old_inode->i_ctime = current_time(old_inode);
nilfs_delete_entry(old_de, old_page);
diff --git a/fs/nsfs.c b/fs/nsfs.c
index 30bb10034120..8718af895eab 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -78,7 +78,7 @@ slow:
return ERR_PTR(-ENOMEM);
}
inode->i_ino = ns->inum;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
inode->i_flags |= S_IMMUTABLE;
inode->i_mode = S_IFREG | S_IRUGO;
inode->i_fop = &ns_file_operations;
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index f548629dfaac..bf72a2c58b75 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -1850,7 +1850,7 @@ again:
* pages being swapped out between us bringing them into memory
* and doing the actual copying.
*/
- if (unlikely(iov_iter_fault_in_multipages_readable(i, bytes))) {
+ if (unlikely(iov_iter_fault_in_readable(i, bytes))) {
status = -EFAULT;
break;
}
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index e01287c964a8..7c410f879412 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -2813,7 +2813,7 @@ done:
* for real.
*/
if (!IS_NOCMTIME(VFS_I(base_ni)) && !IS_RDONLY(VFS_I(base_ni))) {
- struct timespec now = current_fs_time(VFS_I(base_ni)->i_sb);
+ struct timespec now = current_time(VFS_I(base_ni));
int sync_it = 0;
if (!timespec_equal(&VFS_I(base_ni)->i_mtime, &now) ||
@@ -2893,7 +2893,7 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
int err;
unsigned int ia_valid = attr->ia_valid;
- err = inode_change_ok(vi, attr);
+ err = setattr_prepare(dentry, attr);
if (err)
goto out;
/* We do not support NTFS ACLs yet. */
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index d15d492ce47b..d3c009626032 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -2692,7 +2692,7 @@ mft_rec_already_initialized:
/* Set the inode times to the current time. */
vi->i_atime = vi->i_mtime = vi->i_ctime =
- current_fs_time(vi->i_sb);
+ current_time(vi);
/*
* Set the file size to 0, the ntfs inode sizes are set to 0 by
* the call to ntfs_init_big_inode() below.
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index 2162434728c0..bed1fcb63088 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -201,7 +201,7 @@ static int ocfs2_acl_set_mode(struct inode *inode, struct buffer_head *di_bh,
}
inode->i_mode = new_mode;
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
di->i_mode = cpu_to_le16(inode->i_mode);
di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
@@ -241,13 +241,11 @@ int ocfs2_set_acl(handle_t *handle,
case ACL_TYPE_ACCESS:
name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
- umode_t mode = inode->i_mode;
- ret = posix_acl_equiv_mode(acl, &mode);
- if (ret < 0)
- return ret;
+ umode_t mode;
- if (ret == 0)
- acl = NULL;
+ ret = posix_acl_update_mode(inode, &mode, &acl);
+ if (ret)
+ return ret;
ret = ocfs2_acl_set_mode(inode, di_bh,
handle, mode);
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index f165f867f332..f72712f6c28d 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -7293,7 +7293,7 @@ int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh,
}
inode->i_blocks = ocfs2_inode_sector_count(inode);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
di->i_ctime = di->i_mtime = cpu_to_le64(inode->i_ctime.tv_sec);
di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index bbb4b3e5b4ff..c5c5b9748ea3 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -2030,7 +2030,7 @@ out_write_size:
}
inode->i_blocks = ocfs2_inode_sector_count(inode);
di->i_size = cpu_to_le64((u64)i_size_read(inode));
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec);
di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
ocfs2_update_inode_fsync_trans(handle, inode, 1);
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index e1adf285fc31..e7054e2ac922 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -1677,7 +1677,7 @@ int __ocfs2_add_entry(handle_t *handle,
offset, ocfs2_dir_trailer_blk_off(dir->i_sb));
if (ocfs2_dirent_would_fit(de, rec_len)) {
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
retval = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh);
if (retval < 0) {
mlog_errno(retval);
@@ -2990,7 +2990,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
ocfs2_dinode_new_extent_list(dir, di);
i_size_write(dir, sb->s_blocksize);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
di->i_size = cpu_to_le64(sb->s_blocksize);
di->i_ctime = di->i_mtime = cpu_to_le64(dir->i_ctime.tv_sec);
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 6ea06f8a7d29..3f828a187049 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -3188,6 +3188,9 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data,
migrate->new_master,
migrate->master);
+ if (ret < 0)
+ kmem_cache_free(dlm_mle_cache, mle);
+
spin_unlock(&dlm->master_lock);
unlock:
spin_unlock(&dlm->spinlock);
diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c
index 354cdf9714aa..1079fae5aa12 100644
--- a/fs/ocfs2/dlmfs/dlmfs.c
+++ b/fs/ocfs2/dlmfs/dlmfs.c
@@ -211,7 +211,7 @@ static int dlmfs_file_setattr(struct dentry *dentry, struct iattr *attr)
struct inode *inode = d_inode(dentry);
attr->ia_valid &= ~ATTR_SIZE;
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
if (error)
return error;
@@ -398,7 +398,7 @@ static struct inode *dlmfs_get_root_inode(struct super_block *sb)
if (inode) {
inode->i_ino = get_next_ino();
inode_init_owner(inode, NULL, mode);
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
inc_nlink(inode);
inode->i_fop = &simple_dir_operations;
@@ -421,7 +421,7 @@ static struct inode *dlmfs_get_inode(struct inode *parent,
inode->i_ino = get_next_ino();
inode_init_owner(inode, parent, mode);
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
ip = DLMFS_I(inode);
ip->ip_conn = DLMFS_I(parent)->ip_conn;
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 8f91639f8364..000c234d7bbd 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -253,7 +253,7 @@ int ocfs2_should_update_atime(struct inode *inode,
return 0;
}
- now = CURRENT_TIME;
+ now = current_time(inode);
if ((now.tv_sec - inode->i_atime.tv_sec <= osb->s_atime_quantum))
return 0;
else
@@ -287,7 +287,7 @@ int ocfs2_update_inode_atime(struct inode *inode,
* have i_mutex to guard against concurrent changes to other
* inode fields.
*/
- inode->i_atime = CURRENT_TIME;
+ inode->i_atime = current_time(inode);
di->i_atime = cpu_to_le64(inode->i_atime.tv_sec);
di->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);
ocfs2_update_inode_fsync_trans(handle, inode, 0);
@@ -308,7 +308,7 @@ int ocfs2_set_inode_size(handle_t *handle,
i_size_write(inode, new_i_size);
inode->i_blocks = ocfs2_inode_sector_count(inode);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);
if (status < 0) {
@@ -429,7 +429,7 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
}
i_size_write(inode, new_i_size);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
di = (struct ocfs2_dinode *) fe_bh->b_data;
di->i_size = cpu_to_le64(new_i_size);
@@ -840,7 +840,7 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
i_size_write(inode, abs_to);
inode->i_blocks = ocfs2_inode_sector_count(inode);
di->i_size = cpu_to_le64((u64)i_size_read(inode));
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec);
di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
di->i_mtime_nsec = di->i_ctime_nsec;
@@ -1155,7 +1155,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
if (!(attr->ia_valid & OCFS2_VALID_ATTRS))
return 0;
- status = inode_change_ok(inode, attr);
+ status = setattr_prepare(dentry, attr);
if (status)
return status;
@@ -1950,7 +1950,7 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode,
if (change_size && i_size_read(inode) < size)
i_size_write(inode, size);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
ret = ocfs2_mark_inode_dirty(handle, inode, di_bh);
if (ret < 0)
mlog_errno(ret);
@@ -2444,10 +2444,7 @@ const struct inode_operations ocfs2_file_iops = {
.setattr = ocfs2_setattr,
.getattr = ocfs2_getattr,
.permission = ocfs2_permission,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ocfs2_listxattr,
- .removexattr = generic_removexattr,
.fiemap = ocfs2_fiemap,
.get_acl = ocfs2_iop_get_acl,
.set_acl = ocfs2_iop_set_acl,
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c
index e3d05d9901a3..4e8f32eb0bdb 100644
--- a/fs/ocfs2/move_extents.c
+++ b/fs/ocfs2/move_extents.c
@@ -953,7 +953,7 @@ static int ocfs2_move_extents(struct ocfs2_move_extents_context *context)
}
di = (struct ocfs2_dinode *)di_bh->b_data;
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
ocfs2_update_inode_fsync_trans(handle, inode, 0);
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index a8f1225e6d9b..8d887c75765c 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -798,7 +798,7 @@ static int ocfs2_link(struct dentry *old_dentry,
}
inc_nlink(inode);
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
ocfs2_set_links_count(fe, inode->i_nlink);
fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
@@ -1000,7 +1000,7 @@ static int ocfs2_unlink(struct inode *dir,
ocfs2_set_links_count(fe, inode->i_nlink);
ocfs2_journal_dirty(handle, fe_bh);
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ dir->i_ctime = dir->i_mtime = current_time(dir);
if (S_ISDIR(inode->i_mode))
drop_nlink(dir);
@@ -1203,7 +1203,8 @@ static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2)
static int ocfs2_rename(struct inode *old_dir,
struct dentry *old_dentry,
struct inode *new_dir,
- struct dentry *new_dentry)
+ struct dentry *new_dentry,
+ unsigned int flags)
{
int status = 0, rename_lock = 0, parents_locked = 0, target_exists = 0;
int old_child_locked = 0, new_child_locked = 0, update_dot_dot = 0;
@@ -1228,6 +1229,9 @@ static int ocfs2_rename(struct inode *old_dir,
struct ocfs2_dir_lookup_result target_insert = { NULL, };
bool should_add_orphan = false;
+ if (flags)
+ return -EINVAL;
+
/* At some point it might be nice to break this function up a
* bit. */
@@ -1537,7 +1541,7 @@ static int ocfs2_rename(struct inode *old_dir,
new_dir_bh, &target_insert);
}
- old_inode->i_ctime = CURRENT_TIME;
+ old_inode->i_ctime = current_time(old_inode);
mark_inode_dirty(old_inode);
status = ocfs2_journal_access_di(handle, INODE_CACHE(old_inode),
@@ -1586,9 +1590,9 @@ static int ocfs2_rename(struct inode *old_dir,
if (new_inode) {
drop_nlink(new_inode);
- new_inode->i_ctime = CURRENT_TIME;
+ new_inode->i_ctime = current_time(new_inode);
}
- old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+ old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
if (update_dot_dot) {
status = ocfs2_update_entry(old_inode, handle,
@@ -2913,10 +2917,7 @@ const struct inode_operations ocfs2_dir_iops = {
.setattr = ocfs2_setattr,
.getattr = ocfs2_getattr,
.permission = ocfs2_permission,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ocfs2_listxattr,
- .removexattr = generic_removexattr,
.fiemap = ocfs2_fiemap,
.get_acl = ocfs2_iop_get_acl,
.set_acl = ocfs2_iop_set_acl,
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index 92bbe93bfe10..19238512a324 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -3778,7 +3778,7 @@ static int ocfs2_change_ctime(struct inode *inode,
goto out_commit;
}
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
@@ -4094,7 +4094,7 @@ static int ocfs2_complete_reflink(struct inode *s_inode,
* we want mtime to appear identical to the source and
* update ctime.
*/
- t_inode->i_ctime = CURRENT_TIME;
+ t_inode->i_ctime = current_time(t_inode);
di->i_ctime = cpu_to_le64(t_inode->i_ctime.tv_sec);
di->i_ctime_nsec = cpu_to_le32(t_inode->i_ctime.tv_nsec);
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index 6c2a3e3c521c..6ad8eecefe21 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -91,9 +91,6 @@ const struct inode_operations ocfs2_symlink_inode_operations = {
.get_link = page_get_link,
.getattr = ocfs2_getattr,
.setattr = ocfs2_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ocfs2_listxattr,
- .removexattr = generic_removexattr,
.fiemap = ocfs2_fiemap,
};
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 5bb44f7a78ee..cb157a34a656 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -3431,7 +3431,7 @@ static int __ocfs2_xattr_set_handle(struct inode *inode,
goto out;
}
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
ocfs2_journal_dirty(ctxt->handle, xis->inode_bh);
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c
index c8cbf3b60645..b7146526afff 100644
--- a/fs/omfs/dir.c
+++ b/fs/omfs/dir.c
@@ -143,7 +143,7 @@ static int omfs_add_link(struct dentry *dentry, struct inode *inode)
mark_buffer_dirty(bh);
brelse(bh);
- dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_ctime = current_time(dir);
/* mark affected inodes dirty to rebuild checksums */
mark_inode_dirty(dir);
@@ -371,12 +371,16 @@ static bool omfs_fill_chain(struct inode *dir, struct dir_context *ctx,
}
static int omfs_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 *new_inode = d_inode(new_dentry);
struct inode *old_inode = d_inode(old_dentry);
int err;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
if (new_inode) {
/* overwriting existing file/dir */
err = omfs_remove(new_dir, new_dentry);
@@ -395,7 +399,7 @@ static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (err)
goto out;
- old_inode->i_ctime = CURRENT_TIME_SEC;
+ old_inode->i_ctime = current_time(old_inode);
mark_inode_dirty(old_inode);
out:
return err;
diff --git a/fs/omfs/file.c b/fs/omfs/file.c
index d9e26cfbb793..bf83e6644333 100644
--- a/fs/omfs/file.c
+++ b/fs/omfs/file.c
@@ -349,7 +349,7 @@ static int omfs_setattr(struct dentry *dentry, struct iattr *attr)
struct inode *inode = d_inode(dentry);
int error;
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
if (error)
return error;
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c
index 3d935c81789a..df7ea8543a2e 100644
--- a/fs/omfs/inode.c
+++ b/fs/omfs/inode.c
@@ -49,7 +49,7 @@ struct inode *omfs_new_inode(struct inode *dir, umode_t mode)
inode_init_owner(inode, NULL, mode);
inode->i_mapping->a_ops = &omfs_aops;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
switch (mode & S_IFMT) {
case S_IFDIR:
inode->i_op = &omfs_dir_inops;
diff --git a/fs/open.c b/fs/open.c
index 4fd6e256f4f4..a7719cfb7257 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -68,6 +68,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
long vfs_truncate(const struct path *path, loff_t length)
{
struct inode *inode;
+ struct dentry *upperdentry;
long error;
inode = path->dentry->d_inode;
@@ -90,7 +91,17 @@ long vfs_truncate(const struct path *path, loff_t length)
if (IS_APPEND(inode))
goto mnt_drop_write_and_out;
- error = get_write_access(inode);
+ /*
+ * If this is an overlayfs then do as if opening the file so we get
+ * write access on the upper inode, not on the overlay inode. For
+ * non-overlay filesystems d_real() is an identity function.
+ */
+ upperdentry = d_real(path->dentry, NULL, O_WRONLY);
+ error = PTR_ERR(upperdentry);
+ if (IS_ERR(upperdentry))
+ goto mnt_drop_write_and_out;
+
+ error = get_write_access(upperdentry->d_inode);
if (error)
goto mnt_drop_write_and_out;
@@ -109,7 +120,7 @@ long vfs_truncate(const struct path *path, loff_t length)
error = do_truncate(path->dentry, length, 0, NULL);
put_write_and_out:
- put_write_access(inode);
+ put_write_access(upperdentry->d_inode);
mnt_drop_write_and_out:
mnt_drop_write(path->mnt);
out:
@@ -289,7 +300,8 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
* Let individual file system decide if it supports preallocation
* for directories or not.
*/
- if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
+ if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) &&
+ !S_ISBLK(inode->i_mode))
return -ENODEV;
/* Check for wrap through zero too */
@@ -726,7 +738,7 @@ static int do_dentry_open(struct file *f,
if (error)
goto cleanup_all;
- error = break_lease(inode, f->f_flags);
+ error = break_lease(locks_inode(f), f->f_flags);
if (error)
goto cleanup_all;
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index c7a86993d97e..c003a667ed1a 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -355,7 +355,7 @@ static struct inode *openprom_iget(struct super_block *sb, ino_t ino)
if (!inode)
return ERR_PTR(-ENOMEM);
if (inode->i_state & I_NEW) {
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
if (inode->i_ino == OPENPROM_ROOT_INO) {
inode->i_op = &openprom_inode_operations;
inode->i_fop = &openprom_operations;
diff --git a/fs/orangefs/acl.c b/fs/orangefs/acl.c
index 28f2195cd798..7a3754488312 100644
--- a/fs/orangefs/acl.c
+++ b/fs/orangefs/acl.c
@@ -73,14 +73,11 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
case ACL_TYPE_ACCESS:
name = XATTR_NAME_POSIX_ACL_ACCESS;
if (acl) {
- umode_t mode = inode->i_mode;
- /*
- * can we represent this with the traditional file
- * mode permission bits?
- */
- error = posix_acl_equiv_mode(acl, &mode);
- if (error < 0) {
- gossip_err("%s: posix_acl_equiv_mode err: %d\n",
+ umode_t mode;
+
+ error = posix_acl_update_mode(inode, &mode, &acl);
+ if (error) {
+ gossip_err("%s: posix_acl_update_mode err: %d\n",
__func__,
error);
return error;
@@ -90,8 +87,6 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
SetModeFlag(orangefs_inode);
inode->i_mode = mode;
mark_inode_dirty_sync(inode);
- if (error == 0)
- acl = NULL;
}
break;
case ACL_TYPE_DEFAULT:
diff --git a/fs/orangefs/dir.c b/fs/orangefs/dir.c
index 324f0af40d7b..284373a57a08 100644
--- a/fs/orangefs/dir.c
+++ b/fs/orangefs/dir.c
@@ -177,8 +177,8 @@ static int orangefs_readdir(struct file *file, struct dir_context *ctx)
}
gossip_debug(GOSSIP_DIR_DEBUG,
- "orangefs_readdir called on %s (pos=%llu)\n",
- dentry->d_name.name, llu(pos));
+ "orangefs_readdir called on %pd (pos=%llu)\n",
+ dentry, llu(pos));
memset(&readdir_response, 0, sizeof(readdir_response));
diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index 3386886596d6..66ea0cc37b18 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -384,7 +384,7 @@ out:
file_accessed(file);
} else {
SetMtimeFlag(orangefs_inode);
- inode->i_mtime = CURRENT_TIME;
+ inode->i_mtime = current_time(inode);
mark_inode_dirty_sync(inode);
}
}
@@ -611,8 +611,8 @@ static int orangefs_file_mmap(struct file *file, struct vm_area_struct *vma)
static int orangefs_file_release(struct inode *inode, struct file *file)
{
gossip_debug(GOSSIP_FILE_DEBUG,
- "orangefs_file_release: called on %s\n",
- file->f_path.dentry->d_name.name);
+ "orangefs_file_release: called on %pD\n",
+ file);
orangefs_flush_inode(inode);
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index 28a0557a69be..ef3b4eb54cf2 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -129,8 +129,8 @@ static ssize_t orangefs_direct_IO(struct kiocb *iocb,
struct iov_iter *iter)
{
gossip_debug(GOSSIP_INODE_DEBUG,
- "orangefs_direct_IO: %s\n",
- iocb->ki_filp->f_path.dentry->d_name.name);
+ "orangefs_direct_IO: %pD\n",
+ iocb->ki_filp);
return -EINVAL;
}
@@ -216,10 +216,10 @@ int orangefs_setattr(struct dentry *dentry, struct iattr *iattr)
struct inode *inode = dentry->d_inode;
gossip_debug(GOSSIP_INODE_DEBUG,
- "orangefs_setattr: called on %s\n",
- dentry->d_name.name);
+ "orangefs_setattr: called on %pd\n",
+ dentry);
- ret = inode_change_ok(inode, iattr);
+ ret = setattr_prepare(dentry, iattr);
if (ret)
goto out;
@@ -259,8 +259,8 @@ int orangefs_getattr(struct vfsmount *mnt,
struct orangefs_inode_s *orangefs_inode = NULL;
gossip_debug(GOSSIP_INODE_DEBUG,
- "orangefs_getattr: called on %s\n",
- dentry->d_name.name);
+ "orangefs_getattr: called on %pd\n",
+ dentry);
ret = orangefs_inode_getattr(inode, 0, 0);
if (ret == 0) {
@@ -296,10 +296,7 @@ const struct inode_operations orangefs_file_inode_operations = {
.set_acl = orangefs_set_acl,
.setattr = orangefs_setattr,
.getattr = orangefs_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = orangefs_listxattr,
- .removexattr = generic_removexattr,
.permission = orangefs_permission,
};
@@ -438,7 +435,7 @@ struct inode *orangefs_new_inode(struct super_block *sb, struct inode *dir,
inode->i_mode = mode;
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
- 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_size = PAGE_SIZE;
inode->i_rdev = dev;
diff --git a/fs/orangefs/namei.c b/fs/orangefs/namei.c
index 35269e31de92..d15d3d2dba62 100644
--- a/fs/orangefs/namei.c
+++ b/fs/orangefs/namei.c
@@ -24,9 +24,9 @@ static int orangefs_create(struct inode *dir,
struct inode *inode;
int ret;
- gossip_debug(GOSSIP_NAME_DEBUG, "%s: %s\n",
+ gossip_debug(GOSSIP_NAME_DEBUG, "%s: %pd\n",
__func__,
- dentry->d_name.name);
+ dentry);
new_op = op_alloc(ORANGEFS_VFS_OP_CREATE);
if (!new_op)
@@ -43,9 +43,9 @@ static int orangefs_create(struct inode *dir,
ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
gossip_debug(GOSSIP_NAME_DEBUG,
- "%s: %s: handle:%pU: fsid:%d: new_op:%p: ret:%d:\n",
+ "%s: %pd: handle:%pU: fsid:%d: new_op:%p: ret:%d:\n",
__func__,
- dentry->d_name.name,
+ dentry,
&new_op->downcall.resp.create.refn.khandle,
new_op->downcall.resp.create.refn.fs_id,
new_op,
@@ -57,18 +57,18 @@ static int orangefs_create(struct inode *dir,
inode = orangefs_new_inode(dir->i_sb, dir, S_IFREG | mode, 0,
&new_op->downcall.resp.create.refn);
if (IS_ERR(inode)) {
- gossip_err("%s: Failed to allocate inode for file :%s:\n",
+ gossip_err("%s: Failed to allocate inode for file :%pd:\n",
__func__,
- dentry->d_name.name);
+ dentry);
ret = PTR_ERR(inode);
goto out;
}
gossip_debug(GOSSIP_NAME_DEBUG,
- "%s: Assigned inode :%pU: for file :%s:\n",
+ "%s: Assigned inode :%pU: for file :%pd:\n",
__func__,
get_khandle_from_ino(inode),
- dentry->d_name.name);
+ dentry);
d_instantiate(dentry, inode);
unlock_new_inode(inode);
@@ -76,20 +76,20 @@ static int orangefs_create(struct inode *dir,
ORANGEFS_I(inode)->getattr_time = jiffies - 1;
gossip_debug(GOSSIP_NAME_DEBUG,
- "%s: dentry instantiated for %s\n",
+ "%s: dentry instantiated for %pd\n",
__func__,
- dentry->d_name.name);
+ dentry);
SetMtimeFlag(parent);
- dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty_sync(dir);
ret = 0;
out:
op_release(new_op);
gossip_debug(GOSSIP_NAME_DEBUG,
- "%s: %s: returning %d\n",
+ "%s: %pd: returning %d\n",
__func__,
- dentry->d_name.name,
+ dentry,
ret);
return ret;
}
@@ -115,8 +115,8 @@ static struct dentry *orangefs_lookup(struct inode *dir, struct dentry *dentry,
* -EEXIST on O_EXCL opens, which is broken if we skip this lookup
* in the create path)
*/
- gossip_debug(GOSSIP_NAME_DEBUG, "%s called on %s\n",
- __func__, dentry->d_name.name);
+ gossip_debug(GOSSIP_NAME_DEBUG, "%s called on %pd\n",
+ __func__, dentry);
if (dentry->d_name.len > (ORANGEFS_NAME_MAX - 1))
return ERR_PTR(-ENAMETOOLONG);
@@ -169,9 +169,9 @@ static struct dentry *orangefs_lookup(struct inode *dir, struct dentry *dentry,
gossip_debug(GOSSIP_NAME_DEBUG,
"orangefs_lookup: Adding *negative* dentry "
- "%p for %s\n",
+ "%p for %pd\n",
dentry,
- dentry->d_name.name);
+ dentry);
d_add(dentry, NULL);
res = NULL;
@@ -224,10 +224,10 @@ static int orangefs_unlink(struct inode *dir, struct dentry *dentry)
int ret;
gossip_debug(GOSSIP_NAME_DEBUG,
- "%s: called on %s\n"
+ "%s: called on %pd\n"
" (inode %pU): Parent is %pU | fs_id %d\n",
__func__,
- dentry->d_name.name,
+ dentry,
get_khandle_from_ino(inode),
&parent->refn.khandle,
parent->refn.fs_id);
@@ -254,7 +254,7 @@ static int orangefs_unlink(struct inode *dir, struct dentry *dentry)
drop_nlink(inode);
SetMtimeFlag(parent);
- dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty_sync(dir);
}
return ret;
@@ -326,12 +326,12 @@ static int orangefs_symlink(struct inode *dir,
ORANGEFS_I(inode)->getattr_time = jiffies - 1;
gossip_debug(GOSSIP_NAME_DEBUG,
- "Inode (Symlink) %pU -> %s\n",
+ "Inode (Symlink) %pU -> %pd\n",
get_khandle_from_ino(inode),
- dentry->d_name.name);
+ dentry);
SetMtimeFlag(parent);
- dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty_sync(dir);
ret = 0;
out:
@@ -390,16 +390,16 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
ORANGEFS_I(inode)->getattr_time = jiffies - 1;
gossip_debug(GOSSIP_NAME_DEBUG,
- "Inode (Directory) %pU -> %s\n",
+ "Inode (Directory) %pU -> %pd\n",
get_khandle_from_ino(inode),
- dentry->d_name.name);
+ dentry);
/*
* NOTE: we have no good way to keep nlink consistent for directories
* across clients; keep constant at 1.
*/
SetMtimeFlag(parent);
- dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty_sync(dir);
out:
op_release(new_op);
@@ -409,11 +409,15 @@ out:
static int orangefs_rename(struct inode *old_dir,
struct dentry *old_dentry,
struct inode *new_dir,
- struct dentry *new_dentry)
+ struct dentry *new_dentry,
+ unsigned int flags)
{
struct orangefs_kernel_op_s *new_op;
int ret;
+ if (flags)
+ return -EINVAL;
+
gossip_debug(GOSSIP_NAME_DEBUG,
"orangefs_rename: called (%pd2 => %pd2) ct=%d\n",
old_dentry, new_dentry, d_count(new_dentry));
@@ -443,7 +447,7 @@ static int orangefs_rename(struct inode *old_dir,
ret);
if (new_dentry->d_inode)
- new_dentry->d_inode->i_ctime = CURRENT_TIME;
+ new_dentry->d_inode->i_ctime = current_time(new_dentry->d_inode);
op_release(new_op);
return ret;
@@ -462,9 +466,6 @@ const struct inode_operations orangefs_dir_inode_operations = {
.rename = orangefs_rename,
.setattr = orangefs_setattr,
.getattr = orangefs_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .removexattr = generic_removexattr,
.listxattr = orangefs_listxattr,
.permission = orangefs_permission,
};
diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c
index 9b24107c82a8..eb09aa026723 100644
--- a/fs/orangefs/orangefs-debugfs.c
+++ b/fs/orangefs/orangefs-debugfs.c
@@ -428,8 +428,8 @@ static ssize_t orangefs_debug_write(struct file *file,
struct client_debug_mask c_mask = { NULL, 0, 0 };
gossip_debug(GOSSIP_DEBUGFS_DEBUG,
- "orangefs_debug_write: %s\n",
- file->f_path.dentry->d_name.name);
+ "orangefs_debug_write: %pD\n",
+ file);
/*
* Thwart users who try to jamb a ridiculous number
diff --git a/fs/orangefs/symlink.c b/fs/orangefs/symlink.c
index 8fecf823f5ba..10b0b06e075e 100644
--- a/fs/orangefs/symlink.c
+++ b/fs/orangefs/symlink.c
@@ -14,6 +14,5 @@ const struct inode_operations orangefs_symlink_inode_operations = {
.setattr = orangefs_setattr,
.getattr = orangefs_getattr,
.listxattr = orangefs_listxattr,
- .setxattr = generic_setxattr,
.permission = orangefs_permission,
};
diff --git a/fs/orangefs/xattr.c b/fs/orangefs/xattr.c
index 2a9f07f06d10..74a81b1daaac 100644
--- a/fs/orangefs/xattr.c
+++ b/fs/orangefs/xattr.c
@@ -73,6 +73,9 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
"%s: name %s, buffer_size %zd\n",
__func__, name, size);
+ if (S_ISLNK(inode->i_mode))
+ return -EOPNOTSUPP;
+
if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) {
gossip_err("Invalid key length (%d)\n",
(int)strlen(name));
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index db37a0e02d32..3f803b3a1f82 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -58,8 +58,8 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
char *buf, *name, *value = NULL;
int uninitialized_var(error);
- if (!old->d_inode->i_op->getxattr ||
- !new->d_inode->i_op->getxattr)
+ if (!(old->d_inode->i_opflags & IOP_XATTR) ||
+ !(new->d_inode->i_opflags & IOP_XATTR))
return 0;
list_size = vfs_listxattr(old, NULL, 0);
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index b0ffa1d1677e..5f90ddf778ba 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -1006,17 +1006,14 @@ const struct inode_operations ovl_dir_inode_operations = {
.symlink = ovl_symlink,
.unlink = ovl_unlink,
.rmdir = ovl_rmdir,
- .rename2 = ovl_rename2,
+ .rename = ovl_rename2,
.link = ovl_link,
.setattr = ovl_setattr,
.create = ovl_create,
.mknod = ovl_mknod,
.permission = ovl_permission,
.getattr = ovl_dir_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ovl_listxattr,
- .removexattr = generic_removexattr,
.get_acl = ovl_get_acl,
.update_time = ovl_update_time,
};
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index c75625c1efa3..c18d6a4ff456 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -53,7 +53,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
* inode_newsize_ok() will always check against MAX_LFS_FILESIZE and not
* check for a swapfile (which this won't be anyway).
*/
- err = inode_change_ok(dentry->d_inode, attr);
+ err = setattr_prepare(dentry, attr);
if (err)
return err;
@@ -367,10 +367,7 @@ static const struct inode_operations ovl_file_inode_operations = {
.setattr = ovl_setattr,
.permission = ovl_permission,
.getattr = ovl_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ovl_listxattr,
- .removexattr = generic_removexattr,
.get_acl = ovl_get_acl,
.update_time = ovl_update_time,
};
@@ -380,10 +377,7 @@ static const struct inode_operations ovl_symlink_inode_operations = {
.get_link = ovl_get_link,
.readlink = ovl_readlink,
.getattr = ovl_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ovl_listxattr,
- .removexattr = generic_removexattr,
.update_time = ovl_update_time,
};
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 5813ccff8cd9..e218e741cb99 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -114,13 +114,13 @@ static inline int ovl_do_rename(struct inode *olddir, struct dentry *olddentry,
{
int err;
- pr_debug("rename2(%pd2, %pd2, 0x%x)\n",
+ pr_debug("rename(%pd2, %pd2, 0x%x)\n",
olddentry, newdentry, flags);
err = vfs_rename(olddir, olddentry, newdir, newdentry, NULL, flags);
if (err) {
- pr_debug("...rename2(%pd2, %pd2, ...) = %i\n",
+ pr_debug("...rename(%pd2, %pd2, ...) = %i\n",
olddentry, newdentry, err);
}
return err;
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index e2a94a26767b..7e3f0127fc1a 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -275,10 +275,10 @@ static bool ovl_is_opaquedir(struct dentry *dentry)
char val;
struct inode *inode = dentry->d_inode;
- if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr)
+ if (!S_ISDIR(inode->i_mode) || !(inode->i_opflags & IOP_XATTR))
return false;
- res = inode->i_op->getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
+ res = __vfs_getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
if (res == 1 && val == 'y')
return true;
@@ -1320,7 +1320,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
sb->s_xattr = ovl_xattr_handlers;
sb->s_root = root_dentry;
sb->s_fs_info = ufs;
- sb->s_flags |= MS_POSIXACL;
+ sb->s_flags |= MS_POSIXACL | MS_NOREMOTELOCK;
return 0;
diff --git a/fs/pipe.c b/fs/pipe.c
index 4fc422f0dea8..8e0d9f26dfad 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -601,54 +601,63 @@ pipe_fasync(int fd, struct file *filp, int on)
return retval;
}
-static void account_pipe_buffers(struct pipe_inode_info *pipe,
+static unsigned long account_pipe_buffers(struct user_struct *user,
unsigned long old, unsigned long new)
{
- atomic_long_add(new - old, &pipe->user->pipe_bufs);
+ return atomic_long_add_return(new - old, &user->pipe_bufs);
}
-static bool too_many_pipe_buffers_soft(struct user_struct *user)
+static bool too_many_pipe_buffers_soft(unsigned long user_bufs)
{
- return pipe_user_pages_soft &&
- atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_soft;
+ return pipe_user_pages_soft && user_bufs >= pipe_user_pages_soft;
}
-static bool too_many_pipe_buffers_hard(struct user_struct *user)
+static bool too_many_pipe_buffers_hard(unsigned long user_bufs)
{
- return pipe_user_pages_hard &&
- atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_hard;
+ return pipe_user_pages_hard && user_bufs >= pipe_user_pages_hard;
}
struct pipe_inode_info *alloc_pipe_info(void)
{
struct pipe_inode_info *pipe;
+ unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
+ struct user_struct *user = get_current_user();
+ unsigned long user_bufs;
pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL_ACCOUNT);
- if (pipe) {
- unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
- struct user_struct *user = get_current_user();
-
- if (!too_many_pipe_buffers_hard(user)) {
- if (too_many_pipe_buffers_soft(user))
- pipe_bufs = 1;
- pipe->bufs = kcalloc(pipe_bufs,
- sizeof(struct pipe_buffer),
- GFP_KERNEL_ACCOUNT);
- }
+ if (pipe == NULL)
+ goto out_free_uid;
- if (pipe->bufs) {
- init_waitqueue_head(&pipe->wait);
- pipe->r_counter = pipe->w_counter = 1;
- pipe->buffers = pipe_bufs;
- pipe->user = user;
- account_pipe_buffers(pipe, 0, pipe_bufs);
- mutex_init(&pipe->mutex);
- return pipe;
- }
- free_uid(user);
- kfree(pipe);
+ if (pipe_bufs * PAGE_SIZE > pipe_max_size && !capable(CAP_SYS_RESOURCE))
+ pipe_bufs = pipe_max_size >> PAGE_SHIFT;
+
+ user_bufs = account_pipe_buffers(user, 0, pipe_bufs);
+
+ if (too_many_pipe_buffers_soft(user_bufs)) {
+ user_bufs = account_pipe_buffers(user, pipe_bufs, 1);
+ pipe_bufs = 1;
+ }
+
+ if (too_many_pipe_buffers_hard(user_bufs))
+ goto out_revert_acct;
+
+ pipe->bufs = kcalloc(pipe_bufs, sizeof(struct pipe_buffer),
+ GFP_KERNEL_ACCOUNT);
+
+ if (pipe->bufs) {
+ init_waitqueue_head(&pipe->wait);
+ pipe->r_counter = pipe->w_counter = 1;
+ pipe->buffers = pipe_bufs;
+ pipe->user = user;
+ mutex_init(&pipe->mutex);
+ return pipe;
}
+out_revert_acct:
+ (void) account_pipe_buffers(user, pipe_bufs, 0);
+ kfree(pipe);
+out_free_uid:
+ free_uid(user);
return NULL;
}
@@ -656,7 +665,7 @@ void free_pipe_info(struct pipe_inode_info *pipe)
{
int i;
- account_pipe_buffers(pipe, pipe->buffers, 0);
+ (void) account_pipe_buffers(pipe->user, pipe->buffers, 0);
free_uid(pipe->user);
for (i = 0; i < pipe->buffers; i++) {
struct pipe_buffer *buf = pipe->bufs + i;
@@ -713,7 +722,7 @@ static struct inode * get_pipe_inode(void)
inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR;
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
return inode;
@@ -1008,12 +1017,54 @@ const struct file_operations pipefifo_fops = {
};
/*
+ * Currently we rely on the pipe array holding a power-of-2 number
+ * of pages.
+ */
+static inline unsigned int round_pipe_size(unsigned int size)
+{
+ unsigned long nr_pages;
+
+ nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ return roundup_pow_of_two(nr_pages) << PAGE_SHIFT;
+}
+
+/*
* Allocate a new array of pipe buffers and copy the info over. Returns the
* pipe size if successful, or return -ERROR on error.
*/
-static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages)
+static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
{
struct pipe_buffer *bufs;
+ unsigned int size, nr_pages;
+ unsigned long user_bufs;
+ long ret = 0;
+
+ size = round_pipe_size(arg);
+ nr_pages = size >> PAGE_SHIFT;
+
+ if (!nr_pages)
+ return -EINVAL;
+
+ /*
+ * If trying to increase the pipe capacity, check that an
+ * unprivileged user is not trying to exceed various limits
+ * (soft limit check here, hard limit check just below).
+ * Decreasing the pipe capacity is always permitted, even
+ * if the user is currently over a limit.
+ */
+ if (nr_pages > pipe->buffers &&
+ size > pipe_max_size && !capable(CAP_SYS_RESOURCE))
+ return -EPERM;
+
+ user_bufs = account_pipe_buffers(pipe->user, pipe->buffers, nr_pages);
+
+ if (nr_pages > pipe->buffers &&
+ (too_many_pipe_buffers_hard(user_bufs) ||
+ too_many_pipe_buffers_soft(user_bufs)) &&
+ !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) {
+ ret = -EPERM;
+ goto out_revert_acct;
+ }
/*
* We can shrink the pipe, if arg >= pipe->nrbufs. Since we don't
@@ -1021,13 +1072,17 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages)
* again like we would do for growing. If the pipe currently
* contains more buffers than arg, then return busy.
*/
- if (nr_pages < pipe->nrbufs)
- return -EBUSY;
+ if (nr_pages < pipe->nrbufs) {
+ ret = -EBUSY;
+ goto out_revert_acct;
+ }
bufs = kcalloc(nr_pages, sizeof(*bufs),
GFP_KERNEL_ACCOUNT | __GFP_NOWARN);
- if (unlikely(!bufs))
- return -ENOMEM;
+ if (unlikely(!bufs)) {
+ ret = -ENOMEM;
+ goto out_revert_acct;
+ }
/*
* The pipe array wraps around, so just start the new one at zero
@@ -1050,24 +1105,15 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages)
memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer));
}
- account_pipe_buffers(pipe, pipe->buffers, nr_pages);
pipe->curbuf = 0;
kfree(pipe->bufs);
pipe->bufs = bufs;
pipe->buffers = nr_pages;
return nr_pages * PAGE_SIZE;
-}
-
-/*
- * Currently we rely on the pipe array holding a power-of-2 number
- * of pages.
- */
-static inline unsigned int round_pipe_size(unsigned int size)
-{
- unsigned long nr_pages;
- nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
- return roundup_pow_of_two(nr_pages) << PAGE_SHIFT;
+out_revert_acct:
+ (void) account_pipe_buffers(pipe->user, nr_pages, pipe->buffers);
+ return ret;
}
/*
@@ -1109,28 +1155,9 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
__pipe_lock(pipe);
switch (cmd) {
- case F_SETPIPE_SZ: {
- unsigned int size, nr_pages;
-
- size = round_pipe_size(arg);
- nr_pages = size >> PAGE_SHIFT;
-
- ret = -EINVAL;
- if (!nr_pages)
- goto out;
-
- if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
- ret = -EPERM;
- goto out;
- } else if ((too_many_pipe_buffers_hard(pipe->user) ||
- too_many_pipe_buffers_soft(pipe->user)) &&
- !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) {
- ret = -EPERM;
- goto out;
- }
- ret = pipe_set_size(pipe, nr_pages);
+ case F_SETPIPE_SZ:
+ ret = pipe_set_size(pipe, arg);
break;
- }
case F_GETPIPE_SZ:
ret = pipe->buffers * PAGE_SIZE;
break;
@@ -1139,7 +1166,6 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
break;
}
-out:
__pipe_unlock(pipe);
return ret;
}
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 59d47ab0791a..595522022aca 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -598,13 +598,14 @@ posix_acl_create(struct inode *dir, umode_t *mode,
if (IS_ERR(p))
return PTR_ERR(p);
+ ret = -ENOMEM;
clone = posix_acl_clone(p, GFP_NOFS);
if (!clone)
- goto no_mem;
+ goto err_release;
ret = posix_acl_create_masq(clone, mode);
if (ret < 0)
- goto no_mem_clone;
+ goto err_release_clone;
if (ret == 0)
posix_acl_release(clone);
@@ -618,14 +619,45 @@ posix_acl_create(struct inode *dir, umode_t *mode,
return 0;
-no_mem_clone:
+err_release_clone:
posix_acl_release(clone);
-no_mem:
+err_release:
posix_acl_release(p);
- return -ENOMEM;
+ return ret;
}
EXPORT_SYMBOL_GPL(posix_acl_create);
+/**
+ * posix_acl_update_mode - update mode in set_acl
+ *
+ * Update the file mode when setting an ACL: compute the new file permission
+ * bits based on the ACL. In addition, if the ACL is equivalent to the new
+ * file mode, set *acl to NULL to indicate that no ACL should be set.
+ *
+ * As with chmod, clear the setgit bit if the caller is not in the owning group
+ * or capable of CAP_FSETID (see inode_change_ok).
+ *
+ * Called from set_acl inode operations.
+ */
+int posix_acl_update_mode(struct inode *inode, umode_t *mode_p,
+ struct posix_acl **acl)
+{
+ umode_t mode = inode->i_mode;
+ int error;
+
+ error = posix_acl_equiv_mode(*acl, &mode);
+ if (error < 0)
+ return error;
+ if (error == 0)
+ *acl = NULL;
+ if (!in_group_p(inode->i_gid) &&
+ !capable_wrt_inode_uidgid(inode, CAP_FSETID))
+ mode &= ~S_ISGID;
+ *mode_p = mode;
+ return 0;
+}
+EXPORT_SYMBOL(posix_acl_update_mode);
+
/*
* Fix up the uids and gids in posix acl extended attributes in place.
*/
@@ -633,15 +665,15 @@ static void posix_acl_fix_xattr_userns(
struct user_namespace *to, struct user_namespace *from,
void *value, size_t size)
{
- posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
- posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
+ struct posix_acl_xattr_header *header = value;
+ struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
int count;
kuid_t uid;
kgid_t gid;
if (!value)
return;
- if (size < sizeof(posix_acl_xattr_header))
+ if (size < sizeof(struct posix_acl_xattr_header))
return;
if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
return;
@@ -691,15 +723,15 @@ struct posix_acl *
posix_acl_from_xattr(struct user_namespace *user_ns,
const void *value, size_t size)
{
- posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
- posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
+ const struct posix_acl_xattr_header *header = value;
+ const struct posix_acl_xattr_entry *entry = (const void *)(header + 1), *end;
int count;
struct posix_acl *acl;
struct posix_acl_entry *acl_e;
if (!value)
return NULL;
- if (size < sizeof(posix_acl_xattr_header))
+ if (size < sizeof(struct posix_acl_xattr_header))
return ERR_PTR(-EINVAL);
if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
return ERR_PTR(-EOPNOTSUPP);
@@ -760,8 +792,8 @@ int
posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
void *buffer, size_t size)
{
- posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer;
- posix_acl_xattr_entry *ext_entry;
+ struct posix_acl_xattr_header *ext_acl = buffer;
+ struct posix_acl_xattr_entry *ext_entry;
int real_size, n;
real_size = posix_acl_xattr_size(acl->a_count);
@@ -770,7 +802,7 @@ posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
if (real_size > size)
return -ERANGE;
- ext_entry = ext_acl->a_entries;
+ ext_entry = (void *)(ext_acl + 1);
ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
for (n=0; n < acl->a_count; n++, ext_entry++) {
@@ -897,7 +929,7 @@ int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type)
acl = NULL;
}
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = current_time(inode);
set_cached_acl(inode, type, acl);
return 0;
}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index dc7fe5f3a53c..c2964d890c9a 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -400,23 +400,6 @@ static const struct file_operations proc_pid_cmdline_ops = {
.llseek = generic_file_llseek,
};
-static int proc_pid_auxv(struct seq_file *m, struct pid_namespace *ns,
- struct pid *pid, struct task_struct *task)
-{
- struct mm_struct *mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
- if (mm && !IS_ERR(mm)) {
- unsigned int nwords = 0;
- do {
- nwords += 2;
- } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
- seq_write(m, mm->saved_auxv, nwords * sizeof(mm->saved_auxv[0]));
- mmput(mm);
- return 0;
- } else
- return PTR_ERR(mm);
-}
-
-
#ifdef CONFIG_KALLSYMS
/*
* Provides a wchan file via kallsyms in a proper one-value-per-file format.
@@ -709,7 +692,7 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr)
if (attr->ia_valid & ATTR_MODE)
return -EPERM;
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
if (error)
return error;
@@ -1014,6 +997,30 @@ static const struct file_operations proc_environ_operations = {
.release = mem_release,
};
+static int auxv_open(struct inode *inode, struct file *file)
+{
+ return __mem_open(inode, file, PTRACE_MODE_READ_FSCREDS);
+}
+
+static ssize_t auxv_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct mm_struct *mm = file->private_data;
+ unsigned int nwords = 0;
+ do {
+ nwords += 2;
+ } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
+ return simple_read_from_buffer(buf, count, ppos, mm->saved_auxv,
+ nwords * sizeof(mm->saved_auxv[0]));
+}
+
+static const struct file_operations proc_auxv_operations = {
+ .open = auxv_open,
+ .read = auxv_read,
+ .llseek = generic_file_llseek,
+ .release = mem_release,
+};
+
static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
@@ -1664,7 +1671,7 @@ struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *t
/* Common stuff */
ei = PROC_I(inode);
inode->i_ino = get_next_ino();
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
inode->i_op = &proc_def_inode_operations;
/*
@@ -2842,7 +2849,7 @@ static const struct pid_entry tgid_base_stuff[] = {
DIR("net", S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations),
#endif
REG("environ", S_IRUSR, proc_environ_operations),
- ONE("auxv", S_IRUSR, proc_pid_auxv),
+ REG("auxv", S_IRUSR, proc_auxv_operations),
ONE("status", S_IRUGO, proc_pid_status),
ONE("personality", S_IRUSR, proc_pid_personality),
ONE("limits", S_IRUGO, proc_pid_limits),
@@ -3230,7 +3237,7 @@ static const struct pid_entry tid_base_stuff[] = {
DIR("net", S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations),
#endif
REG("environ", S_IRUSR, proc_environ_operations),
- ONE("auxv", S_IRUSR, proc_pid_auxv),
+ REG("auxv", S_IRUSR, proc_auxv_operations),
ONE("status", S_IRUGO, proc_pid_status),
ONE("personality", S_IRUSR, proc_pid_personality),
ONE("limits", S_IRUGO, proc_pid_limits),
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index 01df23cc81f6..d21dafef3102 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -31,7 +31,7 @@ static int seq_show(struct seq_file *m, void *v)
put_task_struct(task);
if (files) {
- int fd = proc_fd(m->private);
+ unsigned int fd = proc_fd(m->private);
spin_lock(&files->file_lock);
file = fcheck_files(files, fd);
@@ -86,7 +86,7 @@ static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
struct task_struct *task;
const struct cred *cred;
struct inode *inode;
- int fd;
+ unsigned int fd;
if (flags & LOOKUP_RCU)
return -ECHILD;
@@ -158,7 +158,7 @@ static int proc_fd_link(struct dentry *dentry, struct path *path)
}
if (files) {
- int fd = proc_fd(d_inode(dentry));
+ unsigned int fd = proc_fd(d_inode(dentry));
struct file *fd_file;
spin_lock(&files->file_lock);
@@ -253,7 +253,7 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx,
continue;
rcu_read_unlock();
- len = snprintf(name, sizeof(name), "%d", fd);
+ len = snprintf(name, sizeof(name), "%u", fd);
if (!proc_fill_cache(file, ctx,
name, len, instantiate, p,
(void *)(unsigned long)fd))
diff --git a/fs/proc/fd.h b/fs/proc/fd.h
index 7c047f256ae2..46dafadd0083 100644
--- a/fs/proc/fd.h
+++ b/fs/proc/fd.h
@@ -11,7 +11,7 @@ extern const struct inode_operations proc_fdinfo_inode_operations;
extern int proc_fd_permission(struct inode *inode, int mask);
-static inline int proc_fd(struct inode *inode)
+static inline unsigned int proc_fd(struct inode *inode)
{
return PROC_I(inode)->fd;
}
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index bca66d83a765..5f2dc2032c79 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -105,7 +105,7 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
struct proc_dir_entry *de = PDE(inode);
int error;
- error = inode_change_ok(inode, iattr);
+ error = setattr_prepare(dentry, iattr);
if (error)
return error;
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index c1b72388e571..e69ebe648a34 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -68,7 +68,6 @@ static struct inode *proc_alloc_inode(struct super_block *sb)
ei->sysctl_entry = NULL;
ei->ns_ops = NULL;
inode = &ei->vfs_inode;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
return inode;
}
@@ -421,7 +420,7 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
if (inode) {
inode->i_ino = de->low_ino;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
PROC_I(inode)->pde = de;
if (is_empty_pde(de)) {
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 7931c558c192..5378441ec1b7 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -60,7 +60,7 @@ union proc_op {
struct proc_inode {
struct pid *pid;
- int fd;
+ unsigned int fd;
union proc_op op;
struct proc_dir_entry *pde;
struct ctl_table_header *sysctl;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 71025b9e2a4e..55313d994895 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -445,7 +445,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
ei->sysctl = head;
ei->sysctl_entry = table;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
inode->i_mode = table->mode;
if (!S_ISDIR(table->mode)) {
inode->i_mode |= S_IFREG;
@@ -759,7 +759,7 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
return -EPERM;
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
if (error)
return error;
diff --git a/fs/proc/self.c b/fs/proc/self.c
index b6a8d3529fea..40245954c450 100644
--- a/fs/proc/self.c
+++ b/fs/proc/self.c
@@ -56,7 +56,7 @@ int proc_setup_self(struct super_block *s)
struct inode *inode = new_inode_pseudo(s);
if (inode) {
inode->i_ino = self_inum;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
inode->i_mode = S_IFLNK | S_IRWXUGO;
inode->i_uid = GLOBAL_ROOT_UID;
inode->i_gid = GLOBAL_ROOT_GID;
diff --git a/fs/proc/thread_self.c b/fs/proc/thread_self.c
index e58a31e8fb2a..595b90a9766c 100644
--- a/fs/proc/thread_self.c
+++ b/fs/proc/thread_self.c
@@ -58,7 +58,7 @@ int proc_setup_thread_self(struct super_block *s)
struct inode *inode = new_inode_pseudo(s);
if (inode) {
inode->i_ino = thread_self_inum;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
inode->i_mode = S_IFLNK | S_IRWXUGO;
inode->i_uid = GLOBAL_ROOT_UID;
inode->i_gid = GLOBAL_ROOT_GID;
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index ec9ddef5ae75..1781dc50762e 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -230,7 +230,7 @@ static struct inode *pstore_get_inode(struct super_block *sb)
struct inode *inode = new_inode(sb);
if (inode) {
inode->i_ino = get_next_ino();
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
}
return inode;
}
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index be3ddd189cd4..2bcbf4e77982 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -169,7 +169,7 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
int ret = 0;
/* POSIX UID/GID verification for setting inode attributes */
- ret = inode_change_ok(inode, ia);
+ ret = setattr_prepare(dentry, ia);
if (ret)
return ret;
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 1ab6e6c2e60e..8621c039b536 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -61,7 +61,7 @@ struct inode *ramfs_get_inode(struct super_block *sb,
inode->i_mapping->a_ops = &ramfs_aops;
mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
mapping_set_unevictable(inode->i_mapping);
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
switch (mode & S_IFMT) {
default:
init_special_inode(inode, mode, dev);
@@ -100,7 +100,7 @@ ramfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
d_instantiate(dentry, inode);
dget(dentry); /* Extra count - pin the dentry in core */
error = 0;
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
}
return error;
}
@@ -130,7 +130,7 @@ static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char *
if (!error) {
d_instantiate(dentry, inode);
dget(dentry);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
} else
iput(inode);
}
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 90f815bdfa8a..2f8c5c9bdaf6 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -260,10 +260,7 @@ const struct file_operations reiserfs_file_operations = {
const struct inode_operations reiserfs_file_inode_operations = {
.setattr = reiserfs_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = reiserfs_listxattr,
- .removexattr = generic_removexattr,
.permission = reiserfs_permission,
.get_acl = reiserfs_get_acl,
.set_acl = reiserfs_set_acl,
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index c2c59f9ff04b..58b2dedb2a3a 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2005,7 +2005,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
if (S_ISLNK(inode->i_mode))
inode->i_flags &= ~(S_IMMUTABLE | S_APPEND);
- 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_size = i_size;
inode->i_blocks = 0;
inode->i_bytes = 0;
@@ -3312,7 +3312,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
unsigned int ia_valid;
int error;
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
if (error)
return error;
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index 2f1ddc908013..1f4692a505a0 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -94,7 +94,7 @@ long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
}
sd_attrs_to_i_attrs(flags, inode);
REISERFS_I(inode)->i_attrs = flags;
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
setflags_out:
mnt_drop_write_file(filp);
@@ -115,7 +115,7 @@ setflags_out:
err = -EFAULT;
goto setversion_out;
}
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
setversion_out:
mnt_drop_write_file(filp);
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 8a36696d6df9..e6a2b406af36 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -570,7 +570,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th,
}
dir->i_size += paste_size;
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
if (!S_ISDIR(inode->i_mode) && visible)
/* reiserfs_mkdir or reiserfs_rename will do that by itself */
reiserfs_update_sd(th, dir);
@@ -963,7 +963,7 @@ static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry)
inode->i_nlink);
clear_nlink(inode);
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+ inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(dir);
reiserfs_update_sd(&th, inode);
DEC_DIR_INODE_NLINK(dir)
@@ -1067,11 +1067,11 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
inc_nlink(inode);
goto end_unlink;
}
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
reiserfs_update_sd(&th, inode);
dir->i_size -= (de.de_entrylen + DEH_SIZE);
- dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+ dir->i_ctime = dir->i_mtime = current_time(dir);
reiserfs_update_sd(&th, dir);
if (!savelink)
@@ -1246,7 +1246,7 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
return err ? err : retval;
}
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
reiserfs_update_sd(&th, inode);
ihold(inode);
@@ -1306,7 +1306,8 @@ static void set_ino_in_dir_entry(struct reiserfs_dir_entry *de,
* get_empty_nodes or its clones
*/
static int reiserfs_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;
INITIALIZE_PATH(old_entry_path);
@@ -1321,6 +1322,9 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
unsigned long savelink = 1;
struct timespec ctime;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
/*
* three balancings: (1) old name removal, (2) new name insertion
* and (3) maybe "save" link insertion
@@ -1567,7 +1571,7 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
mark_de_hidden(old_de.de_deh + old_de.de_entry_num);
journal_mark_dirty(&th, old_de.de_bh);
- ctime = CURRENT_TIME_SEC;
+ ctime = current_time(old_dir);
old_dir->i_ctime = old_dir->i_mtime = ctime;
new_dir->i_ctime = new_dir->i_mtime = ctime;
/*
@@ -1650,10 +1654,7 @@ const struct inode_operations reiserfs_dir_inode_operations = {
.mknod = reiserfs_mknod,
.rename = reiserfs_rename,
.setattr = reiserfs_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = reiserfs_listxattr,
- .removexattr = generic_removexattr,
.permission = reiserfs_permission,
.get_acl = reiserfs_get_acl,
.set_acl = reiserfs_set_acl,
@@ -1667,10 +1668,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
.readlink = generic_readlink,
.get_link = page_get_link,
.setattr = reiserfs_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = reiserfs_listxattr,
- .removexattr = generic_removexattr,
.permission = reiserfs_permission,
};
@@ -1679,10 +1677,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
*/
const struct inode_operations reiserfs_special_inode_operations = {
.setattr = reiserfs_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = reiserfs_listxattr,
- .removexattr = generic_removexattr,
.permission = reiserfs_permission,
.get_acl = reiserfs_get_acl,
.set_acl = reiserfs_set_acl,
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index 4032d1e87c8f..a97e352d05d3 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -1987,8 +1987,8 @@ int reiserfs_do_truncate(struct reiserfs_transaction_handle *th,
pathrelse(&s_search_path);
if (update_timestamps) {
- inode->i_mtime = CURRENT_TIME_SEC;
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_mtime = current_time(inode);
+ inode->i_ctime = current_time(inode);
}
reiserfs_update_sd(th, inode);
@@ -2012,8 +2012,8 @@ int reiserfs_do_truncate(struct reiserfs_transaction_handle *th,
update_and_out:
if (update_timestamps) {
/* this is truncate, not file closing */
- inode->i_mtime = CURRENT_TIME_SEC;
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_mtime = current_time(inode);
+ inode->i_ctime = current_time(inode);
}
reiserfs_update_sd(th, inode);
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 74d5ddd26296..0a6ad4e71e88 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -2522,7 +2522,7 @@ out:
if (inode->i_size < off + len - towrite)
i_size_write(inode, off + len - towrite);
inode->i_version++;
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
return len - towrite;
}
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index a33812ae9fad..e87aa21c30de 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -450,13 +450,13 @@ int reiserfs_commit_write(struct file *f, struct page *page,
static void update_ctime(struct inode *inode)
{
- struct timespec now = current_fs_time(inode->i_sb);
+ struct timespec now = current_time(inode);
if (inode_unhashed(inode) || !inode->i_nlink ||
timespec_equal(&inode->i_ctime, &now))
return;
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
}
@@ -575,7 +575,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
new_size = buffer_size + sizeof(struct reiserfs_xattr_header);
if (!err && new_size < i_size_read(d_inode(dentry))) {
struct iattr newattrs = {
- .ia_ctime = current_fs_time(inode->i_sb),
+ .ia_ctime = current_time(inode),
.ia_size = new_size,
.ia_valid = ATTR_SIZE | ATTR_CTIME,
};
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index dbed42f755e0..3d2256a425ee 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -242,13 +242,9 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
case ACL_TYPE_ACCESS:
name = XATTR_NAME_POSIX_ACL_ACCESS;
if (acl) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (error < 0)
+ error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (error)
return error;
- else {
- if (error == 0)
- acl = NULL;
- }
}
break;
case ACL_TYPE_DEFAULT:
@@ -277,7 +273,7 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
if (error == -ENODATA) {
error = 0;
if (type == ACL_TYPE_ACCESS) {
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
}
}
diff --git a/fs/select.c b/fs/select.c
index 8ed9da50896a..3d4f85defeab 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -29,6 +29,7 @@
#include <linux/sched/rt.h>
#include <linux/freezer.h>
#include <net/busy_poll.h>
+#include <linux/vmalloc.h>
#include <asm/uaccess.h>
@@ -554,7 +555,7 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
fd_set_bits fds;
void *bits;
int ret, max_fds;
- unsigned int size;
+ size_t size, alloc_size;
struct fdtable *fdt;
/* Allocate small arguments on the stack to save memory and be faster */
long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
@@ -581,7 +582,14 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
if (size > sizeof(stack_fds) / 6) {
/* Not enough space in on-stack array; must use kmalloc */
ret = -ENOMEM;
- bits = kmalloc(6 * size, GFP_KERNEL);
+ if (size > (SIZE_MAX / 6))
+ goto out_nofds;
+
+ alloc_size = 6 * size;
+ bits = kmalloc(alloc_size, GFP_KERNEL|__GFP_NOWARN);
+ if (!bits && alloc_size > PAGE_SIZE)
+ bits = vmalloc(alloc_size);
+
if (!bits)
goto out_nofds;
}
@@ -618,7 +626,7 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
out:
if (bits != stack_fds)
- kfree(bits);
+ kvfree(bits);
out_nofds:
return ret;
}
diff --git a/fs/splice.c b/fs/splice.c
index aa38901a4f10..153d4f3bd441 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -315,15 +315,9 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
*ppos = kiocb.ki_pos;
file_accessed(in);
} else if (ret < 0) {
- if (WARN_ON(to.idx != idx || to.iov_offset)) {
- /*
- * a bogus ->read_iter() has copied something and still
- * returned an error instead of a short read.
- */
- to.idx = idx;
- to.iov_offset = 0;
- iov_iter_advance(&to, 0); /* to free what was emitted */
- }
+ to.idx = idx;
+ to.iov_offset = 0;
+ iov_iter_advance(&to, 0); /* to free what was emitted */
/*
* callers of ->splice_read() expect -EAGAIN on
* "can't put anything in there", rather than -EFAULT.
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
index 0927b1e80ab6..e9793b1e49a5 100644
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.c
@@ -425,7 +425,6 @@ failed_read:
const struct inode_operations squashfs_inode_ops = {
- .getxattr = generic_getxattr,
.listxattr = squashfs_listxattr
};
diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c
index 67cad77fefb4..40c10d9974c9 100644
--- a/fs/squashfs/namei.c
+++ b/fs/squashfs/namei.c
@@ -247,6 +247,5 @@ failed:
const struct inode_operations squashfs_dir_inode_ops = {
.lookup = squashfs_lookup,
- .getxattr = generic_getxattr,
.listxattr = squashfs_listxattr
};
diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c
index d688ef42a6a1..79b9c31a0c8f 100644
--- a/fs/squashfs/symlink.c
+++ b/fs/squashfs/symlink.c
@@ -120,7 +120,6 @@ const struct address_space_operations squashfs_symlink_aops = {
const struct inode_operations squashfs_symlink_inode_ops = {
.readlink = generic_readlink,
.get_link = page_get_link,
- .getxattr = generic_getxattr,
.listxattr = squashfs_listxattr
};
diff --git a/fs/squashfs/xattr.h b/fs/squashfs/xattr.h
index c83f5d9ec125..afe70f815e3d 100644
--- a/fs/squashfs/xattr.h
+++ b/fs/squashfs/xattr.h
@@ -42,6 +42,5 @@ static inline int squashfs_xattr_lookup(struct super_block *sb,
return 0;
}
#define squashfs_listxattr NULL
-#define generic_getxattr NULL
#define squashfs_xattr_handlers NULL
#endif
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 2661b77fc8a7..5bdae85ceef7 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -215,7 +215,7 @@ got_it:
memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2);
de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty(dir);
out_page:
dir_put_page(page);
@@ -239,7 +239,7 @@ int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
de->inode = 0;
err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
dir_put_page(page);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
mark_inode_dirty(inode);
return err;
}
@@ -337,7 +337,7 @@ void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
dir_put_page(page);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty(dir);
}
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index 82ddc09061e2..7ba997e31aeb 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -33,7 +33,7 @@ static int sysv_setattr(struct dentry *dentry, struct iattr *attr)
struct inode *inode = d_inode(dentry);
int error;
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
if (error)
return error;
diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c
index f9db4eb31db4..53f1b78996dd 100644
--- a/fs/sysv/ialloc.c
+++ b/fs/sysv/ialloc.c
@@ -164,7 +164,7 @@ struct inode * sysv_new_inode(const struct inode * dir, umode_t mode)
dirty_sb(sb);
inode_init_owner(inode, dir, mode);
inode->i_ino = fs16_to_cpu(sbi, ino);
- 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;
memset(SYSV_I(inode)->i_data, 0, sizeof(SYSV_I(inode)->i_data));
SYSV_I(inode)->i_dir_start_lookup = 0;
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index 2fde40acf024..08d3e630b49c 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -178,7 +178,7 @@ static inline int splice_branch(struct inode *inode,
*where->p = where->key;
write_unlock(&pointers_lock);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
/* had we spliced it onto indirect block? */
if (where->bh)
@@ -418,7 +418,7 @@ do_indirects:
}
n++;
}
- inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
if (IS_SYNC(inode))
sysv_sync_inode (inode);
else
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
index a42de45ce40d..d8817f139763 100644
--- a/fs/sysv/namei.c
+++ b/fs/sysv/namei.c
@@ -120,7 +120,7 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir,
{
struct inode *inode = d_inode(old_dentry);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
inode_inc_link_count(inode);
ihold(inode);
@@ -206,7 +206,8 @@ static int sysv_rmdir(struct inode * dir, struct dentry * dentry)
* higher-level routines.
*/
static int sysv_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 = d_inode(old_dentry);
struct inode * new_inode = d_inode(new_dentry);
@@ -216,6 +217,9 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
struct sysv_dir_entry * old_de;
int err = -ENOENT;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
old_de = sysv_find_entry(old_dentry, &old_page);
if (!old_de)
goto out;
@@ -240,7 +244,7 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
if (!new_de)
goto out_dir;
sysv_set_link(new_de, new_page, old_inode);
- new_inode->i_ctime = CURRENT_TIME_SEC;
+ new_inode->i_ctime = current_time(new_inode);
if (dir_de)
drop_nlink(new_inode);
inode_dec_link_count(new_inode);
diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
index ad40b64c5e2f..21d36d284735 100644
--- a/fs/tracefs/inode.c
+++ b/fs/tracefs/inode.c
@@ -133,7 +133,7 @@ static struct inode *tracefs_get_inode(struct super_block *sb)
struct inode *inode = new_inode(sb);
if (inode) {
inode->i_ino = get_next_ino();
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
}
return inode;
}
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 4b86d3a738e1..c8f60df2733e 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -301,6 +301,95 @@ out_budg:
return err;
}
+static int do_tmpfile(struct inode *dir, struct dentry *dentry,
+ umode_t mode, struct inode **whiteout)
+{
+ struct inode *inode;
+ struct ubifs_info *c = dir->i_sb->s_fs_info;
+ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1};
+ struct ubifs_budget_req ino_req = { .dirtied_ino = 1 };
+ struct ubifs_inode *ui, *dir_ui = ubifs_inode(dir);
+ int err, instantiated = 0;
+
+ /*
+ * Budget request settings: new dirty inode, new direntry,
+ * budget for dirtied inode will be released via writeback.
+ */
+
+ dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
+ dentry, mode, dir->i_ino);
+
+ err = ubifs_budget_space(c, &req);
+ if (err)
+ return err;
+
+ err = ubifs_budget_space(c, &ino_req);
+ if (err) {
+ ubifs_release_budget(c, &req);
+ return err;
+ }
+
+ inode = ubifs_new_inode(c, dir, mode);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ goto out_budg;
+ }
+ ui = ubifs_inode(inode);
+
+ if (whiteout) {
+ init_special_inode(inode, inode->i_mode, WHITEOUT_DEV);
+ ubifs_assert(inode->i_op == &ubifs_file_inode_operations);
+ }
+
+ err = ubifs_init_security(dir, inode, &dentry->d_name);
+ if (err)
+ goto out_inode;
+
+ mutex_lock(&ui->ui_mutex);
+ insert_inode_hash(inode);
+
+ if (whiteout) {
+ mark_inode_dirty(inode);
+ drop_nlink(inode);
+ *whiteout = inode;
+ } else {
+ d_tmpfile(dentry, inode);
+ }
+ ubifs_assert(ui->dirty);
+
+ instantiated = 1;
+ mutex_unlock(&ui->ui_mutex);
+
+ mutex_lock(&dir_ui->ui_mutex);
+ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1, 0);
+ if (err)
+ goto out_cancel;
+ mutex_unlock(&dir_ui->ui_mutex);
+
+ ubifs_release_budget(c, &req);
+
+ return 0;
+
+out_cancel:
+ mutex_unlock(&dir_ui->ui_mutex);
+out_inode:
+ make_bad_inode(inode);
+ if (!instantiated)
+ iput(inode);
+out_budg:
+ ubifs_release_budget(c, &req);
+ if (!instantiated)
+ ubifs_release_budget(c, &ino_req);
+ ubifs_err(c, "cannot create temporary file, error %d", err);
+ return err;
+}
+
+static int ubifs_tmpfile(struct inode *dir, struct dentry *dentry,
+ umode_t mode)
+{
+ return do_tmpfile(dir, dentry, mode, NULL);
+}
+
/**
* vfs_dent_type - get VFS directory entry type.
* @type: UBIFS directory entry type
@@ -927,37 +1016,43 @@ out_budg:
}
/**
- * lock_3_inodes - a wrapper for locking three UBIFS inodes.
+ * lock_4_inodes - a wrapper for locking three UBIFS inodes.
* @inode1: first inode
* @inode2: second inode
* @inode3: third inode
+ * @inode4: fouth inode
*
* This function is used for 'ubifs_rename()' and @inode1 may be the same as
- * @inode2 whereas @inode3 may be %NULL.
+ * @inode2 whereas @inode3 and @inode4 may be %NULL.
*
* We do not implement any tricks to guarantee strict lock ordering, because
* VFS has already done it for us on the @i_mutex. So this is just a simple
* wrapper function.
*/
-static void lock_3_inodes(struct inode *inode1, struct inode *inode2,
- struct inode *inode3)
+static void lock_4_inodes(struct inode *inode1, struct inode *inode2,
+ struct inode *inode3, struct inode *inode4)
{
mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
if (inode2 != inode1)
mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
if (inode3)
mutex_lock_nested(&ubifs_inode(inode3)->ui_mutex, WB_MUTEX_3);
+ if (inode4)
+ mutex_lock_nested(&ubifs_inode(inode4)->ui_mutex, WB_MUTEX_4);
}
/**
- * unlock_3_inodes - a wrapper for unlocking three UBIFS inodes for rename.
+ * unlock_4_inodes - a wrapper for unlocking three UBIFS inodes for rename.
* @inode1: first inode
* @inode2: second inode
* @inode3: third inode
+ * @inode4: fouth inode
*/
-static void unlock_3_inodes(struct inode *inode1, struct inode *inode2,
- struct inode *inode3)
+static void unlock_4_inodes(struct inode *inode1, struct inode *inode2,
+ struct inode *inode3, struct inode *inode4)
{
+ if (inode4)
+ mutex_unlock(&ubifs_inode(inode4)->ui_mutex);
if (inode3)
mutex_unlock(&ubifs_inode(inode3)->ui_mutex);
if (inode1 != inode2)
@@ -966,12 +1061,15 @@ static void unlock_3_inodes(struct inode *inode1, struct inode *inode2,
}
static int ubifs_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 ubifs_info *c = old_dir->i_sb->s_fs_info;
struct inode *old_inode = d_inode(old_dentry);
struct inode *new_inode = d_inode(new_dentry);
+ struct inode *whiteout = NULL;
struct ubifs_inode *old_inode_ui = ubifs_inode(old_inode);
+ struct ubifs_inode *whiteout_ui = NULL;
int err, release, sync = 0, move = (new_dir != old_dir);
int is_dir = S_ISDIR(old_inode->i_mode);
int unlink = !!new_inode;
@@ -984,6 +1082,9 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct timespec time;
unsigned int uninitialized_var(saved_nlink);
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
/*
* Budget request settings: deletion direntry, new direntry, removing
* the old inode, and changing old and new parent directory inodes.
@@ -993,15 +1094,13 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
* separately.
*/
- dbg_gen("dent '%pd' ino %lu in dir ino %lu to dent '%pd' in dir ino %lu",
+ dbg_gen("dent '%pd' ino %lu in dir ino %lu to dent '%pd' in dir ino %lu flags 0x%x",
old_dentry, old_inode->i_ino, old_dir->i_ino,
- new_dentry, new_dir->i_ino);
- ubifs_assert(inode_is_locked(old_dir));
- ubifs_assert(inode_is_locked(new_dir));
+ new_dentry, new_dir->i_ino, flags);
+
if (unlink)
ubifs_assert(inode_is_locked(new_inode));
-
if (unlink && is_dir) {
err = check_dir_empty(c, new_inode);
if (err)
@@ -1017,7 +1116,32 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
return err;
}
- lock_3_inodes(old_dir, new_dir, new_inode);
+ if (flags & RENAME_WHITEOUT) {
+ union ubifs_dev_desc *dev = NULL;
+
+ dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);
+ if (!dev) {
+ ubifs_release_budget(c, &req);
+ ubifs_release_budget(c, &ino_req);
+ return -ENOMEM;
+ }
+
+ err = do_tmpfile(old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, &whiteout);
+ if (err) {
+ ubifs_release_budget(c, &req);
+ ubifs_release_budget(c, &ino_req);
+ kfree(dev);
+ return err;
+ }
+
+ whiteout->i_state |= I_LINKABLE;
+ whiteout_ui = ubifs_inode(whiteout);
+ whiteout_ui->data = dev;
+ whiteout_ui->data_len = ubifs_encode_dev(dev, MKDEV(0, 0));
+ ubifs_assert(!whiteout_ui->dirty);
+ }
+
+ lock_4_inodes(old_dir, new_dir, new_inode, whiteout);
/*
* Like most other Unix systems, set the @i_ctime for inodes on a
@@ -1087,12 +1211,34 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (unlink && IS_SYNC(new_inode))
sync = 1;
}
- err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry,
+
+ if (whiteout) {
+ struct ubifs_budget_req wht_req = { .dirtied_ino = 1,
+ .dirtied_ino_d = \
+ ALIGN(ubifs_inode(whiteout)->data_len, 8) };
+
+ err = ubifs_budget_space(c, &wht_req);
+ if (err) {
+ ubifs_release_budget(c, &req);
+ ubifs_release_budget(c, &ino_req);
+ kfree(whiteout_ui->data);
+ whiteout_ui->data_len = 0;
+ iput(whiteout);
+ return err;
+ }
+
+ inc_nlink(whiteout);
+ mark_inode_dirty(whiteout);
+ whiteout->i_state &= ~I_LINKABLE;
+ iput(whiteout);
+ }
+
+ err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry, whiteout,
sync);
if (err)
goto out_cancel;
- unlock_3_inodes(old_dir, new_dir, new_inode);
+ unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
ubifs_release_budget(c, &req);
mutex_lock(&old_inode_ui->ui_mutex);
@@ -1125,12 +1271,74 @@ out_cancel:
inc_nlink(old_dir);
}
}
- unlock_3_inodes(old_dir, new_dir, new_inode);
+ if (whiteout) {
+ drop_nlink(whiteout);
+ iput(whiteout);
+ }
+ unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
ubifs_release_budget(c, &ino_req);
ubifs_release_budget(c, &req);
return err;
}
+static int ubifs_xrename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+{
+ struct ubifs_info *c = old_dir->i_sb->s_fs_info;
+ struct ubifs_budget_req req = { .new_dent = 1, .mod_dent = 1,
+ .dirtied_ino = 2 };
+ int sync = IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir);
+ struct inode *fst_inode = d_inode(old_dentry);
+ struct inode *snd_inode = d_inode(new_dentry);
+ struct timespec time;
+ int err;
+
+ ubifs_assert(fst_inode && snd_inode);
+
+ lock_4_inodes(old_dir, new_dir, NULL, NULL);
+
+ time = ubifs_current_time(old_dir);
+ fst_inode->i_ctime = time;
+ snd_inode->i_ctime = time;
+ old_dir->i_mtime = old_dir->i_ctime = time;
+ new_dir->i_mtime = new_dir->i_ctime = time;
+
+ if (old_dir != new_dir) {
+ if (S_ISDIR(fst_inode->i_mode) && !S_ISDIR(snd_inode->i_mode)) {
+ inc_nlink(new_dir);
+ drop_nlink(old_dir);
+ }
+ else if (!S_ISDIR(fst_inode->i_mode) && S_ISDIR(snd_inode->i_mode)) {
+ drop_nlink(new_dir);
+ inc_nlink(old_dir);
+ }
+ }
+
+ err = ubifs_jnl_xrename(c, old_dir, old_dentry, new_dir, new_dentry,
+ sync);
+
+ unlock_4_inodes(old_dir, new_dir, NULL, NULL);
+ ubifs_release_budget(c, &req);
+
+ return err;
+}
+
+static int ubifs_rename2(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags)
+{
+ if (flags & ~(RENAME_NOREPLACE | RENAME_WHITEOUT | RENAME_EXCHANGE))
+ return -EINVAL;
+
+ ubifs_assert(inode_is_locked(old_dir));
+ ubifs_assert(inode_is_locked(new_dir));
+
+ if (flags & RENAME_EXCHANGE)
+ return ubifs_xrename(old_dir, old_dentry, new_dir, new_dentry);
+
+ return ubifs_rename(old_dir, old_dentry, new_dir, new_dentry, flags);
+}
+
int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat)
{
@@ -1179,16 +1387,14 @@ const struct inode_operations ubifs_dir_inode_operations = {
.mkdir = ubifs_mkdir,
.rmdir = ubifs_rmdir,
.mknod = ubifs_mknod,
- .rename = ubifs_rename,
+ .rename = ubifs_rename2,
.setattr = ubifs_setattr,
.getattr = ubifs_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ubifs_listxattr,
- .removexattr = generic_removexattr,
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
.update_time = ubifs_update_time,
#endif
+ .tmpfile = ubifs_tmpfile,
};
const struct file_operations ubifs_dir_operations = {
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 7bbf420d1289..b4fbeefba246 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1262,7 +1262,7 @@ int ubifs_setattr(struct dentry *dentry, struct iattr *attr)
dbg_gen("ino %lu, mode %#x, ia_valid %#x",
inode->i_ino, inode->i_mode, attr->ia_valid);
- err = inode_change_ok(inode, attr);
+ err = setattr_prepare(dentry, attr);
if (err)
return err;
@@ -1397,7 +1397,7 @@ int ubifs_update_time(struct inode *inode, struct timespec *time,
#endif
/**
- * update_ctime - update mtime and ctime of an inode.
+ * update_mctime - update mtime and ctime of an inode.
* @inode: inode to update
*
* This function updates mtime and ctime of the inode if it is not equivalent to
@@ -1621,10 +1621,7 @@ const struct address_space_operations ubifs_file_address_operations = {
const struct inode_operations ubifs_file_inode_operations = {
.setattr = ubifs_setattr,
.getattr = ubifs_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ubifs_listxattr,
- .removexattr = generic_removexattr,
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
.update_time = ubifs_update_time,
#endif
@@ -1635,10 +1632,7 @@ const struct inode_operations ubifs_symlink_inode_operations = {
.get_link = simple_get_link,
.setattr = ubifs_setattr,
.getattr = ubifs_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ubifs_listxattr,
- .removexattr = generic_removexattr,
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
.update_time = ubifs_update_time,
#endif
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index 821b34816976..e845c64b6ce1 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -113,7 +113,7 @@ static int switch_gc_head(struct ubifs_info *c)
* data_nodes_cmp - compare 2 data nodes.
* @priv: UBIFS file-system description object
* @a: first data node
- * @a: second data node
+ * @b: second data node
*
* This function compares data nodes @a and @b. Returns %1 if @a has greater
* inode or block number, and %-1 otherwise.
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index 0b9da5b6e0f9..91bc76dc559e 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -908,6 +908,147 @@ int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode)
}
/**
+ * ubifs_jnl_xrename - cross rename two directory entries.
+ * @c: UBIFS file-system description object
+ * @fst_dir: parent inode of 1st directory entry to exchange
+ * @fst_dentry: 1st directory entry to exchange
+ * @snd_dir: parent inode of 2nd directory entry to exchange
+ * @snd_dentry: 2nd directory entry to exchange
+ * @sync: non-zero if the write-buffer has to be synchronized
+ *
+ * This function implements the cross rename operation which may involve
+ * writing 2 inodes and 2 directory entries. It marks the written inodes as clean
+ * and returns zero on success. In case of failure, a negative error code is
+ * returned.
+ */
+int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir,
+ const struct dentry *fst_dentry,
+ const struct inode *snd_dir,
+ const struct dentry *snd_dentry, int sync)
+{
+ union ubifs_key key;
+ struct ubifs_dent_node *dent1, *dent2;
+ int err, dlen1, dlen2, lnum, offs, len, plen = UBIFS_INO_NODE_SZ;
+ int aligned_dlen1, aligned_dlen2;
+ int twoparents = (fst_dir != snd_dir);
+ const struct inode *fst_inode = d_inode(fst_dentry);
+ const struct inode *snd_inode = d_inode(snd_dentry);
+ void *p;
+
+ dbg_jnl("dent '%pd' in dir ino %lu between dent '%pd' in dir ino %lu",
+ fst_dentry, fst_dir->i_ino, snd_dentry, snd_dir->i_ino);
+
+ ubifs_assert(ubifs_inode(fst_dir)->data_len == 0);
+ ubifs_assert(ubifs_inode(snd_dir)->data_len == 0);
+ ubifs_assert(mutex_is_locked(&ubifs_inode(fst_dir)->ui_mutex));
+ ubifs_assert(mutex_is_locked(&ubifs_inode(snd_dir)->ui_mutex));
+
+ dlen1 = UBIFS_DENT_NODE_SZ + snd_dentry->d_name.len + 1;
+ dlen2 = UBIFS_DENT_NODE_SZ + fst_dentry->d_name.len + 1;
+ aligned_dlen1 = ALIGN(dlen1, 8);
+ aligned_dlen2 = ALIGN(dlen2, 8);
+
+ len = aligned_dlen1 + aligned_dlen2 + ALIGN(plen, 8);
+ if (twoparents)
+ len += plen;
+
+ dent1 = kmalloc(len, GFP_NOFS);
+ if (!dent1)
+ return -ENOMEM;
+
+ /* Make reservation before allocating sequence numbers */
+ err = make_reservation(c, BASEHD, len);
+ if (err)
+ goto out_free;
+
+ /* Make new dent for 1st entry */
+ dent1->ch.node_type = UBIFS_DENT_NODE;
+ dent_key_init_flash(c, &dent1->key, snd_dir->i_ino, &snd_dentry->d_name);
+ dent1->inum = cpu_to_le64(fst_inode->i_ino);
+ dent1->type = get_dent_type(fst_inode->i_mode);
+ dent1->nlen = cpu_to_le16(snd_dentry->d_name.len);
+ memcpy(dent1->name, snd_dentry->d_name.name, snd_dentry->d_name.len);
+ dent1->name[snd_dentry->d_name.len] = '\0';
+ zero_dent_node_unused(dent1);
+ ubifs_prep_grp_node(c, dent1, dlen1, 0);
+
+ /* Make new dent for 2nd entry */
+ dent2 = (void *)dent1 + aligned_dlen1;
+ dent2->ch.node_type = UBIFS_DENT_NODE;
+ dent_key_init_flash(c, &dent2->key, fst_dir->i_ino, &fst_dentry->d_name);
+ dent2->inum = cpu_to_le64(snd_inode->i_ino);
+ dent2->type = get_dent_type(snd_inode->i_mode);
+ dent2->nlen = cpu_to_le16(fst_dentry->d_name.len);
+ memcpy(dent2->name, fst_dentry->d_name.name, fst_dentry->d_name.len);
+ dent2->name[fst_dentry->d_name.len] = '\0';
+ zero_dent_node_unused(dent2);
+ ubifs_prep_grp_node(c, dent2, dlen2, 0);
+
+ p = (void *)dent2 + aligned_dlen2;
+ if (!twoparents)
+ pack_inode(c, p, fst_dir, 1);
+ else {
+ pack_inode(c, p, fst_dir, 0);
+ p += ALIGN(plen, 8);
+ pack_inode(c, p, snd_dir, 1);
+ }
+
+ err = write_head(c, BASEHD, dent1, len, &lnum, &offs, sync);
+ if (err)
+ goto out_release;
+ if (!sync) {
+ struct ubifs_wbuf *wbuf = &c->jheads[BASEHD].wbuf;
+
+ ubifs_wbuf_add_ino_nolock(wbuf, fst_dir->i_ino);
+ ubifs_wbuf_add_ino_nolock(wbuf, snd_dir->i_ino);
+ }
+ release_head(c, BASEHD);
+
+ dent_key_init(c, &key, snd_dir->i_ino, &snd_dentry->d_name);
+ err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, &snd_dentry->d_name);
+ if (err)
+ goto out_ro;
+
+ offs += aligned_dlen1;
+ dent_key_init(c, &key, fst_dir->i_ino, &fst_dentry->d_name);
+ err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen2, &fst_dentry->d_name);
+ if (err)
+ goto out_ro;
+
+ offs += aligned_dlen2;
+
+ ino_key_init(c, &key, fst_dir->i_ino);
+ err = ubifs_tnc_add(c, &key, lnum, offs, plen);
+ if (err)
+ goto out_ro;
+
+ if (twoparents) {
+ offs += ALIGN(plen, 8);
+ ino_key_init(c, &key, snd_dir->i_ino);
+ err = ubifs_tnc_add(c, &key, lnum, offs, plen);
+ if (err)
+ goto out_ro;
+ }
+
+ finish_reservation(c);
+
+ mark_inode_clean(c, ubifs_inode(fst_dir));
+ if (twoparents)
+ mark_inode_clean(c, ubifs_inode(snd_dir));
+ kfree(dent1);
+ return 0;
+
+out_release:
+ release_head(c, BASEHD);
+out_ro:
+ ubifs_ro_mode(c, err);
+ finish_reservation(c);
+out_free:
+ kfree(dent1);
+ return err;
+}
+
+/**
* ubifs_jnl_rename - rename a directory entry.
* @c: UBIFS file-system description object
* @old_dir: parent inode of directory entry to rename
@@ -917,14 +1058,15 @@ int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode)
* @sync: non-zero if the write-buffer has to be synchronized
*
* This function implements the re-name operation which may involve writing up
- * to 3 inodes and 2 directory entries. It marks the written inodes as clean
+ * to 4 inodes and 2 directory entries. It marks the written inodes as clean
* and returns zero on success. In case of failure, a negative error code is
* returned.
*/
int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
const struct dentry *old_dentry,
const struct inode *new_dir,
- const struct dentry *new_dentry, int sync)
+ const struct dentry *new_dentry,
+ const struct inode *whiteout, int sync)
{
void *p;
union ubifs_key key;
@@ -958,7 +1100,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
aligned_dlen1 = ALIGN(dlen1, 8);
aligned_dlen2 = ALIGN(dlen2, 8);
len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8);
- if (old_dir != new_dir)
+ if (move)
len += plen;
dent = kmalloc(len, GFP_NOFS);
if (!dent)
@@ -980,13 +1122,19 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
zero_dent_node_unused(dent);
ubifs_prep_grp_node(c, dent, dlen1, 0);
- /* Make deletion dent */
dent2 = (void *)dent + aligned_dlen1;
dent2->ch.node_type = UBIFS_DENT_NODE;
dent_key_init_flash(c, &dent2->key, old_dir->i_ino,
&old_dentry->d_name);
- dent2->inum = 0;
- dent2->type = DT_UNKNOWN;
+
+ if (whiteout) {
+ dent2->inum = cpu_to_le64(whiteout->i_ino);
+ dent2->type = get_dent_type(whiteout->i_mode);
+ } else {
+ /* Make deletion dent */
+ dent2->inum = 0;
+ dent2->type = DT_UNKNOWN;
+ }
dent2->nlen = cpu_to_le16(old_dentry->d_name.len);
memcpy(dent2->name, old_dentry->d_name.name, old_dentry->d_name.len);
dent2->name[old_dentry->d_name.len] = '\0';
@@ -1035,16 +1183,26 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
if (err)
goto out_ro;
- err = ubifs_add_dirt(c, lnum, dlen2);
- if (err)
- goto out_ro;
+ offs += aligned_dlen1;
+ if (whiteout) {
+ dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name);
+ err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen2, &old_dentry->d_name);
+ if (err)
+ goto out_ro;
- dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name);
- err = ubifs_tnc_remove_nm(c, &key, &old_dentry->d_name);
- if (err)
- goto out_ro;
+ ubifs_delete_orphan(c, whiteout->i_ino);
+ } else {
+ err = ubifs_add_dirt(c, lnum, dlen2);
+ if (err)
+ goto out_ro;
+
+ dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name);
+ err = ubifs_tnc_remove_nm(c, &key, &old_dentry->d_name);
+ if (err)
+ goto out_ro;
+ }
- offs += aligned_dlen1 + aligned_dlen2;
+ offs += aligned_dlen2;
if (new_inode) {
ino_key_init(c, &key, new_inode->i_ino);
err = ubifs_tnc_add(c, &key, lnum, offs, ilen);
@@ -1058,7 +1216,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
if (err)
goto out_ro;
- if (old_dir != new_dir) {
+ if (move) {
offs += ALIGN(plen, 8);
ino_key_init(c, &key, new_dir->i_ino);
err = ubifs_tnc_add(c, &key, lnum, offs, plen);
diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c
index a0011aa3a779..6c3a1abd0e22 100644
--- a/fs/ubifs/lprops.c
+++ b/fs/ubifs/lprops.c
@@ -636,7 +636,7 @@ const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c,
/**
* ubifs_get_lp_stats - get lprops statistics.
* @c: UBIFS file-system description object
- * @st: return statistics
+ * @lst: return statistics
*/
void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *lst)
{
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index ce89bdc3eb02..235654c2fe89 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -34,7 +34,6 @@ static int dbg_populate_lsave(struct ubifs_info *c);
/**
* first_dirty_cnode - find first dirty cnode.
- * @c: UBIFS file-system description object
* @nnode: nnode at which to start
*
* This function returns the first dirty cnode or %NULL if there is not one.
@@ -1623,7 +1622,6 @@ static int dbg_is_node_dirty(struct ubifs_info *c, int node_type, int lnum,
* dbg_check_ltab_lnum - check the ltab for a LPT LEB number.
* @c: the UBIFS file-system description object
* @lnum: LEB number where node was written
- * @offs: offset where node was written
*
* This function returns %0 on success and a negative error code on failure.
*/
@@ -1870,7 +1868,7 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
}
/**
- * ubifs_dump_lpt_leb - dump an LPT LEB.
+ * dump_lpt_leb - dump an LPT LEB.
* @c: UBIFS file-system description object
* @lnum: LEB number to dump
*
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index 3ca4540130b5..fb0f44cd1e28 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -267,7 +267,7 @@ static int apply_replay_entry(struct ubifs_info *c, struct replay_entry *r)
* replay_entries_cmp - compare 2 replay entries.
* @priv: UBIFS file-system description object
* @a: first replay entry
- * @a: second replay entry
+ * @b: second replay entry
*
* This is a comparios function for 'list_sort()' which compares 2 replay
* entries @a and @b by comparing their sequence numer. Returns %1 if @a has
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 4617d459022a..096035eb29d0 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -157,6 +157,7 @@ enum {
WB_MUTEX_1 = 0,
WB_MUTEX_2 = 1,
WB_MUTEX_3 = 2,
+ WB_MUTEX_4 = 3,
};
/*
@@ -1520,10 +1521,15 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
const union ubifs_key *key, const void *buf, int len);
int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode);
int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode);
+int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir,
+ const struct dentry *fst_dentry,
+ const struct inode *snd_dir,
+ const struct dentry *snd_dentry, int sync);
int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
const struct dentry *old_dentry,
const struct inode *new_dir,
- const struct dentry *new_dentry, int sync);
+ const struct dentry *new_dentry,
+ const struct inode *whiteout, int sync);
int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
loff_t old_size, loff_t new_size);
int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index 11a004114eba..6c2f4d41ed73 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -200,6 +200,7 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
struct ubifs_inode *host_ui = ubifs_inode(host);
struct ubifs_inode *ui = ubifs_inode(inode);
void *buf = NULL;
+ int old_size;
struct ubifs_budget_req req = { .dirtied_ino = 2,
.dirtied_ino_d = ALIGN(size, 8) + ALIGN(host_ui->data_len, 8) };
@@ -217,12 +218,13 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
kfree(ui->data);
ui->data = buf;
inode->i_size = ui->ui_size = size;
+ old_size = ui->data_len;
ui->data_len = size;
mutex_unlock(&ui->ui_mutex);
mutex_lock(&host_ui->ui_mutex);
host->i_ctime = ubifs_current_time(host);
- host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len);
+ host_ui->xattr_size -= CALC_XATTR_BYTES(old_size);
host_ui->xattr_size += CALC_XATTR_BYTES(size);
/*
@@ -241,7 +243,7 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
out_cancel:
host_ui->xattr_size -= CALC_XATTR_BYTES(size);
- host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len);
+ host_ui->xattr_size += CALC_XATTR_BYTES(old_size);
mutex_unlock(&host_ui->ui_mutex);
make_bad_inode(inode);
out_free:
diff --git a/fs/udf/file.c b/fs/udf/file.c
index e855bf8d74b4..dbcb3a4a0cb9 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -261,7 +261,7 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr)
struct inode *inode = d_inode(dentry);
int error;
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
if (error)
return error;
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index e77db621ec89..c1ed18a10ce4 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -121,7 +121,7 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode)
else
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
inode->i_mtime = inode->i_atime = inode->i_ctime =
- iinfo->i_crtime = current_fs_time(inode->i_sb);
+ iinfo->i_crtime = current_time(inode);
if (unlikely(insert_inode_locked(inode) < 0)) {
make_bad_inode(inode);
iput(inode);
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 55aa587bbc38..aad46401ede5 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -886,7 +886,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
*new = 1;
iinfo->i_next_alloc_block = block;
iinfo->i_next_alloc_goal = newblocknum;
- inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_ctime = current_time(inode);
if (IS_SYNC(inode))
udf_sync_inode(inode);
@@ -1268,7 +1268,7 @@ set_size:
up_write(&iinfo->i_data_sem);
}
update_time:
- inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_mtime = inode->i_ctime = current_time(inode);
if (IS_SYNC(inode))
udf_sync_inode(inode);
else
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index c3e5c9679371..2d65e280748b 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -616,7 +616,7 @@ static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
- dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
+ dir->i_ctime = dir->i_mtime = current_time(dir);
mark_inode_dirty(dir);
if (fibh.sbh != fibh.ebh)
brelse(fibh.ebh);
@@ -730,7 +730,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
inc_nlink(dir);
- dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
+ dir->i_ctime = dir->i_mtime = current_time(dir);
mark_inode_dirty(dir);
unlock_new_inode(inode);
d_instantiate(dentry, inode);
@@ -845,7 +845,7 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry)
inode->i_size = 0;
inode_dec_link_count(dir);
inode->i_ctime = dir->i_ctime = dir->i_mtime =
- current_fs_time(dir->i_sb);
+ current_time(inode);
mark_inode_dirty(dir);
end_rmdir:
@@ -888,7 +888,7 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry)
retval = udf_delete_entry(dir, fi, &fibh, &cfi);
if (retval)
goto end_unlink;
- dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
+ dir->i_ctime = dir->i_mtime = current_time(dir);
mark_inode_dirty(dir);
inode_dec_link_count(inode);
inode->i_ctime = dir->i_ctime;
@@ -1079,9 +1079,9 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,
brelse(fibh.ebh);
brelse(fibh.sbh);
inc_nlink(inode);
- inode->i_ctime = current_fs_time(inode->i_sb);
+ inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
- dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
+ dir->i_ctime = dir->i_mtime = current_time(dir);
mark_inode_dirty(dir);
ihold(inode);
d_instantiate(dentry, inode);
@@ -1093,7 +1093,8 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,
* higher-level routines.
*/
static int udf_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 = d_inode(old_dentry);
struct inode *new_inode = d_inode(new_dentry);
@@ -1105,6 +1106,9 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
struct kernel_lb_addr tloc;
struct udf_inode_info *old_iinfo = UDF_I(old_inode);
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
if (IS_ERR(ofi)) {
retval = PTR_ERR(ofi);
@@ -1172,7 +1176,7 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
* Like most other Unix systems, set the ctime for inodes on a
* rename.
*/
- old_inode->i_ctime = current_fs_time(old_inode->i_sb);
+ old_inode->i_ctime = current_time(old_inode);
mark_inode_dirty(old_inode);
/*
@@ -1188,11 +1192,11 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
udf_delete_entry(old_dir, ofi, &ofibh, &ocfi);
if (new_inode) {
- new_inode->i_ctime = current_fs_time(new_inode->i_sb);
+ new_inode->i_ctime = current_time(new_inode);
inode_dec_link_count(new_inode);
}
- old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb);
- new_dir->i_ctime = new_dir->i_mtime = current_fs_time(new_dir->i_sb);
+ old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
+ new_dir->i_ctime = new_dir->i_mtime = current_time(new_dir);
mark_inode_dirty(old_dir);
mark_inode_dirty(new_dir);
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index fa3bda1a860f..de01b8f2aa78 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -100,7 +100,7 @@ void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
err = ufs_commit_chunk(page, pos, len);
ufs_put_page(page);
if (update_times)
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty(dir);
}
@@ -389,7 +389,7 @@ got_it:
ufs_set_de_type(sb, de, inode->i_mode);
err = ufs_commit_chunk(page, pos, rec_len);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ dir->i_mtime = dir->i_ctime = current_time(dir);
mark_inode_dirty(dir);
/* OFFSET_CACHE */
@@ -530,7 +530,7 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir,
pde->d_reclen = cpu_to_fs16(sb, to - from);
dir->d_ino = 0;
err = ufs_commit_chunk(page, pos, to - from);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
mark_inode_dirty(inode);
out:
ufs_put_page(page);
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index fd0203ce1f7f..9774555b3721 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -290,7 +290,7 @@ cg_found:
inode_init_owner(inode, dir, mode);
inode->i_blocks = 0;
inode->i_generation = 0;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
ufsi->i_flags = UFS_I(dir)->i_flags;
ufsi->i_lastfrag = 0;
ufsi->i_shadow = 0;
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 9f49431e798d..190d64be22ed 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -293,7 +293,7 @@ ufs_inode_getfrag(struct inode *inode, unsigned index,
if (new)
*new = 1;
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
if (IS_SYNC(inode))
ufs_sync_inode (inode);
mark_inode_dirty(inode);
@@ -375,7 +375,7 @@ ufs_inode_getblock(struct inode *inode, u64 ind_block,
mark_buffer_dirty(bh);
if (IS_SYNC(inode))
sync_dirty_buffer(bh);
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
out:
brelse (bh);
@@ -1185,7 +1185,7 @@ static int ufs_truncate(struct inode *inode, loff_t size)
truncate_setsize(inode, size);
__ufs_truncate_blocks(inode);
- inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_mtime = inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);
out:
UFSD("EXIT: err %d\n", err);
@@ -1208,7 +1208,7 @@ int ufs_setattr(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);
if (error)
return error;
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index a1559f762805..8eca4eda8450 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -153,7 +153,7 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
struct inode *inode = d_inode(old_dentry);
int error;
- inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_ctime = current_time(inode);
inode_inc_link_count(inode);
ihold(inode);
@@ -245,7 +245,8 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
}
static int ufs_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 = d_inode(old_dentry);
struct inode *new_inode = d_inode(new_dentry);
@@ -255,6 +256,9 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct ufs_dir_entry *old_de;
int err = -ENOENT;
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_page);
if (!old_de)
goto out;
@@ -279,7 +283,7 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (!new_de)
goto out_dir;
ufs_set_link(new_dir, new_de, new_page, old_inode, 1);
- new_inode->i_ctime = CURRENT_TIME_SEC;
+ new_inode->i_ctime = current_time(new_inode);
if (dir_de)
drop_nlink(new_inode);
inode_dec_link_count(new_inode);
@@ -295,7 +299,7 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
* Like most other Unix systems, set the ctime for inodes on a
* rename.
*/
- old_inode->i_ctime = CURRENT_TIME_SEC;
+ old_inode->i_ctime = current_time(old_inode);
ufs_delete_entry(old_dir, old_de, old_page);
mark_inode_dirty(old_inode);
diff --git a/fs/utimes.c b/fs/utimes.c
index 794f5f5b1fb5..22307cdf7014 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -81,27 +81,13 @@ static int utimes_common(struct path *path, struct timespec *times)
newattrs.ia_valid |= ATTR_MTIME_SET;
}
/*
- * Tell inode_change_ok(), that this is an explicit time
+ * Tell setattr_prepare(), that this is an explicit time
* update, even if neither ATTR_ATIME_SET nor ATTR_MTIME_SET
* were used.
*/
newattrs.ia_valid |= ATTR_TIMES_SET;
} else {
- /*
- * If times is NULL (or both times are UTIME_NOW),
- * then we need to check permissions, because
- * inode_change_ok() won't do it.
- */
- error = -EPERM;
- if (IS_IMMUTABLE(inode))
- goto mnt_drop_write_and_out;
-
- error = -EACCES;
- if (!inode_owner_or_capable(inode)) {
- error = inode_permission(inode, MAY_WRITE);
- if (error)
- goto mnt_drop_write_and_out;
- }
+ newattrs.ia_valid |= ATTR_TOUCH;
}
retry_deleg:
inode_lock(inode);
@@ -113,7 +99,6 @@ retry_deleg:
goto retry_deleg;
}
-mnt_drop_write_and_out:
mnt_drop_write(path->mnt);
out:
return error;
diff --git a/fs/xattr.c b/fs/xattr.c
index c243905835ab..3368659c471e 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -24,6 +24,59 @@
#include <asm/uaccess.h>
+static const char *
+strcmp_prefix(const char *a, const char *a_prefix)
+{
+ while (*a_prefix && *a == *a_prefix) {
+ a++;
+ a_prefix++;
+ }
+ return *a_prefix ? NULL : a;
+}
+
+/*
+ * In order to implement different sets of xattr operations for each xattr
+ * prefix, a filesystem should create a null-terminated array of struct
+ * xattr_handler (one for each prefix) and hang a pointer to it off of the
+ * s_xattr field of the superblock.
+ */
+#define for_each_xattr_handler(handlers, handler) \
+ if (handlers) \
+ for ((handler) = *(handlers)++; \
+ (handler) != NULL; \
+ (handler) = *(handlers)++)
+
+/*
+ * Find the xattr_handler with the matching prefix.
+ */
+static const struct xattr_handler *
+xattr_resolve_name(struct inode *inode, const char **name)
+{
+ const struct xattr_handler **handlers = inode->i_sb->s_xattr;
+ const struct xattr_handler *handler;
+
+ if (!(inode->i_opflags & IOP_XATTR)) {
+ if (unlikely(is_bad_inode(inode)))
+ return ERR_PTR(-EIO);
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+ for_each_xattr_handler(handlers, handler) {
+ const char *n;
+
+ n = strcmp_prefix(*name, xattr_prefix(handler));
+ if (n) {
+ if (!handler->prefix ^ !*n) {
+ if (*n)
+ continue;
+ return ERR_PTR(-EINVAL);
+ }
+ *name = n;
+ return handler;
+ }
+ }
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
/*
* Check permissions for extended attribute access. This is a bit complicated
* because different namespaces have very different rules.
@@ -80,6 +133,23 @@ xattr_permission(struct inode *inode, const char *name, int mask)
return inode_permission(inode, mask);
}
+int
+__vfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
+ const void *value, size_t size, int flags)
+{
+ const struct xattr_handler *handler;
+
+ handler = xattr_resolve_name(inode, &name);
+ if (IS_ERR(handler))
+ return PTR_ERR(handler);
+ if (!handler->set)
+ return -EOPNOTSUPP;
+ if (size == 0)
+ value = ""; /* empty EA, do not remove */
+ return handler->set(handler, dentry, inode, name, value, size, flags);
+}
+EXPORT_SYMBOL(__vfs_setxattr);
+
/**
* __vfs_setxattr_noperm - perform setxattr operation without performing
* permission checks.
@@ -106,8 +176,8 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
if (issec)
inode->i_flags &= ~S_NOSEC;
- if (inode->i_op->setxattr) {
- error = inode->i_op->setxattr(dentry, inode, name, value, size, flags);
+ if (inode->i_opflags & IOP_XATTR) {
+ error = __vfs_setxattr(dentry, inode, name, value, size, flags);
if (!error) {
fsnotify_xattr(dentry);
security_inode_post_setxattr(dentry, name, value,
@@ -115,6 +185,9 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
}
} else if (issec) {
const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
+
+ if (unlikely(is_bad_inode(inode)))
+ return -EIO;
error = security_inode_setsecurity(inode, suffix, value,
size, flags);
if (!error)
@@ -188,6 +261,7 @@ ssize_t
vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
size_t xattr_size, gfp_t flags)
{
+ const struct xattr_handler *handler;
struct inode *inode = dentry->d_inode;
char *value = *xattr_value;
int error;
@@ -196,10 +270,12 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
if (error)
return error;
- if (!inode->i_op->getxattr)
+ handler = xattr_resolve_name(inode, &name);
+ if (IS_ERR(handler))
+ return PTR_ERR(handler);
+ if (!handler->get)
return -EOPNOTSUPP;
-
- error = inode->i_op->getxattr(dentry, inode, name, NULL, 0);
+ error = handler->get(handler, dentry, inode, name, NULL, 0);
if (error < 0)
return error;
@@ -210,12 +286,27 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
memset(value, 0, error + 1);
}
- error = inode->i_op->getxattr(dentry, inode, name, value, error);
+ error = handler->get(handler, dentry, inode, name, value, error);
*xattr_value = value;
return error;
}
ssize_t
+__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
+ void *value, size_t size)
+{
+ const struct xattr_handler *handler;
+
+ handler = xattr_resolve_name(inode, &name);
+ if (IS_ERR(handler))
+ return PTR_ERR(handler);
+ if (!handler->get)
+ return -EOPNOTSUPP;
+ return handler->get(handler, dentry, inode, name, value, size);
+}
+EXPORT_SYMBOL(__vfs_getxattr);
+
+ssize_t
vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
{
struct inode *inode = dentry->d_inode;
@@ -242,28 +333,24 @@ vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
return ret;
}
nolsm:
- if (inode->i_op->getxattr)
- error = inode->i_op->getxattr(dentry, inode, name, value, size);
- else
- error = -EOPNOTSUPP;
-
- return error;
+ return __vfs_getxattr(dentry, inode, name, value, size);
}
EXPORT_SYMBOL_GPL(vfs_getxattr);
ssize_t
-vfs_listxattr(struct dentry *d, char *list, size_t size)
+vfs_listxattr(struct dentry *dentry, char *list, size_t size)
{
+ struct inode *inode = d_inode(dentry);
ssize_t error;
- error = security_inode_listxattr(d);
+ error = security_inode_listxattr(dentry);
if (error)
return error;
- error = -EOPNOTSUPP;
- if (d->d_inode->i_op->listxattr) {
- error = d->d_inode->i_op->listxattr(d, list, size);
+ if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
+ error = -EOPNOTSUPP;
+ error = inode->i_op->listxattr(dentry, list, size);
} else {
- error = security_inode_listsecurity(d->d_inode, list, size);
+ error = security_inode_listsecurity(inode, list, size);
if (size && error > size)
error = -ERANGE;
}
@@ -272,14 +359,26 @@ vfs_listxattr(struct dentry *d, char *list, size_t size)
EXPORT_SYMBOL_GPL(vfs_listxattr);
int
+__vfs_removexattr(struct dentry *dentry, const char *name)
+{
+ struct inode *inode = d_inode(dentry);
+ const struct xattr_handler *handler;
+
+ handler = xattr_resolve_name(inode, &name);
+ if (IS_ERR(handler))
+ return PTR_ERR(handler);
+ if (!handler->set)
+ return -EOPNOTSUPP;
+ return handler->set(handler, dentry, inode, name, NULL, 0, XATTR_REPLACE);
+}
+EXPORT_SYMBOL(__vfs_removexattr);
+
+int
vfs_removexattr(struct dentry *dentry, const char *name)
{
struct inode *inode = dentry->d_inode;
int error;
- if (!inode->i_op->removexattr)
- return -EOPNOTSUPP;
-
error = xattr_permission(inode, name, MAY_WRITE);
if (error)
return error;
@@ -289,7 +388,7 @@ vfs_removexattr(struct dentry *dentry, const char *name)
if (error)
goto out;
- error = inode->i_op->removexattr(dentry, name);
+ error = __vfs_removexattr(dentry, name);
if (!error) {
fsnotify_xattr(dentry);
@@ -641,76 +740,6 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
return error;
}
-
-static const char *
-strcmp_prefix(const char *a, const char *a_prefix)
-{
- while (*a_prefix && *a == *a_prefix) {
- a++;
- a_prefix++;
- }
- return *a_prefix ? NULL : a;
-}
-
-/*
- * In order to implement different sets of xattr operations for each xattr
- * prefix with the generic xattr API, a filesystem should create a
- * null-terminated array of struct xattr_handler (one for each prefix) and
- * hang a pointer to it off of the s_xattr field of the superblock.
- *
- * The generic_fooxattr() functions will use this list to dispatch xattr
- * operations to the correct xattr_handler.
- */
-#define for_each_xattr_handler(handlers, handler) \
- if (handlers) \
- for ((handler) = *(handlers)++; \
- (handler) != NULL; \
- (handler) = *(handlers)++)
-
-/*
- * Find the xattr_handler with the matching prefix.
- */
-static const struct xattr_handler *
-xattr_resolve_name(const struct xattr_handler **handlers, const char **name)
-{
- const struct xattr_handler *handler;
-
- if (!*name)
- return ERR_PTR(-EINVAL);
-
- for_each_xattr_handler(handlers, handler) {
- const char *n;
-
- n = strcmp_prefix(*name, xattr_prefix(handler));
- if (n) {
- if (!handler->prefix ^ !*n) {
- if (*n)
- continue;
- return ERR_PTR(-EINVAL);
- }
- *name = n;
- return handler;
- }
- }
- return ERR_PTR(-EOPNOTSUPP);
-}
-
-/*
- * Find the handler for the prefix and dispatch its get() operation.
- */
-ssize_t
-generic_getxattr(struct dentry *dentry, struct inode *inode,
- const char *name, void *buffer, size_t size)
-{
- const struct xattr_handler *handler;
-
- handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
- if (IS_ERR(handler))
- return PTR_ERR(handler);
- return handler->get(handler, dentry, inode,
- name, buffer, size);
-}
-
/*
* Combine the results of the list() operation from every xattr_handler in the
* list.
@@ -747,44 +776,7 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
}
return size;
}
-
-/*
- * Find the handler for the prefix and dispatch its set() operation.
- */
-int
-generic_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
- const void *value, size_t size, int flags)
-{
- const struct xattr_handler *handler;
-
- if (size == 0)
- value = ""; /* empty EA, do not remove */
- handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
- if (IS_ERR(handler))
- return PTR_ERR(handler);
- return handler->set(handler, dentry, inode, name, value, size, flags);
-}
-
-/*
- * Find the handler for the prefix and dispatch its set() operation to remove
- * any associated extended attribute.
- */
-int
-generic_removexattr(struct dentry *dentry, const char *name)
-{
- const struct xattr_handler *handler;
-
- handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
- if (IS_ERR(handler))
- return PTR_ERR(handler);
- return handler->set(handler, dentry, d_inode(dentry), name, NULL,
- 0, XATTR_REPLACE);
-}
-
-EXPORT_SYMBOL(generic_getxattr);
EXPORT_SYMBOL(generic_listxattr);
-EXPORT_SYMBOL(generic_setxattr);
-EXPORT_SYMBOL(generic_removexattr);
/**
* xattr_full_name - Compute full attribute name from suffix
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index b6e527b8eccb..b468e041f207 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -236,7 +236,7 @@ xfs_set_mode(struct inode *inode, umode_t mode)
iattr.ia_valid = ATTR_MODE | ATTR_CTIME;
iattr.ia_mode = mode;
- iattr.ia_ctime = current_fs_time(inode->i_sb);
+ iattr.ia_ctime = current_time(inode);
error = xfs_setattr_nonsize(XFS_I(inode), &iattr, XFS_ATTR_NOACL);
}
@@ -257,16 +257,11 @@ xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
return error;
if (type == ACL_TYPE_ACCESS) {
- umode_t mode = inode->i_mode;
- error = posix_acl_equiv_mode(acl, &mode);
-
- if (error <= 0) {
- acl = NULL;
-
- if (error < 0)
- return error;
- }
+ umode_t mode;
+ error = posix_acl_update_mode(inode, &mode, &acl);
+ if (error)
+ return error;
error = xfs_set_mode(inode, mode);
if (error)
return error;
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 26acfbb331ae..2bc58b3fd37d 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -319,7 +319,7 @@ xfs_file_dio_aio_read(
data = *to;
ret = __blockdev_direct_IO(iocb, inode, target->bt_bdev, &data,
xfs_get_blocks_direct, NULL, NULL, 0);
- if (ret > 0) {
+ if (ret >= 0) {
iocb->ki_pos += ret;
iov_iter_advance(to, ret);
}
@@ -901,7 +901,7 @@ xfs_file_fallocate(
iattr.ia_valid = ATTR_SIZE;
iattr.ia_size = new_size;
- error = xfs_setattr_size(ip, &iattr);
+ error = xfs_vn_setattr_size(file_dentry(file), &iattr);
if (error)
goto out_unlock;
}
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index e08eaea6327b..624e1dfa716b 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -821,7 +821,7 @@ xfs_ialloc(
ip->i_d.di_nextents = 0;
ASSERT(ip->i_d.di_nblocks == 0);
- tv = current_fs_time(mp->m_super);
+ tv = current_time(inode);
inode->i_mtime = tv;
inode->i_atime = tv;
inode->i_ctime = tv;
@@ -1710,7 +1710,7 @@ xfs_inactive_truncate(
/*
* Log the inode size first to prevent stale data exposure in the event
* of a system crash before the truncate completes. See the related
- * comment in xfs_setattr_size() for details.
+ * comment in xfs_vn_setattr_size() for details.
*/
ip->i_d.di_size = 0;
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 96a70fd1f5d6..0d9021f0551e 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -720,7 +720,7 @@ xfs_ioc_space(
iattr.ia_valid = ATTR_SIZE;
iattr.ia_size = bf->l_start;
- error = xfs_setattr_size(ip, &iattr);
+ error = xfs_vn_setattr_size(file_dentry(filp), &iattr);
break;
default:
ASSERT(0);
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index b24c3102fa93..c5da95eb79b8 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -542,6 +542,28 @@ xfs_setattr_time(
inode->i_mtime = iattr->ia_mtime;
}
+static int
+xfs_vn_change_ok(
+ struct dentry *dentry,
+ struct iattr *iattr)
+{
+ struct xfs_mount *mp = XFS_I(d_inode(dentry))->i_mount;
+
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
+ return -EROFS;
+
+ if (XFS_FORCED_SHUTDOWN(mp))
+ return -EIO;
+
+ return setattr_prepare(dentry, iattr);
+}
+
+/*
+ * Set non-size attributes of an inode.
+ *
+ * Caution: The caller of this function is responsible for calling
+ * setattr_prepare() or otherwise verifying the change is fine.
+ */
int
xfs_setattr_nonsize(
struct xfs_inode *ip,
@@ -558,21 +580,6 @@ xfs_setattr_nonsize(
struct xfs_dquot *udqp = NULL, *gdqp = NULL;
struct xfs_dquot *olddquot1 = NULL, *olddquot2 = NULL;
- trace_xfs_setattr(ip);
-
- /* If acls are being inherited, we already have this checked */
- if (!(flags & XFS_ATTR_NOACL)) {
- if (mp->m_flags & XFS_MOUNT_RDONLY)
- return -EROFS;
-
- if (XFS_FORCED_SHUTDOWN(mp))
- return -EIO;
-
- error = inode_change_ok(inode, iattr);
- if (error)
- return error;
- }
-
ASSERT((mask & ATTR_SIZE) == 0);
/*
@@ -743,8 +750,27 @@ out_dqrele:
return error;
}
+int
+xfs_vn_setattr_nonsize(
+ struct dentry *dentry,
+ struct iattr *iattr)
+{
+ struct xfs_inode *ip = XFS_I(d_inode(dentry));
+ int error;
+
+ trace_xfs_setattr(ip);
+
+ error = xfs_vn_change_ok(dentry, iattr);
+ if (error)
+ return error;
+ return xfs_setattr_nonsize(ip, iattr, 0);
+}
+
/*
* Truncate file. Must have write permission and not be a directory.
+ *
+ * Caution: The caller of this function is responsible for calling
+ * setattr_prepare() or otherwise verifying the change is fine.
*/
int
xfs_setattr_size(
@@ -759,18 +785,6 @@ xfs_setattr_size(
uint lock_flags = 0;
bool did_zeroing = false;
- trace_xfs_setattr(ip);
-
- if (mp->m_flags & XFS_MOUNT_RDONLY)
- return -EROFS;
-
- if (XFS_FORCED_SHUTDOWN(mp))
- return -EIO;
-
- error = inode_change_ok(inode, iattr);
- if (error)
- return error;
-
ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
ASSERT(xfs_isilocked(ip, XFS_MMAPLOCK_EXCL));
ASSERT(S_ISREG(inode->i_mode));
@@ -882,7 +896,7 @@ xfs_setattr_size(
if (newsize != oldsize &&
!(iattr->ia_valid & (ATTR_CTIME | ATTR_MTIME))) {
iattr->ia_ctime = iattr->ia_mtime =
- current_fs_time(inode->i_sb);
+ current_time(inode);
iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME;
}
@@ -942,16 +956,32 @@ out_trans_cancel:
goto out_unlock;
}
+int
+xfs_vn_setattr_size(
+ struct dentry *dentry,
+ struct iattr *iattr)
+{
+ struct xfs_inode *ip = XFS_I(d_inode(dentry));
+ int error;
+
+ trace_xfs_setattr(ip);
+
+ error = xfs_vn_change_ok(dentry, iattr);
+ if (error)
+ return error;
+ return xfs_setattr_size(ip, iattr);
+}
+
STATIC int
xfs_vn_setattr(
struct dentry *dentry,
struct iattr *iattr)
{
- struct xfs_inode *ip = XFS_I(d_inode(dentry));
int error;
if (iattr->ia_valid & ATTR_SIZE) {
- uint iolock = XFS_IOLOCK_EXCL;
+ struct xfs_inode *ip = XFS_I(d_inode(dentry));
+ uint iolock = XFS_IOLOCK_EXCL;
xfs_ilock(ip, iolock);
error = xfs_break_layouts(d_inode(dentry), &iolock, true);
@@ -959,11 +989,11 @@ xfs_vn_setattr(
xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
iolock |= XFS_MMAPLOCK_EXCL;
- error = xfs_setattr_size(ip, iattr);
+ error = xfs_vn_setattr_size(dentry, iattr);
}
xfs_iunlock(ip, iolock);
} else {
- error = xfs_setattr_nonsize(ip, iattr, 0);
+ error = xfs_vn_setattr_nonsize(dentry, iattr);
}
return error;
@@ -1036,9 +1066,6 @@ static const struct inode_operations xfs_inode_operations = {
.set_acl = xfs_set_acl,
.getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr,
.fiemap = xfs_vn_fiemap,
.update_time = xfs_vn_update_time,
@@ -1059,14 +1086,11 @@ static const struct inode_operations xfs_dir_inode_operations = {
*/
.rmdir = xfs_vn_unlink,
.mknod = xfs_vn_mknod,
- .rename2 = xfs_vn_rename,
+ .rename = xfs_vn_rename,
.get_acl = xfs_get_acl,
.set_acl = xfs_set_acl,
.getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr,
.update_time = xfs_vn_update_time,
.tmpfile = xfs_vn_tmpfile,
@@ -1087,14 +1111,11 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
*/
.rmdir = xfs_vn_unlink,
.mknod = xfs_vn_mknod,
- .rename2 = xfs_vn_rename,
+ .rename = xfs_vn_rename,
.get_acl = xfs_get_acl,
.set_acl = xfs_set_acl,
.getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr,
.update_time = xfs_vn_update_time,
.tmpfile = xfs_vn_tmpfile,
@@ -1105,9 +1126,6 @@ static const struct inode_operations xfs_symlink_inode_operations = {
.get_link = xfs_vn_get_link,
.getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr,
.update_time = xfs_vn_update_time,
};
@@ -1117,9 +1135,6 @@ static const struct inode_operations xfs_inline_symlink_inode_operations = {
.get_link = xfs_vn_get_link_inline,
.getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
- .removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr,
.update_time = xfs_vn_update_time,
};
diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h
index a0f84abb0d09..0259a383721a 100644
--- a/fs/xfs/xfs_iops.h
+++ b/fs/xfs/xfs_iops.h
@@ -33,6 +33,7 @@ extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size);
extern void xfs_setattr_time(struct xfs_inode *ip, struct iattr *iattr);
extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap,
int flags);
-extern int xfs_setattr_size(struct xfs_inode *ip, struct iattr *vap);
+extern int xfs_vn_setattr_nonsize(struct dentry *dentry, struct iattr *vap);
+extern int xfs_vn_setattr_size(struct dentry *dentry, struct iattr *vap);
#endif /* __XFS_IOPS_H__ */
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index 11a3af08b5c7..dab8daa676f9 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -73,7 +73,7 @@ xfs_trans_ichgtime(
ASSERT(tp);
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
- tv = current_fs_time(inode->i_sb);
+ tv = current_time(inode);
if (flags & XFS_ICHGTIME_MOD)
inode->i_mtime = tv;