aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/vfs_inode.c16
-rw-r--r--fs/9p/vfs_super.c4
-rw-r--r--fs/Kconfig2
-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/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_misc.c2
-rw-r--r--fs/block_dev.c2
-rw-r--r--fs/buffer.c16
-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/configfs/configfs_internal.h4
-rw-r--r--fs/configfs/dir.c2
-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/debugfs/file.c2
-rw-r--r--fs/devpts/inode.c2
-rw-r--r--fs/dlm/debug_fs.c4
-rw-r--r--fs/dlm/user.c6
-rw-r--r--fs/dquot.c56
-rw-r--r--fs/ecryptfs/Makefile2
-rw-r--r--fs/ecryptfs/crypto.c331
-rw-r--r--fs/ecryptfs/debug.c6
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h160
-rw-r--r--fs/ecryptfs/file.c49
-rw-r--r--fs/ecryptfs/inode.c90
-rw-r--r--fs/ecryptfs/keystore.c798
-rw-r--r--fs/ecryptfs/main.c74
-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/ext2/ext2.h10
-rw-r--r--fs/ext2/file.c2
-rw-r--r--fs/ext2/namei.c4
-rw-r--r--fs/ext2/super.c2
-rw-r--r--fs/ext2/symlink.c4
-rw-r--r--fs/ext3/file.c2
-rw-r--r--fs/ext3/namei.c4
-rw-r--r--fs/ext3/super.c2
-rw-r--r--fs/ext3/symlink.c4
-rw-r--r--fs/ext4/file.c2
-rw-r--r--fs/ext4/namei.c4
-rw-r--r--fs/ext4/super.c2
-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/inode.c2
-rw-r--r--fs/gfs2/locking/dlm/plock.c2
-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_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/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.c12
-rw-r--r--fs/inode.c33
-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.c12
-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/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/proc/array.c2
-rw-r--r--fs/proc/base.c52
-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.c26
-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.c2
-rw-r--r--fs/ramfs/file-nommu.c2
-rw-r--r--fs/ramfs/inode.c8
-rw-r--r--fs/ramfs/internal.h2
-rw-r--r--fs/read_write.c2
-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/symlink.c2
-rw-r--r--fs/super.c2
-rw-r--r--fs/sysfs/dir.c2
-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/ialloc.c116
-rw-r--r--fs/ufs/inode.c193
-rw-r--r--fs/ufs/namei.c2
-rw-r--r--fs/ufs/super.c49
-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/xfs_aops.c3
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c6
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h10
231 files changed, 3453 insertions, 1314 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 378767c07bf..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
@@ -1303,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,
@@ -1318,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,
@@ -1330,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 11c59329ed0..488521ed9e9 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1088,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/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_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 7ff6e9346fa..f99c509697c 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1283,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();
@@ -1319,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);
@@ -1347,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);
@@ -1361,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)) {
@@ -1381,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);
@@ -1440,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);
}
@@ -1823,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;
@@ -2544,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/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 9371ee20995..34750d5e4ff 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -930,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/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/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 a561fb29e20..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>
@@ -687,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) */
@@ -755,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/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 75bbfae5508..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 "
@@ -863,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;
}
/**
@@ -879,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");
@@ -896,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;
}
@@ -905,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");
@@ -915,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
*
@@ -924,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;
}
@@ -967,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);
@@ -1001,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;
@@ -1027,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}
};
/**
@@ -1050,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;
@@ -1091,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);
@@ -1187,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;
@@ -1217,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;
@@ -1268,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;
@@ -1281,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,
@@ -1289,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
@@ -1304,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;
@@ -1338,48 +1429,36 @@ int ecryptfs_write_headers(struct dentry *ecryptfs_dentry,
rc = -ENOMEM;
goto out;
}
-
- 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;
@@ -1394,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);
@@ -1427,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;
@@ -1461,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);
@@ -1476,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;
@@ -1489,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) {
@@ -1510,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 0f897109759..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));
@@ -177,8 +203,13 @@ ecryptfs_get_key_payload_data(struct key *key)
#define ECRYPTFS_DEFAULT_CIPHER "aes"
#define ECRYPTFS_DEFAULT_KEY_BYTES 16
#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
/**
@@ -195,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;
@@ -241,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;
@@ -271,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)
{
@@ -384,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;
@@ -400,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,
@@ -426,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,
@@ -441,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);
@@ -483,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 779c3477d93..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,6 +250,17 @@ 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_zalloc(ecryptfs_file_info_cache, GFP_KERNEL);
ecryptfs_set_file_private(file, file_info);
@@ -261,14 +272,12 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
}
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;
@@ -288,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");
@@ -326,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 d4f02f3e18d..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;
@@ -362,32 +363,43 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
}
/* Released in this function */
page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2,
- GFP_USER);
+ GFP_USER);
if (!page_virt) {
rc = -ENOMEM;
ecryptfs_printk(KERN_ERR,
"Cannot ecryptfs_kmalloc a page\n");
goto out_dput;
}
-
- 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;
@@ -781,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 =
@@ -881,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)
{
@@ -901,7 +919,7 @@ out:
return rc;
}
-static ssize_t
+ssize_t
ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
size_t size)
{
@@ -971,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,
@@ -983,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,
@@ -1001,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 80bccd5ff8e..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;
@@ -319,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:
@@ -358,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;
@@ -459,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 = {
@@ -468,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])"
@@ -551,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,
@@ -587,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];
@@ -603,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
@@ -654,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 "
@@ -704,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) {
@@ -741,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
@@ -756,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) {
@@ -815,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];
@@ -831,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;
@@ -856,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.
@@ -877,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");
@@ -941,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 */
@@ -960,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;
@@ -972,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 "
@@ -995,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);
@@ -1027,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) {
@@ -1060,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 fe41ab1566e..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;
}
@@ -590,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,
@@ -695,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)
@@ -794,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;
}
@@ -805,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/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 daaa243eee9..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,
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/namei.c b/fs/ext3/namei.c
index a8e89328e66..49159f13cc1 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -2365,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,
@@ -2385,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 a0623a84a4b..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,
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/namei.c b/fs/ext4/namei.c
index 34b3448b40f..e7e1d79a7d7 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2363,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,
@@ -2383,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 c63a18b574d..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,
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/inode.c b/fs/fuse/inode.c
index 220255110d7..5ab8e50e780 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -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/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_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/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 e6bd553fdc4..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 */
@@ -563,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,
@@ -576,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 e6d93070f14..5abb097ab1b 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1000,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);
@@ -1093,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)
@@ -1113,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);
@@ -1251,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 6ee20668850..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;
@@ -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/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/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 7fb37d6f286..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,
};
@@ -1834,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),
@@ -1894,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,
};
@@ -1904,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,
@@ -2177,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,
@@ -2408,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 5e2d4359c29..e2c4c0a5c90 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -223,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,
@@ -236,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,
@@ -261,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,
@@ -320,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,
@@ -332,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,
@@ -363,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,
@@ -375,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,
@@ -389,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,
@@ -404,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,
@@ -438,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,
@@ -551,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,
@@ -593,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,
@@ -650,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
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 b935a3dd4b6..2f14774a124 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -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 d05e09ac9a9..d3fd7c6732d 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -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 bcb0ef2aae3..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,
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/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 9e95e7abaf6..8813990304f 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -296,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/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 209be95e9d1..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);
@@ -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:
@@ -890,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.
@@ -973,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);
@@ -1060,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;
@@ -1156,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;
}
@@ -1255,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/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index f3cc4ab20ba..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))
@@ -1272,7 +1270,6 @@ __xfs_get_blocks(
if (direct)
bh_result->b_private = inode;
set_buffer_unwritten(bh_result);
- set_buffer_delay(bh_result);
}
}
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index aa4c3b8cae0..0b5fa124bef 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -813,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,
@@ -824,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,
@@ -843,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