aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/vfs_file.c4
-rw-r--r--fs/9p/vfs_inode.c23
-rw-r--r--fs/9p/vfs_super.c4
-rw-r--r--fs/Kconfig8
-rw-r--r--fs/adfs/adfs.h4
-rw-r--r--fs/adfs/dir.c2
-rw-r--r--fs/adfs/file.c2
-rw-r--r--fs/adfs/super.c2
-rw-r--r--fs/affs/affs.h6
-rw-r--r--fs/affs/dir.c2
-rw-r--r--fs/affs/file.c2
-rw-r--r--fs/affs/inode.c2
-rw-r--r--fs/affs/super.c2
-rw-r--r--fs/affs/symlink.c2
-rw-r--r--fs/afs/dir.c2
-rw-r--r--fs/afs/file.c2
-rw-r--r--fs/afs/internal.h6
-rw-r--r--fs/afs/mntpt.c2
-rw-r--r--fs/afs/super.c2
-rw-r--r--fs/aio.c5
-rw-r--r--fs/autofs/autofs_i.h4
-rw-r--r--fs/autofs/inode.c2
-rw-r--r--fs/autofs/root.c2
-rw-r--r--fs/autofs/symlink.c2
-rw-r--r--fs/autofs4/autofs_i.h10
-rw-r--r--fs/autofs4/inode.c2
-rw-r--r--fs/autofs4/root.c6
-rw-r--r--fs/autofs4/symlink.c2
-rw-r--r--fs/bad_inode.c2
-rw-r--r--fs/befs/linuxvfs.c4
-rw-r--r--fs/bfs/bfs.h4
-rw-r--r--fs/bfs/dir.c2
-rw-r--r--fs/bfs/file.c2
-rw-r--r--fs/bfs/inode.c2
-rw-r--r--fs/binfmt_elf_fdpic.c2
-rw-r--r--fs/binfmt_flat.c31
-rw-r--r--fs/binfmt_misc.c2
-rw-r--r--fs/block_dev.c2
-rw-r--r--fs/buffer.c19
-rw-r--r--fs/char_dev.c7
-rw-r--r--fs/cifs/cifsfs.c10
-rw-r--r--fs/cifs/cifsfs.h8
-rw-r--r--fs/coda/cnode.c2
-rw-r--r--fs/coda/dir.c2
-rw-r--r--fs/coda/inode.c4
-rw-r--r--fs/coda/pioctl.c2
-rw-r--r--fs/coda/sysctl.c76
-rw-r--r--fs/configfs/configfs_internal.h4
-rw-r--r--fs/configfs/dir.c5
-rw-r--r--fs/configfs/inode.c2
-rw-r--r--fs/configfs/mount.c2
-rw-r--r--fs/configfs/symlink.c2
-rw-r--r--fs/cramfs/inode.c8
-rw-r--r--fs/dcache.c150
-rw-r--r--fs/debugfs/file.c2
-rw-r--r--fs/devpts/inode.c2
-rw-r--r--fs/dlm/debug_fs.c4
-rw-r--r--fs/dlm/lowcomms-tcp.c23
-rw-r--r--fs/dlm/memory.c4
-rw-r--r--fs/dlm/user.c6
-rw-r--r--fs/dquot.c59
-rw-r--r--fs/drop_caches.c2
-rw-r--r--fs/ecryptfs/Makefile2
-rw-r--r--fs/ecryptfs/crypto.c337
-rw-r--r--fs/ecryptfs/debug.c6
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h161
-rw-r--r--fs/ecryptfs/file.c52
-rw-r--r--fs/ecryptfs/inode.c93
-rw-r--r--fs/ecryptfs/keystore.c802
-rw-r--r--fs/ecryptfs/main.c82
-rw-r--r--fs/ecryptfs/messaging.c515
-rw-r--r--fs/ecryptfs/mmap.c378
-rw-r--r--fs/ecryptfs/netlink.c255
-rw-r--r--fs/ecryptfs/super.c2
-rw-r--r--fs/efs/dir.c2
-rw-r--r--fs/efs/super.c2
-rw-r--r--fs/exec.c4
-rw-r--r--fs/ext2/dir.c8
-rw-r--r--fs/ext2/ext2.h10
-rw-r--r--fs/ext2/file.c2
-rw-r--r--fs/ext2/namei.c4
-rw-r--r--fs/ext2/super.c6
-rw-r--r--fs/ext2/symlink.c4
-rw-r--r--fs/ext3/file.c2
-rw-r--r--fs/ext3/inode.c4
-rw-r--r--fs/ext3/namei.c31
-rw-r--r--fs/ext3/super.c22
-rw-r--r--fs/ext3/symlink.c4
-rw-r--r--fs/ext4/file.c2
-rw-r--r--fs/ext4/inode.c4
-rw-r--r--fs/ext4/namei.c31
-rw-r--r--fs/ext4/super.c22
-rw-r--r--fs/ext4/symlink.c4
-rw-r--r--fs/fat/file.c2
-rw-r--r--fs/fat/inode.c4
-rw-r--r--fs/freevxfs/vxfs_extern.h2
-rw-r--r--fs/freevxfs/vxfs_immed.c2
-rw-r--r--fs/freevxfs/vxfs_inode.c2
-rw-r--r--fs/freevxfs/vxfs_lookup.c2
-rw-r--r--fs/freevxfs/vxfs_super.c2
-rw-r--r--fs/fuse/control.c2
-rw-r--r--fs/fuse/dir.c6
-rw-r--r--fs/fuse/file.c2
-rw-r--r--fs/fuse/inode.c4
-rw-r--r--fs/gfs2/locking/dlm/plock.c2
-rw-r--r--fs/gfs2/meta_io.c3
-rw-r--r--fs/gfs2/ops_inode.c8
-rw-r--r--fs/gfs2/ops_inode.h8
-rw-r--r--fs/gfs2/ops_super.c2
-rw-r--r--fs/gfs2/ops_super.h2
-rw-r--r--fs/hfs/dir.c2
-rw-r--r--fs/hfs/hfs.h2
-rw-r--r--fs/hfs/hfs_fs.h2
-rw-r--r--fs/hfs/inode.c4
-rw-r--r--fs/hfs/super.c2
-rw-r--r--fs/hfsplus/dir.c2
-rw-r--r--fs/hfsplus/hfsplus_raw.h2
-rw-r--r--fs/hfsplus/inode.c4
-rw-r--r--fs/hfsplus/super.c2
-rw-r--r--fs/hostfs/hostfs_kern.c10
-rw-r--r--fs/hpfs/file.c2
-rw-r--r--fs/hpfs/hpfs_fn.h4
-rw-r--r--fs/hpfs/namei.c2
-rw-r--r--fs/hpfs/super.c2
-rw-r--r--fs/hppfs/hppfs_kern.c10
-rw-r--r--fs/hugetlbfs/inode.c17
-rw-r--r--fs/inode.c42
-rw-r--r--fs/inotify_user.c10
-rw-r--r--fs/ioprio.c18
-rw-r--r--fs/isofs/dir.c2
-rw-r--r--fs/isofs/inode.c2
-rw-r--r--fs/isofs/isofs.h2
-rw-r--r--fs/jffs/inode-v23.c16
-rw-r--r--fs/jffs2/dir.c2
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jffs2/os-linux.h6
-rw-r--r--fs/jffs2/super.c2
-rw-r--r--fs/jffs2/symlink.c2
-rw-r--r--fs/jfs/file.c2
-rw-r--r--fs/jfs/jfs_inode.h6
-rw-r--r--fs/jfs/namei.c2
-rw-r--r--fs/jfs/super.c4
-rw-r--r--fs/jfs/symlink.c2
-rw-r--r--fs/libfs.c6
-rw-r--r--fs/lockd/host.c2
-rw-r--r--fs/lockd/svc.c32
-rw-r--r--fs/lockd/svc4proc.c13
-rw-r--r--fs/lockd/svcproc.c13
-rw-r--r--fs/minix/bitmap.c69
-rw-r--r--fs/minix/dir.c162
-rw-r--r--fs/minix/file.c2
-rw-r--r--fs/minix/inode.c53
-rw-r--r--fs/minix/itree_common.c16
-rw-r--r--fs/minix/itree_v1.c4
-rw-r--r--fs/minix/itree_v2.c7
-rw-r--r--fs/minix/minix.h16
-rw-r--r--fs/minix/namei.c2
-rw-r--r--fs/msdos/namei.c2
-rw-r--r--fs/namei.c2
-rw-r--r--fs/namespace.c3
-rw-r--r--fs/ncpfs/dir.c2
-rw-r--r--fs/ncpfs/file.c2
-rw-r--r--fs/ncpfs/inode.c4
-rw-r--r--fs/nfs/callback.c34
-rw-r--r--fs/nfs/callback_xdr.c4
-rw-r--r--fs/nfs/client.c4
-rw-r--r--fs/nfs/dir.c6
-rw-r--r--fs/nfs/file.c4
-rw-r--r--fs/nfs/namespace.c4
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4proc.c2
-rw-r--r--fs/nfs/super.c5
-rw-r--r--fs/nfs/symlink.c2
-rw-r--r--fs/nfsd/nfs4state.c18
-rw-r--r--fs/nfsd/nfscache.c2
-rw-r--r--fs/nfsd/nfsfh.c7
-rw-r--r--fs/nfsd/nfsproc.c7
-rw-r--r--fs/nfsd/nfssvc.c6
-rw-r--r--fs/ntfs/attrib.c2
-rw-r--r--fs/ntfs/file.c4
-rw-r--r--fs/ntfs/namei.c2
-rw-r--r--fs/ntfs/ntfs.h6
-rw-r--r--fs/ntfs/super.c2
-rw-r--r--fs/ocfs2/dlm/dlmfs.c20
-rw-r--r--fs/ocfs2/file.c4
-rw-r--r--fs/ocfs2/file.h4
-rw-r--r--fs/ocfs2/namei.c2
-rw-r--r--fs/ocfs2/namei.h2
-rw-r--r--fs/ocfs2/super.c2
-rw-r--r--fs/ocfs2/symlink.c4
-rw-r--r--fs/ocfs2/symlink.h4
-rw-r--r--fs/openpromfs/inode.c4
-rw-r--r--fs/partitions/check.c15
-rw-r--r--fs/partitions/msdos.c22
-rw-r--r--fs/partitions/sgi.c2
-rw-r--r--fs/partitions/sun.c5
-rw-r--r--fs/proc/array.c2
-rw-r--r--fs/proc/base.c56
-rw-r--r--fs/proc/generic.c10
-rw-r--r--fs/proc/inode.c2
-rw-r--r--fs/proc/internal.h12
-rw-r--r--fs/proc/nommu.c2
-rw-r--r--fs/proc/proc_misc.c54
-rw-r--r--fs/proc/proc_tty.c2
-rw-r--r--fs/proc/root.c4
-rw-r--r--fs/proc/task_mmu.c6
-rw-r--r--fs/proc/task_nommu.c2
-rw-r--r--fs/qnx4/dir.c2
-rw-r--r--fs/qnx4/file.c2
-rw-r--r--fs/qnx4/inode.c4
-rw-r--r--fs/ramfs/file-mmu.c4
-rw-r--r--fs/ramfs/file-nommu.c4
-rw-r--r--fs/ramfs/inode.c8
-rw-r--r--fs/ramfs/internal.h2
-rw-r--r--fs/read_write.c26
-rw-r--r--fs/reiserfs/do_balan.c5
-rw-r--r--fs/reiserfs/file.c2
-rw-r--r--fs/reiserfs/namei.c6
-rw-r--r--fs/reiserfs/super.c2
-rw-r--r--fs/romfs/inode.c6
-rw-r--r--fs/smbfs/dir.c4
-rw-r--r--fs/smbfs/file.c2
-rw-r--r--fs/smbfs/inode.c2
-rw-r--r--fs/smbfs/proto.h8
-rw-r--r--fs/smbfs/request.c3
-rw-r--r--fs/smbfs/symlink.c2
-rw-r--r--fs/super.c2
-rw-r--r--fs/sysfs/dir.c5
-rw-r--r--fs/sysfs/inode.c2
-rw-r--r--fs/sysfs/mount.c2
-rw-r--r--fs/sysfs/symlink.c2
-rw-r--r--fs/sysfs/sysfs.h4
-rw-r--r--fs/sysv/file.c2
-rw-r--r--fs/sysv/inode.c4
-rw-r--r--fs/sysv/namei.c2
-rw-r--r--fs/sysv/symlink.c2
-rw-r--r--fs/sysv/sysv.h8
-rw-r--r--fs/udf/file.c2
-rw-r--r--fs/udf/namei.c2
-rw-r--r--fs/udf/super.c2
-rw-r--r--fs/udf/udfdecl.h4
-rw-r--r--fs/ufs/balloc.c197
-rw-r--r--fs/ufs/dir.c21
-rw-r--r--fs/ufs/ialloc.c116
-rw-r--r--fs/ufs/inode.c193
-rw-r--r--fs/ufs/namei.c2
-rw-r--r--fs/ufs/super.c54
-rw-r--r--fs/ufs/symlink.c2
-rw-r--r--fs/ufs/truncate.c141
-rw-r--r--fs/ufs/util.h57
-rw-r--r--fs/vfat/namei.c2
-rw-r--r--fs/xfs/linux-2.6/mrlock.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c18
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c142
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h4
-rw-r--r--fs/xfs/linux-2.6/xfs_export.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c51
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c12
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h10
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c48
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c33
-rw-r--r--fs/xfs/linux-2.6/xfs_sysctl.c266
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h4
-rw-r--r--fs/xfs/quota/xfs_dquot.c4
-rw-r--r--fs/xfs/quota/xfs_dquot_item.c8
-rw-r--r--fs/xfs/quota/xfs_qm.c8
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c4
-rw-r--r--fs/xfs/quota/xfs_qm_stats.c2
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c4
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c2
-rw-r--r--fs/xfs/support/debug.c23
-rw-r--r--fs/xfs/support/debug.h30
-rw-r--r--fs/xfs/support/move.h4
-rw-r--r--fs/xfs/xfs_acl.c1
-rw-r--r--fs/xfs/xfs_alloc_btree.h10
-rw-r--r--fs/xfs/xfs_attr.c49
-rw-r--r--fs/xfs/xfs_attr_leaf.c54
-rw-r--r--fs/xfs/xfs_bit.c2
-rw-r--r--fs/xfs/xfs_bmap.c101
-rw-r--r--fs/xfs/xfs_bmap.h1
-rw-r--r--fs/xfs/xfs_bmap_btree.c86
-rw-r--r--fs/xfs/xfs_bmap_btree.h59
-rw-r--r--fs/xfs/xfs_btree.h6
-rw-r--r--fs/xfs/xfs_buf_item.c2
-rw-r--r--fs/xfs/xfs_buf_item.h18
-rw-r--r--fs/xfs/xfs_cap.h70
-rw-r--r--fs/xfs/xfs_da_btree.c18
-rw-r--r--fs/xfs/xfs_da_btree.h1
-rw-r--r--fs/xfs/xfs_dfrag.c1
-rw-r--r--fs/xfs/xfs_error.c26
-rw-r--r--fs/xfs/xfs_error.h3
-rw-r--r--fs/xfs/xfs_extfree_item.c4
-rw-r--r--fs/xfs/xfs_fsops.c60
-rw-r--r--fs/xfs/xfs_ialloc.c2
-rw-r--r--fs/xfs/xfs_ialloc_btree.h10
-rw-r--r--fs/xfs/xfs_inode.c30
-rw-r--r--fs/xfs/xfs_inode_item.c2
-rw-r--r--fs/xfs/xfs_iomap.c10
-rw-r--r--fs/xfs/xfs_log_recover.c61
-rw-r--r--fs/xfs/xfs_mac.h106
-rw-r--r--fs/xfs/xfs_mount.c288
-rw-r--r--fs/xfs/xfs_mount.h39
-rw-r--r--fs/xfs/xfs_rename.c2
-rw-r--r--fs/xfs/xfs_rtalloc.c110
-rw-r--r--fs/xfs/xfs_rtalloc.h18
-rw-r--r--fs/xfs/xfs_rw.c1
-rw-r--r--fs/xfs/xfs_trans.c32
-rw-r--r--fs/xfs/xfs_trans.h46
-rw-r--r--fs/xfs/xfs_trans_ail.c2
-rw-r--r--fs/xfs/xfs_vfsops.c45
-rw-r--r--fs/xfs/xfs_vnodeops.c22
316 files changed, 4679 insertions, 2792 deletions
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 9f17b0cacdd..6c78343cf69 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -110,7 +110,7 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
filemap_write_and_wait(inode->i_mapping);
- invalidate_inode_pages(&inode->i_data);
+ invalidate_mapping_pages(&inode->i_data, 0, -1);
}
return res;
@@ -234,7 +234,7 @@ v9fs_file_write(struct file *filp, const char __user * data,
total += result;
} while (count);
- invalidate_inode_pages2(inode->i_mapping);
+ invalidate_inode_pages2(inode->i_mapping);
return total;
}
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 9109ba1d696..5cf22134826 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -41,10 +41,10 @@
#include "v9fs_vfs.h"
#include "fid.h"
-static struct inode_operations v9fs_dir_inode_operations;
-static struct inode_operations v9fs_dir_inode_operations_ext;
-static struct inode_operations v9fs_file_inode_operations;
-static struct inode_operations v9fs_symlink_inode_operations;
+static const struct inode_operations v9fs_dir_inode_operations;
+static const struct inode_operations v9fs_dir_inode_operations_ext;
+static const struct inode_operations v9fs_file_inode_operations;
+static const struct inode_operations v9fs_symlink_inode_operations;
/**
* unixmode2p9mode - convert unix mode bits to plan 9
@@ -585,17 +585,14 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
inode = NULL;
- goto clean_up_fids;
+ v9fs_fid_destroy(vfid);
+ goto error;
}
dentry->d_op = &v9fs_dentry_operations;
d_instantiate(dentry, inode);
return 0;
-clean_up_fids:
- if (vfid)
- v9fs_fid_destroy(vfid);
-
clean_up_dfid:
v9fs_fid_clunk(v9ses, dfid);
@@ -1306,7 +1303,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
return retval;
}
-static struct inode_operations v9fs_dir_inode_operations_ext = {
+static const struct inode_operations v9fs_dir_inode_operations_ext = {
.create = v9fs_vfs_create,
.lookup = v9fs_vfs_lookup,
.symlink = v9fs_vfs_symlink,
@@ -1321,7 +1318,7 @@ static struct inode_operations v9fs_dir_inode_operations_ext = {
.setattr = v9fs_vfs_setattr,
};
-static struct inode_operations v9fs_dir_inode_operations = {
+static const struct inode_operations v9fs_dir_inode_operations = {
.create = v9fs_vfs_create,
.lookup = v9fs_vfs_lookup,
.unlink = v9fs_vfs_unlink,
@@ -1333,12 +1330,12 @@ static struct inode_operations v9fs_dir_inode_operations = {
.setattr = v9fs_vfs_setattr,
};
-static struct inode_operations v9fs_file_inode_operations = {
+static const struct inode_operations v9fs_file_inode_operations = {
.getattr = v9fs_vfs_getattr,
.setattr = v9fs_vfs_setattr,
};
-static struct inode_operations v9fs_symlink_inode_operations = {
+static const struct inode_operations v9fs_symlink_inode_operations = {
.readlink = v9fs_vfs_readlink,
.follow_link = v9fs_vfs_follow_link,
.put_link = v9fs_vfs_put_link,
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 63320d4e15d..0ec42f66545 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -45,7 +45,7 @@
#include "fid.h"
static void v9fs_clear_inode(struct inode *);
-static struct super_operations v9fs_super_ops;
+static const struct super_operations v9fs_super_ops;
/**
* v9fs_clear_inode - release an inode
@@ -263,7 +263,7 @@ v9fs_umount_begin(struct vfsmount *vfsmnt, int flags)
v9fs_session_cancel(v9ses);
}
-static struct super_operations v9fs_super_ops = {
+static const struct super_operations v9fs_super_ops = {
.statfs = simple_statfs,
.clear_inode = v9fs_clear_inode,
.show_options = v9fs_show_options,
diff --git a/fs/Kconfig b/fs/Kconfig
index 5e8e9d9ccb3..488521ed9e9 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -674,12 +674,6 @@ config ZISOFS
necessary to create such a filesystem. Say Y here if you want to be
able to read such compressed CD-ROMs.
-config ZISOFS_FS
-# for fs/nls/Config.in
- tristate
- depends on ZISOFS
- default ISO9660_FS
-
config UDF_FS
tristate "UDF file system support"
help
@@ -1094,7 +1088,7 @@ config AFFS_FS
config ECRYPT_FS
tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && KEYS && CRYPTO
+ depends on EXPERIMENTAL && KEYS && CRYPTO && NET
help
Encrypted filesystem that operates on the VFS layer. See
<file:Documentation/ecryptfs.txt> to learn more about
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h
index 29217ff36d4..936f2af39c4 100644
--- a/fs/adfs/adfs.h
+++ b/fs/adfs/adfs.h
@@ -84,7 +84,7 @@ void __adfs_error(struct super_block *sb, const char *function,
*/
/* dir_*.c */
-extern struct inode_operations adfs_dir_inode_operations;
+extern const struct inode_operations adfs_dir_inode_operations;
extern const struct file_operations adfs_dir_operations;
extern struct dentry_operations adfs_dentry_operations;
extern struct adfs_dir_ops adfs_f_dir_ops;
@@ -93,7 +93,7 @@ extern struct adfs_dir_ops adfs_fplus_dir_ops;
extern int adfs_dir_update(struct super_block *sb, struct object_info *obj);
/* file.c */
-extern struct inode_operations adfs_file_inode_operations;
+extern const struct inode_operations adfs_file_inode_operations;
extern const struct file_operations adfs_file_operations;
static inline __u32 signed_asl(__u32 val, signed int shift)
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index 2b8903893d3..fc1a8dc64d7 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -295,7 +295,7 @@ adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
/*
* directories can handle most operations...
*/
-struct inode_operations adfs_dir_inode_operations = {
+const struct inode_operations adfs_dir_inode_operations = {
.lookup = adfs_lookup,
.setattr = adfs_notify_change,
};
diff --git a/fs/adfs/file.c b/fs/adfs/file.c
index 6101ea679cb..f544a285592 100644
--- a/fs/adfs/file.c
+++ b/fs/adfs/file.c
@@ -36,6 +36,6 @@ const struct file_operations adfs_file_operations = {
.sendfile = generic_file_sendfile,
};
-struct inode_operations adfs_file_inode_operations = {
+const struct inode_operations adfs_file_inode_operations = {
.setattr = adfs_notify_change,
};
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index 5023351a7af..2e5f2c8371e 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -254,7 +254,7 @@ static void destroy_inodecache(void)
kmem_cache_destroy(adfs_inode_cachep);
}
-static struct super_operations adfs_sops = {
+static const struct super_operations adfs_sops = {
.alloc_inode = adfs_alloc_inode,
.destroy_inode = adfs_destroy_inode,
.write_inode = adfs_write_inode,
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index 1dc8438ef38..7db2d287e9f 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -188,9 +188,9 @@ extern void affs_dir_truncate(struct inode *);
/* jump tables */
-extern struct inode_operations affs_file_inode_operations;
-extern struct inode_operations affs_dir_inode_operations;
-extern struct inode_operations affs_symlink_inode_operations;
+extern const struct inode_operations affs_file_inode_operations;
+extern const struct inode_operations affs_dir_inode_operations;
+extern const struct inode_operations affs_symlink_inode_operations;
extern const struct file_operations affs_file_operations;
extern const struct file_operations affs_file_operations_ofs;
extern const struct file_operations affs_dir_operations;
diff --git a/fs/affs/dir.c b/fs/affs/dir.c
index cad3ee34006..6e3f282424b 100644
--- a/fs/affs/dir.c
+++ b/fs/affs/dir.c
@@ -26,7 +26,7 @@ const struct file_operations affs_dir_operations = {
/*
* directories can handle most operations...
*/
-struct inode_operations affs_dir_inode_operations = {
+const struct inode_operations affs_dir_inode_operations = {
.create = affs_create,
.lookup = affs_lookup,
.link = affs_link,
diff --git a/fs/affs/file.c b/fs/affs/file.c
index 05b5e22de75..4aa8079e71b 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -38,7 +38,7 @@ const struct file_operations affs_file_operations = {
.sendfile = generic_file_sendfile,
};
-struct inode_operations affs_file_inode_operations = {
+const struct inode_operations affs_file_inode_operations = {
.truncate = affs_truncate,
.setattr = affs_notify_change,
};
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 44d439cb69f..fce6848a464 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -12,7 +12,7 @@
#include "affs.h"
-extern struct inode_operations affs_symlink_inode_operations;
+extern const struct inode_operations affs_symlink_inode_operations;
extern struct timezone sys_tz;
void
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 3de93e79994..a324045d855 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -112,7 +112,7 @@ static void destroy_inodecache(void)
kmem_cache_destroy(affs_inode_cachep);
}
-static struct super_operations affs_sops = {
+static const struct super_operations affs_sops = {
.alloc_inode = affs_alloc_inode,
.destroy_inode = affs_destroy_inode,
.read_inode = affs_read_inode,
diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c
index f802256a593..41782539c90 100644
--- a/fs/affs/symlink.c
+++ b/fs/affs/symlink.c
@@ -70,7 +70,7 @@ const struct address_space_operations affs_symlink_aops = {
.readpage = affs_symlink_readpage,
};
-struct inode_operations affs_symlink_inode_operations = {
+const struct inode_operations affs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 4acd0413405..9908462bcad 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -37,7 +37,7 @@ const struct file_operations afs_dir_file_operations = {
.readdir = afs_dir_readdir,
};
-struct inode_operations afs_dir_inode_operations = {
+const struct inode_operations afs_dir_inode_operations = {
.lookup = afs_dir_lookup,
.getattr = afs_inode_getattr,
#if 0 /* TODO */
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 2e8c42639ea..eeff14c3f74 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -30,7 +30,7 @@ static int afs_file_readpage(struct file *file, struct page *page);
static void afs_file_invalidatepage(struct page *page, unsigned long offset);
static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
-struct inode_operations afs_file_inode_operations = {
+const struct inode_operations afs_file_inode_operations = {
.getattr = afs_inode_getattr,
};
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index e88b3b65ae4..5151d5da2c2 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -63,14 +63,14 @@ extern struct cachefs_index_def afs_cache_cell_index_def;
/*
* dir.c
*/
-extern struct inode_operations afs_dir_inode_operations;
+extern const struct inode_operations afs_dir_inode_operations;
extern const struct file_operations afs_dir_file_operations;
/*
* file.c
*/
extern const struct address_space_operations afs_fs_aops;
-extern struct inode_operations afs_file_inode_operations;
+extern const struct inode_operations afs_file_inode_operations;
#ifdef AFS_CACHING_SUPPORT
extern int afs_cache_get_page_cookie(struct page *page,
@@ -104,7 +104,7 @@ extern struct cachefs_netfs afs_cache_netfs;
/*
* mntpt.c
*/
-extern struct inode_operations afs_mntpt_inode_operations;
+extern const struct inode_operations afs_mntpt_inode_operations;
extern const struct file_operations afs_mntpt_file_operations;
extern struct afs_timer afs_mntpt_expiry_timer;
extern struct afs_timer_ops afs_mntpt_expiry_timer_ops;
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 8f74e845082..fdf23b2a211 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -36,7 +36,7 @@ const struct file_operations afs_mntpt_file_operations = {
.open = afs_mntpt_open,
};
-struct inode_operations afs_mntpt_inode_operations = {
+const struct inode_operations afs_mntpt_inode_operations = {
.lookup = afs_mntpt_lookup,
.follow_link = afs_mntpt_follow_link,
.readlink = page_readlink,
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 18d9b77ba40..eb7e32349da 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -56,7 +56,7 @@ struct file_system_type afs_fs_type = {
.fs_flags = FS_BINARY_MOUNTDATA,
};
-static struct super_operations afs_super_ops = {
+static const struct super_operations afs_super_ops = {
.statfs = simple_statfs,
.alloc_inode = afs_alloc_inode,
.drop_inode = generic_delete_inode,
diff --git a/fs/aio.c b/fs/aio.c
index 55991e4132a..0b4ee0a5c83 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -132,7 +132,7 @@ static int aio_setup_ring(struct kioctx *ctx)
dprintk("attempting mmap of %lu bytes\n", info->mmap_size);
down_write(&ctx->mm->mmap_sem);
info->mmap_base = do_mmap(NULL, 0, info->mmap_size,
- PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE,
+ PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE,
0);
if (IS_ERR((void *)info->mmap_base)) {
up_write(&ctx->mm->mmap_sem);
@@ -211,11 +211,10 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
if ((unsigned long)nr_events > aio_max_nr)
return ERR_PTR(-EAGAIN);
- ctx = kmem_cache_alloc(kioctx_cachep, GFP_KERNEL);
+ ctx = kmem_cache_zalloc(kioctx_cachep, GFP_KERNEL);
if (!ctx)
return ERR_PTR(-ENOMEM);
- memset(ctx, 0, sizeof(*ctx));
ctx->max_reqs = nr_events;
mm = ctx->mm = current->mm;
atomic_inc(&mm->mm_count);
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index 906ba5ce226..4ef544434b5 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -142,8 +142,8 @@ struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info
/* Operations structures */
-extern struct inode_operations autofs_root_inode_operations;
-extern struct inode_operations autofs_symlink_inode_operations;
+extern const struct inode_operations autofs_root_inode_operations;
+extern const struct inode_operations autofs_symlink_inode_operations;
extern const struct file_operations autofs_root_operations;
/* Initializing function */
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index f968d134280..aa0b61ff827 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -52,7 +52,7 @@ out_kill_sb:
static void autofs_read_inode(struct inode *inode);
-static struct super_operations autofs_sops = {
+static const struct super_operations autofs_sops = {
.read_inode = autofs_read_inode,
.statfs = simple_statfs,
};
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index e698c51d2b0..f2597205939 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -32,7 +32,7 @@ const struct file_operations autofs_root_operations = {
.ioctl = autofs_root_ioctl,
};
-struct inode_operations autofs_root_inode_operations = {
+const struct inode_operations autofs_root_inode_operations = {
.lookup = autofs_root_lookup,
.unlink = autofs_root_unlink,
.symlink = autofs_root_symlink,
diff --git a/fs/autofs/symlink.c b/fs/autofs/symlink.c
index c74f2eb6577..7ce9cb2c9ce 100644
--- a/fs/autofs/symlink.c
+++ b/fs/autofs/symlink.c
@@ -20,7 +20,7 @@ static void *autofs_follow_link(struct dentry *dentry, struct nameidata *nd)
return NULL;
}
-struct inode_operations autofs_symlink_inode_operations = {
+const struct inode_operations autofs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = autofs_follow_link
};
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 216b1a364cc..6b4cec3f272 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -168,11 +168,11 @@ int autofs4_expire_multi(struct super_block *, struct vfsmount *,
/* Operations structures */
-extern struct inode_operations autofs4_symlink_inode_operations;
-extern struct inode_operations autofs4_dir_inode_operations;
-extern struct inode_operations autofs4_root_inode_operations;
-extern struct inode_operations autofs4_indirect_root_inode_operations;
-extern struct inode_operations autofs4_direct_root_inode_operations;
+extern const struct inode_operations autofs4_symlink_inode_operations;
+extern const struct inode_operations autofs4_dir_inode_operations;
+extern const struct inode_operations autofs4_root_inode_operations;
+extern const struct inode_operations autofs4_indirect_root_inode_operations;
+extern const struct inode_operations autofs4_direct_root_inode_operations;
extern const struct file_operations autofs4_dir_operations;
extern const struct file_operations autofs4_root_operations;
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index e8f6c5ad3e9..5e458e096ef 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -196,7 +196,7 @@ static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt)
return 0;
}
-static struct super_operations autofs4_sops = {
+static const struct super_operations autofs4_sops = {
.statfs = simple_statfs,
.show_options = autofs4_show_options,
};
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 8d05b9f7578..47fee96c218 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -47,7 +47,7 @@ const struct file_operations autofs4_dir_operations = {
.readdir = autofs4_dir_readdir,
};
-struct inode_operations autofs4_indirect_root_inode_operations = {
+const struct inode_operations autofs4_indirect_root_inode_operations = {
.lookup = autofs4_lookup,
.unlink = autofs4_dir_unlink,
.symlink = autofs4_dir_symlink,
@@ -55,7 +55,7 @@ struct inode_operations autofs4_indirect_root_inode_operations = {
.rmdir = autofs4_dir_rmdir,
};
-struct inode_operations autofs4_direct_root_inode_operations = {
+const struct inode_operations autofs4_direct_root_inode_operations = {
.lookup = autofs4_lookup,
.unlink = autofs4_dir_unlink,
.mkdir = autofs4_dir_mkdir,
@@ -63,7 +63,7 @@ struct inode_operations autofs4_direct_root_inode_operations = {
.follow_link = autofs4_follow_link,
};
-struct inode_operations autofs4_dir_inode_operations = {
+const struct inode_operations autofs4_dir_inode_operations = {
.lookup = autofs4_lookup,
.unlink = autofs4_dir_unlink,
.symlink = autofs4_dir_symlink,
diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c
index 2ea2c98fd84..b4ea82934d2 100644
--- a/fs/autofs4/symlink.c
+++ b/fs/autofs4/symlink.c
@@ -19,7 +19,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
return NULL;
}
-struct inode_operations autofs4_symlink_inode_operations = {
+const struct inode_operations autofs4_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = autofs4_follow_link
};
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 869f5193ecc..efeab2fab40 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -291,7 +291,7 @@ static int bad_inode_removexattr(struct dentry *dentry, const char *name)
return -EIO;
}
-static struct inode_operations bad_inode_ops =
+static const struct inode_operations bad_inode_ops =
{
.create = bad_inode_create,
.lookup = bad_inode_lookup,
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 481e59b9d91..cc6cc8ed2e3 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -68,7 +68,7 @@ static const struct file_operations befs_dir_operations = {
.readdir = befs_readdir,
};
-static struct inode_operations befs_dir_inode_operations = {
+static const struct inode_operations befs_dir_inode_operations = {
.lookup = befs_lookup,
};
@@ -78,7 +78,7 @@ static const struct address_space_operations befs_aops = {
.bmap = befs_bmap,
};
-static struct inode_operations befs_symlink_inode_operations = {
+static const struct inode_operations befs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = befs_follow_link,
.put_link = befs_put_link,
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h
index 31973bbbf05..130f6c66c5b 100644
--- a/fs/bfs/bfs.h
+++ b/fs/bfs/bfs.h
@@ -48,12 +48,12 @@ static inline struct bfs_inode_info *BFS_I(struct inode *inode)
/* file.c */
-extern struct inode_operations bfs_file_inops;
+extern const struct inode_operations bfs_file_inops;
extern const struct file_operations bfs_file_operations;
extern const struct address_space_operations bfs_aops;
/* dir.c */
-extern struct inode_operations bfs_dir_inops;
+extern const struct inode_operations bfs_dir_inops;
extern const struct file_operations bfs_dir_operations;
#endif /* _FS_BFS_BFS_H */
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 2a746e688df..097f1497f74 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -260,7 +260,7 @@ end_rename:
return error;
}
-struct inode_operations bfs_dir_inops = {
+const struct inode_operations bfs_dir_inops = {
.create = bfs_create,
.lookup = bfs_lookup,
.link = bfs_link,
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index a9164a87f8d..ef4d1fa04e6 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -164,4 +164,4 @@ const struct address_space_operations bfs_aops = {
.bmap = bfs_bmap,
};
-struct inode_operations bfs_file_inops;
+const struct inode_operations bfs_file_inops;
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 134c99941a6..93d6219243a 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -270,7 +270,7 @@ static void destroy_inodecache(void)
kmem_cache_destroy(bfs_inode_cachep);
}
-static struct super_operations bfs_sops = {
+static const struct super_operations bfs_sops = {
.alloc_inode = bfs_alloc_inode,
.destroy_inode = bfs_destroy_inode,
.read_inode = bfs_read_inode,
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index a4d933a5120..5810aa1339f 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -372,7 +372,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
down_write(&current->mm->mmap_sem);
current->mm->start_brk = do_mmap(NULL, 0, stack_size,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN,
0);
if (IS_ERR_VALUE(current->mm->start_brk)) {
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index ae8595d4985..7b0265d7f3a 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -419,7 +419,7 @@ static int load_flat_file(struct linux_binprm * bprm,
unsigned long textpos = 0, datapos = 0, result;
unsigned long realdatastart = 0;
unsigned long text_len, data_len, bss_len, stack_len, flags;
- unsigned long memp = 0; /* for finding the brk area */
+ unsigned long len, reallen, memp = 0;
unsigned long extra, rlim;
unsigned long *reloc = 0, *rp;
struct inode *inode;
@@ -540,10 +540,18 @@ static int load_flat_file(struct linux_binprm * bprm,
goto err;
}
+ len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
down_write(&current->mm->mmap_sem);
- realdatastart = do_mmap(0, 0, data_len + extra +
- MAX_SHARED_LIBS * sizeof(unsigned long),
- PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
+ realdatastart = do_mmap(0, 0, len,
+ PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
+ /* Remap to use all availabe slack region space */
+ if (realdatastart && (realdatastart < (unsigned long)-4096)) {
+ reallen = ksize(realdatastart);
+ if (reallen > len) {
+ realdatastart = do_mremap(realdatastart, len,
+ reallen, MREMAP_FIXED, realdatastart);
+ }
+ }
up_write(&current->mm->mmap_sem);
if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
@@ -584,11 +592,20 @@ static int load_flat_file(struct linux_binprm * bprm,
} else {
+ len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
down_write(&current->mm->mmap_sem);
- textpos = do_mmap(0, 0, text_len + data_len + extra +
- MAX_SHARED_LIBS * sizeof(unsigned long),
- PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
+ textpos = do_mmap(0, 0, len,
+ PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
+ /* Remap to use all availabe slack region space */
+ if (textpos && (textpos < (unsigned long) -4096)) {
+ reallen = ksize(textpos);
+ if (reallen > len) {
+ textpos = do_mremap(textpos, len, reallen,
+ MREMAP_FIXED, textpos);
+ }
+ }
up_write(&current->mm->mmap_sem);
+
if (!textpos || textpos >= (unsigned long) -4096) {
if (!textpos)
textpos = (unsigned long) -ENOMEM;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index c2e08252af3..e6f57990b12 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -719,7 +719,7 @@ static const struct file_operations bm_status_operations = {
/* Superblock handling */
-static struct super_operations s_ops = {
+static const struct super_operations s_ops = {
.statfs = simple_statfs,
.clear_inode = bm_clear_inode,
};
diff --git a/fs/block_dev.c b/fs/block_dev.c
index fc7028b685f..0c59b703e9d 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -489,7 +489,7 @@ static void bdev_clear_inode(struct inode *inode)
spin_unlock(&bdev_lock);
}
-static struct super_operations bdev_sops = {
+static const struct super_operations bdev_sops = {
.statfs = simple_statfs,
.alloc_inode = bdev_alloc_inode,
.destroy_inode = bdev_destroy_inode,
diff --git a/fs/buffer.c b/fs/buffer.c
index 1ad674fd348..f99c509697c 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -78,6 +78,7 @@ EXPORT_SYMBOL(__lock_buffer);
void fastcall unlock_buffer(struct buffer_head *bh)
{
+ smp_mb__before_clear_bit();
clear_buffer_locked(bh);
smp_mb__after_clear_bit();
wake_up_bit(&bh->b_state, BH_Lock);
@@ -345,7 +346,7 @@ void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers)
* We really want to use invalidate_inode_pages2() for
* that, but not until that's cleaned up.
*/
- invalidate_inode_pages(mapping);
+ invalidate_mapping_pages(mapping, 0, -1);
}
/*
@@ -1282,11 +1283,11 @@ static void bh_lru_install(struct buffer_head *bh)
* Look up the bh in this cpu's LRU. If it's there, move it to the head.
*/
static struct buffer_head *
-lookup_bh_lru(struct block_device *bdev, sector_t block, int size)
+lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size)
{
struct buffer_head *ret = NULL;
struct bh_lru *lru;
- int i;
+ unsigned int i;
check_irqs_on();
bh_lru_lock();
@@ -1318,7 +1319,7 @@ lookup_bh_lru(struct block_device *bdev, sector_t block, int size)
* NULL
*/
struct buffer_head *
-__find_get_block(struct block_device *bdev, sector_t block, int size)
+__find_get_block(struct block_device *bdev, sector_t block, unsigned size)
{
struct buffer_head *bh = lookup_bh_lru(bdev, block, size);
@@ -1346,7 +1347,7 @@ EXPORT_SYMBOL(__find_get_block);
* attempt is failing. FIXME, perhaps?
*/
struct buffer_head *
-__getblk(struct block_device *bdev, sector_t block, int size)
+__getblk(struct block_device *bdev, sector_t block, unsigned size)
{
struct buffer_head *bh = __find_get_block(bdev, block, size);
@@ -1360,7 +1361,7 @@ EXPORT_SYMBOL(__getblk);
/*
* Do async read-ahead on a buffer..
*/
-void __breadahead(struct block_device *bdev, sector_t block, int size)
+void __breadahead(struct block_device *bdev, sector_t block, unsigned size)
{
struct buffer_head *bh = __getblk(bdev, block, size);
if (likely(bh)) {
@@ -1380,7 +1381,7 @@ EXPORT_SYMBOL(__breadahead);
* It returns NULL if the block was unreadable.
*/
struct buffer_head *
-__bread(struct block_device *bdev, sector_t block, int size)
+__bread(struct block_device *bdev, sector_t block, unsigned size)
{
struct buffer_head *bh = __getblk(bdev, block, size);
@@ -1439,6 +1440,7 @@ static void discard_buffer(struct buffer_head * bh)
clear_buffer_req(bh);
clear_buffer_new(bh);
clear_buffer_delay(bh);
+ clear_buffer_unwritten(bh);
unlock_buffer(bh);
}
@@ -1822,6 +1824,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
continue;
}
if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
+ !buffer_unwritten(bh) &&
(block_start < from || block_end > to)) {
ll_rw_block(READ, 1, &bh);
*wait_bh++=bh;
@@ -2543,7 +2546,7 @@ int block_truncate_page(struct address_space *mapping,
if (PageUptodate(page))
set_buffer_uptodate(bh);
- if (!buffer_uptodate(bh) && !buffer_delay(bh)) {
+ if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh)) {
err = -EIO;
ll_rw_block(READ, 1, &bh);
wait_on_buffer(bh);
diff --git a/fs/char_dev.c b/fs/char_dev.c
index a885f46ca00..e6194e2b9bb 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -108,6 +108,13 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
/* temporary */
if (major == 0) {
for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) {
+ /*
+ * Disallow the LANANA-assigned LOCAL/EXPERIMENTAL
+ * majors
+ */
+ if ((60 <= i && i <= 63) || (120 <= i && i <= 127) ||
+ (240 <= i && i <= 254))
+ continue;
if (chrdevs[i] == NULL)
break;
}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 93ef09971d2..e8287c4c6eb 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -64,7 +64,7 @@ extern struct task_struct * oplockThread; /* remove sparse warning */
struct task_struct * oplockThread = NULL;
extern struct task_struct * dnotifyThread; /* remove sparse warning */
struct task_struct * dnotifyThread = NULL;
-static struct super_operations cifs_super_ops;
+static const struct super_operations cifs_super_ops;
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
module_param(CIFSMaxBufSize, int, 0);
MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
@@ -453,7 +453,7 @@ static int cifs_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
-static struct super_operations cifs_super_ops = {
+static const struct super_operations cifs_super_ops = {
.read_inode = cifs_read_inode,
.put_super = cifs_put_super,
.statfs = cifs_statfs,
@@ -533,7 +533,7 @@ static struct file_system_type cifs_fs_type = {
.kill_sb = kill_anon_super,
/* .fs_flags */
};
-struct inode_operations cifs_dir_inode_ops = {
+const struct inode_operations cifs_dir_inode_ops = {
.create = cifs_create,
.lookup = cifs_lookup,
.getattr = cifs_getattr,
@@ -555,7 +555,7 @@ struct inode_operations cifs_dir_inode_ops = {
#endif
};
-struct inode_operations cifs_file_inode_ops = {
+const struct inode_operations cifs_file_inode_ops = {
/* revalidate:cifs_revalidate, */
.setattr = cifs_setattr,
.getattr = cifs_getattr, /* do we need this anymore? */
@@ -569,7 +569,7 @@ struct inode_operations cifs_file_inode_ops = {
#endif
};
-struct inode_operations cifs_symlink_inode_ops = {
+const struct inode_operations cifs_symlink_inode_ops = {
.readlink = generic_readlink,
.follow_link = cifs_follow_link,
.put_link = cifs_put_link,
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 8aa66dcf13b..01ae24af9cf 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -36,13 +36,13 @@ extern const struct address_space_operations cifs_addr_ops;
extern const struct address_space_operations cifs_addr_ops_smallbuf;
/* Functions related to super block operations */
-/* extern struct super_operations cifs_super_ops;*/
+/* extern const struct super_operations cifs_super_ops;*/
extern void cifs_read_inode(struct inode *);
extern void cifs_delete_inode(struct inode *);
/* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
/* Functions related to inodes */
-extern struct inode_operations cifs_dir_inode_ops;
+extern const struct inode_operations cifs_dir_inode_ops;
extern int cifs_create(struct inode *, struct dentry *, int,
struct nameidata *);
extern struct dentry * cifs_lookup(struct inode *, struct dentry *,
@@ -58,8 +58,8 @@ extern int cifs_revalidate(struct dentry *);
extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int cifs_setattr(struct dentry *, struct iattr *);
-extern struct inode_operations cifs_file_inode_ops;
-extern struct inode_operations cifs_symlink_inode_ops;
+extern const struct inode_operations cifs_file_inode_ops;
+extern const struct inode_operations cifs_symlink_inode_ops;
/* Functions related to files and directories */
extern const struct file_operations cifs_file_ops;
diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c
index 4c9fecbfa91..28c872747f8 100644
--- a/fs/coda/cnode.c
+++ b/fs/coda/cnode.c
@@ -16,7 +16,7 @@ static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)
return memcmp(fid1, fid2, sizeof(*fid1)) == 0;
}
-static struct inode_operations coda_symlink_inode_operations = {
+static const struct inode_operations coda_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 0c6f7f3b3dd..9ddf5ed6216 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -66,7 +66,7 @@ static struct dentry_operations coda_dentry_operations =
.d_delete = coda_dentry_delete,
};
-struct inode_operations coda_dir_inode_operations =
+const struct inode_operations coda_dir_inode_operations =
{
.create = coda_create,
.lookup = coda_lookup,
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 01395defed8..614175a3b02 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -90,7 +90,7 @@ static int coda_remount(struct super_block *sb, int *flags, char *data)
}
/* exported operations */
-static struct super_operations coda_super_operations =
+static const struct super_operations coda_super_operations =
{
.alloc_inode = coda_alloc_inode,
.destroy_inode = coda_destroy_inode,
@@ -271,7 +271,7 @@ int coda_setattr(struct dentry *de, struct iattr *iattr)
return error;
}
-struct inode_operations coda_file_inode_operations = {
+const struct inode_operations coda_file_inode_operations = {
.permission = coda_permission,
.getattr = coda_getattr,
.setattr = coda_setattr,
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index 214822be87b..2bf3026adc8 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -30,7 +30,7 @@ static int coda_pioctl(struct inode * inode, struct file * filp,
unsigned int cmd, unsigned long user_data);
/* exported from this file */
-struct inode_operations coda_ioctl_inode_operations =
+const struct inode_operations coda_ioctl_inode_operations =
{
.permission = coda_ioctl_permission,
.setattr = coda_setattr,
diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c
index 1c82e9a7d7c..db3b1a9c9a5 100644
--- a/fs/coda/sysctl.c
+++ b/fs/coda/sysctl.c
@@ -15,6 +15,7 @@
#include <linux/mm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/ctype.h>
@@ -84,15 +85,11 @@ static int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
return 0;
}
-static int coda_vfs_stats_get_info( char * buffer, char ** start,
- off_t offset, int length)
+static int proc_vfs_stats_show(struct seq_file *m, void *v)
{
- int len=0;
- off_t begin;
struct coda_vfs_stats * ps = & coda_vfs_stat;
- /* this works as long as we are below 1024 characters! */
- len += sprintf( buffer,
+ seq_printf(m,
"Coda VFS statistics\n"
"===================\n\n"
"File Operations:\n"
@@ -132,28 +129,14 @@ static int coda_vfs_stats_get_info( char * buffer, char ** start,
ps->rmdir,
ps->rename,
ps->permission);
-
- begin = offset;
- *start = buffer + begin;
- len -= begin;
-
- if ( len > length )
- len = length;
- if ( len < 0 )
- len = 0;
-
- return len;
+ return 0;
}
-static int coda_cache_inv_stats_get_info( char * buffer, char ** start,
- off_t offset, int length)
+static int proc_cache_inv_stats_show(struct seq_file *m, void *v)
{
- int len=0;
- off_t begin;
struct coda_cache_inv_stats * ps = & coda_cache_inv_stat;
- /* this works as long as we are below 1024 characters! */
- len += sprintf( buffer,
+ seq_printf(m,
"Coda cache invalidation statistics\n"
"==================================\n\n"
"flush\t\t%9d\n"
@@ -170,19 +153,35 @@ static int coda_cache_inv_stats_get_info( char * buffer, char ** start,
ps->zap_vnode,
ps->purge_fid,
ps->replace );
-
- begin = offset;
- *start = buffer + begin;
- len -= begin;
+ return 0;
+}
- if ( len > length )
- len = length;
- if ( len < 0 )
- len = 0;
+static int proc_vfs_stats_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_vfs_stats_show, NULL);
+}
- return len;
+static int proc_cache_inv_stats_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_cache_inv_stats_show, NULL);
}
+static const struct file_operations proc_vfs_stats_fops = {
+ .owner = THIS_MODULE,
+ .open = proc_vfs_stats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations proc_cache_inv_stats_fops = {
+ .owner = THIS_MODULE,
+ .open = proc_cache_inv_stats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static ctl_table coda_table[] = {
{CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec},
{CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec},
@@ -212,9 +211,6 @@ static struct proc_dir_entry* proc_fs_coda;
#endif
-#define coda_proc_create(name,get_info) \
- create_proc_info_entry(name, 0, proc_fs_coda, get_info)
-
void coda_sysctl_init(void)
{
reset_coda_vfs_stats();
@@ -223,9 +219,15 @@ void coda_sysctl_init(void)
#ifdef CONFIG_PROC_FS
proc_fs_coda = proc_mkdir("coda", proc_root_fs);
if (proc_fs_coda) {
+ struct proc_dir_entry *pde;
+
proc_fs_coda->owner = THIS_MODULE;
- coda_proc_create("vfs_stats", coda_vfs_stats_get_info);
- coda_proc_create("cache_inv_stats", coda_cache_inv_stats_get_info);
+ pde = create_proc_entry("vfs_stats", 0, proc_fs_coda);
+ if (pde)
+ pde->proc_fops = &proc_vfs_stats_fops;
+ pde = create_proc_entry("cache_inv_stats", 0, proc_fs_coda);
+ if (pde)
+ pde->proc_fops = &proc_cache_inv_stats_fops;
}
#endif
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index f92cd303d2c..7b48c034b31 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -75,8 +75,8 @@ extern struct super_block * configfs_sb;
extern const struct file_operations configfs_dir_operations;
extern const struct file_operations configfs_file_operations;
extern const struct file_operations bin_fops;
-extern struct inode_operations configfs_dir_inode_operations;
-extern struct inode_operations configfs_symlink_inode_operations;
+extern const struct inode_operations configfs_dir_inode_operations;
+extern const struct inode_operations configfs_symlink_inode_operations;
extern int configfs_symlink(struct inode *dir, struct dentry *dentry,
const char *symname);
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 1814ba44680..34750d5e4ff 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -72,11 +72,10 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * pare
{
struct configfs_dirent * sd;
- sd = kmem_cache_alloc(configfs_dir_cachep, GFP_KERNEL);
+ sd = kmem_cache_zalloc(configfs_dir_cachep, GFP_KERNEL);
if (!sd)
return NULL;
- memset(sd, 0, sizeof(*sd));
atomic_set(&sd->s_count, 1);
INIT_LIST_HEAD(&sd->s_links);
INIT_LIST_HEAD(&sd->s_children);
@@ -931,7 +930,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
return 0;
}
-struct inode_operations configfs_dir_inode_operations = {
+const struct inode_operations configfs_dir_inode_operations = {
.mkdir = configfs_mkdir,
.rmdir = configfs_rmdir,
.symlink = configfs_symlink,
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index fb18917954a..2ec9beac17c 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -49,7 +49,7 @@ static struct backing_dev_info configfs_backing_dev_info = {
.capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};
-static struct inode_operations configfs_inode_operations ={
+static const struct inode_operations configfs_inode_operations ={
.setattr = configfs_setattr,
};
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
index ed678529ebb..6f573004cd7 100644
--- a/fs/configfs/mount.c
+++ b/fs/configfs/mount.c
@@ -41,7 +41,7 @@ struct super_block * configfs_sb = NULL;
struct kmem_cache *configfs_dir_cachep;
static int configfs_mnt_count = 0;
-static struct super_operations configfs_ops = {
+static const struct super_operations configfs_ops = {
.statfs = simple_statfs,
.drop_inode = generic_delete_inode,
};
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
index fb65e0800a8..22700d2857d 100644
--- a/fs/configfs/symlink.c
+++ b/fs/configfs/symlink.c
@@ -272,7 +272,7 @@ static void configfs_put_link(struct dentry *dentry, struct nameidata *nd,
}
}
-struct inode_operations configfs_symlink_inode_operations = {
+const struct inode_operations configfs_symlink_inode_operations = {
.follow_link = configfs_follow_link,
.readlink = generic_readlink,
.put_link = configfs_put_link,
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 6db03fb089d..facd0c89be8 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -27,8 +27,8 @@
#include <asm/uaccess.h>
-static struct super_operations cramfs_ops;
-static struct inode_operations cramfs_dir_inode_operations;
+static const struct super_operations cramfs_ops;
+static const struct inode_operations cramfs_dir_inode_operations;
static const struct file_operations cramfs_directory_operations;
static const struct address_space_operations cramfs_aops;
@@ -518,11 +518,11 @@ static const struct file_operations cramfs_directory_operations = {
.readdir = cramfs_readdir,
};
-static struct inode_operations cramfs_dir_inode_operations = {
+static const struct inode_operations cramfs_dir_inode_operations = {
.lookup = cramfs_lookup,
};
-static struct super_operations cramfs_ops = {
+static const struct super_operations cramfs_ops = {
.put_super = cramfs_put_super,
.remount_fs = cramfs_remount,
.statfs = cramfs_statfs,
diff --git a/fs/dcache.c b/fs/dcache.c
index d68631f18df..b5f61393291 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1739,45 +1739,41 @@ shouldnt_be_hashed:
* @rootmnt: vfsmnt to which the root dentry belongs
* @buffer: buffer to return value in
* @buflen: buffer length
+ * @fail_deleted: what to return for deleted files
*
- * Convert a dentry into an ASCII path name. If the entry has been deleted
- * the string " (deleted)" is appended. Note that this is ambiguous.
+ * Convert a dentry into an ASCII path name. If the entry has been deleted,
+ * then if @fail_deleted is true, ERR_PTR(-ENOENT) is returned. Otherwise,
+ * the the string " (deleted)" is appended. Note that this is ambiguous.
*
- * Returns the buffer or an error code if the path was too long.
- *
- * "buflen" should be positive. Caller holds the dcache_lock.
+ * Returns the buffer or an error code.
*/
-static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
- struct dentry *root, struct vfsmount *rootmnt,
- char *buffer, int buflen)
+static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+ struct dentry *root, struct vfsmount *rootmnt,
+ char *buffer, int buflen, int fail_deleted)
{
- char * end = buffer+buflen;
- char * retval;
- int namelen;
+ int namelen, is_slash;
+
+ if (buflen < 2)
+ return ERR_PTR(-ENAMETOOLONG);
+ buffer += --buflen;
+ *buffer = '\0';
- *--end = '\0';
- buflen--;
+ spin_lock(&dcache_lock);
if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
- buflen -= 10;
- end -= 10;
- if (buflen < 0)
+ if (fail_deleted) {
+ buffer = ERR_PTR(-ENOENT);
+ goto out;
+ }
+ if (buflen < 10)
goto Elong;
- memcpy(end, " (deleted)", 10);
+ buflen -= 10;
+ buffer -= 10;
+ memcpy(buffer, " (deleted)", 10);
}
-
- if (buflen < 1)
- goto Elong;
- /* Get '/' right */
- retval = end-1;
- *retval = '/';
-
- for (;;) {
+ while (dentry != root || vfsmnt != rootmnt) {
struct dentry * parent;
- if (dentry == root && vfsmnt == rootmnt)
- break;
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
- /* Global root? */
spin_lock(&vfsmount_lock);
if (vfsmnt->mnt_parent == vfsmnt) {
spin_unlock(&vfsmount_lock);
@@ -1791,33 +1787,60 @@ static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
parent = dentry->d_parent;
prefetch(parent);
namelen = dentry->d_name.len;
- buflen -= namelen + 1;
- if (buflen < 0)
+ if (buflen <= namelen)
goto Elong;
- end -= namelen;
- memcpy(end, dentry->d_name.name, namelen);
- *--end = '/';
- retval = end;
+ buflen -= namelen + 1;
+ buffer -= namelen;
+ memcpy(buffer, dentry->d_name.name, namelen);
+ *--buffer = '/';
dentry = parent;
}
+ /* Get '/' right */
+ if (*buffer != '/')
+ *--buffer = '/';
- return retval;
+out:
+ spin_unlock(&dcache_lock);
+ return buffer;
global_root:
+ /*
+ * We went past the (vfsmount, dentry) we were looking for and have
+ * either hit a root dentry, a lazily unmounted dentry, an
+ * unconnected dentry, or the file is on a pseudo filesystem.
+ */
namelen = dentry->d_name.len;
- buflen -= namelen;
- if (buflen < 0)
+ is_slash = (namelen == 1 && *dentry->d_name.name == '/');
+ if (is_slash || (dentry->d_sb->s_flags & MS_NOUSER)) {
+ /*
+ * Make sure we won't return a pathname starting with '/'.
+ *
+ * Historically, we also glue together the root dentry and
+ * remaining name for pseudo filesystems like pipefs, which
+ * have the MS_NOUSER flag set. This results in pathnames
+ * like "pipe:[439336]".
+ */
+ if (*buffer == '/') {
+ buffer++;
+ buflen++;
+ }
+ if (is_slash)
+ goto out;
+ }
+ if (buflen < namelen)
goto Elong;
- retval -= namelen-1; /* hit the slash */
- memcpy(retval, dentry->d_name.name, namelen);
- return retval;
+ buffer -= namelen;
+ memcpy(buffer, dentry->d_name.name, namelen);
+ goto out;
+
Elong:
- return ERR_PTR(-ENAMETOOLONG);
+ buffer = ERR_PTR(-ENAMETOOLONG);
+ goto out;
}
/* write full pathname into buffer and return start of pathname */
-char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
- char *buf, int buflen)
+char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
+ int buflen)
{
char *res;
struct vfsmount *rootmnt;
@@ -1827,9 +1850,7 @@ char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
rootmnt = mntget(current->fs->rootmnt);
root = dget(current->fs->root);
read_unlock(&current->fs->lock);
- spin_lock(&dcache_lock);
- res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen);
- spin_unlock(&dcache_lock);
+ res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, 0);
dput(root);
mntput(rootmnt);
return res;
@@ -1855,10 +1876,10 @@ char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
*/
asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
{
- int error;
+ int error, len;
struct vfsmount *pwdmnt, *rootmnt;
struct dentry *pwd, *root;
- char *page = (char *) __get_free_page(GFP_USER);
+ char *page = (char *) __get_free_page(GFP_USER), *cwd;
if (!page)
return -ENOMEM;
@@ -1870,29 +1891,18 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
root = dget(current->fs->root);
read_unlock(&current->fs->lock);
- error = -ENOENT;
- /* Has the current directory has been unlinked? */
- spin_lock(&dcache_lock);
- if (pwd->d_parent == pwd || !d_unhashed(pwd)) {
- unsigned long len;
- char * cwd;
-
- cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE);
- spin_unlock(&dcache_lock);
-
- error = PTR_ERR(cwd);
- if (IS_ERR(cwd))
- goto out;
+ cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 1);
+ error = PTR_ERR(cwd);
+ if (IS_ERR(cwd))
+ goto out;
- error = -ERANGE;
- len = PAGE_SIZE + page - cwd;
- if (len <= size) {
- error = len;
- if (copy_to_user(buf, cwd, len))
- error = -EFAULT;
- }
- } else
- spin_unlock(&dcache_lock);
+ error = -ERANGE;
+ len = PAGE_SIZE + page - cwd;
+ if (len <= size) {
+ error = len;
+ if (copy_to_user(buf, cwd, len))
+ error = -EFAULT;
+ }
out:
dput(pwd);
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index bf3901ab174..8d130cc8532 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -254,7 +254,7 @@ static ssize_t read_file_blob(struct file *file, char __user *user_buf,
blob->size);
}
-static struct file_operations fops_blob = {
+static const struct file_operations fops_blob = {
.read = read_file_blob,
.open = default_open,
};
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 5f7b5a6025b..643e57b622b 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -91,7 +91,7 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
-static struct super_operations devpts_sops = {
+static const struct super_operations devpts_sops = {
.statfs = simple_statfs,
.remount_fs = devpts_remount,
};
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index ca94a837a5b..61ba670b9e0 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -287,7 +287,7 @@ static int rsb_open(struct inode *inode, struct file *file)
return 0;
}
-static struct file_operations rsb_fops = {
+static const struct file_operations rsb_fops = {
.owner = THIS_MODULE,
.open = rsb_open,
.read = seq_read,
@@ -331,7 +331,7 @@ static ssize_t waiters_read(struct file *file, char __user *userbuf,
return rv;
}
-static struct file_operations waiters_fops = {
+static const struct file_operations waiters_fops = {
.owner = THIS_MODULE,
.open = waiters_open,
.read = waiters_read
diff --git a/fs/dlm/lowcomms-tcp.c b/fs/dlm/lowcomms-tcp.c
index f1efd17b261..07e0a122c32 100644
--- a/fs/dlm/lowcomms-tcp.c
+++ b/fs/dlm/lowcomms-tcp.c
@@ -268,12 +268,12 @@ static void close_connection(struct connection *con, bool and_other)
static int receive_from_sock(struct connection *con)
{
int ret = 0;
- struct msghdr msg;
- struct iovec iov[2];
- mm_segment_t fs;
+ struct msghdr msg = {};
+ struct kvec iov[2];
unsigned len;
int r;
int call_again_soon = 0;
+ int nvec;
mutex_lock(&con->sock_mutex);
@@ -293,21 +293,13 @@ static int receive_from_sock(struct connection *con)
cbuf_init(&con->cb, PAGE_CACHE_SIZE);
}
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_iovlen = 1;
- msg.msg_iov = iov;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_flags = 0;
-
/*
* iov[0] is the bit of the circular buffer between the current end
* point (cb.base + cb.len) and the end of the buffer.
*/
iov[0].iov_len = con->cb.base - cbuf_data(&con->cb);
iov[0].iov_base = page_address(con->rx_page) + cbuf_data(&con->cb);
- iov[1].iov_len = 0;
+ nvec = 1;
/*
* iov[1] is the bit of the circular buffer between the start of the
@@ -317,15 +309,12 @@ static int receive_from_sock(struct connection *con)
iov[0].iov_len = PAGE_CACHE_SIZE - cbuf_data(&con->cb);
iov[1].iov_len = con->cb.base;
iov[1].iov_base = page_address(con->rx_page);
- msg.msg_iovlen = 2;
+ nvec = 2;
}
len = iov[0].iov_len + iov[1].iov_len;
- fs = get_fs();
- set_fs(get_ds());
- r = ret = sock_recvmsg(con->sock, &msg, len,
+ r = ret = kernel_recvmsg(con->sock, &msg, iov, nvec, len,
MSG_DONTWAIT | MSG_NOSIGNAL);
- set_fs(fs);
if (ret <= 0)
goto out_close;
diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c
index 5352b03ff5a..f858fef6e41 100644
--- a/fs/dlm/memory.c
+++ b/fs/dlm/memory.c
@@ -76,9 +76,7 @@ struct dlm_lkb *allocate_lkb(struct dlm_ls *ls)
{
struct dlm_lkb *lkb;
- lkb = kmem_cache_alloc(lkb_cache, GFP_KERNEL);
- if (lkb)
- memset(lkb, 0, sizeof(*lkb));
+ lkb = kmem_cache_zalloc(lkb_cache, GFP_KERNEL);
return lkb;
}
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index d378b7fe2a1..40db61dc95f 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -25,7 +25,7 @@
static const char *name_prefix="dlm";
static struct miscdevice ctl_device;
-static struct file_operations device_fops;
+static const struct file_operations device_fops;
#ifdef CONFIG_COMPAT
@@ -759,7 +759,7 @@ static int ctl_device_close(struct inode *inode, struct file *file)
return 0;
}
-static struct file_operations device_fops = {
+static const struct file_operations device_fops = {
.open = device_open,
.release = device_close,
.read = device_read,
@@ -768,7 +768,7 @@ static struct file_operations device_fops = {
.owner = THIS_MODULE,
};
-static struct file_operations ctl_device_fops = {
+static const struct file_operations ctl_device_fops = {
.open = ctl_device_open,
.release = ctl_device_close,
.write = device_write,
diff --git a/fs/dquot.c b/fs/dquot.c
index 0952cc474d9..9eb166f9148 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -79,6 +79,7 @@
#include <linux/buffer_head.h>
#include <linux/capability.h>
#include <linux/quotaops.h>
+#include <linux/writeback.h> /* for inode_lock, oddly enough.. */
#include <asm/uaccess.h>
@@ -600,11 +601,10 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
{
struct dquot *dquot;
- dquot = kmem_cache_alloc(dquot_cachep, GFP_NOFS);
+ dquot = kmem_cache_zalloc(dquot_cachep, GFP_NOFS);
if(!dquot)
return NODQUOT;
- memset((caddr_t)dquot, 0, sizeof(struct dquot));
mutex_init(&dquot->dq_lock);
INIT_LIST_HEAD(&dquot->dq_free);
INIT_LIST_HEAD(&dquot->dq_inuse);
@@ -688,23 +688,27 @@ static int dqinit_needed(struct inode *inode, int type)
/* This routine is guarded by dqonoff_mutex mutex */
static void add_dquot_ref(struct super_block *sb, int type)
{
- struct list_head *p;
+ struct inode *inode;
restart:
- file_list_lock();
- list_for_each(p, &sb->s_files) {
- struct file *filp = list_entry(p, struct file, f_u.fu_list);
- struct inode *inode = filp->f_path.dentry->d_inode;
- if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
- struct dentry *dentry = dget(filp->f_path.dentry);
- file_list_unlock();
- sb->dq_op->initialize(inode, type);
- dput(dentry);
- /* As we may have blocked we had better restart... */
- goto restart;
- }
+ spin_lock(&inode_lock);
+ list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+ if (!atomic_read(&inode->i_writecount))
+ continue;
+ if (!dqinit_needed(inode, type))
+ continue;
+ if (inode->i_state & (I_FREEING|I_WILL_FREE))
+ continue;
+
+ __iget(inode);
+ spin_unlock(&inode_lock);
+
+ sb->dq_op->initialize(inode, type);
+ iput(inode);
+ /* As we may have blocked we had better restart... */
+ goto restart;
}
- file_list_unlock();
+ spin_unlock(&inode_lock);
}
/* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */
@@ -756,15 +760,30 @@ static void put_dquot_list(struct list_head *tofree_head)
}
}
+static void remove_dquot_ref(struct super_block *sb, int type,
+ struct list_head *tofree_head)
+{
+ struct inode *inode;
+
+ spin_lock(&inode_lock);
+ list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+ if (!IS_NOQUOTA(inode))
+ remove_inode_dquot_ref(inode, type, tofree_head);
+ }
+ spin_unlock(&inode_lock);
+}
+
/* Gather all references from inodes and drop them */
static void drop_dquot_ref(struct super_block *sb, int type)
{
LIST_HEAD(tofree_head);
- down_write(&sb_dqopt(sb)->dqptr_sem);
- remove_dquot_ref(sb, type, &tofree_head);
- up_write(&sb_dqopt(sb)->dqptr_sem);
- put_dquot_list(&tofree_head);
+ if (sb->dq_op) {
+ down_write(&sb_dqopt(sb)->dqptr_sem);
+ remove_dquot_ref(sb, type, &tofree_head);
+ up_write(&sb_dqopt(sb)->dqptr_sem);
+ put_dquot_list(&tofree_head);
+ }
}
static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index 4e4762389bd..03ea7696fe3 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -20,7 +20,7 @@ static void drop_pagecache_sb(struct super_block *sb)
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
if (inode->i_state & (I_FREEING|I_WILL_FREE))
continue;
- invalidate_inode_pages(inode->i_mapping);
+ invalidate_mapping_pages(inode->i_mapping, 0, -1);
}
spin_unlock(&inode_lock);
}
diff --git a/fs/ecryptfs/Makefile b/fs/ecryptfs/Makefile
index ca6562451ee..1f1107237ea 100644
--- a/fs/ecryptfs/Makefile
+++ b/fs/ecryptfs/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
-ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o debug.o
+ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o messaging.o netlink.o debug.o
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 7196f50fe15..6ac630625b7 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1997-2004 Erez Zadok
* Copyright (C) 2001-2004 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
* Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
* Michael C. Thompson <mcthomps@us.ibm.com>
*
@@ -207,7 +207,7 @@ ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat)
mutex_init(&crypt_stat->cs_mutex);
mutex_init(&crypt_stat->cs_tfm_mutex);
mutex_init(&crypt_stat->cs_hash_tfm_mutex);
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_STRUCT_INITIALIZED);
+ crypt_stat->flags |= ECRYPTFS_STRUCT_INITIALIZED;
}
/**
@@ -305,8 +305,7 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
int rc = 0;
BUG_ON(!crypt_stat || !crypt_stat->tfm
- || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ECRYPTFS_STRUCT_INITIALIZED));
+ || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED));
if (unlikely(ecryptfs_verbosity > 0)) {
ecryptfs_printk(KERN_DEBUG, "Key size [%d]; key:\n",
crypt_stat->key_size);
@@ -429,10 +428,10 @@ static int ecryptfs_read_in_page(struct ecryptfs_page_crypt_context *ctx,
goto out;
}
} else {
- rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL,
- lower_inode,
- lower_page_idx);
- if (rc) {
+ *lower_page = grab_cache_page(lower_inode->i_mapping,
+ lower_page_idx);
+ if (!(*lower_page)) {
+ rc = -EINVAL;
ecryptfs_printk(
KERN_ERR, "Error attempting to grab and map "
"lower page with index [0x%.16x]; rc = [%d]\n",
@@ -485,7 +484,7 @@ int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx)
lower_inode = ecryptfs_inode_to_lower(ctx->page->mapping->host);
inode_info = ecryptfs_inode_to_private(ctx->page->mapping->host);
crypt_stat = &inode_info->crypt_stat;
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) {
+ if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
rc = ecryptfs_copy_page_to_lower(ctx->page, lower_inode,
ctx->param.lower_file);
if (rc)
@@ -617,7 +616,7 @@ int ecryptfs_decrypt_page(struct file *file, struct page *page)
crypt_stat = &(ecryptfs_inode_to_private(
page->mapping->host)->crypt_stat);
lower_inode = ecryptfs_inode_to_lower(page->mapping->host);
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) {
+ if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
rc = ecryptfs_do_readpage(file, page, page->index);
if (rc)
ecryptfs_printk(KERN_ERR, "Error attempting to copy "
@@ -828,9 +827,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
mutex_unlock(&crypt_stat->cs_tfm_mutex);
goto out;
}
- crypto_blkcipher_set_flags(crypt_stat->tfm,
- (ECRYPTFS_DEFAULT_CHAINING_MODE
- | CRYPTO_TFM_REQ_WEAK_KEY));
+ crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
mutex_unlock(&crypt_stat->cs_tfm_mutex);
rc = 0;
out:
@@ -865,7 +862,10 @@ void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat)
ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
} else
crypt_stat->header_extent_size = PAGE_CACHE_SIZE;
- crypt_stat->num_header_extents_at_front = 1;
+ if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+ crypt_stat->num_header_extents_at_front = 0;
+ else
+ crypt_stat->num_header_extents_at_front = 1;
}
/**
@@ -881,7 +881,7 @@ int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat)
BUG_ON(crypt_stat->iv_bytes > MD5_DIGEST_SIZE);
BUG_ON(crypt_stat->iv_bytes <= 0);
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID)) {
+ if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
rc = -EINVAL;
ecryptfs_printk(KERN_WARNING, "Session key not valid; "
"cannot generate root IV\n");
@@ -898,8 +898,7 @@ int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat)
out:
if (rc) {
memset(crypt_stat->root_iv, 0, crypt_stat->iv_bytes);
- ECRYPTFS_SET_FLAG(crypt_stat->flags,
- ECRYPTFS_SECURITY_WARNING);
+ crypt_stat->flags |= ECRYPTFS_SECURITY_WARNING;
}
return rc;
}
@@ -907,7 +906,7 @@ out:
static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat)
{
get_random_bytes(crypt_stat->key, crypt_stat->key_size);
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+ crypt_stat->flags |= ECRYPTFS_KEY_VALID;
ecryptfs_compute_root_iv(crypt_stat);
if (unlikely(ecryptfs_verbosity > 0)) {
ecryptfs_printk(KERN_DEBUG, "Generated new session key:\n");
@@ -917,6 +916,22 @@ static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat)
}
/**
+ * ecryptfs_copy_mount_wide_flags_to_inode_flags
+ *
+ * This function propagates the mount-wide flags to individual inode
+ * flags.
+ */
+static void ecryptfs_copy_mount_wide_flags_to_inode_flags(
+ struct ecryptfs_crypt_stat *crypt_stat,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
+{
+ if (mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED)
+ crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
+ if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
+ crypt_stat->flags |= ECRYPTFS_VIEW_AS_ENCRYPTED;
+}
+
+/**
* ecryptfs_set_default_crypt_stat_vals
* @crypt_stat
*
@@ -926,10 +941,12 @@ static void ecryptfs_set_default_crypt_stat_vals(
struct ecryptfs_crypt_stat *crypt_stat,
struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
{
+ ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
+ mount_crypt_stat);
ecryptfs_set_default_sizes(crypt_stat);
strcpy(crypt_stat->cipher, ECRYPTFS_DEFAULT_CIPHER);
crypt_stat->key_size = ECRYPTFS_DEFAULT_KEY_BYTES;
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+ crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID);
crypt_stat->file_version = ECRYPTFS_FILE_VERSION;
crypt_stat->mount_crypt_stat = mount_crypt_stat;
}
@@ -969,8 +986,10 @@ int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry)
if (mount_crypt_stat->global_auth_tok) {
ecryptfs_printk(KERN_DEBUG, "Initializing context for new "
"file using mount_crypt_stat\n");
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+ crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
+ crypt_stat->flags |= ECRYPTFS_KEY_VALID;
+ ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
+ mount_crypt_stat);
memcpy(crypt_stat->keysigs[crypt_stat->num_keysigs++],
mount_crypt_stat->global_auth_tok_sig,
ECRYPTFS_SIG_SIZE_HEX);
@@ -1003,7 +1022,7 @@ int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry)
*
* Returns one if marker found; zero if not found
*/
-int contains_ecryptfs_marker(char *data)
+static int contains_ecryptfs_marker(char *data)
{
u32 m_1, m_2;
@@ -1029,7 +1048,8 @@ struct ecryptfs_flag_map_elem {
/* Add support for additional flags by adding elements here. */
static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = {
{0x00000001, ECRYPTFS_ENABLE_HMAC},
- {0x00000002, ECRYPTFS_ENCRYPTED}
+ {0x00000002, ECRYPTFS_ENCRYPTED},
+ {0x00000004, ECRYPTFS_METADATA_IN_XATTR}
};
/**
@@ -1052,11 +1072,9 @@ static int ecryptfs_process_flags(struct ecryptfs_crypt_stat *crypt_stat,
for (i = 0; i < ((sizeof(ecryptfs_flag_map)
/ sizeof(struct ecryptfs_flag_map_elem))); i++)
if (flags & ecryptfs_flag_map[i].file_flag) {
- ECRYPTFS_SET_FLAG(crypt_stat->flags,
- ecryptfs_flag_map[i].local_flag);
+ crypt_stat->flags |= ecryptfs_flag_map[i].local_flag;
} else
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags,
- ecryptfs_flag_map[i].local_flag);
+ crypt_stat->flags &= ~(ecryptfs_flag_map[i].local_flag);
/* Version is in top 8 bits of the 32-bit flag vector */
crypt_stat->file_version = ((flags >> 24) & 0xFF);
(*bytes_read) = 4;
@@ -1093,8 +1111,7 @@ write_ecryptfs_flags(char *page_virt, struct ecryptfs_crypt_stat *crypt_stat,
for (i = 0; i < ((sizeof(ecryptfs_flag_map)
/ sizeof(struct ecryptfs_flag_map_elem))); i++)
- if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ecryptfs_flag_map[i].local_flag))
+ if (crypt_stat->flags & ecryptfs_flag_map[i].local_flag)
flags |= ecryptfs_flag_map[i].file_flag;
/* Version is in top 8 bits of the 32-bit flag vector */
flags |= ((((u8)crypt_stat->file_version) << 24) & 0xFF000000);
@@ -1189,8 +1206,8 @@ int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code)
*
* Returns zero on success; non-zero otherwise
*/
-int ecryptfs_read_header_region(char *data, struct dentry *dentry,
- struct vfsmount *mnt)
+static int ecryptfs_read_header_region(char *data, struct dentry *dentry,
+ struct vfsmount *mnt)
{
struct file *lower_file;
mm_segment_t oldfs;
@@ -1219,9 +1236,25 @@ out:
return rc;
}
-static void
-write_header_metadata(char *virt, struct ecryptfs_crypt_stat *crypt_stat,
- size_t *written)
+int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry,
+ struct vfsmount *mnt)
+{
+ int rc;
+
+ rc = ecryptfs_read_header_region(data, dentry, mnt);
+ if (rc)
+ goto out;
+ if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES))
+ rc = -EINVAL;
+out:
+ return rc;
+}
+
+
+void
+ecryptfs_write_header_metadata(char *virt,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ size_t *written)
{
u32 header_extent_size;
u16 num_header_extents_at_front;
@@ -1270,9 +1303,9 @@ struct kmem_cache *ecryptfs_header_cache_2;
*
* Returns zero on success
*/
-int ecryptfs_write_headers_virt(char *page_virt,
- struct ecryptfs_crypt_stat *crypt_stat,
- struct dentry *ecryptfs_dentry)
+static int ecryptfs_write_headers_virt(char *page_virt, size_t *size,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ struct dentry *ecryptfs_dentry)
{
int rc;
size_t written;
@@ -1283,7 +1316,8 @@ int ecryptfs_write_headers_virt(char *page_virt,
offset += written;
write_ecryptfs_flags((page_virt + offset), crypt_stat, &written);
offset += written;
- write_header_metadata((page_virt + offset), crypt_stat, &written);
+ ecryptfs_write_header_metadata((page_virt + offset), crypt_stat,
+ &written);
offset += written;
rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat,
ecryptfs_dentry, &written,
@@ -1291,11 +1325,70 @@ int ecryptfs_write_headers_virt(char *page_virt,
if (rc)
ecryptfs_printk(KERN_WARNING, "Error generating key packet "
"set; rc = [%d]\n", rc);
+ if (size) {
+ offset += written;
+ *size = offset;
+ }
+ return rc;
+}
+
+static int ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,
+ struct file *lower_file,
+ char *page_virt)
+{
+ mm_segment_t oldfs;
+ int current_header_page;
+ int header_pages;
+ ssize_t size;
+ int rc = 0;
+
+ lower_file->f_pos = 0;
+ oldfs = get_fs();
+ set_fs(get_ds());
+ size = vfs_write(lower_file, (char __user *)page_virt, PAGE_CACHE_SIZE,
+ &lower_file->f_pos);
+ if (size < 0) {
+ rc = (int)size;
+ printk(KERN_ERR "Error attempting to write lower page; "
+ "rc = [%d]\n", rc);
+ set_fs(oldfs);
+ goto out;
+ }
+ header_pages = ((crypt_stat->header_extent_size
+ * crypt_stat->num_header_extents_at_front)
+ / PAGE_CACHE_SIZE);
+ memset(page_virt, 0, PAGE_CACHE_SIZE);
+ current_header_page = 1;
+ while (current_header_page < header_pages) {
+ size = vfs_write(lower_file, (char __user *)page_virt,
+ PAGE_CACHE_SIZE, &lower_file->f_pos);
+ if (size < 0) {
+ rc = (int)size;
+ printk(KERN_ERR "Error attempting to write lower page; "
+ "rc = [%d]\n", rc);
+ set_fs(oldfs);
+ goto out;
+ }
+ current_header_page++;
+ }
+ set_fs(oldfs);
+out:
+ return rc;
+}
+
+static int ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ char *page_virt, size_t size)
+{
+ int rc;
+
+ rc = ecryptfs_setxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, page_virt,
+ size, 0);
return rc;
}
/**
- * ecryptfs_write_headers
+ * ecryptfs_write_metadata
* @lower_file: The lower file struct, which was returned from dentry_open
*
* Write the file headers out. This will likely involve a userspace
@@ -1306,22 +1399,18 @@ int ecryptfs_write_headers_virt(char *page_virt,
*
* Returns zero on success; non-zero on error
*/
-int ecryptfs_write_headers(struct dentry *ecryptfs_dentry,
- struct file *lower_file)
+int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
+ struct file *lower_file)
{
- mm_segment_t oldfs;
struct ecryptfs_crypt_stat *crypt_stat;
char *page_virt;
- int current_header_page;
- int header_pages;
+ size_t size;
int rc = 0;
crypt_stat = &ecryptfs_inode_to_private(
ecryptfs_dentry->d_inode)->crypt_stat;
- if (likely(ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ECRYPTFS_ENCRYPTED))) {
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ECRYPTFS_KEY_VALID)) {
+ if (likely(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
+ if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
ecryptfs_printk(KERN_DEBUG, "Key is "
"invalid; bailing out\n");
rc = -EINVAL;
@@ -1334,54 +1423,42 @@ int ecryptfs_write_headers(struct dentry *ecryptfs_dentry,
goto out;
}
/* Released in this function */
- page_virt = kmem_cache_alloc(ecryptfs_header_cache_0, GFP_USER);
+ page_virt = kmem_cache_zalloc(ecryptfs_header_cache_0, GFP_USER);
if (!page_virt) {
ecryptfs_printk(KERN_ERR, "Out of memory\n");
rc = -ENOMEM;
goto out;
}
- memset(page_virt, 0, PAGE_CACHE_SIZE);
- rc = ecryptfs_write_headers_virt(page_virt, crypt_stat,
- ecryptfs_dentry);
+ rc = ecryptfs_write_headers_virt(page_virt, &size, crypt_stat,
+ ecryptfs_dentry);
if (unlikely(rc)) {
ecryptfs_printk(KERN_ERR, "Error whilst writing headers\n");
memset(page_virt, 0, PAGE_CACHE_SIZE);
goto out_free;
}
- ecryptfs_printk(KERN_DEBUG,
- "Writing key packet set to underlying file\n");
- lower_file->f_pos = 0;
- oldfs = get_fs();
- set_fs(get_ds());
- ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->"
- "write() w/ header page; lower_file->f_pos = "
- "[0x%.16x]\n", lower_file->f_pos);
- lower_file->f_op->write(lower_file, (char __user *)page_virt,
- PAGE_CACHE_SIZE, &lower_file->f_pos);
- header_pages = ((crypt_stat->header_extent_size
- * crypt_stat->num_header_extents_at_front)
- / PAGE_CACHE_SIZE);
- memset(page_virt, 0, PAGE_CACHE_SIZE);
- current_header_page = 1;
- while (current_header_page < header_pages) {
- ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->"
- "write() w/ zero'd page; lower_file->f_pos = "
- "[0x%.16x]\n", lower_file->f_pos);
- lower_file->f_op->write(lower_file, (char __user *)page_virt,
- PAGE_CACHE_SIZE, &lower_file->f_pos);
- current_header_page++;
+ if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+ rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry,
+ crypt_stat, page_virt,
+ size);
+ else
+ rc = ecryptfs_write_metadata_to_contents(crypt_stat, lower_file,
+ page_virt);
+ if (rc) {
+ printk(KERN_ERR "Error writing metadata out to lower file; "
+ "rc = [%d]\n", rc);
+ goto out_free;
}
- set_fs(oldfs);
- ecryptfs_printk(KERN_DEBUG,
- "Done writing key packet set to underlying file.\n");
out_free:
kmem_cache_free(ecryptfs_header_cache_0, page_virt);
out:
return rc;
}
+#define ECRYPTFS_DONT_VALIDATE_HEADER_SIZE 0
+#define ECRYPTFS_VALIDATE_HEADER_SIZE 1
static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat,
- char *virt, int *bytes_read)
+ char *virt, int *bytes_read,
+ int validate_header_size)
{
int rc = 0;
u32 header_extent_size;
@@ -1396,9 +1473,10 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat,
crypt_stat->num_header_extents_at_front =
(int)num_header_extents_at_front;
(*bytes_read) = 6;
- if ((crypt_stat->header_extent_size
- * crypt_stat->num_header_extents_at_front)
- < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) {
+ if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE)
+ && ((crypt_stat->header_extent_size
+ * crypt_stat->num_header_extents_at_front)
+ < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) {
rc = -EINVAL;
ecryptfs_printk(KERN_WARNING, "Invalid header extent size: "
"[%d]\n", crypt_stat->header_extent_size);
@@ -1429,7 +1507,8 @@ static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat)
*/
static int ecryptfs_read_headers_virt(char *page_virt,
struct ecryptfs_crypt_stat *crypt_stat,
- struct dentry *ecryptfs_dentry)
+ struct dentry *ecryptfs_dentry,
+ int validate_header_size)
{
int rc = 0;
int offset;
@@ -1463,7 +1542,7 @@ static int ecryptfs_read_headers_virt(char *page_virt,
offset += bytes_read;
if (crypt_stat->file_version >= 1) {
rc = parse_header_metadata(crypt_stat, (page_virt + offset),
- &bytes_read);
+ &bytes_read, validate_header_size);
if (rc) {
ecryptfs_printk(KERN_WARNING, "Error reading header "
"metadata; rc = [%d]\n", rc);
@@ -1478,12 +1557,60 @@ out:
}
/**
- * ecryptfs_read_headers
+ * ecryptfs_read_xattr_region
+ *
+ * Attempts to read the crypto metadata from the extended attribute
+ * region of the lower file.
+ */
+int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry)
+{
+ ssize_t size;
+ int rc = 0;
+
+ size = ecryptfs_getxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME,
+ page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE);
+ if (size < 0) {
+ printk(KERN_DEBUG "Error attempting to read the [%s] "
+ "xattr from the lower file; return value = [%zd]\n",
+ ECRYPTFS_XATTR_NAME, size);
+ rc = -EINVAL;
+ goto out;
+ }
+out:
+ return rc;
+}
+
+int ecryptfs_read_and_validate_xattr_region(char *page_virt,
+ struct dentry *ecryptfs_dentry)
+{
+ int rc;
+
+ rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_dentry);
+ if (rc)
+ goto out;
+ if (!contains_ecryptfs_marker(page_virt + ECRYPTFS_FILE_SIZE_BYTES)) {
+ printk(KERN_WARNING "Valid data found in [%s] xattr, but "
+ "the marker is invalid\n", ECRYPTFS_XATTR_NAME);
+ rc = -EINVAL;
+ }
+out:
+ return rc;
+}
+
+/**
+ * ecryptfs_read_metadata
+ *
+ * Common entry point for reading file metadata. From here, we could
+ * retrieve the header information from the header region of the file,
+ * the xattr region of the file, or some other repostory that is
+ * stored separately from the file itself. The current implementation
+ * supports retrieving the metadata information from the file contents
+ * and from the xattr region.
*
* Returns zero if valid headers found and parsed; non-zero otherwise
*/
-int ecryptfs_read_headers(struct dentry *ecryptfs_dentry,
- struct file *lower_file)
+int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry,
+ struct file *lower_file)
{
int rc = 0;
char *page_virt = NULL;
@@ -1491,7 +1618,12 @@ int ecryptfs_read_headers(struct dentry *ecryptfs_dentry,
ssize_t bytes_read;
struct ecryptfs_crypt_stat *crypt_stat =
&ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
+ &ecryptfs_superblock_to_private(
+ ecryptfs_dentry->d_sb)->mount_crypt_stat;
+ ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
+ mount_crypt_stat);
/* Read the first page from the underlying file */
page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, GFP_USER);
if (!page_virt) {
@@ -1512,11 +1644,36 @@ int ecryptfs_read_headers(struct dentry *ecryptfs_dentry,
goto out;
}
rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
- ecryptfs_dentry);
+ ecryptfs_dentry,
+ ECRYPTFS_VALIDATE_HEADER_SIZE);
if (rc) {
- ecryptfs_printk(KERN_DEBUG, "Valid eCryptfs headers not "
- "found\n");
- rc = -EINVAL;
+ rc = ecryptfs_read_xattr_region(page_virt,
+ ecryptfs_dentry);
+ if (rc) {
+ printk(KERN_DEBUG "Valid eCryptfs headers not found in "
+ "file header region or xattr region\n");
+ rc = -EINVAL;
+ goto out;
+ }
+ rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
+ ecryptfs_dentry,
+ ECRYPTFS_DONT_VALIDATE_HEADER_SIZE);
+ if (rc) {
+ printk(KERN_DEBUG "Valid eCryptfs headers not found in "
+ "file xattr region either\n");
+ rc = -EINVAL;
+ }
+ if (crypt_stat->mount_crypt_stat->flags
+ & ECRYPTFS_XATTR_METADATA_ENABLED) {
+ crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
+ } else {
+ printk(KERN_WARNING "Attempt to access file with "
+ "crypto metadata only in the extended attribute "
+ "region, but eCryptfs was mounted without "
+ "xattr support enabled. eCryptfs will not treat "
+ "this like an encrypted file.\n");
+ rc = -EINVAL;
+ }
}
out:
if (page_virt) {
diff --git a/fs/ecryptfs/debug.c b/fs/ecryptfs/debug.c
index 61f8e894284..434c7efd80f 100644
--- a/fs/ecryptfs/debug.c
+++ b/fs/ecryptfs/debug.c
@@ -36,7 +36,7 @@ void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok)
ecryptfs_printk(KERN_DEBUG, "Auth tok at mem loc [%p]:\n",
auth_tok);
- if (ECRYPTFS_CHECK_FLAG(auth_tok->flags, ECRYPTFS_PRIVATE_KEY)) {
+ if (auth_tok->flags & ECRYPTFS_PRIVATE_KEY) {
ecryptfs_printk(KERN_DEBUG, " * private key type\n");
ecryptfs_printk(KERN_DEBUG, " * (NO PRIVATE KEY SUPPORT "
"IN ECRYPTFS VERSION 0.1)\n");
@@ -46,8 +46,8 @@ void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok)
ECRYPTFS_SALT_SIZE);
salt[ECRYPTFS_SALT_SIZE * 2] = '\0';
ecryptfs_printk(KERN_DEBUG, " * salt = [%s]\n", salt);
- if (ECRYPTFS_CHECK_FLAG(auth_tok->token.password.flags,
- ECRYPTFS_PERSISTENT_PASSWORD)) {
+ if (auth_tok->token.password.flags &
+ ECRYPTFS_PERSISTENT_PASSWORD) {
ecryptfs_printk(KERN_DEBUG, " * persistent\n");
}
memcpy(sig, auth_tok->token.password.signature,
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index afb64bdbe6a..b3609b7cdf1 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -4,8 +4,10 @@
*
* Copyright (C) 1997-2003 Erez Zadok
* Copyright (C) 2001-2003 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
* Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
+ * Trevor S. Highland <trevor.highland@gmail.com>
+ * Tyler Hicks <tyhicks@ou.edu>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -31,22 +33,25 @@
#include <linux/fs_stack.h>
#include <linux/namei.h>
#include <linux/scatterlist.h>
+#include <linux/hash.h>
/* Version verification for shared data structures w/ userspace */
#define ECRYPTFS_VERSION_MAJOR 0x00
#define ECRYPTFS_VERSION_MINOR 0x04
-#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x01
+#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x02
/* These flags indicate which features are supported by the kernel
* module; userspace tools such as the mount helper read
* ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine
* how to behave. */
-#define ECRYPTFS_VERSIONING_PASSPHRASE 0x00000001
-#define ECRYPTFS_VERSIONING_PUBKEY 0x00000002
+#define ECRYPTFS_VERSIONING_PASSPHRASE 0x00000001
+#define ECRYPTFS_VERSIONING_PUBKEY 0x00000002
#define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004
-#define ECRYPTFS_VERSIONING_POLICY 0x00000008
+#define ECRYPTFS_VERSIONING_POLICY 0x00000008
+#define ECRYPTFS_VERSIONING_XATTR 0x00000010
#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
- | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH)
-
+ | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
+ | ECRYPTFS_VERSIONING_PUBKEY \
+ | ECRYPTFS_VERSIONING_XATTR)
#define ECRYPTFS_MAX_PASSWORD_LENGTH 64
#define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
#define ECRYPTFS_SALT_SIZE 8
@@ -60,10 +65,25 @@
#define ECRYPTFS_MAX_KEY_BYTES 64
#define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512
#define ECRYPTFS_DEFAULT_IV_BYTES 16
-#define ECRYPTFS_FILE_VERSION 0x01
+#define ECRYPTFS_FILE_VERSION 0x02
#define ECRYPTFS_DEFAULT_HEADER_EXTENT_SIZE 8192
#define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096
#define ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE 8192
+#define ECRYPTFS_DEFAULT_MSG_CTX_ELEMS 32
+#define ECRYPTFS_DEFAULT_SEND_TIMEOUT HZ
+#define ECRYPTFS_MAX_MSG_CTX_TTL (HZ*3)
+#define ECRYPTFS_NLMSG_HELO 100
+#define ECRYPTFS_NLMSG_QUIT 101
+#define ECRYPTFS_NLMSG_REQUEST 102
+#define ECRYPTFS_NLMSG_RESPONSE 103
+#define ECRYPTFS_MAX_PKI_NAME_BYTES 16
+#define ECRYPTFS_DEFAULT_NUM_USERS 4
+#define ECRYPTFS_MAX_NUM_USERS 32768
+#define ECRYPTFS_TRANSPORT_NETLINK 0
+#define ECRYPTFS_TRANSPORT_CONNECTOR 1
+#define ECRYPTFS_TRANSPORT_RELAYFS 2
+#define ECRYPTFS_DEFAULT_TRANSPORT ECRYPTFS_TRANSPORT_NETLINK
+#define ECRYPTFS_XATTR_NAME "user.ecryptfs"
#define RFC2440_CIPHER_DES3_EDE 0x02
#define RFC2440_CIPHER_CAST_5 0x03
@@ -74,9 +94,7 @@
#define RFC2440_CIPHER_TWOFISH 0x0a
#define RFC2440_CIPHER_CAST_6 0x0b
-#define ECRYPTFS_SET_FLAG(flag_bit_vector, flag) (flag_bit_vector |= (flag))
-#define ECRYPTFS_CLEAR_FLAG(flag_bit_vector, flag) (flag_bit_vector &= ~(flag))
-#define ECRYPTFS_CHECK_FLAG(flag_bit_vector, flag) (flag_bit_vector & (flag))
+#define RFC2440_CIPHER_RSA 0x01
/**
* For convenience, we may need to pass around the encrypted session
@@ -114,6 +132,14 @@ struct ecryptfs_password {
enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY};
+struct ecryptfs_private_key {
+ u32 key_size;
+ u32 data_len;
+ u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
+ char pki_type[ECRYPTFS_MAX_PKI_NAME_BYTES + 1];
+ u8 data[];
+};
+
/* May be a password or a private key */
struct ecryptfs_auth_tok {
u16 version; /* 8-bit major and 8-bit minor */
@@ -123,7 +149,7 @@ struct ecryptfs_auth_tok {
u8 reserved[32];
union {
struct ecryptfs_password password;
- /* Private key is in future eCryptfs releases */
+ struct ecryptfs_private_key private_key;
} token;
} __attribute__ ((packed));
@@ -176,10 +202,14 @@ ecryptfs_get_key_payload_data(struct key *key)
#define ECRYPTFS_FILE_SIZE_BYTES 8
#define ECRYPTFS_DEFAULT_CIPHER "aes"
#define ECRYPTFS_DEFAULT_KEY_BYTES 16
-#define ECRYPTFS_DEFAULT_CHAINING_MODE CRYPTO_TFM_MODE_CBC
#define ECRYPTFS_DEFAULT_HASH "md5"
+#define ECRYPTFS_TAG_1_PACKET_TYPE 0x01
#define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C
#define ECRYPTFS_TAG_11_PACKET_TYPE 0xED
+#define ECRYPTFS_TAG_64_PACKET_TYPE 0x40
+#define ECRYPTFS_TAG_65_PACKET_TYPE 0x41
+#define ECRYPTFS_TAG_66_PACKET_TYPE 0x42
+#define ECRYPTFS_TAG_67_PACKET_TYPE 0x43
#define MD5_DIGEST_SIZE 16
/**
@@ -196,6 +226,8 @@ struct ecryptfs_crypt_stat {
#define ECRYPTFS_ENABLE_HMAC 0x00000020
#define ECRYPTFS_ENCRYPT_IV_PAGES 0x00000040
#define ECRYPTFS_KEY_VALID 0x00000080
+#define ECRYPTFS_METADATA_IN_XATTR 0x00000100
+#define ECRYPTFS_VIEW_AS_ENCRYPTED 0x00000200
u32 flags;
unsigned int file_version;
size_t iv_bytes;
@@ -242,6 +274,8 @@ struct ecryptfs_dentry_info {
struct ecryptfs_mount_crypt_stat {
/* Pointers to memory we do not own, do not free these */
#define ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED 0x00000001
+#define ECRYPTFS_XATTR_METADATA_ENABLED 0x00000002
+#define ECRYPTFS_ENCRYPTED_VIEW_ENABLED 0x00000004
u32 flags;
struct ecryptfs_auth_tok *global_auth_tok;
struct key *global_auth_tok_key;
@@ -272,6 +306,33 @@ struct ecryptfs_auth_tok_list_item {
struct ecryptfs_auth_tok auth_tok;
};
+struct ecryptfs_message {
+ u32 index;
+ u32 data_len;
+ u8 data[];
+};
+
+struct ecryptfs_msg_ctx {
+#define ECRYPTFS_MSG_CTX_STATE_FREE 0x0001
+#define ECRYPTFS_MSG_CTX_STATE_PENDING 0x0002
+#define ECRYPTFS_MSG_CTX_STATE_DONE 0x0003
+ u32 state;
+ unsigned int index;
+ unsigned int counter;
+ struct ecryptfs_message *msg;
+ struct task_struct *task;
+ struct list_head node;
+ struct mutex mux;
+};
+
+extern unsigned int ecryptfs_transport;
+
+struct ecryptfs_daemon_id {
+ pid_t pid;
+ uid_t uid;
+ struct hlist_node id_chain;
+};
+
static inline struct ecryptfs_file_info *
ecryptfs_file_to_private(struct file *file)
{
@@ -385,13 +446,16 @@ void __ecryptfs_printk(const char *fmt, ...);
extern const struct file_operations ecryptfs_main_fops;
extern const struct file_operations ecryptfs_dir_fops;
-extern struct inode_operations ecryptfs_main_iops;
-extern struct inode_operations ecryptfs_dir_iops;
-extern struct inode_operations ecryptfs_symlink_iops;
-extern struct super_operations ecryptfs_sops;
+extern const struct inode_operations ecryptfs_main_iops;
+extern const struct inode_operations ecryptfs_dir_iops;
+extern const struct inode_operations ecryptfs_symlink_iops;
+extern const struct super_operations ecryptfs_sops;
extern struct dentry_operations ecryptfs_dops;
extern struct address_space_operations ecryptfs_aops;
extern int ecryptfs_verbosity;
+extern unsigned int ecryptfs_message_buf_len;
+extern signed long ecryptfs_message_wait_timeout;
+extern unsigned int ecryptfs_number_of_users;
extern struct kmem_cache *ecryptfs_auth_tok_list_item_cache;
extern struct kmem_cache *ecryptfs_file_info_cache;
@@ -401,6 +465,7 @@ extern struct kmem_cache *ecryptfs_sb_info_cache;
extern struct kmem_cache *ecryptfs_header_cache_0;
extern struct kmem_cache *ecryptfs_header_cache_1;
extern struct kmem_cache *ecryptfs_header_cache_2;
+extern struct kmem_cache *ecryptfs_xattr_cache;
extern struct kmem_cache *ecryptfs_lower_page_cache;
int ecryptfs_interpose(struct dentry *hidden_dentry,
@@ -427,9 +492,13 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat);
int ecryptfs_crypto_api_algify_cipher_name(char **algified_name,
char *cipher_name,
char *chaining_modifier);
-int ecryptfs_write_inode_size_to_header(struct file *lower_file,
- struct inode *lower_inode,
- struct inode *inode);
+#define ECRYPTFS_LOWER_I_MUTEX_NOT_HELD 0
+#define ECRYPTFS_LOWER_I_MUTEX_HELD 1
+int ecryptfs_write_inode_size_to_metadata(struct file *lower_file,
+ struct inode *lower_inode,
+ struct inode *inode,
+ struct dentry *ecryptfs_dentry,
+ int lower_i_mutex_held);
int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
struct file *lower_file,
unsigned long lower_page_index, int byte_offset,
@@ -442,26 +511,20 @@ int ecryptfs_copy_page_to_lower(struct page *page, struct inode *lower_inode,
struct file *lower_file);
int ecryptfs_do_readpage(struct file *file, struct page *page,
pgoff_t lower_page_index);
-int ecryptfs_grab_and_map_lower_page(struct page **lower_page,
- char **lower_virt,
- struct inode *lower_inode,
- unsigned long lower_page_index);
int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
struct inode *lower_inode,
struct writeback_control *wbc);
int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx);
int ecryptfs_decrypt_page(struct file *file, struct page *page);
-int ecryptfs_write_headers(struct dentry *ecryptfs_dentry,
+int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
+ struct file *lower_file);
+int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry,
struct file *lower_file);
-int ecryptfs_write_headers_virt(char *page_virt,
- struct ecryptfs_crypt_stat *crypt_stat,
- struct dentry *ecryptfs_dentry);
-int ecryptfs_read_headers(struct dentry *ecryptfs_dentry,
- struct file *lower_file);
int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry);
-int contains_ecryptfs_marker(char *data);
-int ecryptfs_read_header_region(char *data, struct dentry *dentry,
- struct vfsmount *mnt);
+int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry,
+ struct vfsmount *mnt);
+int ecryptfs_read_and_validate_xattr_region(char *page_virt,
+ struct dentry *ecryptfs_dentry);
u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat);
int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code);
void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat);
@@ -484,5 +547,37 @@ int ecryptfs_open_lower_file(struct file **lower_file,
struct dentry *lower_dentry,
struct vfsmount *lower_mnt, int flags);
int ecryptfs_close_lower_file(struct file *lower_file);
+ssize_t ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
+ size_t size);
+int
+ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
+ size_t size, int flags);
+int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry);
+int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid);
+int ecryptfs_process_quit(uid_t uid, pid_t pid);
+int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
+ pid_t pid, u32 seq);
+int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
+ struct ecryptfs_msg_ctx **msg_ctx);
+int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
+ struct ecryptfs_message **emsg);
+int ecryptfs_init_messaging(unsigned int transport);
+void ecryptfs_release_messaging(unsigned int transport);
+
+int ecryptfs_send_netlink(char *data, int data_len,
+ struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
+ u16 msg_flags, pid_t daemon_pid);
+int ecryptfs_init_netlink(void);
+void ecryptfs_release_netlink(void);
+
+int ecryptfs_send_connector(char *data, int data_len,
+ struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
+ u16 msg_flags, pid_t daemon_pid);
+int ecryptfs_init_connector(void);
+void ecryptfs_release_connector(void);
+void
+ecryptfs_write_header_metadata(char *virt,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ size_t *written);
#endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index c5a2e5298f1..bd969adf70d 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1997-2004 Erez Zadok
* Copyright (C) 2001-2004 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
* Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
* Michael C. Thompson <mcthomps@us.ibm.com>
*
@@ -250,8 +250,19 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
struct ecryptfs_file_info *file_info;
int lower_flags;
+ mount_crypt_stat = &ecryptfs_superblock_to_private(
+ ecryptfs_dentry->d_sb)->mount_crypt_stat;
+ if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
+ && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR)
+ || (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC)
+ || (file->f_flags & O_APPEND))) {
+ printk(KERN_WARNING "Mount has encrypted view enabled; "
+ "files may only be read\n");
+ rc = -EPERM;
+ goto out;
+ }
/* Released in ecryptfs_release or end of function if failure */
- file_info = kmem_cache_alloc(ecryptfs_file_info_cache, GFP_KERNEL);
+ file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL);
ecryptfs_set_file_private(file, file_info);
if (!file_info) {
ecryptfs_printk(KERN_ERR,
@@ -259,17 +270,14 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
rc = -ENOMEM;
goto out;
}
- memset(file_info, 0, sizeof(*file_info));
lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
- mount_crypt_stat = &ecryptfs_superblock_to_private(
- ecryptfs_dentry->d_sb)->mount_crypt_stat;
mutex_lock(&crypt_stat->cs_mutex);
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) {
+ if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) {
ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n");
/* Policy code enabled in future release */
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED);
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
+ crypt_stat->flags |= ECRYPTFS_POLICY_APPLIED;
+ crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
}
mutex_unlock(&crypt_stat->cs_mutex);
lower_flags = file->f_flags;
@@ -289,31 +297,14 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
lower_inode = lower_dentry->d_inode;
if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
+ crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
rc = 0;
goto out;
}
mutex_lock(&crypt_stat->cs_mutex);
- if (i_size_read(lower_inode) < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) {
- if (!(mount_crypt_stat->flags
- & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
- rc = -EIO;
- printk(KERN_WARNING "Attempt to read file that is "
- "not in a valid eCryptfs format, and plaintext "
- "passthrough mode is not enabled; returning "
- "-EIO\n");
- mutex_unlock(&crypt_stat->cs_mutex);
- goto out_puts;
- }
- crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
- rc = 0;
- mutex_unlock(&crypt_stat->cs_mutex);
- goto out;
- } else if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ECRYPTFS_POLICY_APPLIED)
- || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ECRYPTFS_KEY_VALID)) {
- rc = ecryptfs_read_headers(ecryptfs_dentry, lower_file);
+ if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)
+ || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
+ rc = ecryptfs_read_metadata(ecryptfs_dentry, lower_file);
if (rc) {
ecryptfs_printk(KERN_DEBUG,
"Valid headers not found\n");
@@ -327,9 +318,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
mutex_unlock(&crypt_stat->cs_mutex);
goto out_puts;
}
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags,
- ECRYPTFS_ENCRYPTED);
rc = 0;
+ crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
mutex_unlock(&crypt_stat->cs_mutex);
goto out;
}
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 11f5e5076ae..9fa7e0b27a9 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1997-2004 Erez Zadok
* Copyright (C) 2001-2004 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
* Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
* Michael C. Thompsion <mcthomps@us.ibm.com>
*
@@ -161,17 +161,17 @@ static int grow_file(struct dentry *ecryptfs_dentry, struct file *lower_file,
ecryptfs_set_file_lower(&fake_file, lower_file);
rc = ecryptfs_fill_zeros(&fake_file, 1);
if (rc) {
- ECRYPTFS_SET_FLAG(
- ecryptfs_inode_to_private(inode)->crypt_stat.flags,
- ECRYPTFS_SECURITY_WARNING);
+ ecryptfs_inode_to_private(inode)->crypt_stat.flags |=
+ ECRYPTFS_SECURITY_WARNING;
ecryptfs_printk(KERN_WARNING, "Error attempting to fill zeros "
"in file; rc = [%d]\n", rc);
goto out;
}
i_size_write(inode, 0);
- ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode);
- ECRYPTFS_SET_FLAG(ecryptfs_inode_to_private(inode)->crypt_stat.flags,
- ECRYPTFS_NEW_FILE);
+ ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, inode,
+ ecryptfs_dentry,
+ ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
+ ecryptfs_inode_to_private(inode)->crypt_stat.flags |= ECRYPTFS_NEW_FILE;
out:
return rc;
}
@@ -199,7 +199,7 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
lower_dentry->d_name.name);
inode = ecryptfs_dentry->d_inode;
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
- lower_flags = ((O_CREAT | O_WRONLY | O_TRUNC) & O_ACCMODE) | O_RDWR;
+ lower_flags = ((O_CREAT | O_TRUNC) & O_ACCMODE) | O_RDWR;
#if BITS_PER_LONG != 32
lower_flags |= O_LARGEFILE;
#endif
@@ -214,10 +214,10 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
lower_inode = lower_dentry->d_inode;
if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
+ crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
goto out_fput;
}
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE);
+ crypt_stat->flags |= ECRYPTFS_NEW_FILE;
ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n");
rc = ecryptfs_new_file_context(ecryptfs_dentry);
if (rc) {
@@ -225,7 +225,7 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
"context\n");
goto out_fput;
}
- rc = ecryptfs_write_headers(ecryptfs_dentry, lower_file);
+ rc = ecryptfs_write_metadata(ecryptfs_dentry, lower_file);
if (rc) {
ecryptfs_printk(KERN_DEBUG, "Error writing headers\n");
goto out_fput;
@@ -287,6 +287,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
char *encoded_name;
unsigned int encoded_namelen;
struct ecryptfs_crypt_stat *crypt_stat = NULL;
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
char *page_virt = NULL;
struct inode *lower_inode;
u64 file_size;
@@ -361,34 +362,44 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
goto out;
}
/* Released in this function */
- page_virt =
- (char *)kmem_cache_alloc(ecryptfs_header_cache_2,
- GFP_USER);
+ page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2,
+ GFP_USER);
if (!page_virt) {
rc = -ENOMEM;
ecryptfs_printk(KERN_ERR,
"Cannot ecryptfs_kmalloc a page\n");
goto out_dput;
}
- memset(page_virt, 0, PAGE_CACHE_SIZE);
- rc = ecryptfs_read_header_region(page_virt, lower_dentry, nd->mnt);
crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED))
+ if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
ecryptfs_set_default_sizes(crypt_stat);
+ rc = ecryptfs_read_and_validate_header_region(page_virt, lower_dentry,
+ nd->mnt);
if (rc) {
- rc = 0;
- ecryptfs_printk(KERN_WARNING, "Error reading header region;"
- " assuming unencrypted\n");
- } else {
- if (!contains_ecryptfs_marker(page_virt
- + ECRYPTFS_FILE_SIZE_BYTES)) {
+ rc = ecryptfs_read_and_validate_xattr_region(page_virt, dentry);
+ if (rc) {
+ printk(KERN_DEBUG "Valid metadata not found in header "
+ "region or xattr region; treating file as "
+ "unencrypted\n");
+ rc = 0;
kmem_cache_free(ecryptfs_header_cache_2, page_virt);
goto out;
}
+ crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
+ }
+ mount_crypt_stat = &ecryptfs_superblock_to_private(
+ dentry->d_sb)->mount_crypt_stat;
+ if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
+ if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+ file_size = (crypt_stat->header_extent_size
+ + i_size_read(lower_dentry->d_inode));
+ else
+ file_size = i_size_read(lower_dentry->d_inode);
+ } else {
memcpy(&file_size, page_virt, sizeof(file_size));
file_size = be64_to_cpu(file_size);
- i_size_write(dentry->d_inode, (loff_t)file_size);
}
+ i_size_write(dentry->d_inode, (loff_t)file_size);
kmem_cache_free(ecryptfs_header_cache_2, page_virt);
goto out;
@@ -782,20 +793,26 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
goto out_fput;
}
i_size_write(inode, new_length);
- rc = ecryptfs_write_inode_size_to_header(lower_file,
- lower_dentry->d_inode,
- inode);
+ rc = ecryptfs_write_inode_size_to_metadata(
+ lower_file, lower_dentry->d_inode, inode, dentry,
+ ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
if (rc) {
- ecryptfs_printk(KERN_ERR,
- "Problem with ecryptfs_write"
- "_inode_size\n");
+ printk(KERN_ERR "Problem with "
+ "ecryptfs_write_inode_size_to_metadata; "
+ "rc = [%d]\n", rc);
goto out_fput;
}
} else { /* new_length < i_size_read(inode) */
vmtruncate(inode, new_length);
- ecryptfs_write_inode_size_to_header(lower_file,
- lower_dentry->d_inode,
- inode);
+ rc = ecryptfs_write_inode_size_to_metadata(
+ lower_file, lower_dentry->d_inode, inode, dentry,
+ ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
+ if (rc) {
+ printk(KERN_ERR "Problem with "
+ "ecryptfs_write_inode_size_to_metadata; "
+ "rc = [%d]\n", rc);
+ goto out_fput;
+ }
/* We are reducing the size of the ecryptfs file, and need to
* know if we need to reduce the size of the lower file. */
lower_size_before_truncate =
@@ -882,7 +899,7 @@ out:
return rc;
}
-static int
+int
ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags)
{
@@ -902,7 +919,7 @@ out:
return rc;
}
-static ssize_t
+ssize_t
ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
size_t size)
{
@@ -972,7 +989,7 @@ int ecryptfs_inode_set(struct inode *inode, void *lower_inode)
return 0;
}
-struct inode_operations ecryptfs_symlink_iops = {
+const struct inode_operations ecryptfs_symlink_iops = {
.readlink = ecryptfs_readlink,
.follow_link = ecryptfs_follow_link,
.put_link = ecryptfs_put_link,
@@ -984,7 +1001,7 @@ struct inode_operations ecryptfs_symlink_iops = {
.removexattr = ecryptfs_removexattr
};
-struct inode_operations ecryptfs_dir_iops = {
+const struct inode_operations ecryptfs_dir_iops = {
.create = ecryptfs_create,
.lookup = ecryptfs_lookup,
.link = ecryptfs_link,
@@ -1002,7 +1019,7 @@ struct inode_operations ecryptfs_dir_iops = {
.removexattr = ecryptfs_removexattr
};
-struct inode_operations ecryptfs_main_iops = {
+const struct inode_operations ecryptfs_main_iops = {
.permission = ecryptfs_permission,
.setattr = ecryptfs_setattr,
.setxattr = ecryptfs_setxattr,
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index 745c0f1bfbb..c209f67e7a2 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -7,6 +7,7 @@
* Copyright (C) 2004-2006 International Business Machines Corp.
* Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
* Michael C. Thompson <mcthomps@us.ibm.com>
+ * Trevor S. Highland <trevor.highland@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -64,26 +65,6 @@ int process_request_key_err(long err_code)
return rc;
}
-static void wipe_auth_tok_list(struct list_head *auth_tok_list_head)
-{
- struct list_head *walker;
- struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
-
- walker = auth_tok_list_head->next;
- while (walker != auth_tok_list_head) {
- auth_tok_list_item =
- list_entry(walker, struct ecryptfs_auth_tok_list_item,
- list);
- walker = auth_tok_list_item->list.next;
- memset(auth_tok_list_item, 0,
- sizeof(struct ecryptfs_auth_tok_list_item));
- kmem_cache_free(ecryptfs_auth_tok_list_item_cache,
- auth_tok_list_item);
- }
-}
-
-struct kmem_cache *ecryptfs_auth_tok_list_item_cache;
-
/**
* parse_packet_length
* @data: Pointer to memory containing length at offset
@@ -102,12 +83,12 @@ static int parse_packet_length(unsigned char *data, size_t *size,
(*size) = 0;
if (data[0] < 192) {
/* One-byte length */
- (*size) = data[0];
+ (*size) = (unsigned char)data[0];
(*length_size) = 1;
} else if (data[0] < 224) {
/* Two-byte length */
- (*size) = ((data[0] - 192) * 256);
- (*size) += (data[1] + 192);
+ (*size) = (((unsigned char)(data[0]) - 192) * 256);
+ (*size) += ((unsigned char)(data[1]) + 192);
(*length_size) = 2;
} else if (data[0] == 255) {
/* Five-byte length; we're not supposed to see this */
@@ -154,6 +135,499 @@ static int write_packet_length(char *dest, size_t size,
return rc;
}
+static int
+write_tag_64_packet(char *signature, struct ecryptfs_session_key *session_key,
+ char **packet, size_t *packet_len)
+{
+ size_t i = 0;
+ size_t data_len;
+ size_t packet_size_len;
+ char *message;
+ int rc;
+
+ /*
+ * ***** TAG 64 Packet Format *****
+ * | Content Type | 1 byte |
+ * | Key Identifier Size | 1 or 2 bytes |
+ * | Key Identifier | arbitrary |
+ * | Encrypted File Encryption Key Size | 1 or 2 bytes |
+ * | Encrypted File Encryption Key | arbitrary |
+ */
+ data_len = (5 + ECRYPTFS_SIG_SIZE_HEX
+ + session_key->encrypted_key_size);
+ *packet = kmalloc(data_len, GFP_KERNEL);
+ message = *packet;
+ if (!message) {
+ ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+ message[i++] = ECRYPTFS_TAG_64_PACKET_TYPE;
+ rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
+ &packet_size_len);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet "
+ "header; cannot generate packet length\n");
+ goto out;
+ }
+ i += packet_size_len;
+ memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX);
+ i += ECRYPTFS_SIG_SIZE_HEX;
+ rc = write_packet_length(&message[i], session_key->encrypted_key_size,
+ &packet_size_len);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet "
+ "header; cannot generate packet length\n");
+ goto out;
+ }
+ i += packet_size_len;
+ memcpy(&message[i], session_key->encrypted_key,
+ session_key->encrypted_key_size);
+ i += session_key->encrypted_key_size;
+ *packet_len = i;
+out:
+ return rc;
+}
+
+static int
+parse_tag_65_packet(struct ecryptfs_session_key *session_key, u16 *cipher_code,
+ struct ecryptfs_message *msg)
+{
+ size_t i = 0;
+ char *data;
+ size_t data_len;
+ size_t m_size;
+ size_t message_len;
+ u16 checksum = 0;
+ u16 expected_checksum = 0;
+ int rc;
+
+ /*
+ * ***** TAG 65 Packet Format *****
+ * | Content Type | 1 byte |
+ * | Status Indicator | 1 byte |
+ * | File Encryption Key Size | 1 or 2 bytes |
+ * | File Encryption Key | arbitrary |
+ */
+ message_len = msg->data_len;
+ data = msg->data;
+ if (message_len < 4) {
+ rc = -EIO;
+ goto out;
+ }
+ if (data[i++] != ECRYPTFS_TAG_65_PACKET_TYPE) {
+ ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_65\n");
+ rc = -EIO;
+ goto out;
+ }
+ if (data[i++]) {
+ ecryptfs_printk(KERN_ERR, "Status indicator has non-zero value "
+ "[%d]\n", data[i-1]);
+ rc = -EIO;
+ goto out;
+ }
+ rc = parse_packet_length(&data[i], &m_size, &data_len);
+ if (rc) {
+ ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
+ "rc = [%d]\n", rc);
+ goto out;
+ }
+ i += data_len;
+ if (message_len < (i + m_size)) {
+ ecryptfs_printk(KERN_ERR, "The received netlink message is "
+ "shorter than expected\n");
+ rc = -EIO;
+ goto out;
+ }
+ if (m_size < 3) {
+ ecryptfs_printk(KERN_ERR,
+ "The decrypted key is not long enough to "
+ "include a cipher code and checksum\n");
+ rc = -EIO;
+ goto out;
+ }
+ *cipher_code = data[i++];
+ /* The decrypted key includes 1 byte cipher code and 2 byte checksum */
+ session_key->decrypted_key_size = m_size - 3;
+ if (session_key->decrypted_key_size > ECRYPTFS_MAX_KEY_BYTES) {
+ ecryptfs_printk(KERN_ERR, "key_size [%d] larger than "
+ "the maximum key size [%d]\n",
+ session_key->decrypted_key_size,
+ ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
+ rc = -EIO;
+ goto out;
+ }
+ memcpy(session_key->decrypted_key, &data[i],
+ session_key->decrypted_key_size);
+ i += session_key->decrypted_key_size;
+ expected_checksum += (unsigned char)(data[i++]) << 8;
+ expected_checksum += (unsigned char)(data[i++]);
+ for (i = 0; i < session_key->decrypted_key_size; i++)
+ checksum += session_key->decrypted_key[i];
+ if (expected_checksum != checksum) {
+ ecryptfs_printk(KERN_ERR, "Invalid checksum for file "
+ "encryption key; expected [%x]; calculated "
+ "[%x]\n", expected_checksum, checksum);
+ rc = -EIO;
+ }
+out:
+ return rc;
+}
+
+
+static int
+write_tag_66_packet(char *signature, size_t cipher_code,
+ struct ecryptfs_crypt_stat *crypt_stat, char **packet,
+ size_t *packet_len)
+{
+ size_t i = 0;
+ size_t j;
+ size_t data_len;
+ size_t checksum = 0;
+ size_t packet_size_len;
+ char *message;
+ int rc;
+
+ /*
+ * ***** TAG 66 Packet Format *****
+ * | Content Type | 1 byte |
+ * | Key Identifier Size | 1 or 2 bytes |
+ * | Key Identifier | arbitrary |
+ * | File Encryption Key Size | 1 or 2 bytes |
+ * | File Encryption Key | arbitrary |
+ */
+ data_len = (5 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size);
+ *packet = kmalloc(data_len, GFP_KERNEL);
+ message = *packet;
+ if (!message) {
+ ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+ message[i++] = ECRYPTFS_TAG_66_PACKET_TYPE;
+ rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
+ &packet_size_len);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet "
+ "header; cannot generate packet length\n");
+ goto out;
+ }
+ i += packet_size_len;
+ memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX);
+ i += ECRYPTFS_SIG_SIZE_HEX;
+ /* The encrypted key includes 1 byte cipher code and 2 byte checksum */
+ rc = write_packet_length(&message[i], crypt_stat->key_size + 3,
+ &packet_size_len);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet "
+ "header; cannot generate packet length\n");
+ goto out;
+ }
+ i += packet_size_len;
+ message[i++] = cipher_code;
+ memcpy(&message[i], crypt_stat->key, crypt_stat->key_size);
+ i += crypt_stat->key_size;
+ for (j = 0; j < crypt_stat->key_size; j++)
+ checksum += crypt_stat->key[j];
+ message[i++] = (checksum / 256) % 256;
+ message[i++] = (checksum % 256);
+ *packet_len = i;
+out:
+ return rc;
+}
+
+static int
+parse_tag_67_packet(struct ecryptfs_key_record *key_rec,
+ struct ecryptfs_message *msg)
+{
+ size_t i = 0;
+ char *data;
+ size_t data_len;
+ size_t message_len;
+ int rc;
+
+ /*
+ * ***** TAG 65 Packet Format *****
+ * | Content Type | 1 byte |
+ * | Status Indicator | 1 byte |
+ * | Encrypted File Encryption Key Size | 1 or 2 bytes |
+ * | Encrypted File Encryption Key | arbitrary |
+ */
+ message_len = msg->data_len;
+ data = msg->data;
+ /* verify that everything through the encrypted FEK size is present */
+ if (message_len < 4) {
+ rc = -EIO;
+ goto out;
+ }
+ if (data[i++] != ECRYPTFS_TAG_67_PACKET_TYPE) {
+ ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_67\n");
+ rc = -EIO;
+ goto out;
+ }
+ if (data[i++]) {
+ ecryptfs_printk(KERN_ERR, "Status indicator has non zero value"
+ " [%d]\n", data[i-1]);
+ rc = -EIO;
+ goto out;
+ }
+ rc = parse_packet_length(&data[i], &key_rec->enc_key_size, &data_len);
+ if (rc) {
+ ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
+ "rc = [%d]\n", rc);
+ goto out;
+ }
+ i += data_len;
+ if (message_len < (i + key_rec->enc_key_size)) {
+ ecryptfs_printk(KERN_ERR, "message_len [%d]; max len is [%d]\n",
+ message_len, (i + key_rec->enc_key_size));
+ rc = -EIO;
+ goto out;
+ }
+ if (key_rec->enc_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
+ ecryptfs_printk(KERN_ERR, "Encrypted key_size [%d] larger than "
+ "the maximum key size [%d]\n",
+ key_rec->enc_key_size,
+ ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
+ rc = -EIO;
+ goto out;
+ }
+ memcpy(key_rec->enc_key, &data[i], key_rec->enc_key_size);
+out:
+ return rc;
+}
+
+/**
+ * decrypt_pki_encrypted_session_key - Decrypt the session key with
+ * the given auth_tok.
+ *
+ * Returns Zero on success; non-zero error otherwise.
+ */
+static int decrypt_pki_encrypted_session_key(
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+ struct ecryptfs_auth_tok *auth_tok,
+ struct ecryptfs_crypt_stat *crypt_stat)
+{
+ u16 cipher_code = 0;
+ struct ecryptfs_msg_ctx *msg_ctx;
+ struct ecryptfs_message *msg = NULL;
+ char *netlink_message;
+ size_t netlink_message_length;
+ int rc;
+
+ rc = write_tag_64_packet(mount_crypt_stat->global_auth_tok_sig,
+ &(auth_tok->session_key),
+ &netlink_message, &netlink_message_length);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Failed to write tag 64 packet");
+ goto out;
+ }
+ rc = ecryptfs_send_message(ecryptfs_transport, netlink_message,
+ netlink_message_length, &msg_ctx);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error sending netlink message\n");
+ goto out;
+ }
+ rc = ecryptfs_wait_for_response(msg_ctx, &msg);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Failed to receive tag 65 packet "
+ "from the user space daemon\n");
+ rc = -EIO;
+ goto out;
+ }
+ rc = parse_tag_65_packet(&(auth_tok->session_key),
+ &cipher_code, msg);
+ if (rc) {
+ printk(KERN_ERR "Failed to parse tag 65 packet; rc = [%d]\n",
+ rc);
+ goto out;
+ }
+ auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY;
+ memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key,
+ auth_tok->session_key.decrypted_key_size);
+ crypt_stat->key_size = auth_tok->session_key.decrypted_key_size;
+ rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher, cipher_code);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Cipher code [%d] is invalid\n",
+ cipher_code)
+ goto out;
+ }
+ crypt_stat->flags |= ECRYPTFS_KEY_VALID;
+ if (ecryptfs_verbosity > 0) {
+ ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n");
+ ecryptfs_dump_hex(crypt_stat->key,
+ crypt_stat->key_size);
+ }
+out:
+ if (msg)
+ kfree(msg);
+ return rc;
+}
+
+static void wipe_auth_tok_list(struct list_head *auth_tok_list_head)
+{
+ struct list_head *walker;
+ struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
+
+ walker = auth_tok_list_head->next;
+ while (walker != auth_tok_list_head) {
+ auth_tok_list_item =
+ list_entry(walker, struct ecryptfs_auth_tok_list_item,
+ list);
+ walker = auth_tok_list_item->list.next;
+ memset(auth_tok_list_item, 0,
+ sizeof(struct ecryptfs_auth_tok_list_item));
+ kmem_cache_free(ecryptfs_auth_tok_list_item_cache,
+ auth_tok_list_item);
+ }
+ auth_tok_list_head->next = NULL;
+}
+
+struct kmem_cache *ecryptfs_auth_tok_list_item_cache;
+
+
+/**
+ * parse_tag_1_packet
+ * @crypt_stat: The cryptographic context to modify based on packet
+ * contents.
+ * @data: The raw bytes of the packet.
+ * @auth_tok_list: eCryptfs parses packets into authentication tokens;
+ * a new authentication token will be placed at the end
+ * of this list for this packet.
+ * @new_auth_tok: Pointer to a pointer to memory that this function
+ * allocates; sets the memory address of the pointer to
+ * NULL on error. This object is added to the
+ * auth_tok_list.
+ * @packet_size: This function writes the size of the parsed packet
+ * into this memory location; zero on error.
+ *
+ * Returns zero on success; non-zero on error.
+ */
+static int
+parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,
+ unsigned char *data, struct list_head *auth_tok_list,
+ struct ecryptfs_auth_tok **new_auth_tok,
+ size_t *packet_size, size_t max_packet_size)
+{
+ size_t body_size;
+ struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
+ size_t length_size;
+ int rc = 0;
+
+ (*packet_size) = 0;
+ (*new_auth_tok) = NULL;
+
+ /* we check that:
+ * one byte for the Tag 1 ID flag
+ * two bytes for the body size
+ * do not exceed the maximum_packet_size
+ */
+ if (unlikely((*packet_size) + 3 > max_packet_size)) {
+ ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+ rc = -EINVAL;
+ goto out;
+ }
+ /* check for Tag 1 identifier - one byte */
+ if (data[(*packet_size)++] != ECRYPTFS_TAG_1_PACKET_TYPE) {
+ ecryptfs_printk(KERN_ERR, "Enter w/ first byte != 0x%.2x\n",
+ ECRYPTFS_TAG_1_PACKET_TYPE);
+ rc = -EINVAL;
+ goto out;
+ }
+ /* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or
+ * at end of function upon failure */
+ auth_tok_list_item =
+ kmem_cache_alloc(ecryptfs_auth_tok_list_item_cache,
+ GFP_KERNEL);
+ if (!auth_tok_list_item) {
+ ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+ memset(auth_tok_list_item, 0,
+ sizeof(struct ecryptfs_auth_tok_list_item));
+ (*new_auth_tok) = &auth_tok_list_item->auth_tok;
+ /* check for body size - one to two bytes
+ *
+ * ***** TAG 1 Packet Format *****
+ * | version number | 1 byte |
+ * | key ID | 8 bytes |
+ * | public key algorithm | 1 byte |
+ * | encrypted session key | arbitrary |
+ */
+ rc = parse_packet_length(&data[(*packet_size)], &body_size,
+ &length_size);
+ if (rc) {
+ ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
+ "rc = [%d]\n", rc);
+ goto out_free;
+ }
+ if (unlikely(body_size < (0x02 + ECRYPTFS_SIG_SIZE))) {
+ ecryptfs_printk(KERN_WARNING, "Invalid body size ([%d])\n",
+ body_size);
+ rc = -EINVAL;
+ goto out_free;
+ }
+ (*packet_size) += length_size;
+ if (unlikely((*packet_size) + body_size > max_packet_size)) {
+ ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+ rc = -EINVAL;
+ goto out_free;
+ }
+ /* Version 3 (from RFC2440) - one byte */
+ if (unlikely(data[(*packet_size)++] != 0x03)) {
+ ecryptfs_printk(KERN_DEBUG, "Unknown version number "
+ "[%d]\n", data[(*packet_size) - 1]);
+ rc = -EINVAL;
+ goto out_free;
+ }
+ /* Read Signature */
+ ecryptfs_to_hex((*new_auth_tok)->token.private_key.signature,
+ &data[(*packet_size)], ECRYPTFS_SIG_SIZE);
+ *packet_size += ECRYPTFS_SIG_SIZE;
+ /* This byte is skipped because the kernel does not need to
+ * know which public key encryption algorithm was used */
+ (*packet_size)++;
+ (*new_auth_tok)->session_key.encrypted_key_size =
+ body_size - (0x02 + ECRYPTFS_SIG_SIZE);
+ if ((*new_auth_tok)->session_key.encrypted_key_size
+ > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
+ ecryptfs_printk(KERN_ERR, "Tag 1 packet contains key larger "
+ "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES");
+ rc = -EINVAL;
+ goto out;
+ }
+ ecryptfs_printk(KERN_DEBUG, "Encrypted key size = [%d]\n",
+ (*new_auth_tok)->session_key.encrypted_key_size);
+ memcpy((*new_auth_tok)->session_key.encrypted_key,
+ &data[(*packet_size)], (body_size - 0x02 - ECRYPTFS_SIG_SIZE));
+ (*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size;
+ (*new_auth_tok)->session_key.flags &=
+ ~ECRYPTFS_CONTAINS_DECRYPTED_KEY;
+ (*new_auth_tok)->session_key.flags |=
+ ECRYPTFS_CONTAINS_ENCRYPTED_KEY;
+ (*new_auth_tok)->token_type = ECRYPTFS_PRIVATE_KEY;
+ (*new_auth_tok)->flags |= ECRYPTFS_PRIVATE_KEY;
+ /* TODO: Why are we setting this flag here? Don't we want the
+ * userspace to decrypt the session key? */
+ (*new_auth_tok)->session_key.flags &=
+ ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
+ (*new_auth_tok)->session_key.flags &=
+ ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
+ list_add(&auth_tok_list_item->list, auth_tok_list);
+ goto out;
+out_free:
+ (*new_auth_tok) = NULL;
+ memset(auth_tok_list_item, 0,
+ sizeof(struct ecryptfs_auth_tok_list_item));
+ kmem_cache_free(ecryptfs_auth_tok_list_item_cache,
+ auth_tok_list_item);
+out:
+ if (rc)
+ (*packet_size) = 0;
+ return rc;
+}
+
/**
* parse_tag_3_packet
* @crypt_stat: The cryptographic context to modify based on packet
@@ -178,10 +652,10 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
struct ecryptfs_auth_tok **new_auth_tok,
size_t *packet_size, size_t max_packet_size)
{
- int rc = 0;
size_t body_size;
struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
size_t length_size;
+ int rc = 0;
(*packet_size) = 0;
(*new_auth_tok) = NULL;
@@ -207,14 +681,12 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
/* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or
* at end of function upon failure */
auth_tok_list_item =
- kmem_cache_alloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL);
+ kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL);
if (!auth_tok_list_item) {
ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
rc = -ENOMEM;
goto out;
}
- memset(auth_tok_list_item, 0,
- sizeof(struct ecryptfs_auth_tok_list_item));
(*new_auth_tok) = &auth_tok_list_item->auth_tok;
/* check for body size - one to two bytes */
@@ -321,10 +793,10 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
(*new_auth_tok)->token_type = ECRYPTFS_PASSWORD;
/* TODO: Parametarize; we might actually want userspace to
* decrypt the session key. */
- ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags,
- ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
- ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags,
- ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
+ (*new_auth_tok)->session_key.flags &=
+ ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
+ (*new_auth_tok)->session_key.flags &=
+ ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
list_add(&auth_tok_list_item->list, auth_tok_list);
goto out;
out_free:
@@ -360,9 +832,9 @@ parse_tag_11_packet(unsigned char *data, unsigned char *contents,
size_t max_contents_bytes, size_t *tag_11_contents_size,
size_t *packet_size, size_t max_packet_size)
{
- int rc = 0;
size_t body_size;
size_t length_size;
+ int rc = 0;
(*packet_size) = 0;
(*tag_11_contents_size) = 0;
@@ -461,7 +933,6 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
struct ecryptfs_password *password_s_ptr;
struct scatterlist src_sg[2], dst_sg[2];
struct mutex *tfm_mutex = NULL;
- /* TODO: Use virt_to_scatterlist for these */
char *encrypted_session_key;
char *session_key;
struct blkcipher_desc desc = {
@@ -470,8 +941,7 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
int rc = 0;
password_s_ptr = &auth_tok->token.password;
- if (ECRYPTFS_CHECK_FLAG(password_s_ptr->flags,
- ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET))
+ if (password_s_ptr->flags & ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET)
ecryptfs_printk(KERN_DEBUG, "Session key encryption key "
"set; skipping key generation\n");
ecryptfs_printk(KERN_DEBUG, "Session key encryption key (size [%d])"
@@ -553,7 +1023,7 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY;
memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key,
auth_tok->session_key.decrypted_key_size);
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+ crypt_stat->flags |= ECRYPTFS_KEY_VALID;
ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n");
if (ecryptfs_verbosity > 0)
ecryptfs_dump_hex(crypt_stat->key,
@@ -589,7 +1059,6 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
struct dentry *ecryptfs_dentry)
{
size_t i = 0;
- int rc = 0;
size_t found_auth_tok = 0;
size_t next_packet_is_auth_tok_packet;
char sig[ECRYPTFS_SIG_SIZE_HEX];
@@ -605,6 +1074,7 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
unsigned char sig_tmp_space[ECRYPTFS_SIG_SIZE];
size_t tag_11_contents_size;
size_t tag_11_packet_size;
+ int rc = 0;
INIT_LIST_HEAD(&auth_tok_list);
/* Parse the header to find as many packets as we can, these will be
@@ -656,8 +1126,21 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
sig_tmp_space, tag_11_contents_size);
new_auth_tok->token.password.signature[
ECRYPTFS_PASSWORD_SIG_SIZE] = '\0';
- ECRYPTFS_SET_FLAG(crypt_stat->flags,
- ECRYPTFS_ENCRYPTED);
+ crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
+ break;
+ case ECRYPTFS_TAG_1_PACKET_TYPE:
+ rc = parse_tag_1_packet(crypt_stat,
+ (unsigned char *)&src[i],
+ &auth_tok_list, &new_auth_tok,
+ &packet_size, max_packet_size);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error parsing "
+ "tag 1 packet\n");
+ rc = -EIO;
+ goto out_wipe_list;
+ }
+ i += packet_size;
+ crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
break;
case ECRYPTFS_TAG_11_PACKET_TYPE:
ecryptfs_printk(KERN_WARNING, "Invalid packet set "
@@ -706,31 +1189,46 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
goto leave_list;
/* TODO: Transfer the common salt into the
* crypt_stat salt */
+ } else if ((candidate_auth_tok->token_type
+ == ECRYPTFS_PRIVATE_KEY)
+ && !strncmp(candidate_auth_tok->token.private_key.signature,
+ sig, ECRYPTFS_SIG_SIZE_HEX)) {
+ found_auth_tok = 1;
+ goto leave_list;
}
}
-leave_list:
if (!found_auth_tok) {
ecryptfs_printk(KERN_ERR, "Could not find authentication "
"token on temporary list for sig [%.*s]\n",
ECRYPTFS_SIG_SIZE_HEX, sig);
rc = -EIO;
goto out_wipe_list;
- } else {
+ }
+leave_list:
+ rc = -ENOTSUPP;
+ if (candidate_auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
+ memcpy(&(candidate_auth_tok->token.private_key),
+ &(chosen_auth_tok->token.private_key),
+ sizeof(struct ecryptfs_private_key));
+ rc = decrypt_pki_encrypted_session_key(mount_crypt_stat,
+ candidate_auth_tok,
+ crypt_stat);
+ } else if (candidate_auth_tok->token_type == ECRYPTFS_PASSWORD) {
memcpy(&(candidate_auth_tok->token.password),
&(chosen_auth_tok->token.password),
sizeof(struct ecryptfs_password));
rc = decrypt_session_key(candidate_auth_tok, crypt_stat);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error decrypting the "
- "session key\n");
- goto out_wipe_list;
- }
- rc = ecryptfs_compute_root_iv(crypt_stat);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error computing "
- "the root IV\n");
- goto out_wipe_list;
- }
+ }
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error decrypting the "
+ "session key; rc = [%d]\n", rc);
+ goto out_wipe_list;
+ }
+ rc = ecryptfs_compute_root_iv(crypt_stat);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error computing "
+ "the root IV\n");
+ goto out_wipe_list;
}
rc = ecryptfs_init_crypt_ctx(crypt_stat);
if (rc) {
@@ -743,6 +1241,145 @@ out_wipe_list:
out:
return rc;
}
+static int
+pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ struct ecryptfs_key_record *key_rec)
+{
+ struct ecryptfs_msg_ctx *msg_ctx = NULL;
+ char *netlink_payload;
+ size_t netlink_payload_length;
+ struct ecryptfs_message *msg;
+ int rc;
+
+ rc = write_tag_66_packet(auth_tok->token.private_key.signature,
+ ecryptfs_code_for_cipher_string(crypt_stat),
+ crypt_stat, &netlink_payload,
+ &netlink_payload_length);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n");
+ goto out;
+ }
+ rc = ecryptfs_send_message(ecryptfs_transport, netlink_payload,
+ netlink_payload_length, &msg_ctx);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error sending netlink message\n");
+ goto out;
+ }
+ rc = ecryptfs_wait_for_response(msg_ctx, &msg);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Failed to receive tag 67 packet "
+ "from the user space daemon\n");
+ rc = -EIO;
+ goto out;
+ }
+ rc = parse_tag_67_packet(key_rec, msg);
+ if (rc)
+ ecryptfs_printk(KERN_ERR, "Error parsing tag 67 packet\n");
+ kfree(msg);
+out:
+ if (netlink_payload)
+ kfree(netlink_payload);
+ return rc;
+}
+/**
+ * write_tag_1_packet - Write an RFC2440-compatible tag 1 (public key) packet
+ * @dest: Buffer into which to write the packet
+ * @max: Maximum number of bytes that can be writtn
+ * @packet_size: This function will write the number of bytes that end
+ * up constituting the packet; set to zero on error
+ *
+ * Returns zero on success; non-zero on error.
+ */
+static int
+write_tag_1_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+ struct ecryptfs_key_record *key_rec, size_t *packet_size)
+{
+ size_t i;
+ size_t encrypted_session_key_valid = 0;
+ size_t key_rec_size;
+ size_t packet_size_length;
+ int rc = 0;
+
+ (*packet_size) = 0;
+ ecryptfs_from_hex(key_rec->sig, auth_tok->token.private_key.signature,
+ ECRYPTFS_SIG_SIZE);
+ encrypted_session_key_valid = 0;
+ for (i = 0; i < crypt_stat->key_size; i++)
+ encrypted_session_key_valid |=
+ auth_tok->session_key.encrypted_key[i];
+ if (encrypted_session_key_valid) {
+ memcpy(key_rec->enc_key,
+ auth_tok->session_key.encrypted_key,
+ auth_tok->session_key.encrypted_key_size);
+ goto encrypted_session_key_set;
+ }
+ if (auth_tok->session_key.encrypted_key_size == 0)
+ auth_tok->session_key.encrypted_key_size =
+ auth_tok->token.private_key.key_size;
+ rc = pki_encrypt_session_key(auth_tok, crypt_stat, key_rec);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Failed to encrypt session key "
+ "via a pki");
+ goto out;
+ }
+ if (ecryptfs_verbosity > 0) {
+ ecryptfs_printk(KERN_DEBUG, "Encrypted key:\n");
+ ecryptfs_dump_hex(key_rec->enc_key, key_rec->enc_key_size);
+ }
+encrypted_session_key_set:
+ /* Now we have a valid key_rec. Append it to the
+ * key_rec set. */
+ key_rec_size = (sizeof(struct ecryptfs_key_record)
+ - ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES
+ + (key_rec->enc_key_size));
+ /* TODO: Include a packet size limit as a parameter to this
+ * function once we have multi-packet headers (for versions
+ * later than 0.1 */
+ if (key_rec_size >= ECRYPTFS_MAX_KEYSET_SIZE) {
+ ecryptfs_printk(KERN_ERR, "Keyset too large\n");
+ rc = -EINVAL;
+ goto out;
+ }
+ /* ***** TAG 1 Packet Format *****
+ * | version number | 1 byte |
+ * | key ID | 8 bytes |
+ * | public key algorithm | 1 byte |
+ * | encrypted session key | arbitrary |
+ */
+ if ((0x02 + ECRYPTFS_SIG_SIZE + key_rec->enc_key_size) >= max) {
+ ecryptfs_printk(KERN_ERR,
+ "Authentication token is too large\n");
+ rc = -EINVAL;
+ goto out;
+ }
+ dest[(*packet_size)++] = ECRYPTFS_TAG_1_PACKET_TYPE;
+ /* This format is inspired by OpenPGP; see RFC 2440
+ * packet tag 1 */
+ rc = write_packet_length(&dest[(*packet_size)],
+ (0x02 + ECRYPTFS_SIG_SIZE +
+ key_rec->enc_key_size),
+ &packet_size_length);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Error generating tag 1 packet "
+ "header; cannot generate packet length\n");
+ goto out;
+ }
+ (*packet_size) += packet_size_length;
+ dest[(*packet_size)++] = 0x03; /* version 3 */
+ memcpy(&dest[(*packet_size)], key_rec->sig, ECRYPTFS_SIG_SIZE);
+ (*packet_size) += ECRYPTFS_SIG_SIZE;
+ dest[(*packet_size)++] = RFC2440_CIPHER_RSA;
+ memcpy(&dest[(*packet_size)], key_rec->enc_key,
+ key_rec->enc_key_size);
+ (*packet_size) += key_rec->enc_key_size;
+out:
+ if (rc)
+ (*packet_size) = 0;
+ return rc;
+}
/**
* write_tag_11_packet
@@ -758,8 +1395,8 @@ static int
write_tag_11_packet(char *dest, int max, char *contents, size_t contents_length,
size_t *packet_length)
{
- int rc = 0;
size_t packet_size_length;
+ int rc = 0;
(*packet_length) = 0;
if ((13 + contents_length) > max) {
@@ -817,7 +1454,6 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
struct ecryptfs_key_record *key_rec, size_t *packet_size)
{
size_t i;
- size_t signature_is_valid = 0;
size_t encrypted_session_key_valid = 0;
char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
struct scatterlist dest_sg[2];
@@ -833,19 +1469,14 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
int rc = 0;
(*packet_size) = 0;
- /* Check for a valid signature on the auth_tok */
- for (i = 0; i < ECRYPTFS_SIG_SIZE_HEX; i++)
- signature_is_valid |= auth_tok->token.password.signature[i];
- if (!signature_is_valid)
- BUG();
- ecryptfs_from_hex((*key_rec).sig, auth_tok->token.password.signature,
+ ecryptfs_from_hex(key_rec->sig, auth_tok->token.password.signature,
ECRYPTFS_SIG_SIZE);
encrypted_session_key_valid = 0;
for (i = 0; i < crypt_stat->key_size; i++)
encrypted_session_key_valid |=
auth_tok->session_key.encrypted_key[i];
if (encrypted_session_key_valid) {
- memcpy((*key_rec).enc_key,
+ memcpy(key_rec->enc_key,
auth_tok->session_key.encrypted_key,
auth_tok->session_key.encrypted_key_size);
goto encrypted_session_key_set;
@@ -858,10 +1489,10 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
memset((crypt_stat->key + 24), 0, 8);
auth_tok->session_key.encrypted_key_size = 32;
}
- (*key_rec).enc_key_size =
+ key_rec->enc_key_size =
auth_tok->session_key.encrypted_key_size;
- if (ECRYPTFS_CHECK_FLAG(auth_tok->token.password.flags,
- ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET)) {
+ if (auth_tok->token.password.flags &
+ ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET) {
ecryptfs_printk(KERN_DEBUG, "Using previously generated "
"session key encryption key of size [%d]\n",
auth_tok->token.password.
@@ -879,15 +1510,15 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
ecryptfs_dump_hex(session_key_encryption_key, 16);
}
rc = virt_to_scatterlist(crypt_stat->key,
- (*key_rec).enc_key_size, src_sg, 2);
+ key_rec->enc_key_size, src_sg, 2);
if (!rc) {
ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
"for crypt_stat session key\n");
rc = -ENOMEM;
goto out;
}
- rc = virt_to_scatterlist((*key_rec).enc_key,
- (*key_rec).enc_key_size, dest_sg, 2);
+ rc = virt_to_scatterlist(key_rec->enc_key,
+ key_rec->enc_key_size, dest_sg, 2);
if (!rc) {
ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
"for crypt_stat encrypted session key\n");
@@ -943,14 +1574,14 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
mutex_unlock(tfm_mutex);
ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n");
if (ecryptfs_verbosity > 0)
- ecryptfs_dump_hex((*key_rec).enc_key,
- (*key_rec).enc_key_size);
+ ecryptfs_dump_hex(key_rec->enc_key,
+ key_rec->enc_key_size);
encrypted_session_key_set:
/* Now we have a valid key_rec. Append it to the
* key_rec set. */
key_rec_size = (sizeof(struct ecryptfs_key_record)
- ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES
- + ((*key_rec).enc_key_size));
+ + (key_rec->enc_key_size));
/* TODO: Include a packet size limit as a parameter to this
* function once we have multi-packet headers (for versions
* later than 0.1 */
@@ -962,7 +1593,7 @@ encrypted_session_key_set:
/* TODO: Packet size limit */
/* We have 5 bytes of surrounding packet data */
if ((0x05 + ECRYPTFS_SALT_SIZE
- + (*key_rec).enc_key_size) >= max) {
+ + key_rec->enc_key_size) >= max) {
ecryptfs_printk(KERN_ERR, "Authentication token is too "
"large\n");
rc = -EINVAL;
@@ -974,7 +1605,7 @@ encrypted_session_key_set:
/* ver+cipher+s2k+hash+salt+iter+enc_key */
rc = write_packet_length(&dest[(*packet_size)],
(0x05 + ECRYPTFS_SALT_SIZE
- + (*key_rec).enc_key_size),
+ + key_rec->enc_key_size),
&packet_size_length);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error generating tag 3 packet "
@@ -997,9 +1628,9 @@ encrypted_session_key_set:
ECRYPTFS_SALT_SIZE);
(*packet_size) += ECRYPTFS_SALT_SIZE; /* salt */
dest[(*packet_size)++] = 0x60; /* hash iterations (65536) */
- memcpy(&dest[(*packet_size)], (*key_rec).enc_key,
- (*key_rec).enc_key_size);
- (*packet_size) += (*key_rec).enc_key_size;
+ memcpy(&dest[(*packet_size)], key_rec->enc_key,
+ key_rec->enc_key_size);
+ (*packet_size) += key_rec->enc_key_size;
out:
if (desc.tfm && !tfm_mutex)
crypto_free_blkcipher(desc.tfm);
@@ -1029,13 +1660,13 @@ ecryptfs_generate_key_packet_set(char *dest_base,
struct dentry *ecryptfs_dentry, size_t *len,
size_t max)
{
- int rc = 0;
struct ecryptfs_auth_tok *auth_tok;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
&ecryptfs_superblock_to_private(
ecryptfs_dentry->d_sb)->mount_crypt_stat;
size_t written;
struct ecryptfs_key_record key_rec;
+ int rc = 0;
(*len) = 0;
if (mount_crypt_stat->global_auth_tok) {
@@ -1062,20 +1693,23 @@ ecryptfs_generate_key_packet_set(char *dest_base,
goto out;
}
(*len) += written;
+ } else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
+ rc = write_tag_1_packet(dest_base + (*len),
+ max, auth_tok,
+ crypt_stat,mount_crypt_stat,
+ &key_rec, &written);
+ if (rc) {
+ ecryptfs_printk(KERN_WARNING, "Error "
+ "writing tag 1 packet\n");
+ goto out;
+ }
+ (*len) += written;
} else {
ecryptfs_printk(KERN_WARNING, "Unsupported "
"authentication token type\n");
rc = -EINVAL;
goto out;
}
- if (rc) {
- ecryptfs_printk(KERN_WARNING, "Error writing "
- "authentication token packet with sig "
- "= [%s]\n",
- mount_crypt_stat->global_auth_tok_sig);
- rc = -EIO;
- goto out;
- }
} else
BUG();
if (likely((max - (*len)) > 0)) {
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index d0541ae8fab..26fe405a576 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -3,9 +3,10 @@
*
* Copyright (C) 1997-2003 Erez Zadok
* Copyright (C) 2001-2003 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
* Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
* Michael C. Thompson <mcthomps@us.ibm.com>
+ * Tyler Hicks <tyhicks@ou.edu>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -48,6 +49,43 @@ MODULE_PARM_DESC(ecryptfs_verbosity,
"Initial verbosity level (0 or 1; defaults to "
"0, which is Quiet)");
+/**
+ * Module parameter that defines the number of netlink message buffer
+ * elements
+ */
+unsigned int ecryptfs_message_buf_len = ECRYPTFS_DEFAULT_MSG_CTX_ELEMS;
+
+module_param(ecryptfs_message_buf_len, uint, 0);
+MODULE_PARM_DESC(ecryptfs_message_buf_len,
+ "Number of message buffer elements");
+
+/**
+ * Module parameter that defines the maximum guaranteed amount of time to wait
+ * for a response through netlink. The actual sleep time will be, more than
+ * likely, a small amount greater than this specified value, but only less if
+ * the netlink message successfully arrives.
+ */
+signed long ecryptfs_message_wait_timeout = ECRYPTFS_MAX_MSG_CTX_TTL / HZ;
+
+module_param(ecryptfs_message_wait_timeout, long, 0);
+MODULE_PARM_DESC(ecryptfs_message_wait_timeout,
+ "Maximum number of seconds that an operation will "
+ "sleep while waiting for a message response from "
+ "userspace");
+
+/**
+ * Module parameter that is an estimate of the maximum number of users
+ * that will be concurrently using eCryptfs. Set this to the right
+ * value to balance performance and memory use.
+ */
+unsigned int ecryptfs_number_of_users = ECRYPTFS_DEFAULT_NUM_USERS;
+
+module_param(ecryptfs_number_of_users, uint, 0);
+MODULE_PARM_DESC(ecryptfs_number_of_users, "An estimate of the number of "
+ "concurrent users of eCryptfs");
+
+unsigned int ecryptfs_transport = ECRYPTFS_DEFAULT_TRANSPORT;
+
void __ecryptfs_printk(const char *fmt, ...)
{
va_list args;
@@ -124,7 +162,8 @@ out:
enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, ecryptfs_opt_debug,
ecryptfs_opt_ecryptfs_debug, ecryptfs_opt_cipher,
ecryptfs_opt_ecryptfs_cipher, ecryptfs_opt_ecryptfs_key_bytes,
- ecryptfs_opt_passthrough, ecryptfs_opt_err };
+ ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata,
+ ecryptfs_opt_encrypted_view, ecryptfs_opt_err };
static match_table_t tokens = {
{ecryptfs_opt_sig, "sig=%s"},
@@ -135,6 +174,8 @@ static match_table_t tokens = {
{ecryptfs_opt_ecryptfs_cipher, "ecryptfs_cipher=%s"},
{ecryptfs_opt_ecryptfs_key_bytes, "ecryptfs_key_bytes=%u"},
{ecryptfs_opt_passthrough, "ecryptfs_passthrough"},
+ {ecryptfs_opt_xattr_metadata, "ecryptfs_xattr_metadata"},
+ {ecryptfs_opt_encrypted_view, "ecryptfs_encrypted_view"},
{ecryptfs_opt_err, NULL}
};
@@ -275,6 +316,16 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
mount_crypt_stat->flags |=
ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED;
break;
+ case ecryptfs_opt_xattr_metadata:
+ mount_crypt_stat->flags |=
+ ECRYPTFS_XATTR_METADATA_ENABLED;
+ break;
+ case ecryptfs_opt_encrypted_view:
+ mount_crypt_stat->flags |=
+ ECRYPTFS_XATTR_METADATA_ENABLED;
+ mount_crypt_stat->flags |=
+ ECRYPTFS_ENCRYPTED_VIEW_ENABLED;
+ break;
case ecryptfs_opt_err:
default:
ecryptfs_printk(KERN_WARNING,
@@ -347,9 +398,10 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
rc = -EINVAL;
goto out;
}
- if (auth_tok->token_type != ECRYPTFS_PASSWORD) {
+ if (auth_tok->token_type != ECRYPTFS_PASSWORD
+ && auth_tok->token_type != ECRYPTFS_PRIVATE_KEY) {
ecryptfs_printk(KERN_ERR, "Invalid auth_tok structure "
- "returned from key\n");
+ "returned from key query\n");
rc = -EINVAL;
goto out;
}
@@ -378,15 +430,13 @@ ecryptfs_fill_super(struct super_block *sb, void *raw_data, int silent)
/* Released in ecryptfs_put_super() */
ecryptfs_set_superblock_private(sb,
- kmem_cache_alloc(ecryptfs_sb_info_cache,
+ kmem_cache_zalloc(ecryptfs_sb_info_cache,
GFP_KERNEL));
if (!ecryptfs_superblock_to_private(sb)) {
ecryptfs_printk(KERN_WARNING, "Out of memory\n");
rc = -ENOMEM;
goto out;
}
- memset(ecryptfs_superblock_to_private(sb), 0,
- sizeof(struct ecryptfs_sb_info));
sb->s_op = &ecryptfs_sops;
/* Released through deactivate_super(sb) from get_sb_nodev */
sb->s_root = d_alloc(NULL, &(const struct qstr) {
@@ -402,7 +452,7 @@ ecryptfs_fill_super(struct super_block *sb, void *raw_data, int silent)
/* Released in d_release when dput(sb->s_root) is called */
/* through deactivate_super(sb) from get_sb_nodev() */
ecryptfs_set_dentry_private(sb->s_root,
- kmem_cache_alloc(ecryptfs_dentry_info_cache,
+ kmem_cache_zalloc(ecryptfs_dentry_info_cache,
GFP_KERNEL));
if (!ecryptfs_dentry_to_private(sb->s_root)) {
ecryptfs_printk(KERN_ERR,
@@ -410,8 +460,6 @@ ecryptfs_fill_super(struct super_block *sb, void *raw_data, int silent)
rc = -ENOMEM;
goto out;
}
- memset(ecryptfs_dentry_to_private(sb->s_root), 0,
- sizeof(struct ecryptfs_dentry_info));
rc = 0;
out:
/* Should be able to rely on deactivate_super called from
@@ -594,6 +642,11 @@ static struct ecryptfs_cache_info {
.size = PAGE_CACHE_SIZE,
},
{
+ .cache = &ecryptfs_xattr_cache,
+ .name = "ecryptfs_xattr_cache",
+ .size = PAGE_CACHE_SIZE,
+ },
+ {
.cache = &ecryptfs_lower_page_cache,
.name = "ecryptfs_lower_page_cache",
.size = PAGE_CACHE_SIZE,
@@ -699,7 +752,8 @@ static struct ecryptfs_version_str_map_elem {
{ECRYPTFS_VERSIONING_PASSPHRASE, "passphrase"},
{ECRYPTFS_VERSIONING_PUBKEY, "pubkey"},
{ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH, "plaintext passthrough"},
- {ECRYPTFS_VERSIONING_POLICY, "policy"}
+ {ECRYPTFS_VERSIONING_POLICY, "policy"},
+ {ECRYPTFS_VERSIONING_XATTR, "metadata in extended attribute"}
};
static ssize_t version_str_show(struct ecryptfs_obj *obj, char *buff)
@@ -798,6 +852,11 @@ static int __init ecryptfs_init(void)
ecryptfs_free_kmem_caches();
goto out;
}
+ rc = ecryptfs_init_messaging(ecryptfs_transport);
+ if (rc) {
+ ecryptfs_printk(KERN_ERR, "Failure occured while attempting to "
+ "initialize the eCryptfs netlink socket\n");
+ }
out:
return rc;
}
@@ -809,6 +868,7 @@ static void __exit ecryptfs_exit(void)
sysfs_remove_file(&ecryptfs_subsys.kset.kobj,
&sysfs_attr_version_str.attr);
subsystem_unregister(&ecryptfs_subsys);
+ ecryptfs_release_messaging(ecryptfs_transport);
unregister_filesystem(&ecryptfs_fs_type);
ecryptfs_free_kmem_caches();
}
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
new file mode 100644
index 00000000000..47d7e7b611f
--- /dev/null
+++ b/fs/ecryptfs/messaging.c
@@ -0,0 +1,515 @@
+/**
+ * eCryptfs: Linux filesystem encryption layer
+ *
+ * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
+ * Tyler Hicks <tyhicks@ou.edu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "ecryptfs_kernel.h"
+
+static LIST_HEAD(ecryptfs_msg_ctx_free_list);
+static LIST_HEAD(ecryptfs_msg_ctx_alloc_list);
+static struct mutex ecryptfs_msg_ctx_lists_mux;
+
+static struct hlist_head *ecryptfs_daemon_id_hash;
+static struct mutex ecryptfs_daemon_id_hash_mux;
+static int ecryptfs_hash_buckets;
+#define ecryptfs_uid_hash(uid) \
+ hash_long((unsigned long)uid, ecryptfs_hash_buckets)
+
+static unsigned int ecryptfs_msg_counter;
+static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr;
+
+/**
+ * ecryptfs_acquire_free_msg_ctx
+ * @msg_ctx: The context that was acquired from the free list
+ *
+ * Acquires a context element from the free list and locks the mutex
+ * on the context. Returns zero on success; non-zero on error or upon
+ * failure to acquire a free context element. Be sure to lock the
+ * list mutex before calling.
+ */
+static int ecryptfs_acquire_free_msg_ctx(struct ecryptfs_msg_ctx **msg_ctx)
+{
+ struct list_head *p;
+ int rc;
+
+ if (list_empty(&ecryptfs_msg_ctx_free_list)) {
+ ecryptfs_printk(KERN_WARNING, "The eCryptfs free "
+ "context list is empty. It may be helpful to "
+ "specify the ecryptfs_message_buf_len "
+ "parameter to be greater than the current "
+ "value of [%d]\n", ecryptfs_message_buf_len);
+ rc = -ENOMEM;
+ goto out;
+ }
+ list_for_each(p, &ecryptfs_msg_ctx_free_list) {
+ *msg_ctx = list_entry(p, struct ecryptfs_msg_ctx, node);
+ if (mutex_trylock(&(*msg_ctx)->mux)) {
+ (*msg_ctx)->task = current;
+ rc = 0;
+ goto out;
+ }
+ }
+ rc = -ENOMEM;
+out:
+ return rc;
+}
+
+/**
+ * ecryptfs_msg_ctx_free_to_alloc
+ * @msg_ctx: The context to move from the free list to the alloc list
+ *
+ * Be sure to lock the list mutex and the context mutex before
+ * calling.
+ */
+static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx)
+{
+ list_move(&msg_ctx->node, &ecryptfs_msg_ctx_alloc_list);
+ msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_PENDING;
+ msg_ctx->counter = ++ecryptfs_msg_counter;
+}
+
+/**
+ * ecryptfs_msg_ctx_alloc_to_free
+ * @msg_ctx: The context to move from the alloc list to the free list
+ *
+ * Be sure to lock the list mutex and the context mutex before
+ * calling.
+ */
+static void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx)
+{
+ list_move(&(msg_ctx->node), &ecryptfs_msg_ctx_free_list);
+ if (msg_ctx->msg)
+ kfree(msg_ctx->msg);
+ msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_FREE;
+}
+
+/**
+ * ecryptfs_find_daemon_id
+ * @uid: The user id which maps to the desired daemon id
+ * @id: If return value is zero, points to the desired daemon id
+ * pointer
+ *
+ * Search the hash list for the given user id. Returns zero if the
+ * user id exists in the list; non-zero otherwise. The daemon id hash
+ * mutex should be held before calling this function.
+ */
+static int ecryptfs_find_daemon_id(uid_t uid, struct ecryptfs_daemon_id **id)
+{
+ struct hlist_node *elem;
+ int rc;
+
+ hlist_for_each_entry(*id, elem,
+ &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)],
+ id_chain) {
+ if ((*id)->uid == uid) {
+ rc = 0;
+ goto out;
+ }
+ }
+ rc = -EINVAL;
+out:
+ return rc;
+}
+
+static int ecryptfs_send_raw_message(unsigned int transport, u16 msg_type,
+ pid_t pid)
+{
+ int rc;
+
+ switch(transport) {
+ case ECRYPTFS_TRANSPORT_NETLINK:
+ rc = ecryptfs_send_netlink(NULL, 0, NULL, msg_type, 0, pid);
+ break;
+ case ECRYPTFS_TRANSPORT_CONNECTOR:
+ case ECRYPTFS_TRANSPORT_RELAYFS:
+ default:
+ rc = -ENOSYS;
+ }
+ return rc;
+}
+
+/**
+ * ecryptfs_process_helo
+ * @transport: The underlying transport (netlink, etc.)
+ * @uid: The user ID owner of the message
+ * @pid: The process ID for the userspace program that sent the
+ * message
+ *
+ * Adds the uid and pid values to the daemon id hash. If a uid
+ * already has a daemon pid registered, the daemon will be
+ * unregistered before the new daemon id is put into the hash list.
+ * Returns zero after adding a new daemon id to the hash list;
+ * non-zero otherwise.
+ */
+int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid)
+{
+ struct ecryptfs_daemon_id *new_id;
+ struct ecryptfs_daemon_id *old_id;
+ int rc;
+
+ mutex_lock(&ecryptfs_daemon_id_hash_mux);
+ new_id = kmalloc(sizeof(*new_id), GFP_KERNEL);
+ if (!new_id) {
+ rc = -ENOMEM;
+ ecryptfs_printk(KERN_ERR, "Failed to allocate memory; unable "
+ "to register daemon [%d] for user\n", pid, uid);
+ goto unlock;
+ }
+ if (!ecryptfs_find_daemon_id(uid, &old_id)) {
+ printk(KERN_WARNING "Received request from user [%d] "
+ "to register daemon [%d]; unregistering daemon "
+ "[%d]\n", uid, pid, old_id->pid);
+ hlist_del(&old_id->id_chain);
+ rc = ecryptfs_send_raw_message(transport, ECRYPTFS_NLMSG_QUIT,
+ old_id->pid);
+ if (rc)
+ printk(KERN_WARNING "Failed to send QUIT "
+ "message to daemon [%d]; rc = [%d]\n",
+ old_id->pid, rc);
+ kfree(old_id);
+ }
+ new_id->uid = uid;
+ new_id->pid = pid;
+ hlist_add_head(&new_id->id_chain,
+ &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)]);
+ rc = 0;
+unlock:
+ mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+ return rc;
+}
+
+/**
+ * ecryptfs_process_quit
+ * @uid: The user ID owner of the message
+ * @pid: The process ID for the userspace program that sent the
+ * message
+ *
+ * Deletes the corresponding daemon id for the given uid and pid, if
+ * it is the registered that is requesting the deletion. Returns zero
+ * after deleting the desired daemon id; non-zero otherwise.
+ */
+int ecryptfs_process_quit(uid_t uid, pid_t pid)
+{
+ struct ecryptfs_daemon_id *id;
+ int rc;
+
+ mutex_lock(&ecryptfs_daemon_id_hash_mux);
+ if (ecryptfs_find_daemon_id(uid, &id)) {
+ rc = -EINVAL;
+ ecryptfs_printk(KERN_ERR, "Received request from user [%d] to "
+ "unregister unrecognized daemon [%d]\n", uid,
+ pid);
+ goto unlock;
+ }
+ if (id->pid != pid) {
+ rc = -EINVAL;
+ ecryptfs_printk(KERN_WARNING, "Received request from user [%d] "
+ "with pid [%d] to unregister daemon [%d]\n",
+ uid, pid, id->pid);
+ goto unlock;
+ }
+ hlist_del(&id->id_chain);
+ kfree(id);
+ rc = 0;
+unlock:
+ mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+ return rc;
+}
+
+/**
+ * ecryptfs_process_reponse
+ * @msg: The ecryptfs message received; the caller should sanity check
+ * msg->data_len
+ * @pid: The process ID of the userspace application that sent the
+ * message
+ * @seq: The sequence number of the message
+ *
+ * Processes a response message after sending a operation request to
+ * userspace. Returns zero upon delivery to desired context element;
+ * non-zero upon delivery failure or error.
+ */
+int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
+ pid_t pid, u32 seq)
+{
+ struct ecryptfs_daemon_id *id;
+ struct ecryptfs_msg_ctx *msg_ctx;
+ int msg_size;
+ int rc;
+
+ if (msg->index >= ecryptfs_message_buf_len) {
+ rc = -EINVAL;
+ ecryptfs_printk(KERN_ERR, "Attempt to reference "
+ "context buffer at index [%d]; maximum "
+ "allowable is [%d]\n", msg->index,
+ (ecryptfs_message_buf_len - 1));
+ goto out;
+ }
+ msg_ctx = &ecryptfs_msg_ctx_arr[msg->index];
+ mutex_lock(&msg_ctx->mux);
+ if (ecryptfs_find_daemon_id(msg_ctx->task->euid, &id)) {
+ rc = -EBADMSG;
+ ecryptfs_printk(KERN_WARNING, "User [%d] received a "
+ "message response from process [%d] but does "
+ "not have a registered daemon\n",
+ msg_ctx->task->euid, pid);
+ goto wake_up;
+ }
+ if (msg_ctx->task->euid != uid) {
+ rc = -EBADMSG;
+ ecryptfs_printk(KERN_WARNING, "Received message from user "
+ "[%d]; expected message from user [%d]\n",
+ uid, msg_ctx->task->euid);
+ goto unlock;
+ }
+ if (id->pid != pid) {
+ rc = -EBADMSG;
+ ecryptfs_printk(KERN_ERR, "User [%d] received a "
+ "message response from an unrecognized "
+ "process [%d]\n", msg_ctx->task->euid, pid);
+ goto unlock;
+ }
+ if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) {
+ rc = -EINVAL;
+ ecryptfs_printk(KERN_WARNING, "Desired context element is not "
+ "pending a response\n");
+ goto unlock;
+ } else if (msg_ctx->counter != seq) {
+ rc = -EINVAL;
+ ecryptfs_printk(KERN_WARNING, "Invalid message sequence; "
+ "expected [%d]; received [%d]\n",
+ msg_ctx->counter, seq);
+ goto unlock;
+ }
+ msg_size = sizeof(*msg) + msg->data_len;
+ msg_ctx->msg = kmalloc(msg_size, GFP_KERNEL);
+ if (!msg_ctx->msg) {
+ rc = -ENOMEM;
+ ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+ goto unlock;
+ }
+ memcpy(msg_ctx->msg, msg, msg_size);
+ msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE;
+ rc = 0;
+wake_up:
+ wake_up_process(msg_ctx->task);
+unlock:
+ mutex_unlock(&msg_ctx->mux);
+out:
+ return rc;
+}
+
+/**
+ * ecryptfs_send_message
+ * @transport: The transport over which to send the message (i.e.,
+ * netlink)
+ * @data: The data to send
+ * @data_len: The length of data
+ * @msg_ctx: The message context allocated for the send
+ */
+int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
+ struct ecryptfs_msg_ctx **msg_ctx)
+{
+ struct ecryptfs_daemon_id *id;
+ int rc;
+
+ mutex_lock(&ecryptfs_daemon_id_hash_mux);
+ if (ecryptfs_find_daemon_id(current->euid, &id)) {
+ mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+ rc = -ENOTCONN;
+ ecryptfs_printk(KERN_ERR, "User [%d] does not have a daemon "
+ "registered\n", current->euid);
+ goto out;
+ }
+ mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+ mutex_lock(&ecryptfs_msg_ctx_lists_mux);
+ rc = ecryptfs_acquire_free_msg_ctx(msg_ctx);
+ if (rc) {
+ mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+ ecryptfs_printk(KERN_WARNING, "Could not claim a free "
+ "context element\n");
+ goto out;
+ }
+ ecryptfs_msg_ctx_free_to_alloc(*msg_ctx);
+ mutex_unlock(&(*msg_ctx)->mux);
+ mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+ switch (transport) {
+ case ECRYPTFS_TRANSPORT_NETLINK:
+ rc = ecryptfs_send_netlink(data, data_len, *msg_ctx,
+ ECRYPTFS_NLMSG_REQUEST, 0, id->pid);
+ break;
+ case ECRYPTFS_TRANSPORT_CONNECTOR:
+ case ECRYPTFS_TRANSPORT_RELAYFS:
+ default:
+ rc = -ENOSYS;
+ }
+ if (rc) {
+ printk(KERN_ERR "Error attempting to send message to userspace "
+ "daemon; rc = [%d]\n", rc);
+ }
+out:
+ return rc;
+}
+
+/**
+ * ecryptfs_wait_for_response
+ * @msg_ctx: The context that was assigned when sending a message
+ * @msg: The incoming message from userspace; not set if rc != 0
+ *
+ * Sleeps until awaken by ecryptfs_receive_message or until the amount
+ * of time exceeds ecryptfs_message_wait_timeout. If zero is
+ * returned, msg will point to a valid message from userspace; a
+ * non-zero value is returned upon failure to receive a message or an
+ * error occurs.
+ */
+int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
+ struct ecryptfs_message **msg)
+{
+ signed long timeout = ecryptfs_message_wait_timeout * HZ;
+ int rc = 0;
+
+sleep:
+ timeout = schedule_timeout_interruptible(timeout);
+ mutex_lock(&ecryptfs_msg_ctx_lists_mux);
+ mutex_lock(&msg_ctx->mux);
+ if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_DONE) {
+ if (timeout) {
+ mutex_unlock(&msg_ctx->mux);
+ mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+ goto sleep;
+ }
+ rc = -ENOMSG;
+ } else {
+ *msg = msg_ctx->msg;
+ msg_ctx->msg = NULL;
+ }
+ ecryptfs_msg_ctx_alloc_to_free(msg_ctx);
+ mutex_unlock(&msg_ctx->mux);
+ mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+ return rc;
+}
+
+int ecryptfs_init_messaging(unsigned int transport)
+{
+ int i;
+ int rc = 0;
+
+ if (ecryptfs_number_of_users > ECRYPTFS_MAX_NUM_USERS) {
+ ecryptfs_number_of_users = ECRYPTFS_MAX_NUM_USERS;
+ ecryptfs_printk(KERN_WARNING, "Specified number of users is "
+ "too large, defaulting to [%d] users\n",
+ ecryptfs_number_of_users);
+ }
+ mutex_init(&ecryptfs_daemon_id_hash_mux);
+ mutex_lock(&ecryptfs_daemon_id_hash_mux);
+ ecryptfs_hash_buckets = 0;
+ while (ecryptfs_number_of_users >> ++ecryptfs_hash_buckets);
+ ecryptfs_daemon_id_hash = kmalloc(sizeof(struct hlist_head)
+ * ecryptfs_hash_buckets, GFP_KERNEL);
+ if (!ecryptfs_daemon_id_hash) {
+ rc = -ENOMEM;
+ ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+ goto out;
+ }
+ for (i = 0; i < ecryptfs_hash_buckets; i++)
+ INIT_HLIST_HEAD(&ecryptfs_daemon_id_hash[i]);
+ mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+
+ ecryptfs_msg_ctx_arr = kmalloc((sizeof(struct ecryptfs_msg_ctx)
+ * ecryptfs_message_buf_len), GFP_KERNEL);
+ if (!ecryptfs_msg_ctx_arr) {
+ rc = -ENOMEM;
+ ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+ goto out;
+ }
+ mutex_init(&ecryptfs_msg_ctx_lists_mux);
+ mutex_lock(&ecryptfs_msg_ctx_lists_mux);
+ ecryptfs_msg_counter = 0;
+ for (i = 0; i < ecryptfs_message_buf_len; i++) {
+ INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].node);
+ mutex_init(&ecryptfs_msg_ctx_arr[i].mux);
+ mutex_lock(&ecryptfs_msg_ctx_arr[i].mux);
+ ecryptfs_msg_ctx_arr[i].index = i;
+ ecryptfs_msg_ctx_arr[i].state = ECRYPTFS_MSG_CTX_STATE_FREE;
+ ecryptfs_msg_ctx_arr[i].counter = 0;
+ ecryptfs_msg_ctx_arr[i].task = NULL;
+ ecryptfs_msg_ctx_arr[i].msg = NULL;
+ list_add_tail(&ecryptfs_msg_ctx_arr[i].node,
+ &ecryptfs_msg_ctx_free_list);
+ mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux);
+ }
+ mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+ switch(transport) {
+ case ECRYPTFS_TRANSPORT_NETLINK:
+ rc = ecryptfs_init_netlink();
+ if (rc)
+ ecryptfs_release_messaging(transport);
+ break;
+ case ECRYPTFS_TRANSPORT_CONNECTOR:
+ case ECRYPTFS_TRANSPORT_RELAYFS:
+ default:
+ rc = -ENOSYS;
+ }
+out:
+ return rc;
+}
+
+void ecryptfs_release_messaging(unsigned int transport)
+{
+ if (ecryptfs_msg_ctx_arr) {
+ int i;
+
+ mutex_lock(&ecryptfs_msg_ctx_lists_mux);
+ for (i = 0; i < ecryptfs_message_buf_len; i++) {
+ mutex_lock(&ecryptfs_msg_ctx_arr[i].mux);
+ if (ecryptfs_msg_ctx_arr[i].msg)
+ kfree(ecryptfs_msg_ctx_arr[i].msg);
+ mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux);
+ }
+ kfree(ecryptfs_msg_ctx_arr);
+ mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+ }
+ if (ecryptfs_daemon_id_hash) {
+ struct hlist_node *elem;
+ struct ecryptfs_daemon_id *id;
+ int i;
+
+ mutex_lock(&ecryptfs_daemon_id_hash_mux);
+ for (i = 0; i < ecryptfs_hash_buckets; i++) {
+ hlist_for_each_entry(id, elem,
+ &ecryptfs_daemon_id_hash[i],
+ id_chain) {
+ hlist_del(elem);
+ kfree(id);
+ }
+ }
+ kfree(ecryptfs_daemon_id_hash);
+ mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+ }
+ switch(transport) {
+ case ECRYPTFS_TRANSPORT_NETLINK:
+ ecryptfs_release_netlink();
+ break;
+ case ECRYPTFS_TRANSPORT_CONNECTOR:
+ case ECRYPTFS_TRANSPORT_RELAYFS:
+ default:
+ break;
+ }
+ return;
+}
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 06843d24f23..3a6f65c3f14 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -6,7 +6,7 @@
*
* Copyright (C) 1997-2003 Erez Zadok
* Copyright (C) 2001-2003 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
* Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
*
* This program is free software; you can redistribute it and/or
@@ -234,22 +234,13 @@ int ecryptfs_do_readpage(struct file *file, struct page *page,
goto out;
}
wait_on_page_locked(lower_page);
- page_data = (char *)kmap(page);
- if (!page_data) {
- rc = -ENOMEM;
- ecryptfs_printk(KERN_ERR, "Error mapping page\n");
- goto out;
- }
- lower_page_data = (char *)kmap(lower_page);
- if (!lower_page_data) {
- rc = -ENOMEM;
- ecryptfs_printk(KERN_ERR, "Error mapping page\n");
- kunmap(page);
- goto out;
- }
+ page_data = kmap_atomic(page, KM_USER0);
+ lower_page_data = kmap_atomic(lower_page, KM_USER1);
memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE);
- kunmap(lower_page);
- kunmap(page);
+ kunmap_atomic(lower_page_data, KM_USER1);
+ flush_dcache_page(lower_page);
+ kunmap_atomic(page_data, KM_USER0);
+ flush_dcache_page(page);
rc = 0;
out:
if (likely(lower_page))
@@ -260,6 +251,33 @@ out:
ClearPageUptodate(page);
return rc;
}
+/**
+ * Header Extent:
+ * Octets 0-7: Unencrypted file size (big-endian)
+ * Octets 8-15: eCryptfs special marker
+ * Octets 16-19: Flags
+ * Octet 16: File format version number (between 0 and 255)
+ * Octets 17-18: Reserved
+ * Octet 19: Bit 1 (lsb): Reserved
+ * Bit 2: Encrypted?
+ * Bits 3-8: Reserved
+ * Octets 20-23: Header extent size (big-endian)
+ * Octets 24-25: Number of header extents at front of file
+ * (big-endian)
+ * Octet 26: Begin RFC 2440 authentication token packet set
+ */
+static void set_header_info(char *page_virt,
+ struct ecryptfs_crypt_stat *crypt_stat)
+{
+ size_t written;
+ int save_num_header_extents_at_front =
+ crypt_stat->num_header_extents_at_front;
+
+ crypt_stat->num_header_extents_at_front = 1;
+ ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written);
+ crypt_stat->num_header_extents_at_front =
+ save_num_header_extents_at_front;
+}
/**
* ecryptfs_readpage
@@ -279,8 +297,8 @@ static int ecryptfs_readpage(struct file *file, struct page *page)
crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
->crypt_stat;
if (!crypt_stat
- || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)
- || ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
+ || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
+ || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
ecryptfs_printk(KERN_DEBUG,
"Passing through unencrypted page\n");
rc = ecryptfs_do_readpage(file, page, page->index);
@@ -289,10 +307,51 @@ static int ecryptfs_readpage(struct file *file, struct page *page)
"[%d]\n", rc);
goto out;
}
+ } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
+ if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
+ int num_pages_in_header_region =
+ (crypt_stat->header_extent_size
+ / PAGE_CACHE_SIZE);
+
+ if (page->index < num_pages_in_header_region) {
+ char *page_virt;
+
+ page_virt = kmap_atomic(page, KM_USER0);
+ memset(page_virt, 0, PAGE_CACHE_SIZE);
+ if (page->index == 0) {
+ rc = ecryptfs_read_xattr_region(
+ page_virt, file->f_path.dentry);
+ set_header_info(page_virt, crypt_stat);
+ }
+ kunmap_atomic(page_virt, KM_USER0);
+ flush_dcache_page(page);
+ if (rc) {
+ printk(KERN_ERR "Error reading xattr "
+ "region\n");
+ goto out;
+ }
+ } else {
+ rc = ecryptfs_do_readpage(
+ file, page,
+ (page->index
+ - num_pages_in_header_region));
+ if (rc) {
+ printk(KERN_ERR "Error reading page; "
+ "rc = [%d]\n", rc);
+ goto out;
+ }
+ }
+ } else {
+ rc = ecryptfs_do_readpage(file, page, page->index);
+ if (rc) {
+ printk(KERN_ERR "Error reading page; rc = "
+ "[%d]\n", rc);
+ goto out;
+ }
+ }
} else {
rc = ecryptfs_decrypt_page(file, page);
if (rc) {
-
ecryptfs_printk(KERN_ERR, "Error decrypting page; "
"rc = [%d]\n", rc);
goto out;
@@ -308,30 +367,27 @@ out:
return rc;
}
+/**
+ * Called with lower inode mutex held.
+ */
static int fill_zeros_to_end_of_page(struct page *page, unsigned int to)
{
struct inode *inode = page->mapping->host;
int end_byte_in_page;
- int rc = 0;
char *page_virt;
- if ((i_size_read(inode) / PAGE_CACHE_SIZE) == page->index) {
- end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE;
- if (to > end_byte_in_page)
- end_byte_in_page = to;
- page_virt = kmap(page);
- if (!page_virt) {
- rc = -ENOMEM;
- ecryptfs_printk(KERN_WARNING,
- "Could not map page\n");
- goto out;
- }
- memset((page_virt + end_byte_in_page), 0,
- (PAGE_CACHE_SIZE - end_byte_in_page));
- kunmap(page);
- }
+ if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index)
+ goto out;
+ end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE;
+ if (to > end_byte_in_page)
+ end_byte_in_page = to;
+ page_virt = kmap_atomic(page, KM_USER0);
+ memset((page_virt + end_byte_in_page), 0,
+ (PAGE_CACHE_SIZE - end_byte_in_page));
+ kunmap_atomic(page_virt, KM_USER0);
+ flush_dcache_page(page);
out:
- return rc;
+ return 0;
}
static int ecryptfs_prepare_write(struct file *file, struct page *page,
@@ -339,7 +395,6 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
{
int rc = 0;
- kmap(page);
if (from == 0 && to == PAGE_CACHE_SIZE)
goto out; /* If we are writing a full page, it will be
up to date. */
@@ -349,30 +404,6 @@ out:
return rc;
}
-int ecryptfs_grab_and_map_lower_page(struct page **lower_page,
- char **lower_virt,
- struct inode *lower_inode,
- unsigned long lower_page_index)
-{
- int rc = 0;
-
- (*lower_page) = grab_cache_page(lower_inode->i_mapping,
- lower_page_index);
- if (!(*lower_page)) {
- ecryptfs_printk(KERN_ERR, "grab_cache_page for "
- "lower_page_index = [0x%.16x] failed\n",
- lower_page_index);
- rc = -EINVAL;
- goto out;
- }
- if (lower_virt)
- (*lower_virt) = kmap((*lower_page));
- else
- kmap((*lower_page));
-out:
- return rc;
-}
-
int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
struct inode *lower_inode,
struct writeback_control *wbc)
@@ -391,11 +422,8 @@ out:
return rc;
}
-static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page)
+static void ecryptfs_release_lower_page(struct page *lower_page)
{
- kunmap(lower_page);
- ecryptfs_printk(KERN_DEBUG, "Unlocking lower page with index = "
- "[0x%.16x]\n", lower_page->index);
unlock_page(lower_page);
page_cache_release(lower_page);
}
@@ -407,10 +435,9 @@ static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page)
*
* Returns zero on success; non-zero on error.
*/
-int
-ecryptfs_write_inode_size_to_header(struct file *lower_file,
- struct inode *lower_inode,
- struct inode *inode)
+static int ecryptfs_write_inode_size_to_header(struct file *lower_file,
+ struct inode *lower_inode,
+ struct inode *inode)
{
int rc = 0;
struct page *header_page;
@@ -418,11 +445,11 @@ ecryptfs_write_inode_size_to_header(struct file *lower_file,
const struct address_space_operations *lower_a_ops;
u64 file_size;
- rc = ecryptfs_grab_and_map_lower_page(&header_page, &header_virt,
- lower_inode, 0);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "grab_cache_page for header page "
- "failed\n");
+ header_page = grab_cache_page(lower_inode->i_mapping, 0);
+ if (!header_page) {
+ ecryptfs_printk(KERN_ERR, "grab_cache_page for "
+ "lower_page_index 0 failed\n");
+ rc = -EINVAL;
goto out;
}
lower_a_ops = lower_inode->i_mapping->a_ops;
@@ -430,18 +457,95 @@ ecryptfs_write_inode_size_to_header(struct file *lower_file,
file_size = (u64)i_size_read(inode);
ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size);
file_size = cpu_to_be64(file_size);
+ header_virt = kmap_atomic(header_page, KM_USER0);
memcpy(header_virt, &file_size, sizeof(u64));
+ kunmap_atomic(header_virt, KM_USER0);
+ flush_dcache_page(header_page);
rc = lower_a_ops->commit_write(lower_file, header_page, 0, 8);
if (rc < 0)
ecryptfs_printk(KERN_ERR, "Error commiting header page "
"write\n");
- ecryptfs_unmap_and_release_lower_page(header_page);
+ ecryptfs_release_lower_page(header_page);
lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
mark_inode_dirty_sync(inode);
out:
return rc;
}
+static int ecryptfs_write_inode_size_to_xattr(struct inode *lower_inode,
+ struct inode *inode,
+ struct dentry *ecryptfs_dentry,
+ int lower_i_mutex_held)
+{
+ ssize_t size;
+ void *xattr_virt;
+ struct dentry *lower_dentry;
+ u64 file_size;
+ int rc;
+
+ xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL);
+ if (!xattr_virt) {
+ printk(KERN_ERR "Out of memory whilst attempting to write "
+ "inode size to xattr\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+ lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
+ if (!lower_dentry->d_inode->i_op->getxattr) {
+ printk(KERN_WARNING
+ "No support for setting xattr in lower filesystem\n");
+ rc = -ENOSYS;
+ kmem_cache_free(ecryptfs_xattr_cache, xattr_virt);
+ goto out;
+ }
+ if (!lower_i_mutex_held)
+ mutex_lock(&lower_dentry->d_inode->i_mutex);
+ size = lower_dentry->d_inode->i_op->getxattr(lower_dentry,
+ ECRYPTFS_XATTR_NAME,
+ xattr_virt,
+ PAGE_CACHE_SIZE);
+ if (!lower_i_mutex_held)
+ mutex_unlock(&lower_dentry->d_inode->i_mutex);
+ if (size < 0)
+ size = 8;
+ file_size = (u64)i_size_read(inode);
+ file_size = cpu_to_be64(file_size);
+ memcpy(xattr_virt, &file_size, sizeof(u64));
+ if (!lower_i_mutex_held)
+ mutex_lock(&lower_dentry->d_inode->i_mutex);
+ rc = lower_dentry->d_inode->i_op->setxattr(lower_dentry,
+ ECRYPTFS_XATTR_NAME,
+ xattr_virt, size, 0);
+ if (!lower_i_mutex_held)
+ mutex_unlock(&lower_dentry->d_inode->i_mutex);
+ if (rc)
+ printk(KERN_ERR "Error whilst attempting to write inode size "
+ "to lower file xattr; rc = [%d]\n", rc);
+ kmem_cache_free(ecryptfs_xattr_cache, xattr_virt);
+out:
+ return rc;
+}
+
+int
+ecryptfs_write_inode_size_to_metadata(struct file *lower_file,
+ struct inode *lower_inode,
+ struct inode *inode,
+ struct dentry *ecryptfs_dentry,
+ int lower_i_mutex_held)
+{
+ struct ecryptfs_crypt_stat *crypt_stat;
+
+ crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
+ if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+ return ecryptfs_write_inode_size_to_xattr(lower_inode, inode,
+ ecryptfs_dentry,
+ lower_i_mutex_held);
+ else
+ return ecryptfs_write_inode_size_to_header(lower_file,
+ lower_inode,
+ inode);
+}
+
int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
struct file *lower_file,
unsigned long lower_page_index, int byte_offset,
@@ -449,10 +553,10 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
{
int rc = 0;
- rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL, lower_inode,
- lower_page_index);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting to grab and map "
+ *lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index);
+ if (!(*lower_page)) {
+ rc = -EINVAL;
+ ecryptfs_printk(KERN_ERR, "Error attempting to grab "
"lower page with index [0x%.16x]\n",
lower_page_index);
goto out;
@@ -468,7 +572,7 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
}
out:
if (rc && (*lower_page)) {
- ecryptfs_unmap_and_release_lower_page(*lower_page);
+ ecryptfs_release_lower_page(*lower_page);
(*lower_page) = NULL;
}
return rc;
@@ -493,7 +597,7 @@ ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode,
"Error committing write; rc = [%d]\n", rc);
} else
rc = 0;
- ecryptfs_unmap_and_release_lower_page(lower_page);
+ ecryptfs_release_lower_page(lower_page);
return rc;
}
@@ -528,89 +632,7 @@ out:
return rc;
}
-static int
-process_new_file(struct ecryptfs_crypt_stat *crypt_stat,
- struct file *file, struct inode *inode)
-{
- struct page *header_page;
- const struct address_space_operations *lower_a_ops;
- struct inode *lower_inode;
- struct file *lower_file;
- char *header_virt;
- int rc = 0;
- int current_header_page = 0;
- int header_pages;
- int more_header_data_to_be_written = 1;
-
- lower_inode = ecryptfs_inode_to_lower(inode);
- lower_file = ecryptfs_file_to_lower(file);
- lower_a_ops = lower_inode->i_mapping->a_ops;
- header_pages = ((crypt_stat->header_extent_size
- * crypt_stat->num_header_extents_at_front)
- / PAGE_CACHE_SIZE);
- BUG_ON(header_pages < 1);
- while (current_header_page < header_pages) {
- rc = ecryptfs_grab_and_map_lower_page(&header_page,
- &header_virt,
- lower_inode,
- current_header_page);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "grab_cache_page for "
- "header page [%d] failed; rc = [%d]\n",
- current_header_page, rc);
- goto out;
- }
- rc = lower_a_ops->prepare_write(lower_file, header_page, 0,
- PAGE_CACHE_SIZE);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error preparing to write "
- "header page out; rc = [%d]\n", rc);
- goto out;
- }
- memset(header_virt, 0, PAGE_CACHE_SIZE);
- if (more_header_data_to_be_written) {
- rc = ecryptfs_write_headers_virt(header_virt,
- crypt_stat,
- file->f_dentry);
- if (rc) {
- ecryptfs_printk(KERN_WARNING, "Error "
- "generating header; rc = "
- "[%d]\n", rc);
- rc = -EIO;
- memset(header_virt, 0, PAGE_CACHE_SIZE);
- ecryptfs_unmap_and_release_lower_page(
- header_page);
- goto out;
- }
- if (current_header_page == 0)
- memset(header_virt, 0, 8);
- more_header_data_to_be_written = 0;
- }
- rc = lower_a_ops->commit_write(lower_file, header_page, 0,
- PAGE_CACHE_SIZE);
- ecryptfs_unmap_and_release_lower_page(header_page);
- if (rc < 0) {
- ecryptfs_printk(KERN_ERR,
- "Error commiting header page write; "
- "rc = [%d]\n", rc);
- break;
- }
- current_header_page++;
- }
- if (rc >= 0) {
- rc = 0;
- ecryptfs_printk(KERN_DEBUG, "lower_inode->i_blocks = "
- "[0x%.16x]\n", lower_inode->i_blocks);
- i_size_write(inode, 0);
- lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
- mark_inode_dirty_sync(inode);
- }
- ecryptfs_printk(KERN_DEBUG, "Clearing ECRYPTFS_NEW_FILE flag in "
- "crypt_stat at memory location [%p]\n", crypt_stat);
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE);
-out:
- return rc;
-}
+struct kmem_cache *ecryptfs_xattr_cache;
/**
* ecryptfs_commit_write
@@ -640,15 +662,10 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
mutex_lock(&lower_inode->i_mutex);
crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
->crypt_stat;
- if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
+ if (crypt_stat->flags & ECRYPTFS_NEW_FILE) {
ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in "
"crypt_stat at memory location [%p]\n", crypt_stat);
- rc = process_new_file(crypt_stat, file, inode);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error processing new "
- "file; rc = [%d]\n", rc);
- goto out;
- }
+ crypt_stat->flags &= ~(ECRYPTFS_NEW_FILE);
} else
ecryptfs_printk(KERN_DEBUG, "Not a new file\n");
ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
@@ -670,7 +687,6 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
"index [0x%.16x])\n", page->index);
goto out;
}
- rc = 0;
inode->i_blocks = lower_inode->i_blocks;
pos = (page->index << PAGE_CACHE_SHIFT) + to;
if (pos > i_size_read(inode)) {
@@ -678,11 +694,15 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
"[0x%.16x]\n", i_size_read(inode));
}
- ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode);
+ rc = ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode,
+ inode, file->f_dentry,
+ ECRYPTFS_LOWER_I_MUTEX_HELD);
+ if (rc)
+ printk(KERN_ERR "Error writing inode size to metadata; "
+ "rc = [%d]\n", rc);
lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
mark_inode_dirty_sync(inode);
out:
- kunmap(page); /* mapped in prior call (prepare_write) */
if (rc < 0)
ClearPageUptodate(page);
else
@@ -707,6 +727,7 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros)
{
int rc = 0;
struct page *tmp_page;
+ char *tmp_page_virt;
tmp_page = ecryptfs_get1page(file, index);
if (IS_ERR(tmp_page)) {
@@ -715,28 +736,27 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros)
rc = PTR_ERR(tmp_page);
goto out;
}
- kmap(tmp_page);
rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error preparing to write zero's "
"to remainder of page at index [0x%.16x]\n",
index);
- kunmap(tmp_page);
page_cache_release(tmp_page);
goto out;
}
- memset(((char *)page_address(tmp_page) + start), 0, num_zeros);
+ tmp_page_virt = kmap_atomic(tmp_page, KM_USER0);
+ memset(((char *)tmp_page_virt + start), 0, num_zeros);
+ kunmap_atomic(tmp_page_virt, KM_USER0);
+ flush_dcache_page(tmp_page);
rc = ecryptfs_commit_write(file, tmp_page, start, start + num_zeros);
if (rc < 0) {
ecryptfs_printk(KERN_ERR, "Error attempting to write zero's "
"to remainder of page at index [0x%.16x]\n",
index);
- kunmap(tmp_page);
page_cache_release(tmp_page);
goto out;
}
rc = 0;
- kunmap(tmp_page);
page_cache_release(tmp_page);
out:
return rc;
diff --git a/fs/ecryptfs/netlink.c b/fs/ecryptfs/netlink.c
new file mode 100644
index 00000000000..e3aa2253c85
--- /dev/null
+++ b/fs/ecryptfs/netlink.c
@@ -0,0 +1,255 @@
+/**
+ * eCryptfs: Linux filesystem encryption layer
+ *
+ * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
+ * Tyler Hicks <tyhicks@ou.edu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <net/sock.h>
+#include <linux/hash.h>
+#include <linux/random.h>
+#include "ecryptfs_kernel.h"
+
+static struct sock *ecryptfs_nl_sock;
+
+/**
+ * ecryptfs_send_netlink
+ * @data: The data to include as the payload
+ * @data_len: The byte count of the data
+ * @msg_ctx: The netlink context that will be used to handle the
+ * response message
+ * @msg_type: The type of netlink message to send
+ * @msg_flags: The flags to include in the netlink header
+ * @daemon_pid: The process id of the daemon to send the message to
+ *
+ * Sends the data to the specified daemon pid and uses the netlink
+ * context element to store the data needed for validation upon
+ * receiving the response. The data and the netlink context can be
+ * null if just sending a netlink header is sufficient. Returns zero
+ * upon sending the message; non-zero upon error.
+ */
+int ecryptfs_send_netlink(char *data, int data_len,
+ struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
+ u16 msg_flags, pid_t daemon_pid)
+{
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ struct ecryptfs_message *msg;
+ size_t payload_len;
+ int rc;
+
+ payload_len = ((data && data_len) ? (sizeof(*msg) + data_len) : 0);
+ skb = alloc_skb(NLMSG_SPACE(payload_len), GFP_KERNEL);
+ if (!skb) {
+ rc = -ENOMEM;
+ ecryptfs_printk(KERN_ERR, "Failed to allocate socket buffer\n");
+ goto out;
+ }
+ nlh = NLMSG_PUT(skb, daemon_pid, msg_ctx ? msg_ctx->counter : 0,
+ msg_type, payload_len);
+ nlh->nlmsg_flags = msg_flags;
+ if (msg_ctx && payload_len) {
+ msg = (struct ecryptfs_message *)NLMSG_DATA(nlh);
+ msg->index = msg_ctx->index;
+ msg->data_len = data_len;
+ memcpy(msg->data, data, data_len);
+ }
+ rc = netlink_unicast(ecryptfs_nl_sock, skb, daemon_pid, 0);
+ if (rc < 0) {
+ ecryptfs_printk(KERN_ERR, "Failed to send eCryptfs netlink "
+ "message; rc = [%d]\n", rc);
+ goto out;
+ }
+ rc = 0;
+ goto out;
+nlmsg_failure:
+ rc = -EMSGSIZE;
+ kfree_skb(skb);
+out:
+ return rc;
+}
+
+/**
+ * ecryptfs_process_nl_reponse
+ * @skb: The socket buffer containing the netlink message of state
+ * RESPONSE
+ *
+ * Processes a response message after sending a operation request to
+ * userspace. Attempts to assign the msg to a netlink context element
+ * at the index specified in the msg. The sk_buff and nlmsghdr must
+ * be validated before this function. Returns zero upon delivery to
+ * desired context element; non-zero upon delivery failure or error.
+ */
+static int ecryptfs_process_nl_response(struct sk_buff *skb)
+{
+ struct nlmsghdr *nlh = (struct nlmsghdr*)skb->data;
+ struct ecryptfs_message *msg = NLMSG_DATA(nlh);
+ int rc;
+
+ if (skb->len - NLMSG_HDRLEN - sizeof(*msg) != msg->data_len) {
+ rc = -EINVAL;
+ ecryptfs_printk(KERN_ERR, "Received netlink message with "
+ "incorrectly specified data length\n");
+ goto out;
+ }
+ rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->uid,
+ NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq);
+ if (rc)
+ printk(KERN_ERR
+ "Error processing response message; rc = [%d]\n", rc);
+out:
+ return rc;
+}
+
+/**
+ * ecryptfs_process_nl_helo
+ * @skb: The socket buffer containing the nlmsghdr in HELO state
+ *
+ * Gets uid and pid of the skb and adds the values to the daemon id
+ * hash. Returns zero after adding a new daemon id to the hash list;
+ * non-zero otherwise.
+ */
+static int ecryptfs_process_nl_helo(struct sk_buff *skb)
+{
+ int rc;
+
+ rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_NETLINK,
+ NETLINK_CREDS(skb)->uid,
+ NETLINK_CREDS(skb)->pid);
+ if (rc)
+ printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc);
+ return rc;
+}
+
+/**
+ * ecryptfs_process_nl_quit
+ * @skb: The socket buffer containing the nlmsghdr in QUIT state
+ *
+ * Gets uid and pid of the skb and deletes the corresponding daemon
+ * id, if it is the registered that is requesting the
+ * deletion. Returns zero after deleting the desired daemon id;
+ * non-zero otherwise.
+ */
+static int ecryptfs_process_nl_quit(struct sk_buff *skb)
+{
+ int rc;
+
+ rc = ecryptfs_process_quit(NETLINK_CREDS(skb)->uid,
+ NETLINK_CREDS(skb)->pid);
+ if (rc)
+ printk(KERN_WARNING
+ "Error processing QUIT message; rc = [%d]\n", rc);
+ return rc;
+}
+
+/**
+ * ecryptfs_receive_nl_message
+ *
+ * Callback function called by netlink system when a message arrives.
+ * If the message looks to be valid, then an attempt is made to assign
+ * it to its desired netlink context element and wake up the process
+ * that is waiting for a response.
+ */
+static void ecryptfs_receive_nl_message(struct sock *sk, int len)
+{
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ int rc = 0; /* skb_recv_datagram requires this */
+
+receive:
+ skb = skb_recv_datagram(sk, 0, 0, &rc);
+ if (rc == -EINTR)
+ goto receive;
+ else if (rc < 0) {
+ ecryptfs_printk(KERN_ERR, "Error occurred while "
+ "receiving eCryptfs netlink message; "
+ "rc = [%d]\n", rc);
+ return;
+ }
+ nlh = (struct nlmsghdr *)skb->data;
+ if (!NLMSG_OK(nlh, skb->len)) {
+ ecryptfs_printk(KERN_ERR, "Received corrupt netlink "
+ "message\n");
+ goto free;
+ }
+ switch (nlh->nlmsg_type) {
+ case ECRYPTFS_NLMSG_RESPONSE:
+ if (ecryptfs_process_nl_response(skb)) {
+ ecryptfs_printk(KERN_WARNING, "Failed to "
+ "deliver netlink response to "
+ "requesting operation\n");
+ }
+ break;
+ case ECRYPTFS_NLMSG_HELO:
+ if (ecryptfs_process_nl_helo(skb)) {
+ ecryptfs_printk(KERN_WARNING, "Failed to "
+ "fulfill HELO request\n");
+ }
+ break;
+ case ECRYPTFS_NLMSG_QUIT:
+ if (ecryptfs_process_nl_quit(skb)) {
+ ecryptfs_printk(KERN_WARNING, "Failed to "
+ "fulfill QUIT request\n");
+ }
+ break;
+ default:
+ ecryptfs_printk(KERN_WARNING, "Dropping netlink "
+ "message of unrecognized type [%d]\n",
+ nlh->nlmsg_type);
+ break;
+ }
+free:
+ kfree_skb(skb);
+}
+
+/**
+ * ecryptfs_init_netlink
+ *
+ * Initializes the daemon id hash list, netlink context array, and
+ * necessary locks. Returns zero upon success; non-zero upon error.
+ */
+int ecryptfs_init_netlink(void)
+{
+ int rc;
+
+ ecryptfs_nl_sock = netlink_kernel_create(NETLINK_ECRYPTFS, 0,
+ ecryptfs_receive_nl_message,
+ THIS_MODULE);
+ if (!ecryptfs_nl_sock) {
+ rc = -EIO;
+ ecryptfs_printk(KERN_ERR, "Failed to create netlink socket\n");
+ goto out;
+ }
+ ecryptfs_nl_sock->sk_sndtimeo = ECRYPTFS_DEFAULT_SEND_TIMEOUT;
+ rc = 0;
+out:
+ return rc;
+}
+
+/**
+ * ecryptfs_release_netlink
+ *
+ * Frees all memory used by the netlink context array and releases the
+ * netlink socket.
+ */
+void ecryptfs_release_netlink(void)
+{
+ if (ecryptfs_nl_sock && ecryptfs_nl_sock->sk_socket)
+ sock_release(ecryptfs_nl_sock->sk_socket);
+ ecryptfs_nl_sock = NULL;
+}
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index eaa5daaf106..7b3f0cc09a6 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -168,7 +168,7 @@ out:
return rc;
}
-struct super_operations ecryptfs_sops = {
+const struct super_operations ecryptfs_sops = {
.alloc_inode = ecryptfs_alloc_inode,
.destroy_inode = ecryptfs_destroy_inode,
.drop_inode = generic_delete_inode,
diff --git a/fs/efs/dir.c b/fs/efs/dir.c
index b46c488eefc..dfb5cb40021 100644
--- a/fs/efs/dir.c
+++ b/fs/efs/dir.c
@@ -15,7 +15,7 @@ const struct file_operations efs_dir_operations = {
.readdir = efs_readdir,
};
-struct inode_operations efs_dir_inode_operations = {
+const struct inode_operations efs_dir_inode_operations = {
.lookup = efs_lookup,
};
diff --git a/fs/efs/super.c b/fs/efs/super.c
index dfebf21289f..c2235e46edc 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -105,7 +105,7 @@ static int efs_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
-static struct super_operations efs_superblock_operations = {
+static const struct super_operations efs_superblock_operations = {
.alloc_inode = efs_alloc_inode,
.destroy_inode = efs_destroy_inode,
.read_inode = efs_read_inode,
diff --git a/fs/exec.c b/fs/exec.c
index 11fe93f7363..7e36c6f6f53 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -405,12 +405,10 @@ int setup_arg_pages(struct linux_binprm *bprm,
bprm->loader += stack_base;
bprm->exec += stack_base;
- mpnt = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+ mpnt = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
if (!mpnt)
return -ENOMEM;
- memset(mpnt, 0, sizeof(*mpnt));
-
down_write(&mm->mmap_sem);
{
mpnt->vm_mm = mm;
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 0b02ba9642d..e89bfc8cf95 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -368,6 +368,14 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
}
if (++n >= npages)
n = 0;
+ /* next page is past the blocks we've got */
+ if (unlikely(n > (dir->i_blocks >> (PAGE_CACHE_SHIFT - 9)))) {
+ ext2_error(dir->i_sb, __FUNCTION__,
+ "dir %lu size %lld exceeds block count %llu",
+ dir->i_ino, dir->i_size,
+ (unsigned long long)dir->i_blocks);
+ goto out;
+ }
} while (n != start);
out:
return NULL;
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index c19ac153f56..e2a0ea50af1 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -158,7 +158,7 @@ extern void ext2_write_super (struct super_block *);
extern const struct file_operations ext2_dir_operations;
/* file.c */
-extern struct inode_operations ext2_file_inode_operations;
+extern const struct inode_operations ext2_file_inode_operations;
extern const struct file_operations ext2_file_operations;
extern const struct file_operations ext2_xip_file_operations;
@@ -168,9 +168,9 @@ extern const struct address_space_operations ext2_aops_xip;
extern const struct address_space_operations ext2_nobh_aops;
/* namei.c */
-extern struct inode_operations ext2_dir_inode_operations;
-extern struct inode_operations ext2_special_inode_operations;
+extern const struct inode_operations ext2_dir_inode_operations;
+extern const struct inode_operations ext2_special_inode_operations;
/* symlink.c */
-extern struct inode_operations ext2_fast_symlink_inode_operations;
-extern struct inode_operations ext2_symlink_inode_operations;
+extern const struct inode_operations ext2_fast_symlink_inode_operations;
+extern const struct inode_operations ext2_symlink_inode_operations;
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 2dba473c524..566d4e2d385 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -75,7 +75,7 @@ const struct file_operations ext2_xip_file_operations = {
};
#endif
-struct inode_operations ext2_file_inode_operations = {
+const struct inode_operations ext2_file_inode_operations = {
.truncate = ext2_truncate,
#ifdef CONFIG_EXT2_FS_XATTR
.setxattr = generic_setxattr,
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index e1af5b4cf80..e69beed839a 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -373,7 +373,7 @@ out:
return err;
}
-struct inode_operations ext2_dir_inode_operations = {
+const struct inode_operations ext2_dir_inode_operations = {
.create = ext2_create,
.lookup = ext2_lookup,
.link = ext2_link,
@@ -393,7 +393,7 @@ struct inode_operations ext2_dir_inode_operations = {
.permission = ext2_permission,
};
-struct inode_operations ext2_special_inode_operations = {
+const struct inode_operations ext2_special_inode_operations = {
#ifdef CONFIG_EXT2_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 6347c2dbdd8..a046a419d8a 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -231,7 +231,7 @@ static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, siz
static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off);
#endif
-static struct super_operations ext2_sops = {
+static const struct super_operations ext2_sops = {
.alloc_inode = ext2_alloc_inode,
.destroy_inode = ext2_destroy_inode,
.read_inode = ext2_read_inode,
@@ -708,10 +708,14 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
set_opt(sbi->s_mount_opt, GRPID);
if (def_mount_opts & EXT2_DEFM_UID16)
set_opt(sbi->s_mount_opt, NO_UID32);
+#ifdef CONFIG_EXT2_FS_XATTR
if (def_mount_opts & EXT2_DEFM_XATTR_USER)
set_opt(sbi->s_mount_opt, XATTR_USER);
+#endif
+#ifdef CONFIG_EXT2_FS_POSIX_ACL
if (def_mount_opts & EXT2_DEFM_ACL)
set_opt(sbi->s_mount_opt, POSIX_ACL);
+#endif
if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC)
set_opt(sbi->s_mount_opt, ERRORS_PANIC);
diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c
index 1e67d87cfa9..4e2426e22bb 100644
--- a/fs/ext2/symlink.c
+++ b/fs/ext2/symlink.c
@@ -28,7 +28,7 @@ static void *ext2_follow_link(struct dentry *dentry, struct nameidata *nd)
return NULL;
}
-struct inode_operations ext2_symlink_inode_operations = {
+const struct inode_operations ext2_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
@@ -40,7 +40,7 @@ struct inode_operations ext2_symlink_inode_operations = {
#endif
};
-struct inode_operations ext2_fast_symlink_inode_operations = {
+const struct inode_operations ext2_fast_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = ext2_follow_link,
#ifdef CONFIG_EXT2_FS_XATTR
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 881f6365c41..1e6f1386453 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -125,7 +125,7 @@ const struct file_operations ext3_file_operations = {
.splice_write = generic_file_splice_write,
};
-struct inode_operations ext3_file_inode_operations = {
+const struct inode_operations ext3_file_inode_operations = {
.truncate = ext3_truncate,
.setattr = ext3_setattr,
#ifdef CONFIG_EXT3_FS_XATTR
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index beaf25f5112..8a824f4ce5c 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -947,7 +947,7 @@ out:
static int ext3_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create)
{
- handle_t *handle = journal_current_handle();
+ handle_t *handle = ext3_journal_current_handle();
int ret = 0;
unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
@@ -1717,7 +1717,7 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
/*
* Reacquire the handle: ext3_get_block() can restart the transaction
*/
- handle = journal_current_handle();
+ handle = ext3_journal_current_handle();
out_stop:
if (handle) {
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 4df39c4315e..49159f13cc1 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1618,21 +1618,6 @@ static int ext3_delete_entry (handle_t *handle,
return -ENOENT;
}
-/*
- * ext3_mark_inode_dirty is somewhat expensive, so unlike ext2 we
- * do not perform it in these functions. We perform it at the call site,
- * if it is needed.
- */
-static inline void ext3_inc_count(handle_t *handle, struct inode *inode)
-{
- inc_nlink(inode);
-}
-
-static inline void ext3_dec_count(handle_t *handle, struct inode *inode)
-{
- drop_nlink(inode);
-}
-
static int ext3_add_nondir(handle_t *handle,
struct dentry *dentry, struct inode *inode)
{
@@ -1642,7 +1627,7 @@ static int ext3_add_nondir(handle_t *handle,
d_instantiate(dentry, inode);
return 0;
}
- ext3_dec_count(handle, inode);
+ drop_nlink(inode);
iput(inode);
return err;
}
@@ -2163,7 +2148,7 @@ retry:
err = __page_symlink(inode, symname, l,
mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
if (err) {
- ext3_dec_count(handle, inode);
+ drop_nlink(inode);
ext3_mark_inode_dirty(handle, inode);
iput (inode);
goto out_stop;
@@ -2191,6 +2176,12 @@ static int ext3_link (struct dentry * old_dentry,
if (inode->i_nlink >= EXT3_LINK_MAX)
return -EMLINK;
+ /*
+ * Return -ENOENT if we've raced with unlink and i_nlink is 0. Doing
+ * otherwise has the potential to corrupt the orphan inode list.
+ */
+ if (inode->i_nlink == 0)
+ return -ENOENT;
retry:
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
@@ -2202,7 +2193,7 @@ retry:
handle->h_sync = 1;
inode->i_ctime = CURRENT_TIME_SEC;
- ext3_inc_count(handle, inode);
+ inc_nlink(inode);
atomic_inc(&inode->i_count);
err = ext3_add_nondir(handle, dentry, inode);
@@ -2374,7 +2365,7 @@ end_rename:
/*
* directories can handle most operations...
*/
-struct inode_operations ext3_dir_inode_operations = {
+const struct inode_operations ext3_dir_inode_operations = {
.create = ext3_create,
.lookup = ext3_lookup,
.link = ext3_link,
@@ -2394,7 +2385,7 @@ struct inode_operations ext3_dir_inode_operations = {
.permission = ext3_permission,
};
-struct inode_operations ext3_special_inode_operations = {
+const struct inode_operations ext3_special_inode_operations = {
.setattr = ext3_setattr,
#ifdef CONFIG_EXT3_FS_XATTR
.setxattr = generic_setxattr,
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index b34886734a4..4a4fcd6868c 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -639,7 +639,7 @@ static struct quotactl_ops ext3_qctl_operations = {
};
#endif
-static struct super_operations ext3_sops = {
+static const struct super_operations ext3_sops = {
.alloc_inode = ext3_alloc_inode,
.destroy_inode = ext3_destroy_inode,
.read_inode = ext3_read_inode,
@@ -1459,10 +1459,14 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
set_opt(sbi->s_mount_opt, GRPID);
if (def_mount_opts & EXT3_DEFM_UID16)
set_opt(sbi->s_mount_opt, NO_UID32);
+#ifdef CONFIG_EXT3_FS_XATTR
if (def_mount_opts & EXT3_DEFM_XATTR_USER)
set_opt(sbi->s_mount_opt, XATTR_USER);
+#endif
+#ifdef CONFIG_EXT3_FS_POSIX_ACL
if (def_mount_opts & EXT3_DEFM_ACL)
set_opt(sbi->s_mount_opt, POSIX_ACL);
+#endif
if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_DATA)
sbi->s_mount_opt |= EXT3_MOUNT_JOURNAL_DATA;
else if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_ORDERED)
@@ -2344,6 +2348,22 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
err = -EROFS;
goto restore_opts;
}
+
+ /*
+ * If we have an unprocessed orphan list hanging
+ * around from a previously readonly bdev mount,
+ * require a full umount/remount for now.
+ */
+ if (es->s_last_orphan) {
+ printk(KERN_WARNING "EXT3-fs: %s: couldn't "
+ "remount RDWR because of unprocessed "
+ "orphan inode list. Please "
+ "umount/remount instead.\n",
+ sb->s_id);
+ err = -EINVAL;
+ goto restore_opts;
+ }
+
/*
* Mounting a RDONLY partition read-write, so reread
* and store the current valid flag. (It may have
diff --git a/fs/ext3/symlink.c b/fs/ext3/symlink.c
index 4f79122cde6..ff7b4ccd898 100644
--- a/fs/ext3/symlink.c
+++ b/fs/ext3/symlink.c
@@ -30,7 +30,7 @@ static void * ext3_follow_link(struct dentry *dentry, struct nameidata *nd)
return NULL;
}
-struct inode_operations ext3_symlink_inode_operations = {
+const struct inode_operations ext3_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
@@ -42,7 +42,7 @@ struct inode_operations ext3_symlink_inode_operations = {
#endif
};
-struct inode_operations ext3_fast_symlink_inode_operations = {
+const struct inode_operations ext3_fast_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = ext3_follow_link,
#ifdef CONFIG_EXT3_FS_XATTR
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 3bbc24b5878..3c6c1fd2be9 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -125,7 +125,7 @@ const struct file_operations ext4_file_operations = {
.splice_write = generic_file_splice_write,
};
-struct inode_operations ext4_file_inode_operations = {
+const struct inode_operations ext4_file_inode_operations = {
.truncate = ext4_truncate,
.setattr = ext4_setattr,
#ifdef CONFIG_EXT4DEV_FS_XATTR
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index a127cc03c9f..fbff4b9e122 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -946,7 +946,7 @@ out:
static int ext4_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create)
{
- handle_t *handle = journal_current_handle();
+ handle_t *handle = ext4_journal_current_handle();
int ret = 0;
unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
@@ -1716,7 +1716,7 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
/*
* Reacquire the handle: ext4_get_block() can restart the transaction
*/
- handle = journal_current_handle();
+ handle = ext4_journal_current_handle();
out_stop:
if (handle) {
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index e5a74a5ac26..e7e1d79a7d7 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1616,21 +1616,6 @@ static int ext4_delete_entry (handle_t *handle,
return -ENOENT;
}
-/*
- * ext4_mark_inode_dirty is somewhat expensive, so unlike ext2 we
- * do not perform it in these functions. We perform it at the call site,
- * if it is needed.
- */
-static inline void ext4_inc_count(handle_t *handle, struct inode *inode)
-{
- inc_nlink(inode);
-}
-
-static inline void ext4_dec_count(handle_t *handle, struct inode *inode)
-{
- drop_nlink(inode);
-}
-
static int ext4_add_nondir(handle_t *handle,
struct dentry *dentry, struct inode *inode)
{
@@ -1640,7 +1625,7 @@ static int ext4_add_nondir(handle_t *handle,
d_instantiate(dentry, inode);
return 0;
}
- ext4_dec_count(handle, inode);
+ drop_nlink(inode);
iput(inode);
return err;
}
@@ -2161,7 +2146,7 @@ retry:
err = __page_symlink(inode, symname, l,
mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
if (err) {
- ext4_dec_count(handle, inode);
+ drop_nlink(inode);
ext4_mark_inode_dirty(handle, inode);
iput (inode);
goto out_stop;
@@ -2189,6 +2174,12 @@ static int ext4_link (struct dentry * old_dentry,
if (inode->i_nlink >= EXT4_LINK_MAX)
return -EMLINK;
+ /*
+ * Return -ENOENT if we've raced with unlink and i_nlink is 0. Doing
+ * otherwise has the potential to corrupt the orphan inode list.
+ */
+ if (inode->i_nlink == 0)
+ return -ENOENT;
retry:
handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
@@ -2200,7 +2191,7 @@ retry:
handle->h_sync = 1;
inode->i_ctime = CURRENT_TIME_SEC;
- ext4_inc_count(handle, inode);
+ inc_nlink(inode);
atomic_inc(&inode->i_count);
err = ext4_add_nondir(handle, dentry, inode);
@@ -2372,7 +2363,7 @@ end_rename:
/*
* directories can handle most operations...
*/
-struct inode_operations ext4_dir_inode_operations = {
+const struct inode_operations ext4_dir_inode_operations = {
.create = ext4_create,
.lookup = ext4_lookup,
.link = ext4_link,
@@ -2392,7 +2383,7 @@ struct inode_operations ext4_dir_inode_operations = {
.permission = ext4_permission,
};
-struct inode_operations ext4_special_inode_operations = {
+const struct inode_operations ext4_special_inode_operations = {
.setattr = ext4_setattr,
#ifdef CONFIG_EXT4DEV_FS_XATTR
.setxattr = generic_setxattr,
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 486a641ca71..61c4718e4a5 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -690,7 +690,7 @@ static struct quotactl_ops ext4_qctl_operations = {
};
#endif
-static struct super_operations ext4_sops = {
+static const struct super_operations ext4_sops = {
.alloc_inode = ext4_alloc_inode,
.destroy_inode = ext4_destroy_inode,
.read_inode = ext4_read_inode,
@@ -1518,10 +1518,14 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
set_opt(sbi->s_mount_opt, GRPID);
if (def_mount_opts & EXT4_DEFM_UID16)
set_opt(sbi->s_mount_opt, NO_UID32);
+#ifdef CONFIG_EXT4DEV_FS_XATTR
if (def_mount_opts & EXT4_DEFM_XATTR_USER)
set_opt(sbi->s_mount_opt, XATTR_USER);
+#endif
+#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
if (def_mount_opts & EXT4_DEFM_ACL)
set_opt(sbi->s_mount_opt, POSIX_ACL);
+#endif
if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA)
sbi->s_mount_opt |= EXT4_MOUNT_JOURNAL_DATA;
else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED)
@@ -2419,6 +2423,22 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
err = -EROFS;
goto restore_opts;
}
+
+ /*
+ * If we have an unprocessed orphan list hanging
+ * around from a previously readonly bdev mount,
+ * require a full umount/remount for now.
+ */
+ if (es->s_last_orphan) {
+ printk(KERN_WARNING "EXT4-fs: %s: couldn't "
+ "remount RDWR because of unprocessed "
+ "orphan inode list. Please "
+ "umount/remount instead.\n",
+ sb->s_id);
+ err = -EINVAL;
+ goto restore_opts;
+ }
+
/*
* Mounting a RDONLY partition read-write, so reread
* and store the current valid flag. (It may have
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index fcf527286d7..e6f9da4287c 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -30,7 +30,7 @@ static void * ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
return NULL;
}
-struct inode_operations ext4_symlink_inode_operations = {
+const struct inode_operations ext4_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
@@ -42,7 +42,7 @@ struct inode_operations ext4_symlink_inode_operations = {
#endif
};
-struct inode_operations ext4_fast_symlink_inode_operations = {
+const struct inode_operations ext4_fast_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = ext4_follow_link,
#ifdef CONFIG_EXT4DEV_FS_XATTR
diff --git a/fs/fat/file.c b/fs/fat/file.c
index c1237b70c1f..55d3c7461c5 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -312,7 +312,7 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
}
EXPORT_SYMBOL_GPL(fat_getattr);
-struct inode_operations fat_file_inode_operations = {
+const struct inode_operations fat_file_inode_operations = {
.truncate = fat_truncate,
.setattr = fat_notify_change,
.getattr = fat_getattr,
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index a9e4688582a..76107354421 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -618,7 +618,7 @@ int fat_sync_inode(struct inode *inode)
EXPORT_SYMBOL_GPL(fat_sync_inode);
static int fat_show_options(struct seq_file *m, struct vfsmount *mnt);
-static struct super_operations fat_sops = {
+static const struct super_operations fat_sops = {
.alloc_inode = fat_alloc_inode,
.destroy_inode = fat_destroy_inode,
.write_inode = fat_write_inode,
@@ -1151,7 +1151,7 @@ static int fat_read_root(struct inode *inode)
* Read the super block of an MS-DOS FS.
*/
int fat_fill_super(struct super_block *sb, void *data, int silent,
- struct inode_operations *fs_dir_inode_ops, int isvfat)
+ const struct inode_operations *fs_dir_inode_ops, int isvfat)
{
struct inode *root_inode = NULL;
struct buffer_head *bh;
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 1cf1fe8466a..91ccee8723f 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -62,7 +62,7 @@ extern void vxfs_read_inode(struct inode *);
extern void vxfs_clear_inode(struct inode *);
/* vxfs_lookup.c */
-extern struct inode_operations vxfs_dir_inode_ops;
+extern const struct inode_operations vxfs_dir_inode_ops;
extern const struct file_operations vxfs_dir_operations;
/* vxfs_olt.c */
diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c
index 4e25f3fbed8..24b5a775ff9 100644
--- a/fs/freevxfs/vxfs_immed.c
+++ b/fs/freevxfs/vxfs_immed.c
@@ -48,7 +48,7 @@ static int vxfs_immed_readpage(struct file *, struct page *);
* Unliked all other operations we do not go through the pagecache,
* but do all work directly on the inode.
*/
-struct inode_operations vxfs_immed_symlink_iops = {
+const struct inode_operations vxfs_immed_symlink_iops = {
.readlink = generic_readlink,
.follow_link = vxfs_immed_follow_link,
};
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 0b7ae897cb7..098a915fd9a 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -44,7 +44,7 @@
extern const struct address_space_operations vxfs_aops;
extern const struct address_space_operations vxfs_immed_aops;
-extern struct inode_operations vxfs_immed_symlink_iops;
+extern const struct inode_operations vxfs_immed_symlink_iops;
struct kmem_cache *vxfs_inode_cachep;
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 3995d7fbeda..bf86e5444ea 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -52,7 +52,7 @@
static struct dentry * vxfs_lookup(struct inode *, struct dentry *, struct nameidata *);
static int vxfs_readdir(struct file *, void *, filldir_t);
-struct inode_operations vxfs_dir_inode_ops = {
+const struct inode_operations vxfs_dir_inode_ops = {
.lookup = vxfs_lookup,
};
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index ac28b0835ff..647d600f0bc 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -59,7 +59,7 @@ static void vxfs_put_super(struct super_block *);
static int vxfs_statfs(struct dentry *, struct kstatfs *);
static int vxfs_remount(struct super_block *, int *, char *);
-static struct super_operations vxfs_super_ops = {
+static const struct super_operations vxfs_super_ops = {
.read_inode = vxfs_read_inode,
.clear_inode = vxfs_clear_inode,
.put_super = vxfs_put_super,
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index 1794305f9ed..105d4a271e0 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -73,7 +73,7 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
struct fuse_conn *fc,
const char *name,
int mode, int nlink,
- struct inode_operations *iop,
+ const struct inode_operations *iop,
const struct file_operations *fop)
{
struct dentry *dentry;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 40080477ceb..406bf61ed51 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1242,7 +1242,7 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
return err;
}
-static struct inode_operations fuse_dir_inode_operations = {
+static const struct inode_operations fuse_dir_inode_operations = {
.lookup = fuse_lookup,
.mkdir = fuse_mkdir,
.symlink = fuse_symlink,
@@ -1270,7 +1270,7 @@ static const struct file_operations fuse_dir_operations = {
.fsync = fuse_dir_fsync,
};
-static struct inode_operations fuse_common_inode_operations = {
+static const struct inode_operations fuse_common_inode_operations = {
.setattr = fuse_setattr,
.permission = fuse_permission,
.getattr = fuse_getattr,
@@ -1280,7 +1280,7 @@ static struct inode_operations fuse_common_inode_operations = {
.removexattr = fuse_removexattr,
};
-static struct inode_operations fuse_symlink_inode_operations = {
+static const struct inode_operations fuse_symlink_inode_operations = {
.setattr = fuse_setattr,
.follow_link = fuse_follow_link,
.put_link = fuse_put_link,
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index f63efe1337e..2fd06927e85 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -69,7 +69,7 @@ void fuse_finish_open(struct inode *inode, struct file *file,
if (outarg->open_flags & FOPEN_DIRECT_IO)
file->f_op = &fuse_direct_io_file_operations;
if (!(outarg->open_flags & FOPEN_KEEP_CACHE))
- invalidate_inode_pages(inode->i_mapping);
+ invalidate_mapping_pages(inode->i_mapping, 0, -1);
ff->fh = outarg->fh;
file->private_data = ff;
}
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 12450d2b320..5ab8e50e780 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -112,7 +112,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
{
struct fuse_conn *fc = get_fuse_conn(inode);
if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size)
- invalidate_inode_pages(inode->i_mapping);
+ invalidate_mapping_pages(inode->i_mapping, 0, -1);
inode->i_ino = attr->ino;
inode->i_mode = (inode->i_mode & S_IFMT) + (attr->mode & 07777);
@@ -446,7 +446,7 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
return fuse_iget(sb, 1, 0, &attr);
}
-static struct super_operations fuse_super_operations = {
+static const struct super_operations fuse_super_operations = {
.alloc_inode = fuse_alloc_inode,
.destroy_inode = fuse_destroy_inode,
.read_inode = fuse_read_inode,
diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c
index 3799f19b282..1dd4215b83d 100644
--- a/fs/gfs2/locking/dlm/plock.c
+++ b/fs/gfs2/locking/dlm/plock.c
@@ -264,7 +264,7 @@ static unsigned int dev_poll(struct file *file, poll_table *wait)
return 0;
}
-static struct file_operations dev_fops = {
+static const struct file_operations dev_fops = {
.read = dev_read,
.write = dev_write,
.poll = dev_poll,
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 0e34d991897..e62d4f620c5 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -282,8 +282,7 @@ void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh,
return;
}
- bd = kmem_cache_alloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL),
- memset(bd, 0, sizeof(struct gfs2_bufdata));
+ bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL),
bd->bd_bh = bh;
bd->bd_gl = gl;
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index f40a84807d7..60f47bf2e8e 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -1115,7 +1115,7 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name)
return gfs2_ea_remove(GFS2_I(dentry->d_inode), &er);
}
-struct inode_operations gfs2_file_iops = {
+const struct inode_operations gfs2_file_iops = {
.permission = gfs2_permission,
.setattr = gfs2_setattr,
.getattr = gfs2_getattr,
@@ -1125,7 +1125,7 @@ struct inode_operations gfs2_file_iops = {
.removexattr = gfs2_removexattr,
};
-struct inode_operations gfs2_dev_iops = {
+const struct inode_operations gfs2_dev_iops = {
.permission = gfs2_permission,
.setattr = gfs2_setattr,
.getattr = gfs2_getattr,
@@ -1135,7 +1135,7 @@ struct inode_operations gfs2_dev_iops = {
.removexattr = gfs2_removexattr,
};
-struct inode_operations gfs2_dir_iops = {
+const struct inode_operations gfs2_dir_iops = {
.create = gfs2_create,
.lookup = gfs2_lookup,
.link = gfs2_link,
@@ -1154,7 +1154,7 @@ struct inode_operations gfs2_dir_iops = {
.removexattr = gfs2_removexattr,
};
-struct inode_operations gfs2_symlink_iops = {
+const struct inode_operations gfs2_symlink_iops = {
.readlink = gfs2_readlink,
.follow_link = gfs2_follow_link,
.permission = gfs2_permission,
diff --git a/fs/gfs2/ops_inode.h b/fs/gfs2/ops_inode.h
index b15acb4fd34..34f0caac1a0 100644
--- a/fs/gfs2/ops_inode.h
+++ b/fs/gfs2/ops_inode.h
@@ -12,9 +12,9 @@
#include <linux/fs.h>
-extern struct inode_operations gfs2_file_iops;
-extern struct inode_operations gfs2_dir_iops;
-extern struct inode_operations gfs2_symlink_iops;
-extern struct inode_operations gfs2_dev_iops;
+extern const struct inode_operations gfs2_file_iops;
+extern const struct inode_operations gfs2_dir_iops;
+extern const struct inode_operations gfs2_symlink_iops;
+extern const struct inode_operations gfs2_dev_iops;
#endif /* __OPS_INODE_DOT_H__ */
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 47369d01121..b89999d3a76 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -468,7 +468,7 @@ static void gfs2_destroy_inode(struct inode *inode)
kmem_cache_free(gfs2_inode_cachep, inode);
}
-struct super_operations gfs2_super_ops = {
+const struct super_operations gfs2_super_ops = {
.alloc_inode = gfs2_alloc_inode,
.destroy_inode = gfs2_destroy_inode,
.write_inode = gfs2_write_inode,
diff --git a/fs/gfs2/ops_super.h b/fs/gfs2/ops_super.h
index 9de73f042f7..442a274c627 100644
--- a/fs/gfs2/ops_super.h
+++ b/fs/gfs2/ops_super.h
@@ -12,6 +12,6 @@
#include <linux/fs.h>
-extern struct super_operations gfs2_super_ops;
+extern const struct super_operations gfs2_super_ops;
#endif /* __OPS_SUPER_DOT_H__ */
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index e2e0358da33..7c69b98a2e4 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -320,7 +320,7 @@ const struct file_operations hfs_dir_operations = {
.release = hfs_dir_release,
};
-struct inode_operations hfs_dir_inode_operations = {
+const struct inode_operations hfs_dir_inode_operations = {
.create = hfs_create,
.lookup = hfs_lookup,
.unlink = hfs_unlink,
diff --git a/fs/hfs/hfs.h b/fs/hfs/hfs.h
index 88099ab1a18..1445e3a56ed 100644
--- a/fs/hfs/hfs.h
+++ b/fs/hfs/hfs.h
@@ -83,8 +83,6 @@
/*======== HFS structures as they appear on the disk ========*/
-#define __packed __attribute__ ((packed))
-
/* Pascal-style string of up to 31 characters */
struct hfs_name {
u8 len;
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 735332dfd1b..147374b6f67 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -170,7 +170,7 @@ extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, struct qst
/* dir.c */
extern const struct file_operations hfs_dir_operations;
-extern struct inode_operations hfs_dir_inode_operations;
+extern const struct inode_operations hfs_dir_inode_operations;
/* extent.c */
extern int hfs_ext_keycmp(const btree_key *, const btree_key *);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 5cb7f8fee8d..fafcba59387 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -18,7 +18,7 @@
#include "btree.h"
static const struct file_operations hfs_file_operations;
-static struct inode_operations hfs_file_inode_operations;
+static const struct inode_operations hfs_file_inode_operations;
/*================ Variable-like macros ================*/
@@ -612,7 +612,7 @@ static const struct file_operations hfs_file_operations = {
.release = hfs_file_release,
};
-static struct inode_operations hfs_file_inode_operations = {
+static const struct inode_operations hfs_file_inode_operations = {
.lookup = hfs_file_lookup,
.truncate = hfs_file_truncate,
.setattr = hfs_inode_setattr,
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index a3698796600..623f509f1d4 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -154,7 +154,7 @@ static void hfs_destroy_inode(struct inode *inode)
kmem_cache_free(hfs_inode_cachep, HFS_I(inode));
}
-static struct super_operations hfs_super_operations = {
+static const struct super_operations hfs_super_operations = {
.alloc_inode = hfs_alloc_inode,
.destroy_inode = hfs_destroy_inode,
.write_inode = hfs_write_inode,
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index e886ac8460d..78137007ccc 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -471,7 +471,7 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
return res;
}
-struct inode_operations hfsplus_dir_inode_operations = {
+const struct inode_operations hfsplus_dir_inode_operations = {
.lookup = hfsplus_lookup,
.create = hfsplus_create,
.link = hfsplus_link,
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
index 49205531a50..fe99fe8db61 100644
--- a/fs/hfsplus/hfsplus_raw.h
+++ b/fs/hfsplus/hfsplus_raw.h
@@ -15,8 +15,6 @@
#include <linux/types.h>
-#define __packed __attribute__ ((packed))
-
/* Some constants */
#define HFSPLUS_SECTOR_SIZE 512
#define HFSPLUS_SECTOR_SHIFT 9
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 75e8c4d8aac..642012ac337 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -268,10 +268,10 @@ static int hfsplus_file_release(struct inode *inode, struct file *file)
return 0;
}
-extern struct inode_operations hfsplus_dir_inode_operations;
+extern const struct inode_operations hfsplus_dir_inode_operations;
extern struct file_operations hfsplus_dir_operations;
-static struct inode_operations hfsplus_file_inode_operations = {
+static const struct inode_operations hfsplus_file_inode_operations = {
.lookup = hfsplus_file_lookup,
.truncate = hfsplus_file_truncate,
.permission = hfsplus_permission,
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 0f513c6bf84..5a282f64c63 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -260,7 +260,7 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
-static struct super_operations hfsplus_sops = {
+static const struct super_operations hfsplus_sops = {
.alloc_inode = hfsplus_alloc_inode,
.destroy_inode = hfsplus_destroy_inode,
.read_inode = hfsplus_read_inode,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 69a376f35a6..e965eb11d76 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -52,8 +52,8 @@ static int append = 0;
#define HOSTFS_SUPER_MAGIC 0x00c0ffee
-static struct inode_operations hostfs_iops;
-static struct inode_operations hostfs_dir_iops;
+static const struct inode_operations hostfs_iops;
+static const struct inode_operations hostfs_dir_iops;
static const struct address_space_operations hostfs_link_aops;
#ifndef MODULE
@@ -309,7 +309,7 @@ static void hostfs_read_inode(struct inode *inode)
read_inode(inode);
}
-static struct super_operations hostfs_sbops = {
+static const struct super_operations hostfs_sbops = {
.alloc_inode = hostfs_alloc_inode,
.drop_inode = generic_delete_inode,
.delete_inode = hostfs_delete_inode,
@@ -880,7 +880,7 @@ int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
return(0);
}
-static struct inode_operations hostfs_iops = {
+static const struct inode_operations hostfs_iops = {
.create = hostfs_create,
.link = hostfs_link,
.unlink = hostfs_unlink,
@@ -894,7 +894,7 @@ static struct inode_operations hostfs_iops = {
.getattr = hostfs_getattr,
};
-static struct inode_operations hostfs_dir_iops = {
+static const struct inode_operations hostfs_dir_iops = {
.create = hostfs_create,
.lookup = hostfs_lookup,
.link = hostfs_link,
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index fb4c8915010..b4eafc0f1e5 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -132,7 +132,7 @@ const struct file_operations hpfs_file_ops =
.sendfile = generic_file_sendfile,
};
-struct inode_operations hpfs_file_iops =
+const struct inode_operations hpfs_file_iops =
{
.truncate = hpfs_truncate,
.setattr = hpfs_notify_change,
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 1c07aa82d32..42ff60ccf2a 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -266,7 +266,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int);
int hpfs_file_fsync(struct file *, struct dentry *, int);
extern const struct file_operations hpfs_file_ops;
-extern struct inode_operations hpfs_file_iops;
+extern const struct inode_operations hpfs_file_iops;
extern const struct address_space_operations hpfs_aops;
/* inode.c */
@@ -302,7 +302,7 @@ void hpfs_decide_conv(struct inode *, unsigned char *, unsigned);
/* namei.c */
-extern struct inode_operations hpfs_dir_iops;
+extern const struct inode_operations hpfs_dir_iops;
extern const struct address_space_operations hpfs_symlink_aops;
static inline struct hpfs_inode_info *hpfs_i(struct inode *inode)
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 2507e7393f3..9953cf9a2f1 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -659,7 +659,7 @@ end1:
return err;
}
-struct inode_operations hpfs_dir_iops =
+const struct inode_operations hpfs_dir_iops =
{
.create = hpfs_create,
.lookup = hpfs_lookup,
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index d4abc1a1d56..e0174e33852 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -426,7 +426,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
/* Super operations */
-static struct super_operations hpfs_sops =
+static const struct super_operations hpfs_sops =
{
.alloc_inode = hpfs_alloc_inode,
.destroy_inode = hpfs_destroy_inode,
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
index afd340a45da..affb7412125 100644
--- a/fs/hppfs/hppfs_kern.c
+++ b/fs/hppfs/hppfs_kern.c
@@ -43,7 +43,7 @@ static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode)
#define HPPFS_SUPER_MAGIC 0xb00000ee
-static struct super_operations hppfs_sbops;
+static const struct super_operations hppfs_sbops;
static int is_pid(struct dentry *dentry)
{
@@ -212,7 +212,7 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
return(ERR_PTR(err));
}
-static struct inode_operations hppfs_file_iops = {
+static const struct inode_operations hppfs_file_iops = {
};
static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count,
@@ -649,7 +649,7 @@ static void hppfs_destroy_inode(struct inode *inode)
kfree(HPPFS_I(inode));
}
-static struct super_operations hppfs_sbops = {
+static const struct super_operations hppfs_sbops = {
.alloc_inode = hppfs_alloc_inode,
.destroy_inode = hppfs_destroy_inode,
.read_inode = hppfs_read_inode,
@@ -693,11 +693,11 @@ static void* hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
return ret;
}
-static struct inode_operations hppfs_dir_iops = {
+static const struct inode_operations hppfs_dir_iops = {
.lookup = hppfs_lookup,
};
-static struct inode_operations hppfs_link_iops = {
+static const struct inode_operations hppfs_link_iops = {
.readlink = hppfs_readlink,
.follow_link = hppfs_follow_link,
};
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 4f4cd132b57..8c718a3d413 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -33,11 +33,11 @@
/* some random number */
#define HUGETLBFS_MAGIC 0x958458f6
-static struct super_operations hugetlbfs_ops;
+static const struct super_operations hugetlbfs_ops;
static const struct address_space_operations hugetlbfs_aops;
const struct file_operations hugetlbfs_file_operations;
-static struct inode_operations hugetlbfs_dir_inode_operations;
-static struct inode_operations hugetlbfs_inode_operations;
+static const struct inode_operations hugetlbfs_dir_inode_operations;
+static const struct inode_operations hugetlbfs_inode_operations;
static struct backing_dev_info hugetlbfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
@@ -449,10 +449,13 @@ static int hugetlbfs_symlink(struct inode *dir,
}
/*
- * For direct-IO reads into hugetlb pages
+ * mark the head page dirty
*/
static int hugetlbfs_set_page_dirty(struct page *page)
{
+ struct page *head = (struct page *)page_private(page);
+
+ SetPageDirty(head);
return 0;
}
@@ -560,7 +563,7 @@ const struct file_operations hugetlbfs_file_operations = {
.get_unmapped_area = hugetlb_get_unmapped_area,
};
-static struct inode_operations hugetlbfs_dir_inode_operations = {
+static const struct inode_operations hugetlbfs_dir_inode_operations = {
.create = hugetlbfs_create,
.lookup = simple_lookup,
.link = simple_link,
@@ -573,11 +576,11 @@ static struct inode_operations hugetlbfs_dir_inode_operations = {
.setattr = hugetlbfs_setattr,
};
-static struct inode_operations hugetlbfs_inode_operations = {
+static const struct inode_operations hugetlbfs_inode_operations = {
.setattr = hugetlbfs_setattr,
};
-static struct super_operations hugetlbfs_ops = {
+static const struct super_operations hugetlbfs_ops = {
.alloc_inode = hugetlbfs_alloc_inode,
.destroy_inode = hugetlbfs_destroy_inode,
.statfs = hugetlbfs_statfs,
diff --git a/fs/inode.c b/fs/inode.c
index bf21dc6d0db..5abb097ab1b 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -414,7 +414,8 @@ static void prune_icache(int nr_to_scan)
__iget(inode);
spin_unlock(&inode_lock);
if (remove_inode_buffers(inode))
- reap += invalidate_inode_pages(&inode->i_data);
+ reap += invalidate_mapping_pages(&inode->i_data,
+ 0, -1);
iput(inode);
spin_lock(&inode_lock);
@@ -709,7 +710,7 @@ EXPORT_SYMBOL(iunique);
struct inode *igrab(struct inode *inode)
{
spin_lock(&inode_lock);
- if (!(inode->i_state & (I_FREEING|I_WILL_FREE)))
+ if (!(inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)))
__iget(inode);
else
/*
@@ -999,7 +1000,7 @@ EXPORT_SYMBOL(remove_inode_hash);
*/
void generic_delete_inode(struct inode *inode)
{
- struct super_operations *op = inode->i_sb->s_op;
+ const struct super_operations *op = inode->i_sb->s_op;
list_del_init(&inode->i_list);
list_del_init(&inode->i_sb_list);
@@ -1092,7 +1093,7 @@ EXPORT_SYMBOL_GPL(generic_drop_inode);
*/
static inline void iput_final(struct inode *inode)
{
- struct super_operations *op = inode->i_sb->s_op;
+ const struct super_operations *op = inode->i_sb->s_op;
void (*drop)(struct inode *) = generic_drop_inode;
if (op && op->drop_inode)
@@ -1112,7 +1113,7 @@ static inline void iput_final(struct inode *inode)
void iput(struct inode *inode)
{
if (inode) {
- struct super_operations *op = inode->i_sb->s_op;
+ const struct super_operations *op = inode->i_sb->s_op;
BUG_ON(inode->i_state == I_CLEAR);
@@ -1160,11 +1161,9 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
struct inode *inode = dentry->d_inode;
struct timespec now;
- if (IS_RDONLY(inode))
- return;
if (inode->i_flags & S_NOATIME)
return;
- if (inode->i_sb->s_flags & MS_NOATIME)
+ if (IS_NOATIME(inode))
return;
if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
return;
@@ -1252,33 +1251,6 @@ int inode_needs_sync(struct inode *inode)
EXPORT_SYMBOL(inode_needs_sync);
-/*
- * Quota functions that want to walk the inode lists..
- */
-#ifdef CONFIG_QUOTA
-
-void remove_dquot_ref(struct super_block *sb, int type,
- struct list_head *tofree_head)
-{
- struct inode *inode;
-
- if (!sb->dq_op)
- return; /* nothing to do */
- spin_lock(&inode_lock); /* This lock is for inodes code */
-
- /*
- * We don't have to lock against quota code - test IS_QUOTAINIT is
- * just for speedup...
- */
- list_for_each_entry(inode, &sb->s_inodes, i_sb_list)
- if (!IS_NOQUOTA(inode))
- remove_inode_dquot_ref(inode, type, tofree_head);
-
- spin_unlock(&inode_lock);
-}
-
-#endif
-
int inode_wait(void *word)
{
schedule();
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index 55f6da55b7c..9f2224f65a1 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -455,8 +455,16 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
break;
kevent = inotify_dev_get_event(dev);
- if (event_size + kevent->event.len > count)
+ if (event_size + kevent->event.len > count) {
+ if (ret == 0 && count > 0) {
+ /*
+ * could not get a single event because we
+ * didn't have enough buffer space.
+ */
+ ret = -EINVAL;
+ }
break;
+ }
if (copy_to_user(buf, &kevent->event, event_size)) {
ret = -EFAULT;
diff --git a/fs/ioprio.c b/fs/ioprio.c
index 89e8da112a7..10d2c211d18 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -60,6 +60,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
int data = IOPRIO_PRIO_DATA(ioprio);
struct task_struct *p, *g;
struct user_struct *user;
+ struct pid *pgrp;
int ret;
switch (class) {
@@ -98,12 +99,14 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
break;
case IOPRIO_WHO_PGRP:
if (!who)
- who = process_group(current);
- do_each_task_pid(who, PIDTYPE_PGID, p) {
+ pgrp = task_pgrp(current);
+ else
+ pgrp = find_pid(who);
+ do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
ret = set_task_ioprio(p, ioprio);
if (ret)
break;
- } while_each_task_pid(who, PIDTYPE_PGID, p);
+ } while_each_pid_task(pgrp, PIDTYPE_PGID, p);
break;
case IOPRIO_WHO_USER:
if (!who)
@@ -167,6 +170,7 @@ asmlinkage long sys_ioprio_get(int which, int who)
{
struct task_struct *g, *p;
struct user_struct *user;
+ struct pid *pgrp;
int ret = -ESRCH;
int tmpio;
@@ -182,8 +186,10 @@ asmlinkage long sys_ioprio_get(int which, int who)
break;
case IOPRIO_WHO_PGRP:
if (!who)
- who = process_group(current);
- do_each_task_pid(who, PIDTYPE_PGID, p) {
+ pgrp = task_pgrp(current);
+ else
+ pgrp = find_pid(who);
+ do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
tmpio = get_task_ioprio(p);
if (tmpio < 0)
continue;
@@ -191,7 +197,7 @@ asmlinkage long sys_ioprio_get(int which, int who)
ret = tmpio;
else
ret = ioprio_best(ret, tmpio);
- } while_each_task_pid(who, PIDTYPE_PGID, p);
+ } while_each_pid_task(pgrp, PIDTYPE_PGID, p);
break;
case IOPRIO_WHO_USER:
if (!who)
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 4af2548f97a..0e94c31cad9 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -24,7 +24,7 @@ const struct file_operations isofs_dir_operations =
/*
* directories can handle most operations...
*/
-struct inode_operations isofs_dir_inode_operations =
+const struct inode_operations isofs_dir_inode_operations =
{
.lookup = isofs_lookup,
};
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index ea55b6c469e..64a96cdfe3a 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -106,7 +106,7 @@ static int isofs_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
-static struct super_operations isofs_sops = {
+static const struct super_operations isofs_sops = {
.alloc_inode = isofs_alloc_inode,
.destroy_inode = isofs_destroy_inode,
.read_inode = isofs_read_inode,
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index e6308c8b573..efe2872cd4e 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -174,7 +174,7 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de,
}
}
-extern struct inode_operations isofs_dir_inode_operations;
+extern const struct inode_operations isofs_dir_inode_operations;
extern const struct file_operations isofs_dir_operations;
extern const struct address_space_operations isofs_symlink_aops;
extern struct export_operations isofs_export_ops;
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index 43baa1afa02..9602b925da0 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -54,11 +54,11 @@
static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
-static struct super_operations jffs_ops;
+static const struct super_operations jffs_ops;
static const struct file_operations jffs_file_operations;
-static struct inode_operations jffs_file_inode_operations;
+static const struct inode_operations jffs_file_inode_operations;
static const struct file_operations jffs_dir_operations;
-static struct inode_operations jffs_dir_inode_operations;
+static const struct inode_operations jffs_dir_inode_operations;
static const struct address_space_operations jffs_address_operations;
struct kmem_cache *node_cache = NULL;
@@ -296,7 +296,7 @@ jffs_setattr(struct dentry *dentry, struct iattr *iattr)
inode->i_blocks = (inode->i_size + 511) >> 9;
if (len) {
- invalidate_inode_pages(inode->i_mapping);
+ invalidate_mapping_pages(inode->i_mapping, 0, -1);
}
inode->i_ctime = CURRENT_TIME_SEC;
inode->i_mtime = inode->i_ctime;
@@ -1518,7 +1518,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count,
}
inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
- invalidate_inode_pages(inode->i_mapping);
+ invalidate_mapping_pages(inode->i_mapping, 0, -1);
out_isem:
return err;
@@ -1642,7 +1642,7 @@ static const struct file_operations jffs_file_operations =
};
-static struct inode_operations jffs_file_inode_operations =
+static const struct inode_operations jffs_file_inode_operations =
{
.lookup = jffs_lookup, /* lookup */
.setattr = jffs_setattr,
@@ -1655,7 +1655,7 @@ static const struct file_operations jffs_dir_operations =
};
-static struct inode_operations jffs_dir_inode_operations =
+static const struct inode_operations jffs_dir_inode_operations =
{
.create = jffs_create,
.lookup = jffs_lookup,
@@ -1774,7 +1774,7 @@ static int jffs_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
-static struct super_operations jffs_ops =
+static const struct super_operations jffs_ops =
{
.read_inode = jffs_read_inode,
.delete_inode = jffs_delete_inode,
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index da6034d5071..cdbe2fe14e2 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -46,7 +46,7 @@ const struct file_operations jffs2_dir_operations =
};
-struct inode_operations jffs2_dir_inode_operations =
+const struct inode_operations jffs2_dir_inode_operations =
{
.create = jffs2_create,
.lookup = jffs2_lookup,
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 242875f77cb..e82eeaf7590 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -54,7 +54,7 @@ const struct file_operations jffs2_file_operations =
/* jffs2_file_inode_operations */
-struct inode_operations jffs2_file_inode_operations =
+const struct inode_operations jffs2_file_inode_operations =
{
.permission = jffs2_permission,
.setattr = jffs2_setattr,
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 9f41fc01a37..e07a0edcdb4 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -153,11 +153,11 @@ void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c);
/* dir.c */
extern const struct file_operations jffs2_dir_operations;
-extern struct inode_operations jffs2_dir_inode_operations;
+extern const struct inode_operations jffs2_dir_inode_operations;
/* file.c */
extern const struct file_operations jffs2_file_operations;
-extern struct inode_operations jffs2_file_inode_operations;
+extern const struct inode_operations jffs2_file_inode_operations;
extern const struct address_space_operations jffs2_file_address_operations;
int jffs2_fsync(struct file *, struct dentry *, int);
int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg);
@@ -166,7 +166,7 @@ int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg);
int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
/* symlink.c */
-extern struct inode_operations jffs2_symlink_inode_operations;
+extern const struct inode_operations jffs2_symlink_inode_operations;
/* fs.c */
int jffs2_setattr (struct dentry *, struct iattr *);
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 08a0e6c49e6..cc7e8e71ad4 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -66,7 +66,7 @@ static int jffs2_sync_fs(struct super_block *sb, int wait)
return 0;
}
-static struct super_operations jffs2_super_operations =
+static const struct super_operations jffs2_super_operations =
{
.alloc_inode = jffs2_alloc_inode,
.destroy_inode =jffs2_destroy_inode,
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index b90d5aa3d96..7e4882c8a7e 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -20,7 +20,7 @@
static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd);
-struct inode_operations jffs2_symlink_inode_operations =
+const struct inode_operations jffs2_symlink_inode_operations =
{
.readlink = generic_readlink,
.follow_link = jffs2_follow_link,
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index aa9132d0492..f7f8eff19b7 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -88,7 +88,7 @@ static int jfs_release(struct inode *inode, struct file *file)
return 0;
}
-struct inode_operations jfs_file_inode_operations = {
+const struct inode_operations jfs_file_inode_operations = {
.truncate = jfs_truncate,
.setxattr = jfs_setxattr,
.getxattr = jfs_getxattr,
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index 0d06ccfaff0..6802837f757 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -35,10 +35,10 @@ extern void jfs_set_inode_flags(struct inode *);
extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
extern const struct address_space_operations jfs_aops;
-extern struct inode_operations jfs_dir_inode_operations;
+extern const struct inode_operations jfs_dir_inode_operations;
extern const struct file_operations jfs_dir_operations;
-extern struct inode_operations jfs_file_inode_operations;
+extern const struct inode_operations jfs_file_inode_operations;
extern const struct file_operations jfs_file_operations;
-extern struct inode_operations jfs_symlink_inode_operations;
+extern const struct inode_operations jfs_symlink_inode_operations;
extern struct dentry_operations jfs_ci_dentry_operations;
#endif /* _H_JFS_INODE */
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 7ab47561b68..41c20477126 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1503,7 +1503,7 @@ struct dentry *jfs_get_parent(struct dentry *dentry)
return parent;
}
-struct inode_operations jfs_dir_inode_operations = {
+const struct inode_operations jfs_dir_inode_operations = {
.create = jfs_create,
.lookup = jfs_lookup,
.link = jfs_link,
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 846ac8f3451..52d73d54a93 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
static struct kmem_cache * jfs_inode_cachep;
-static struct super_operations jfs_super_operations;
+static const struct super_operations jfs_super_operations;
static struct export_operations jfs_export_operations;
static struct file_system_type jfs_fs_type;
@@ -716,7 +716,7 @@ out:
#endif
-static struct super_operations jfs_super_operations = {
+static const struct super_operations jfs_super_operations = {
.alloc_inode = jfs_alloc_inode,
.destroy_inode = jfs_destroy_inode,
.read_inode = jfs_read_inode,
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c
index cee43f36f51..4af1a05aad0 100644
--- a/fs/jfs/symlink.c
+++ b/fs/jfs/symlink.c
@@ -29,7 +29,7 @@ static void *jfs_follow_link(struct dentry *dentry, struct nameidata *nd)
return NULL;
}
-struct inode_operations jfs_symlink_inode_operations = {
+const struct inode_operations jfs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = jfs_follow_link,
.setxattr = jfs_setxattr,
diff --git a/fs/libfs.c b/fs/libfs.c
index 503898d5c4a..7d487047dbb 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -186,7 +186,7 @@ const struct file_operations simple_dir_operations = {
.fsync = simple_sync_file,
};
-struct inode_operations simple_dir_inode_operations = {
+const struct inode_operations simple_dir_inode_operations = {
.lookup = simple_lookup,
};
@@ -195,11 +195,11 @@ struct inode_operations simple_dir_inode_operations = {
* will never be mountable)
*/
int get_sb_pseudo(struct file_system_type *fs_type, char *name,
- struct super_operations *ops, unsigned long magic,
+ const struct super_operations *ops, unsigned long magic,
struct vfsmount *mnt)
{
struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
- static struct super_operations default_ops = {.statfs = simple_statfs};
+ static const struct super_operations default_ops = {.statfs = simple_statfs};
struct dentry *dentry;
struct inode *root;
struct qstr d_name = {.name = name, .len = strlen(name)};
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 3d4610c2a26..22d40320897 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -192,7 +192,7 @@ struct nlm_host *
nlmsvc_lookup_host(struct svc_rqst *rqstp,
const char *hostname, int hostname_len)
{
- return nlm_lookup_host(1, &rqstp->rq_addr,
+ return nlm_lookup_host(1, svc_addr_in(rqstp),
rqstp->rq_prot, rqstp->rq_vers,
hostname, hostname_len);
}
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 8ca18085e68..80fcacc1acf 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -141,6 +141,7 @@ lockd(struct svc_rqst *rqstp)
*/
while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) {
long timeout = MAX_SCHEDULE_TIMEOUT;
+ char buf[RPC_MAX_ADDRBUFLEN];
if (signalled()) {
flush_signals(current);
@@ -175,11 +176,10 @@ lockd(struct svc_rqst *rqstp)
break;
}
- dprintk("lockd: request from %08x\n",
- (unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
+ dprintk("lockd: request from %s\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)));
svc_process(rqstp);
-
}
flush_signals(current);
@@ -223,23 +223,29 @@ static int find_socket(struct svc_serv *serv, int proto)
return found;
}
+/*
+ * Make any sockets that are needed but not present.
+ * If nlm_udpport or nlm_tcpport were set as module
+ * options, make those sockets unconditionally
+ */
static int make_socks(struct svc_serv *serv, int proto)
{
- /* Make any sockets that are needed but not present.
- * If nlm_udpport or nlm_tcpport were set as module
- * options, make those sockets unconditionally
- */
- static int warned;
+ static int warned;
int err = 0;
+
if (proto == IPPROTO_UDP || nlm_udpport)
if (!find_socket(serv, IPPROTO_UDP))
- err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport);
- if (err == 0 && (proto == IPPROTO_TCP || nlm_tcpport))
+ err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport,
+ SVC_SOCK_DEFAULTS);
+ if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport))
if (!find_socket(serv, IPPROTO_TCP))
- err= svc_makesock(serv, IPPROTO_TCP, nlm_tcpport);
- if (!err)
+ err = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport,
+ SVC_SOCK_DEFAULTS);
+
+ if (err >= 0) {
warned = 0;
- else if (warned++ == 0)
+ err = 0;
+ } else if (warned++ == 0)
printk(KERN_WARNING
"lockd_up: makesock failed, error=%d\n", err);
return err;
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index f67146a8199..47a66aa5d55 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -224,7 +224,7 @@ nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
resp->cookie = argp->cookie;
dprintk("lockd: GRANTED called\n");
- resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock);
+ resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock);
dprintk("lockd: GRANTED status %d\n", ntohl(resp->status));
return rpc_success;
}
@@ -421,15 +421,16 @@ static __be32
nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
void *resp)
{
- struct sockaddr_in saddr = rqstp->rq_addr;
+ struct sockaddr_in saddr;
+
+ memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
dprintk("lockd: SM_NOTIFY called\n");
if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
|| ntohs(saddr.sin_port) >= 1024) {
- printk(KERN_WARNING
- "lockd: rejected NSM callback from %08x:%d\n",
- ntohl(rqstp->rq_addr.sin_addr.s_addr),
- ntohs(rqstp->rq_addr.sin_port));
+ char buf[RPC_MAX_ADDRBUFLEN];
+ printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)));
return rpc_system_err;
}
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 3707c3a23e9..31cb4842573 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -253,7 +253,7 @@ nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
resp->cookie = argp->cookie;
dprintk("lockd: GRANTED called\n");
- resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock);
+ resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock);
dprintk("lockd: GRANTED status %d\n", ntohl(resp->status));
return rpc_success;
}
@@ -452,15 +452,16 @@ static __be32
nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
void *resp)
{
- struct sockaddr_in saddr = rqstp->rq_addr;
+ struct sockaddr_in saddr;
+
+ memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
dprintk("lockd: SM_NOTIFY called\n");
if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
|| ntohs(saddr.sin_port) >= 1024) {
- printk(KERN_WARNING
- "lockd: rejected NSM callback from %08x:%d\n",
- ntohl(rqstp->rq_addr.sin_addr.s_addr),
- ntohs(rqstp->rq_addr.sin_port));
+ char buf[RPC_MAX_ADDRBUFLEN];
+ printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)));
return rpc_system_err;
}
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index df6b1075b54..c4a554df7b7 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -26,14 +26,14 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _
for (i=0; i<numblocks-1; i++) {
if (!(bh=map[i]))
return(0);
- for (j=0; j<BLOCK_SIZE; j++)
+ for (j=0; j<bh->b_size; j++)
sum += nibblemap[bh->b_data[j] & 0xf]
+ nibblemap[(bh->b_data[j]>>4) & 0xf];
}
if (numblocks==0 || !(bh=map[numblocks-1]))
return(0);
- i = ((numbits-(numblocks-1)*BLOCK_SIZE*8)/16)*2;
+ i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2;
for (j=0; j<i; j++) {
sum += nibblemap[bh->b_data[j] & 0xf]
+ nibblemap[(bh->b_data[j]>>4) & 0xf];
@@ -48,28 +48,29 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _
return(sum);
}
-void minix_free_block(struct inode * inode, int block)
+void minix_free_block(struct inode *inode, unsigned long block)
{
- struct super_block * sb = inode->i_sb;
- struct minix_sb_info * sbi = minix_sb(sb);
- struct buffer_head * bh;
- unsigned int bit,zone;
+ struct super_block *sb = inode->i_sb;
+ struct minix_sb_info *sbi = minix_sb(sb);
+ struct buffer_head *bh;
+ int k = sb->s_blocksize_bits + 3;
+ unsigned long bit, zone;
if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
printk("Trying to free block not in datazone\n");
return;
}
zone = block - sbi->s_firstdatazone + 1;
- bit = zone & 8191;
- zone >>= 13;
+ bit = zone & ((1<<k) - 1);
+ zone >>= k;
if (zone >= sbi->s_zmap_blocks) {
printk("minix_free_block: nonexistent bitmap buffer\n");
return;
}
bh = sbi->s_zmap[zone];
lock_kernel();
- if (!minix_test_and_clear_bit(bit,bh->b_data))
- printk("free_block (%s:%d): bit already cleared\n",
+ if (!minix_test_and_clear_bit(bit, bh->b_data))
+ printk("minix_free_block (%s:%lu): bit already cleared\n",
sb->s_id, block);
unlock_kernel();
mark_buffer_dirty(bh);
@@ -79,6 +80,7 @@ void minix_free_block(struct inode * inode, int block)
int minix_new_block(struct inode * inode)
{
struct minix_sb_info *sbi = minix_sb(inode->i_sb);
+ int bits_per_zone = 8 * inode->i_sb->s_blocksize;
int i;
for (i = 0; i < sbi->s_zmap_blocks; i++) {
@@ -86,11 +88,12 @@ int minix_new_block(struct inode * inode)
int j;
lock_kernel();
- if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) {
- minix_set_bit(j,bh->b_data);
+ j = minix_find_first_zero_bit(bh->b_data, bits_per_zone);
+ if (j < bits_per_zone) {
+ minix_set_bit(j, bh->b_data);
unlock_kernel();
mark_buffer_dirty(bh);
- j += i*8192 + sbi->s_firstdatazone-1;
+ j += i * bits_per_zone + sbi->s_firstdatazone-1;
if (j < sbi->s_firstdatazone || j >= sbi->s_nzones)
break;
return j;
@@ -137,6 +140,7 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
int block;
struct minix_sb_info *sbi = minix_sb(sb);
struct minix2_inode *p;
+ int minix2_inodes_per_block = sb->s_blocksize / sizeof(struct minix2_inode);
*bh = NULL;
if (!ino || ino > sbi->s_ninodes) {
@@ -146,14 +150,14 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
}
ino--;
block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks +
- ino / MINIX2_INODES_PER_BLOCK;
+ ino / minix2_inodes_per_block;
*bh = sb_bread(sb, block);
if (!*bh) {
printk("Unable to read inode block\n");
return NULL;
}
p = (void *)(*bh)->b_data;
- return p + ino % MINIX2_INODES_PER_BLOCK;
+ return p + ino % minix2_inodes_per_block;
}
/* Clear the link count and mode of a deleted inode on disk. */
@@ -185,26 +189,30 @@ static void minix_clear_inode(struct inode *inode)
void minix_free_inode(struct inode * inode)
{
+ struct super_block *sb = inode->i_sb;
struct minix_sb_info *sbi = minix_sb(inode->i_sb);
- struct buffer_head * bh;
- unsigned long ino;
+ struct buffer_head *bh;
+ int k = sb->s_blocksize_bits + 3;
+ unsigned long ino, bit;
ino = inode->i_ino;
if (ino < 1 || ino > sbi->s_ninodes) {
printk("minix_free_inode: inode 0 or nonexistent inode\n");
goto out;
}
- if ((ino >> 13) >= sbi->s_imap_blocks) {
+ bit = ino & ((1<<k) - 1);
+ ino >>= k;
+ if (ino >= sbi->s_imap_blocks) {
printk("minix_free_inode: nonexistent imap in superblock\n");
goto out;
}
minix_clear_inode(inode); /* clear on-disk copy */
- bh = sbi->s_imap[ino >> 13];
+ bh = sbi->s_imap[ino];
lock_kernel();
- if (!minix_test_and_clear_bit(ino & 8191, bh->b_data))
- printk("minix_free_inode: bit %lu already cleared\n", ino);
+ if (!minix_test_and_clear_bit(bit, bh->b_data))
+ printk("minix_free_inode: bit %lu already cleared\n", bit);
unlock_kernel();
mark_buffer_dirty(bh);
out:
@@ -217,35 +225,38 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
struct minix_sb_info *sbi = minix_sb(sb);
struct inode *inode = new_inode(sb);
struct buffer_head * bh;
- int i,j;
+ int bits_per_zone = 8 * sb->s_blocksize;
+ unsigned long j;
+ int i;
if (!inode) {
*error = -ENOMEM;
return NULL;
}
- j = 8192;
+ j = bits_per_zone;
bh = NULL;
*error = -ENOSPC;
lock_kernel();
for (i = 0; i < sbi->s_imap_blocks; i++) {
bh = sbi->s_imap[i];
- if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
+ j = minix_find_first_zero_bit(bh->b_data, bits_per_zone);
+ if (j < bits_per_zone)
break;
}
- if (!bh || j >= 8192) {
+ if (!bh || j >= bits_per_zone) {
unlock_kernel();
iput(inode);
return NULL;
}
- if (minix_test_and_set_bit(j,bh->b_data)) { /* shouldn't happen */
- printk("new_inode: bit already set\n");
+ if (minix_test_and_set_bit(j, bh->b_data)) { /* shouldn't happen */
unlock_kernel();
+ printk("minix_new_inode: bit already set\n");
iput(inode);
return NULL;
}
unlock_kernel();
mark_buffer_dirty(bh);
- j += i*8192;
+ j += i * bits_per_zone;
if (!j || j > sbi->s_ninodes) {
iput(inode);
return NULL;
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index ab782c4086f..cb4cb571fdd 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -4,6 +4,8 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*
* minix directory handling functions
+ *
+ * Updated to filesystem version 3 by Daniel Aragones
*/
#include "minix.h"
@@ -11,6 +13,7 @@
#include <linux/smp_lock.h>
typedef struct minix_dir_entry minix_dirent;
+typedef struct minix3_dir_entry minix3_dirent;
static int minix_readdir(struct file *, void *, filldir_t);
@@ -89,6 +92,8 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
unsigned long npages = dir_pages(inode);
struct minix_sb_info *sbi = minix_sb(sb);
unsigned chunk_size = sbi->s_dirsize;
+ char *name;
+ __u32 inumber;
lock_kernel();
@@ -105,16 +110,24 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
kaddr = (char *)page_address(page);
p = kaddr+offset;
limit = kaddr + minix_last_byte(inode, n) - chunk_size;
- for ( ; p <= limit ; p = minix_next_entry(p, sbi)) {
- minix_dirent *de = (minix_dirent *)p;
- if (de->inode) {
+ for ( ; p <= limit; p = minix_next_entry(p, sbi)) {
+ if (sbi->s_version == MINIX_V3) {
+ minix3_dirent *de3 = (minix3_dirent *)p;
+ name = de3->name;
+ inumber = de3->inode;
+ } else {
+ minix_dirent *de = (minix_dirent *)p;
+ name = de->name;
+ inumber = de->inode;
+ }
+ if (inumber) {
int over;
- unsigned l = strnlen(de->name,sbi->s_namelen);
+ unsigned l = strnlen(name, sbi->s_namelen);
offset = p - kaddr;
- over = filldir(dirent, de->name, l,
- (n<<PAGE_CACHE_SHIFT) | offset,
- de->inode, DT_UNKNOWN);
+ over = filldir(dirent, name, l,
+ (n << PAGE_CACHE_SHIFT) | offset,
+ inumber, DT_UNKNOWN);
if (over) {
dir_put_page(page);
goto done;
@@ -156,23 +169,34 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)
unsigned long n;
unsigned long npages = dir_pages(dir);
struct page *page = NULL;
- struct minix_dir_entry *de;
+ char *p;
+ char *namx;
+ __u32 inumber;
*res_page = NULL;
for (n = 0; n < npages; n++) {
- char *kaddr;
+ char *kaddr, *limit;
+
page = dir_get_page(dir, n);
if (IS_ERR(page))
continue;
kaddr = (char*)page_address(page);
- de = (struct minix_dir_entry *) kaddr;
- kaddr += minix_last_byte(dir, n) - sbi->s_dirsize;
- for ( ; (char *) de <= kaddr ; de = minix_next_entry(de,sbi)) {
- if (!de->inode)
+ limit = kaddr + minix_last_byte(dir, n) - sbi->s_dirsize;
+ for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
+ if (sbi->s_version == MINIX_V3) {
+ minix3_dirent *de3 = (minix3_dirent *)p;
+ namx = de3->name;
+ inumber = de3->inode;
+ } else {
+ minix_dirent *de = (minix_dirent *)p;
+ namx = de->name;
+ inumber = de->inode;
+ }
+ if (!inumber)
continue;
- if (namecompare(namelen,sbi->s_namelen,name,de->name))
+ if (namecompare(namelen, sbi->s_namelen, name, namx))
goto found;
}
dir_put_page(page);
@@ -181,7 +205,7 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)
found:
*res_page = page;
- return de;
+ return (minix_dirent *)p;
}
int minix_add_link(struct dentry *dentry, struct inode *inode)
@@ -192,12 +216,15 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
struct super_block * sb = dir->i_sb;
struct minix_sb_info * sbi = minix_sb(sb);
struct page *page = NULL;
- struct minix_dir_entry * de;
unsigned long npages = dir_pages(dir);
unsigned long n;
- char *kaddr;
+ char *kaddr, *p;
+ minix_dirent *de;
+ minix3_dirent *de3;
unsigned from, to;
int err;
+ char *namx = NULL;
+ __u32 inumber;
/*
* We take care of directory expansion in the same loop
@@ -205,7 +232,7 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
* to protect that region.
*/
for (n = 0; n <= npages; n++) {
- char *dir_end;
+ char *limit, *dir_end;
page = dir_get_page(dir, n);
err = PTR_ERR(page);
@@ -214,20 +241,30 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
lock_page(page);
kaddr = (char*)page_address(page);
dir_end = kaddr + minix_last_byte(dir, n);
- de = (minix_dirent *)kaddr;
- kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize;
- while ((char *)de <= kaddr) {
- if ((char *)de == dir_end) {
+ limit = kaddr + PAGE_CACHE_SIZE - sbi->s_dirsize;
+ for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
+ de = (minix_dirent *)p;
+ de3 = (minix3_dirent *)p;
+ if (sbi->s_version == MINIX_V3) {
+ namx = de3->name;
+ inumber = de3->inode;
+ } else {
+ namx = de->name;
+ inumber = de->inode;
+ }
+ if (p == dir_end) {
/* We hit i_size */
- de->inode = 0;
+ if (sbi->s_version == MINIX_V3)
+ de3->inode = 0;
+ else
+ de->inode = 0;
goto got_it;
}
- if (!de->inode)
+ if (!inumber)
goto got_it;
err = -EEXIST;
- if (namecompare(namelen,sbi->s_namelen,name,de->name))
+ if (namecompare(namelen, sbi->s_namelen, name, namx))
goto out_unlock;
- de = minix_next_entry(de, sbi);
}
unlock_page(page);
dir_put_page(page);
@@ -236,14 +273,19 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
return -EINVAL;
got_it:
- from = (char*)de - (char*)page_address(page);
+ from = p - (char*)page_address(page);
to = from + sbi->s_dirsize;
err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
if (err)
goto out_unlock;
- memcpy (de->name, name, namelen);
- memset (de->name + namelen, 0, sbi->s_dirsize - namelen - 2);
- de->inode = inode->i_ino;
+ memcpy (namx, name, namelen);
+ if (sbi->s_version == MINIX_V3) {
+ memset (namx + namelen, 0, sbi->s_dirsize - namelen - 4);
+ de3->inode = inode->i_ino;
+ } else {
+ memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2);
+ de->inode = inode->i_ino;
+ }
err = dir_commit_chunk(page, from, to);
dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(dir);
@@ -283,8 +325,7 @@ int minix_make_empty(struct inode *inode, struct inode *dir)
{
struct address_space *mapping = inode->i_mapping;
struct page *page = grab_cache_page(mapping, 0);
- struct minix_sb_info * sbi = minix_sb(inode->i_sb);
- struct minix_dir_entry * de;
+ struct minix_sb_info *sbi = minix_sb(inode->i_sb);
char *kaddr;
int err;
@@ -299,12 +340,23 @@ int minix_make_empty(struct inode *inode, struct inode *dir)
kaddr = kmap_atomic(page, KM_USER0);
memset(kaddr, 0, PAGE_CACHE_SIZE);
- de = (struct minix_dir_entry *)kaddr;
- de->inode = inode->i_ino;
- strcpy(de->name,".");
- de = minix_next_entry(de, sbi);
- de->inode = dir->i_ino;
- strcpy(de->name,"..");
+ if (sbi->s_version == MINIX_V3) {
+ minix3_dirent *de3 = (minix3_dirent *)kaddr;
+
+ de3->inode = inode->i_ino;
+ strcpy(de3->name, ".");
+ de3 = minix_next_entry(de3, sbi);
+ de3->inode = dir->i_ino;
+ strcpy(de3->name, "..");
+ } else {
+ minix_dirent *de = (minix_dirent *)kaddr;
+
+ de->inode = inode->i_ino;
+ strcpy(de->name, ".");
+ de = minix_next_entry(de, sbi);
+ de->inode = dir->i_ino;
+ strcpy(de->name, "..");
+ }
kunmap_atomic(kaddr, KM_USER0);
err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
@@ -321,33 +373,41 @@ int minix_empty_dir(struct inode * inode)
struct page *page = NULL;
unsigned long i, npages = dir_pages(inode);
struct minix_sb_info *sbi = minix_sb(inode->i_sb);
+ char *name;
+ __u32 inumber;
for (i = 0; i < npages; i++) {
- char *kaddr;
- minix_dirent * de;
- page = dir_get_page(inode, i);
+ char *p, *kaddr, *limit;
+ page = dir_get_page(inode, i);
if (IS_ERR(page))
continue;
kaddr = (char *)page_address(page);
- de = (minix_dirent *)kaddr;
- kaddr += minix_last_byte(inode, i) - sbi->s_dirsize;
+ limit = kaddr + minix_last_byte(inode, i) - sbi->s_dirsize;
+ for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
+ if (sbi->s_version == MINIX_V3) {
+ minix3_dirent *de3 = (minix3_dirent *)p;
+ name = de3->name;
+ inumber = de3->inode;
+ } else {
+ minix_dirent *de = (minix_dirent *)p;
+ name = de->name;
+ inumber = de->inode;
+ }
- while ((char *)de <= kaddr) {
- if (de->inode != 0) {
+ if (inumber != 0) {
/* check for . and .. */
- if (de->name[0] != '.')
+ if (name[0] != '.')
goto not_empty;
- if (!de->name[1]) {
- if (de->inode != inode->i_ino)
+ if (!name[1]) {
+ if (inumber != inode->i_ino)
goto not_empty;
- } else if (de->name[1] != '.')
+ } else if (name[1] != '.')
goto not_empty;
- else if (de->name[2])
+ else if (name[2])
goto not_empty;
}
- de = minix_next_entry(de, sbi);
}
dir_put_page(page);
}
diff --git a/fs/minix/file.c b/fs/minix/file.c
index 40eac2e60d2..f92baa1d757 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -26,7 +26,7 @@ const struct file_operations minix_file_operations = {
.sendfile = generic_file_sendfile,
};
-struct inode_operations minix_file_inode_operations = {
+const struct inode_operations minix_file_inode_operations = {
.truncate = minix_truncate,
.getattr = minix_getattr,
};
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 629e09b38c5..92e383af370 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -7,6 +7,7 @@
* Minix V2 fs support.
*
* Modified for 680x0 by Andreas Schwab
+ * Updated to filesystem version 3 by Daniel Aragones
*/
#include <linux/module.h>
@@ -36,7 +37,8 @@ static void minix_put_super(struct super_block *sb)
struct minix_sb_info *sbi = minix_sb(sb);
if (!(sb->s_flags & MS_RDONLY)) {
- sbi->s_ms->s_state = sbi->s_mount_state;
+ if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
+ sbi->s_ms->s_state = sbi->s_mount_state;
mark_buffer_dirty(sbi->s_sbh);
}
for (i = 0; i < sbi->s_imap_blocks; i++)
@@ -93,7 +95,7 @@ static void destroy_inodecache(void)
kmem_cache_destroy(minix_inode_cachep);
}
-static struct super_operations minix_sops = {
+static const struct super_operations minix_sops = {
.alloc_inode = minix_alloc_inode,
.destroy_inode = minix_destroy_inode,
.read_inode = minix_read_inode,
@@ -117,12 +119,17 @@ static int minix_remount (struct super_block * sb, int * flags, char * data)
!(sbi->s_mount_state & MINIX_VALID_FS))
return 0;
/* Mounting a rw partition read-only. */
- ms->s_state = sbi->s_mount_state;
+ if (sbi->s_version != MINIX_V3)
+ ms->s_state = sbi->s_mount_state;
mark_buffer_dirty(sbi->s_sbh);
} else {
/* Mount a partition which is read-only, read-write. */
- sbi->s_mount_state = ms->s_state;
- ms->s_state &= ~MINIX_VALID_FS;
+ if (sbi->s_version != MINIX_V3) {
+ sbi->s_mount_state = ms->s_state;
+ ms->s_state &= ~MINIX_VALID_FS;
+ } else {
+ sbi->s_mount_state = MINIX_VALID_FS;
+ }
mark_buffer_dirty(sbi->s_sbh);
if (!(sbi->s_mount_state & MINIX_VALID_FS))
@@ -140,7 +147,8 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
struct buffer_head *bh;
struct buffer_head **map;
struct minix_super_block *ms;
- int i, block;
+ struct minix3_super_block *m3s = NULL;
+ unsigned long i, block;
struct inode *root_inode;
struct minix_sb_info *sbi;
@@ -192,6 +200,22 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
sbi->s_dirsize = 32;
sbi->s_namelen = 30;
sbi->s_link_max = MINIX2_LINK_MAX;
+ } else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) {
+ m3s = (struct minix3_super_block *) bh->b_data;
+ s->s_magic = m3s->s_magic;
+ sbi->s_imap_blocks = m3s->s_imap_blocks;
+ sbi->s_zmap_blocks = m3s->s_zmap_blocks;
+ sbi->s_firstdatazone = m3s->s_firstdatazone;
+ sbi->s_log_zone_size = m3s->s_log_zone_size;
+ sbi->s_max_size = m3s->s_max_size;
+ sbi->s_ninodes = m3s->s_ninodes;
+ sbi->s_nzones = m3s->s_zones;
+ sbi->s_dirsize = 64;
+ sbi->s_namelen = 60;
+ sbi->s_version = MINIX_V3;
+ sbi->s_link_max = MINIX2_LINK_MAX;
+ sbi->s_mount_state = MINIX_VALID_FS;
+ sb_set_blocksize(s, m3s->s_blocksize);
} else
goto out_no_fs;
@@ -236,7 +260,8 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
s->s_root->d_op = &minix_dentry_operations;
if (!(s->s_flags & MS_RDONLY)) {
- ms->s_state &= ~MINIX_VALID_FS;
+ if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
+ ms->s_state &= ~MINIX_VALID_FS;
mark_buffer_dirty(bh);
}
if (!(sbi->s_mount_state & MINIX_VALID_FS))
@@ -278,8 +303,8 @@ out_illegal_sb:
out_no_fs:
if (!silent)
- printk("VFS: Can't find a Minix or Minix V2 filesystem "
- "on device %s\n", s->s_id);
+ printk("VFS: Can't find a Minix filesystem V1 | V2 | V3 "
+ "on device %s.\n", s->s_id);
out_release:
brelse(bh);
goto out;
@@ -344,7 +369,7 @@ static const struct address_space_operations minix_aops = {
.bmap = minix_bmap
};
-static struct inode_operations minix_symlink_inode_operations = {
+static const struct inode_operations minix_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
@@ -537,12 +562,14 @@ int minix_sync_inode(struct inode * inode)
int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
{
+ struct inode *dir = dentry->d_parent->d_inode;
+ struct super_block *sb = dir->i_sb;
generic_fillattr(dentry->d_inode, stat);
if (INODE_VERSION(dentry->d_inode) == MINIX_V1)
- stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size);
+ stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb);
else
- stat->blocks = (BLOCK_SIZE / 512) * V2_minix_blocks(stat->size);
- stat->blksize = BLOCK_SIZE;
+ stat->blocks = (sb->s_blocksize / 512) * V2_minix_blocks(stat->size, sb);
+ stat->blksize = sb->s_blocksize;
return 0;
}
diff --git a/fs/minix/itree_common.c b/fs/minix/itree_common.c
index 429baf8de10..a731cabf154 100644
--- a/fs/minix/itree_common.c
+++ b/fs/minix/itree_common.c
@@ -23,7 +23,7 @@ static inline int verify_chain(Indirect *from, Indirect *to)
static inline block_t *block_end(struct buffer_head *bh)
{
- return (block_t *)((char*)bh->b_data + BLOCK_SIZE);
+ return (block_t *)((char*)bh->b_data + bh->b_size);
}
static inline Indirect *get_branch(struct inode *inode,
@@ -85,7 +85,7 @@ static int alloc_branch(struct inode *inode,
branch[n].key = cpu_to_block(nr);
bh = sb_getblk(inode->i_sb, parent);
lock_buffer(bh);
- memset(bh->b_data, 0, BLOCK_SIZE);
+ memset(bh->b_data, 0, bh->b_size);
branch[n].bh = bh;
branch[n].p = (block_t*) bh->b_data + offsets[n];
*branch[n].p = branch[n].key;
@@ -292,6 +292,7 @@ static void free_branches(struct inode *inode, block_t *p, block_t *q, int depth
static inline void truncate (struct inode * inode)
{
+ struct super_block *sb = inode->i_sb;
block_t *idata = i_data(inode);
int offsets[DEPTH];
Indirect chain[DEPTH];
@@ -301,7 +302,7 @@ static inline void truncate (struct inode * inode)
int first_whole;
long iblock;
- iblock = (inode->i_size + BLOCK_SIZE-1) >> 10;
+ iblock = (inode->i_size + sb->s_blocksize -1) >> sb->s_blocksize_bits;
block_truncate_page(inode->i_mapping, inode->i_size, get_block);
n = block_to_path(inode, iblock, offsets);
@@ -346,15 +347,16 @@ do_indirects:
mark_inode_dirty(inode);
}
-static inline unsigned nblocks(loff_t size)
+static inline unsigned nblocks(loff_t size, struct super_block *sb)
{
+ int k = sb->s_blocksize_bits - 10;
unsigned blocks, res, direct = DIRECT, i = DEPTH;
- blocks = (size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
+ blocks = (size + sb->s_blocksize - 1) >> (BLOCK_SIZE_BITS + k);
res = blocks;
while (--i && blocks > direct) {
blocks -= direct;
- blocks += BLOCK_SIZE/sizeof(block_t) - 1;
- blocks /= BLOCK_SIZE/sizeof(block_t);
+ blocks += sb->s_blocksize/sizeof(block_t) - 1;
+ blocks /= sb->s_blocksize/sizeof(block_t);
res += blocks;
direct = 1;
}
diff --git a/fs/minix/itree_v1.c b/fs/minix/itree_v1.c
index 656b1347a25..1a5f3bf0bce 100644
--- a/fs/minix/itree_v1.c
+++ b/fs/minix/itree_v1.c
@@ -55,7 +55,7 @@ void V1_minix_truncate(struct inode * inode)
truncate(inode);
}
-unsigned V1_minix_blocks(loff_t size)
+unsigned V1_minix_blocks(loff_t size, struct super_block *sb)
{
- return nblocks(size);
+ return nblocks(size, sb);
}
diff --git a/fs/minix/itree_v2.c b/fs/minix/itree_v2.c
index 9adcdc754e0..ad8f0dec4ef 100644
--- a/fs/minix/itree_v2.c
+++ b/fs/minix/itree_v2.c
@@ -23,10 +23,11 @@ static inline block_t *i_data(struct inode *inode)
static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
{
int n = 0;
+ struct super_block *sb = inode->i_sb;
if (block < 0) {
printk("minix_bmap: block<0\n");
- } else if (block >= (minix_sb(inode->i_sb)->s_max_size/BLOCK_SIZE)) {
+ } else if (block >= (minix_sb(inode->i_sb)->s_max_size/sb->s_blocksize)) {
printk("minix_bmap: block>big\n");
} else if (block < 7) {
offsets[n++] = block;
@@ -60,7 +61,7 @@ void V2_minix_truncate(struct inode * inode)
truncate(inode);
}
-unsigned V2_minix_blocks(loff_t size)
+unsigned V2_minix_blocks(loff_t size, struct super_block *sb)
{
- return nblocks(size);
+ return nblocks(size, sb);
}
diff --git a/fs/minix/minix.h b/fs/minix/minix.h
index c55b77cdcc8..73ef84f8fb0 100644
--- a/fs/minix/minix.h
+++ b/fs/minix/minix.h
@@ -7,11 +7,10 @@
* truncated. Else they will be disallowed (ENAMETOOLONG).
*/
#define NO_TRUNCATE 1
-
#define INODE_VERSION(inode) minix_sb(inode->i_sb)->s_version
-
#define MINIX_V1 0x0001 /* original minix fs */
#define MINIX_V2 0x0002 /* minix V2 fs */
+#define MINIX_V3 0x0003 /* minix V3 fs */
/*
* minix fs inode data in memory
@@ -52,12 +51,10 @@ extern struct inode * minix_new_inode(const struct inode * dir, int * error);
extern void minix_free_inode(struct inode * inode);
extern unsigned long minix_count_free_inodes(struct minix_sb_info *sbi);
extern int minix_new_block(struct inode * inode);
-extern void minix_free_block(struct inode * inode, int block);
+extern void minix_free_block(struct inode *inode, unsigned long block);
extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi);
-
extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *);
-extern void V2_minix_truncate(struct inode *);
extern void V1_minix_truncate(struct inode *);
extern void V2_minix_truncate(struct inode *);
extern void minix_truncate(struct inode *);
@@ -65,8 +62,8 @@ extern int minix_sync_inode(struct inode *);
extern void minix_set_inode(struct inode *, dev_t);
extern int V1_minix_get_block(struct inode *, long, struct buffer_head *, int);
extern int V2_minix_get_block(struct inode *, long, struct buffer_head *, int);
-extern unsigned V1_minix_blocks(loff_t);
-extern unsigned V2_minix_blocks(loff_t);
+extern unsigned V1_minix_blocks(loff_t, struct super_block *);
+extern unsigned V2_minix_blocks(loff_t, struct super_block *);
extern struct minix_dir_entry *minix_find_entry(struct dentry*, struct page**);
extern int minix_add_link(struct dentry*, struct inode*);
@@ -76,11 +73,10 @@ extern int minix_empty_dir(struct inode*);
extern void minix_set_link(struct minix_dir_entry*, struct page*, struct inode*);
extern struct minix_dir_entry *minix_dotdot(struct inode*, struct page**);
extern ino_t minix_inode_by_name(struct dentry*);
-
extern int minix_sync_file(struct file *, struct dentry *, int);
-extern struct inode_operations minix_file_inode_operations;
-extern struct inode_operations minix_dir_inode_operations;
+extern const struct inode_operations minix_file_inode_operations;
+extern const struct inode_operations minix_dir_inode_operations;
extern const struct file_operations minix_file_operations;
extern const struct file_operations minix_dir_operations;
extern struct dentry_operations minix_dentry_operations;
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 299bb66e3bd..f4aa7a93904 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -291,7 +291,7 @@ out:
/*
* directories can handle most operations...
*/
-struct inode_operations minix_dir_inode_operations = {
+const struct inode_operations minix_dir_inode_operations = {
.create = minix_create,
.lookup = minix_lookup,
.link = minix_link,
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 452461955cb..30f7d0ae221 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -646,7 +646,7 @@ out:
return err;
}
-static struct inode_operations msdos_dir_inode_operations = {
+static const struct inode_operations msdos_dir_inode_operations = {
.create = msdos_create,
.lookup = msdos_lookup,
.unlink = msdos_unlink,
diff --git a/fs/namei.c b/fs/namei.c
index e4f108f0823..161e2225c75 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2744,7 +2744,7 @@ int page_symlink(struct inode *inode, const char *symname, int len)
mapping_gfp_mask(inode->i_mapping));
}
-struct inode_operations page_symlink_inode_operations = {
+const struct inode_operations page_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
diff --git a/fs/namespace.c b/fs/namespace.c
index 5ef336c1103..fd999cab7b5 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -53,9 +53,8 @@ static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
struct vfsmount *alloc_vfsmnt(const char *name)
{
- struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL);
+ struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
if (mnt) {
- memset(mnt, 0, sizeof(struct vfsmount));
atomic_set(&mnt->mnt_count, 1);
INIT_LIST_HEAD(&mnt->mnt_hash);
INIT_LIST_HEAD(&mnt->mnt_child);
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 73747772c3b..011ef0b6d2d 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -58,7 +58,7 @@ const struct file_operations ncp_dir_operations =
#endif
};
-struct inode_operations ncp_dir_inode_operations =
+const struct inode_operations ncp_dir_inode_operations =
{
.create = ncp_create,
.lookup = ncp_lookup,
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index b91fea03b1c..6b1f6d27099 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -297,7 +297,7 @@ const struct file_operations ncp_file_operations =
.fsync = ncp_fsync,
};
-struct inode_operations ncp_file_inode_operations =
+const struct inode_operations ncp_file_inode_operations =
{
.setattr = ncp_notify_change,
};
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 67a90bf795d..14939ddf74f 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -90,7 +90,7 @@ static int ncp_remount(struct super_block *sb, int *flags, char* data)
return 0;
}
-static struct super_operations ncp_sops =
+static const struct super_operations ncp_sops =
{
.alloc_inode = ncp_alloc_inode,
.destroy_inode = ncp_destroy_inode,
@@ -229,7 +229,7 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
}
#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
-static struct inode_operations ncp_symlink_inode_operations = {
+static const struct inode_operations ncp_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 7933e2e99db..75f309c8741 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -71,6 +71,8 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
complete(&nfs_callback_info.started);
for(;;) {
+ char buf[RPC_MAX_ADDRBUFLEN];
+
if (signalled()) {
if (nfs_callback_info.users == 0)
break;
@@ -88,8 +90,8 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
__FUNCTION__, -err);
break;
}
- dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__,
- NIPQUAD(rqstp->rq_addr.sin_addr.s_addr));
+ dprintk("%s: request from %s\n", __FUNCTION__,
+ svc_print_addr(rqstp, buf, sizeof(buf)));
svc_process(rqstp);
}
@@ -106,7 +108,6 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
int nfs_callback_up(void)
{
struct svc_serv *serv;
- struct svc_sock *svsk;
int ret = 0;
lock_kernel();
@@ -119,17 +120,14 @@ int nfs_callback_up(void)
ret = -ENOMEM;
if (!serv)
goto out_err;
- /* FIXME: We don't want to register this socket with the portmapper */
- ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport);
- if (ret < 0)
+
+ ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport,
+ SVC_SOCK_ANONYMOUS);
+ if (ret <= 0)
goto out_destroy;
- if (!list_empty(&serv->sv_permsocks)) {
- svsk = list_entry(serv->sv_permsocks.next,
- struct svc_sock, sk_list);
- nfs_callback_tcpport = ntohs(inet_sk(svsk->sk_sk)->sport);
- dprintk ("Callback port = 0x%x\n", nfs_callback_tcpport);
- } else
- BUG();
+ nfs_callback_tcpport = ret;
+ dprintk("Callback port = 0x%x\n", nfs_callback_tcpport);
+
ret = svc_create_thread(nfs_callback_svc, serv);
if (ret < 0)
goto out_destroy;
@@ -140,6 +138,8 @@ out:
unlock_kernel();
return ret;
out_destroy:
+ dprintk("Couldn't create callback socket or server thread; err = %d\n",
+ ret);
svc_destroy(serv);
out_err:
nfs_callback_info.users--;
@@ -166,15 +166,19 @@ void nfs_callback_down(void)
static int nfs_callback_authenticate(struct svc_rqst *rqstp)
{
- struct sockaddr_in *addr = &rqstp->rq_addr;
+ struct sockaddr_in *addr = svc_addr_in(rqstp);
struct nfs_client *clp;
+ char buf[RPC_MAX_ADDRBUFLEN];
/* Don't talk to strangers */
clp = nfs_find_client(addr, 4);
if (clp == NULL)
return SVC_DROP;
- dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr->sin_addr));
+
+ dprintk("%s: %s NFSv4 callback!\n", __FUNCTION__,
+ svc_print_addr(rqstp, buf, sizeof(buf)));
nfs_put_client(clp);
+
switch (rqstp->rq_authop->flavour) {
case RPC_AUTH_NULL:
if (rqstp->rq_proc != CB_NULL)
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index f8ea1f51f59..849a2029975 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -176,7 +176,7 @@ static __be32 decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr
status = decode_fh(xdr, &args->fh);
if (unlikely(status != 0))
goto out;
- args->addr = &rqstp->rq_addr;
+ args->addr = svc_addr_in(rqstp);
status = decode_bitmap(xdr, args->bitmap);
out:
dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
@@ -188,7 +188,7 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr,
__be32 *p;
__be32 status;
- args->addr = &rqstp->rq_addr;
+ args->addr = svc_addr_in(rqstp);
status = decode_stateid(xdr, &args->stateid);
if (unlikely(status != 0))
goto out;
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 23ab145daa2..ae9f36e393c 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1173,7 +1173,7 @@ static struct seq_operations nfs_server_list_ops = {
.show = nfs_server_list_show,
};
-static struct file_operations nfs_server_list_fops = {
+static const struct file_operations nfs_server_list_fops = {
.open = nfs_server_list_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -1193,7 +1193,7 @@ static struct seq_operations nfs_volume_list_ops = {
.show = nfs_volume_list_show,
};
-static struct file_operations nfs_volume_list_fops = {
+static const struct file_operations nfs_volume_list_fops = {
.open = nfs_volume_list_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index d9ba8cb0ee7..f03a770bacb 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -65,7 +65,7 @@ const struct file_operations nfs_dir_operations = {
.fsync = nfs_fsync_dir,
};
-struct inode_operations nfs_dir_inode_operations = {
+const struct inode_operations nfs_dir_inode_operations = {
.create = nfs_create,
.lookup = nfs_lookup,
.link = nfs_link,
@@ -81,7 +81,7 @@ struct inode_operations nfs_dir_inode_operations = {
};
#ifdef CONFIG_NFS_V3
-struct inode_operations nfs3_dir_inode_operations = {
+const struct inode_operations nfs3_dir_inode_operations = {
.create = nfs_create,
.lookup = nfs_lookup,
.link = nfs_link,
@@ -104,7 +104,7 @@ struct inode_operations nfs3_dir_inode_operations = {
#ifdef CONFIG_NFS_V4
static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
-struct inode_operations nfs4_dir_inode_operations = {
+const struct inode_operations nfs4_dir_inode_operations = {
.create = nfs_create,
.lookup = nfs_atomic_lookup,
.link = nfs_link,
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 9e4a2b70995..8e66b5a2d49 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -68,14 +68,14 @@ const struct file_operations nfs_file_operations = {
.check_flags = nfs_check_flags,
};
-struct inode_operations nfs_file_inode_operations = {
+const struct inode_operations nfs_file_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
};
#ifdef CONFIG_NFS_V3
-struct inode_operations nfs3_file_inode_operations = {
+const struct inode_operations nfs3_file_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 371b804e7cc..7f86e65182e 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -155,12 +155,12 @@ out_follow:
goto out;
}
-struct inode_operations nfs_mountpoint_inode_operations = {
+const struct inode_operations nfs_mountpoint_inode_operations = {
.follow_link = nfs_follow_mountpoint,
.getattr = nfs_getattr,
};
-struct inode_operations nfs_referral_inode_operations = {
+const struct inode_operations nfs_referral_inode_operations = {
.follow_link = nfs_follow_mountpoint,
};
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index c26cd978c7c..e2341766c4f 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -151,7 +151,7 @@ struct nfs4_state_recovery_ops {
};
extern struct dentry_operations nfs4_dentry_operations;
-extern struct inode_operations nfs4_dir_inode_operations;
+extern const struct inode_operations nfs4_dir_inode_operations;
/* inode.c */
extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index b3fd29baadc..1daee65b517 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3625,7 +3625,7 @@ struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = {
.recover_lock = nfs4_lock_expired,
};
-static struct inode_operations nfs4_file_inode_operations = {
+static const struct inode_operations nfs4_file_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 28108c82b88..baa28860ad2 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -44,6 +44,7 @@
#include <linux/vfs.h>
#include <linux/inet.h>
#include <linux/nfs_xdr.h>
+#include <linux/magic.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -81,7 +82,7 @@ struct file_system_type nfs_xdev_fs_type = {
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
};
-static struct super_operations nfs_sops = {
+static const struct super_operations nfs_sops = {
.alloc_inode = nfs_alloc_inode,
.destroy_inode = nfs_destroy_inode,
.write_inode = nfs_write_inode,
@@ -125,7 +126,7 @@ struct file_system_type nfs4_referral_fs_type = {
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
};
-static struct super_operations nfs4_sops = {
+static const struct super_operations nfs4_sops = {
.alloc_inode = nfs_alloc_inode,
.destroy_inode = nfs_destroy_inode,
.write_inode = nfs_write_inode,
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 525c136c7d8..f4a0548b9ce 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -78,7 +78,7 @@ read_failed:
/*
* symlinks can't do much...
*/
-struct inode_operations nfs_symlink_inode_operations = {
+const struct inode_operations nfs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = nfs_follow_link,
.put_link = page_put_link,
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 9de89df961f..9e406799920 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -714,7 +714,7 @@ __be32
nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_setclientid *setclid)
{
- __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+ struct sockaddr_in *sin = svc_addr_in(rqstp);
struct xdr_netobj clname = {
.len = setclid->se_namelen,
.data = setclid->se_name,
@@ -749,7 +749,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
*/
status = nfserr_clid_inuse;
if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred)
- || conf->cl_addr != ip_addr) {
+ || conf->cl_addr != sin->sin_addr.s_addr) {
printk("NFSD: setclientid: string in use by client"
"(clientid %08x/%08x)\n",
conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id);
@@ -769,7 +769,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (new == NULL)
goto out;
copy_verf(new, &clverifier);
- new->cl_addr = ip_addr;
+ new->cl_addr = sin->sin_addr.s_addr;
copy_cred(&new->cl_cred,&rqstp->rq_cred);
gen_clid(new);
gen_confirm(new);
@@ -801,7 +801,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (new == NULL)
goto out;
copy_verf(new,&conf->cl_verifier);
- new->cl_addr = ip_addr;
+ new->cl_addr = sin->sin_addr.s_addr;
copy_cred(&new->cl_cred,&rqstp->rq_cred);
copy_clid(new, conf);
gen_confirm(new);
@@ -820,7 +820,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (new == NULL)
goto out;
copy_verf(new,&clverifier);
- new->cl_addr = ip_addr;
+ new->cl_addr = sin->sin_addr.s_addr;
copy_cred(&new->cl_cred,&rqstp->rq_cred);
gen_clid(new);
gen_confirm(new);
@@ -847,7 +847,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (new == NULL)
goto out;
copy_verf(new,&clverifier);
- new->cl_addr = ip_addr;
+ new->cl_addr = sin->sin_addr.s_addr;
copy_cred(&new->cl_cred,&rqstp->rq_cred);
gen_clid(new);
gen_confirm(new);
@@ -881,7 +881,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
struct nfsd4_compound_state *cstate,
struct nfsd4_setclientid_confirm *setclientid_confirm)
{
- __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+ struct sockaddr_in *sin = svc_addr_in(rqstp);
struct nfs4_client *conf, *unconf;
nfs4_verifier confirm = setclientid_confirm->sc_confirm;
clientid_t * clid = &setclientid_confirm->sc_clientid;
@@ -900,9 +900,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
unconf = find_unconfirmed_client(clid);
status = nfserr_clid_inuse;
- if (conf && conf->cl_addr != ip_addr)
+ if (conf && conf->cl_addr != sin->sin_addr.s_addr)
goto out;
- if (unconf && unconf->cl_addr != ip_addr)
+ if (unconf && unconf->cl_addr != sin->sin_addr.s_addr)
goto out;
if ((conf && unconf) &&
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index f90d7047585..578f2c9d56b 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -185,7 +185,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
rp->c_state = RC_INPROG;
rp->c_xid = xid;
rp->c_proc = proc;
- rp->c_addr = rqstp->rq_addr;
+ memcpy(&rp->c_addr, svc_addr_in(rqstp), sizeof(rp->c_addr));
rp->c_prot = proto;
rp->c_vers = vers;
rp->c_timestamp = jiffies;
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index c59d6fbb7a6..a0b4282cb28 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -20,6 +20,7 @@
#include <linux/mount.h>
#include <asm/pgtable.h>
+#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
@@ -180,10 +181,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
/* Check if the request originated from a secure port. */
error = nfserr_perm;
if (!rqstp->rq_secure && EX_SECURE(exp)) {
+ char buf[RPC_MAX_ADDRBUFLEN];
printk(KERN_WARNING
- "nfsd: request from insecure port (%u.%u.%u.%u:%d)!\n",
- NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
- ntohs(rqstp->rq_addr.sin_port));
+ "nfsd: request from insecure port %s!\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)));
goto out;
}
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index ec983b77768..5cc2eec981b 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -19,6 +19,7 @@
#include <linux/unistd.h>
#include <linux/slab.h>
+#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
@@ -147,10 +148,10 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
*/
if (NFSSVC_MAXBLKSIZE_V2 < argp->count) {
+ char buf[RPC_MAX_ADDRBUFLEN];
printk(KERN_NOTICE
- "oversized read request from %u.%u.%u.%u:%d (%d bytes)\n",
- NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
- ntohs(rqstp->rq_addr.sin_port),
+ "oversized read request from %s (%d bytes)\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)),
argp->count);
argp->count = NFSSVC_MAXBLKSIZE_V2;
}
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index fbf5d51947e..d7759ce6ed9 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -235,7 +235,8 @@ static int nfsd_init_socks(int port)
error = lockd_up(IPPROTO_UDP);
if (error >= 0) {
- error = svc_makesock(nfsd_serv, IPPROTO_UDP, port);
+ error = svc_makesock(nfsd_serv, IPPROTO_UDP, port,
+ SVC_SOCK_DEFAULTS);
if (error < 0)
lockd_down();
}
@@ -245,7 +246,8 @@ static int nfsd_init_socks(int port)
#ifdef CONFIG_NFSD_TCP
error = lockd_up(IPPROTO_TCP);
if (error >= 0) {
- error = svc_makesock(nfsd_serv, IPPROTO_TCP, port);
+ error = svc_makesock(nfsd_serv, IPPROTO_TCP, port,
+ SVC_SOCK_DEFAULTS);
if (error < 0)
lockd_down();
}
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index c577d8e1bd9..7659cc19299 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -1921,7 +1921,7 @@ s64 ntfs_attr_extend_allocation(ntfs_inode *ni, s64 new_alloc_size,
u32 attr_len = 0; /* Silence stupid gcc warning. */
bool mp_rebuilt;
-#ifdef NTFS_DEBUG
+#ifdef DEBUG
read_lock_irqsave(&ni->size_lock, flags);
allocated_size = ni->allocated_size;
read_unlock_irqrestore(&ni->size_lock, flags);
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 076c9420c25..d69c4595ccd 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2328,7 +2328,7 @@ const struct file_operations ntfs_file_ops = {
the data source. */
};
-struct inode_operations ntfs_file_inode_ops = {
+const struct inode_operations ntfs_file_inode_ops = {
#ifdef NTFS_RW
.truncate = ntfs_truncate_vfs,
.setattr = ntfs_setattr,
@@ -2337,4 +2337,4 @@ struct inode_operations ntfs_file_inode_ops = {
const struct file_operations ntfs_empty_file_ops = {};
-struct inode_operations ntfs_empty_inode_ops = {};
+const struct inode_operations ntfs_empty_inode_ops = {};
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index eddb2247cec..bff01a54675 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -359,7 +359,7 @@ err_out:
/**
* Inode operations for directories.
*/
-struct inode_operations ntfs_dir_inode_ops = {
+const struct inode_operations ntfs_dir_inode_ops = {
.lookup = ntfs_lookup, /* VFS: Lookup directory. */
};
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h
index a12847ae467..d73f5a9ac34 100644
--- a/fs/ntfs/ntfs.h
+++ b/fs/ntfs/ntfs.h
@@ -61,13 +61,13 @@ extern const struct address_space_operations ntfs_aops;
extern const struct address_space_operations ntfs_mst_aops;
extern const struct file_operations ntfs_file_ops;
-extern struct inode_operations ntfs_file_inode_ops;
+extern const struct inode_operations ntfs_file_inode_ops;
extern const struct file_operations ntfs_dir_ops;
-extern struct inode_operations ntfs_dir_inode_ops;
+extern const struct inode_operations ntfs_dir_inode_ops;
extern const struct file_operations ntfs_empty_file_ops;
-extern struct inode_operations ntfs_empty_inode_ops;
+extern const struct inode_operations ntfs_empty_inode_ops;
extern struct export_operations ntfs_export_ops;
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index babf94d90de..1594c90b716 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -2699,7 +2699,7 @@ static int ntfs_statfs(struct dentry *dentry, struct kstatfs *sfs)
/**
* The complete super operations.
*/
-static struct super_operations ntfs_sops = {
+static const struct super_operations ntfs_sops = {
.alloc_inode = ntfs_alloc_big_inode, /* VFS: Allocate new inode. */
.destroy_inode = ntfs_destroy_big_inode, /* VFS: Deallocate inode. */
#ifdef NTFS_RW
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
index b7f0ba97a1a..de952eba29a 100644
--- a/fs/ocfs2/dlm/dlmfs.c
+++ b/fs/ocfs2/dlm/dlmfs.c
@@ -61,11 +61,11 @@
#define MLOG_MASK_PREFIX ML_DLMFS
#include "cluster/masklog.h"
-static struct super_operations dlmfs_ops;
-static struct file_operations dlmfs_file_operations;
-static struct inode_operations dlmfs_dir_inode_operations;
-static struct inode_operations dlmfs_root_inode_operations;
-static struct inode_operations dlmfs_file_inode_operations;
+static const struct super_operations dlmfs_ops;
+static const struct file_operations dlmfs_file_operations;
+static const struct inode_operations dlmfs_dir_inode_operations;
+static const struct inode_operations dlmfs_root_inode_operations;
+static const struct inode_operations dlmfs_file_inode_operations;
static struct kmem_cache *dlmfs_inode_cache;
struct workqueue_struct *user_dlm_worker;
@@ -540,27 +540,27 @@ static int dlmfs_fill_super(struct super_block * sb,
return 0;
}
-static struct file_operations dlmfs_file_operations = {
+static const struct file_operations dlmfs_file_operations = {
.open = dlmfs_file_open,
.release = dlmfs_file_release,
.read = dlmfs_file_read,
.write = dlmfs_file_write,
};
-static struct inode_operations dlmfs_dir_inode_operations = {
+static const struct inode_operations dlmfs_dir_inode_operations = {
.create = dlmfs_create,
.lookup = simple_lookup,
.unlink = dlmfs_unlink,
};
/* this way we can restrict mkdir to only the toplevel of the fs. */
-static struct inode_operations dlmfs_root_inode_operations = {
+static const struct inode_operations dlmfs_root_inode_operations = {
.lookup = simple_lookup,
.mkdir = dlmfs_mkdir,
.rmdir = simple_rmdir,
};
-static struct super_operations dlmfs_ops = {
+static const struct super_operations dlmfs_ops = {
.statfs = simple_statfs,
.alloc_inode = dlmfs_alloc_inode,
.destroy_inode = dlmfs_destroy_inode,
@@ -568,7 +568,7 @@ static struct super_operations dlmfs_ops = {
.drop_inode = generic_delete_inode,
};
-static struct inode_operations dlmfs_file_inode_operations = {
+static const struct inode_operations dlmfs_file_inode_operations = {
.getattr = simple_getattr,
};
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 10953a508f2..f2cd3bf9efb 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1365,13 +1365,13 @@ bail:
return ret;
}
-struct inode_operations ocfs2_file_iops = {
+const struct inode_operations ocfs2_file_iops = {
.setattr = ocfs2_setattr,
.getattr = ocfs2_getattr,
.permission = ocfs2_permission,
};
-struct inode_operations ocfs2_special_file_iops = {
+const struct inode_operations ocfs2_special_file_iops = {
.setattr = ocfs2_setattr,
.getattr = ocfs2_getattr,
.permission = ocfs2_permission,
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index 601a453f18a..cc973f01f6c 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -28,8 +28,8 @@
extern const struct file_operations ocfs2_fops;
extern const struct file_operations ocfs2_dops;
-extern struct inode_operations ocfs2_file_iops;
-extern struct inode_operations ocfs2_special_file_iops;
+extern const struct inode_operations ocfs2_file_iops;
+extern const struct inode_operations ocfs2_special_file_iops;
struct ocfs2_alloc_context;
enum ocfs2_alloc_restarted {
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index f3d7803b4b4..f7fa52bb3f6 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -2306,7 +2306,7 @@ leave:
return status;
}
-struct inode_operations ocfs2_dir_iops = {
+const struct inode_operations ocfs2_dir_iops = {
.create = ocfs2_create,
.lookup = ocfs2_lookup,
.link = ocfs2_link,
diff --git a/fs/ocfs2/namei.h b/fs/ocfs2/namei.h
index 8425944fccc..0975c7b7212 100644
--- a/fs/ocfs2/namei.h
+++ b/fs/ocfs2/namei.h
@@ -26,7 +26,7 @@
#ifndef OCFS2_NAMEI_H
#define OCFS2_NAMEI_H
-extern struct inode_operations ocfs2_dir_iops;
+extern const struct inode_operations ocfs2_dir_iops;
struct dentry *ocfs2_get_parent(struct dentry *child);
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 6e300a88a47..6534f92424d 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -116,7 +116,7 @@ static void ocfs2_destroy_inode(struct inode *inode);
static unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
-static struct super_operations ocfs2_sops = {
+static const struct super_operations ocfs2_sops = {
.statfs = ocfs2_statfs,
.alloc_inode = ocfs2_alloc_inode,
.destroy_inode = ocfs2_destroy_inode,
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index 03b0191534d..40dc1a51f4a 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -170,12 +170,12 @@ bail:
return ERR_PTR(status);
}
-struct inode_operations ocfs2_symlink_inode_operations = {
+const struct inode_operations ocfs2_symlink_inode_operations = {
.readlink = page_readlink,
.follow_link = ocfs2_follow_link,
.getattr = ocfs2_getattr,
};
-struct inode_operations ocfs2_fast_symlink_inode_operations = {
+const struct inode_operations ocfs2_fast_symlink_inode_operations = {
.readlink = ocfs2_readlink,
.follow_link = ocfs2_follow_link,
.getattr = ocfs2_getattr,
diff --git a/fs/ocfs2/symlink.h b/fs/ocfs2/symlink.h
index 1ea9e4d9e9e..65a6c9c6ad5 100644
--- a/fs/ocfs2/symlink.h
+++ b/fs/ocfs2/symlink.h
@@ -26,8 +26,8 @@
#ifndef OCFS2_SYMLINK_H
#define OCFS2_SYMLINK_H
-extern struct inode_operations ocfs2_symlink_inode_operations;
-extern struct inode_operations ocfs2_fast_symlink_inode_operations;
+extern const struct inode_operations ocfs2_symlink_inode_operations;
+extern const struct inode_operations ocfs2_fast_symlink_inode_operations;
/*
* Test whether an inode is a fast symlink.
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index 99c0bc37ba0..bde1c164417 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -169,7 +169,7 @@ static const struct file_operations openprom_operations = {
static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, struct nameidata *);
-static struct inode_operations openprom_inode_operations = {
+static const struct inode_operations openprom_inode_operations = {
.lookup = openpromfs_lookup,
};
@@ -364,7 +364,7 @@ static int openprom_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
-static struct super_operations openprom_sops = {
+static const struct super_operations openprom_sops = {
.alloc_inode = openprom_alloc_inode,
.destroy_inode = openprom_destroy_inode,
.read_inode = openprom_read_inode,
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 3d73d94d93a..ac32a2e8540 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -365,7 +365,7 @@ void delete_partition(struct gendisk *disk, int part)
kobject_put(&p->kobj);
}
-void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
+void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags)
{
struct hd_struct *p;
@@ -390,6 +390,15 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
if (!disk->part_uevent_suppress)
kobject_uevent(&p->kobj, KOBJ_ADD);
sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem");
+ if (flags & ADDPART_FLAG_WHOLEDISK) {
+ static struct attribute addpartattr = {
+ .name = "whole_disk",
+ .mode = S_IRUSR | S_IRGRP | S_IROTH,
+ .owner = THIS_MODULE,
+ };
+
+ sysfs_create_file(&p->kobj, &addpartattr);
+ }
partition_sysfs_add_subdir(p);
disk->part[part-1] = p;
}
@@ -543,9 +552,9 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
printk(" %s: p%d exceeds device capacity\n",
disk->disk_name, p);
}
- add_partition(disk, p, from, size);
+ add_partition(disk, p, from, size, state->parts[p].flags);
#ifdef CONFIG_BLK_DEV_MD
- if (state->parts[p].flags)
+ if (state->parts[p].flags & ADDPART_FLAG_RAID)
md_autodetect_dev(bdev->bd_dev+p);
#endif
}
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 8c7af177781..4ccec4cd136 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -63,15 +63,25 @@ msdos_magic_present(unsigned char *p)
#define AIX_LABEL_MAGIC4 0xC1
static int aix_magic_present(unsigned char *p, struct block_device *bdev)
{
+ struct partition *pt = (struct partition *) (p + 0x1be);
Sector sect;
unsigned char *d;
- int ret = 0;
+ int slot, ret = 0;
- if (p[0] != AIX_LABEL_MAGIC1 &&
- p[1] != AIX_LABEL_MAGIC2 &&
- p[2] != AIX_LABEL_MAGIC3 &&
- p[3] != AIX_LABEL_MAGIC4)
+ if (!(p[0] == AIX_LABEL_MAGIC1 &&
+ p[1] == AIX_LABEL_MAGIC2 &&
+ p[2] == AIX_LABEL_MAGIC3 &&
+ p[3] == AIX_LABEL_MAGIC4))
return 0;
+ /* Assume the partition table is valid if Linux partitions exists */
+ for (slot = 1; slot <= 4; slot++, pt++) {
+ if (pt->sys_ind == LINUX_SWAP_PARTITION ||
+ pt->sys_ind == LINUX_RAID_PARTITION ||
+ pt->sys_ind == LINUX_DATA_PARTITION ||
+ pt->sys_ind == LINUX_LVM_PARTITION ||
+ is_extended_partition(pt))
+ return 0;
+ }
d = read_dev_sector(bdev, 7, &sect);
if (d) {
if (d[0] == '_' && d[1] == 'L' && d[2] == 'V' && d[3] == 'M')
@@ -155,7 +165,7 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev,
put_partition(state, state->next, next, size);
if (SYS_IND(p) == LINUX_RAID_PARTITION)
- state->parts[state->next].flags = 1;
+ state->parts[state->next].flags = ADDPART_FLAG_RAID;
loopct = 0;
if (++state->next == state->limit)
goto done;
diff --git a/fs/partitions/sgi.c b/fs/partitions/sgi.c
index 6fa4ff89510..ed5ac83fe83 100644
--- a/fs/partitions/sgi.c
+++ b/fs/partitions/sgi.c
@@ -72,7 +72,7 @@ int sgi_partition(struct parsed_partitions *state, struct block_device *bdev)
if (blocks) {
put_partition(state, slot, start, blocks);
if (be32_to_cpu(p->type) == LINUX_RAID_PARTITION)
- state->parts[slot].flags = 1;
+ state->parts[slot].flags = ADDPART_FLAG_RAID;
}
slot++;
}
diff --git a/fs/partitions/sun.c b/fs/partitions/sun.c
index 0a5927c806c..123f8b46c8b 100644
--- a/fs/partitions/sun.c
+++ b/fs/partitions/sun.c
@@ -80,8 +80,11 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
num_sectors = be32_to_cpu(p->num_sectors);
if (num_sectors) {
put_partition(state, slot, st_sector, num_sectors);
+ state->parts[slot].flags = 0;
if (label->infos[i].id == LINUX_RAID_PARTITION)
- state->parts[slot].flags = 1;
+ state->parts[slot].flags |= ADDPART_FLAG_RAID;
+ if (label->infos[i].id == SUN_WHOLE_DISK)
+ state->parts[slot].flags |= ADDPART_FLAG_WHOLEDISK;
}
slot++;
}
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 70e4fab117b..07c9cdbcdca 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -351,7 +351,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
struct signal_struct *sig = task->signal;
if (sig->tty) {
- tty_pgrp = sig->tty->pgrp;
+ tty_pgrp = pid_nr(sig->tty->pgrp);
tty_nr = new_encode_dev(tty_devnum(sig->tty));
}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 1a979ea3b37..4f5745af8c1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -93,8 +93,8 @@ struct pid_entry {
int len;
char *name;
mode_t mode;
- struct inode_operations *iop;
- struct file_operations *fop;
+ const struct inode_operations *iop;
+ const struct file_operations *fop;
union proc_op op;
};
@@ -352,7 +352,7 @@ static int proc_setattr(struct dentry *dentry, struct iattr *attr)
return error;
}
-static struct inode_operations proc_def_inode_operations = {
+static const struct inode_operations proc_def_inode_operations = {
.setattr = proc_setattr,
};
@@ -424,7 +424,7 @@ static unsigned mounts_poll(struct file *file, poll_table *wait)
return res;
}
-static struct file_operations proc_mounts_operations = {
+static const struct file_operations proc_mounts_operations = {
.open = mounts_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -462,7 +462,7 @@ static int mountstats_open(struct inode *inode, struct file *file)
return ret;
}
-static struct file_operations proc_mountstats_operations = {
+static const struct file_operations proc_mountstats_operations = {
.open = mountstats_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -501,7 +501,7 @@ out_no_task:
return length;
}
-static struct file_operations proc_info_file_operations = {
+static const struct file_operations proc_info_file_operations = {
.read = proc_info_read,
};
@@ -646,7 +646,7 @@ static loff_t mem_lseek(struct file * file, loff_t offset, int orig)
return file->f_pos;
}
-static struct file_operations proc_mem_operations = {
+static const struct file_operations proc_mem_operations = {
.llseek = mem_lseek,
.read = mem_read,
.write = mem_write,
@@ -710,7 +710,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
return end - buffer;
}
-static struct file_operations proc_oom_adjust_operations = {
+static const struct file_operations proc_oom_adjust_operations = {
.read = oom_adjust_read,
.write = oom_adjust_write,
};
@@ -777,7 +777,7 @@ out_free_page:
return length;
}
-static struct file_operations proc_loginuid_operations = {
+static const struct file_operations proc_loginuid_operations = {
.read = proc_loginuid_read,
.write = proc_loginuid_write,
};
@@ -849,7 +849,7 @@ out_no_task:
return result;
}
-static struct file_operations proc_seccomp_operations = {
+static const struct file_operations proc_seccomp_operations = {
.read = seccomp_read,
.write = seccomp_write,
};
@@ -908,7 +908,7 @@ static ssize_t proc_fault_inject_write(struct file * file,
return end - buffer;
}
-static struct file_operations proc_fault_inject_operations = {
+static const struct file_operations proc_fault_inject_operations = {
.read = proc_fault_inject_read,
.write = proc_fault_inject_write,
};
@@ -980,7 +980,7 @@ out:
return error;
}
-static struct inode_operations proc_pid_link_inode_operations = {
+static const struct inode_operations proc_pid_link_inode_operations = {
.readlink = proc_pid_readlink,
.follow_link = proc_pid_follow_link,
.setattr = proc_setattr,
@@ -1408,7 +1408,7 @@ out_no_task:
return retval;
}
-static struct file_operations proc_fd_operations = {
+static const struct file_operations proc_fd_operations = {
.read = generic_read_dir,
.readdir = proc_readfd,
};
@@ -1416,7 +1416,7 @@ static struct file_operations proc_fd_operations = {
/*
* proc directories can do almost nothing..
*/
-static struct inode_operations proc_fd_inode_operations = {
+static const struct inode_operations proc_fd_inode_operations = {
.lookup = proc_lookupfd,
.setattr = proc_setattr,
};
@@ -1623,7 +1623,7 @@ out_no_task:
return length;
}
-static struct file_operations proc_pid_attr_operations = {
+static const struct file_operations proc_pid_attr_operations = {
.read = proc_pid_attr_read,
.write = proc_pid_attr_write,
};
@@ -1644,7 +1644,7 @@ static int proc_attr_dir_readdir(struct file * filp,
attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff));
}
-static struct file_operations proc_attr_dir_operations = {
+static const struct file_operations proc_attr_dir_operations = {
.read = generic_read_dir,
.readdir = proc_attr_dir_readdir,
};
@@ -1656,7 +1656,7 @@ static struct dentry *proc_attr_dir_lookup(struct inode *dir,
attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));
}
-static struct inode_operations proc_attr_dir_inode_operations = {
+static const struct inode_operations proc_attr_dir_inode_operations = {
.lookup = proc_attr_dir_lookup,
.getattr = pid_getattr,
.setattr = proc_setattr,
@@ -1682,7 +1682,7 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
return ERR_PTR(vfs_follow_link(nd,tmp));
}
-static struct inode_operations proc_self_inode_operations = {
+static const struct inode_operations proc_self_inode_operations = {
.readlink = proc_self_readlink,
.follow_link = proc_self_follow_link,
};
@@ -1810,17 +1810,21 @@ static int proc_base_fill_cache(struct file *filp, void *dirent, filldir_t filld
static int proc_pid_io_accounting(struct task_struct *task, char *buffer)
{
return sprintf(buffer,
+#ifdef CONFIG_TASK_XACCT
"rchar: %llu\n"
"wchar: %llu\n"
"syscr: %llu\n"
"syscw: %llu\n"
+#endif
"read_bytes: %llu\n"
"write_bytes: %llu\n"
"cancelled_write_bytes: %llu\n",
+#ifdef CONFIG_TASK_XACCT
(unsigned long long)task->rchar,
(unsigned long long)task->wchar,
(unsigned long long)task->syscr,
(unsigned long long)task->syscw,
+#endif
(unsigned long long)task->ioac.read_bytes,
(unsigned long long)task->ioac.write_bytes,
(unsigned long long)task->ioac.cancelled_write_bytes);
@@ -1830,8 +1834,8 @@ static int proc_pid_io_accounting(struct task_struct *task, char *buffer)
/*
* Thread groups
*/
-static struct file_operations proc_task_operations;
-static struct inode_operations proc_task_inode_operations;
+static const struct file_operations proc_task_operations;
+static const struct inode_operations proc_task_inode_operations;
static struct pid_entry tgid_base_stuff[] = {
DIR("task", S_IRUGO|S_IXUGO, task),
@@ -1890,7 +1894,7 @@ static int proc_tgid_base_readdir(struct file * filp,
tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff));
}
-static struct file_operations proc_tgid_base_operations = {
+static const struct file_operations proc_tgid_base_operations = {
.read = generic_read_dir,
.readdir = proc_tgid_base_readdir,
};
@@ -1900,7 +1904,7 @@ static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *de
tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
}
-static struct inode_operations proc_tgid_base_inode_operations = {
+static const struct inode_operations proc_tgid_base_inode_operations = {
.lookup = proc_tgid_base_lookup,
.getattr = pid_getattr,
.setattr = proc_setattr,
@@ -2173,12 +2177,12 @@ static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *den
tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
}
-static struct file_operations proc_tid_base_operations = {
+static const struct file_operations proc_tid_base_operations = {
.read = generic_read_dir,
.readdir = proc_tid_base_readdir,
};
-static struct inode_operations proc_tid_base_inode_operations = {
+static const struct inode_operations proc_tid_base_inode_operations = {
.lookup = proc_tid_base_lookup,
.getattr = pid_getattr,
.setattr = proc_setattr,
@@ -2404,13 +2408,13 @@ static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct
return 0;
}
-static struct inode_operations proc_task_inode_operations = {
+static const struct inode_operations proc_task_inode_operations = {
.lookup = proc_task_lookup,
.getattr = proc_task_getattr,
.setattr = proc_setattr,
};
-static struct file_operations proc_task_operations = {
+static const struct file_operations proc_task_operations = {
.read = generic_read_dir,
.readdir = proc_task_readdir,
};
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 853cb877d5f..0cdc00d9d97 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -39,7 +39,7 @@ int proc_match(int len, const char *name, struct proc_dir_entry *de)
return !memcmp(name, de->name, len);
}
-static struct file_operations proc_file_operations = {
+static const struct file_operations proc_file_operations = {
.llseek = proc_file_lseek,
.read = proc_file_read,
.write = proc_file_write,
@@ -265,7 +265,7 @@ static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry,
return 0;
}
-static struct inode_operations proc_file_inode_operations = {
+static const struct inode_operations proc_file_inode_operations = {
.setattr = proc_notify_change,
};
@@ -357,7 +357,7 @@ static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
return NULL;
}
-static struct inode_operations proc_link_inode_operations = {
+static const struct inode_operations proc_link_inode_operations = {
.readlink = generic_readlink,
.follow_link = proc_follow_link,
};
@@ -497,7 +497,7 @@ out: unlock_kernel();
* use the in-memory "struct proc_dir_entry" tree to parse
* the /proc directory.
*/
-static struct file_operations proc_dir_operations = {
+static const struct file_operations proc_dir_operations = {
.read = generic_read_dir,
.readdir = proc_readdir,
};
@@ -505,7 +505,7 @@ static struct file_operations proc_dir_operations = {
/*
* proc directories can do almost nothing..
*/
-static struct inode_operations proc_dir_inode_operations = {
+static const struct inode_operations proc_dir_inode_operations = {
.lookup = proc_lookup,
.getattr = proc_getattr,
.setattr = proc_notify_change,
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index e26945ba685..f6722be37dd 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -132,7 +132,7 @@ static int proc_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
-static struct super_operations proc_sops = {
+static const struct super_operations proc_sops = {
.alloc_inode = proc_alloc_inode,
.destroy_inode = proc_destroy_inode,
.read_inode = proc_read_inode,
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 987c773dbb2..277dcd66ebe 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -38,13 +38,13 @@ extern int proc_tgid_stat(struct task_struct *, char *);
extern int proc_pid_status(struct task_struct *, char *);
extern int proc_pid_statm(struct task_struct *, char *);
-extern struct file_operations proc_maps_operations;
-extern struct file_operations proc_numa_maps_operations;
-extern struct file_operations proc_smaps_operations;
+extern const struct file_operations proc_maps_operations;
+extern const struct file_operations proc_numa_maps_operations;
+extern const struct file_operations proc_smaps_operations;
-extern struct file_operations proc_maps_operations;
-extern struct file_operations proc_numa_maps_operations;
-extern struct file_operations proc_smaps_operations;
+extern const struct file_operations proc_maps_operations;
+extern const struct file_operations proc_numa_maps_operations;
+extern const struct file_operations proc_smaps_operations;
void free_proc_entry(struct proc_dir_entry *de);
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
index 5ec67257e5f..22f789de390 100644
--- a/fs/proc/nommu.c
+++ b/fs/proc/nommu.c
@@ -128,7 +128,7 @@ static int proc_nommu_vma_list_open(struct inode *inode, struct file *file)
return seq_open(file, &proc_nommu_vma_list_seqop);
}
-static struct file_operations proc_nommu_vma_list_operations = {
+static const struct file_operations proc_nommu_vma_list_operations = {
.open = proc_nommu_vma_list_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index b37ce33f67e..e2c4c0a5c90 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -121,16 +121,11 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
{
struct sysinfo i;
int len;
- unsigned long inactive;
- unsigned long active;
- unsigned long free;
unsigned long committed;
unsigned long allowed;
struct vmalloc_info vmi;
long cached;
- get_zone_counts(&active, &inactive, &free);
-
/*
* display in kilobytes.
*/
@@ -187,8 +182,8 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
K(i.bufferram),
K(cached),
K(total_swapcache_pages),
- K(active),
- K(inactive),
+ K(global_page_state(NR_ACTIVE)),
+ K(global_page_state(NR_INACTIVE)),
#ifdef CONFIG_HIGHMEM
K(i.totalhigh),
K(i.freehigh),
@@ -228,7 +223,7 @@ static int fragmentation_open(struct inode *inode, struct file *file)
return seq_open(file, &fragmentation_op);
}
-static struct file_operations fragmentation_file_operations = {
+static const struct file_operations fragmentation_file_operations = {
.open = fragmentation_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -241,7 +236,7 @@ static int zoneinfo_open(struct inode *inode, struct file *file)
return seq_open(file, &zoneinfo_op);
}
-static struct file_operations proc_zoneinfo_file_operations = {
+static const struct file_operations proc_zoneinfo_file_operations = {
.open = zoneinfo_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -266,7 +261,7 @@ static int cpuinfo_open(struct inode *inode, struct file *file)
return seq_open(file, &cpuinfo_op);
}
-static struct file_operations proc_cpuinfo_operations = {
+static const struct file_operations proc_cpuinfo_operations = {
.open = cpuinfo_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -325,7 +320,7 @@ static int devinfo_open(struct inode *inode, struct file *filp)
return seq_open(filp, &devinfo_ops);
}
-static struct file_operations proc_devinfo_operations = {
+static const struct file_operations proc_devinfo_operations = {
.open = devinfo_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -337,7 +332,7 @@ static int vmstat_open(struct inode *inode, struct file *file)
{
return seq_open(file, &vmstat_op);
}
-static struct file_operations proc_vmstat_file_operations = {
+static const struct file_operations proc_vmstat_file_operations = {
.open = vmstat_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -368,7 +363,7 @@ static int partitions_open(struct inode *inode, struct file *file)
{
return seq_open(file, &partitions_op);
}
-static struct file_operations proc_partitions_operations = {
+static const struct file_operations proc_partitions_operations = {
.open = partitions_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -380,7 +375,7 @@ static int diskstats_open(struct inode *inode, struct file *file)
{
return seq_open(file, &diskstats_op);
}
-static struct file_operations proc_diskstats_operations = {
+static const struct file_operations proc_diskstats_operations = {
.open = diskstats_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -394,7 +389,7 @@ static int modules_open(struct inode *inode, struct file *file)
{
return seq_open(file, &modules_op);
}
-static struct file_operations proc_modules_operations = {
+static const struct file_operations proc_modules_operations = {
.open = modules_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -409,7 +404,7 @@ static int slabinfo_open(struct inode *inode, struct file *file)
{
return seq_open(file, &slabinfo_op);
}
-static struct file_operations proc_slabinfo_operations = {
+static const struct file_operations proc_slabinfo_operations = {
.open = slabinfo_open,
.read = seq_read,
.write = slabinfo_write,
@@ -443,7 +438,7 @@ static int slabstats_release(struct inode *inode, struct file *file)
return seq_release(inode, file);
}
-static struct file_operations proc_slabstats_operations = {
+static const struct file_operations proc_slabstats_operations = {
.open = slabstats_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -556,7 +551,7 @@ static int stat_open(struct inode *inode, struct file *file)
kfree(buf);
return res;
}
-static struct file_operations proc_stat_operations = {
+static const struct file_operations proc_stat_operations = {
.open = stat_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -598,7 +593,7 @@ static int interrupts_open(struct inode *inode, struct file *filp)
return seq_open(filp, &int_seq_ops);
}
-static struct file_operations proc_interrupts_operations = {
+static const struct file_operations proc_interrupts_operations = {
.open = interrupts_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -655,7 +650,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
return count;
}
-static struct file_operations proc_sysrq_trigger_operations = {
+static const struct file_operations proc_sysrq_trigger_operations = {
.write = write_sysrq_trigger,
};
#endif
@@ -672,7 +667,6 @@ void create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
void __init proc_misc_init(void)
{
- struct proc_dir_entry *entry;
static struct {
char *name;
int (*read_proc)(char*,char**,off_t,int,int*,void*);
@@ -700,9 +694,12 @@ void __init proc_misc_init(void)
/* And now for trickier ones */
#ifdef CONFIG_PRINTK
- entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
- if (entry)
- entry->proc_fops = &proc_kmsg_operations;
+ {
+ struct proc_dir_entry *entry;
+ entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
+ if (entry)
+ entry->proc_fops = &proc_kmsg_operations;
+ }
#endif
create_seq_entry("devices", 0, &proc_devinfo_operations);
create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
@@ -743,8 +740,11 @@ void __init proc_misc_init(void)
proc_vmcore->proc_fops = &proc_vmcore_operations;
#endif
#ifdef CONFIG_MAGIC_SYSRQ
- entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL);
- if (entry)
- entry->proc_fops = &proc_sysrq_trigger_operations;
+ {
+ struct proc_dir_entry *entry;
+ entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL);
+ if (entry)
+ entry->proc_fops = &proc_sysrq_trigger_operations;
+ }
#endif
}
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index 15c4455b09e..c1bbfbeb035 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -138,7 +138,7 @@ static int tty_drivers_open(struct inode *inode, struct file *file)
return seq_open(file, &tty_drivers_op);
}
-static struct file_operations proc_tty_drivers_operations = {
+static const struct file_operations proc_tty_drivers_operations = {
.open = tty_drivers_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 64d242b6dcf..af154458b54 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -136,7 +136,7 @@ static int proc_root_readdir(struct file * filp,
* <pid> directories. Thus we don't use the generic
* directory handling functions for that..
*/
-static struct file_operations proc_root_operations = {
+static const struct file_operations proc_root_operations = {
.read = generic_read_dir,
.readdir = proc_root_readdir,
};
@@ -144,7 +144,7 @@ static struct file_operations proc_root_operations = {
/*
* proc root can do almost nothing..
*/
-static struct inode_operations proc_root_inode_operations = {
+static const struct inode_operations proc_root_inode_operations = {
.lookup = proc_root_lookup,
.getattr = proc_root_getattr,
};
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 55ade0d1562..7445980c802 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -434,7 +434,7 @@ static int maps_open(struct inode *inode, struct file *file)
return do_maps_open(inode, file, &proc_pid_maps_op);
}
-struct file_operations proc_maps_operations = {
+const struct file_operations proc_maps_operations = {
.open = maps_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -456,7 +456,7 @@ static int numa_maps_open(struct inode *inode, struct file *file)
return do_maps_open(inode, file, &proc_pid_numa_maps_op);
}
-struct file_operations proc_numa_maps_operations = {
+const struct file_operations proc_numa_maps_operations = {
.open = numa_maps_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -469,7 +469,7 @@ static int smaps_open(struct inode *inode, struct file *file)
return do_maps_open(inode, file, &proc_pid_smaps_op);
}
-struct file_operations proc_smaps_operations = {
+const struct file_operations proc_smaps_operations = {
.open = smaps_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index fcc5caf93f5..7cddf6b8635 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -220,7 +220,7 @@ static int maps_open(struct inode *inode, struct file *file)
return ret;
}
-struct file_operations proc_maps_operations = {
+const struct file_operations proc_maps_operations = {
.open = maps_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index c94db1db7a7..ea9ffefb48a 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -87,7 +87,7 @@ const struct file_operations qnx4_dir_operations =
.fsync = file_fsync,
};
-struct inode_operations qnx4_dir_inode_operations =
+const struct inode_operations qnx4_dir_inode_operations =
{
.lookup = qnx4_lookup,
#ifdef CONFIG_QNX4FS_RW
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c
index 467e5ac7280..44649981bbc 100644
--- a/fs/qnx4/file.c
+++ b/fs/qnx4/file.c
@@ -33,7 +33,7 @@ const struct file_operations qnx4_file_operations =
#endif
};
-struct inode_operations qnx4_file_inode_operations =
+const struct inode_operations qnx4_file_inode_operations =
{
#ifdef CONFIG_QNX4FS_RW
.truncate = qnx4_truncate,
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index c047dc654d5..83bc8e7824c 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -30,7 +30,7 @@
#define QNX4_VERSION 4
#define QNX4_BMNAME ".bitmap"
-static struct super_operations qnx4_sops;
+static const struct super_operations qnx4_sops;
#ifdef CONFIG_QNX4FS_RW
@@ -129,7 +129,7 @@ static void qnx4_read_inode(struct inode *);
static int qnx4_remount(struct super_block *sb, int *flags, char *data);
static int qnx4_statfs(struct dentry *, struct kstatfs *);
-static struct super_operations qnx4_sops =
+static const struct super_operations qnx4_sops =
{
.alloc_inode = qnx4_alloc_inode,
.destroy_inode = qnx4_destroy_inode,
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index 54ebbc84207..2f14774a124 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -31,7 +31,7 @@ const struct address_space_operations ramfs_aops = {
.readpage = simple_readpage,
.prepare_write = simple_prepare_write,
.commit_write = simple_commit_write,
- .set_page_dirty = __set_page_dirty_nobuffers,
+ .set_page_dirty = __set_page_dirty_no_writeback,
};
const struct file_operations ramfs_file_operations = {
@@ -45,6 +45,6 @@ const struct file_operations ramfs_file_operations = {
.llseek = generic_file_llseek,
};
-struct inode_operations ramfs_file_inode_operations = {
+const struct inode_operations ramfs_file_inode_operations = {
.getattr = simple_getattr,
};
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index e9d6c473328..d3fd7c6732d 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -32,7 +32,7 @@ const struct address_space_operations ramfs_aops = {
.readpage = simple_readpage,
.prepare_write = simple_prepare_write,
.commit_write = simple_commit_write,
- .set_page_dirty = __set_page_dirty_nobuffers,
+ .set_page_dirty = __set_page_dirty_no_writeback,
};
const struct file_operations ramfs_file_operations = {
@@ -47,7 +47,7 @@ const struct file_operations ramfs_file_operations = {
.llseek = generic_file_llseek,
};
-struct inode_operations ramfs_file_inode_operations = {
+const struct inode_operations ramfs_file_inode_operations = {
.setattr = ramfs_nommu_setattr,
.getattr = simple_getattr,
};
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 2faf4cdf61b..ff1f7639707 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -40,8 +40,8 @@
/* some random number */
#define RAMFS_MAGIC 0x858458f6
-static struct super_operations ramfs_ops;
-static struct inode_operations ramfs_dir_inode_operations;
+static const struct super_operations ramfs_ops;
+static const struct inode_operations ramfs_dir_inode_operations;
static struct backing_dev_info ramfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
@@ -143,7 +143,7 @@ static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char *
return error;
}
-static struct inode_operations ramfs_dir_inode_operations = {
+static const struct inode_operations ramfs_dir_inode_operations = {
.create = ramfs_create,
.lookup = simple_lookup,
.link = simple_link,
@@ -155,7 +155,7 @@ static struct inode_operations ramfs_dir_inode_operations = {
.rename = simple_rename,
};
-static struct super_operations ramfs_ops = {
+static const struct super_operations ramfs_ops = {
.statfs = simple_statfs,
.drop_inode = generic_delete_inode,
};
diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h
index c2bb58e7465..af7cc074a47 100644
--- a/fs/ramfs/internal.h
+++ b/fs/ramfs/internal.h
@@ -12,4 +12,4 @@
extern const struct address_space_operations ramfs_aops;
extern const struct file_operations ramfs_file_operations;
-extern struct inode_operations ramfs_file_inode_operations;
+extern const struct inode_operations ramfs_file_inode_operations;
diff --git a/fs/read_write.c b/fs/read_write.c
index 707ac21700d..1f8dc373ede 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -197,13 +197,13 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
struct inode *inode;
loff_t pos;
+ inode = file->f_path.dentry->d_inode;
if (unlikely((ssize_t) count < 0))
goto Einval;
pos = *ppos;
if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
goto Einval;
- inode = file->f_path.dentry->d_inode;
if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) {
int retval = locks_mandatory_area(
read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
@@ -274,9 +274,9 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
ret = do_sync_read(file, buf, count, pos);
if (ret > 0) {
fsnotify_access(file->f_path.dentry);
- current->rchar += ret;
+ add_rchar(current, ret);
}
- current->syscr++;
+ inc_syscr(current);
}
}
@@ -332,9 +332,9 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
ret = do_sync_write(file, buf, count, pos);
if (ret > 0) {
fsnotify_modify(file->f_path.dentry);
- current->wchar += ret;
+ add_wchar(current, ret);
}
- current->syscw++;
+ inc_syscw(current);
}
}
@@ -675,8 +675,8 @@ sys_readv(unsigned long fd, const struct iovec __user *vec, unsigned long vlen)
}
if (ret > 0)
- current->rchar += ret;
- current->syscr++;
+ add_rchar(current, ret);
+ inc_syscr(current);
return ret;
}
@@ -696,8 +696,8 @@ sys_writev(unsigned long fd, const struct iovec __user *vec, unsigned long vlen)
}
if (ret > 0)
- current->wchar += ret;
- current->syscw++;
+ add_wchar(current, ret);
+ inc_syscw(current);
return ret;
}
@@ -779,12 +779,12 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file);
if (retval > 0) {
- current->rchar += retval;
- current->wchar += retval;
+ add_rchar(current, retval);
+ add_wchar(current, retval);
}
- current->syscr++;
- current->syscw++;
+ inc_syscr(current);
+ inc_syscw(current);
if (*ppos > max)
retval = -EOVERFLOW;
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
index fba304e64de..f85c5cf4934 100644
--- a/fs/reiserfs/do_balan.c
+++ b/fs/reiserfs/do_balan.c
@@ -19,6 +19,7 @@
#include <linux/time.h>
#include <linux/reiserfs_fs.h>
#include <linux/buffer_head.h>
+#include <linux/kernel.h>
#ifdef CONFIG_REISERFS_CHECK
@@ -1756,7 +1757,7 @@ static void store_thrown(struct tree_balance *tb, struct buffer_head *bh)
if (buffer_dirty(bh))
reiserfs_warning(tb->tb_sb,
"store_thrown deals with dirty buffer");
- for (i = 0; i < sizeof(tb->thrown) / sizeof(tb->thrown[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(tb->thrown); i++)
if (!tb->thrown[i]) {
tb->thrown[i] = bh;
get_bh(bh); /* free_thrown puts this */
@@ -1769,7 +1770,7 @@ static void free_thrown(struct tree_balance *tb)
{
int i;
b_blocknr_t blocknr;
- for (i = 0; i < sizeof(tb->thrown) / sizeof(tb->thrown[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(tb->thrown); i++) {
if (tb->thrown[i]) {
blocknr = tb->thrown[i]->b_blocknr;
if (buffer_dirty(tb->thrown[i]))
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 5109f1d5e7f..abfada2f52d 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1556,7 +1556,7 @@ const struct file_operations reiserfs_file_operations = {
.splice_write = generic_file_splice_write,
};
-struct inode_operations reiserfs_file_inode_operations = {
+const struct inode_operations reiserfs_file_inode_operations = {
.truncate = reiserfs_vfs_truncate_file,
.setattr = reiserfs_setattr,
.setxattr = reiserfs_setxattr,
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 23f5cd5bbf5..a2161840bc7 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -1525,7 +1525,7 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
/*
* directories can handle most operations...
*/
-struct inode_operations reiserfs_dir_inode_operations = {
+const struct inode_operations reiserfs_dir_inode_operations = {
//&reiserfs_dir_operations, /* default_file_ops */
.create = reiserfs_create,
.lookup = reiserfs_lookup,
@@ -1548,7 +1548,7 @@ struct inode_operations reiserfs_dir_inode_operations = {
* symlink operations.. same as page_symlink_inode_operations, with xattr
* stuff added
*/
-struct inode_operations reiserfs_symlink_inode_operations = {
+const struct inode_operations reiserfs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
@@ -1564,7 +1564,7 @@ struct inode_operations reiserfs_symlink_inode_operations = {
/*
* special file operations.. just xattr/acl stuff
*/
-struct inode_operations reiserfs_special_inode_operations = {
+const struct inode_operations reiserfs_special_inode_operations = {
.setattr = reiserfs_setattr,
.setxattr = reiserfs_setxattr,
.getxattr = reiserfs_getxattr,
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 58ad4551a7c..f13a7f164dc 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -593,7 +593,7 @@ static ssize_t reiserfs_quota_read(struct super_block *, int, char *, size_t,
loff_t);
#endif
-static struct super_operations reiserfs_sops = {
+static const struct super_operations reiserfs_sops = {
.alloc_inode = reiserfs_alloc_inode,
.destroy_inode = reiserfs_destroy_inode,
.write_inode = reiserfs_write_inode,
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index d3e243a6f60..fd601014813 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -110,7 +110,7 @@ romfs_checksum(void *data, int size)
return sum;
}
-static struct super_operations romfs_ops;
+static const struct super_operations romfs_ops;
static int romfs_fill_super(struct super_block *s, void *data, int silent)
{
@@ -468,7 +468,7 @@ static const struct file_operations romfs_dir_operations = {
.readdir = romfs_readdir,
};
-static struct inode_operations romfs_dir_inode_operations = {
+static const struct inode_operations romfs_dir_inode_operations = {
.lookup = romfs_lookup,
};
@@ -598,7 +598,7 @@ static int romfs_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
-static struct super_operations romfs_ops = {
+static const struct super_operations romfs_ops = {
.alloc_inode = romfs_alloc_inode,
.destroy_inode = romfs_destroy_inode,
.read_inode = romfs_read_inode,
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index b1e58d1ac9c..50136b1a3ec 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -42,7 +42,7 @@ const struct file_operations smb_dir_operations =
.open = smb_dir_open,
};
-struct inode_operations smb_dir_inode_operations =
+const struct inode_operations smb_dir_inode_operations =
{
.create = smb_create,
.lookup = smb_lookup,
@@ -54,7 +54,7 @@ struct inode_operations smb_dir_inode_operations =
.setattr = smb_notify_change,
};
-struct inode_operations smb_dir_inode_operations_unix =
+const struct inode_operations smb_dir_inode_operations_unix =
{
.create = smb_create,
.lookup = smb_lookup,
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index e50533a7951..f161797160c 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -418,7 +418,7 @@ const struct file_operations smb_file_operations =
.sendfile = smb_file_sendfile,
};
-struct inode_operations smb_file_inode_operations =
+const struct inode_operations smb_file_inode_operations =
{
.permission = smb_file_permission,
.getattr = smb_getattr,
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 84dfe3f3482..5faba4f1c9a 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -98,7 +98,7 @@ static int smb_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
-static struct super_operations smb_sops =
+static const struct super_operations smb_sops =
{
.alloc_inode = smb_alloc_inode,
.destroy_inode = smb_destroy_inode,
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h
index 34fb462b237..03f456c1b7d 100644
--- a/fs/smbfs/proto.h
+++ b/fs/smbfs/proto.h
@@ -36,8 +36,8 @@ extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, stru
extern void smb_install_null_ops(struct smb_ops *ops);
/* dir.c */
extern const struct file_operations smb_dir_operations;
-extern struct inode_operations smb_dir_inode_operations;
-extern struct inode_operations smb_dir_inode_operations_unix;
+extern const struct inode_operations smb_dir_inode_operations;
+extern const struct inode_operations smb_dir_inode_operations_unix;
extern void smb_new_dentry(struct dentry *dentry);
extern void smb_renew_times(struct dentry *dentry);
/* cache.c */
@@ -65,7 +65,7 @@ extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
/* file.c */
extern const struct address_space_operations smb_file_aops;
extern const struct file_operations smb_file_operations;
-extern struct inode_operations smb_file_inode_operations;
+extern const struct inode_operations smb_file_inode_operations;
/* ioctl.c */
extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
/* smbiod.c */
@@ -84,4 +84,4 @@ extern int smb_request_send_server(struct smb_sb_info *server);
extern int smb_request_recv(struct smb_sb_info *server);
/* symlink.c */
extern int smb_symlink(struct inode *inode, struct dentry *dentry, const char *oldname);
-extern struct inode_operations smb_link_inode_operations;
+extern const struct inode_operations smb_link_inode_operations;
diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c
index a4bcae8a9af..42261dbdf60 100644
--- a/fs/smbfs/request.c
+++ b/fs/smbfs/request.c
@@ -61,7 +61,7 @@ static struct smb_request *smb_do_alloc_request(struct smb_sb_info *server,
struct smb_request *req;
unsigned char *buf = NULL;
- req = kmem_cache_alloc(req_cachep, GFP_KERNEL);
+ req = kmem_cache_zalloc(req_cachep, GFP_KERNEL);
VERBOSE("allocating request: %p\n", req);
if (!req)
goto out;
@@ -74,7 +74,6 @@ static struct smb_request *smb_do_alloc_request(struct smb_sb_info *server,
}
}
- memset(req, 0, sizeof(struct smb_request));
req->rq_buffer = buf;
req->rq_bufsize = bufsize;
req->rq_server = server;
diff --git a/fs/smbfs/symlink.c b/fs/smbfs/symlink.c
index cdc53c4fb38..e4bf3456d07 100644
--- a/fs/smbfs/symlink.c
+++ b/fs/smbfs/symlink.c
@@ -62,7 +62,7 @@ static void smb_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
__putname(s);
}
-struct inode_operations smb_link_inode_operations =
+const struct inode_operations smb_link_inode_operations =
{
.readlink = generic_readlink,
.follow_link = smb_follow_link,
diff --git a/fs/super.c b/fs/super.c
index 3e7458c2bb7..60b1e50cbf5 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -285,7 +285,7 @@ int fsync_super(struct super_block *sb)
*/
void generic_shutdown_super(struct super_block *sb)
{
- struct super_operations *sop = sb->s_op;
+ const struct super_operations *sop = sb->s_op;
if (sb->s_root) {
shrink_dcache_for_umount(sb);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 9dcdf556c99..8813990304f 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -37,11 +37,10 @@ static struct sysfs_dirent * __sysfs_new_dirent(void * element)
{
struct sysfs_dirent * sd;
- sd = kmem_cache_alloc(sysfs_dir_cachep, GFP_KERNEL);
+ sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
if (!sd)
return NULL;
- memset(sd, 0, sizeof(*sd));
atomic_set(&sd->s_count, 1);
atomic_set(&sd->s_event, 1);
INIT_LIST_HEAD(&sd->s_children);
@@ -297,7 +296,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
return ERR_PTR(err);
}
-struct inode_operations sysfs_dir_inode_operations = {
+const struct inode_operations sysfs_dir_inode_operations = {
.lookup = sysfs_lookup,
.setattr = sysfs_setattr,
};
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 542d2bcc73d..dd1344b007f 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -29,7 +29,7 @@ static struct backing_dev_info sysfs_backing_dev_info = {
.capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};
-static struct inode_operations sysfs_inode_operations ={
+static const struct inode_operations sysfs_inode_operations ={
.setattr = sysfs_setattr,
};
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index f6a87a82488..23a48a38e6a 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -21,7 +21,7 @@ struct kmem_cache *sysfs_dir_cachep;
static void sysfs_clear_inode(struct inode *inode);
-static struct super_operations sysfs_ops = {
+static const struct super_operations sysfs_ops = {
.statfs = simple_statfs,
.drop_inode = sysfs_delete_inode,
.clear_inode = sysfs_clear_inode,
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 4869f611192..7b9c5bfde92 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -181,7 +181,7 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *co
free_page((unsigned long)page);
}
-struct inode_operations sysfs_symlink_inode_operations = {
+const struct inode_operations sysfs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = sysfs_follow_link,
.put_link = sysfs_put_link,
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index fe1cbfd208e..d976b000554 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -26,8 +26,8 @@ extern struct super_block * sysfs_sb;
extern const struct file_operations sysfs_dir_operations;
extern const struct file_operations sysfs_file_operations;
extern const struct file_operations bin_fops;
-extern struct inode_operations sysfs_dir_inode_operations;
-extern struct inode_operations sysfs_symlink_inode_operations;
+extern const struct inode_operations sysfs_dir_inode_operations;
+extern const struct inode_operations sysfs_symlink_inode_operations;
struct sysfs_symlink {
char * link_name;
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index 47a4b728f15..0732ddb9020 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -30,7 +30,7 @@ const struct file_operations sysv_file_operations = {
.sendfile = generic_file_sendfile,
};
-struct inode_operations sysv_file_inode_operations = {
+const struct inode_operations sysv_file_inode_operations = {
.truncate = sysv_truncate,
.getattr = sysv_getattr,
};
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index ead9864567e..9311cac186f 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -142,7 +142,7 @@ static inline void write3byte(struct sysv_sb_info *sbi,
}
}
-static struct inode_operations sysv_symlink_inode_operations = {
+static const struct inode_operations sysv_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
@@ -327,7 +327,7 @@ static void init_once(void *p, struct kmem_cache *cachep, unsigned long flags)
inode_init_once(&si->vfs_inode);
}
-struct super_operations sysv_sops = {
+const struct super_operations sysv_sops = {
.alloc_inode = sysv_alloc_inode,
.destroy_inode = sysv_destroy_inode,
.read_inode = sysv_read_inode,
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
index f7c08db8e34..4e48abbd2b5 100644
--- a/fs/sysv/namei.c
+++ b/fs/sysv/namei.c
@@ -292,7 +292,7 @@ out:
/*
* directories can handle most operations...
*/
-struct inode_operations sysv_dir_inode_operations = {
+const struct inode_operations sysv_dir_inode_operations = {
.create = sysv_create,
.lookup = sysv_lookup,
.link = sysv_link,
diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c
index b85ce61d635..00d2f8a43e4 100644
--- a/fs/sysv/symlink.c
+++ b/fs/sysv/symlink.c
@@ -14,7 +14,7 @@ static void *sysv_follow_link(struct dentry *dentry, struct nameidata *nd)
return NULL;
}
-struct inode_operations sysv_fast_symlink_inode_operations = {
+const struct inode_operations sysv_fast_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = sysv_follow_link,
};
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index dcb18b2171f..5b4fedf17cc 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -159,13 +159,13 @@ extern struct sysv_dir_entry *sysv_dotdot(struct inode *, struct page **);
extern ino_t sysv_inode_by_name(struct dentry *);
-extern struct inode_operations sysv_file_inode_operations;
-extern struct inode_operations sysv_dir_inode_operations;
-extern struct inode_operations sysv_fast_symlink_inode_operations;
+extern const struct inode_operations sysv_file_inode_operations;
+extern const struct inode_operations sysv_dir_inode_operations;
+extern const struct inode_operations sysv_fast_symlink_inode_operations;
extern const struct file_operations sysv_file_operations;
extern const struct file_operations sysv_dir_operations;
extern const struct address_space_operations sysv_aops;
-extern struct super_operations sysv_sops;
+extern const struct super_operations sysv_sops;
extern struct dentry_operations sysv_dentry_operations;
diff --git a/fs/udf/file.c b/fs/udf/file.c
index d81f2db7b0e..40d5047defe 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -263,6 +263,6 @@ const struct file_operations udf_file_operations = {
.sendfile = generic_file_sendfile,
};
-struct inode_operations udf_file_inode_operations = {
+const struct inode_operations udf_file_inode_operations = {
.truncate = udf_truncate,
};
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 73163325e5e..fe361cd19a9 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -1308,7 +1308,7 @@ end_rename:
return retval;
}
-struct inode_operations udf_dir_inode_operations = {
+const struct inode_operations udf_dir_inode_operations = {
.lookup = udf_lookup,
.create = udf_create,
.link = udf_link,
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 1dbc2955f02..8672b88f7ff 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -160,7 +160,7 @@ static void destroy_inodecache(void)
}
/* Superblock operations */
-static struct super_operations udf_sb_ops = {
+static const struct super_operations udf_sb_ops = {
.alloc_inode = udf_alloc_inode,
.destroy_inode = udf_destroy_inode,
.write_inode = udf_write_inode,
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 1033b7cf293..ee1dece1f6f 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -42,9 +42,9 @@ struct task_struct;
struct buffer_head;
struct super_block;
-extern struct inode_operations udf_dir_inode_operations;
+extern const struct inode_operations udf_dir_inode_operations;
extern const struct file_operations udf_dir_operations;
-extern struct inode_operations udf_file_inode_operations;
+extern const struct inode_operations udf_file_inode_operations;
extern const struct file_operations udf_file_operations;
extern const struct address_space_operations udf_aops;
extern const struct address_space_operations udf_adinicb_aops;
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 638f4c585e8..0e97a4f79c3 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -4,6 +4,8 @@
* Copyright (C) 1998
* Daniel Pirkl <daniel.pirkl@email.cz>
* Charles University, Faculty of Mathematics and Physics
+ *
+ * UFS2 write support Evgeniy Dushistov <dushistov@mail.ru>, 2007
*/
#include <linux/fs.h>
@@ -21,38 +23,42 @@
#include "swab.h"
#include "util.h"
-static unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
-static unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
-static unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *);
-static unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned);
+#define INVBLOCK ((u64)-1L)
+
+static u64 ufs_add_fragments(struct inode *, u64, unsigned, unsigned, int *);
+static u64 ufs_alloc_fragments(struct inode *, unsigned, u64, unsigned, int *);
+static u64 ufs_alloccg_block(struct inode *, struct ufs_cg_private_info *, u64, int *);
+static u64 ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, u64, unsigned);
static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[];
static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);
/*
* Free 'count' fragments from fragment number 'fragment'
*/
-void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count)
+void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
{
struct super_block * sb;
struct ufs_sb_private_info * uspi;
struct ufs_super_block_first * usb1;
struct ufs_cg_private_info * ucpi;
struct ufs_cylinder_group * ucg;
- unsigned cgno, bit, end_bit, bbase, blkmap, i, blkno, cylno;
+ unsigned cgno, bit, end_bit, bbase, blkmap, i;
+ u64 blkno;
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
usb1 = ubh_get_usb_first(uspi);
- UFSD("ENTER, fragment %u, count %u\n", fragment, count);
+ UFSD("ENTER, fragment %llu, count %u\n",
+ (unsigned long long)fragment, count);
if (ufs_fragnum(fragment) + count > uspi->s_fpg)
ufs_error (sb, "ufs_free_fragments", "internal error");
lock_super(sb);
- cgno = ufs_dtog(fragment);
- bit = ufs_dtogd(fragment);
+ cgno = ufs_dtog(uspi, fragment);
+ bit = ufs_dtogd(uspi, fragment);
if (cgno >= uspi->s_ncg) {
ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device");
goto failed;
@@ -101,9 +107,13 @@ void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count)
fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
uspi->cs_total.cs_nbfree++;
fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
- cylno = ufs_cbtocylno (bbase);
- fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(bbase)), 1);
- fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+ if (uspi->fs_magic != UFS2_MAGIC) {
+ unsigned cylno = ufs_cbtocylno (bbase);
+
+ fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
+ ufs_cbtorpos(bbase)), 1);
+ fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+ }
}
ubh_mark_buffer_dirty (USPI_UBH(uspi));
@@ -127,24 +137,27 @@ failed:
/*
* Free 'count' fragments from fragment number 'fragment' (free whole blocks)
*/
-void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count)
+void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count)
{
struct super_block * sb;
struct ufs_sb_private_info * uspi;
struct ufs_super_block_first * usb1;
struct ufs_cg_private_info * ucpi;
struct ufs_cylinder_group * ucg;
- unsigned overflow, cgno, bit, end_bit, blkno, i, cylno;
+ unsigned overflow, cgno, bit, end_bit, i;
+ u64 blkno;
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
usb1 = ubh_get_usb_first(uspi);
- UFSD("ENTER, fragment %u, count %u\n", fragment, count);
+ UFSD("ENTER, fragment %llu, count %u\n",
+ (unsigned long long)fragment, count);
if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) {
ufs_error (sb, "ufs_free_blocks", "internal error, "
- "fragment %u, count %u\n", fragment, count);
+ "fragment %llu, count %u\n",
+ (unsigned long long)fragment, count);
goto failed;
}
@@ -152,8 +165,8 @@ void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count)
do_more:
overflow = 0;
- cgno = ufs_dtog (fragment);
- bit = ufs_dtogd (fragment);
+ cgno = ufs_dtog(uspi, fragment);
+ bit = ufs_dtogd(uspi, fragment);
if (cgno >= uspi->s_ncg) {
ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device");
goto failed_unlock;
@@ -187,9 +200,14 @@ do_more:
fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
uspi->cs_total.cs_nbfree++;
fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
- cylno = ufs_cbtocylno(i);
- fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(i)), 1);
- fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+
+ if (uspi->fs_magic != UFS2_MAGIC) {
+ unsigned cylno = ufs_cbtocylno(i);
+
+ fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
+ ufs_cbtorpos(i)), 1);
+ fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+ }
}
ubh_mark_buffer_dirty (USPI_UBH(uspi));
@@ -308,15 +326,19 @@ static void ufs_clear_frags(struct inode *inode, sector_t beg, unsigned int n,
}
}
-unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
- unsigned goal, unsigned count, int * err, struct page *locked_page)
+u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
+ u64 goal, unsigned count, int *err,
+ struct page *locked_page)
{
struct super_block * sb;
struct ufs_sb_private_info * uspi;
struct ufs_super_block_first * usb1;
- unsigned cgno, oldcount, newcount, tmp, request, result;
+ unsigned cgno, oldcount, newcount;
+ u64 tmp, request, result;
- UFSD("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count);
+ UFSD("ENTER, ino %lu, fragment %llu, goal %llu, count %u\n",
+ inode->i_ino, (unsigned long long)fragment,
+ (unsigned long long)goal, count);
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
@@ -324,11 +346,12 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
*err = -ENOSPC;
lock_super (sb);
-
- tmp = fs32_to_cpu(sb, *p);
+ tmp = ufs_data_ptr_to_cpu(sb, p);
+
if (count + ufs_fragnum(fragment) > uspi->s_fpb) {
- ufs_warning (sb, "ufs_new_fragments", "internal warning"
- " fragment %u, count %u", fragment, count);
+ ufs_warning(sb, "ufs_new_fragments", "internal warning"
+ " fragment %llu, count %u",
+ (unsigned long long)fragment, count);
count = uspi->s_fpb - ufs_fragnum(fragment);
}
oldcount = ufs_fragnum (fragment);
@@ -339,10 +362,12 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
*/
if (oldcount) {
if (!tmp) {
- ufs_error (sb, "ufs_new_fragments", "internal error, "
- "fragment %u, tmp %u\n", fragment, tmp);
- unlock_super (sb);
- return (unsigned)-1;
+ ufs_error(sb, "ufs_new_fragments", "internal error, "
+ "fragment %llu, tmp %llu\n",
+ (unsigned long long)fragment,
+ (unsigned long long)tmp);
+ unlock_super(sb);
+ return INVBLOCK;
}
if (fragment < UFS_I(inode)->i_lastfrag) {
UFSD("EXIT (ALREADY ALLOCATED)\n");
@@ -372,7 +397,7 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
if (goal == 0)
cgno = ufs_inotocg (inode->i_ino);
else
- cgno = ufs_dtog (goal);
+ cgno = ufs_dtog(uspi, goal);
/*
* allocate new fragment
@@ -380,14 +405,16 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
if (oldcount == 0) {
result = ufs_alloc_fragments (inode, cgno, goal, count, err);
if (result) {
- *p = cpu_to_fs32(sb, result);
+ ufs_cpu_to_data_ptr(sb, p, result);
*err = 0;
- UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
- ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
- locked_page != NULL);
+ UFS_I(inode)->i_lastfrag =
+ max_t(u32, UFS_I(inode)->i_lastfrag,
+ fragment + count);
+ ufs_clear_frags(inode, result + oldcount,
+ newcount - oldcount, locked_page != NULL);
}
unlock_super(sb);
- UFSD("EXIT, result %u\n", result);
+ UFSD("EXIT, result %llu\n", (unsigned long long)result);
return result;
}
@@ -401,7 +428,7 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
locked_page != NULL);
unlock_super(sb);
- UFSD("EXIT, result %u\n", result);
+ UFSD("EXIT, result %llu\n", (unsigned long long)result);
return result;
}
@@ -433,15 +460,14 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
locked_page != NULL);
ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp,
result, locked_page);
-
- *p = cpu_to_fs32(sb, result);
+ ufs_cpu_to_data_ptr(sb, p, result);
*err = 0;
UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
unlock_super(sb);
if (newcount < request)
ufs_free_fragments (inode, result + newcount, request - newcount);
ufs_free_fragments (inode, tmp, oldcount);
- UFSD("EXIT, result %u\n", result);
+ UFSD("EXIT, result %llu\n", (unsigned long long)result);
return result;
}
@@ -450,9 +476,8 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
return 0;
}
-static unsigned
-ufs_add_fragments (struct inode * inode, unsigned fragment,
- unsigned oldcount, unsigned newcount, int * err)
+static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
+ unsigned oldcount, unsigned newcount, int *err)
{
struct super_block * sb;
struct ufs_sb_private_info * uspi;
@@ -461,14 +486,15 @@ ufs_add_fragments (struct inode * inode, unsigned fragment,
struct ufs_cylinder_group * ucg;
unsigned cgno, fragno, fragoff, count, fragsize, i;
- UFSD("ENTER, fragment %u, oldcount %u, newcount %u\n", fragment, oldcount, newcount);
+ UFSD("ENTER, fragment %llu, oldcount %u, newcount %u\n",
+ (unsigned long long)fragment, oldcount, newcount);
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
usb1 = ubh_get_usb_first (uspi);
count = newcount - oldcount;
- cgno = ufs_dtog(fragment);
+ cgno = ufs_dtog(uspi, fragment);
if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count)
return 0;
if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb)
@@ -483,7 +509,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment,
return 0;
}
- fragno = ufs_dtogd (fragment);
+ fragno = ufs_dtogd(uspi, fragment);
fragoff = ufs_fragnum (fragno);
for (i = oldcount; i < newcount; i++)
if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
@@ -521,7 +547,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment,
}
sb->s_dirt = 1;
- UFSD("EXIT, fragment %u\n", fragment);
+ UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment);
return fragment;
}
@@ -534,17 +560,19 @@ ufs_add_fragments (struct inode * inode, unsigned fragment,
if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \
goto cg_found;
-static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
- unsigned goal, unsigned count, int * err)
+static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno,
+ u64 goal, unsigned count, int *err)
{
struct super_block * sb;
struct ufs_sb_private_info * uspi;
struct ufs_super_block_first * usb1;
struct ufs_cg_private_info * ucpi;
struct ufs_cylinder_group * ucg;
- unsigned oldcg, i, j, k, result, allocsize;
+ unsigned oldcg, i, j, k, allocsize;
+ u64 result;
- UFSD("ENTER, ino %lu, cgno %u, goal %u, count %u\n", inode->i_ino, cgno, goal, count);
+ UFSD("ENTER, ino %lu, cgno %u, goal %llu, count %u\n",
+ inode->i_ino, cgno, (unsigned long long)goal, count);
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
@@ -593,7 +621,7 @@ cg_found:
if (count == uspi->s_fpb) {
result = ufs_alloccg_block (inode, ucpi, goal, err);
- if (result == (unsigned)-1)
+ if (result == INVBLOCK)
return 0;
goto succed;
}
@@ -604,9 +632,9 @@ cg_found:
if (allocsize == uspi->s_fpb) {
result = ufs_alloccg_block (inode, ucpi, goal, err);
- if (result == (unsigned)-1)
+ if (result == INVBLOCK)
return 0;
- goal = ufs_dtogd (result);
+ goal = ufs_dtogd(uspi, result);
for (i = count; i < uspi->s_fpb; i++)
ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
i = uspi->s_fpb - count;
@@ -620,7 +648,7 @@ cg_found:
}
result = ufs_bitmap_search (sb, ucpi, goal, allocsize);
- if (result == (unsigned)-1)
+ if (result == INVBLOCK)
return 0;
if(DQUOT_ALLOC_BLOCK(inode, count)) {
*err = -EDQUOT;
@@ -647,20 +675,21 @@ succed:
sb->s_dirt = 1;
result += cgno * uspi->s_fpg;
- UFSD("EXIT3, result %u\n", result);
+ UFSD("EXIT3, result %llu\n", (unsigned long long)result);
return result;
}
-static unsigned ufs_alloccg_block (struct inode * inode,
- struct ufs_cg_private_info * ucpi, unsigned goal, int * err)
+static u64 ufs_alloccg_block(struct inode *inode,
+ struct ufs_cg_private_info *ucpi,
+ u64 goal, int *err)
{
struct super_block * sb;
struct ufs_sb_private_info * uspi;
struct ufs_super_block_first * usb1;
struct ufs_cylinder_group * ucg;
- unsigned result, cylno, blkno;
+ u64 result, blkno;
- UFSD("ENTER, goal %u\n", goal);
+ UFSD("ENTER, goal %llu\n", (unsigned long long)goal);
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
@@ -672,7 +701,7 @@ static unsigned ufs_alloccg_block (struct inode * inode,
goto norot;
}
goal = ufs_blknum (goal);
- goal = ufs_dtogd (goal);
+ goal = ufs_dtogd(uspi, goal);
/*
* If the requested block is available, use it.
@@ -684,8 +713,8 @@ static unsigned ufs_alloccg_block (struct inode * inode,
norot:
result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb);
- if (result == (unsigned)-1)
- return (unsigned)-1;
+ if (result == INVBLOCK)
+ return INVBLOCK;
ucpi->c_rotor = result;
gotit:
blkno = ufs_fragstoblks(result);
@@ -694,17 +723,22 @@ gotit:
ufs_clusteracct (sb, ucpi, blkno, -1);
if(DQUOT_ALLOC_BLOCK(inode, uspi->s_fpb)) {
*err = -EDQUOT;
- return (unsigned)-1;
+ return INVBLOCK;
}
fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1);
uspi->cs_total.cs_nbfree--;
fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1);
- cylno = ufs_cbtocylno(result);
- fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(result)), 1);
- fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+
+ if (uspi->fs_magic != UFS2_MAGIC) {
+ unsigned cylno = ufs_cbtocylno((unsigned)result);
+
+ fs16_sub(sb, &ubh_cg_blks(ucpi, cylno,
+ ufs_cbtorpos((unsigned)result)), 1);
+ fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+ }
- UFSD("EXIT, result %u\n", result);
+ UFSD("EXIT, result %llu\n", (unsigned long long)result);
return result;
}
@@ -744,9 +778,9 @@ static unsigned ubh_scanc(struct ufs_sb_private_info *uspi,
* @goal: near which block we want find new one
* @count: specified size
*/
-static unsigned ufs_bitmap_search(struct super_block *sb,
- struct ufs_cg_private_info *ucpi,
- unsigned goal, unsigned count)
+static u64 ufs_bitmap_search(struct super_block *sb,
+ struct ufs_cg_private_info *ucpi,
+ u64 goal, unsigned count)
{
/*
* Bit patterns for identifying fragments in the block map
@@ -761,16 +795,18 @@ static unsigned ufs_bitmap_search(struct super_block *sb,
struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
struct ufs_super_block_first *usb1;
struct ufs_cylinder_group *ucg;
- unsigned start, length, loc, result;
+ unsigned start, length, loc;
unsigned pos, want, blockmap, mask, end;
+ u64 result;
- UFSD("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count);
+ UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx,
+ (unsigned long long)goal, count);
usb1 = ubh_get_usb_first (uspi);
ucg = ubh_get_ucg(UCPI_UBH(ucpi));
if (goal)
- start = ufs_dtogd(goal) >> 3;
+ start = ufs_dtogd(uspi, goal) >> 3;
else
start = ucpi->c_frotor >> 3;
@@ -790,7 +826,7 @@ static unsigned ufs_bitmap_search(struct super_block *sb,
" length %u, count %u, freeoff %u\n",
ucpi->c_cgx, start, length, count,
ucpi->c_freeoff);
- return (unsigned)-1;
+ return INVBLOCK;
}
start = 0;
}
@@ -808,7 +844,8 @@ static unsigned ufs_bitmap_search(struct super_block *sb,
want = want_arr[count];
for (pos = 0; pos <= uspi->s_fpb - count; pos++) {
if ((blockmap & mask) == want) {
- UFSD("EXIT, result %u\n", result);
+ UFSD("EXIT, result %llu\n",
+ (unsigned long long)result);
return result + pos;
}
mask <<= 1;
@@ -819,7 +856,7 @@ static unsigned ufs_bitmap_search(struct super_block *sb,
ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n",
ucpi->c_cgx);
UFSD("EXIT (FAILED)\n");
- return (unsigned)-1;
+ return INVBLOCK;
}
static void ufs_clusteracct(struct super_block * sb,
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 433b6f68403..a6c0ca9f48b 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -106,12 +106,13 @@ static void ufs_check_page(struct page *page)
char *kaddr = page_address(page);
unsigned offs, rec_len;
unsigned limit = PAGE_CACHE_SIZE;
+ const unsigned chunk_mask = UFS_SB(sb)->s_uspi->s_dirblksize - 1;
struct ufs_dir_entry *p;
char *error;
if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) {
limit = dir->i_size & ~PAGE_CACHE_MASK;
- if (limit & (UFS_SECTOR_SIZE - 1))
+ if (limit & chunk_mask)
goto Ebadsize;
if (!limit)
goto out;
@@ -126,7 +127,7 @@ static void ufs_check_page(struct page *page)
goto Ealign;
if (rec_len < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, p)))
goto Enamelen;
- if (((offs + rec_len - 1) ^ offs) & ~(UFS_SECTOR_SIZE-1))
+ if (((offs + rec_len - 1) ^ offs) & ~chunk_mask)
goto Espan;
if (fs32_to_cpu(sb, p->d_ino) > (UFS_SB(sb)->s_uspi->s_ipg *
UFS_SB(sb)->s_uspi->s_ncg))
@@ -310,6 +311,7 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode)
int namelen = dentry->d_name.len;
struct super_block *sb = dir->i_sb;
unsigned reclen = UFS_DIR_REC_LEN(namelen);
+ const unsigned int chunk_size = UFS_SB(sb)->s_uspi->s_dirblksize;
unsigned short rec_len, name_len;
struct page *page = NULL;
struct ufs_dir_entry *de;
@@ -342,8 +344,8 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode)
if ((char *)de == dir_end) {
/* We hit i_size */
name_len = 0;
- rec_len = UFS_SECTOR_SIZE;
- de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE);
+ rec_len = chunk_size;
+ de->d_reclen = cpu_to_fs16(sb, chunk_size);
de->d_ino = 0;
goto got_it;
}
@@ -431,7 +433,7 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
unsigned int offset = pos & ~PAGE_CACHE_MASK;
unsigned long n = pos >> PAGE_CACHE_SHIFT;
unsigned long npages = ufs_dir_pages(inode);
- unsigned chunk_mask = ~(UFS_SECTOR_SIZE - 1);
+ unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1);
int need_revalidate = filp->f_version != inode->i_version;
unsigned flags = UFS_SB(sb)->s_flags;
@@ -511,7 +513,7 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir,
struct super_block *sb = inode->i_sb;
struct address_space *mapping = page->mapping;
char *kaddr = page_address(page);
- unsigned from = ((char*)dir - kaddr) & ~(UFS_SECTOR_SIZE - 1);
+ unsigned from = ((char*)dir - kaddr) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1);
unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen);
struct ufs_dir_entry *pde = NULL;
struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from);
@@ -556,6 +558,7 @@ int ufs_make_empty(struct inode * inode, struct inode *dir)
struct super_block * sb = dir->i_sb;
struct address_space *mapping = inode->i_mapping;
struct page *page = grab_cache_page(mapping, 0);
+ const unsigned int chunk_size = UFS_SB(sb)->s_uspi->s_dirblksize;
struct ufs_dir_entry * de;
char *base;
int err;
@@ -563,7 +566,7 @@ int ufs_make_empty(struct inode * inode, struct inode *dir)
if (!page)
return -ENOMEM;
kmap(page);
- err = mapping->a_ops->prepare_write(NULL, page, 0, UFS_SECTOR_SIZE);
+ err = mapping->a_ops->prepare_write(NULL, page, 0, chunk_size);
if (err) {
unlock_page(page);
goto fail;
@@ -584,11 +587,11 @@ int ufs_make_empty(struct inode * inode, struct inode *dir)
((char *)de + fs16_to_cpu(sb, de->d_reclen));
de->d_ino = cpu_to_fs32(sb, dir->i_ino);
ufs_set_de_type(sb, de, dir->i_mode);
- de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1));
+ de->d_reclen = cpu_to_fs16(sb, chunk_size - UFS_DIR_REC_LEN(1));
ufs_set_de_namlen(sb, de, 2);
strcpy (de->d_name, "..");
- err = ufs_commit_chunk(page, 0, UFS_SECTOR_SIZE);
+ err = ufs_commit_chunk(page, 0, chunk_size);
fail:
kunmap(page);
page_cache_release(page);
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index 2ad1259c6ec..b868878009b 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -18,6 +18,9 @@
* Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
* Big-endian to little-endian byte-swapping/bitmaps by
* David S. Miller (davem@caip.rutgers.edu), 1995
+ *
+ * UFS2 write support added by
+ * Evgeniy Dushistov <dushistov@mail.ru>, 2007
*/
#include <linux/fs.h>
@@ -126,6 +129,47 @@ void ufs_free_inode (struct inode * inode)
}
/*
+ * Nullify new chunk of inodes,
+ * BSD people also set ui_gen field of inode
+ * during nullification, but we not care about
+ * that because of linux ufs do not support NFS
+ */
+static void ufs2_init_inodes_chunk(struct super_block *sb,
+ struct ufs_cg_private_info *ucpi,
+ struct ufs_cylinder_group *ucg)
+{
+ struct buffer_head *bh;
+ struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
+ sector_t beg = uspi->s_sbbase +
+ ufs_inotofsba(ucpi->c_cgx * uspi->s_ipg +
+ fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk));
+ sector_t end = beg + uspi->s_fpb;
+
+ UFSD("ENTER cgno %d\n", ucpi->c_cgx);
+
+ for (; beg < end; ++beg) {
+ bh = sb_getblk(sb, beg);
+ lock_buffer(bh);
+ memset(bh->b_data, 0, sb->s_blocksize);
+ set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
+ unlock_buffer(bh);
+ if (sb->s_flags & MS_SYNCHRONOUS)
+ sync_dirty_buffer(bh);
+ brelse(bh);
+ }
+
+ fs32_add(sb, &ucg->cg_u.cg_u2.cg_initediblk, uspi->s_inopb);
+ ubh_mark_buffer_dirty(UCPI_UBH(ucpi));
+ if (sb->s_flags & MS_SYNCHRONOUS) {
+ ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
+ ubh_wait_on_buffer(UCPI_UBH(ucpi));
+ }
+
+ UFSD("EXIT\n");
+}
+
+/*
* There are two policies for allocating an inode. If the new inode is
* a directory, then a forward search is made for a block group with both
* free space and a low directory-to-inode ratio; if that fails, then of
@@ -146,6 +190,7 @@ struct inode * ufs_new_inode(struct inode * dir, int mode)
struct inode * inode;
unsigned cg, bit, i, j, start;
struct ufs_inode_info *ufsi;
+ int err = -ENOSPC;
UFSD("ENTER\n");
@@ -198,13 +243,15 @@ struct inode * ufs_new_inode(struct inode * dir, int mode)
goto cg_found;
}
}
-
+
goto failed;
cg_found:
ucpi = ufs_load_cylinder (sb, cg);
- if (!ucpi)
+ if (!ucpi) {
+ err = -EIO;
goto failed;
+ }
ucg = ubh_get_ucg(UCPI_UBH(ucpi));
if (!ufs_cg_chkmagic(sb, ucg))
ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number");
@@ -216,6 +263,7 @@ cg_found:
if (!(bit < start)) {
ufs_error (sb, "ufs_new_inode",
"cylinder group %u corrupted - error in inode bitmap\n", cg);
+ err = -EIO;
goto failed;
}
}
@@ -224,9 +272,18 @@ cg_found:
ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit);
else {
ufs_panic (sb, "ufs_new_inode", "internal error");
+ err = -EIO;
goto failed;
}
-
+
+ if (uspi->fs_magic == UFS2_MAGIC) {
+ u32 initediblk = fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk);
+
+ if (bit + uspi->s_inopb > initediblk &&
+ initediblk < fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_niblk))
+ ufs2_init_inodes_chunk(sb, ucpi, ucg);
+ }
+
fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1);
uspi->cs_total.cs_nifree--;
fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1);
@@ -236,7 +293,6 @@ cg_found:
uspi->cs_total.cs_ndir++;
fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1);
}
-
ubh_mark_buffer_dirty (USPI_UBH(uspi));
ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
if (sb->s_flags & MS_SYNCHRONOUS) {
@@ -245,6 +301,7 @@ cg_found:
}
sb->s_dirt = 1;
+ inode->i_ino = cg * uspi->s_ipg + bit;
inode->i_mode = mode;
inode->i_uid = current->fsuid;
if (dir->i_mode & S_ISGID) {
@@ -254,39 +311,72 @@ cg_found:
} else
inode->i_gid = current->fsgid;
- inode->i_ino = cg * uspi->s_ipg + bit;
inode->i_blocks = 0;
+ inode->i_generation = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
ufsi->i_flags = UFS_I(dir)->i_flags;
ufsi->i_lastfrag = 0;
- ufsi->i_gen = 0;
ufsi->i_shadow = 0;
ufsi->i_osync = 0;
ufsi->i_oeftflag = 0;
ufsi->i_dir_start_lookup = 0;
memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1));
-
insert_inode_hash(inode);
mark_inode_dirty(inode);
+ if (uspi->fs_magic == UFS2_MAGIC) {
+ struct buffer_head *bh;
+ struct ufs2_inode *ufs2_inode;
+
+ /*
+ * setup birth date, we do it here because of there is no sense
+ * to hold it in struct ufs_inode_info, and lose 64 bit
+ */
+ bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino));
+ if (!bh) {
+ ufs_warning(sb, "ufs_read_inode",
+ "unable to read inode %lu\n",
+ inode->i_ino);
+ err = -EIO;
+ goto fail_remove_inode;
+ }
+ lock_buffer(bh);
+ ufs2_inode = (struct ufs2_inode *)bh->b_data;
+ ufs2_inode += ufs_inotofsbo(inode->i_ino);
+ ufs2_inode->ui_birthtime.tv_sec =
+ cpu_to_fs32(sb, CURRENT_TIME_SEC.tv_sec);
+ ufs2_inode->ui_birthtime.tv_usec = 0;
+ mark_buffer_dirty(bh);
+ unlock_buffer(bh);
+ if (sb->s_flags & MS_SYNCHRONOUS)
+ sync_dirty_buffer(bh);
+ brelse(bh);
+ }
+
unlock_super (sb);
if (DQUOT_ALLOC_INODE(inode)) {
DQUOT_DROP(inode);
- inode->i_flags |= S_NOQUOTA;
- inode->i_nlink = 0;
- iput(inode);
- return ERR_PTR(-EDQUOT);
+ err = -EDQUOT;
+ goto fail_without_unlock;
}
UFSD("allocating inode %lu\n", inode->i_ino);
UFSD("EXIT\n");
return inode;
+fail_remove_inode:
+ unlock_super(sb);
+fail_without_unlock:
+ inode->i_flags |= S_NOQUOTA;
+ inode->i_nlink = 0;
+ iput(inode);
+ UFSD("EXIT (FAILED): err %d\n", err);
+ return ERR_PTR(err);
failed:
unlock_super (sb);
make_bad_inode(inode);
iput (inode);
- UFSD("EXIT (FAILED)\n");
- return ERR_PTR(-ENOSPC);
+ UFSD("EXIT (FAILED): err %d\n", err);
+ return ERR_PTR(err);
}
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 4295ca91cf8..fb34ad03e22 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -170,7 +170,7 @@ out:
* @locked_page - for ufs_new_fragments()
*/
static struct buffer_head *
-ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
+ufs_inode_getfrag(struct inode *inode, u64 fragment,
sector_t new_fragment, unsigned int required, int *err,
long *phys, int *new, struct page *locked_page)
{
@@ -178,12 +178,12 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
struct super_block *sb = inode->i_sb;
struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
struct buffer_head * result;
- unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
- unsigned tmp, goal;
- __fs32 * p, * p2;
+ unsigned blockoff, lastblockoff;
+ u64 tmp, goal, lastfrag, block, lastblock;
+ void *p, *p2;
- UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, required %u, "
- "metadata %d\n", inode->i_ino, fragment,
+ UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, required %u, "
+ "metadata %d\n", inode->i_ino, (unsigned long long)fragment,
(unsigned long long)new_fragment, required, !phys);
/* TODO : to be done for write support
@@ -193,17 +193,20 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
block = ufs_fragstoblks (fragment);
blockoff = ufs_fragnum (fragment);
- p = ufsi->i_u1.i_data + block;
+ p = ufs_get_direct_data_ptr(uspi, ufsi, block);
+
goal = 0;
repeat:
- tmp = fs32_to_cpu(sb, *p);
+ tmp = ufs_data_ptr_to_cpu(sb, p);
+
lastfrag = ufsi->i_lastfrag;
if (tmp && fragment < lastfrag) {
if (!phys) {
result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
- if (tmp == fs32_to_cpu(sb, *p)) {
- UFSD("EXIT, result %u\n", tmp + blockoff);
+ if (tmp == ufs_data_ptr_to_cpu(sb, p)) {
+ UFSD("EXIT, result %llu\n",
+ (unsigned long long)tmp + blockoff);
return result;
}
brelse (result);
@@ -224,10 +227,11 @@ repeat:
* We must reallocate last allocated block
*/
if (lastblockoff) {
- p2 = ufsi->i_u1.i_data + lastblock;
- tmp = ufs_new_fragments (inode, p2, lastfrag,
- fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff,
- err, locked_page);
+ p2 = ufs_get_direct_data_ptr(uspi, ufsi, lastblock);
+ tmp = ufs_new_fragments(inode, p2, lastfrag,
+ ufs_data_ptr_to_cpu(sb, p2),
+ uspi->s_fpb - lastblockoff,
+ err, locked_page);
if (!tmp) {
if (lastfrag != ufsi->i_lastfrag)
goto repeat;
@@ -237,27 +241,31 @@ repeat:
lastfrag = ufsi->i_lastfrag;
}
- tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]);
+ tmp = ufs_data_ptr_to_cpu(sb,
+ ufs_get_direct_data_ptr(uspi, ufsi,
+ lastblock));
if (tmp)
goal = tmp + uspi->s_fpb;
tmp = ufs_new_fragments (inode, p, fragment - blockoff,
goal, required + blockoff,
err,
phys != NULL ? locked_page : NULL);
- }
+ } else if (lastblock == block) {
/*
* We will extend last allocated block
*/
- else if (lastblock == block) {
- tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff),
- fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff),
+ tmp = ufs_new_fragments(inode, p, fragment -
+ (blockoff - lastblockoff),
+ ufs_data_ptr_to_cpu(sb, p),
+ required + (blockoff - lastblockoff),
err, phys != NULL ? locked_page : NULL);
} else /* (lastblock > block) */ {
/*
* We will allocate new block before last allocated block
*/
if (block) {
- tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[block-1]);
+ tmp = ufs_data_ptr_to_cpu(sb,
+ ufs_get_direct_data_ptr(uspi, ufsi, block - 1));
if (tmp)
goal = tmp + uspi->s_fpb;
}
@@ -266,7 +274,7 @@ repeat:
phys != NULL ? locked_page : NULL);
}
if (!tmp) {
- if ((!blockoff && *p) ||
+ if ((!blockoff && ufs_data_ptr_to_cpu(sb, p)) ||
(blockoff && lastfrag != ufsi->i_lastfrag))
goto repeat;
*err = -ENOSPC;
@@ -286,7 +294,7 @@ repeat:
if (IS_SYNC(inode))
ufs_sync_inode (inode);
mark_inode_dirty(inode);
- UFSD("EXIT, result %u\n", tmp + blockoff);
+ UFSD("EXIT, result %llu\n", (unsigned long long)tmp + blockoff);
return result;
/* This part : To be implemented ....
@@ -320,20 +328,22 @@ repeat2:
*/
static struct buffer_head *
ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
- unsigned int fragment, sector_t new_fragment, int *err,
+ u64 fragment, sector_t new_fragment, int *err,
long *phys, int *new, struct page *locked_page)
{
struct super_block *sb = inode->i_sb;
struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
struct buffer_head * result;
- unsigned tmp, goal, block, blockoff;
- __fs32 * p;
+ unsigned blockoff;
+ u64 tmp, goal, block;
+ void *p;
block = ufs_fragstoblks (fragment);
blockoff = ufs_fragnum (fragment);
- UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, metadata %d\n",
- inode->i_ino, fragment, (unsigned long long)new_fragment, !phys);
+ UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, metadata %d\n",
+ inode->i_ino, (unsigned long long)fragment,
+ (unsigned long long)new_fragment, !phys);
result = NULL;
if (!bh)
@@ -344,14 +354,16 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
if (!buffer_uptodate(bh))
goto out;
}
-
- p = (__fs32 *) bh->b_data + block;
+ if (uspi->fs_magic == UFS2_MAGIC)
+ p = (__fs64 *)bh->b_data + block;
+ else
+ p = (__fs32 *)bh->b_data + block;
repeat:
- tmp = fs32_to_cpu(sb, *p);
+ tmp = ufs_data_ptr_to_cpu(sb, p);
if (tmp) {
if (!phys) {
result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
- if (tmp == fs32_to_cpu(sb, *p))
+ if (tmp == ufs_data_ptr_to_cpu(sb, p))
goto out;
brelse (result);
goto repeat;
@@ -361,14 +373,16 @@ repeat:
}
}
- if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1])))
+ if (block && (uspi->fs_magic == UFS2_MAGIC ?
+ (tmp = fs64_to_cpu(sb, ((__fs64 *)bh->b_data)[block-1])) :
+ (tmp = fs32_to_cpu(sb, ((__fs32 *)bh->b_data)[block-1]))))
goal = tmp + uspi->s_fpb;
else
goal = bh->b_blocknr + uspi->s_fpb;
tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal,
uspi->s_fpb, err, locked_page);
if (!tmp) {
- if (fs32_to_cpu(sb, *p))
+ if (ufs_data_ptr_to_cpu(sb, p))
goto repeat;
goto out;
}
@@ -386,7 +400,7 @@ repeat:
sync_dirty_buffer(bh);
inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
- UFSD("result %u\n", tmp + blockoff);
+ UFSD("result %llu\n", (unsigned long long)tmp + blockoff);
out:
brelse (bh);
UFSD("EXIT\n");
@@ -616,8 +630,8 @@ static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
inode->i_atime.tv_nsec = 0;
inode->i_ctime.tv_nsec = 0;
inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks);
+ inode->i_generation = fs32_to_cpu(sb, ufs_inode->ui_gen);
ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags);
- ufsi->i_gen = fs32_to_cpu(sb, ufs_inode->ui_gen);
ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
@@ -661,8 +675,8 @@ static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode)
inode->i_atime.tv_nsec = 0;
inode->i_ctime.tv_nsec = 0;
inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks);
+ inode->i_generation = fs32_to_cpu(sb, ufs2_inode->ui_gen);
ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags);
- ufsi->i_gen = fs32_to_cpu(sb, ufs2_inode->ui_gen);
/*
ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
@@ -731,34 +745,11 @@ bad_inode:
make_bad_inode(inode);
}
-static int ufs_update_inode(struct inode * inode, int do_sync)
+static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode)
{
- struct ufs_inode_info *ufsi = UFS_I(inode);
- struct super_block * sb;
- struct ufs_sb_private_info * uspi;
- struct buffer_head * bh;
- struct ufs_inode * ufs_inode;
- unsigned i;
- unsigned flags;
-
- UFSD("ENTER, ino %lu\n", inode->i_ino);
-
- sb = inode->i_sb;
- uspi = UFS_SB(sb)->s_uspi;
- flags = UFS_SB(sb)->s_flags;
-
- if (inode->i_ino < UFS_ROOTINO ||
- inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
- ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino);
- return -1;
- }
-
- bh = sb_bread(sb, ufs_inotofsba(inode->i_ino));
- if (!bh) {
- ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
- return -1;
- }
- ufs_inode = (struct ufs_inode *) (bh->b_data + ufs_inotofsbo(inode->i_ino) * sizeof(struct ufs_inode));
+ struct super_block *sb = inode->i_sb;
+ struct ufs_inode_info *ufsi = UFS_I(inode);
+ unsigned i;
ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);
@@ -775,9 +766,9 @@ static int ufs_update_inode(struct inode * inode, int do_sync)
ufs_inode->ui_mtime.tv_usec = 0;
ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks);
ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags);
- ufs_inode->ui_gen = cpu_to_fs32(sb, ufsi->i_gen);
+ ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation);
- if ((flags & UFS_UID_MASK) == UFS_UID_EFT) {
+ if ((UFS_SB(sb)->s_flags & UFS_UID_MASK) == UFS_UID_EFT) {
ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, ufsi->i_shadow);
ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag);
}
@@ -796,6 +787,78 @@ static int ufs_update_inode(struct inode * inode, int do_sync)
if (!inode->i_nlink)
memset (ufs_inode, 0, sizeof(struct ufs_inode));
+}
+
+static void ufs2_update_inode(struct inode *inode, struct ufs2_inode *ufs_inode)
+{
+ struct super_block *sb = inode->i_sb;
+ struct ufs_inode_info *ufsi = UFS_I(inode);
+ unsigned i;
+
+ UFSD("ENTER\n");
+ ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
+ ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);
+
+ ufs_inode->ui_uid = cpu_to_fs32(sb, inode->i_uid);
+ ufs_inode->ui_gid = cpu_to_fs32(sb, inode->i_gid);
+
+ ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size);
+ ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec);
+ ufs_inode->ui_atime.tv_usec = 0;
+ ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime.tv_sec);
+ ufs_inode->ui_ctime.tv_usec = 0;
+ ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime.tv_sec);
+ ufs_inode->ui_mtime.tv_usec = 0;
+
+ ufs_inode->ui_blocks = cpu_to_fs64(sb, inode->i_blocks);
+ ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags);
+ ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation);
+
+ if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
+ /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */
+ ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.u2_i_data[0];
+ } else if (inode->i_blocks) {
+ for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
+ ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.u2_i_data[i];
+ } else {
+ for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++)
+ ufs_inode->ui_u2.ui_symlink[i] = ufsi->i_u1.i_symlink[i];
+ }
+
+ if (!inode->i_nlink)
+ memset (ufs_inode, 0, sizeof(struct ufs2_inode));
+ UFSD("EXIT\n");
+}
+
+static int ufs_update_inode(struct inode * inode, int do_sync)
+{
+ struct super_block *sb = inode->i_sb;
+ struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
+ struct buffer_head * bh;
+
+ UFSD("ENTER, ino %lu\n", inode->i_ino);
+
+ if (inode->i_ino < UFS_ROOTINO ||
+ inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
+ ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino);
+ return -1;
+ }
+
+ bh = sb_bread(sb, ufs_inotofsba(inode->i_ino));
+ if (!bh) {
+ ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
+ return -1;
+ }
+ if (uspi->fs_magic == UFS2_MAGIC) {
+ struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data;
+
+ ufs2_update_inode(inode,
+ ufs2_inode + ufs_inotofsbo(inode->i_ino));
+ } else {
+ struct ufs_inode *ufs_inode = (struct ufs_inode *) bh->b_data;
+
+ ufs1_update_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino));
+ }
mark_buffer_dirty(bh);
if (do_sync)
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index e84c0ecf073..a059ccd064e 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -355,7 +355,7 @@ out:
return err;
}
-struct inode_operations ufs_dir_inode_operations = {
+const struct inode_operations ufs_dir_inode_operations = {
.create = ufs_create,
.lookup = ufs_lookup,
.link = ufs_link,
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 8a8e9382ec0..b5a6461ec66 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -61,6 +61,8 @@
* UFS2 (of FreeBSD 5.x) support added by
* Niraj Kumar <niraj17@iitbombay.org>, Jan 2004
*
+ * UFS2 write support added by
+ * Evgeniy Dushistov <dushistov@mail.ru>, 2007
*/
@@ -93,14 +95,16 @@
/*
* Print contents of ufs_super_block, useful for debugging
*/
-static void ufs_print_super_stuff(struct super_block *sb, unsigned flags,
+static void ufs_print_super_stuff(struct super_block *sb,
struct ufs_super_block_first *usb1,
struct ufs_super_block_second *usb2,
struct ufs_super_block_third *usb3)
{
+ u32 magic = fs32_to_cpu(sb, usb3->fs_magic);
+
printk("ufs_print_super_stuff\n");
- printk(" magic: 0x%x\n", fs32_to_cpu(sb, usb3->fs_magic));
- if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+ printk(" magic: 0x%x\n", magic);
+ if (fs32_to_cpu(sb, usb3->fs_magic) == UFS2_MAGIC) {
printk(" fs_size: %llu\n", (unsigned long long)
fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size));
printk(" fs_dsize: %llu\n", (unsigned long long)
@@ -117,6 +121,12 @@ static void ufs_print_super_stuff(struct super_block *sb, unsigned flags,
printk(" cs_nbfree(No of free blocks): %llu\n",
(unsigned long long)
fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree));
+ printk(KERN_INFO" cs_nifree(Num of free inodes): %llu\n",
+ (unsigned long long)
+ fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree));
+ printk(KERN_INFO" cs_nffree(Num of free frags): %llu\n",
+ (unsigned long long)
+ fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree));
} else {
printk(" sblkno: %u\n", fs32_to_cpu(sb, usb1->fs_sblkno));
printk(" cblkno: %u\n", fs32_to_cpu(sb, usb1->fs_cblkno));
@@ -199,11 +209,11 @@ static void ufs_print_cylinder_stuff(struct super_block *sb,
printk("\n");
}
#else
-# define ufs_print_super_stuff(sb, flags, usb1, usb2, usb3) /**/
+# define ufs_print_super_stuff(sb, usb1, usb2, usb3) /**/
# define ufs_print_cylinder_stuff(sb, cg) /**/
#endif /* CONFIG_UFS_DEBUG */
-static struct super_operations ufs_super_ops;
+static const struct super_operations ufs_super_ops;
static char error_buf[1024];
@@ -422,7 +432,6 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
{
struct ufs_sb_info *sbi = UFS_SB(sb);
struct ufs_sb_private_info *uspi = sbi->s_uspi;
- unsigned flags = sbi->s_flags;
struct ufs_buffer_head * ubh;
unsigned char * base, * space;
unsigned size, blks, i;
@@ -446,11 +455,7 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
if (i + uspi->s_fpb > blks)
size = (blks - i) * uspi->s_fsize;
- if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
- ubh = ubh_bread(sb,
- fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr) + i, size);
- else
- ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
+ ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
if (!ubh)
goto failed;
@@ -545,6 +550,7 @@ static void ufs_put_cstotal(struct super_block *sb)
cpu_to_fs32(sb, uspi->cs_total.cs_nffree);
}
ubh_mark_buffer_dirty(USPI_UBH(uspi));
+ ufs_print_super_stuff(sb, usb1, usb2, usb3);
UFSD("EXIT\n");
}
@@ -572,7 +578,9 @@ static void ufs_put_super_internal(struct super_block *sb)
size = uspi->s_bsize;
if (i + uspi->s_fpb > blks)
size = (blks - i) * uspi->s_fsize;
+
ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
+
ubh_memcpyubh (ubh, space, size);
space += size;
ubh_mark_buffer_uptodate (ubh, 1);
@@ -649,7 +657,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
kmalloc (sizeof(struct ufs_sb_private_info), GFP_KERNEL);
if (!uspi)
goto failed;
-
+ uspi->s_dirblksize = UFS_SECTOR_SIZE;
super_block_offset=UFS_SBLOCK;
/* Keep 2Gig file limit. Some UFS variants need to override
@@ -674,10 +682,6 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
uspi->s_sbsize = super_block_size = 1536;
uspi->s_sbbase = 0;
flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
- if (!(sb->s_flags & MS_RDONLY)) {
- printk(KERN_INFO "ufstype=ufs2 is supported read-only\n");
- sb->s_flags |= MS_RDONLY;
- }
break;
case UFS_MOUNT_UFSTYPE_SUN:
@@ -718,6 +722,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
break;
case UFS_MOUNT_UFSTYPE_NEXTSTEP:
+ /*TODO: check may be we need set special dir block size?*/
UFSD("ufstype=nextstep\n");
uspi->s_fsize = block_size = 1024;
uspi->s_fmask = ~(1024 - 1);
@@ -733,6 +738,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
break;
case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD:
+ /*TODO: check may be we need set special dir block size?*/
UFSD("ufstype=nextstep-cd\n");
uspi->s_fsize = block_size = 2048;
uspi->s_fmask = ~(2048 - 1);
@@ -754,6 +760,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
uspi->s_fshift = 10;
uspi->s_sbsize = super_block_size = 2048;
uspi->s_sbbase = 0;
+ uspi->s_dirblksize = 1024;
flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
if (!(sb->s_flags & MS_RDONLY)) {
if (!silent)
@@ -887,7 +894,7 @@ magic_found:
}
- ufs_print_super_stuff(sb, flags, usb1, usb2, usb3);
+ ufs_print_super_stuff(sb, usb1, usb2, usb3);
/*
* Check, if file system was correctly unmounted.
@@ -970,7 +977,12 @@ magic_found:
uspi->s_npsect = ufs_get_fs_npsect(sb, usb1, usb3);
uspi->s_interleave = fs32_to_cpu(sb, usb1->fs_interleave);
uspi->s_trackskew = fs32_to_cpu(sb, usb1->fs_trackskew);
- uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr);
+
+ if (uspi->fs_magic == UFS2_MAGIC)
+ uspi->s_csaddr = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr);
+ else
+ uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr);
+
uspi->s_cssize = fs32_to_cpu(sb, usb1->fs_cssize);
uspi->s_cgsize = fs32_to_cpu(sb, usb1->fs_cgsize);
uspi->s_ntrak = fs32_to_cpu(sb, usb1->fs_ntrak);
@@ -1057,7 +1069,6 @@ static void ufs_write_super(struct super_block *sb)
unsigned flags;
lock_kernel();
-
UFSD("ENTER\n");
flags = UFS_SB(sb)->s_flags;
uspi = UFS_SB(sb)->s_uspi;
@@ -1153,7 +1164,8 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
#else
if (ufstype != UFS_MOUNT_UFSTYPE_SUN &&
ufstype != UFS_MOUNT_UFSTYPE_44BSD &&
- ufstype != UFS_MOUNT_UFSTYPE_SUNx86) {
+ ufstype != UFS_MOUNT_UFSTYPE_SUNx86 &&
+ ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
printk("this ufstype is read-only supported\n");
return -EINVAL;
}
@@ -1252,7 +1264,7 @@ static ssize_t ufs_quota_read(struct super_block *, int, char *,size_t, loff_t);
static ssize_t ufs_quota_write(struct super_block *, int, const char *, size_t, loff_t);
#endif
-static struct super_operations ufs_super_ops = {
+static const struct super_operations ufs_super_ops = {
.alloc_inode = ufs_alloc_inode,
.destroy_inode = ufs_destroy_inode,
.read_inode = ufs_read_inode,
diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c
index 337512ed578..d8549f807e8 100644
--- a/fs/ufs/symlink.c
+++ b/fs/ufs/symlink.c
@@ -36,7 +36,7 @@ static void *ufs_follow_link(struct dentry *dentry, struct nameidata *nd)
return NULL;
}
-struct inode_operations ufs_fast_symlink_inode_operations = {
+const struct inode_operations ufs_fast_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = ufs_follow_link,
};
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index 0437b0a6fe9..749581fa772 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -30,8 +30,8 @@
*/
/*
- * Modified to avoid infinite loop on 2006 by
- * Evgeniy Dushistov <dushistov@mail.ru>
+ * Adoptation to use page cache and UFS2 write support by
+ * Evgeniy Dushistov <dushistov@mail.ru>, 2006-2007
*/
#include <linux/errno.h>
@@ -63,13 +63,13 @@
#define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
-static int ufs_trunc_direct (struct inode * inode)
+static int ufs_trunc_direct(struct inode *inode)
{
struct ufs_inode_info *ufsi = UFS_I(inode);
struct super_block * sb;
struct ufs_sb_private_info * uspi;
- __fs32 * p;
- unsigned frag1, frag2, frag3, frag4, block1, block2;
+ void *p;
+ u64 frag1, frag2, frag3, frag4, block1, block2;
unsigned frag_to_free, free_count;
unsigned i, tmp;
int retry;
@@ -91,13 +91,16 @@ static int ufs_trunc_direct (struct inode * inode)
if (frag2 > frag3) {
frag2 = frag4;
frag3 = frag4 = 0;
- }
- else if (frag2 < frag3) {
+ } else if (frag2 < frag3) {
block1 = ufs_fragstoblks (frag2);
block2 = ufs_fragstoblks (frag3);
}
- UFSD("frag1 %u, frag2 %u, block1 %u, block2 %u, frag3 %u, frag4 %u\n", frag1, frag2, block1, block2, frag3, frag4);
+ UFSD("frag1 %llu, frag2 %llu, block1 %llu, block2 %llu, frag3 %llu,"
+ " frag4 %llu\n",
+ (unsigned long long)frag1, (unsigned long long)frag2,
+ (unsigned long long)block1, (unsigned long long)block2,
+ (unsigned long long)frag3, (unsigned long long)frag4);
if (frag1 >= frag2)
goto next1;
@@ -105,8 +108,8 @@ static int ufs_trunc_direct (struct inode * inode)
/*
* Free first free fragments
*/
- p = ufsi->i_u1.i_data + ufs_fragstoblks (frag1);
- tmp = fs32_to_cpu(sb, *p);
+ p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1));
+ tmp = ufs_data_ptr_to_cpu(sb, p);
if (!tmp )
ufs_panic (sb, "ufs_trunc_direct", "internal error");
frag2 -= frag1;
@@ -121,12 +124,11 @@ next1:
* Free whole blocks
*/
for (i = block1 ; i < block2; i++) {
- p = ufsi->i_u1.i_data + i;
- tmp = fs32_to_cpu(sb, *p);
+ p = ufs_get_direct_data_ptr(uspi, ufsi, i);
+ tmp = ufs_data_ptr_to_cpu(sb, p);
if (!tmp)
continue;
-
- *p = 0;
+ ufs_data_ptr_clear(uspi, p);
if (free_count == 0) {
frag_to_free = tmp;
@@ -150,13 +152,12 @@ next1:
/*
* Free last free fragments
*/
- p = ufsi->i_u1.i_data + ufs_fragstoblks (frag3);
- tmp = fs32_to_cpu(sb, *p);
+ p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3));
+ tmp = ufs_data_ptr_to_cpu(sb, p);
if (!tmp )
ufs_panic(sb, "ufs_truncate_direct", "internal error");
frag4 = ufs_fragnum (frag4);
-
- *p = 0;
+ ufs_data_ptr_clear(uspi, p);
ufs_free_fragments (inode, tmp, frag4);
mark_inode_dirty(inode);
@@ -167,17 +168,20 @@ next1:
}
-static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p)
+static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p)
{
struct super_block * sb;
struct ufs_sb_private_info * uspi;
struct ufs_buffer_head * ind_ubh;
- __fs32 * ind;
- unsigned indirect_block, i, tmp;
- unsigned frag_to_free, free_count;
+ void *ind;
+ u64 tmp, indirect_block, i, frag_to_free;
+ unsigned free_count;
int retry;
- UFSD("ENTER\n");
+ UFSD("ENTER: ino %lu, offset %llu, p: %p\n",
+ inode->i_ino, (unsigned long long)offset, p);
+
+ BUG_ON(!p);
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
@@ -186,27 +190,27 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p)
free_count = 0;
retry = 0;
- tmp = fs32_to_cpu(sb, *p);
+ tmp = ufs_data_ptr_to_cpu(sb, p);
if (!tmp)
return 0;
ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize);
- if (tmp != fs32_to_cpu(sb, *p)) {
+ if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
ubh_brelse (ind_ubh);
return 1;
}
if (!ind_ubh) {
- *p = 0;
+ ufs_data_ptr_clear(uspi, p);
return 0;
}
indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0;
for (i = indirect_block; i < uspi->s_apb; i++) {
- ind = ubh_get_addr32 (ind_ubh, i);
- tmp = fs32_to_cpu(sb, *ind);
+ ind = ubh_get_data_ptr(uspi, ind_ubh, i);
+ tmp = ufs_data_ptr_to_cpu(sb, ind);
if (!tmp)
continue;
- *ind = 0;
+ ufs_data_ptr_clear(uspi, ind);
ubh_mark_buffer_dirty(ind_ubh);
if (free_count == 0) {
frag_to_free = tmp;
@@ -226,11 +230,12 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p)
ufs_free_blocks (inode, frag_to_free, free_count);
}
for (i = 0; i < uspi->s_apb; i++)
- if (*ubh_get_addr32(ind_ubh,i))
+ if (!ufs_is_data_ptr_zero(uspi,
+ ubh_get_data_ptr(uspi, ind_ubh, i)))
break;
if (i >= uspi->s_apb) {
- tmp = fs32_to_cpu(sb, *p);
- *p = 0;
+ tmp = ufs_data_ptr_to_cpu(sb, p);
+ ufs_data_ptr_clear(uspi, p);
ufs_free_blocks (inode, tmp, uspi->s_fpb);
mark_inode_dirty(inode);
@@ -248,13 +253,13 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p)
return retry;
}
-static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p)
+static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p)
{
struct super_block * sb;
struct ufs_sb_private_info * uspi;
- struct ufs_buffer_head * dind_bh;
- unsigned i, tmp, dindirect_block;
- __fs32 * dind;
+ struct ufs_buffer_head *dind_bh;
+ u64 i, tmp, dindirect_block;
+ void *dind;
int retry = 0;
UFSD("ENTER\n");
@@ -266,22 +271,22 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p)
? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0;
retry = 0;
- tmp = fs32_to_cpu(sb, *p);
+ tmp = ufs_data_ptr_to_cpu(sb, p);
if (!tmp)
return 0;
dind_bh = ubh_bread(sb, tmp, uspi->s_bsize);
- if (tmp != fs32_to_cpu(sb, *p)) {
+ if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
ubh_brelse (dind_bh);
return 1;
}
if (!dind_bh) {
- *p = 0;
+ ufs_data_ptr_clear(uspi, p);
return 0;
}
for (i = dindirect_block ; i < uspi->s_apb ; i++) {
- dind = ubh_get_addr32 (dind_bh, i);
- tmp = fs32_to_cpu(sb, *dind);
+ dind = ubh_get_data_ptr(uspi, dind_bh, i);
+ tmp = ufs_data_ptr_to_cpu(sb, dind);
if (!tmp)
continue;
retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind);
@@ -289,11 +294,12 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p)
}
for (i = 0; i < uspi->s_apb; i++)
- if (*ubh_get_addr32 (dind_bh, i))
+ if (!ufs_is_data_ptr_zero(uspi,
+ ubh_get_data_ptr(uspi, dind_bh, i)))
break;
if (i >= uspi->s_apb) {
- tmp = fs32_to_cpu(sb, *p);
- *p = 0;
+ tmp = ufs_data_ptr_to_cpu(sb, p);
+ ufs_data_ptr_clear(uspi, p);
ufs_free_blocks(inode, tmp, uspi->s_fpb);
mark_inode_dirty(inode);
@@ -311,34 +317,33 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p)
return retry;
}
-static int ufs_trunc_tindirect (struct inode * inode)
+static int ufs_trunc_tindirect(struct inode *inode)
{
+ struct super_block *sb = inode->i_sb;
+ struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
struct ufs_inode_info *ufsi = UFS_I(inode);
- struct super_block * sb;
- struct ufs_sb_private_info * uspi;
struct ufs_buffer_head * tind_bh;
- unsigned tindirect_block, tmp, i;
- __fs32 * tind, * p;
+ u64 tindirect_block, tmp, i;
+ void *tind, *p;
int retry;
UFSD("ENTER\n");
- sb = inode->i_sb;
- uspi = UFS_SB(sb)->s_uspi;
retry = 0;
tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb))
? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0;
- p = ufsi->i_u1.i_data + UFS_TIND_BLOCK;
- if (!(tmp = fs32_to_cpu(sb, *p)))
+
+ p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK);
+ if (!(tmp = ufs_data_ptr_to_cpu(sb, p)))
return 0;
tind_bh = ubh_bread (sb, tmp, uspi->s_bsize);
- if (tmp != fs32_to_cpu(sb, *p)) {
+ if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
ubh_brelse (tind_bh);
return 1;
}
if (!tind_bh) {
- *p = 0;
+ ufs_data_ptr_clear(uspi, p);
return 0;
}
@@ -349,11 +354,12 @@ static int ufs_trunc_tindirect (struct inode * inode)
ubh_mark_buffer_dirty(tind_bh);
}
for (i = 0; i < uspi->s_apb; i++)
- if (*ubh_get_addr32 (tind_bh, i))
+ if (!ufs_is_data_ptr_zero(uspi,
+ ubh_get_data_ptr(uspi, tind_bh, i)))
break;
if (i >= uspi->s_apb) {
- tmp = fs32_to_cpu(sb, *p);
- *p = 0;
+ tmp = ufs_data_ptr_to_cpu(sb, p);
+ ufs_data_ptr_clear(uspi, p);
ufs_free_blocks(inode, tmp, uspi->s_fpb);
mark_inode_dirty(inode);
@@ -375,7 +381,8 @@ static int ufs_alloc_lastblock(struct inode *inode)
int err = 0;
struct address_space *mapping = inode->i_mapping;
struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi;
- unsigned lastfrag, i, end;
+ unsigned i, end;
+ sector_t lastfrag;
struct page *lastpage;
struct buffer_head *bh;
@@ -430,7 +437,9 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size)
struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
int retry, err = 0;
- UFSD("ENTER\n");
+ UFSD("ENTER: ino %lu, i_size: %llu, old_i_size: %llu\n",
+ inode->i_ino, (unsigned long long)i_size_read(inode),
+ (unsigned long long)old_i_size);
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
@@ -450,10 +459,12 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size)
lock_kernel();
while (1) {
retry = ufs_trunc_direct(inode);
- retry |= ufs_trunc_indirect (inode, UFS_IND_BLOCK,
- (__fs32 *) &ufsi->i_u1.i_data[UFS_IND_BLOCK]);
- retry |= ufs_trunc_dindirect (inode, UFS_IND_BLOCK + uspi->s_apb,
- (__fs32 *) &ufsi->i_u1.i_data[UFS_DIND_BLOCK]);
+ retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK,
+ ufs_get_direct_data_ptr(uspi, ufsi,
+ UFS_IND_BLOCK));
+ retry |= ufs_trunc_dindirect(inode, UFS_IND_BLOCK + uspi->s_apb,
+ ufs_get_direct_data_ptr(uspi, ufsi,
+ UFS_DIND_BLOCK));
retry |= ufs_trunc_tindirect (inode);
if (!retry)
break;
@@ -502,6 +513,6 @@ static int ufs_setattr(struct dentry *dentry, struct iattr *attr)
return inode_setattr(inode, attr);
}
-struct inode_operations ufs_file_inode_operations = {
+const struct inode_operations ufs_file_inode_operations = {
.setattr = ufs_setattr,
};
diff --git a/fs/ufs/util.h b/fs/ufs/util.h
index 7dd12bb1d62..06d344839c4 100644
--- a/fs/ufs/util.h
+++ b/fs/ufs/util.h
@@ -305,8 +305,22 @@ static inline void *get_usb_offset(struct ufs_sb_private_info *uspi,
(((__fs32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \
((begin) & ((uspi->s_fsize>>2) - 1)))
+#define ubh_get_addr64(ubh,begin) \
+ (((__fs64*)((ubh)->bh[(begin) >> (uspi->s_fshift-3)]->b_data)) + \
+ ((begin) & ((uspi->s_fsize>>3) - 1)))
+
#define ubh_get_addr ubh_get_addr8
+static inline void *ubh_get_data_ptr(struct ufs_sb_private_info *uspi,
+ struct ufs_buffer_head *ubh,
+ u64 blk)
+{
+ if (uspi->fs_magic == UFS2_MAGIC)
+ return ubh_get_addr64(ubh, blk);
+ else
+ return ubh_get_addr32(ubh, blk);
+}
+
#define ubh_blkmap(ubh,begin,bit) \
((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb)))
@@ -507,3 +521,46 @@ static inline void ufs_fragacct (struct super_block * sb, unsigned blockmap,
if (fragsize > 0 && fragsize < uspi->s_fpb)
fs32_add(sb, &fraglist[fragsize], cnt);
}
+
+static inline void *ufs_get_direct_data_ptr(struct ufs_sb_private_info *uspi,
+ struct ufs_inode_info *ufsi,
+ unsigned blk)
+{
+ BUG_ON(blk > UFS_TIND_BLOCK);
+ return uspi->fs_magic == UFS2_MAGIC ?
+ (void *)&ufsi->i_u1.u2_i_data[blk] :
+ (void *)&ufsi->i_u1.i_data[blk];
+}
+
+static inline u64 ufs_data_ptr_to_cpu(struct super_block *sb, void *p)
+{
+ return UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC ?
+ fs64_to_cpu(sb, *(__fs64 *)p) :
+ fs32_to_cpu(sb, *(__fs32 *)p);
+}
+
+static inline void ufs_cpu_to_data_ptr(struct super_block *sb, void *p, u64 val)
+{
+ if (UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC)
+ *(__fs64 *)p = cpu_to_fs64(sb, val);
+ else
+ *(__fs32 *)p = cpu_to_fs32(sb, val);
+}
+
+static inline void ufs_data_ptr_clear(struct ufs_sb_private_info *uspi,
+ void *p)
+{
+ if (uspi->fs_magic == UFS2_MAGIC)
+ *(__fs64 *)p = 0;
+ else
+ *(__fs32 *)p = 0;
+}
+
+static inline int ufs_is_data_ptr_zero(struct ufs_sb_private_info *uspi,
+ void *p)
+{
+ if (uspi->fs_magic == UFS2_MAGIC)
+ return *(__fs64 *)p == 0;
+ else
+ return *(__fs32 *)p == 0;
+}
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 0afd745a37c..c28add2fbe9 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -996,7 +996,7 @@ error_inode:
goto out;
}
-static struct inode_operations vfat_dir_inode_operations = {
+static const struct inode_operations vfat_dir_inode_operations = {
.create = vfat_create,
.lookup = vfat_lookup,
.unlink = vfat_unlink,
diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/linux-2.6/mrlock.h
index 32e1ce0f04c..af168a1a98c 100644
--- a/fs/xfs/linux-2.6/mrlock.h
+++ b/fs/xfs/linux-2.6/mrlock.h
@@ -31,15 +31,13 @@ typedef struct {
do { (mrp)->mr_writer = 0; init_rwsem(&(mrp)->mr_lock); } while (0)
#define mrlock_init(mrp, t,n,s) mrinit(mrp, n)
#define mrfree(mrp) do { } while (0)
-#define mraccess(mrp) mraccessf(mrp, 0)
-#define mrupdate(mrp) mrupdatef(mrp, 0)
-static inline void mraccessf(mrlock_t *mrp, int flags)
+static inline void mraccess(mrlock_t *mrp)
{
down_read(&mrp->mr_lock);
}
-static inline void mrupdatef(mrlock_t *mrp, int flags)
+static inline void mrupdate(mrlock_t *mrp)
{
down_write(&mrp->mr_lock);
mrp->mr_writer = 1;
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 7b54461695e..143ffc851c9 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -56,8 +56,6 @@ xfs_count_page_state(
do {
if (buffer_uptodate(bh) && !buffer_mapped(bh))
(*unmapped) = 1;
- else if (buffer_unwritten(bh) && !buffer_delay(bh))
- clear_buffer_unwritten(bh);
else if (buffer_unwritten(bh))
(*unwritten) = 1;
else if (buffer_delay(bh))
@@ -249,7 +247,7 @@ xfs_map_blocks(
return -error;
}
-STATIC inline int
+STATIC_INLINE int
xfs_iomap_valid(
xfs_iomap_t *iomapp,
loff_t offset)
@@ -1272,7 +1270,6 @@ __xfs_get_blocks(
if (direct)
bh_result->b_private = inode;
set_buffer_unwritten(bh_result);
- set_buffer_delay(bh_result);
}
}
@@ -1283,13 +1280,18 @@ __xfs_get_blocks(
bh_result->b_bdev = iomap.iomap_target->bt_bdev;
/*
- * If we previously allocated a block out beyond eof and we are
- * now coming back to use it then we will need to flag it as new
- * even if it has a disk address.
+ * If we previously allocated a block out beyond eof and we are now
+ * coming back to use it then we will need to flag it as new even if it
+ * has a disk address.
+ *
+ * With sub-block writes into unwritten extents we also need to mark
+ * the buffer as new so that the unwritten parts of the buffer gets
+ * correctly zeroed.
*/
if (create &&
((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) ||
- (offset >= i_size_read(inode)) || (iomap.iomap_flags & IOMAP_NEW)))
+ (offset >= i_size_read(inode)) ||
+ (iomap.iomap_flags & (IOMAP_NEW|IOMAP_UNWRITTEN))))
set_buffer_new(bh_result);
if (iomap.iomap_flags & IOMAP_DELAY) {
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 4fb01ffdfd1..e2bea6a661f 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -34,13 +34,13 @@
#include <linux/backing-dev.h>
#include <linux/freezer.h>
-STATIC kmem_zone_t *xfs_buf_zone;
-STATIC kmem_shaker_t xfs_buf_shake;
+static kmem_zone_t *xfs_buf_zone;
+static kmem_shaker_t xfs_buf_shake;
STATIC int xfsbufd(void *);
STATIC int xfsbufd_wakeup(int, gfp_t);
STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int);
-STATIC struct workqueue_struct *xfslogd_workqueue;
+static struct workqueue_struct *xfslogd_workqueue;
struct workqueue_struct *xfsdatad_workqueue;
#ifdef XFS_BUF_TRACE
@@ -139,7 +139,7 @@ page_region_mask(
return mask;
}
-STATIC inline void
+STATIC_INLINE void
set_page_region(
struct page *page,
size_t offset,
@@ -151,7 +151,7 @@ set_page_region(
SetPageUptodate(page);
}
-STATIC inline int
+STATIC_INLINE int
test_page_region(
struct page *page,
size_t offset,
@@ -171,9 +171,9 @@ typedef struct a_list {
struct a_list *next;
} a_list_t;
-STATIC a_list_t *as_free_head;
-STATIC int as_list_len;
-STATIC DEFINE_SPINLOCK(as_lock);
+static a_list_t *as_free_head;
+static int as_list_len;
+static DEFINE_SPINLOCK(as_lock);
/*
* Try to batch vunmaps because they are costly.
@@ -1085,7 +1085,7 @@ xfs_buf_iostart(
return status;
}
-STATIC __inline__ int
+STATIC_INLINE int
_xfs_buf_iolocked(
xfs_buf_t *bp)
{
@@ -1095,7 +1095,7 @@ _xfs_buf_iolocked(
return 0;
}
-STATIC __inline__ void
+STATIC_INLINE void
_xfs_buf_ioend(
xfs_buf_t *bp,
int schedule)
@@ -1426,8 +1426,8 @@ xfs_free_bufhash(
/*
* buftarg list for delwrite queue processing
*/
-STATIC LIST_HEAD(xfs_buftarg_list);
-STATIC DEFINE_SPINLOCK(xfs_buftarg_lock);
+LIST_HEAD(xfs_buftarg_list);
+static DEFINE_SPINLOCK(xfs_buftarg_lock);
STATIC void
xfs_register_buftarg(
@@ -1679,21 +1679,60 @@ xfsbufd_wakeup(
return 0;
}
+/*
+ * Move as many buffers as specified to the supplied list
+ * idicating if we skipped any buffers to prevent deadlocks.
+ */
+STATIC int
+xfs_buf_delwri_split(
+ xfs_buftarg_t *target,
+ struct list_head *list,
+ unsigned long age)
+{
+ xfs_buf_t *bp, *n;
+ struct list_head *dwq = &target->bt_delwrite_queue;
+ spinlock_t *dwlk = &target->bt_delwrite_lock;
+ int skipped = 0;
+ int force;
+
+ force = test_and_clear_bit(XBT_FORCE_FLUSH, &target->bt_flags);
+ INIT_LIST_HEAD(list);
+ spin_lock(dwlk);
+ list_for_each_entry_safe(bp, n, dwq, b_list) {
+ XB_TRACE(bp, "walkq1", (long)xfs_buf_ispin(bp));
+ ASSERT(bp->b_flags & XBF_DELWRI);
+
+ if (!xfs_buf_ispin(bp) && !xfs_buf_cond_lock(bp)) {
+ if (!force &&
+ time_before(jiffies, bp->b_queuetime + age)) {
+ xfs_buf_unlock(bp);
+ break;
+ }
+
+ bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q|
+ _XBF_RUN_QUEUES);
+ bp->b_flags |= XBF_WRITE;
+ list_move_tail(&bp->b_list, list);
+ } else
+ skipped++;
+ }
+ spin_unlock(dwlk);
+
+ return skipped;
+
+}
+
STATIC int
xfsbufd(
- void *data)
+ void *data)
{
- struct list_head tmp;
- unsigned long age;
- xfs_buftarg_t *target = (xfs_buftarg_t *)data;
- xfs_buf_t *bp, *n;
- struct list_head *dwq = &target->bt_delwrite_queue;
- spinlock_t *dwlk = &target->bt_delwrite_lock;
- int count;
+ struct list_head tmp;
+ xfs_buftarg_t *target = (xfs_buftarg_t *)data;
+ int count;
+ xfs_buf_t *bp;
current->flags |= PF_MEMALLOC;
- INIT_LIST_HEAD(&tmp);
do {
if (unlikely(freezing(current))) {
set_bit(XBT_FORCE_SLEEP, &target->bt_flags);
@@ -1705,37 +1744,17 @@ xfsbufd(
schedule_timeout_interruptible(
xfs_buf_timer_centisecs * msecs_to_jiffies(10));
- count = 0;
- age = xfs_buf_age_centisecs * msecs_to_jiffies(10);
- spin_lock(dwlk);
- list_for_each_entry_safe(bp, n, dwq, b_list) {
- XB_TRACE(bp, "walkq1", (long)xfs_buf_ispin(bp));
- ASSERT(bp->b_flags & XBF_DELWRI);
-
- if (!xfs_buf_ispin(bp) && !xfs_buf_cond_lock(bp)) {
- if (!test_bit(XBT_FORCE_FLUSH,
- &target->bt_flags) &&
- time_before(jiffies,
- bp->b_queuetime + age)) {
- xfs_buf_unlock(bp);
- break;
- }
-
- bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q|
- _XBF_RUN_QUEUES);
- bp->b_flags |= XBF_WRITE;
- list_move_tail(&bp->b_list, &tmp);
- count++;
- }
- }
- spin_unlock(dwlk);
+ xfs_buf_delwri_split(target, &tmp,
+ xfs_buf_age_centisecs * msecs_to_jiffies(10));
+ count = 0;
while (!list_empty(&tmp)) {
bp = list_entry(tmp.next, xfs_buf_t, b_list);
ASSERT(target == bp->b_target);
list_del_init(&bp->b_list);
xfs_buf_iostrategy(bp);
+ count++;
}
if (as_list_len > 0)
@@ -1743,7 +1762,6 @@ xfsbufd(
if (count)
blk_run_address_space(target->bt_mapping);
- clear_bit(XBT_FORCE_FLUSH, &target->bt_flags);
} while (!kthread_should_stop());
return 0;
@@ -1756,40 +1774,24 @@ xfsbufd(
*/
int
xfs_flush_buftarg(
- xfs_buftarg_t *target,
- int wait)
+ xfs_buftarg_t *target,
+ int wait)
{
- struct list_head tmp;
- xfs_buf_t *bp, *n;
- int pincount = 0;
- struct list_head *dwq = &target->bt_delwrite_queue;
- spinlock_t *dwlk = &target->bt_delwrite_lock;
+ struct list_head tmp;
+ xfs_buf_t *bp, *n;
+ int pincount = 0;
xfs_buf_runall_queues(xfsdatad_workqueue);
xfs_buf_runall_queues(xfslogd_workqueue);
- INIT_LIST_HEAD(&tmp);
- spin_lock(dwlk);
- list_for_each_entry_safe(bp, n, dwq, b_list) {
- ASSERT(bp->b_target == target);
- ASSERT(bp->b_flags & (XBF_DELWRI | _XBF_DELWRI_Q));
- XB_TRACE(bp, "walkq2", (long)xfs_buf_ispin(bp));
- if (xfs_buf_ispin(bp)) {
- pincount++;
- continue;
- }
-
- list_move_tail(&bp->b_list, &tmp);
- }
- spin_unlock(dwlk);
+ set_bit(XBT_FORCE_FLUSH, &target->bt_flags);
+ pincount = xfs_buf_delwri_split(target, &tmp, 0);
/*
* Dropped the delayed write list lock, now walk the temporary list
*/
list_for_each_entry_safe(bp, n, &tmp, b_list) {
- xfs_buf_lock(bp);
- bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q|_XBF_RUN_QUEUES);
- bp->b_flags |= XBF_WRITE;
+ ASSERT(target == bp->b_target);
if (wait)
bp->b_flags &= ~XBF_ASYNC;
else
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 9dd235cb010..9e8ef8fef39 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -69,8 +69,8 @@ typedef enum {
} xfs_buf_flags_t;
typedef enum {
- XBT_FORCE_SLEEP = (0 << 1),
- XBT_FORCE_FLUSH = (1 << 1),
+ XBT_FORCE_SLEEP = 0,
+ XBT_FORCE_FLUSH = 1,
} xfs_buftarg_flags_t;
typedef struct xfs_bufhash {
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index 5fb75d9151f..e3a5fedac1b 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -24,7 +24,7 @@
#include "xfs_mount.h"
#include "xfs_export.h"
-STATIC struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, };
+static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, };
/*
* XFS encodes and decodes the fileid portion of NFS filehandles
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index d26f5cd2ba7..cb51dc96135 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -46,7 +46,7 @@ static struct vm_operations_struct xfs_file_vm_ops;
static struct vm_operations_struct xfs_dmapi_file_vm_ops;
#endif
-STATIC inline ssize_t
+STATIC_INLINE ssize_t
__xfs_file_read(
struct kiocb *iocb,
const struct iovec *iov,
@@ -84,7 +84,7 @@ xfs_file_aio_read_invis(
return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
}
-STATIC inline ssize_t
+STATIC_INLINE ssize_t
__xfs_file_write(
struct kiocb *iocb,
const struct iovec *iov,
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index f011c9cd0d6..ff5c41ff8d4 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -41,8 +41,6 @@
#include "xfs_error.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_bmap.h"
#include "xfs_buf_item.h"
@@ -355,7 +353,6 @@ STATIC int
xfs_readlink_by_handle(
xfs_mount_t *mp,
void __user *arg,
- struct file *parfilp,
struct inode *parinode)
{
int error;
@@ -388,7 +385,7 @@ xfs_readlink_by_handle(
aiov.iov_len = olen;
aiov.iov_base = hreq.ohandle;
- auio.uio_iov = &aiov;
+ auio.uio_iov = (struct kvec *)&aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
auio.uio_segflg = UIO_USERSPACE;
@@ -406,7 +403,6 @@ STATIC int
xfs_fssetdm_by_handle(
xfs_mount_t *mp,
void __user *arg,
- struct file *parfilp,
struct inode *parinode)
{
int error;
@@ -448,7 +444,6 @@ STATIC int
xfs_attrlist_by_handle(
xfs_mount_t *mp,
void __user *arg,
- struct file *parfilp,
struct inode *parinode)
{
int error;
@@ -569,7 +564,6 @@ STATIC int
xfs_attrmulti_by_handle(
xfs_mount_t *mp,
void __user *arg,
- struct file *parfilp,
struct inode *parinode)
{
int error;
@@ -689,7 +683,6 @@ xfs_ioc_xattr(
STATIC int
xfs_ioc_getbmap(
bhv_desc_t *bdp,
- struct file *filp,
int flags,
unsigned int cmd,
void __user *arg);
@@ -788,7 +781,7 @@ xfs_ioctl(
case XFS_IOC_GETBMAP:
case XFS_IOC_GETBMAPA:
- return xfs_ioc_getbmap(bdp, filp, ioflags, cmd, arg);
+ return xfs_ioc_getbmap(bdp, ioflags, cmd, arg);
case XFS_IOC_GETBMAPX:
return xfs_ioc_getbmapx(bdp, arg);
@@ -802,16 +795,16 @@ xfs_ioctl(
return xfs_open_by_handle(mp, arg, filp, inode);
case XFS_IOC_FSSETDM_BY_HANDLE:
- return xfs_fssetdm_by_handle(mp, arg, filp, inode);
+ return xfs_fssetdm_by_handle(mp, arg, inode);
case XFS_IOC_READLINK_BY_HANDLE:
- return xfs_readlink_by_handle(mp, arg, filp, inode);
+ return xfs_readlink_by_handle(mp, arg, inode);
case XFS_IOC_ATTRLIST_BY_HANDLE:
- return xfs_attrlist_by_handle(mp, arg, filp, inode);
+ return xfs_attrlist_by_handle(mp, arg, inode);
case XFS_IOC_ATTRMULTI_BY_HANDLE:
- return xfs_attrmulti_by_handle(mp, arg, filp, inode);
+ return xfs_attrmulti_by_handle(mp, arg, inode);
case XFS_IOC_SWAPEXT: {
error = xfs_swapext((struct xfs_swapext __user *)arg);
@@ -1095,11 +1088,6 @@ xfs_ioc_fsgeometry(
/*
* Linux extended inode flags interface.
*/
-#define LINUX_XFLAG_SYNC 0x00000008 /* Synchronous updates */
-#define LINUX_XFLAG_IMMUTABLE 0x00000010 /* Immutable file */
-#define LINUX_XFLAG_APPEND 0x00000020 /* writes to file may only append */
-#define LINUX_XFLAG_NODUMP 0x00000040 /* do not dump file */
-#define LINUX_XFLAG_NOATIME 0x00000080 /* do not update atime */
STATIC unsigned int
xfs_merge_ioc_xflags(
@@ -1108,23 +1096,23 @@ xfs_merge_ioc_xflags(
{
unsigned int xflags = start;
- if (flags & LINUX_XFLAG_IMMUTABLE)
+ if (flags & FS_IMMUTABLE_FL)
xflags |= XFS_XFLAG_IMMUTABLE;
else
xflags &= ~XFS_XFLAG_IMMUTABLE;
- if (flags & LINUX_XFLAG_APPEND)
+ if (flags & FS_APPEND_FL)
xflags |= XFS_XFLAG_APPEND;
else
xflags &= ~XFS_XFLAG_APPEND;
- if (flags & LINUX_XFLAG_SYNC)
+ if (flags & FS_SYNC_FL)
xflags |= XFS_XFLAG_SYNC;
else
xflags &= ~XFS_XFLAG_SYNC;
- if (flags & LINUX_XFLAG_NOATIME)
+ if (flags & FS_NOATIME_FL)
xflags |= XFS_XFLAG_NOATIME;
else
xflags &= ~XFS_XFLAG_NOATIME;
- if (flags & LINUX_XFLAG_NODUMP)
+ if (flags & FS_NODUMP_FL)
xflags |= XFS_XFLAG_NODUMP;
else
xflags &= ~XFS_XFLAG_NODUMP;
@@ -1139,15 +1127,15 @@ xfs_di2lxflags(
unsigned int flags = 0;
if (di_flags & XFS_DIFLAG_IMMUTABLE)
- flags |= LINUX_XFLAG_IMMUTABLE;
+ flags |= FS_IMMUTABLE_FL;
if (di_flags & XFS_DIFLAG_APPEND)
- flags |= LINUX_XFLAG_APPEND;
+ flags |= FS_APPEND_FL;
if (di_flags & XFS_DIFLAG_SYNC)
- flags |= LINUX_XFLAG_SYNC;
+ flags |= FS_SYNC_FL;
if (di_flags & XFS_DIFLAG_NOATIME)
- flags |= LINUX_XFLAG_NOATIME;
+ flags |= FS_NOATIME_FL;
if (di_flags & XFS_DIFLAG_NODUMP)
- flags |= LINUX_XFLAG_NODUMP;
+ flags |= FS_NODUMP_FL;
return flags;
}
@@ -1247,9 +1235,9 @@ xfs_ioc_xattr(
break;
}
- if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \
- LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \
- LINUX_XFLAG_SYNC)) {
+ if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
+ FS_NOATIME_FL | FS_NODUMP_FL | \
+ FS_SYNC_FL)) {
error = -EOPNOTSUPP;
break;
}
@@ -1281,7 +1269,6 @@ xfs_ioc_xattr(
STATIC int
xfs_ioc_getbmap(
bhv_desc_t *bdp,
- struct file *filp,
int ioflags,
unsigned int cmd,
void __user *arg)
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 3ba814ae3bb..0b5fa124bef 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -43,8 +43,6 @@
#include "xfs_itable.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_utils.h"
@@ -250,13 +248,13 @@ xfs_init_security(
*
* XXX(hch): nfsd is broken, better fix it instead.
*/
-STATIC inline int
+STATIC_INLINE int
xfs_has_fs_struct(struct task_struct *task)
{
return (task->fs != init_task.fs);
}
-STATIC inline void
+STATIC void
xfs_cleanup_inode(
bhv_vnode_t *dvp,
bhv_vnode_t *vp,
@@ -815,7 +813,7 @@ xfs_vn_removexattr(
}
-struct inode_operations xfs_inode_operations = {
+const struct inode_operations xfs_inode_operations = {
.permission = xfs_vn_permission,
.truncate = xfs_vn_truncate,
.getattr = xfs_vn_getattr,
@@ -826,7 +824,7 @@ struct inode_operations xfs_inode_operations = {
.removexattr = xfs_vn_removexattr,
};
-struct inode_operations xfs_dir_inode_operations = {
+const struct inode_operations xfs_dir_inode_operations = {
.create = xfs_vn_create,
.lookup = xfs_vn_lookup,
.link = xfs_vn_link,
@@ -845,7 +843,7 @@ struct inode_operations xfs_dir_inode_operations = {
.removexattr = xfs_vn_removexattr,
};
-struct inode_operations xfs_symlink_inode_operations = {
+const struct inode_operations xfs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = xfs_vn_follow_link,
.put_link = xfs_vn_put_link,
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h
index ad6173da567..95a69398fce 100644
--- a/fs/xfs/linux-2.6/xfs_iops.h
+++ b/fs/xfs/linux-2.6/xfs_iops.h
@@ -18,9 +18,9 @@
#ifndef __XFS_IOPS_H__
#define __XFS_IOPS_H__
-extern struct inode_operations xfs_inode_operations;
-extern struct inode_operations xfs_dir_inode_operations;
-extern struct inode_operations xfs_symlink_inode_operations;
+extern const struct inode_operations xfs_inode_operations;
+extern const struct inode_operations xfs_dir_inode_operations;
+extern const struct inode_operations xfs_symlink_inode_operations;
extern const struct file_operations xfs_file_operations;
extern const struct file_operations xfs_dir_file_operations;
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 2b0e0018738..715adad7dd4 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -109,16 +109,6 @@
#undef HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */
#endif
-/*
- * State flag for unwritten extent buffers.
- *
- * We need to be able to distinguish between these and delayed
- * allocate buffers within XFS. The generic IO path code does
- * not need to distinguish - we use the BH_Delay flag for both
- * delalloc and these ondisk-uninitialised buffers.
- */
-BUFFER_FNS(PrivateStart, unwritten);
-
#define restricted_chown xfs_params.restrict_chown.val
#define irix_sgid_inherit xfs_params.sgid_inherit.val
#define irix_symlink_mode xfs_params.symlink_mode.val
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 65e79b471d4..ff8d64eba9f 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -43,8 +43,6 @@
#include "xfs_itable.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_inode_item.h"
#include "xfs_buf_item.h"
@@ -134,13 +132,11 @@ STATIC int
xfs_iozero(
struct inode *ip, /* inode */
loff_t pos, /* offset in file */
- size_t count, /* size of data to zero */
- loff_t end_size) /* max file size to set */
+ size_t count) /* size of data to zero */
{
unsigned bytes;
struct page *page;
struct address_space *mapping;
- char *kaddr;
int status;
mapping = ip->i_mapping;
@@ -158,26 +154,21 @@ xfs_iozero(
if (!page)
break;
- kaddr = kmap(page);
status = mapping->a_ops->prepare_write(NULL, page, offset,
offset + bytes);
- if (status) {
+ if (status)
goto unlock;
- }
- memset((void *) (kaddr + offset), 0, bytes);
- flush_dcache_page(page);
+ memclear_highpage_flush(page, offset, bytes);
+
status = mapping->a_ops->commit_write(NULL, page, offset,
offset + bytes);
if (!status) {
pos += bytes;
count -= bytes;
- if (pos > i_size_read(ip))
- i_size_write(ip, pos < end_size ? pos : end_size);
}
unlock:
- kunmap(page);
unlock_page(page);
page_cache_release(page);
if (status)
@@ -449,8 +440,8 @@ STATIC int /* error (positive) */
xfs_zero_last_block(
struct inode *ip,
xfs_iocore_t *io,
- xfs_fsize_t isize,
- xfs_fsize_t end_size)
+ xfs_fsize_t offset,
+ xfs_fsize_t isize)
{
xfs_fileoff_t last_fsb;
xfs_mount_t *mp = io->io_mount;
@@ -459,7 +450,6 @@ xfs_zero_last_block(
int zero_len;
int error = 0;
xfs_bmbt_irec_t imap;
- loff_t loff;
ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
@@ -494,9 +484,10 @@ xfs_zero_last_block(
*/
XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
- loff = XFS_FSB_TO_B(mp, last_fsb);
zero_len = mp->m_sb.sb_blocksize - zero_offset;
- error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size);
+ if (isize + zero_len > offset)
+ zero_len = offset - isize;
+ error = xfs_iozero(ip, isize, zero_len);
XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
ASSERT(error >= 0);
@@ -519,14 +510,15 @@ xfs_zero_eof(
bhv_vnode_t *vp,
xfs_iocore_t *io,
xfs_off_t offset, /* starting I/O offset */
- xfs_fsize_t isize, /* current inode size */
- xfs_fsize_t end_size) /* terminal inode size */
+ xfs_fsize_t isize) /* current inode size */
{
struct inode *ip = vn_to_inode(vp);
xfs_fileoff_t start_zero_fsb;
xfs_fileoff_t end_zero_fsb;
xfs_fileoff_t zero_count_fsb;
xfs_fileoff_t last_fsb;
+ xfs_fileoff_t zero_off;
+ xfs_fsize_t zero_len;
xfs_mount_t *mp = io->io_mount;
int nimaps;
int error = 0;
@@ -540,7 +532,7 @@ xfs_zero_eof(
* First handle zeroing the block on which isize resides.
* We only zero a part of that block so it is handled specially.
*/
- error = xfs_zero_last_block(ip, io, isize, end_size);
+ error = xfs_zero_last_block(ip, io, offset, isize);
if (error) {
ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
@@ -601,10 +593,13 @@ xfs_zero_eof(
*/
XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
- error = xfs_iozero(ip,
- XFS_FSB_TO_B(mp, start_zero_fsb),
- XFS_FSB_TO_B(mp, imap.br_blockcount),
- end_size);
+ zero_off = XFS_FSB_TO_B(mp, start_zero_fsb);
+ zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount);
+
+ if ((zero_off + zero_len) > offset)
+ zero_len = offset - zero_off;
+
+ error = xfs_iozero(ip, zero_off, zero_len);
if (error) {
goto out_lock;
}
@@ -783,8 +778,7 @@ start:
*/
if (pos > isize) {
- error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos,
- isize, pos + count);
+ error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, isize);
if (error) {
xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
goto out_unlock_mutex;
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index c77e62efb74..7ac51b1d216 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -83,7 +83,7 @@ extern int xfs_bdstrat_cb(struct xfs_buf *);
extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t,
- xfs_fsize_t, xfs_fsize_t);
+ xfs_fsize_t);
extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
const struct iovec *, unsigned int,
loff_t *, int, struct cred *);
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index b93265b7c79..1a4103ca593 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -43,8 +43,6 @@
#include "xfs_itable.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_utils.h"
@@ -58,10 +56,10 @@
#include <linux/kthread.h>
#include <linux/freezer.h>
-STATIC struct quotactl_ops xfs_quotactl_operations;
-STATIC struct super_operations xfs_super_operations;
-STATIC kmem_zone_t *xfs_vnode_zone;
-STATIC kmem_zone_t *xfs_ioend_zone;
+static struct quotactl_ops xfs_quotactl_operations;
+static struct super_operations xfs_super_operations;
+static kmem_zone_t *xfs_vnode_zone;
+static kmem_zone_t *xfs_ioend_zone;
mempool_t *xfs_ioend_pool;
STATIC struct xfs_mount_args *
@@ -121,7 +119,7 @@ xfs_max_file_offset(
return (((__uint64_t)pagefactor) << bitshift) - 1;
}
-STATIC __inline__ void
+STATIC_INLINE void
xfs_set_inodeops(
struct inode *inode)
{
@@ -147,7 +145,7 @@ xfs_set_inodeops(
}
}
-STATIC __inline__ void
+STATIC_INLINE void
xfs_revalidate_inode(
xfs_mount_t *mp,
bhv_vnode_t *vp,
@@ -553,7 +551,6 @@ vfs_sync_worker(
error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \
SYNC_ATTR | SYNC_REFCACHE, NULL);
vfsp->vfs_sync_seq++;
- wmb();
wake_up(&vfsp->vfs_wait_single_sync_task);
}
@@ -659,9 +656,17 @@ xfs_fs_sync_super(
int error;
int flags;
- if (unlikely(sb->s_frozen == SB_FREEZE_WRITE))
- flags = SYNC_QUIESCE;
- else
+ if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) {
+ /*
+ * First stage of freeze - no more writers will make progress
+ * now we are here, so we flush delwri and delalloc buffers
+ * here, then wait for all I/O to complete. Data is frozen at
+ * that point. Metadata is not frozen, transactions can still
+ * occur here so don't bother flushing the buftarg (i.e
+ * SYNC_QUIESCE) because it'll just get dirty again.
+ */
+ flags = SYNC_FSDATA | SYNC_DELWRI | SYNC_WAIT | SYNC_IOWAIT;
+ } else
flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
error = bhv_vfs_sync(vfsp, flags, NULL);
@@ -873,7 +878,7 @@ xfs_fs_get_sb(
mnt);
}
-STATIC struct super_operations xfs_super_operations = {
+static struct super_operations xfs_super_operations = {
.alloc_inode = xfs_fs_alloc_inode,
.destroy_inode = xfs_fs_destroy_inode,
.write_inode = xfs_fs_write_inode,
@@ -887,7 +892,7 @@ STATIC struct super_operations xfs_super_operations = {
.show_options = xfs_fs_show_options,
};
-STATIC struct quotactl_ops xfs_quotactl_operations = {
+static struct quotactl_ops xfs_quotactl_operations = {
.quota_sync = xfs_fs_quotasync,
.get_xstate = xfs_fs_getxstate,
.set_xstate = xfs_fs_setxstate,
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c
index af246532fbf..5c46c35a97a 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.c
+++ b/fs/xfs/linux-2.6/xfs_sysctl.c
@@ -54,102 +54,204 @@ xfs_stats_clear_proc_handler(
}
#endif /* CONFIG_PROC_FS */
-STATIC ctl_table xfs_table[] = {
- {XFS_RESTRICT_CHOWN, "restrict_chown", &xfs_params.restrict_chown.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.restrict_chown.min, &xfs_params.restrict_chown.max},
-
- {XFS_SGID_INHERIT, "irix_sgid_inherit", &xfs_params.sgid_inherit.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.sgid_inherit.min, &xfs_params.sgid_inherit.max},
-
- {XFS_SYMLINK_MODE, "irix_symlink_mode", &xfs_params.symlink_mode.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.symlink_mode.min, &xfs_params.symlink_mode.max},
-
- {XFS_PANIC_MASK, "panic_mask", &xfs_params.panic_mask.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.panic_mask.min, &xfs_params.panic_mask.max},
-
- {XFS_ERRLEVEL, "error_level", &xfs_params.error_level.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.error_level.min, &xfs_params.error_level.max},
-
- {XFS_SYNCD_TIMER, "xfssyncd_centisecs", &xfs_params.syncd_timer.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.syncd_timer.min, &xfs_params.syncd_timer.max},
-
- {XFS_INHERIT_SYNC, "inherit_sync", &xfs_params.inherit_sync.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.inherit_sync.min, &xfs_params.inherit_sync.max},
-
- {XFS_INHERIT_NODUMP, "inherit_nodump", &xfs_params.inherit_nodump.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.inherit_nodump.min, &xfs_params.inherit_nodump.max},
-
- {XFS_INHERIT_NOATIME, "inherit_noatime", &xfs_params.inherit_noatim.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.inherit_noatim.min, &xfs_params.inherit_noatim.max},
-
- {XFS_BUF_TIMER, "xfsbufd_centisecs", &xfs_params.xfs_buf_timer.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.xfs_buf_timer.min, &xfs_params.xfs_buf_timer.max},
-
- {XFS_BUF_AGE, "age_buffer_centisecs", &xfs_params.xfs_buf_age.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.xfs_buf_age.min, &xfs_params.xfs_buf_age.max},
-
- {XFS_INHERIT_NOSYM, "inherit_nosymlinks", &xfs_params.inherit_nosym.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.inherit_nosym.min, &xfs_params.inherit_nosym.max},
-
- {XFS_ROTORSTEP, "rotorstep", &xfs_params.rotorstep.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.rotorstep.min, &xfs_params.rotorstep.max},
-
- {XFS_INHERIT_NODFRG, "inherit_nodefrag", &xfs_params.inherit_nodfrg.val,
- sizeof(int), 0644, NULL, &proc_dointvec_minmax,
- &sysctl_intvec, NULL,
- &xfs_params.inherit_nodfrg.min, &xfs_params.inherit_nodfrg.max},
+static ctl_table xfs_table[] = {
+ {
+ .ctl_name = XFS_RESTRICT_CHOWN,
+ .procname = "restrict_chown",
+ .data = &xfs_params.restrict_chown.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.restrict_chown.min,
+ .extra2 = &xfs_params.restrict_chown.max
+ },
+ {
+ .ctl_name = XFS_SGID_INHERIT,
+ .procname = "irix_sgid_inherit",
+ .data = &xfs_params.sgid_inherit.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.sgid_inherit.min,
+ .extra2 = &xfs_params.sgid_inherit.max
+ },
+ {
+ .ctl_name = XFS_SYMLINK_MODE,
+ .procname = "irix_symlink_mode",
+ .data = &xfs_params.symlink_mode.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.symlink_mode.min,
+ .extra2 = &xfs_params.symlink_mode.max
+ },
+ {
+ .ctl_name = XFS_PANIC_MASK,
+ .procname = "panic_mask",
+ .data = &xfs_params.panic_mask.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.panic_mask.min,
+ .extra2 = &xfs_params.panic_mask.max
+ },
+ {
+ .ctl_name = XFS_ERRLEVEL,
+ .procname = "error_level",
+ .data = &xfs_params.error_level.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.error_level.min,
+ .extra2 = &xfs_params.error_level.max
+ },
+ {
+ .ctl_name = XFS_SYNCD_TIMER,
+ .procname = "xfssyncd_centisecs",
+ .data = &xfs_params.syncd_timer.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.syncd_timer.min,
+ .extra2 = &xfs_params.syncd_timer.max
+ },
+ {
+ .ctl_name = XFS_INHERIT_SYNC,
+ .procname = "inherit_sync",
+ .data = &xfs_params.inherit_sync.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.inherit_sync.min,
+ .extra2 = &xfs_params.inherit_sync.max
+ },
+ {
+ .ctl_name = XFS_INHERIT_NODUMP,
+ .procname = "inherit_nodump",
+ .data = &xfs_params.inherit_nodump.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.inherit_nodump.min,
+ .extra2 = &xfs_params.inherit_nodump.max
+ },
+ {
+ .ctl_name = XFS_INHERIT_NOATIME,
+ .procname = "inherit_noatime",
+ .data = &xfs_params.inherit_noatim.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.inherit_noatim.min,
+ .extra2 = &xfs_params.inherit_noatim.max
+ },
+ {
+ .ctl_name = XFS_BUF_TIMER,
+ .procname = "xfsbufd_centisecs",
+ .data = &xfs_params.xfs_buf_timer.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.xfs_buf_timer.min,
+ .extra2 = &xfs_params.xfs_buf_timer.max
+ },
+ {
+ .ctl_name = XFS_BUF_AGE,
+ .procname = "age_buffer_centisecs",
+ .data = &xfs_params.xfs_buf_age.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.xfs_buf_age.min,
+ .extra2 = &xfs_params.xfs_buf_age.max
+ },
+ {
+ .ctl_name = XFS_INHERIT_NOSYM,
+ .procname = "inherit_nosymlinks",
+ .data = &xfs_params.inherit_nosym.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.inherit_nosym.min,
+ .extra2 = &xfs_params.inherit_nosym.max
+ },
+ {
+ .ctl_name = XFS_ROTORSTEP,
+ .procname = "rotorstep",
+ .data = &xfs_params.rotorstep.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.rotorstep.min,
+ .extra2 = &xfs_params.rotorstep.max
+ },
+ {
+ .ctl_name = XFS_INHERIT_NODFRG,
+ .procname = "inherit_nodefrag",
+ .data = &xfs_params.inherit_nodfrg.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.inherit_nodfrg.min,
+ .extra2 = &xfs_params.inherit_nodfrg.max
+ },
/* please keep this the last entry */
#ifdef CONFIG_PROC_FS
- {XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val,
- sizeof(int), 0644, NULL, &xfs_stats_clear_proc_handler,
- &sysctl_intvec, NULL,
- &xfs_params.stats_clear.min, &xfs_params.stats_clear.max},
+ {
+ .ctl_name = XFS_STATS_CLEAR,
+ .procname = "stats_clear",
+ .data = &xfs_params.stats_clear.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &xfs_stats_clear_proc_handler,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.stats_clear.min,
+ .extra2 = &xfs_params.stats_clear.max
+ },
#endif /* CONFIG_PROC_FS */
- {0}
+ {}
};
-STATIC ctl_table xfs_dir_table[] = {
- {FS_XFS, "xfs", NULL, 0, 0555, xfs_table},
- {0}
+static ctl_table xfs_dir_table[] = {
+ {
+ .ctl_name = FS_XFS,
+ .procname = "xfs",
+ .mode = 0555,
+ .child = xfs_table
+ },
+ {}
};
-STATIC ctl_table xfs_root_table[] = {
- {CTL_FS, "fs", NULL, 0, 0555, xfs_dir_table},
- {0}
+static ctl_table xfs_root_table[] = {
+ {
+ .ctl_name = CTL_FS,
+ .procname = "fs",
+ .mode = 0555,
+ .child = xfs_dir_table
+ },
+ {}
};
void
xfs_sysctl_register(void)
{
- xfs_table_header = register_sysctl_table(xfs_root_table, 1);
+ xfs_table_header = register_sysctl_table(xfs_root_table, 0);
}
void
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index da255bdf526..e2c2ce98ab5 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -91,7 +91,7 @@ typedef enum {
#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */
#define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */
#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
-#define SYNC_QUIESCE 0x0100 /* quiesce fileystem for a snapshot */
+#define SYNC_IOWAIT 0x0100 /* wait for all I/O to complete */
#define SHUTDOWN_META_IO_ERROR 0x0001 /* write attempt to metadata failed */
#define SHUTDOWN_LOG_IO_ERROR 0x0002 /* write attempt to the log failed */
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index 553fa731ade..ada24baf88d 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -26,7 +26,7 @@ DEFINE_SPINLOCK(vnumber_lock);
*/
#define NVSYNC 37
#define vptosync(v) (&vsync[((unsigned long)v) % NVSYNC])
-STATIC wait_queue_head_t vsync[NVSYNC];
+static wait_queue_head_t vsync[NVSYNC];
void
vn_init(void)
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 515f5fdea57..b76118cf489 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -489,14 +489,14 @@ static inline struct bhv_vnode *vn_grab(struct bhv_vnode *vp)
#define VN_LOCK(vp) mutex_spinlock(&(vp)->v_lock)
#define VN_UNLOCK(vp, s) mutex_spinunlock(&(vp)->v_lock, s)
-static __inline__ void vn_flagset(struct bhv_vnode *vp, uint flag)
+STATIC_INLINE void vn_flagset(struct bhv_vnode *vp, uint flag)
{
spin_lock(&vp->v_lock);
vp->v_flag |= flag;
spin_unlock(&vp->v_lock);
}
-static __inline__ uint vn_flagclr(struct bhv_vnode *vp, uint flag)
+STATIC_INLINE uint vn_flagclr(struct bhv_vnode *vp, uint flag)
{
uint cleared;
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 3aa77153185..4adaf13aac6 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -43,8 +43,6 @@
#include "xfs_itable.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_trans_space.h"
@@ -484,7 +482,7 @@ xfs_qm_dqalloc(
xfs_trans_bhold(tp, bp);
- if ((error = xfs_bmap_finish(tpp, &flist, firstblock, &committed))) {
+ if ((error = xfs_bmap_finish(tpp, &flist, &committed))) {
goto error1;
}
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index 33ad5af386e..ddb61fe22a5 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -43,8 +43,6 @@
#include "xfs_itable.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_trans_priv.h"
@@ -399,7 +397,7 @@ xfs_qm_dquot_logitem_committing(
/*
* This is the ops vector for dquots
*/
-STATIC struct xfs_item_ops xfs_dquot_item_ops = {
+static struct xfs_item_ops xfs_dquot_item_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_qm_dquot_logitem_format,
@@ -606,7 +604,7 @@ xfs_qm_qoffend_logitem_committing(xfs_qoff_logitem_t *qip, xfs_lsn_t commit_lsn)
return;
}
-STATIC struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
+static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_qm_qoff_logitem_format,
@@ -628,7 +626,7 @@ STATIC struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
/*
* This is the ops vector shared by all quotaoff-start log items.
*/
-STATIC struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
+static struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_qm_qoff_logitem_format,
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 7c6a3a50379..1de2acdc7f7 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -44,8 +44,6 @@
#include "xfs_bmap.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_trans_space.h"
@@ -64,10 +62,10 @@ uint ndquot;
kmem_zone_t *qm_dqzone;
kmem_zone_t *qm_dqtrxzone;
-STATIC kmem_shaker_t xfs_qm_shaker;
+static kmem_shaker_t xfs_qm_shaker;
-STATIC cred_t xfs_zerocr;
-STATIC xfs_inode_t xfs_zeroino;
+static cred_t xfs_zerocr;
+static xfs_inode_t xfs_zeroino;
STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int);
STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index db8872be8c8..d2cdb8a2aad 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -44,8 +44,6 @@
#include "xfs_error.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_qm.h"
@@ -384,7 +382,7 @@ xfs_qm_dqrele_null(
}
-STATIC struct xfs_qmops xfs_qmcore_xfs = {
+static struct xfs_qmops xfs_qmcore_xfs = {
.xfs_qminit = xfs_qm_newmount,
.xfs_qmdone = xfs_qm_unmount_quotadestroy,
.xfs_qmmount = xfs_qm_endmount,
diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c
index 6f858fb81a3..709f5f545cf 100644
--- a/fs/xfs/quota/xfs_qm_stats.c
+++ b/fs/xfs/quota/xfs_qm_stats.c
@@ -43,8 +43,6 @@
#include "xfs_error.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_qm.h"
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index ed620c4d159..716f562aa8b 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -46,8 +46,6 @@
#include "xfs_error.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_utils.h"
@@ -134,7 +132,7 @@ xfs_qm_quotactl(
break;
case Q_XQUOTASYNC:
- return (xfs_sync_inodes(mp, SYNC_DELWRI, 0, NULL));
+ return (xfs_sync_inodes(mp, SYNC_DELWRI, NULL));
default:
break;
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 0242e9666e8..d7491e7b1f3 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -43,8 +43,6 @@
#include "xfs_error.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_trans_priv.h"
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
index 4363512d2f9..08bbd3cb87a 100644
--- a/fs/xfs/support/debug.c
+++ b/fs/xfs/support/debug.c
@@ -19,7 +19,7 @@
#include "debug.h"
#include "spin.h"
-static char message[256]; /* keep it off the stack */
+static char message[1024]; /* keep it off the stack */
static DEFINE_SPINLOCK(xfs_err_lock);
/* Translate from CE_FOO to KERN_FOO, err_level(CE_FOO) == KERN_FOO */
@@ -44,13 +44,14 @@ cmn_err(register int level, char *fmt, ...)
spin_lock_irqsave(&xfs_err_lock,flags);
va_start(ap, fmt);
if (*fmt == '!') fp++;
- len = vsprintf(message, fp, ap);
- if (level != CE_DEBUG && message[len-1] != '\n')
- strcat(message, "\n");
- printk("%s%s", err_level[level], message);
+ len = vsnprintf(message, sizeof(message), fp, ap);
+ if (len >= sizeof(message))
+ len = sizeof(message) - 1;
+ if (message[len-1] == '\n')
+ message[len-1] = 0;
+ printk("%s%s\n", err_level[level], message);
va_end(ap);
spin_unlock_irqrestore(&xfs_err_lock,flags);
-
BUG_ON(level == CE_PANIC);
}
@@ -64,11 +65,13 @@ icmn_err(register int level, char *fmt, va_list ap)
if(level > XFS_MAX_ERR_LEVEL)
level = XFS_MAX_ERR_LEVEL;
spin_lock_irqsave(&xfs_err_lock,flags);
- len = vsprintf(message, fmt, ap);
- if (level != CE_DEBUG && message[len-1] != '\n')
- strcat(message, "\n");
+ len = vsnprintf(message, sizeof(message), fmt, ap);
+ if (len >= sizeof(message))
+ len = sizeof(message) - 1;
+ if (message[len-1] == '\n')
+ message[len-1] = 0;
+ printk("%s%s\n", err_level[level], message);
spin_unlock_irqrestore(&xfs_err_lock,flags);
- printk("%s%s", err_level[level], message);
BUG_ON(level == CE_PANIC);
}
diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h
index 4f54dca662a..2a70cc605ae 100644
--- a/fs/xfs/support/debug.h
+++ b/fs/xfs/support/debug.h
@@ -38,13 +38,37 @@ extern void assfail(char *expr, char *f, int l);
#ifndef DEBUG
# define ASSERT(expr) ((void)0)
-#else
+
+#ifndef STATIC
+# define STATIC static noinline
+#endif
+
+#ifndef STATIC_INLINE
+# define STATIC_INLINE static inline
+#endif
+
+#else /* DEBUG */
+
# define ASSERT(expr) ASSERT_ALWAYS(expr)
extern unsigned long random(void);
-#endif
#ifndef STATIC
-# define STATIC static
+# define STATIC noinline
#endif
+/*
+ * We stop inlining of inline functions in debug mode.
+ * Unfortunately, this means static inline in header files
+ * get multiple definitions, so they need to remain static.
+ * This then gives tonnes of warnings about unused but defined
+ * functions, so we need to add the unused attribute to prevent
+ * these spurious warnings.
+ */
+#ifndef STATIC_INLINE
+# define STATIC_INLINE static __attribute__ ((unused)) noinline
+#endif
+
+#endif /* DEBUG */
+
+
#endif /* __XFS_SUPPORT_DEBUG_H__ */
diff --git a/fs/xfs/support/move.h b/fs/xfs/support/move.h
index 977879c24ff..324e413dead 100644
--- a/fs/xfs/support/move.h
+++ b/fs/xfs/support/move.h
@@ -55,7 +55,7 @@ enum uio_seg {
};
struct uio {
- struct iovec *uio_iov; /* pointer to array of iovecs */
+ struct kvec *uio_iov; /* pointer to array of iovecs */
int uio_iovcnt; /* number of iovecs in array */
xfs_off_t uio_offset; /* offset in file this uio corresponds to */
int uio_resid; /* residual i/o count */
@@ -63,7 +63,7 @@ struct uio {
};
typedef struct uio uio_t;
-typedef struct iovec iovec_t;
+typedef struct kvec iovec_t;
extern int xfs_uio_read (caddr_t, size_t, uio_t *);
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 4b0cb474be4..4ca4beb7bb5 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -31,7 +31,6 @@
#include "xfs_inode.h"
#include "xfs_btree.h"
#include "xfs_acl.h"
-#include "xfs_mac.h"
#include "xfs_attr.h"
#include <linux/capability.h>
diff --git a/fs/xfs/xfs_alloc_btree.h b/fs/xfs/xfs_alloc_btree.h
index bce81c7a4fd..5bd1a2c8bd0 100644
--- a/fs/xfs/xfs_alloc_btree.h
+++ b/fs/xfs/xfs_alloc_btree.h
@@ -58,7 +58,6 @@ typedef struct xfs_btree_sblock xfs_alloc_block_t;
/*
* Real block structures have a size equal to the disk block size.
*/
-#define XFS_ALLOC_BLOCK_SIZE(lev,cur) (1 << (cur)->bc_blocklog)
#define XFS_ALLOC_BLOCK_MAXRECS(lev,cur) ((cur)->bc_mp->m_alloc_mxr[lev != 0])
#define XFS_ALLOC_BLOCK_MINRECS(lev,cur) ((cur)->bc_mp->m_alloc_mnr[lev != 0])
@@ -87,16 +86,13 @@ typedef struct xfs_btree_sblock xfs_alloc_block_t;
* Record, key, and pointer address macros for btree blocks.
*/
#define XFS_ALLOC_REC_ADDR(bb,i,cur) \
- XFS_BTREE_REC_ADDR(XFS_ALLOC_BLOCK_SIZE(0,cur), xfs_alloc, \
- bb, i, XFS_ALLOC_BLOCK_MAXRECS(0, cur))
+ XFS_BTREE_REC_ADDR(xfs_alloc, bb, i)
#define XFS_ALLOC_KEY_ADDR(bb,i,cur) \
- XFS_BTREE_KEY_ADDR(XFS_ALLOC_BLOCK_SIZE(1,cur), xfs_alloc, \
- bb, i, XFS_ALLOC_BLOCK_MAXRECS(1, cur))
+ XFS_BTREE_KEY_ADDR(xfs_alloc, bb, i)
#define XFS_ALLOC_PTR_ADDR(bb,i,cur) \
- XFS_BTREE_PTR_ADDR(XFS_ALLOC_BLOCK_SIZE(1,cur), xfs_alloc, \
- bb, i, XFS_ALLOC_BLOCK_MAXRECS(1, cur))
+ XFS_BTREE_PTR_ADDR(xfs_alloc, bb, i, XFS_ALLOC_BLOCK_MAXRECS(1, cur))
/*
* Decrement cursor by one record at the level.
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 9ada7bdbae5..9d358ffce4e 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -57,9 +57,9 @@
*/
#define ATTR_SYSCOUNT 2
-STATIC struct attrnames posix_acl_access;
-STATIC struct attrnames posix_acl_default;
-STATIC struct attrnames *attr_system_names[ATTR_SYSCOUNT];
+static struct attrnames posix_acl_access;
+static struct attrnames posix_acl_default;
+static struct attrnames *attr_system_names[ATTR_SYSCOUNT];
/*========================================================================
* Function prototypes for the kernel.
@@ -199,18 +199,14 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
return (error);
/*
- * Determine space new attribute will use, and if it would be
- * "local" or "remote" (note: local != inline).
- */
- size = xfs_attr_leaf_newentsize(namelen, valuelen,
- mp->m_sb.sb_blocksize, &local);
-
- /*
* If the inode doesn't have an attribute fork, add one.
* (inode must not be locked when we call this routine)
*/
if (XFS_IFORK_Q(dp) == 0) {
- if ((error = xfs_bmap_add_attrfork(dp, size, rsvd)))
+ int sf_size = sizeof(xfs_attr_sf_hdr_t) +
+ XFS_ATTR_SF_ENTSIZE_BYNAME(namelen, valuelen);
+
+ if ((error = xfs_bmap_add_attrfork(dp, sf_size, rsvd)))
return(error);
}
@@ -231,6 +227,13 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
args.addname = 1;
args.oknoent = 1;
+ /*
+ * Determine space new attribute will use, and if it would be
+ * "local" or "remote" (note: local != inline).
+ */
+ size = xfs_attr_leaf_newentsize(namelen, valuelen,
+ mp->m_sb.sb_blocksize, &local);
+
nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
if (local) {
if (size > (mp->m_sb.sb_blocksize >> 1)) {
@@ -346,7 +349,7 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
error = xfs_attr_shortform_to_leaf(&args);
if (!error) {
error = xfs_bmap_finish(&args.trans, args.flist,
- *args.firstblock, &committed);
+ &committed);
}
if (error) {
ASSERT(committed);
@@ -973,7 +976,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
error = xfs_attr_leaf_to_node(args);
if (!error) {
error = xfs_bmap_finish(&args->trans, args->flist,
- *args->firstblock, &committed);
+ &committed);
}
if (error) {
ASSERT(committed);
@@ -1074,7 +1077,6 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
if (!error) {
error = xfs_bmap_finish(&args->trans,
args->flist,
- *args->firstblock,
&committed);
}
if (error) {
@@ -1152,7 +1154,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
/* bp is gone due to xfs_da_shrink_inode */
if (!error) {
error = xfs_bmap_finish(&args->trans, args->flist,
- *args->firstblock, &committed);
+ &committed);
}
if (error) {
ASSERT(committed);
@@ -1307,7 +1309,6 @@ restart:
if (!error) {
error = xfs_bmap_finish(&args->trans,
args->flist,
- *args->firstblock,
&committed);
}
if (error) {
@@ -1347,7 +1348,7 @@ restart:
error = xfs_da_split(state);
if (!error) {
error = xfs_bmap_finish(&args->trans, args->flist,
- *args->firstblock, &committed);
+ &committed);
}
if (error) {
ASSERT(committed);
@@ -1459,7 +1460,6 @@ restart:
if (!error) {
error = xfs_bmap_finish(&args->trans,
args->flist,
- *args->firstblock,
&committed);
}
if (error) {
@@ -1594,7 +1594,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
error = xfs_da_join(state);
if (!error) {
error = xfs_bmap_finish(&args->trans, args->flist,
- *args->firstblock, &committed);
+ &committed);
}
if (error) {
ASSERT(committed);
@@ -1646,7 +1646,6 @@ xfs_attr_node_removename(xfs_da_args_t *args)
if (!error) {
error = xfs_bmap_finish(&args->trans,
args->flist,
- *args->firstblock,
&committed);
}
if (error) {
@@ -2090,7 +2089,7 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
args->flist, NULL);
if (!error) {
error = xfs_bmap_finish(&args->trans, args->flist,
- *args->firstblock, &committed);
+ &committed);
}
if (error) {
ASSERT(committed);
@@ -2246,7 +2245,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
NULL, &done);
if (!error) {
error = xfs_bmap_finish(&args->trans, args->flist,
- *args->firstblock, &committed);
+ &committed);
}
if (error) {
ASSERT(committed);
@@ -2477,7 +2476,7 @@ posix_acl_default_exists(
return xfs_acl_vhasacl_default(vp);
}
-STATIC struct attrnames posix_acl_access = {
+static struct attrnames posix_acl_access = {
.attr_name = "posix_acl_access",
.attr_namelen = sizeof("posix_acl_access") - 1,
.attr_get = posix_acl_access_get,
@@ -2486,7 +2485,7 @@ STATIC struct attrnames posix_acl_access = {
.attr_exists = posix_acl_access_exists,
};
-STATIC struct attrnames posix_acl_default = {
+static struct attrnames posix_acl_default = {
.attr_name = "posix_acl_default",
.attr_namelen = sizeof("posix_acl_default") - 1,
.attr_get = posix_acl_default_get,
@@ -2495,7 +2494,7 @@ STATIC struct attrnames posix_acl_default = {
.attr_exists = posix_acl_default_exists,
};
-STATIC struct attrnames *attr_system_names[] =
+static struct attrnames *attr_system_names[] =
{ &posix_acl_access, &posix_acl_default };
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 9719bbef122..8eab73e8340 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -94,7 +94,7 @@ STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
* Namespace helper routines
*========================================================================*/
-STATIC inline attrnames_t *
+STATIC_INLINE attrnames_t *
xfs_attr_flags_namesp(int flags)
{
return ((flags & XFS_ATTR_SECURE) ? &attr_secure:
@@ -105,7 +105,7 @@ xfs_attr_flags_namesp(int flags)
* If namespace bits don't match return 0.
* If all match then return 1.
*/
-STATIC inline int
+STATIC_INLINE int
xfs_attr_namesp_match(int arg_flags, int ondisk_flags)
{
return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags);
@@ -116,7 +116,7 @@ xfs_attr_namesp_match(int arg_flags, int ondisk_flags)
* then return 0.
* If all match or are overridable then return 1.
*/
-STATIC inline int
+STATIC_INLINE int
xfs_attr_namesp_match_overrides(int arg_flags, int ondisk_flags)
{
if (((arg_flags & ATTR_SECURE) == 0) !=
@@ -150,6 +150,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
int offset;
int minforkoff; /* lower limit on valid forkoff locations */
int maxforkoff; /* upper limit on valid forkoff locations */
+ int dsize;
xfs_mount_t *mp = dp->i_mount;
offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */
@@ -169,8 +170,43 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
return 0;
}
- /* data fork btree root can have at least this many key/ptr pairs */
- minforkoff = MAX(dp->i_df.if_bytes, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
+ dsize = dp->i_df.if_bytes;
+
+ switch (dp->i_d.di_format) {
+ case XFS_DINODE_FMT_EXTENTS:
+ /*
+ * If there is no attr fork and the data fork is extents,
+ * determine if creating the default attr fork will result
+ * in the extents form migrating to btree. If so, the
+ * minimum offset only needs to be the space required for
+ * the btree root.
+ */
+ if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > mp->m_attroffset)
+ dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
+ break;
+
+ case XFS_DINODE_FMT_BTREE:
+ /*
+ * If have data btree then keep forkoff if we have one,
+ * otherwise we are adding a new attr, so then we set
+ * minforkoff to where the btree root can finish so we have
+ * plenty of room for attrs
+ */
+ if (dp->i_d.di_forkoff) {
+ if (offset < dp->i_d.di_forkoff)
+ return 0;
+ else
+ return dp->i_d.di_forkoff;
+ } else
+ dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot);
+ break;
+ }
+
+ /*
+ * A data fork btree root must have space for at least
+ * MINDBTPTRS key/ptr pairs if the data fork is small or empty.
+ */
+ minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
minforkoff = roundup(minforkoff, 8) >> 3;
/* attr fork btree root can have at least this many key/ptr pairs */
@@ -336,7 +372,8 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
*/
totsize -= size;
if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname &&
- (mp->m_flags & XFS_MOUNT_ATTR2)) {
+ (mp->m_flags & XFS_MOUNT_ATTR2) &&
+ (dp->i_d.di_format != XFS_DINODE_FMT_BTREE)) {
/*
* Last attribute now removed, revert to original
* inode format making all literal area available
@@ -355,7 +392,8 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize);
ASSERT(dp->i_d.di_forkoff);
ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname ||
- !(mp->m_flags & XFS_MOUNT_ATTR2));
+ !(mp->m_flags & XFS_MOUNT_ATTR2) ||
+ dp->i_d.di_format == XFS_DINODE_FMT_BTREE);
dp->i_afp->if_ext_max =
XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
dp->i_df.if_ext_max =
@@ -748,6 +786,7 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp)
+ be16_to_cpu(name_loc->valuelen);
}
if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&
+ (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
(bytes == sizeof(struct xfs_attr_sf_hdr)))
return(-1);
return(xfs_attr_shortform_bytesfit(dp, bytes));
@@ -786,6 +825,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
if (forkoff == -1) {
ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
+ ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE);
/*
* Last attribute was removed, revert to original
diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/xfs_bit.c
index 43be6a7e47c..1afe07f67e3 100644
--- a/fs/xfs/xfs_bit.c
+++ b/fs/xfs/xfs_bit.c
@@ -29,7 +29,7 @@
/*
* Index of high bit number in byte, -1 for none set, 0..7 otherwise.
*/
-STATIC const char xfs_highbit[256] = {
+static const char xfs_highbit[256] = {
-1, 0, 1, 1, 2, 2, 2, 2, /* 00 .. 07 */
3, 3, 3, 3, 3, 3, 3, 3, /* 08 .. 0f */
4, 4, 4, 4, 4, 4, 4, 4, /* 10 .. 17 */
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 498ad50d1f4..87795188ced 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -185,16 +185,6 @@ xfs_bmap_btree_to_extents(
int *logflagsp, /* inode logging flags */
int whichfork); /* data or attr fork */
-#ifdef DEBUG
-/*
- * Check that the extents list for the inode ip is in the right order.
- */
-STATIC void
-xfs_bmap_check_extents(
- xfs_inode_t *ip, /* incore inode pointer */
- int whichfork); /* data or attr fork */
-#endif
-
/*
* Called by xfs_bmapi to update file extent records and the btree
* after removing space (or undoing a delayed allocation).
@@ -410,7 +400,6 @@ xfs_bmap_count_leaves(
STATIC int
xfs_bmap_disk_count_leaves(
xfs_ifork_t *ifp,
- xfs_mount_t *mp,
xfs_extnum_t idx,
xfs_bmbt_block_t *block,
int numrecs,
@@ -684,7 +673,7 @@ xfs_bmap_add_extent(
ASSERT(nblks <= da_old);
if (nblks < da_old)
xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
- (int)(da_old - nblks), rsvd);
+ (int64_t)(da_old - nblks), rsvd);
}
/*
* Clear out the allocated field, done with it now in any case.
@@ -1209,7 +1198,7 @@ xfs_bmap_add_extent_delay_real(
diff = (int)(temp + temp2 - STARTBLOCKVAL(PREV.br_startblock) -
(cur ? cur->bc_private.b.allocated : 0));
if (diff > 0 &&
- xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, -diff, rsvd)) {
+ xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd)) {
/*
* Ick gross gag me with a spoon.
*/
@@ -1220,7 +1209,7 @@ xfs_bmap_add_extent_delay_real(
diff--;
if (!diff ||
!xfs_mod_incore_sb(ip->i_mount,
- XFS_SBS_FDBLOCKS, -diff, rsvd))
+ XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
break;
}
if (temp2) {
@@ -1228,7 +1217,7 @@ xfs_bmap_add_extent_delay_real(
diff--;
if (!diff ||
!xfs_mod_incore_sb(ip->i_mount,
- XFS_SBS_FDBLOCKS, -diff, rsvd))
+ XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
break;
}
}
@@ -2015,7 +2004,7 @@ xfs_bmap_add_extent_hole_delay(
if (oldlen != newlen) {
ASSERT(oldlen > newlen);
xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
- (int)(oldlen - newlen), rsvd);
+ (int64_t)(oldlen - newlen), rsvd);
/*
* Nothing to do for disk quota accounting here.
*/
@@ -3359,7 +3348,7 @@ xfs_bmap_del_extent(
*/
ASSERT(da_old >= da_new);
if (da_old > da_new)
- xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int)(da_old - da_new),
+ xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int64_t)(da_old - da_new),
rsvd);
if (delta) {
/* DELTA: report the original extent. */
@@ -3543,6 +3532,7 @@ xfs_bmap_forkoff_reset(
if (whichfork == XFS_ATTR_FORK &&
(ip->i_d.di_format != XFS_DINODE_FMT_DEV) &&
(ip->i_d.di_format != XFS_DINODE_FMT_UUID) &&
+ (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
((mp->m_attroffset >> 3) > ip->i_d.di_forkoff)) {
ip->i_d.di_forkoff = mp->m_attroffset >> 3;
ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) /
@@ -4079,7 +4069,7 @@ xfs_bmap_add_attrfork(
} else
XFS_SB_UNLOCK(mp, s);
}
- if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed)))
+ if ((error = xfs_bmap_finish(&tp, &flist, &committed)))
goto error2;
error = xfs_trans_commit(tp, XFS_TRANS_PERM_LOG_RES, NULL);
ASSERT(ip->i_df.if_ext_max ==
@@ -4212,7 +4202,6 @@ int /* error */
xfs_bmap_finish(
xfs_trans_t **tp, /* transaction pointer addr */
xfs_bmap_free_t *flist, /* i/o: list extents to free */
- xfs_fsblock_t firstblock, /* controlled ag for allocs */
int *committed) /* xact committed or not */
{
xfs_efd_log_item_t *efd; /* extent free data */
@@ -4533,8 +4522,7 @@ xfs_bmap_read_extents(
error0);
if (level == 0)
break;
- pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block,
- 1, mp->m_bmap_dmxr[1]);
+ pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
bno = be64_to_cpu(*pp);
XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
xfs_trans_brelse(tp, bp);
@@ -4577,8 +4565,7 @@ xfs_bmap_read_extents(
/*
* Copy records into the extent records.
*/
- frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt,
- block, 1, mp->m_bmap_dmxr[0]);
+ frp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1);
start = i;
for (j = 0; j < num_recs; j++, i++, frp++) {
trp = xfs_iext_get_ext(ifp, i);
@@ -4929,28 +4916,28 @@ xfs_bmapi(
if (rt) {
error = xfs_mod_incore_sb(mp,
XFS_SBS_FREXTENTS,
- -(extsz), (flags &
+ -((int64_t)extsz), (flags &
XFS_BMAPI_RSVBLOCKS));
} else {
error = xfs_mod_incore_sb(mp,
XFS_SBS_FDBLOCKS,
- -(alen), (flags &
+ -((int64_t)alen), (flags &
XFS_BMAPI_RSVBLOCKS));
}
if (!error) {
error = xfs_mod_incore_sb(mp,
XFS_SBS_FDBLOCKS,
- -(indlen), (flags &
+ -((int64_t)indlen), (flags &
XFS_BMAPI_RSVBLOCKS));
if (error && rt)
xfs_mod_incore_sb(mp,
XFS_SBS_FREXTENTS,
- extsz, (flags &
+ (int64_t)extsz, (flags &
XFS_BMAPI_RSVBLOCKS));
else if (error)
xfs_mod_incore_sb(mp,
XFS_SBS_FDBLOCKS,
- alen, (flags &
+ (int64_t)alen, (flags &
XFS_BMAPI_RSVBLOCKS));
}
@@ -5616,13 +5603,13 @@ xfs_bunmapi(
rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
do_div(rtexts, mp->m_sb.sb_rextsize);
xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
- (int)rtexts, rsvd);
+ (int64_t)rtexts, rsvd);
(void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
NULL, ip, -((long)del.br_blockcount), 0,
XFS_QMOPT_RES_RTBLKS);
} else {
xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
- (int)del.br_blockcount, rsvd);
+ (int64_t)del.br_blockcount, rsvd);
(void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
NULL, ip, -((long)del.br_blockcount), 0,
XFS_QMOPT_RES_REGBLKS);
@@ -6048,32 +6035,6 @@ xfs_bmap_eof(
}
#ifdef DEBUG
-/*
- * Check that the extents list for the inode ip is in the right order.
- */
-STATIC void
-xfs_bmap_check_extents(
- xfs_inode_t *ip, /* incore inode pointer */
- int whichfork) /* data or attr fork */
-{
- xfs_bmbt_rec_t *ep; /* current extent entry */
- xfs_extnum_t idx; /* extent record index */
- xfs_ifork_t *ifp; /* inode fork pointer */
- xfs_extnum_t nextents; /* number of extents in list */
- xfs_bmbt_rec_t *nextp; /* next extent entry */
-
- ifp = XFS_IFORK_PTR(ip, whichfork);
- ASSERT(ifp->if_flags & XFS_IFEXTENTS);
- nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
- ep = xfs_iext_get_ext(ifp, 0);
- for (idx = 0; idx < nextents - 1; idx++) {
- nextp = xfs_iext_get_ext(ifp, idx + 1);
- xfs_btree_check_rec(XFS_BTNUM_BMAP, (void *)ep,
- (void *)(nextp));
- ep = nextp;
- }
-}
-
STATIC
xfs_buf_t *
xfs_bmap_get_bp(
@@ -6156,8 +6117,7 @@ xfs_check_block(
if (root) {
keyp = XFS_BMAP_BROOT_KEY_ADDR(block, i, sz);
} else {
- keyp = XFS_BTREE_KEY_ADDR(mp->m_sb.sb_blocksize,
- xfs_bmbt, block, i, dmxr);
+ keyp = XFS_BTREE_KEY_ADDR(xfs_bmbt, block, i);
}
if (prevp) {
@@ -6172,15 +6132,14 @@ xfs_check_block(
if (root) {
pp = XFS_BMAP_BROOT_PTR_ADDR(block, i, sz);
} else {
- pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
- xfs_bmbt, block, i, dmxr);
+ pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, i, dmxr);
}
for (j = i+1; j <= be16_to_cpu(block->bb_numrecs); j++) {
if (root) {
thispa = XFS_BMAP_BROOT_PTR_ADDR(block, j, sz);
} else {
- thispa = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
- xfs_bmbt, block, j, dmxr);
+ thispa = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, j,
+ dmxr);
}
if (*thispa == *pp) {
cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld",
@@ -6267,8 +6226,7 @@ xfs_bmap_check_leaf_extents(
*/
xfs_check_block(block, mp, 0, 0);
- pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block,
- 1, mp->m_bmap_dmxr[1]);
+ pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
bno = be64_to_cpu(*pp);
XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
if (bp_release) {
@@ -6305,11 +6263,9 @@ xfs_bmap_check_leaf_extents(
* conform with the first entry in this one.
*/
- ep = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt,
- block, 1, mp->m_bmap_dmxr[0]);
+ ep = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1);
for (j = 1; j < num_recs; j++) {
- nextp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt,
- block, j + 1, mp->m_bmap_dmxr[0]);
+ nextp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, j + 1);
if (lastp) {
xfs_btree_check_rec(XFS_BTNUM_BMAP,
(void *)lastp, (void *)ep);
@@ -6454,8 +6410,7 @@ xfs_bmap_count_tree(
}
/* Dive to the next level */
- pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
- xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
+ pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
bno = be64_to_cpu(*pp);
if (unlikely((error =
xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) {
@@ -6470,7 +6425,7 @@ xfs_bmap_count_tree(
for (;;) {
nextbno = be64_to_cpu(block->bb_rightsib);
numrecs = be16_to_cpu(block->bb_numrecs);
- if (unlikely(xfs_bmap_disk_count_leaves(ifp, mp,
+ if (unlikely(xfs_bmap_disk_count_leaves(ifp,
0, block, numrecs, count) < 0)) {
xfs_trans_brelse(tp, bp);
XFS_ERROR_REPORT("xfs_bmap_count_tree(2)",
@@ -6518,7 +6473,6 @@ xfs_bmap_count_leaves(
int
xfs_bmap_disk_count_leaves(
xfs_ifork_t *ifp,
- xfs_mount_t *mp,
xfs_extnum_t idx,
xfs_bmbt_block_t *block,
int numrecs,
@@ -6528,8 +6482,7 @@ xfs_bmap_disk_count_leaves(
xfs_bmbt_rec_t *frp;
for (b = 1; b <= numrecs; b++) {
- frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize,
- xfs_bmbt, block, idx + b, mp->m_bmap_dmxr[0]);
+ frp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, idx + b);
*count += xfs_bmbt_disk_get_blockcount(frp);
}
return 0;
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 80e93409b78..4f24c7e39b3 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -202,7 +202,6 @@ int /* error */
xfs_bmap_finish(
struct xfs_trans **tp, /* transaction pointer addr */
xfs_bmap_free_t *flist, /* i/o: list extents to free */
- xfs_fsblock_t firstblock, /* controlled a.g. for allocs */
int *committed); /* xact committed or not */
/*
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index a7b835bf870..0bf192fea3e 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -678,47 +678,6 @@ error0:
return error;
}
-#ifdef DEBUG
-/*
- * Get the data from the pointed-to record.
- */
-int
-xfs_bmbt_get_rec(
- xfs_btree_cur_t *cur,
- xfs_fileoff_t *off,
- xfs_fsblock_t *bno,
- xfs_filblks_t *len,
- xfs_exntst_t *state,
- int *stat)
-{
- xfs_bmbt_block_t *block;
- xfs_buf_t *bp;
-#ifdef DEBUG
- int error;
-#endif
- int ptr;
- xfs_bmbt_rec_t *rp;
-
- block = xfs_bmbt_get_block(cur, 0, &bp);
- ptr = cur->bc_ptrs[0];
-#ifdef DEBUG
- if ((error = xfs_btree_check_lblock(cur, block, 0, bp)))
- return error;
-#endif
- if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) {
- *stat = 0;
- return 0;
- }
- rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
- *off = xfs_bmbt_disk_get_startoff(rp);
- *bno = xfs_bmbt_disk_get_startblock(rp);
- *len = xfs_bmbt_disk_get_blockcount(rp);
- *state = xfs_bmbt_disk_get_state(rp);
- *stat = 1;
- return 0;
-}
-#endif
-
/*
* Insert one record/level. Return information to the caller
* allowing the next level up to proceed if necessary.
@@ -1731,9 +1690,9 @@ xfs_bmdr_to_bmbt(
rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO);
rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO);
dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
- fkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
+ fkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1);
tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
- fpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
+ fpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr);
tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
dmxr = be16_to_cpu(dblock->bb_numrecs);
memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
@@ -1862,7 +1821,7 @@ xfs_bmbt_delete(
* xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state.
*/
-STATIC __inline__ void
+STATIC_INLINE void
__xfs_bmbt_get_all(
__uint64_t l0,
__uint64_t l1,
@@ -2016,30 +1975,6 @@ xfs_bmbt_disk_get_blockcount(
}
/*
- * Extract the startblock field from an on disk bmap extent record.
- */
-xfs_fsblock_t
-xfs_bmbt_disk_get_startblock(
- xfs_bmbt_rec_t *r)
-{
-#if XFS_BIG_BLKNOS
- return (((xfs_fsblock_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) |
- (((xfs_fsblock_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
-#else
-#ifdef DEBUG
- xfs_dfsbno_t b;
-
- b = (((xfs_dfsbno_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) |
- (((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
- ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
- return (xfs_fsblock_t)b;
-#else /* !DEBUG */
- return (xfs_fsblock_t)(((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
-#endif /* DEBUG */
-#endif /* XFS_BIG_BLKNOS */
-}
-
-/*
* Extract the startoff field from a disk format bmap extent record.
*/
xfs_fileoff_t
@@ -2049,17 +1984,6 @@ xfs_bmbt_disk_get_startoff(
return ((xfs_fileoff_t)INT_GET(r->l0, ARCH_CONVERT) &
XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
}
-
-xfs_exntst_t
-xfs_bmbt_disk_get_state(
- xfs_bmbt_rec_t *r)
-{
- int ext_flag;
-
- ext_flag = (int)((INT_GET(r->l0, ARCH_CONVERT)) >> (64 - BMBT_EXNTFLAG_BITLEN));
- return xfs_extent_state(xfs_bmbt_disk_get_blockcount(r),
- ext_flag);
-}
#endif /* XFS_NATIVE_HOST */
@@ -2684,9 +2608,9 @@ xfs_bmbt_to_bmdr(
dblock->bb_numrecs = rblock->bb_numrecs;
dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
- tkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
+ tkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1);
fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
- tpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
+ tpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr);
dmxr = be16_to_cpu(dblock->bb_numrecs);
memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 49539de9525..a77b1b753d0 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -175,19 +175,11 @@ typedef struct xfs_btree_lblock xfs_bmbt_block_t;
#define XFS_BUF_TO_BMBT_BLOCK(bp) ((xfs_bmbt_block_t *)XFS_BUF_PTR(bp))
-#define XFS_BMAP_IBLOCK_SIZE(lev,cur) (1 << (cur)->bc_blocklog)
#define XFS_BMAP_RBLOCK_DSIZE(lev,cur) ((cur)->bc_private.b.forksize)
#define XFS_BMAP_RBLOCK_ISIZE(lev,cur) \
((int)XFS_IFORK_PTR((cur)->bc_private.b.ip, \
(cur)->bc_private.b.whichfork)->if_broot_bytes)
-#define XFS_BMAP_BLOCK_DSIZE(lev,cur) \
- (((lev) == (cur)->bc_nlevels - 1 ? \
- XFS_BMAP_RBLOCK_DSIZE(lev,cur) : XFS_BMAP_IBLOCK_SIZE(lev,cur)))
-#define XFS_BMAP_BLOCK_ISIZE(lev,cur) \
- (((lev) == (cur)->bc_nlevels - 1 ? \
- XFS_BMAP_RBLOCK_ISIZE(lev,cur) : XFS_BMAP_IBLOCK_SIZE(lev,cur)))
-
#define XFS_BMAP_BLOCK_DMAXRECS(lev,cur) \
(((lev) == (cur)->bc_nlevels - 1 ? \
XFS_BTREE_BLOCK_MAXRECS(XFS_BMAP_RBLOCK_DSIZE(lev,cur), \
@@ -210,37 +202,21 @@ typedef struct xfs_btree_lblock xfs_bmbt_block_t;
xfs_bmbt, (lev) == 0) : \
((cur)->bc_mp->m_bmap_dmnr[(lev) != 0])))
-#define XFS_BMAP_REC_DADDR(bb,i,cur) \
- (XFS_BTREE_REC_ADDR(XFS_BMAP_BLOCK_DSIZE( \
- be16_to_cpu((bb)->bb_level), cur), \
- xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS( \
- be16_to_cpu((bb)->bb_level), cur)))
-#define XFS_BMAP_REC_IADDR(bb,i,cur) \
- (XFS_BTREE_REC_ADDR(XFS_BMAP_BLOCK_ISIZE( \
- be16_to_cpu((bb)->bb_level), cur), \
- xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS( \
- be16_to_cpu((bb)->bb_level), cur)))
+#define XFS_BMAP_REC_DADDR(bb,i,cur) (XFS_BTREE_REC_ADDR(xfs_bmbt, bb, i))
+
+#define XFS_BMAP_REC_IADDR(bb,i,cur) (XFS_BTREE_REC_ADDR(xfs_bmbt, bb, i))
#define XFS_BMAP_KEY_DADDR(bb,i,cur) \
- (XFS_BTREE_KEY_ADDR(XFS_BMAP_BLOCK_DSIZE( \
- be16_to_cpu((bb)->bb_level), cur), \
- xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS( \
- be16_to_cpu((bb)->bb_level), cur)))
+ (XFS_BTREE_KEY_ADDR(xfs_bmbt, bb, i))
+
#define XFS_BMAP_KEY_IADDR(bb,i,cur) \
- (XFS_BTREE_KEY_ADDR(XFS_BMAP_BLOCK_ISIZE( \
- be16_to_cpu((bb)->bb_level), cur), \
- xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS( \
- be16_to_cpu((bb)->bb_level), cur)))
+ (XFS_BTREE_KEY_ADDR(xfs_bmbt, bb, i))
#define XFS_BMAP_PTR_DADDR(bb,i,cur) \
- (XFS_BTREE_PTR_ADDR(XFS_BMAP_BLOCK_DSIZE( \
- be16_to_cpu((bb)->bb_level), cur), \
- xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS( \
+ (XFS_BTREE_PTR_ADDR(xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS( \
be16_to_cpu((bb)->bb_level), cur)))
#define XFS_BMAP_PTR_IADDR(bb,i,cur) \
- (XFS_BTREE_PTR_ADDR(XFS_BMAP_BLOCK_ISIZE( \
- be16_to_cpu((bb)->bb_level), cur), \
- xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS( \
+ (XFS_BTREE_PTR_ADDR(xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS( \
be16_to_cpu((bb)->bb_level), cur)))
/*
@@ -248,11 +224,11 @@ typedef struct xfs_btree_lblock xfs_bmbt_block_t;
* we don't have a cursor.
*/
#define XFS_BMAP_BROOT_REC_ADDR(bb,i,sz) \
- (XFS_BTREE_REC_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
+ (XFS_BTREE_REC_ADDR(xfs_bmbt,bb,i))
#define XFS_BMAP_BROOT_KEY_ADDR(bb,i,sz) \
- (XFS_BTREE_KEY_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
+ (XFS_BTREE_KEY_ADDR(xfs_bmbt,bb,i))
#define XFS_BMAP_BROOT_PTR_ADDR(bb,i,sz) \
- (XFS_BTREE_PTR_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
+ (XFS_BTREE_PTR_ADDR(xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
#define XFS_BMAP_BROOT_NUMRECS(bb) be16_to_cpu((bb)->bb_numrecs)
#define XFS_BMAP_BROOT_MAXRECS(sz) XFS_BTREE_BLOCK_MAXRECS(sz,xfs_bmbt,0)
@@ -315,15 +291,11 @@ extern xfs_exntst_t xfs_bmbt_get_state(xfs_bmbt_rec_t *r);
#ifndef XFS_NATIVE_HOST
extern void xfs_bmbt_disk_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
-extern xfs_exntst_t xfs_bmbt_disk_get_state(xfs_bmbt_rec_t *r);
extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r);
-extern xfs_fsblock_t xfs_bmbt_disk_get_startblock(xfs_bmbt_rec_t *r);
extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r);
#else
#define xfs_bmbt_disk_get_all(r, s) xfs_bmbt_get_all(r, s)
-#define xfs_bmbt_disk_get_state(r) xfs_bmbt_get_state(r)
#define xfs_bmbt_disk_get_blockcount(r) xfs_bmbt_get_blockcount(r)
-#define xfs_bmbt_disk_get_startblock(r) xfs_bmbt_get_blockcount(r)
#define xfs_bmbt_disk_get_startoff(r) xfs_bmbt_get_startoff(r)
#endif /* XFS_NATIVE_HOST */
@@ -364,15 +336,6 @@ extern void xfs_bmbt_to_bmdr(xfs_bmbt_block_t *, int, xfs_bmdr_block_t *, int);
extern int xfs_bmbt_update(struct xfs_btree_cur *, xfs_fileoff_t,
xfs_fsblock_t, xfs_filblks_t, xfs_exntst_t);
-#ifdef DEBUG
-/*
- * Get the data from the pointed-to record.
- */
-extern int xfs_bmbt_get_rec(struct xfs_btree_cur *, xfs_fileoff_t *,
- xfs_fsblock_t *, xfs_filblks_t *,
- xfs_exntst_t *, int *);
-#endif
-
#endif /* __KERNEL__ */
#endif /* __XFS_BMAP_BTREE_H__ */
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 892b06c5426..4e27d55a1e7 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -122,13 +122,13 @@ extern const __uint32_t xfs_magics[];
* Given block size, type prefix, block pointer, and index of requested entry
* (first entry numbered 1).
*/
-#define XFS_BTREE_REC_ADDR(bsz,t,bb,i,mxr) \
+#define XFS_BTREE_REC_ADDR(t,bb,i) \
((t ## _rec_t *)((char *)(bb) + sizeof(t ## _block_t) + \
((i) - 1) * sizeof(t ## _rec_t)))
-#define XFS_BTREE_KEY_ADDR(bsz,t,bb,i,mxr) \
+#define XFS_BTREE_KEY_ADDR(t,bb,i) \
((t ## _key_t *)((char *)(bb) + sizeof(t ## _block_t) + \
((i) - 1) * sizeof(t ## _key_t)))
-#define XFS_BTREE_PTR_ADDR(bsz,t,bb,i,mxr) \
+#define XFS_BTREE_PTR_ADDR(t,bb,i,mxr) \
((t ## _ptr_t *)((char *)(bb) + sizeof(t ## _block_t) + \
(mxr) * sizeof(t ## _key_t) + ((i) - 1) * sizeof(t ## _ptr_t)))
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 7a55c248ea7..6c1bddc04e3 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -660,7 +660,7 @@ xfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn)
/*
* This is the ops vector shared by all buf log items.
*/
-STATIC struct xfs_item_ops xfs_buf_item_ops = {
+static struct xfs_item_ops xfs_buf_item_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_buf_item_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_buf_item_format,
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index 07c708c2b52..d7e13614306 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -21,23 +21,7 @@
/*
* This is the structure used to lay out a buf log item in the
* log. The data map describes which 128 byte chunks of the buffer
- * have been logged. This structure works only on buffers that
- * reside up to the first TB in the filesystem. These buffers are
- * generated only by pre-6.2 systems and are known as XFS_LI_6_1_BUF.
- */
-typedef struct xfs_buf_log_format_v1 {
- unsigned short blf_type; /* buf log item type indicator */
- unsigned short blf_size; /* size of this item */
- __int32_t blf_blkno; /* starting blkno of this buf */
- ushort blf_flags; /* misc state */
- ushort blf_len; /* number of blocks in this buf */
- unsigned int blf_map_size; /* size of data bitmap in words */
- unsigned int blf_data_map[1];/* variable size bitmap of */
- /* regions of buffer in this item */
-} xfs_buf_log_format_v1_t;
-
-/*
- * This is a form of the above structure with a 64 bit blkno field.
+ * have been logged.
* For 6.2 and beyond, this is XFS_LI_BUF. We use this to log everything.
*/
typedef struct xfs_buf_log_format_t {
diff --git a/fs/xfs/xfs_cap.h b/fs/xfs/xfs_cap.h
deleted file mode 100644
index 7a0e482dd43..00000000000
--- a/fs/xfs/xfs_cap.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#ifndef __XFS_CAP_H__
-#define __XFS_CAP_H__
-
-/*
- * Capabilities
- */
-typedef __uint64_t xfs_cap_value_t;
-
-typedef struct xfs_cap_set {
- xfs_cap_value_t cap_effective; /* use in capability checks */
- xfs_cap_value_t cap_permitted; /* combined with file attrs */
- xfs_cap_value_t cap_inheritable;/* pass through exec */
-} xfs_cap_set_t;
-
-/* On-disk XFS extended attribute names */
-#define SGI_CAP_FILE "SGI_CAP_FILE"
-#define SGI_CAP_FILE_SIZE (sizeof(SGI_CAP_FILE)-1)
-#define SGI_CAP_LINUX "SGI_CAP_LINUX"
-#define SGI_CAP_LINUX_SIZE (sizeof(SGI_CAP_LINUX)-1)
-
-/*
- * For Linux, we take the bitfields directly from capability.h
- * and no longer attempt to keep this attribute ondisk compatible
- * with IRIX. Since this attribute is only set on executables,
- * it just doesn't make much sense to try. We do use a different
- * named attribute though, to avoid confusion.
- */
-
-#ifdef __KERNEL__
-
-#ifdef CONFIG_FS_POSIX_CAP
-
-#include <linux/posix_cap_xattr.h>
-
-struct bhv_vnode;
-
-extern int xfs_cap_vhascap(struct bhv_vnode *);
-extern int xfs_cap_vset(struct bhv_vnode *, void *, size_t);
-extern int xfs_cap_vget(struct bhv_vnode *, void *, size_t);
-extern int xfs_cap_vremove(struct bhv_vnode *);
-
-#define _CAP_EXISTS xfs_cap_vhascap
-
-#else
-#define xfs_cap_vset(v,p,sz) (-EOPNOTSUPP)
-#define xfs_cap_vget(v,p,sz) (-EOPNOTSUPP)
-#define xfs_cap_vremove(v) (-EOPNOTSUPP)
-#define _CAP_EXISTS (NULL)
-#endif
-
-#endif /* __KERNEL__ */
-
-#endif /* __XFS_CAP_H__ */
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index a68bc1f1a31..aea37df4aa6 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -1090,8 +1090,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
if (blk->magic == XFS_DA_NODE_MAGIC) {
node = blk->bp->data;
max = be16_to_cpu(node->hdr.count);
- btreehashval = node->btree[max-1].hashval;
- blk->hashval = be32_to_cpu(btreehashval);
+ blk->hashval = be32_to_cpu(node->btree[max-1].hashval);
/*
* Binary search. (note: small blocks will skip loop)
@@ -2166,21 +2165,6 @@ xfs_da_reada_buf(
return rval;
}
-/*
- * Calculate the number of bits needed to hold i different values.
- */
-uint
-xfs_da_log2_roundup(uint i)
-{
- uint rval;
-
- for (rval = 0; rval < NBBY * sizeof(i); rval++) {
- if ((1 << rval) >= i)
- break;
- }
- return(rval);
-}
-
kmem_zone_t *xfs_da_state_zone; /* anchor for state struct zone */
kmem_zone_t *xfs_dabuf_zone; /* dabuf zone */
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 4ab865ec8b8..44dabf02f2a 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -249,7 +249,6 @@ int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
xfs_dabuf_t *dead_buf);
uint xfs_da_hashname(const uchar_t *name_string, int name_length);
-uint xfs_da_log2_roundup(uint i);
xfs_da_state_t *xfs_da_state_alloc(void);
void xfs_da_state_free(xfs_da_state_t *state);
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 50d0faea371..b847e6a7a3f 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -41,7 +41,6 @@
#include "xfs_itable.h"
#include "xfs_dfrag.h"
#include "xfs_error.h"
-#include "xfs_mac.h"
#include "xfs_rw.h"
/*
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index b95681b03d8..b1af54464f0 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -132,32 +132,6 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp)
}
int
-xfs_errortag_clear(int error_tag, xfs_mount_t *mp)
-{
- int i;
- int64_t fsid;
-
- memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
-
- for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
- if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
- xfs_etest[i] = 0;
- xfs_etest_fsid[i] = 0LL;
- kmem_free(xfs_etest_fsname[i],
- strlen(xfs_etest_fsname[i]) + 1);
- xfs_etest_fsname[i] = NULL;
- cmn_err(CE_WARN, "Cleared XFS error tag #%d",
- error_tag);
- return 0;
- }
- }
-
- cmn_err(CE_WARN, "XFS error tag %d not on", error_tag);
-
- return 1;
-}
-
-int
xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud)
{
int i;
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 0893e16b7d8..5599ada456a 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -144,7 +144,6 @@ extern void xfs_error_test_init(void);
#endif /* __ANSI_CPP__ */
extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp);
-extern int xfs_errortag_clear(int error_tag, xfs_mount_t *mp);
extern int xfs_errortag_clearall(xfs_mount_t *mp);
extern int xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud);
#else
@@ -180,6 +179,6 @@ extern void xfs_fs_cmn_err(int level, struct xfs_mount *mp, char *fmt, ...);
xfs_fs_cmn_err(level, mp, fmt " Unmount and run xfs_repair.", ## args)
#define xfs_fs_mount_cmn_err(f, fmt, args...) \
- ((f & XFS_MFSI_QUIET)? cmn_err(CE_WARN, "XFS: " fmt, ## args) : (void)0)
+ ((f & XFS_MFSI_QUIET)? (void)0 : cmn_err(CE_WARN, "XFS: " fmt, ## args))
#endif /* __XFS_ERROR_H__ */
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 6dba78199fa..3b14427ee12 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -227,7 +227,7 @@ xfs_efi_item_committing(xfs_efi_log_item_t *efip, xfs_lsn_t lsn)
/*
* This is the ops vector shared by all efi log items.
*/
-STATIC struct xfs_item_ops xfs_efi_item_ops = {
+static struct xfs_item_ops xfs_efi_item_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_efi_item_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_efi_item_format,
@@ -525,7 +525,7 @@ xfs_efd_item_committing(xfs_efd_log_item_t *efip, xfs_lsn_t lsn)
/*
* This is the ops vector shared by all efd log items.
*/
-STATIC struct xfs_item_ops xfs_efd_item_ops = {
+static struct xfs_item_ops xfs_efd_item_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_efd_item_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_efd_item_format,
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index c064e72ada9..32c37c1c47a 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -250,8 +250,7 @@ xfs_growfs_data_private(
block->bb_numrecs = cpu_to_be16(1);
block->bb_leftsib = cpu_to_be32(NULLAGBLOCK);
block->bb_rightsib = cpu_to_be32(NULLAGBLOCK);
- arec = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_alloc,
- block, 1, mp->m_alloc_mxr[0]);
+ arec = XFS_BTREE_REC_ADDR(xfs_alloc, block, 1);
arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
arec->ar_blockcount = cpu_to_be32(
agsize - be32_to_cpu(arec->ar_startblock));
@@ -272,8 +271,7 @@ xfs_growfs_data_private(
block->bb_numrecs = cpu_to_be16(1);
block->bb_leftsib = cpu_to_be32(NULLAGBLOCK);
block->bb_rightsib = cpu_to_be32(NULLAGBLOCK);
- arec = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_alloc,
- block, 1, mp->m_alloc_mxr[0]);
+ arec = XFS_BTREE_REC_ADDR(xfs_alloc, block, 1);
arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
arec->ar_blockcount = cpu_to_be32(
agsize - be32_to_cpu(arec->ar_startblock));
@@ -460,7 +458,7 @@ xfs_fs_counts(
{
unsigned long s;
- xfs_icsb_sync_counters_lazy(mp);
+ xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);
s = XFS_SB_LOCK(mp);
cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
cnt->freertx = mp->m_sb.sb_frextents;
@@ -491,7 +489,7 @@ xfs_reserve_blocks(
__uint64_t *inval,
xfs_fsop_resblks_t *outval)
{
- __int64_t lcounter, delta;
+ __int64_t lcounter, delta, fdblks_delta;
__uint64_t request;
unsigned long s;
@@ -504,17 +502,35 @@ xfs_reserve_blocks(
}
request = *inval;
+
+ /*
+ * With per-cpu counters, this becomes an interesting
+ * problem. we needto work out if we are freeing or allocation
+ * blocks first, then we can do the modification as necessary.
+ *
+ * We do this under the XFS_SB_LOCK so that if we are near
+ * ENOSPC, we will hold out any changes while we work out
+ * what to do. This means that the amount of free space can
+ * change while we do this, so we need to retry if we end up
+ * trying to reserve more space than is available.
+ *
+ * We also use the xfs_mod_incore_sb() interface so that we
+ * don't have to care about whether per cpu counter are
+ * enabled, disabled or even compiled in....
+ */
+retry:
s = XFS_SB_LOCK(mp);
+ xfs_icsb_sync_counters_flags(mp, XFS_ICSB_SB_LOCKED);
/*
* If our previous reservation was larger than the current value,
* then move any unused blocks back to the free pool.
*/
-
+ fdblks_delta = 0;
if (mp->m_resblks > request) {
lcounter = mp->m_resblks_avail - request;
if (lcounter > 0) { /* release unused blocks */
- mp->m_sb.sb_fdblocks += lcounter;
+ fdblks_delta = lcounter;
mp->m_resblks_avail -= lcounter;
}
mp->m_resblks = request;
@@ -522,24 +538,50 @@ xfs_reserve_blocks(
__int64_t free;
free = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
+ if (!free)
+ goto out; /* ENOSPC and fdblks_delta = 0 */
+
delta = request - mp->m_resblks;
lcounter = free - delta;
if (lcounter < 0) {
/* We can't satisfy the request, just get what we can */
mp->m_resblks += free;
mp->m_resblks_avail += free;
+ fdblks_delta = -free;
mp->m_sb.sb_fdblocks = XFS_ALLOC_SET_ASIDE(mp);
} else {
+ fdblks_delta = -delta;
mp->m_sb.sb_fdblocks =
lcounter + XFS_ALLOC_SET_ASIDE(mp);
mp->m_resblks = request;
mp->m_resblks_avail += delta;
}
}
-
+out:
outval->resblks = mp->m_resblks;
outval->resblks_avail = mp->m_resblks_avail;
XFS_SB_UNLOCK(mp, s);
+
+ if (fdblks_delta) {
+ /*
+ * If we are putting blocks back here, m_resblks_avail is
+ * already at it's max so this will put it in the free pool.
+ *
+ * If we need space, we'll either succeed in getting it
+ * from the free block count or we'll get an enospc. If
+ * we get a ENOSPC, it means things changed while we were
+ * calculating fdblks_delta and so we should try again to
+ * see if there is anything left to reserve.
+ *
+ * Don't set the reserved flag here - we don't want to reserve
+ * the extra reserve blocks from the reserve.....
+ */
+ int error;
+ error = xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, fdblks_delta, 0);
+ if (error == ENOSPC)
+ goto retry;
+ }
+
return 0;
}
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index a446e5a115c..b5feb3e7711 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -342,7 +342,7 @@ xfs_ialloc_ag_alloc(
return 0;
}
-STATIC __inline xfs_agnumber_t
+STATIC_INLINE xfs_agnumber_t
xfs_ialloc_next_ag(
xfs_mount_t *mp)
{
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h
index 2c0e49893ff..bf8e9aff272 100644
--- a/fs/xfs/xfs_ialloc_btree.h
+++ b/fs/xfs/xfs_ialloc_btree.h
@@ -89,7 +89,6 @@ typedef struct xfs_btree_sblock xfs_inobt_block_t;
/*
* Real block structures have a size equal to the disk block size.
*/
-#define XFS_INOBT_BLOCK_SIZE(lev,cur) (1 << (cur)->bc_blocklog)
#define XFS_INOBT_BLOCK_MAXRECS(lev,cur) ((cur)->bc_mp->m_inobt_mxr[lev != 0])
#define XFS_INOBT_BLOCK_MINRECS(lev,cur) ((cur)->bc_mp->m_inobt_mnr[lev != 0])
#define XFS_INOBT_IS_LAST_REC(cur) \
@@ -110,14 +109,13 @@ typedef struct xfs_btree_sblock xfs_inobt_block_t;
* Record, key, and pointer address macros for btree blocks.
*/
#define XFS_INOBT_REC_ADDR(bb,i,cur) \
- (XFS_BTREE_REC_ADDR(XFS_INOBT_BLOCK_SIZE(0,cur), xfs_inobt, bb, \
- i, XFS_INOBT_BLOCK_MAXRECS(0, cur)))
+ (XFS_BTREE_REC_ADDR(xfs_inobt, bb, i))
+
#define XFS_INOBT_KEY_ADDR(bb,i,cur) \
- (XFS_BTREE_KEY_ADDR(XFS_INOBT_BLOCK_SIZE(1,cur), xfs_inobt, bb, \
- i, XFS_INOBT_BLOCK_MAXRECS(1, cur)))
+ (XFS_BTREE_KEY_ADDR(xfs_inobt, bb, i))
#define XFS_INOBT_PTR_ADDR(bb,i,cur) \
- (XFS_BTREE_PTR_ADDR(XFS_INOBT_BLOCK_SIZE(1,cur), xfs_inobt, bb, \
+ (XFS_BTREE_PTR_ADDR(xfs_inobt, bb, \
i, XFS_INOBT_BLOCK_MAXRECS(1, cur)))
/*
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 44dfac52128..3da9829c19d 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -47,7 +47,6 @@
#include "xfs_utils.h"
#include "xfs_dir2_trace.h"
#include "xfs_quota.h"
-#include "xfs_mac.h"
#include "xfs_acl.h"
@@ -1699,8 +1698,7 @@ xfs_itruncate_finish(
* Duplicate the transaction that has the permanent
* reservation and commit the old transaction.
*/
- error = xfs_bmap_finish(tp, &free_list, first_block,
- &committed);
+ error = xfs_bmap_finish(tp, &free_list, &committed);
ntp = *tp;
if (error) {
/*
@@ -1810,7 +1808,7 @@ xfs_igrow_start(
* and any blocks between the old and new file sizes.
*/
error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size,
- ip->i_d.di_size, new_size);
+ ip->i_d.di_size);
return error;
}
@@ -2125,7 +2123,7 @@ xfs_iunlink_remove(
return 0;
}
-static __inline__ int xfs_inode_clean(xfs_inode_t *ip)
+STATIC_INLINE int xfs_inode_clean(xfs_inode_t *ip)
{
return (((ip->i_itemp == NULL) ||
!(ip->i_itemp->ili_format.ilf_fields & XFS_ILOG_ALL)) &&
@@ -2707,10 +2705,24 @@ xfs_idestroy(
ktrace_free(ip->i_dir_trace);
#endif
if (ip->i_itemp) {
- /* XXXdpd should be able to assert this but shutdown
- * is leaving the AIL behind. */
- ASSERT(((ip->i_itemp->ili_item.li_flags & XFS_LI_IN_AIL) == 0) ||
- XFS_FORCED_SHUTDOWN(ip->i_mount));
+ /*
+ * Only if we are shutting down the fs will we see an
+ * inode still in the AIL. If it is there, we should remove
+ * it to prevent a use-after-free from occurring.
+ */
+ xfs_mount_t *mp = ip->i_mount;
+ xfs_log_item_t *lip = &ip->i_itemp->ili_item;
+ int s;
+
+ ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
+ XFS_FORCED_SHUTDOWN(ip->i_mount));
+ if (lip->li_flags & XFS_LI_IN_AIL) {
+ AIL_LOCK(mp, s);
+ if (lip->li_flags & XFS_LI_IN_AIL)
+ xfs_trans_delete_ail(mp, lip, s);
+ else
+ AIL_UNLOCK(mp, s);
+ }
xfs_inode_item_destroy(ip);
}
kmem_zone_free(xfs_inode_zone, ip);
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index a7a92251eb5..565d470a6b4 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -887,7 +887,7 @@ xfs_inode_item_committing(
/*
* This is the ops vector shared by all buf log items.
*/
-STATIC struct xfs_item_ops xfs_inode_item_ops = {
+static struct xfs_item_ops xfs_inode_item_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_inode_item_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_inode_item_format,
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 19655124da7..cc6a7b5a991 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -43,8 +43,6 @@
#include "xfs_itable.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_trans_space.h"
@@ -542,7 +540,7 @@ xfs_iomap_write_direct(
/*
* Complete the transaction
*/
- error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
+ error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error)
goto error0;
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
@@ -838,8 +836,7 @@ xfs_iomap_write_allocate(
if (error)
goto trans_cancel;
- error = xfs_bmap_finish(&tp, &free_list,
- first_block, &committed);
+ error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error)
goto trans_cancel;
@@ -947,8 +944,7 @@ xfs_iomap_write_unwritten(
if (error)
goto error_on_bmapi_transaction;
- error = xfs_bmap_finish(&(tp), &(free_list),
- firstfsb, &committed);
+ error = xfs_bmap_finish(&(tp), &(free_list), &committed);
if (error)
goto error_on_bmapi_transaction;
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 3cb678e3a13..ca74d3f5910 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1514,7 +1514,6 @@ xlog_recover_reorder_trans(
{
xlog_recover_item_t *first_item, *itemq, *itemq_next;
xfs_buf_log_format_t *buf_f;
- xfs_buf_log_format_v1_t *obuf_f;
ushort flags = 0;
first_item = itemq = trans->r_itemq;
@@ -1522,29 +1521,16 @@ xlog_recover_reorder_trans(
do {
itemq_next = itemq->ri_next;
buf_f = (xfs_buf_log_format_t *)itemq->ri_buf[0].i_addr;
- switch (ITEM_TYPE(itemq)) {
- case XFS_LI_BUF:
- flags = buf_f->blf_flags;
- break;
- case XFS_LI_6_1_BUF:
- case XFS_LI_5_3_BUF:
- obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
- flags = obuf_f->blf_flags;
- break;
- }
switch (ITEM_TYPE(itemq)) {
case XFS_LI_BUF:
- case XFS_LI_6_1_BUF:
- case XFS_LI_5_3_BUF:
+ flags = buf_f->blf_flags;
if (!(flags & XFS_BLI_CANCEL)) {
xlog_recover_insert_item_frontq(&trans->r_itemq,
itemq);
break;
}
case XFS_LI_INODE:
- case XFS_LI_6_1_INODE:
- case XFS_LI_5_3_INODE:
case XFS_LI_DQUOT:
case XFS_LI_QUOTAOFF:
case XFS_LI_EFD:
@@ -1583,7 +1569,6 @@ xlog_recover_do_buffer_pass1(
xfs_buf_cancel_t *nextp;
xfs_buf_cancel_t *prevp;
xfs_buf_cancel_t **bucket;
- xfs_buf_log_format_v1_t *obuf_f;
xfs_daddr_t blkno = 0;
uint len = 0;
ushort flags = 0;
@@ -1594,13 +1579,6 @@ xlog_recover_do_buffer_pass1(
len = buf_f->blf_len;
flags = buf_f->blf_flags;
break;
- case XFS_LI_6_1_BUF:
- case XFS_LI_5_3_BUF:
- obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
- blkno = (xfs_daddr_t) obuf_f->blf_blkno;
- len = obuf_f->blf_len;
- flags = obuf_f->blf_flags;
- break;
}
/*
@@ -1746,7 +1724,6 @@ xlog_recover_do_buffer_pass2(
xlog_t *log,
xfs_buf_log_format_t *buf_f)
{
- xfs_buf_log_format_v1_t *obuf_f;
xfs_daddr_t blkno = 0;
ushort flags = 0;
uint len = 0;
@@ -1757,13 +1734,6 @@ xlog_recover_do_buffer_pass2(
flags = buf_f->blf_flags;
len = buf_f->blf_len;
break;
- case XFS_LI_6_1_BUF:
- case XFS_LI_5_3_BUF:
- obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
- blkno = (xfs_daddr_t) obuf_f->blf_blkno;
- flags = obuf_f->blf_flags;
- len = (xfs_daddr_t) obuf_f->blf_len;
- break;
}
return xlog_check_buffer_cancelled(log, blkno, len, flags);
@@ -1799,7 +1769,6 @@ xlog_recover_do_inode_buffer(
int inodes_per_buf;
xfs_agino_t *logged_nextp;
xfs_agino_t *buffer_nextp;
- xfs_buf_log_format_v1_t *obuf_f;
unsigned int *data_map = NULL;
unsigned int map_size = 0;
@@ -1808,12 +1777,6 @@ xlog_recover_do_inode_buffer(
data_map = buf_f->blf_data_map;
map_size = buf_f->blf_map_size;
break;
- case XFS_LI_6_1_BUF:
- case XFS_LI_5_3_BUF:
- obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
- data_map = obuf_f->blf_data_map;
- map_size = obuf_f->blf_map_size;
- break;
}
/*
* Set the variables corresponding to the current region to
@@ -1912,7 +1875,6 @@ xlog_recover_do_reg_buffer(
int i;
int bit;
int nbits;
- xfs_buf_log_format_v1_t *obuf_f;
unsigned int *data_map = NULL;
unsigned int map_size = 0;
int error;
@@ -1922,12 +1884,6 @@ xlog_recover_do_reg_buffer(
data_map = buf_f->blf_data_map;
map_size = buf_f->blf_map_size;
break;
- case XFS_LI_6_1_BUF:
- case XFS_LI_5_3_BUF:
- obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
- data_map = obuf_f->blf_data_map;
- map_size = obuf_f->blf_map_size;
- break;
}
bit = 0;
i = 1; /* 0 is the buf format structure */
@@ -2160,7 +2116,6 @@ xlog_recover_do_buffer_trans(
int pass)
{
xfs_buf_log_format_t *buf_f;
- xfs_buf_log_format_v1_t *obuf_f;
xfs_mount_t *mp;
xfs_buf_t *bp;
int error;
@@ -2197,13 +2152,6 @@ xlog_recover_do_buffer_trans(
len = buf_f->blf_len;
flags = buf_f->blf_flags;
break;
- case XFS_LI_6_1_BUF:
- case XFS_LI_5_3_BUF:
- obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
- blkno = obuf_f->blf_blkno;
- len = obuf_f->blf_len;
- flags = obuf_f->blf_flags;
- break;
default:
xfs_fs_cmn_err(CE_ALERT, log->l_mp,
"xfs_log_recover: unknown buffer type 0x%x, logdev %s",
@@ -2830,9 +2778,7 @@ xlog_recover_do_trans(
* where xfs_daddr_t is 32-bits but mount will warn us
* off a > 1 TB filesystem before we get here.
*/
- if ((ITEM_TYPE(item) == XFS_LI_BUF) ||
- (ITEM_TYPE(item) == XFS_LI_6_1_BUF) ||
- (ITEM_TYPE(item) == XFS_LI_5_3_BUF)) {
+ if ((ITEM_TYPE(item) == XFS_LI_BUF)) {
if ((error = xlog_recover_do_buffer_trans(log, item,
pass)))
break;
@@ -3902,6 +3848,9 @@ xlog_do_recover(
ASSERT(XFS_SB_GOOD_VERSION(sbp));
xfs_buf_relse(bp);
+ /* We've re-read the superblock so re-initialize per-cpu counters */
+ xfs_icsb_reinit_counters(log->l_mp);
+
xlog_recover_check_summary(log);
/* Normal transactions can now occur */
diff --git a/fs/xfs/xfs_mac.h b/fs/xfs/xfs_mac.h
deleted file mode 100644
index 18e0e98e03d..00000000000
--- a/fs/xfs/xfs_mac.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2001-2002,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#ifndef __XFS_MAC_H__
-#define __XFS_MAC_H__
-
-/*
- * Mandatory Access Control
- *
- * Layout of a composite MAC label:
- * ml_list contains the list of categories (MSEN) followed by the list of
- * divisions (MINT). This is actually a header for the data structure which
- * will have an ml_list with more than one element.
- *
- * -------------------------------
- * | ml_msen_type | ml_mint_type |
- * -------------------------------
- * | ml_level | ml_grade |
- * -------------------------------
- * | ml_catcount |
- * -------------------------------
- * | ml_divcount |
- * -------------------------------
- * | category 1 |
- * | . . . |
- * | category N | (where N = ml_catcount)
- * -------------------------------
- * | division 1 |
- * | . . . |
- * | division M | (where M = ml_divcount)
- * -------------------------------
- */
-#define XFS_MAC_MAX_SETS 250
-typedef struct xfs_mac_label {
- __uint8_t ml_msen_type; /* MSEN label type */
- __uint8_t ml_mint_type; /* MINT label type */
- __uint8_t ml_level; /* Hierarchical level */
- __uint8_t ml_grade; /* Hierarchical grade */
- __uint16_t ml_catcount; /* Category count */
- __uint16_t ml_divcount; /* Division count */
- /* Category set, then Division set */
- __uint16_t ml_list[XFS_MAC_MAX_SETS];
-} xfs_mac_label_t;
-
-/* MSEN label type names. Choose an upper case ASCII character. */
-#define XFS_MSEN_ADMIN_LABEL 'A' /* Admin: low<admin != tcsec<high */
-#define XFS_MSEN_EQUAL_LABEL 'E' /* Wildcard - always equal */
-#define XFS_MSEN_HIGH_LABEL 'H' /* System High - always dominates */
-#define XFS_MSEN_MLD_HIGH_LABEL 'I' /* System High, multi-level dir */
-#define XFS_MSEN_LOW_LABEL 'L' /* System Low - always dominated */
-#define XFS_MSEN_MLD_LABEL 'M' /* TCSEC label on a multi-level dir */
-#define XFS_MSEN_MLD_LOW_LABEL 'N' /* System Low, multi-level dir */
-#define XFS_MSEN_TCSEC_LABEL 'T' /* TCSEC label */
-#define XFS_MSEN_UNKNOWN_LABEL 'U' /* unknown label */
-
-/* MINT label type names. Choose a lower case ASCII character. */
-#define XFS_MINT_BIBA_LABEL 'b' /* Dual of a TCSEC label */
-#define XFS_MINT_EQUAL_LABEL 'e' /* Wildcard - always equal */
-#define XFS_MINT_HIGH_LABEL 'h' /* High Grade - always dominates */
-#define XFS_MINT_LOW_LABEL 'l' /* Low Grade - always dominated */
-
-/* On-disk XFS extended attribute names */
-#define SGI_MAC_FILE "SGI_MAC_FILE"
-#define SGI_MAC_FILE_SIZE (sizeof(SGI_MAC_FILE)-1)
-
-
-#ifdef __KERNEL__
-
-#ifdef CONFIG_FS_POSIX_MAC
-
-/* NOT YET IMPLEMENTED */
-
-#define MACEXEC 00100
-#define MACWRITE 00200
-#define MACREAD 00400
-
-struct xfs_inode;
-extern int xfs_mac_iaccess(struct xfs_inode *, mode_t, cred_t *);
-
-#define _MAC_XFS_IACCESS(i,m,c) (xfs_mac_iaccess(i,m,c))
-#define _MAC_VACCESS(v,c,m) (xfs_mac_vaccess(v,c,m))
-#define _MAC_EXISTS xfs_mac_vhaslabel
-
-#else
-#define _MAC_XFS_IACCESS(i,m,c) (0)
-#define _MAC_VACCESS(v,c,m) (0)
-#define _MAC_EXISTS (NULL)
-#endif
-
-#endif /* __KERNEL__ */
-
-#endif /* __XFS_MAC_H__ */
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 9dfae18d995..3bed0cf0d8a 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -52,21 +52,19 @@ STATIC void xfs_unmountfs_wait(xfs_mount_t *);
#ifdef HAVE_PERCPU_SB
STATIC void xfs_icsb_destroy_counters(xfs_mount_t *);
-STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t, int);
+STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
+ int, int);
STATIC void xfs_icsb_sync_counters(xfs_mount_t *);
STATIC int xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t,
- int, int);
-STATIC int xfs_icsb_modify_counters_locked(xfs_mount_t *, xfs_sb_field_t,
- int, int);
+ int64_t, int);
STATIC int xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
#else
#define xfs_icsb_destroy_counters(mp) do { } while (0)
-#define xfs_icsb_balance_counter(mp, a, b) do { } while (0)
+#define xfs_icsb_balance_counter(mp, a, b, c) do { } while (0)
#define xfs_icsb_sync_counters(mp) do { } while (0)
#define xfs_icsb_modify_counters(mp, a, b, c) do { } while (0)
-#define xfs_icsb_modify_counters_locked(mp, a, b, c) do { } while (0)
#endif
@@ -545,9 +543,8 @@ xfs_readsb(xfs_mount_t *mp, int flags)
ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
}
- xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
- xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
- xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
+ /* Initialize per-cpu counters */
+ xfs_icsb_reinit_counters(mp);
mp->m_sb_bp = bp;
xfs_buf_relse(bp);
@@ -1254,8 +1251,11 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
* The SB_LOCK must be held when this routine is called.
*/
int
-xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field,
- int delta, int rsvd)
+xfs_mod_incore_sb_unlocked(
+ xfs_mount_t *mp,
+ xfs_sb_field_t field,
+ int64_t delta,
+ int rsvd)
{
int scounter; /* short counter for 32 bit fields */
long long lcounter; /* long counter for 64 bit fields */
@@ -1287,7 +1287,6 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field,
mp->m_sb.sb_ifree = lcounter;
return 0;
case XFS_SBS_FDBLOCKS:
-
lcounter = (long long)
mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
@@ -1418,7 +1417,11 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field,
* routine to do the work.
*/
int
-xfs_mod_incore_sb(xfs_mount_t *mp, xfs_sb_field_t field, int delta, int rsvd)
+xfs_mod_incore_sb(
+ xfs_mount_t *mp,
+ xfs_sb_field_t field,
+ int64_t delta,
+ int rsvd)
{
unsigned long s;
int status;
@@ -1485,9 +1488,11 @@ xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd)
case XFS_SBS_IFREE:
case XFS_SBS_FDBLOCKS:
if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
- status = xfs_icsb_modify_counters_locked(mp,
+ XFS_SB_UNLOCK(mp, s);
+ status = xfs_icsb_modify_counters(mp,
msbp->msb_field,
msbp->msb_delta, rsvd);
+ s = XFS_SB_LOCK(mp);
break;
}
/* FALLTHROUGH */
@@ -1521,11 +1526,12 @@ xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd)
case XFS_SBS_IFREE:
case XFS_SBS_FDBLOCKS:
if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
- status =
- xfs_icsb_modify_counters_locked(mp,
+ XFS_SB_UNLOCK(mp, s);
+ status = xfs_icsb_modify_counters(mp,
msbp->msb_field,
-(msbp->msb_delta),
rsvd);
+ s = XFS_SB_LOCK(mp);
break;
}
/* FALLTHROUGH */
@@ -1733,14 +1739,17 @@ xfs_icsb_cpu_notify(
memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
break;
case CPU_ONLINE:
- xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
- xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
- xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
+ xfs_icsb_lock(mp);
+ xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0, 0);
+ xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0, 0);
+ xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0, 0);
+ xfs_icsb_unlock(mp);
break;
case CPU_DEAD:
/* Disable all the counters, then fold the dead cpu's
* count into the total on the global superblock and
* re-enable the counters. */
+ xfs_icsb_lock(mp);
s = XFS_SB_LOCK(mp);
xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT);
xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
@@ -1752,10 +1761,14 @@ xfs_icsb_cpu_notify(
memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
- xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, XFS_ICSB_SB_LOCKED);
- xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, XFS_ICSB_SB_LOCKED);
- xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, XFS_ICSB_SB_LOCKED);
+ xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT,
+ XFS_ICSB_SB_LOCKED, 0);
+ xfs_icsb_balance_counter(mp, XFS_SBS_IFREE,
+ XFS_ICSB_SB_LOCKED, 0);
+ xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS,
+ XFS_ICSB_SB_LOCKED, 0);
XFS_SB_UNLOCK(mp, s);
+ xfs_icsb_unlock(mp);
break;
}
@@ -1784,6 +1797,9 @@ xfs_icsb_init_counters(
cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
}
+
+ mutex_init(&mp->m_icsb_mutex);
+
/*
* start with all counters disabled so that the
* initial balance kicks us off correctly
@@ -1792,6 +1808,22 @@ xfs_icsb_init_counters(
return 0;
}
+void
+xfs_icsb_reinit_counters(
+ xfs_mount_t *mp)
+{
+ xfs_icsb_lock(mp);
+ /*
+ * start with all counters disabled so that the
+ * initial balance kicks us off correctly
+ */
+ mp->m_icsb_counters = -1;
+ xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0, 0);
+ xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0, 0);
+ xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0, 0);
+ xfs_icsb_unlock(mp);
+}
+
STATIC void
xfs_icsb_destroy_counters(
xfs_mount_t *mp)
@@ -1800,9 +1832,10 @@ xfs_icsb_destroy_counters(
unregister_hotcpu_notifier(&mp->m_icsb_notifier);
free_percpu(mp->m_sb_cnts);
}
+ mutex_destroy(&mp->m_icsb_mutex);
}
-STATIC inline void
+STATIC_INLINE void
xfs_icsb_lock_cntr(
xfs_icsb_cnts_t *icsbp)
{
@@ -1811,7 +1844,7 @@ xfs_icsb_lock_cntr(
}
}
-STATIC inline void
+STATIC_INLINE void
xfs_icsb_unlock_cntr(
xfs_icsb_cnts_t *icsbp)
{
@@ -1819,7 +1852,7 @@ xfs_icsb_unlock_cntr(
}
-STATIC inline void
+STATIC_INLINE void
xfs_icsb_lock_all_counters(
xfs_mount_t *mp)
{
@@ -1832,7 +1865,7 @@ xfs_icsb_lock_all_counters(
}
}
-STATIC inline void
+STATIC_INLINE void
xfs_icsb_unlock_all_counters(
xfs_mount_t *mp)
{
@@ -1888,6 +1921,17 @@ xfs_icsb_disable_counter(
ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
+ /*
+ * If we are already disabled, then there is nothing to do
+ * here. We check before locking all the counters to avoid
+ * the expensive lock operation when being called in the
+ * slow path and the counter is already disabled. This is
+ * safe because the only time we set or clear this state is under
+ * the m_icsb_mutex.
+ */
+ if (xfs_icsb_counter_disabled(mp, field))
+ return 0;
+
xfs_icsb_lock_all_counters(mp);
if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
/* drain back to superblock */
@@ -1948,8 +1992,8 @@ xfs_icsb_enable_counter(
xfs_icsb_unlock_all_counters(mp);
}
-STATIC void
-xfs_icsb_sync_counters_int(
+void
+xfs_icsb_sync_counters_flags(
xfs_mount_t *mp,
int flags)
{
@@ -1981,40 +2025,39 @@ STATIC void
xfs_icsb_sync_counters(
xfs_mount_t *mp)
{
- xfs_icsb_sync_counters_int(mp, 0);
-}
-
-/*
- * lazy addition used for things like df, background sb syncs, etc
- */
-void
-xfs_icsb_sync_counters_lazy(
- xfs_mount_t *mp)
-{
- xfs_icsb_sync_counters_int(mp, XFS_ICSB_LAZY_COUNT);
+ xfs_icsb_sync_counters_flags(mp, 0);
}
/*
* Balance and enable/disable counters as necessary.
*
- * Thresholds for re-enabling counters are somewhat magic.
- * inode counts are chosen to be the same number as single
- * on disk allocation chunk per CPU, and free blocks is
- * something far enough zero that we aren't going thrash
- * when we get near ENOSPC.
+ * Thresholds for re-enabling counters are somewhat magic. inode counts are
+ * chosen to be the same number as single on disk allocation chunk per CPU, and
+ * free blocks is something far enough zero that we aren't going thrash when we
+ * get near ENOSPC. We also need to supply a minimum we require per cpu to
+ * prevent looping endlessly when xfs_alloc_space asks for more than will
+ * be distributed to a single CPU but each CPU has enough blocks to be
+ * reenabled.
+ *
+ * Note that we can be called when counters are already disabled.
+ * xfs_icsb_disable_counter() optimises the counter locking in this case to
+ * prevent locking every per-cpu counter needlessly.
*/
-#define XFS_ICSB_INO_CNTR_REENABLE 64
+
+#define XFS_ICSB_INO_CNTR_REENABLE (uint64_t)64
#define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \
- (512 + XFS_ALLOC_SET_ASIDE(mp))
+ (uint64_t)(512 + XFS_ALLOC_SET_ASIDE(mp))
STATIC void
xfs_icsb_balance_counter(
xfs_mount_t *mp,
xfs_sb_field_t field,
- int flags)
+ int flags,
+ int min_per_cpu)
{
uint64_t count, resid;
int weight = num_online_cpus();
int s;
+ uint64_t min = (uint64_t)min_per_cpu;
if (!(flags & XFS_ICSB_SB_LOCKED))
s = XFS_SB_LOCK(mp);
@@ -2027,19 +2070,19 @@ xfs_icsb_balance_counter(
case XFS_SBS_ICOUNT:
count = mp->m_sb.sb_icount;
resid = do_div(count, weight);
- if (count < XFS_ICSB_INO_CNTR_REENABLE)
+ if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
goto out;
break;
case XFS_SBS_IFREE:
count = mp->m_sb.sb_ifree;
resid = do_div(count, weight);
- if (count < XFS_ICSB_INO_CNTR_REENABLE)
+ if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
goto out;
break;
case XFS_SBS_FDBLOCKS:
count = mp->m_sb.sb_fdblocks;
resid = do_div(count, weight);
- if (count < XFS_ICSB_FDBLK_CNTR_REENABLE(mp))
+ if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp)))
goto out;
break;
default:
@@ -2054,32 +2097,39 @@ out:
XFS_SB_UNLOCK(mp, s);
}
-STATIC int
-xfs_icsb_modify_counters_int(
+int
+xfs_icsb_modify_counters(
xfs_mount_t *mp,
xfs_sb_field_t field,
- int delta,
- int rsvd,
- int flags)
+ int64_t delta,
+ int rsvd)
{
xfs_icsb_cnts_t *icsbp;
long long lcounter; /* long counter for 64 bit fields */
- int cpu, s, locked = 0;
- int ret = 0, balance_done = 0;
+ int cpu, ret = 0, s;
+ might_sleep();
again:
cpu = get_cpu();
- icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu),
- xfs_icsb_lock_cntr(icsbp);
+ icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu);
+
+ /*
+ * if the counter is disabled, go to slow path
+ */
if (unlikely(xfs_icsb_counter_disabled(mp, field)))
goto slow_path;
+ xfs_icsb_lock_cntr(icsbp);
+ if (unlikely(xfs_icsb_counter_disabled(mp, field))) {
+ xfs_icsb_unlock_cntr(icsbp);
+ goto slow_path;
+ }
switch (field) {
case XFS_SBS_ICOUNT:
lcounter = icsbp->icsb_icount;
lcounter += delta;
if (unlikely(lcounter < 0))
- goto slow_path;
+ goto balance_counter;
icsbp->icsb_icount = lcounter;
break;
@@ -2087,7 +2137,7 @@ again:
lcounter = icsbp->icsb_ifree;
lcounter += delta;
if (unlikely(lcounter < 0))
- goto slow_path;
+ goto balance_counter;
icsbp->icsb_ifree = lcounter;
break;
@@ -2097,7 +2147,7 @@ again:
lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
lcounter += delta;
if (unlikely(lcounter < 0))
- goto slow_path;
+ goto balance_counter;
icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
break;
default:
@@ -2106,72 +2156,78 @@ again:
}
xfs_icsb_unlock_cntr(icsbp);
put_cpu();
- if (locked)
- XFS_SB_UNLOCK(mp, s);
return 0;
- /*
- * The slow path needs to be run with the SBLOCK
- * held so that we prevent other threads from
- * attempting to run this path at the same time.
- * this provides exclusion for the balancing code,
- * and exclusive fallback if the balance does not
- * provide enough resources to continue in an unlocked
- * manner.
- */
slow_path:
- xfs_icsb_unlock_cntr(icsbp);
put_cpu();
- /* need to hold superblock incase we need
- * to disable a counter */
- if (!(flags & XFS_ICSB_SB_LOCKED)) {
- s = XFS_SB_LOCK(mp);
- locked = 1;
- flags |= XFS_ICSB_SB_LOCKED;
- }
- if (!balance_done) {
- xfs_icsb_balance_counter(mp, field, flags);
- balance_done = 1;
+ /*
+ * serialise with a mutex so we don't burn lots of cpu on
+ * the superblock lock. We still need to hold the superblock
+ * lock, however, when we modify the global structures.
+ */
+ xfs_icsb_lock(mp);
+
+ /*
+ * Now running atomically.
+ *
+ * If the counter is enabled, someone has beaten us to rebalancing.
+ * Drop the lock and try again in the fast path....
+ */
+ if (!(xfs_icsb_counter_disabled(mp, field))) {
+ xfs_icsb_unlock(mp);
goto again;
- } else {
- /*
- * we might not have enough on this local
- * cpu to allocate for a bulk request.
- * We need to drain this field from all CPUs
- * and disable the counter fastpath
- */
- xfs_icsb_disable_counter(mp, field);
}
+ /*
+ * The counter is currently disabled. Because we are
+ * running atomically here, we know a rebalance cannot
+ * be in progress. Hence we can go straight to operating
+ * on the global superblock. We do not call xfs_mod_incore_sb()
+ * here even though we need to get the SB_LOCK. Doing so
+ * will cause us to re-enter this function and deadlock.
+ * Hence we get the SB_LOCK ourselves and then call
+ * xfs_mod_incore_sb_unlocked() as the unlocked path operates
+ * directly on the global counters.
+ */
+ s = XFS_SB_LOCK(mp);
ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
+ XFS_SB_UNLOCK(mp, s);
- if (locked)
- XFS_SB_UNLOCK(mp, s);
+ /*
+ * Now that we've modified the global superblock, we
+ * may be able to re-enable the distributed counters
+ * (e.g. lots of space just got freed). After that
+ * we are done.
+ */
+ if (ret != ENOSPC)
+ xfs_icsb_balance_counter(mp, field, 0, 0);
+ xfs_icsb_unlock(mp);
return ret;
-}
-STATIC int
-xfs_icsb_modify_counters(
- xfs_mount_t *mp,
- xfs_sb_field_t field,
- int delta,
- int rsvd)
-{
- return xfs_icsb_modify_counters_int(mp, field, delta, rsvd, 0);
-}
+balance_counter:
+ xfs_icsb_unlock_cntr(icsbp);
+ put_cpu();
-/*
- * Called when superblock is already locked
- */
-STATIC int
-xfs_icsb_modify_counters_locked(
- xfs_mount_t *mp,
- xfs_sb_field_t field,
- int delta,
- int rsvd)
-{
- return xfs_icsb_modify_counters_int(mp, field, delta,
- rsvd, XFS_ICSB_SB_LOCKED);
+ /*
+ * We may have multiple threads here if multiple per-cpu
+ * counters run dry at the same time. This will mean we can
+ * do more balances than strictly necessary but it is not
+ * the common slowpath case.
+ */
+ xfs_icsb_lock(mp);
+
+ /*
+ * running atomically.
+ *
+ * This will leave the counter in the correct state for future
+ * accesses. After the rebalance, we simply try again and our retry
+ * will either succeed through the fast path or slow path without
+ * another balance operation being required.
+ */
+ xfs_icsb_balance_counter(mp, field, 0, delta);
+ xfs_icsb_unlock(mp);
+ goto again;
}
+
#endif
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index e5f396ff9a3..82304b94646 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -18,6 +18,7 @@
#ifndef __XFS_MOUNT_H__
#define __XFS_MOUNT_H__
+
typedef struct xfs_trans_reservations {
uint tr_write; /* extent alloc trans */
uint tr_itruncate; /* truncate trans */
@@ -306,11 +307,13 @@ typedef struct xfs_icsb_cnts {
#define XFS_ICSB_LAZY_COUNT (1 << 1) /* accuracy not needed */
extern int xfs_icsb_init_counters(struct xfs_mount *);
-extern void xfs_icsb_sync_counters_lazy(struct xfs_mount *);
+extern void xfs_icsb_reinit_counters(struct xfs_mount *);
+extern void xfs_icsb_sync_counters_flags(struct xfs_mount *, int);
#else
#define xfs_icsb_init_counters(mp) (0)
-#define xfs_icsb_sync_counters_lazy(mp) do { } while (0)
+#define xfs_icsb_reinit_counters(mp) do { } while (0)
+#define xfs_icsb_sync_counters_flags(mp, flags) do { } while (0)
#endif
typedef struct xfs_mount {
@@ -419,6 +422,7 @@ typedef struct xfs_mount {
xfs_icsb_cnts_t *m_sb_cnts; /* per-cpu superblock counters */
unsigned long m_icsb_counters; /* disabled per-cpu counters */
struct notifier_block m_icsb_notifier; /* hotplug cpu notifier */
+ struct mutex m_icsb_mutex; /* balancer sync lock */
#endif
} xfs_mount_t;
@@ -563,11 +567,32 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
}
/*
+ * Per-cpu superblock locking functions
+ */
+#ifdef HAVE_PERCPU_SB
+STATIC_INLINE void
+xfs_icsb_lock(xfs_mount_t *mp)
+{
+ mutex_lock(&mp->m_icsb_mutex);
+}
+
+STATIC_INLINE void
+xfs_icsb_unlock(xfs_mount_t *mp)
+{
+ mutex_unlock(&mp->m_icsb_mutex);
+}
+#else
+#define xfs_icsb_lock(mp)
+#define xfs_icsb_unlock(mp)
+#endif
+
+/*
* This structure is for use by the xfs_mod_incore_sb_batch() routine.
+ * xfs_growfs can specify a few fields which are more than int limit
*/
typedef struct xfs_mod_sb {
xfs_sb_field_t msb_field; /* Field to modify, see below */
- int msb_delta; /* Change to make to specified field */
+ int64_t msb_delta; /* Change to make to specified field */
} xfs_mod_sb_t;
#define XFS_MOUNT_ILOCK(mp) mutex_lock(&((mp)->m_ilock))
@@ -585,17 +610,17 @@ extern int xfs_unmountfs(xfs_mount_t *, struct cred *);
extern void xfs_unmountfs_close(xfs_mount_t *, struct cred *);
extern int xfs_unmountfs_writesb(xfs_mount_t *);
extern int xfs_unmount_flush(xfs_mount_t *, int);
-extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int, int);
+extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
extern int xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t,
- int, int);
+ int64_t, int);
extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
uint, int);
extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
extern int xfs_readsb(xfs_mount_t *, int);
extern void xfs_freesb(xfs_mount_t *);
extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
-extern int xfs_syncsub(xfs_mount_t *, int, int, int *);
-extern int xfs_sync_inodes(xfs_mount_t *, int, int, int *);
+extern int xfs_syncsub(xfs_mount_t *, int, int *);
+extern int xfs_sync_inodes(xfs_mount_t *, int, int *);
extern xfs_agnumber_t xfs_initialize_perag(struct bhv_vfs *, xfs_mount_t *,
xfs_agnumber_t);
extern void xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t);
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index d98171deaa1..4c6573d784c 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -565,7 +565,7 @@ xfs_rename(
IHOLD(target_ip);
IHOLD(src_ip);
- error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+ error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error) {
xfs_bmap_cancel(&free_list);
xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 880c73271c0..6fff19dc3cf 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -147,7 +147,7 @@ xfs_growfs_rt_alloc(
/*
* Free any blocks freed up in the transaction, then commit.
*/
- error = xfs_bmap_finish(&tp, &flist, firstblock, &committed);
+ error = xfs_bmap_finish(&tp, &flist, &committed);
if (error)
goto error_exit;
xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
@@ -913,57 +913,6 @@ xfs_rtcheck_alloc_range(
}
#endif
-#ifdef DEBUG
-/*
- * Check whether the given block in the bitmap has the given value.
- */
-STATIC int /* 1 for matches, 0 for not */
-xfs_rtcheck_bit(
- xfs_mount_t *mp, /* file system mount structure */
- xfs_trans_t *tp, /* transaction pointer */
- xfs_rtblock_t start, /* bit (block) to check */
- int val) /* 1 for free, 0 for allocated */
-{
- int bit; /* bit number in the word */
- xfs_rtblock_t block; /* bitmap block number */
- xfs_buf_t *bp; /* buf for the block */
- xfs_rtword_t *bufp; /* pointer into the buffer */
- /* REFERENCED */
- int error; /* error value */
- xfs_rtword_t wdiff; /* difference between bit & expected */
- int word; /* word number in the buffer */
- xfs_rtword_t wval; /* word value from buffer */
-
- block = XFS_BITTOBLOCK(mp, start);
- error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
- bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
- word = XFS_BITTOWORD(mp, start);
- bit = (int)(start & (XFS_NBWORD - 1));
- wval = bufp[word];
- xfs_trans_brelse(tp, bp);
- wdiff = (wval ^ -val) & ((xfs_rtword_t)1 << bit);
- return !wdiff;
-}
-#endif /* DEBUG */
-
-#if 0
-/*
- * Check that the given extent (block range) is free already.
- */
-STATIC int /* error */
-xfs_rtcheck_free_range(
- xfs_mount_t *mp, /* file system mount point */
- xfs_trans_t *tp, /* transaction pointer */
- xfs_rtblock_t bno, /* starting block number of extent */
- xfs_extlen_t len, /* length of extent */
- int *stat) /* out: 1 for free, 0 for not */
-{
- xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */
-
- return xfs_rtcheck_range(mp, tp, bno, len, 1, &new, stat);
-}
-#endif
-
/*
* Check that the given range is either all allocated (val = 0) or
* all free (val = 1).
@@ -2382,60 +2331,3 @@ xfs_rtpick_extent(
*pick = b;
return 0;
}
-
-#ifdef DEBUG
-/*
- * Debug code: print out the value of a range in the bitmap.
- */
-void
-xfs_rtprint_range(
- xfs_mount_t *mp, /* file system mount structure */
- xfs_trans_t *tp, /* transaction pointer */
- xfs_rtblock_t start, /* starting block to print */
- xfs_extlen_t len) /* length to print */
-{
- xfs_extlen_t i; /* block number in the extent */
-
- cmn_err(CE_DEBUG, "%Ld: ", (long long)start);
- for (i = 0; i < len; i++)
- cmn_err(CE_DEBUG, "%d", xfs_rtcheck_bit(mp, tp, start + i, 1));
- cmn_err(CE_DEBUG, "\n");
-}
-
-/*
- * Debug code: print the summary file.
- */
-void
-xfs_rtprint_summary(
- xfs_mount_t *mp, /* file system mount structure */
- xfs_trans_t *tp) /* transaction pointer */
-{
- xfs_suminfo_t c; /* summary data */
- xfs_rtblock_t i; /* bitmap block number */
- int l; /* summary information level */
- int p; /* flag for printed anything */
- xfs_fsblock_t sb; /* summary block number */
- xfs_buf_t *sumbp; /* summary block buffer */
-
- sumbp = NULL;
- for (l = 0; l < mp->m_rsumlevels; l++) {
- for (p = 0, i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
- (void)xfs_rtget_summary(mp, tp, l, i, &sumbp, &sb, &c);
- if (c) {
- if (!p) {
- cmn_err(CE_DEBUG, "%Ld-%Ld:", 1LL << l,
- XFS_RTMIN((1LL << l) +
- ((1LL << l) - 1LL),
- mp->m_sb.sb_rextents));
- p = 1;
- }
- cmn_err(CE_DEBUG, " %Ld:%d", (long long)i, c);
- }
- }
- if (p)
- cmn_err(CE_DEBUG, "\n");
- }
- if (sumbp)
- xfs_trans_brelse(tp, sumbp);
-}
-#endif /* DEBUG */
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h
index 0e0b4d2ec20..799c1f87126 100644
--- a/fs/xfs/xfs_rtalloc.h
+++ b/fs/xfs/xfs_rtalloc.h
@@ -134,24 +134,6 @@ xfs_rtpick_extent(
xfs_rtblock_t *pick); /* result rt extent */
/*
- * Debug code: print out the value of a range in the bitmap.
- */
-void
-xfs_rtprint_range(
- struct xfs_mount *mp, /* file system mount structure */
- struct xfs_trans *tp, /* transaction pointer */
- xfs_rtblock_t start, /* starting block to print */
- xfs_extlen_t len); /* length to print */
-
-/*
- * Debug code: print the summary file.
- */
-void
-xfs_rtprint_summary(
- struct xfs_mount *mp, /* file system mount structure */
- struct xfs_trans *tp); /* transaction pointer */
-
-/*
* Grow the realtime area of the filesystem.
*/
int
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c
index defb2febaaf..1ea7c0ca6ae 100644
--- a/fs/xfs/xfs_rw.c
+++ b/fs/xfs/xfs_rw.c
@@ -42,7 +42,6 @@
#include "xfs_attr.h"
#include "xfs_bmap.h"
#include "xfs_acl.h"
-#include "xfs_mac.h"
#include "xfs_error.h"
#include "xfs_buf_item.h"
#include "xfs_rw.h"
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index ee2721e0de4..301ff9445b6 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -339,7 +339,7 @@ xfs_trans_reserve(
*/
if (blocks > 0) {
error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,
- -blocks, rsvd);
+ -((int64_t)blocks), rsvd);
if (error != 0) {
current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
return (XFS_ERROR(ENOSPC));
@@ -380,7 +380,7 @@ xfs_trans_reserve(
*/
if (rtextents > 0) {
error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS,
- -rtextents, rsvd);
+ -((int64_t)rtextents), rsvd);
if (error) {
error = XFS_ERROR(ENOSPC);
goto undo_log;
@@ -410,7 +410,7 @@ undo_log:
undo_blocks:
if (blocks > 0) {
(void) xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,
- blocks, rsvd);
+ (int64_t)blocks, rsvd);
tp->t_blk_res = 0;
}
@@ -432,7 +432,7 @@ void
xfs_trans_mod_sb(
xfs_trans_t *tp,
uint field,
- long delta)
+ int64_t delta)
{
switch (field) {
@@ -663,62 +663,62 @@ xfs_trans_unreserve_and_mod_sb(
if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
if (tp->t_icount_delta != 0) {
msbp->msb_field = XFS_SBS_ICOUNT;
- msbp->msb_delta = (int)tp->t_icount_delta;
+ msbp->msb_delta = tp->t_icount_delta;
msbp++;
}
if (tp->t_ifree_delta != 0) {
msbp->msb_field = XFS_SBS_IFREE;
- msbp->msb_delta = (int)tp->t_ifree_delta;
+ msbp->msb_delta = tp->t_ifree_delta;
msbp++;
}
if (tp->t_fdblocks_delta != 0) {
msbp->msb_field = XFS_SBS_FDBLOCKS;
- msbp->msb_delta = (int)tp->t_fdblocks_delta;
+ msbp->msb_delta = tp->t_fdblocks_delta;
msbp++;
}
if (tp->t_frextents_delta != 0) {
msbp->msb_field = XFS_SBS_FREXTENTS;
- msbp->msb_delta = (int)tp->t_frextents_delta;
+ msbp->msb_delta = tp->t_frextents_delta;
msbp++;
}
if (tp->t_dblocks_delta != 0) {
msbp->msb_field = XFS_SBS_DBLOCKS;
- msbp->msb_delta = (int)tp->t_dblocks_delta;
+ msbp->msb_delta = tp->t_dblocks_delta;
msbp++;
}
if (tp->t_agcount_delta != 0) {
msbp->msb_field = XFS_SBS_AGCOUNT;
- msbp->msb_delta = (int)tp->t_agcount_delta;
+ msbp->msb_delta = tp->t_agcount_delta;
msbp++;
}
if (tp->t_imaxpct_delta != 0) {
msbp->msb_field = XFS_SBS_IMAX_PCT;
- msbp->msb_delta = (int)tp->t_imaxpct_delta;
+ msbp->msb_delta = tp->t_imaxpct_delta;
msbp++;
}
if (tp->t_rextsize_delta != 0) {
msbp->msb_field = XFS_SBS_REXTSIZE;
- msbp->msb_delta = (int)tp->t_rextsize_delta;
+ msbp->msb_delta = tp->t_rextsize_delta;
msbp++;
}
if (tp->t_rbmblocks_delta != 0) {
msbp->msb_field = XFS_SBS_RBMBLOCKS;
- msbp->msb_delta = (int)tp->t_rbmblocks_delta;
+ msbp->msb_delta = tp->t_rbmblocks_delta;
msbp++;
}
if (tp->t_rblocks_delta != 0) {
msbp->msb_field = XFS_SBS_RBLOCKS;
- msbp->msb_delta = (int)tp->t_rblocks_delta;
+ msbp->msb_delta = tp->t_rblocks_delta;
msbp++;
}
if (tp->t_rextents_delta != 0) {
msbp->msb_field = XFS_SBS_REXTENTS;
- msbp->msb_delta = (int)tp->t_rextents_delta;
+ msbp->msb_delta = tp->t_rextents_delta;
msbp++;
}
if (tp->t_rextslog_delta != 0) {
msbp->msb_field = XFS_SBS_REXTSLOG;
- msbp->msb_delta = (int)tp->t_rextslog_delta;
+ msbp->msb_delta = tp->t_rextslog_delta;
msbp++;
}
}
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index c68e00105d2..f1d7ab23672 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -39,13 +39,9 @@ typedef struct xfs_trans_header {
/*
* Log item types.
*/
-#define XFS_LI_5_3_BUF 0x1234 /* v1 bufs, 1-block inode buffers */
-#define XFS_LI_5_3_INODE 0x1235 /* 1-block inode buffers */
#define XFS_LI_EFI 0x1236
#define XFS_LI_EFD 0x1237
#define XFS_LI_IUNLINK 0x1238
-#define XFS_LI_6_1_INODE 0x1239 /* 4K non-aligned inode bufs */
-#define XFS_LI_6_1_BUF 0x123a /* v1, 4K inode buffers */
#define XFS_LI_INODE 0x123b /* aligned ino chunks, var-size ibufs */
#define XFS_LI_BUF 0x123c /* v2 bufs, variable sized inode bufs */
#define XFS_LI_DQUOT 0x123d
@@ -354,25 +350,25 @@ typedef struct xfs_trans {
xfs_trans_callback_t t_callback; /* transaction callback */
void *t_callarg; /* callback arg */
unsigned int t_flags; /* misc flags */
- long t_icount_delta; /* superblock icount change */
- long t_ifree_delta; /* superblock ifree change */
- long t_fdblocks_delta; /* superblock fdblocks chg */
- long t_res_fdblocks_delta; /* on-disk only chg */
- long t_frextents_delta;/* superblock freextents chg*/
- long t_res_frextents_delta; /* on-disk only chg */
+ int64_t t_icount_delta; /* superblock icount change */
+ int64_t t_ifree_delta; /* superblock ifree change */
+ int64_t t_fdblocks_delta; /* superblock fdblocks chg */
+ int64_t t_res_fdblocks_delta; /* on-disk only chg */
+ int64_t t_frextents_delta;/* superblock freextents chg*/
+ int64_t t_res_frextents_delta; /* on-disk only chg */
#ifdef DEBUG
- long t_ag_freeblks_delta; /* debugging counter */
- long t_ag_flist_delta; /* debugging counter */
- long t_ag_btree_delta; /* debugging counter */
+ int64_t t_ag_freeblks_delta; /* debugging counter */
+ int64_t t_ag_flist_delta; /* debugging counter */
+ int64_t t_ag_btree_delta; /* debugging counter */
#endif
- long t_dblocks_delta;/* superblock dblocks change */
- long t_agcount_delta;/* superblock agcount change */
- long t_imaxpct_delta;/* superblock imaxpct change */
- long t_rextsize_delta;/* superblock rextsize chg */
- long t_rbmblocks_delta;/* superblock rbmblocks chg */
- long t_rblocks_delta;/* superblock rblocks change */
- long t_rextents_delta;/* superblocks rextents chg */
- long t_rextslog_delta;/* superblocks rextslog chg */
+ int64_t t_dblocks_delta;/* superblock dblocks change */
+ int64_t t_agcount_delta;/* superblock agcount change */
+ int64_t t_imaxpct_delta;/* superblock imaxpct change */
+ int64_t t_rextsize_delta;/* superblock rextsize chg */
+ int64_t t_rbmblocks_delta;/* superblock rbmblocks chg */
+ int64_t t_rblocks_delta;/* superblock rblocks change */
+ int64_t t_rextents_delta;/* superblocks rextents chg */
+ int64_t t_rextslog_delta;/* superblocks rextslog chg */
unsigned int t_items_free; /* log item descs free */
xfs_log_item_chunk_t t_items; /* first log item desc chunk */
xfs_trans_header_t t_header; /* header for in-log trans */
@@ -936,9 +932,9 @@ typedef struct xfs_trans {
#define xfs_trans_set_sync(tp) ((tp)->t_flags |= XFS_TRANS_SYNC)
#ifdef DEBUG
-#define xfs_trans_agblocks_delta(tp, d) ((tp)->t_ag_freeblks_delta += (long)d)
-#define xfs_trans_agflist_delta(tp, d) ((tp)->t_ag_flist_delta += (long)d)
-#define xfs_trans_agbtree_delta(tp, d) ((tp)->t_ag_btree_delta += (long)d)
+#define xfs_trans_agblocks_delta(tp, d) ((tp)->t_ag_freeblks_delta += (int64_t)d)
+#define xfs_trans_agflist_delta(tp, d) ((tp)->t_ag_flist_delta += (int64_t)d)
+#define xfs_trans_agbtree_delta(tp, d) ((tp)->t_ag_btree_delta += (int64_t)d)
#else
#define xfs_trans_agblocks_delta(tp, d)
#define xfs_trans_agflist_delta(tp, d)
@@ -954,7 +950,7 @@ xfs_trans_t *_xfs_trans_alloc(struct xfs_mount *, uint);
xfs_trans_t *xfs_trans_dup(xfs_trans_t *);
int xfs_trans_reserve(xfs_trans_t *, uint, uint, uint,
uint, uint);
-void xfs_trans_mod_sb(xfs_trans_t *, uint, long);
+void xfs_trans_mod_sb(xfs_trans_t *, uint, int64_t);
struct xfs_buf *xfs_trans_get_buf(xfs_trans_t *, struct xfs_buftarg *, xfs_daddr_t,
int, uint);
int xfs_trans_read_buf(struct xfs_mount *, xfs_trans_t *,
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index fc39b166d40..ceb4f6e9996 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -90,7 +90,7 @@ xfs_trans_push_ail(
int flush_log;
SPLDECL(s);
-#define XFS_TRANS_PUSH_AIL_RESTARTS 10
+#define XFS_TRANS_PUSH_AIL_RESTARTS 1000
AIL_LOCK(mp,s);
lip = xfs_trans_first_ail(mp, &gen);
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 62336a4cc5a..29f72f61378 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -640,7 +640,7 @@ xfs_quiesce_fs(
* we can write the unmount record.
*/
do {
- xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, 0, NULL);
+ xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, NULL);
pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
if (!pincount) {
delay(50);
@@ -806,7 +806,7 @@ xfs_statvfs(
statp->f_type = XFS_SB_MAGIC;
- xfs_icsb_sync_counters_lazy(mp);
+ xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);
s = XFS_SB_LOCK(mp);
statp->f_bsize = sbp->sb_blocksize;
lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;
@@ -872,6 +872,10 @@ xfs_statvfs(
* this by simply making sure the log gets flushed
* if SYNC_BDFLUSH is set, and by actually writing it
* out otherwise.
+ * SYNC_IOWAIT - The caller wants us to wait for all data I/O to complete
+ * before we return (including direct I/O). Forms the drain
+ * side of the write barrier needed to safely quiesce the
+ * filesystem.
*
*/
/*ARGSUSED*/
@@ -883,27 +887,20 @@ xfs_sync(
{
xfs_mount_t *mp = XFS_BHVTOM(bdp);
- if (unlikely(flags == SYNC_QUIESCE))
- return xfs_quiesce_fs(mp);
- else
- return xfs_syncsub(mp, flags, 0, NULL);
+ return xfs_syncsub(mp, flags, NULL);
}
/*
* xfs sync routine for internal use
*
* This routine supports all of the flags defined for the generic vfs_sync
- * interface as explained above under xfs_sync. In the interests of not
- * changing interfaces within the 6.5 family, additional internally-
- * required functions are specified within a separate xflags parameter,
- * only available by calling this routine.
+ * interface as explained above under xfs_sync.
*
*/
int
xfs_sync_inodes(
xfs_mount_t *mp,
int flags,
- int xflags,
int *bypassed)
{
xfs_inode_t *ip = NULL;
@@ -1176,6 +1173,13 @@ xfs_sync_inodes(
}
}
+ /*
+ * When freezing, we need to wait ensure all I/O (including direct
+ * I/O) is complete to ensure no further data modification can take
+ * place after this point
+ */
+ if (flags & SYNC_IOWAIT)
+ vn_iowait(vp);
if (flags & SYNC_BDFLUSH) {
if ((flags & SYNC_ATTR) &&
@@ -1412,17 +1416,13 @@ xfs_sync_inodes(
* xfs sync routine for internal use
*
* This routine supports all of the flags defined for the generic vfs_sync
- * interface as explained above under xfs_sync. In the interests of not
- * changing interfaces within the 6.5 family, additional internally-
- * required functions are specified within a separate xflags parameter,
- * only available by calling this routine.
+ * interface as explained above under xfs_sync.
*
*/
int
xfs_syncsub(
xfs_mount_t *mp,
int flags,
- int xflags,
int *bypassed)
{
int error = 0;
@@ -1444,7 +1444,7 @@ xfs_syncsub(
if (flags & SYNC_BDFLUSH)
xfs_finish_reclaim_all(mp, 1);
else
- error = xfs_sync_inodes(mp, flags, xflags, bypassed);
+ error = xfs_sync_inodes(mp, flags, bypassed);
}
/*
@@ -1958,15 +1958,26 @@ xfs_showargs(
return 0;
}
+/*
+ * Second stage of a freeze. The data is already frozen, now we have to take
+ * care of the metadata. New transactions are already blocked, so we need to
+ * wait for any remaining transactions to drain out before proceding.
+ */
STATIC void
xfs_freeze(
bhv_desc_t *bdp)
{
xfs_mount_t *mp = XFS_BHVTOM(bdp);
+ /* wait for all modifications to complete */
while (atomic_read(&mp->m_active_trans) > 0)
delay(100);
+ /* flush inodes and push all remaining buffers out to disk */
+ xfs_quiesce_fs(mp);
+
+ ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
+
/* Push the superblock and write an unmount record */
xfs_log_unmount_write(mp);
xfs_unmountfs_writesb(mp);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index bda774a04b8..52c41714ec5 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -51,7 +51,6 @@
#include "xfs_refcache.h"
#include "xfs_trans_space.h"
#include "xfs_log_priv.h"
-#include "xfs_mac.h"
STATIC int
xfs_open(
@@ -1381,7 +1380,7 @@ xfs_inactive_symlink_rmt(
/*
* Commit the first transaction. This logs the EFI and the inode.
*/
- if ((error = xfs_bmap_finish(&tp, &free_list, first_block, &committed)))
+ if ((error = xfs_bmap_finish(&tp, &free_list, &committed)))
goto error1;
/*
* The transaction must have been committed, since there were
@@ -1790,8 +1789,7 @@ xfs_inactive(
* Just ignore errors at this point. There is
* nothing we can do except to try to keep going.
*/
- (void) xfs_bmap_finish(&tp, &free_list, first_block,
- &committed);
+ (void) xfs_bmap_finish(&tp, &free_list, &committed);
(void) xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
}
/*
@@ -2022,7 +2020,7 @@ xfs_create(
IHOLD(ip);
vp = XFS_ITOV(ip);
- error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+ error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error) {
xfs_bmap_cancel(&free_list);
goto abort_rele;
@@ -2507,7 +2505,7 @@ xfs_remove(
xfs_trans_set_sync(tp);
}
- error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+ error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error) {
REMOVE_DEBUG_TRACE(__LINE__);
goto error_rele;
@@ -2715,7 +2713,7 @@ xfs_link(
xfs_trans_set_sync(tp);
}
- error = xfs_bmap_finish (&tp, &free_list, first_block, &committed);
+ error = xfs_bmap_finish (&tp, &free_list, &committed);
if (error) {
xfs_bmap_cancel(&free_list);
goto abort_return;
@@ -2932,7 +2930,7 @@ xfs_mkdir(
xfs_trans_set_sync(tp);
}
- error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+ error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error) {
IRELE(cdp);
goto error2;
@@ -3183,7 +3181,7 @@ xfs_rmdir(
xfs_trans_set_sync(tp);
}
- error = xfs_bmap_finish (&tp, &free_list, first_block, &committed);
+ error = xfs_bmap_finish (&tp, &free_list, &committed);
if (error) {
xfs_bmap_cancel(&free_list);
xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
@@ -3533,7 +3531,7 @@ xfs_symlink(
*/
IHOLD(ip);
- error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
+ error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error) {
goto error2;
}
@@ -4145,7 +4143,7 @@ retry:
/*
* Complete the transaction
*/
- error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
+ error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error) {
goto error0;
}
@@ -4452,7 +4450,7 @@ xfs_free_file_space(
/*
* complete the transaction
*/
- error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
+ error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error) {
goto error0;
}