aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2006-06-25 11:57:32 -0400
committerSteve French <sfrench@us.ibm.com>2006-06-25 11:57:32 -0400
commitbbe5d235ee201705530a7153b57e141cd77d818b (patch)
treee98c31b4cb2ced6357a87a02596f9ecdbd6dbb26 /fs
parent189acaaef81b1d71aedd0d28810de24160c2e781 (diff)
parentdfd8317d3340f03bc06eba6b58f0ec0861da4a13 (diff)
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/vfs_super.c21
-rw-r--r--fs/Kconfig64
-rw-r--r--fs/Makefile1
-rw-r--r--fs/adfs/super.c15
-rw-r--r--fs/affs/super.c12
-rw-r--r--fs/afs/dir.c4
-rw-r--r--fs/afs/mntpt.c11
-rw-r--r--fs/afs/super.c24
-rw-r--r--fs/aio.c4
-rw-r--r--fs/autofs/init.c6
-rw-r--r--fs/autofs4/init.c6
-rw-r--r--fs/befs/linuxvfs.c12
-rw-r--r--fs/bfs/inode.c9
-rw-r--r--fs/binfmt_elf.c348
-rw-r--r--fs/binfmt_elf_fdpic.c26
-rw-r--r--fs/binfmt_misc.c7
-rw-r--r--fs/block_dev.c38
-rw-r--r--fs/buffer.c2
-rw-r--r--fs/cifs/cifsfs.c13
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/file.c26
-rw-r--r--fs/coda/file.c2
-rw-r--r--fs/coda/inode.c12
-rw-r--r--fs/coda/upcall.c4
-rw-r--r--fs/compat.c8
-rw-r--r--fs/configfs/mount.c6
-rw-r--r--fs/cramfs/inode.c15
-rw-r--r--fs/dcache.c109
-rw-r--r--fs/debugfs/inode.c8
-rw-r--r--fs/devfs/base.c8
-rw-r--r--fs/devpts/inode.c6
-rw-r--r--fs/direct-io.c18
-rw-r--r--fs/efs/super.c12
-rw-r--r--fs/eventpoll.c19
-rw-r--r--fs/exec.c7
-rw-r--r--fs/ext2/dir.c3
-rw-r--r--fs/ext2/super.c36
-rw-r--r--fs/ext3/dir.c2
-rw-r--r--fs/ext3/super.c70
-rw-r--r--fs/fat/inode.c8
-rw-r--r--fs/fat/misc.c1
-rw-r--r--fs/file_table.c2
-rw-r--r--fs/freevxfs/vxfs_subr.c3
-rw-r--r--fs/freevxfs/vxfs_super.c20
-rw-r--r--fs/fs-writeback.c6
-rw-r--r--fs/fuse/file.c2
-rw-r--r--fs/fuse/inode.c11
-rw-r--r--fs/hfs/bnode.c2
-rw-r--r--fs/hfs/btree.c2
-rw-r--r--fs/hfs/super.c11
-rw-r--r--fs/hfsplus/bitmap.c15
-rw-r--r--fs/hfsplus/bnode.c2
-rw-r--r--fs/hfsplus/btree.c2
-rw-r--r--fs/hfsplus/super.c12
-rw-r--r--fs/hostfs/hostfs_kern.c12
-rw-r--r--fs/hpfs/super.c10
-rw-r--r--fs/hppfs/hppfs_kern.c10
-rw-r--r--fs/hugetlbfs/inode.c31
-rw-r--r--fs/inotify.c991
-rw-r--r--fs/inotify_user.c719
-rw-r--r--fs/ioprio.c6
-rw-r--r--fs/isofs/inode.c13
-rw-r--r--fs/jbd/checkpoint.c419
-rw-r--r--fs/jbd/commit.c21
-rw-r--r--fs/jbd/transaction.c12
-rw-r--r--fs/jffs/inode-v23.c11
-rw-r--r--fs/jffs/intrep.c15
-rw-r--r--fs/jffs2/Makefile3
-rw-r--r--fs/jffs2/README.Locking21
-rw-r--r--fs/jffs2/acl.c485
-rw-r--r--fs/jffs2/acl.h45
-rw-r--r--fs/jffs2/build.c2
-rw-r--r--fs/jffs2/compr.c2
-rw-r--r--fs/jffs2/compr.h4
-rw-r--r--fs/jffs2/debug.c14
-rw-r--r--fs/jffs2/debug.h6
-rw-r--r--fs/jffs2/dir.c121
-rw-r--r--fs/jffs2/erase.c56
-rw-r--r--fs/jffs2/file.c35
-rw-r--r--fs/jffs2/fs.c67
-rw-r--r--fs/jffs2/gc.c131
-rw-r--r--fs/jffs2/histo.h3
-rw-r--r--fs/jffs2/jffs2_fs_i.h55
-rw-r--r--fs/jffs2/jffs2_fs_sb.h133
-rw-r--r--fs/jffs2/malloc.c127
-rw-r--r--fs/jffs2/nodelist.c183
-rw-r--r--fs/jffs2/nodelist.h190
-rw-r--r--fs/jffs2/nodemgmt.c196
-rw-r--r--fs/jffs2/os-linux.h25
-rw-r--r--fs/jffs2/readinode.c137
-rw-r--r--fs/jffs2/scan.c442
-rw-r--r--fs/jffs2/security.c82
-rw-r--r--fs/jffs2/summary.c484
-rw-r--r--fs/jffs2/summary.h64
-rw-r--r--fs/jffs2/super.c69
-rw-r--r--fs/jffs2/symlink.c7
-rw-r--r--fs/jffs2/wbuf.c968
-rw-r--r--fs/jffs2/write.c147
-rw-r--r--fs/jffs2/xattr.c1238
-rw-r--r--fs/jffs2/xattr.h116
-rw-r--r--fs/jffs2/xattr_trusted.c52
-rw-r--r--fs/jffs2/xattr_user.c52
-rw-r--r--fs/jfs/jfs_metapage.c5
-rw-r--r--fs/jfs/super.c11
-rw-r--r--fs/libfs.c16
-rw-r--r--fs/locks.c123
-rw-r--r--fs/minix/dir.c3
-rw-r--r--fs/minix/inode.c17
-rw-r--r--fs/mpage.c22
-rw-r--r--fs/msdos/namei.c9
-rw-r--r--fs/namei.c5
-rw-r--r--fs/namespace.c9
-rw-r--r--fs/ncpfs/inode.c11
-rw-r--r--fs/nfs/file.c4
-rw-r--r--fs/nfs/inode.c101
-rw-r--r--fs/nfsd/nfs4xdr.c2
-rw-r--r--fs/nfsd/nfsctl.c6
-rw-r--r--fs/nfsd/vfs.c2
-rw-r--r--fs/ntfs/aops.h3
-rw-r--r--fs/ntfs/attrib.c6
-rw-r--r--fs/ntfs/file.c16
-rw-r--r--fs/ntfs/super.c14
-rw-r--r--fs/ocfs2/dlm/dlmfs.c6
-rw-r--r--fs/ocfs2/super.c22
-rw-r--r--fs/ocfs2/symlink.c3
-rw-r--r--fs/open.c32
-rw-r--r--fs/openpromfs/inode.c6
-rw-r--r--fs/partitions/check.c12
-rw-r--r--fs/pipe.c9
-rw-r--r--fs/proc/base.c5
-rw-r--r--fs/proc/root.c6
-rw-r--r--fs/qnx4/inode.c13
-rw-r--r--fs/ramfs/inode.c13
-rw-r--r--fs/reiserfs/super.c17
-rw-r--r--fs/reiserfs/xattr.c3
-rw-r--r--fs/romfs/inode.c11
-rw-r--r--fs/select.c83
-rw-r--r--fs/smbfs/inode.c12
-rw-r--r--fs/smbfs/proc.c4
-rw-r--r--fs/smbfs/proto.h2
-rw-r--r--fs/splice.c46
-rw-r--r--fs/super.c111
-rw-r--r--fs/sync.c2
-rw-r--r--fs/sysfs/mount.c6
-rw-r--r--fs/sysv/dir.c3
-rw-r--r--fs/sysv/inode.c3
-rw-r--r--fs/sysv/super.c13
-rw-r--r--fs/udf/super.c12
-rw-r--r--fs/ufs/super.c9
-rw-r--r--fs/vfat/namei.c9
-rw-r--r--fs/xattr.c4
-rw-r--r--fs/xfs/Kconfig27
-rw-r--r--fs/xfs/Makefile-linux-2.64
-rw-r--r--fs/xfs/linux-2.6/kmem.h38
-rw-r--r--fs/xfs/linux-2.6/mrlock.h4
-rw-r--r--fs/xfs/linux-2.6/sema.h19
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c65
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.h8
-rw-r--r--fs/xfs/linux-2.6/xfs_export.c13
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c170
-rw-r--r--fs/xfs/linux-2.6/xfs_fs_subr.c59
-rw-r--r--fs/xfs/linux-2.6/xfs_globals.c1
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c65
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c117
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h35
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c123
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_stats.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c200
-rw-r--r--fs/xfs/linux-2.6/xfs_super.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_sysctl.c7
-rw-r--r--fs/xfs/linux-2.6/xfs_sysctl.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.c41
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.h167
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.c52
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h376
-rw-r--r--fs/xfs/quota/xfs_dquot.c8
-rw-r--r--fs/xfs/quota/xfs_dquot.h4
-rw-r--r--fs/xfs/quota/xfs_dquot_item.c6
-rw-r--r--fs/xfs/quota/xfs_qm.c8
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c81
-rw-r--r--fs/xfs/quota/xfs_qm_stats.c2
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c6
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c2
-rw-r--r--fs/xfs/support/debug.c4
-rw-r--r--fs/xfs/support/debug.h3
-rw-r--r--fs/xfs/xfs_acl.c71
-rw-r--r--fs/xfs/xfs_acl.h16
-rw-r--r--fs/xfs/xfs_alloc.c31
-rw-r--r--fs/xfs/xfs_alloc.h2
-rw-r--r--fs/xfs/xfs_alloc_btree.c2
-rw-r--r--fs/xfs/xfs_attr.c66
-rw-r--r--fs/xfs/xfs_attr.h14
-rw-r--r--fs/xfs/xfs_attr_leaf.c4
-rw-r--r--fs/xfs/xfs_bmap.c386
-rw-r--r--fs/xfs/xfs_bmap.h22
-rw-r--r--fs/xfs/xfs_bmap_btree.c12
-rw-r--r--fs/xfs/xfs_btree.c2
-rw-r--r--fs/xfs/xfs_buf_item.c9
-rw-r--r--fs/xfs/xfs_cap.h10
-rw-r--r--fs/xfs/xfs_da_btree.c194
-rw-r--r--fs/xfs/xfs_da_btree.h4
-rw-r--r--fs/xfs/xfs_dfrag.c84
-rw-r--r--fs/xfs/xfs_dfrag.h3
-rw-r--r--fs/xfs/xfs_dinode.h5
-rw-r--r--fs/xfs/xfs_dir.c1217
-rw-r--r--fs/xfs/xfs_dir.h142
-rw-r--r--fs/xfs/xfs_dir2.c396
-rw-r--r--fs/xfs/xfs_dir2.h32
-rw-r--r--fs/xfs/xfs_dir2_block.c31
-rw-r--r--fs/xfs/xfs_dir2_data.c5
-rw-r--r--fs/xfs/xfs_dir2_data.h8
-rw-r--r--fs/xfs/xfs_dir2_leaf.c14
-rw-r--r--fs/xfs/xfs_dir2_node.c16
-rw-r--r--fs/xfs/xfs_dir2_sf.c13
-rw-r--r--fs/xfs/xfs_dir2_trace.c2
-rw-r--r--fs/xfs/xfs_dir_leaf.c2213
-rw-r--r--fs/xfs/xfs_dir_leaf.h231
-rw-r--r--fs/xfs/xfs_dir_sf.h155
-rw-r--r--fs/xfs/xfs_dmapi.h2
-rw-r--r--fs/xfs/xfs_dmops.c1
-rw-r--r--fs/xfs/xfs_error.c2
-rw-r--r--fs/xfs/xfs_extfree_item.c57
-rw-r--r--fs/xfs/xfs_extfree_item.h53
-rw-r--r--fs/xfs/xfs_fs.h7
-rw-r--r--fs/xfs/xfs_fsops.c20
-rw-r--r--fs/xfs/xfs_ialloc.c5
-rw-r--r--fs/xfs/xfs_ialloc_btree.c2
-rw-r--r--fs/xfs/xfs_iget.c22
-rw-r--r--fs/xfs/xfs_inode.c94
-rw-r--r--fs/xfs/xfs_inode.h7
-rw-r--r--fs/xfs/xfs_inode_item.c57
-rw-r--r--fs/xfs/xfs_inode_item.h61
-rw-r--r--fs/xfs/xfs_iocore.c7
-rw-r--r--fs/xfs/xfs_iomap.c26
-rw-r--r--fs/xfs/xfs_itable.c20
-rw-r--r--fs/xfs/xfs_itable.h1
-rw-r--r--fs/xfs/xfs_log.c21
-rw-r--r--fs/xfs/xfs_log_recover.c113
-rw-r--r--fs/xfs/xfs_mount.c54
-rw-r--r--fs/xfs/xfs_mount.h70
-rw-r--r--fs/xfs/xfs_qmops.c1
-rw-r--r--fs/xfs/xfs_quota.h2
-rw-r--r--fs/xfs/xfs_rename.c68
-rw-r--r--fs/xfs/xfs_rtalloc.c16
-rw-r--r--fs/xfs/xfs_rw.c124
-rw-r--r--fs/xfs/xfs_rw.h10
-rw-r--r--fs/xfs/xfs_trans.c48
-rw-r--r--fs/xfs/xfs_trans.h7
-rw-r--r--fs/xfs/xfs_trans_ail.c6
-rw-r--r--fs/xfs/xfs_trans_buf.c12
-rw-r--r--fs/xfs/xfs_trans_extfree.c1
-rw-r--r--fs/xfs/xfs_trans_inode.c2
-rw-r--r--fs/xfs/xfs_trans_item.c2
-rw-r--r--fs/xfs/xfs_trans_space.h11
-rw-r--r--fs/xfs/xfs_utils.c13
-rw-r--r--fs/xfs/xfs_utils.h7
-rw-r--r--fs/xfs/xfs_vfsops.c122
-rw-r--r--fs/xfs/xfs_vnodeops.c295
260 files changed, 9074 insertions, 9509 deletions
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 61c599b4a1e3..872943004e59 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -99,12 +99,13 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
99 * @flags: mount flags 99 * @flags: mount flags
100 * @dev_name: device name that was mounted 100 * @dev_name: device name that was mounted
101 * @data: mount options 101 * @data: mount options
102 * @mnt: mountpoint record to be instantiated
102 * 103 *
103 */ 104 */
104 105
105static struct super_block *v9fs_get_sb(struct file_system_type 106static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
106 *fs_type, int flags, 107 const char *dev_name, void *data,
107 const char *dev_name, void *data) 108 struct vfsmount *mnt)
108{ 109{
109 struct super_block *sb = NULL; 110 struct super_block *sb = NULL;
110 struct v9fs_fcall *fcall = NULL; 111 struct v9fs_fcall *fcall = NULL;
@@ -123,17 +124,19 @@ static struct super_block *v9fs_get_sb(struct file_system_type
123 124
124 v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); 125 v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
125 if (!v9ses) 126 if (!v9ses)
126 return ERR_PTR(-ENOMEM); 127 return -ENOMEM;
127 128
128 if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { 129 if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) {
129 dprintk(DEBUG_ERROR, "problem initiating session\n"); 130 dprintk(DEBUG_ERROR, "problem initiating session\n");
130 sb = ERR_PTR(newfid); 131 retval = newfid;
131 goto out_free_session; 132 goto out_free_session;
132 } 133 }
133 134
134 sb = sget(fs_type, NULL, v9fs_set_super, v9ses); 135 sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
135 if (IS_ERR(sb)) 136 if (IS_ERR(sb)) {
137 retval = PTR_ERR(sb);
136 goto out_close_session; 138 goto out_close_session;
139 }
137 v9fs_fill_super(sb, v9ses, flags); 140 v9fs_fill_super(sb, v9ses, flags);
138 141
139 inode = v9fs_get_inode(sb, S_IFDIR | mode); 142 inode = v9fs_get_inode(sb, S_IFDIR | mode);
@@ -184,19 +187,19 @@ static struct super_block *v9fs_get_sb(struct file_system_type
184 goto put_back_sb; 187 goto put_back_sb;
185 } 188 }
186 189
187 return sb; 190 return simple_set_mnt(mnt, sb);
188 191
189out_close_session: 192out_close_session:
190 v9fs_session_close(v9ses); 193 v9fs_session_close(v9ses);
191out_free_session: 194out_free_session:
192 kfree(v9ses); 195 kfree(v9ses);
193 return sb; 196 return retval;
194 197
195put_back_sb: 198put_back_sb:
196 /* deactivate_super calls v9fs_kill_super which will frees the rest */ 199 /* deactivate_super calls v9fs_kill_super which will frees the rest */
197 up_write(&sb->s_umount); 200 up_write(&sb->s_umount);
198 deactivate_super(sb); 201 deactivate_super(sb);
199 return ERR_PTR(retval); 202 return retval;
200} 203}
201 204
202/** 205/**
diff --git a/fs/Kconfig b/fs/Kconfig
index d49b2a8c0be6..467f7ae5f092 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -53,7 +53,7 @@ config EXT2_FS_SECURITY
53 53
54config EXT2_FS_XIP 54config EXT2_FS_XIP
55 bool "Ext2 execute in place support" 55 bool "Ext2 execute in place support"
56 depends on EXT2_FS 56 depends on EXT2_FS && MMU
57 help 57 help
58 Execute in place can be used on memory-backed block devices. If you 58 Execute in place can be used on memory-backed block devices. If you
59 enable this option, you can select to mount block devices which are 59 enable this option, you can select to mount block devices which are
@@ -393,18 +393,30 @@ config INOTIFY
393 bool "Inotify file change notification support" 393 bool "Inotify file change notification support"
394 default y 394 default y
395 ---help--- 395 ---help---
396 Say Y here to enable inotify support and the associated system 396 Say Y here to enable inotify support. Inotify is a file change
397 calls. Inotify is a file change notification system and a 397 notification system and a replacement for dnotify. Inotify fixes
398 replacement for dnotify. Inotify fixes numerous shortcomings in 398 numerous shortcomings in dnotify and introduces several new features
399 dnotify and introduces several new features. It allows monitoring 399 including multiple file events, one-shot support, and unmount
400 of both files and directories via a single open fd. Other features
401 include multiple file events, one-shot support, and unmount
402 notification. 400 notification.
403 401
404 For more information, see Documentation/filesystems/inotify.txt 402 For more information, see Documentation/filesystems/inotify.txt
405 403
406 If unsure, say Y. 404 If unsure, say Y.
407 405
406config INOTIFY_USER
407 bool "Inotify support for userspace"
408 depends on INOTIFY
409 default y
410 ---help---
411 Say Y here to enable inotify support for userspace, including the
412 associated system calls. Inotify allows monitoring of both files and
413 directories via a single open fd. Events are read from the file
414 descriptor, which is also select()- and poll()-able.
415
416 For more information, see Documentation/filesystems/inotify.txt
417
418 If unsure, say Y.
419
408config QUOTA 420config QUOTA
409 bool "Quota support" 421 bool "Quota support"
410 help 422 help
@@ -1101,6 +1113,44 @@ config JFFS2_SUMMARY
1101 1113
1102 If unsure, say 'N'. 1114 If unsure, say 'N'.
1103 1115
1116config JFFS2_FS_XATTR
1117 bool "JFFS2 XATTR support (EXPERIMENTAL)"
1118 depends on JFFS2_FS && EXPERIMENTAL && !JFFS2_FS_WRITEBUFFER
1119 default n
1120 help
1121 Extended attributes are name:value pairs associated with inodes by
1122 the kernel or by users (see the attr(5) manual page, or visit
1123 <http://acl.bestbits.at/> for details).
1124
1125 If unsure, say N.
1126
1127config JFFS2_FS_POSIX_ACL
1128 bool "JFFS2 POSIX Access Control Lists"
1129 depends on JFFS2_FS_XATTR
1130 default y
1131 select FS_POSIX_ACL
1132 help
1133 Posix Access Control Lists (ACLs) support permissions for users and
1134 groups beyond the owner/group/world scheme.
1135
1136 To learn more about Access Control Lists, visit the Posix ACLs for
1137 Linux website <http://acl.bestbits.at/>.
1138
1139 If you don't know what Access Control Lists are, say N
1140
1141config JFFS2_FS_SECURITY
1142 bool "JFFS2 Security Labels"
1143 depends on JFFS2_FS_XATTR
1144 default y
1145 help
1146 Security labels support alternative access control models
1147 implemented by security modules like SELinux. This option
1148 enables an extended attribute handler for file security
1149 labels in the jffs2 filesystem.
1150
1151 If you are not using a security module that requires using
1152 extended attributes for file security labels, say N.
1153
1104config JFFS2_COMPRESSION_OPTIONS 1154config JFFS2_COMPRESSION_OPTIONS
1105 bool "Advanced compression options for JFFS2" 1155 bool "Advanced compression options for JFFS2"
1106 depends on JFFS2_FS 1156 depends on JFFS2_FS
diff --git a/fs/Makefile b/fs/Makefile
index 078d3d1191a5..d0ea6bfccf29 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -13,6 +13,7 @@ obj-y := open.o read_write.o file_table.o buffer.o bio.o super.o \
13 ioprio.o pnode.o drop_caches.o splice.o sync.o 13 ioprio.o pnode.o drop_caches.o splice.o sync.o
14 14
15obj-$(CONFIG_INOTIFY) += inotify.o 15obj-$(CONFIG_INOTIFY) += inotify.o
16obj-$(CONFIG_INOTIFY_USER) += inotify_user.o
16obj-$(CONFIG_EPOLL) += eventpoll.o 17obj-$(CONFIG_EPOLL) += eventpoll.o
17obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o 18obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o
18 19
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index 252abda0d200..ba1c88af49fe 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -196,17 +196,17 @@ static int adfs_remount(struct super_block *sb, int *flags, char *data)
196 return parse_options(sb, data); 196 return parse_options(sb, data);
197} 197}
198 198
199static int adfs_statfs(struct super_block *sb, struct kstatfs *buf) 199static int adfs_statfs(struct dentry *dentry, struct kstatfs *buf)
200{ 200{
201 struct adfs_sb_info *asb = ADFS_SB(sb); 201 struct adfs_sb_info *asb = ADFS_SB(dentry->d_sb);
202 202
203 buf->f_type = ADFS_SUPER_MAGIC; 203 buf->f_type = ADFS_SUPER_MAGIC;
204 buf->f_namelen = asb->s_namelen; 204 buf->f_namelen = asb->s_namelen;
205 buf->f_bsize = sb->s_blocksize; 205 buf->f_bsize = dentry->d_sb->s_blocksize;
206 buf->f_blocks = asb->s_size; 206 buf->f_blocks = asb->s_size;
207 buf->f_files = asb->s_ids_per_zone * asb->s_map_size; 207 buf->f_files = asb->s_ids_per_zone * asb->s_map_size;
208 buf->f_bavail = 208 buf->f_bavail =
209 buf->f_bfree = adfs_map_free(sb); 209 buf->f_bfree = adfs_map_free(dentry->d_sb);
210 buf->f_ffree = (long)(buf->f_bfree * buf->f_files) / (long)buf->f_blocks; 210 buf->f_ffree = (long)(buf->f_bfree * buf->f_files) / (long)buf->f_blocks;
211 211
212 return 0; 212 return 0;
@@ -470,10 +470,11 @@ error:
470 return -EINVAL; 470 return -EINVAL;
471} 471}
472 472
473static struct super_block *adfs_get_sb(struct file_system_type *fs_type, 473static int adfs_get_sb(struct file_system_type *fs_type,
474 int flags, const char *dev_name, void *data) 474 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
475{ 475{
476 return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super); 476 return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super,
477 mnt);
477} 478}
478 479
479static struct file_system_type adfs_fs_type = { 480static struct file_system_type adfs_fs_type = {
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 4d7e5b19e5cd..8765cba35bb9 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -18,7 +18,7 @@
18 18
19extern struct timezone sys_tz; 19extern struct timezone sys_tz;
20 20
21static int affs_statfs(struct super_block *sb, struct kstatfs *buf); 21static int affs_statfs(struct dentry *dentry, struct kstatfs *buf);
22static int affs_remount (struct super_block *sb, int *flags, char *data); 22static int affs_remount (struct super_block *sb, int *flags, char *data);
23 23
24static void 24static void
@@ -508,8 +508,9 @@ affs_remount(struct super_block *sb, int *flags, char *data)
508} 508}
509 509
510static int 510static int
511affs_statfs(struct super_block *sb, struct kstatfs *buf) 511affs_statfs(struct dentry *dentry, struct kstatfs *buf)
512{ 512{
513 struct super_block *sb = dentry->d_sb;
513 int free; 514 int free;
514 515
515 pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",AFFS_SB(sb)->s_partition_size, 516 pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",AFFS_SB(sb)->s_partition_size,
@@ -524,10 +525,11 @@ affs_statfs(struct super_block *sb, struct kstatfs *buf)
524 return 0; 525 return 0;
525} 526}
526 527
527static struct super_block *affs_get_sb(struct file_system_type *fs_type, 528static int affs_get_sb(struct file_system_type *fs_type,
528 int flags, const char *dev_name, void *data) 529 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
529{ 530{
530 return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super); 531 return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super,
532 mnt);
531} 533}
532 534
533static struct file_system_type affs_fs_type = { 535static struct file_system_type affs_fs_type = {
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index a6dff6a4f204..2fc99877cb0d 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -185,9 +185,7 @@ static struct page *afs_dir_get_page(struct inode *dir, unsigned long index)
185 185
186 _enter("{%lu},%lu", dir->i_ino, index); 186 _enter("{%lu},%lu", dir->i_ino, index);
187 187
188 page = read_cache_page(dir->i_mapping,index, 188 page = read_mapping_page(dir->i_mapping, index, NULL);
189 (filler_t *) dir->i_mapping->a_ops->readpage,
190 NULL);
191 if (!IS_ERR(page)) { 189 if (!IS_ERR(page)) {
192 wait_on_page_locked(page); 190 wait_on_page_locked(page);
193 kmap(page); 191 kmap(page);
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 4e6eeb59b83c..b5cf9e1205ad 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -63,7 +63,6 @@ unsigned long afs_mntpt_expiry_timeout = 20;
63int afs_mntpt_check_symlink(struct afs_vnode *vnode) 63int afs_mntpt_check_symlink(struct afs_vnode *vnode)
64{ 64{
65 struct page *page; 65 struct page *page;
66 filler_t *filler;
67 size_t size; 66 size_t size;
68 char *buf; 67 char *buf;
69 int ret; 68 int ret;
@@ -71,10 +70,7 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode)
71 _enter("{%u,%u}", vnode->fid.vnode, vnode->fid.unique); 70 _enter("{%u,%u}", vnode->fid.vnode, vnode->fid.unique);
72 71
73 /* read the contents of the symlink into the pagecache */ 72 /* read the contents of the symlink into the pagecache */
74 filler = (filler_t *) AFS_VNODE_TO_I(vnode)->i_mapping->a_ops->readpage; 73 page = read_mapping_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, NULL);
75
76 page = read_cache_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0,
77 filler, NULL);
78 if (IS_ERR(page)) { 74 if (IS_ERR(page)) {
79 ret = PTR_ERR(page); 75 ret = PTR_ERR(page);
80 goto out; 76 goto out;
@@ -160,7 +156,6 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
160 struct page *page = NULL; 156 struct page *page = NULL;
161 size_t size; 157 size_t size;
162 char *buf, *devname = NULL, *options = NULL; 158 char *buf, *devname = NULL, *options = NULL;
163 filler_t *filler;
164 int ret; 159 int ret;
165 160
166 kenter("{%s}", mntpt->d_name.name); 161 kenter("{%s}", mntpt->d_name.name);
@@ -182,9 +177,7 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
182 goto error; 177 goto error;
183 178
184 /* read the contents of the AFS special symlink */ 179 /* read the contents of the AFS special symlink */
185 filler = (filler_t *)mntpt->d_inode->i_mapping->a_ops->readpage; 180 page = read_mapping_page(mntpt->d_inode->i_mapping, 0, NULL);
186
187 page = read_cache_page(mntpt->d_inode->i_mapping, 0, filler, NULL);
188 if (IS_ERR(page)) { 181 if (IS_ERR(page)) {
189 ret = PTR_ERR(page); 182 ret = PTR_ERR(page);
190 goto error; 183 goto error;
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 53c56e7231ab..82468df0ba54 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -38,9 +38,9 @@ struct afs_mount_params {
38static void afs_i_init_once(void *foo, kmem_cache_t *cachep, 38static void afs_i_init_once(void *foo, kmem_cache_t *cachep,
39 unsigned long flags); 39 unsigned long flags);
40 40
41static struct super_block *afs_get_sb(struct file_system_type *fs_type, 41static int afs_get_sb(struct file_system_type *fs_type,
42 int flags, const char *dev_name, 42 int flags, const char *dev_name,
43 void *data); 43 void *data, struct vfsmount *mnt);
44 44
45static struct inode *afs_alloc_inode(struct super_block *sb); 45static struct inode *afs_alloc_inode(struct super_block *sb);
46 46
@@ -294,10 +294,11 @@ static int afs_fill_super(struct super_block *sb, void *data, int silent)
294 * get an AFS superblock 294 * get an AFS superblock
295 * - TODO: don't use get_sb_nodev(), but rather call sget() directly 295 * - TODO: don't use get_sb_nodev(), but rather call sget() directly
296 */ 296 */
297static struct super_block *afs_get_sb(struct file_system_type *fs_type, 297static int afs_get_sb(struct file_system_type *fs_type,
298 int flags, 298 int flags,
299 const char *dev_name, 299 const char *dev_name,
300 void *options) 300 void *options,
301 struct vfsmount *mnt)
301{ 302{
302 struct afs_mount_params params; 303 struct afs_mount_params params;
303 struct super_block *sb; 304 struct super_block *sb;
@@ -311,7 +312,7 @@ static struct super_block *afs_get_sb(struct file_system_type *fs_type,
311 ret = afscm_start(); 312 ret = afscm_start();
312 if (ret < 0) { 313 if (ret < 0) {
313 _leave(" = %d", ret); 314 _leave(" = %d", ret);
314 return ERR_PTR(ret); 315 return ret;
315 } 316 }
316 317
317 /* parse the options */ 318 /* parse the options */
@@ -348,18 +349,19 @@ static struct super_block *afs_get_sb(struct file_system_type *fs_type,
348 goto error; 349 goto error;
349 } 350 }
350 sb->s_flags |= MS_ACTIVE; 351 sb->s_flags |= MS_ACTIVE;
352 simple_set_mnt(mnt, sb);
351 353
352 afs_put_volume(params.volume); 354 afs_put_volume(params.volume);
353 afs_put_cell(params.default_cell); 355 afs_put_cell(params.default_cell);
354 _leave(" = %p", sb); 356 _leave(" = 0 [%p]", 0, sb);
355 return sb; 357 return 0;
356 358
357 error: 359 error:
358 afs_put_volume(params.volume); 360 afs_put_volume(params.volume);
359 afs_put_cell(params.default_cell); 361 afs_put_cell(params.default_cell);
360 afscm_stop(); 362 afscm_stop();
361 _leave(" = %d", ret); 363 _leave(" = %d", ret);
362 return ERR_PTR(ret); 364 return ret;
363} /* end afs_get_sb() */ 365} /* end afs_get_sb() */
364 366
365/*****************************************************************************/ 367/*****************************************************************************/
diff --git a/fs/aio.c b/fs/aio.c
index e41e932ba489..8c34a62df7d7 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -777,11 +777,11 @@ out:
777static int __aio_run_iocbs(struct kioctx *ctx) 777static int __aio_run_iocbs(struct kioctx *ctx)
778{ 778{
779 struct kiocb *iocb; 779 struct kiocb *iocb;
780 LIST_HEAD(run_list); 780 struct list_head run_list;
781 781
782 assert_spin_locked(&ctx->ctx_lock); 782 assert_spin_locked(&ctx->ctx_lock);
783 783
784 list_splice_init(&ctx->run_list, &run_list); 784 list_replace_init(&ctx->run_list, &run_list);
785 while (!list_empty(&run_list)) { 785 while (!list_empty(&run_list)) {
786 iocb = list_entry(run_list.next, struct kiocb, 786 iocb = list_entry(run_list.next, struct kiocb,
787 ki_run_list); 787 ki_run_list);
diff --git a/fs/autofs/init.c b/fs/autofs/init.c
index b977ece69f0c..aca123752406 100644
--- a/fs/autofs/init.c
+++ b/fs/autofs/init.c
@@ -14,10 +14,10 @@
14#include <linux/init.h> 14#include <linux/init.h>
15#include "autofs_i.h" 15#include "autofs_i.h"
16 16
17static struct super_block *autofs_get_sb(struct file_system_type *fs_type, 17static int autofs_get_sb(struct file_system_type *fs_type,
18 int flags, const char *dev_name, void *data) 18 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
19{ 19{
20 return get_sb_nodev(fs_type, flags, data, autofs_fill_super); 20 return get_sb_nodev(fs_type, flags, data, autofs_fill_super, mnt);
21} 21}
22 22
23static struct file_system_type autofs_fs_type = { 23static struct file_system_type autofs_fs_type = {
diff --git a/fs/autofs4/init.c b/fs/autofs4/init.c
index acecec8578ce..5d9193332bef 100644
--- a/fs/autofs4/init.c
+++ b/fs/autofs4/init.c
@@ -14,10 +14,10 @@
14#include <linux/init.h> 14#include <linux/init.h>
15#include "autofs_i.h" 15#include "autofs_i.h"
16 16
17static struct super_block *autofs_get_sb(struct file_system_type *fs_type, 17static int autofs_get_sb(struct file_system_type *fs_type,
18 int flags, const char *dev_name, void *data) 18 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
19{ 19{
20 return get_sb_nodev(fs_type, flags, data, autofs4_fill_super); 20 return get_sb_nodev(fs_type, flags, data, autofs4_fill_super, mnt);
21} 21}
22 22
23static struct file_system_type autofs_fs_type = { 23static struct file_system_type autofs_fs_type = {
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 68ebd10f345d..08201fab26cd 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -49,7 +49,7 @@ static int befs_nls2utf(struct super_block *sb, const char *in, int in_len,
49 char **out, int *out_len); 49 char **out, int *out_len);
50static void befs_put_super(struct super_block *); 50static void befs_put_super(struct super_block *);
51static int befs_remount(struct super_block *, int *, char *); 51static int befs_remount(struct super_block *, int *, char *);
52static int befs_statfs(struct super_block *, struct kstatfs *); 52static int befs_statfs(struct dentry *, struct kstatfs *);
53static int parse_options(char *, befs_mount_options *); 53static int parse_options(char *, befs_mount_options *);
54 54
55static const struct super_operations befs_sops = { 55static const struct super_operations befs_sops = {
@@ -880,8 +880,9 @@ befs_remount(struct super_block *sb, int *flags, char *data)
880} 880}
881 881
882static int 882static int
883befs_statfs(struct super_block *sb, struct kstatfs *buf) 883befs_statfs(struct dentry *dentry, struct kstatfs *buf)
884{ 884{
885 struct super_block *sb = dentry->d_sb;
885 886
886 befs_debug(sb, "---> befs_statfs()"); 887 befs_debug(sb, "---> befs_statfs()");
887 888
@@ -899,11 +900,12 @@ befs_statfs(struct super_block *sb, struct kstatfs *buf)
899 return 0; 900 return 0;
900} 901}
901 902
902static struct super_block * 903static int
903befs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, 904befs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name,
904 void *data) 905 void *data, struct vfsmount *mnt)
905{ 906{
906 return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super); 907 return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super,
908 mnt);
907} 909}
908 910
909static struct file_system_type befs_fs_type = { 911static struct file_system_type befs_fs_type = {
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 55a7a78332f8..cf74f3d4d966 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -203,8 +203,9 @@ static void bfs_put_super(struct super_block *s)
203 s->s_fs_info = NULL; 203 s->s_fs_info = NULL;
204} 204}
205 205
206static int bfs_statfs(struct super_block *s, struct kstatfs *buf) 206static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf)
207{ 207{
208 struct super_block *s = dentry->d_sb;
208 struct bfs_sb_info *info = BFS_SB(s); 209 struct bfs_sb_info *info = BFS_SB(s);
209 u64 id = huge_encode_dev(s->s_bdev->bd_dev); 210 u64 id = huge_encode_dev(s->s_bdev->bd_dev);
210 buf->f_type = BFS_MAGIC; 211 buf->f_type = BFS_MAGIC;
@@ -410,10 +411,10 @@ out:
410 return -EINVAL; 411 return -EINVAL;
411} 412}
412 413
413static struct super_block *bfs_get_sb(struct file_system_type *fs_type, 414static int bfs_get_sb(struct file_system_type *fs_type,
414 int flags, const char *dev_name, void *data) 415 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
415{ 416{
416 return get_sb_bdev(fs_type, flags, dev_name, data, bfs_fill_super); 417 return get_sb_bdev(fs_type, flags, dev_name, data, bfs_fill_super, mnt);
417} 418}
418 419
419static struct file_system_type bfs_fs_type = { 420static struct file_system_type bfs_fs_type = {
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 537893a16014..d0434406eaeb 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -38,15 +38,13 @@
38#include <linux/security.h> 38#include <linux/security.h>
39#include <linux/syscalls.h> 39#include <linux/syscalls.h>
40#include <linux/random.h> 40#include <linux/random.h>
41 41#include <linux/elf.h>
42#include <asm/uaccess.h> 42#include <asm/uaccess.h>
43#include <asm/param.h> 43#include <asm/param.h>
44#include <asm/page.h> 44#include <asm/page.h>
45 45
46#include <linux/elf.h> 46static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
47 47static int load_elf_library(struct file *);
48static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
49static int load_elf_library(struct file*);
50static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int); 48static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
51extern int dump_fpu (struct pt_regs *, elf_fpregset_t *); 49extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
52 50
@@ -59,15 +57,15 @@ extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
59 * don't even try. 57 * don't even try.
60 */ 58 */
61#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) 59#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
62static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file); 60static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file);
63#else 61#else
64#define elf_core_dump NULL 62#define elf_core_dump NULL
65#endif 63#endif
66 64
67#if ELF_EXEC_PAGESIZE > PAGE_SIZE 65#if ELF_EXEC_PAGESIZE > PAGE_SIZE
68# define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE 66#define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE
69#else 67#else
70# define ELF_MIN_ALIGN PAGE_SIZE 68#define ELF_MIN_ALIGN PAGE_SIZE
71#endif 69#endif
72 70
73#ifndef ELF_CORE_EFLAGS 71#ifndef ELF_CORE_EFLAGS
@@ -86,7 +84,7 @@ static struct linux_binfmt elf_format = {
86 .min_coredump = ELF_EXEC_PAGESIZE 84 .min_coredump = ELF_EXEC_PAGESIZE
87}; 85};
88 86
89#define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE) 87#define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE)
90 88
91static int set_brk(unsigned long start, unsigned long end) 89static int set_brk(unsigned long start, unsigned long end)
92{ 90{
@@ -104,13 +102,11 @@ static int set_brk(unsigned long start, unsigned long end)
104 return 0; 102 return 0;
105} 103}
106 104
107
108/* We need to explicitly zero any fractional pages 105/* We need to explicitly zero any fractional pages
109 after the data section (i.e. bss). This would 106 after the data section (i.e. bss). This would
110 contain the junk from the file that should not 107 contain the junk from the file that should not
111 be in memory */ 108 be in memory
112 109 */
113
114static int padzero(unsigned long elf_bss) 110static int padzero(unsigned long elf_bss)
115{ 111{
116 unsigned long nbyte; 112 unsigned long nbyte;
@@ -129,7 +125,9 @@ static int padzero(unsigned long elf_bss)
129#define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items)) 125#define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items))
130#define STACK_ROUND(sp, items) \ 126#define STACK_ROUND(sp, items) \
131 ((15 + (unsigned long) ((sp) + (items))) &~ 15UL) 127 ((15 + (unsigned long) ((sp) + (items))) &~ 15UL)
132#define STACK_ALLOC(sp, len) ({ elf_addr_t __user *old_sp = (elf_addr_t __user *)sp; sp += len; old_sp; }) 128#define STACK_ALLOC(sp, len) ({ \
129 elf_addr_t __user *old_sp = (elf_addr_t __user *)sp; sp += len; \
130 old_sp; })
133#else 131#else
134#define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) - (items)) 132#define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) - (items))
135#define STACK_ROUND(sp, items) \ 133#define STACK_ROUND(sp, items) \
@@ -138,7 +136,7 @@ static int padzero(unsigned long elf_bss)
138#endif 136#endif
139 137
140static int 138static int
141create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, 139create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
142 int interp_aout, unsigned long load_addr, 140 int interp_aout, unsigned long load_addr,
143 unsigned long interp_load_addr) 141 unsigned long interp_load_addr)
144{ 142{
@@ -161,7 +159,6 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
161 * for userspace to get any other way, in others (i386) it is 159 * for userspace to get any other way, in others (i386) it is
162 * merely difficult. 160 * merely difficult.
163 */ 161 */
164
165 u_platform = NULL; 162 u_platform = NULL;
166 if (k_platform) { 163 if (k_platform) {
167 size_t len = strlen(k_platform) + 1; 164 size_t len = strlen(k_platform) + 1;
@@ -171,7 +168,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
171 * evictions by the processes running on the same package. One 168 * evictions by the processes running on the same package. One
172 * thing we can do is to shuffle the initial stack for them. 169 * thing we can do is to shuffle the initial stack for them.
173 */ 170 */
174 171
175 p = arch_align_stack(p); 172 p = arch_align_stack(p);
176 173
177 u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len); 174 u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
@@ -180,9 +177,12 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
180 } 177 }
181 178
182 /* Create the ELF interpreter info */ 179 /* Create the ELF interpreter info */
183 elf_info = (elf_addr_t *) current->mm->saved_auxv; 180 elf_info = (elf_addr_t *)current->mm->saved_auxv;
184#define NEW_AUX_ENT(id, val) \ 181#define NEW_AUX_ENT(id, val) \
185 do { elf_info[ei_index++] = id; elf_info[ei_index++] = val; } while (0) 182 do { \
183 elf_info[ei_index++] = id; \
184 elf_info[ei_index++] = val; \
185 } while (0)
186 186
187#ifdef ARCH_DLINFO 187#ifdef ARCH_DLINFO
188 /* 188 /*
@@ -195,21 +195,22 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
195 NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE); 195 NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE);
196 NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC); 196 NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC);
197 NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff); 197 NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff);
198 NEW_AUX_ENT(AT_PHENT, sizeof (struct elf_phdr)); 198 NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr));
199 NEW_AUX_ENT(AT_PHNUM, exec->e_phnum); 199 NEW_AUX_ENT(AT_PHNUM, exec->e_phnum);
200 NEW_AUX_ENT(AT_BASE, interp_load_addr); 200 NEW_AUX_ENT(AT_BASE, interp_load_addr);
201 NEW_AUX_ENT(AT_FLAGS, 0); 201 NEW_AUX_ENT(AT_FLAGS, 0);
202 NEW_AUX_ENT(AT_ENTRY, exec->e_entry); 202 NEW_AUX_ENT(AT_ENTRY, exec->e_entry);
203 NEW_AUX_ENT(AT_UID, (elf_addr_t) tsk->uid); 203 NEW_AUX_ENT(AT_UID, tsk->uid);
204 NEW_AUX_ENT(AT_EUID, (elf_addr_t) tsk->euid); 204 NEW_AUX_ENT(AT_EUID, tsk->euid);
205 NEW_AUX_ENT(AT_GID, (elf_addr_t) tsk->gid); 205 NEW_AUX_ENT(AT_GID, tsk->gid);
206 NEW_AUX_ENT(AT_EGID, (elf_addr_t) tsk->egid); 206 NEW_AUX_ENT(AT_EGID, tsk->egid);
207 NEW_AUX_ENT(AT_SECURE, (elf_addr_t) security_bprm_secureexec(bprm)); 207 NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
208 if (k_platform) { 208 if (k_platform) {
209 NEW_AUX_ENT(AT_PLATFORM, (elf_addr_t)(unsigned long)u_platform); 209 NEW_AUX_ENT(AT_PLATFORM,
210 (elf_addr_t)(unsigned long)u_platform);
210 } 211 }
211 if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { 212 if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
212 NEW_AUX_ENT(AT_EXECFD, (elf_addr_t) bprm->interp_data); 213 NEW_AUX_ENT(AT_EXECFD, bprm->interp_data);
213 } 214 }
214#undef NEW_AUX_ENT 215#undef NEW_AUX_ENT
215 /* AT_NULL is zero; clear the rest too */ 216 /* AT_NULL is zero; clear the rest too */
@@ -232,7 +233,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
232 /* Point sp at the lowest address on the stack */ 233 /* Point sp at the lowest address on the stack */
233#ifdef CONFIG_STACK_GROWSUP 234#ifdef CONFIG_STACK_GROWSUP
234 sp = (elf_addr_t __user *)bprm->p - items - ei_index; 235 sp = (elf_addr_t __user *)bprm->p - items - ei_index;
235 bprm->exec = (unsigned long) sp; /* XXX: PARISC HACK */ 236 bprm->exec = (unsigned long)sp; /* XXX: PARISC HACK */
236#else 237#else
237 sp = (elf_addr_t __user *)bprm->p; 238 sp = (elf_addr_t __user *)bprm->p;
238#endif 239#endif
@@ -285,7 +286,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
285#ifndef elf_map 286#ifndef elf_map
286 287
287static unsigned long elf_map(struct file *filep, unsigned long addr, 288static unsigned long elf_map(struct file *filep, unsigned long addr,
288 struct elf_phdr *eppnt, int prot, int type) 289 struct elf_phdr *eppnt, int prot, int type)
289{ 290{
290 unsigned long map_addr; 291 unsigned long map_addr;
291 unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr); 292 unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr);
@@ -310,9 +311,8 @@ static unsigned long elf_map(struct file *filep, unsigned long addr,
310 is only provided so that we can read a.out libraries that have 311 is only provided so that we can read a.out libraries that have
311 an ELF header */ 312 an ELF header */
312 313
313static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, 314static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
314 struct file * interpreter, 315 struct file *interpreter, unsigned long *interp_load_addr)
315 unsigned long *interp_load_addr)
316{ 316{
317 struct elf_phdr *elf_phdata; 317 struct elf_phdr *elf_phdata;
318 struct elf_phdr *eppnt; 318 struct elf_phdr *eppnt;
@@ -342,15 +342,15 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
342 goto out; 342 goto out;
343 343
344 /* Now read in all of the header information */ 344 /* Now read in all of the header information */
345
346 size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum; 345 size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum;
347 if (size > ELF_MIN_ALIGN) 346 if (size > ELF_MIN_ALIGN)
348 goto out; 347 goto out;
349 elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); 348 elf_phdata = kmalloc(size, GFP_KERNEL);
350 if (!elf_phdata) 349 if (!elf_phdata)
351 goto out; 350 goto out;
352 351
353 retval = kernel_read(interpreter,interp_elf_ex->e_phoff,(char *)elf_phdata,size); 352 retval = kernel_read(interpreter, interp_elf_ex->e_phoff,
353 (char *)elf_phdata,size);
354 error = -EIO; 354 error = -EIO;
355 if (retval != size) { 355 if (retval != size) {
356 if (retval < 0) 356 if (retval < 0)
@@ -359,58 +359,65 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
359 } 359 }
360 360
361 eppnt = elf_phdata; 361 eppnt = elf_phdata;
362 for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) { 362 for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
363 if (eppnt->p_type == PT_LOAD) { 363 if (eppnt->p_type == PT_LOAD) {
364 int elf_type = MAP_PRIVATE | MAP_DENYWRITE; 364 int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
365 int elf_prot = 0; 365 int elf_prot = 0;
366 unsigned long vaddr = 0; 366 unsigned long vaddr = 0;
367 unsigned long k, map_addr; 367 unsigned long k, map_addr;
368 368
369 if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; 369 if (eppnt->p_flags & PF_R)
370 if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; 370 elf_prot = PROT_READ;
371 if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; 371 if (eppnt->p_flags & PF_W)
372 vaddr = eppnt->p_vaddr; 372 elf_prot |= PROT_WRITE;
373 if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) 373 if (eppnt->p_flags & PF_X)
374 elf_type |= MAP_FIXED; 374 elf_prot |= PROT_EXEC;
375 375 vaddr = eppnt->p_vaddr;
376 map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type); 376 if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
377 error = map_addr; 377 elf_type |= MAP_FIXED;
378 if (BAD_ADDR(map_addr)) 378
379 goto out_close; 379 map_addr = elf_map(interpreter, load_addr + vaddr,
380 380 eppnt, elf_prot, elf_type);
381 if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) { 381 error = map_addr;
382 load_addr = map_addr - ELF_PAGESTART(vaddr); 382 if (BAD_ADDR(map_addr))
383 load_addr_set = 1; 383 goto out_close;
384 } 384
385 385 if (!load_addr_set &&
386 /* 386 interp_elf_ex->e_type == ET_DYN) {
387 * Check to see if the section's size will overflow the 387 load_addr = map_addr - ELF_PAGESTART(vaddr);
388 * allowed task size. Note that p_filesz must always be 388 load_addr_set = 1;
389 * <= p_memsize so it is only necessary to check p_memsz. 389 }
390 */ 390
391 k = load_addr + eppnt->p_vaddr; 391 /*
392 if (k > TASK_SIZE || eppnt->p_filesz > eppnt->p_memsz || 392 * Check to see if the section's size will overflow the
393 eppnt->p_memsz > TASK_SIZE || TASK_SIZE - eppnt->p_memsz < k) { 393 * allowed task size. Note that p_filesz must always be
394 error = -ENOMEM; 394 * <= p_memsize so it's only necessary to check p_memsz.
395 goto out_close; 395 */
396 } 396 k = load_addr + eppnt->p_vaddr;
397 397 if (k > TASK_SIZE ||
398 /* 398 eppnt->p_filesz > eppnt->p_memsz ||
399 * Find the end of the file mapping for this phdr, and keep 399 eppnt->p_memsz > TASK_SIZE ||
400 * track of the largest address we see for this. 400 TASK_SIZE - eppnt->p_memsz < k) {
401 */ 401 error = -ENOMEM;
402 k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; 402 goto out_close;
403 if (k > elf_bss) 403 }
404 elf_bss = k; 404
405 405 /*
406 /* 406 * Find the end of the file mapping for this phdr, and
407 * Do the same thing for the memory mapping - between 407 * keep track of the largest address we see for this.
408 * elf_bss and last_bss is the bss section. 408 */
409 */ 409 k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
410 k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; 410 if (k > elf_bss)
411 if (k > last_bss) 411 elf_bss = k;
412 last_bss = k; 412
413 } 413 /*
414 * Do the same thing for the memory mapping - between
415 * elf_bss and last_bss is the bss section.
416 */
417 k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
418 if (k > last_bss)
419 last_bss = k;
420 }
414 } 421 }
415 422
416 /* 423 /*
@@ -424,7 +431,8 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
424 goto out_close; 431 goto out_close;
425 } 432 }
426 433
427 elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1); /* What we have mapped so far */ 434 /* What we have mapped so far */
435 elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);
428 436
429 /* Map the last of the bss segment */ 437 /* Map the last of the bss segment */
430 if (last_bss > elf_bss) { 438 if (last_bss > elf_bss) {
@@ -436,7 +444,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
436 } 444 }
437 445
438 *interp_load_addr = load_addr; 446 *interp_load_addr = load_addr;
439 error = ((unsigned long) interp_elf_ex->e_entry) + load_addr; 447 error = ((unsigned long)interp_elf_ex->e_entry) + load_addr;
440 448
441out_close: 449out_close:
442 kfree(elf_phdata); 450 kfree(elf_phdata);
@@ -444,8 +452,8 @@ out:
444 return error; 452 return error;
445} 453}
446 454
447static unsigned long load_aout_interp(struct exec * interp_ex, 455static unsigned long load_aout_interp(struct exec *interp_ex,
448 struct file * interpreter) 456 struct file *interpreter)
449{ 457{
450 unsigned long text_data, elf_entry = ~0UL; 458 unsigned long text_data, elf_entry = ~0UL;
451 char __user * addr; 459 char __user * addr;
@@ -464,7 +472,7 @@ static unsigned long load_aout_interp(struct exec * interp_ex,
464 case ZMAGIC: 472 case ZMAGIC:
465 case QMAGIC: 473 case QMAGIC:
466 offset = N_TXTOFF(*interp_ex); 474 offset = N_TXTOFF(*interp_ex);
467 addr = (char __user *) N_TXTADDR(*interp_ex); 475 addr = (char __user *)N_TXTADDR(*interp_ex);
468 break; 476 break;
469 default: 477 default:
470 goto out; 478 goto out;
@@ -480,7 +488,6 @@ static unsigned long load_aout_interp(struct exec * interp_ex,
480 flush_icache_range((unsigned long)addr, 488 flush_icache_range((unsigned long)addr,
481 (unsigned long)addr + text_data); 489 (unsigned long)addr + text_data);
482 490
483
484 down_write(&current->mm->mmap_sem); 491 down_write(&current->mm->mmap_sem);
485 do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), 492 do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
486 interp_ex->a_bss); 493 interp_ex->a_bss);
@@ -519,7 +526,7 @@ static unsigned long randomize_stack_top(unsigned long stack_top)
519#endif 526#endif
520} 527}
521 528
522static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) 529static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
523{ 530{
524 struct file *interpreter = NULL; /* to shut gcc up */ 531 struct file *interpreter = NULL; /* to shut gcc up */
525 unsigned long load_addr = 0, load_bias = 0; 532 unsigned long load_addr = 0, load_bias = 0;
@@ -528,7 +535,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
528 unsigned int interpreter_type = INTERPRETER_NONE; 535 unsigned int interpreter_type = INTERPRETER_NONE;
529 unsigned char ibcs2_interpreter = 0; 536 unsigned char ibcs2_interpreter = 0;
530 unsigned long error; 537 unsigned long error;
531 struct elf_phdr * elf_ppnt, *elf_phdata; 538 struct elf_phdr *elf_ppnt, *elf_phdata;
532 unsigned long elf_bss, elf_brk; 539 unsigned long elf_bss, elf_brk;
533 int elf_exec_fileno; 540 int elf_exec_fileno;
534 int retval, i; 541 int retval, i;
@@ -553,7 +560,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
553 } 560 }
554 561
555 /* Get the exec-header */ 562 /* Get the exec-header */
556 loc->elf_ex = *((struct elfhdr *) bprm->buf); 563 loc->elf_ex = *((struct elfhdr *)bprm->buf);
557 564
558 retval = -ENOEXEC; 565 retval = -ENOEXEC;
559 /* First of all, some simple consistency checks */ 566 /* First of all, some simple consistency checks */
@@ -568,7 +575,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
568 goto out; 575 goto out;
569 576
570 /* Now read in all of the header information */ 577 /* Now read in all of the header information */
571
572 if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr)) 578 if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr))
573 goto out; 579 goto out;
574 if (loc->elf_ex.e_phnum < 1 || 580 if (loc->elf_ex.e_phnum < 1 ||
@@ -576,18 +582,19 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
576 goto out; 582 goto out;
577 size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr); 583 size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr);
578 retval = -ENOMEM; 584 retval = -ENOMEM;
579 elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); 585 elf_phdata = kmalloc(size, GFP_KERNEL);
580 if (!elf_phdata) 586 if (!elf_phdata)
581 goto out; 587 goto out;
582 588
583 retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, (char *) elf_phdata, size); 589 retval = kernel_read(bprm->file, loc->elf_ex.e_phoff,
590 (char *)elf_phdata, size);
584 if (retval != size) { 591 if (retval != size) {
585 if (retval >= 0) 592 if (retval >= 0)
586 retval = -EIO; 593 retval = -EIO;
587 goto out_free_ph; 594 goto out_free_ph;
588 } 595 }
589 596
590 files = current->files; /* Refcounted so ok */ 597 files = current->files; /* Refcounted so ok */
591 retval = unshare_files(); 598 retval = unshare_files();
592 if (retval < 0) 599 if (retval < 0)
593 goto out_free_ph; 600 goto out_free_ph;
@@ -598,7 +605,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
598 605
599 /* exec will make our files private anyway, but for the a.out 606 /* exec will make our files private anyway, but for the a.out
600 loader stuff we need to do it earlier */ 607 loader stuff we need to do it earlier */
601
602 retval = get_unused_fd(); 608 retval = get_unused_fd();
603 if (retval < 0) 609 if (retval < 0)
604 goto out_free_fh; 610 goto out_free_fh;
@@ -620,7 +626,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
620 * shared libraries - for now assume that this 626 * shared libraries - for now assume that this
621 * is an a.out format binary 627 * is an a.out format binary
622 */ 628 */
623
624 retval = -ENOEXEC; 629 retval = -ENOEXEC;
625 if (elf_ppnt->p_filesz > PATH_MAX || 630 if (elf_ppnt->p_filesz > PATH_MAX ||
626 elf_ppnt->p_filesz < 2) 631 elf_ppnt->p_filesz < 2)
@@ -628,13 +633,13 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
628 633
629 retval = -ENOMEM; 634 retval = -ENOMEM;
630 elf_interpreter = kmalloc(elf_ppnt->p_filesz, 635 elf_interpreter = kmalloc(elf_ppnt->p_filesz,
631 GFP_KERNEL); 636 GFP_KERNEL);
632 if (!elf_interpreter) 637 if (!elf_interpreter)
633 goto out_free_file; 638 goto out_free_file;
634 639
635 retval = kernel_read(bprm->file, elf_ppnt->p_offset, 640 retval = kernel_read(bprm->file, elf_ppnt->p_offset,
636 elf_interpreter, 641 elf_interpreter,
637 elf_ppnt->p_filesz); 642 elf_ppnt->p_filesz);
638 if (retval != elf_ppnt->p_filesz) { 643 if (retval != elf_ppnt->p_filesz) {
639 if (retval >= 0) 644 if (retval >= 0)
640 retval = -EIO; 645 retval = -EIO;
@@ -678,7 +683,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
678 retval = PTR_ERR(interpreter); 683 retval = PTR_ERR(interpreter);
679 if (IS_ERR(interpreter)) 684 if (IS_ERR(interpreter))
680 goto out_free_interp; 685 goto out_free_interp;
681 retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE); 686 retval = kernel_read(interpreter, 0, bprm->buf,
687 BINPRM_BUF_SIZE);
682 if (retval != BINPRM_BUF_SIZE) { 688 if (retval != BINPRM_BUF_SIZE) {
683 if (retval >= 0) 689 if (retval >= 0)
684 retval = -EIO; 690 retval = -EIO;
@@ -686,8 +692,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
686 } 692 }
687 693
688 /* Get the exec headers */ 694 /* Get the exec headers */
689 loc->interp_ex = *((struct exec *) bprm->buf); 695 loc->interp_ex = *((struct exec *)bprm->buf);
690 loc->interp_elf_ex = *((struct elfhdr *) bprm->buf); 696 loc->interp_elf_ex = *((struct elfhdr *)bprm->buf);
691 break; 697 break;
692 } 698 }
693 elf_ppnt++; 699 elf_ppnt++;
@@ -739,7 +745,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
739 745
740 /* OK, we are done with that, now set up the arg stuff, 746 /* OK, we are done with that, now set up the arg stuff,
741 and then start this sucker up */ 747 and then start this sucker up */
742
743 if ((!bprm->sh_bang) && (interpreter_type == INTERPRETER_AOUT)) { 748 if ((!bprm->sh_bang) && (interpreter_type == INTERPRETER_AOUT)) {
744 char *passed_p = passed_fileno; 749 char *passed_p = passed_fileno;
745 sprintf(passed_fileno, "%d", elf_exec_fileno); 750 sprintf(passed_fileno, "%d", elf_exec_fileno);
@@ -759,7 +764,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
759 764
760 /* Discard our unneeded old files struct */ 765 /* Discard our unneeded old files struct */
761 if (files) { 766 if (files) {
762 steal_locks(files);
763 put_files_struct(files); 767 put_files_struct(files);
764 files = NULL; 768 files = NULL;
765 } 769 }
@@ -778,7 +782,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
778 if (elf_read_implies_exec(loc->elf_ex, executable_stack)) 782 if (elf_read_implies_exec(loc->elf_ex, executable_stack))
779 current->personality |= READ_IMPLIES_EXEC; 783 current->personality |= READ_IMPLIES_EXEC;
780 784
781 if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) 785 if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
782 current->flags |= PF_RANDOMIZE; 786 current->flags |= PF_RANDOMIZE;
783 arch_pick_mmap_layout(current->mm); 787 arch_pick_mmap_layout(current->mm);
784 788
@@ -799,8 +803,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
799 the correct location in memory. At this point, we assume that 803 the correct location in memory. At this point, we assume that
800 the image should be loaded at fixed address, not at a variable 804 the image should be loaded at fixed address, not at a variable
801 address. */ 805 address. */
802 806 for(i = 0, elf_ppnt = elf_phdata;
803 for(i = 0, elf_ppnt = elf_phdata; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { 807 i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
804 int elf_prot = 0, elf_flags; 808 int elf_prot = 0, elf_flags;
805 unsigned long k, vaddr; 809 unsigned long k, vaddr;
806 810
@@ -828,30 +832,35 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
828 load_bias, nbyte)) { 832 load_bias, nbyte)) {
829 /* 833 /*
830 * This bss-zeroing can fail if the ELF 834 * This bss-zeroing can fail if the ELF
831 * file specifies odd protections. So 835 * file specifies odd protections. So
832 * we don't check the return value 836 * we don't check the return value
833 */ 837 */
834 } 838 }
835 } 839 }
836 } 840 }
837 841
838 if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; 842 if (elf_ppnt->p_flags & PF_R)
839 if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; 843 elf_prot |= PROT_READ;
840 if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; 844 if (elf_ppnt->p_flags & PF_W)
845 elf_prot |= PROT_WRITE;
846 if (elf_ppnt->p_flags & PF_X)
847 elf_prot |= PROT_EXEC;
841 848
842 elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE; 849 elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE;
843 850
844 vaddr = elf_ppnt->p_vaddr; 851 vaddr = elf_ppnt->p_vaddr;
845 if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { 852 if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) {
846 elf_flags |= MAP_FIXED; 853 elf_flags |= MAP_FIXED;
847 } else if (loc->elf_ex.e_type == ET_DYN) { 854 } else if (loc->elf_ex.e_type == ET_DYN) {
848 /* Try and get dynamic programs out of the way of the default mmap 855 /* Try and get dynamic programs out of the way of the
849 base, as well as whatever program they might try to exec. This 856 * default mmap base, as well as whatever program they
850 is because the brk will follow the loader, and is not movable. */ 857 * might try to exec. This is because the brk will
858 * follow the loader, and is not movable. */
851 load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); 859 load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
852 } 860 }
853 861
854 error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags); 862 error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
863 elf_prot, elf_flags);
855 if (BAD_ADDR(error)) { 864 if (BAD_ADDR(error)) {
856 send_sig(SIGKILL, current, 0); 865 send_sig(SIGKILL, current, 0);
857 goto out_free_dentry; 866 goto out_free_dentry;
@@ -868,8 +877,10 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
868 } 877 }
869 } 878 }
870 k = elf_ppnt->p_vaddr; 879 k = elf_ppnt->p_vaddr;
871 if (k < start_code) start_code = k; 880 if (k < start_code)
872 if (start_data < k) start_data = k; 881 start_code = k;
882 if (start_data < k)
883 start_data = k;
873 884
874 /* 885 /*
875 * Check to see if the section's size will overflow the 886 * Check to see if the section's size will overflow the
@@ -879,7 +890,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
879 if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz || 890 if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
880 elf_ppnt->p_memsz > TASK_SIZE || 891 elf_ppnt->p_memsz > TASK_SIZE ||
881 TASK_SIZE - elf_ppnt->p_memsz < k) { 892 TASK_SIZE - elf_ppnt->p_memsz < k) {
882 /* set_brk can never work. Avoid overflows. */ 893 /* set_brk can never work. Avoid overflows. */
883 send_sig(SIGKILL, current, 0); 894 send_sig(SIGKILL, current, 0);
884 goto out_free_dentry; 895 goto out_free_dentry;
885 } 896 }
@@ -967,8 +978,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
967 978
968 compute_creds(bprm); 979 compute_creds(bprm);
969 current->flags &= ~PF_FORKNOEXEC; 980 current->flags &= ~PF_FORKNOEXEC;
970 create_elf_tables(bprm, &loc->elf_ex, (interpreter_type == INTERPRETER_AOUT), 981 create_elf_tables(bprm, &loc->elf_ex,
971 load_addr, interp_load_addr); 982 (interpreter_type == INTERPRETER_AOUT),
983 load_addr, interp_load_addr);
972 /* N.B. passed_fileno might not be initialized? */ 984 /* N.B. passed_fileno might not be initialized? */
973 if (interpreter_type == INTERPRETER_AOUT) 985 if (interpreter_type == INTERPRETER_AOUT)
974 current->mm->arg_start += strlen(passed_fileno) + 1; 986 current->mm->arg_start += strlen(passed_fileno) + 1;
@@ -982,7 +994,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
982 /* Why this, you ask??? Well SVr4 maps page 0 as read-only, 994 /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
983 and some applications "depend" upon this behavior. 995 and some applications "depend" upon this behavior.
984 Since we do not have the power to recompile these, we 996 Since we do not have the power to recompile these, we
985 emulate the SVr4 behavior. Sigh. */ 997 emulate the SVr4 behavior. Sigh. */
986 down_write(&current->mm->mmap_sem); 998 down_write(&current->mm->mmap_sem);
987 error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, 999 error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
988 MAP_FIXED | MAP_PRIVATE, 0); 1000 MAP_FIXED | MAP_PRIVATE, 0);
@@ -1037,7 +1049,6 @@ out_free_ph:
1037 1049
1038/* This is really simpleminded and specialized - we are loading an 1050/* This is really simpleminded and specialized - we are loading an
1039 a.out library that is given an ELF header. */ 1051 a.out library that is given an ELF header. */
1040
1041static int load_elf_library(struct file *file) 1052static int load_elf_library(struct file *file)
1042{ 1053{
1043 struct elf_phdr *elf_phdata; 1054 struct elf_phdr *elf_phdata;
@@ -1047,7 +1058,7 @@ static int load_elf_library(struct file *file)
1047 struct elfhdr elf_ex; 1058 struct elfhdr elf_ex;
1048 1059
1049 error = -ENOEXEC; 1060 error = -ENOEXEC;
1050 retval = kernel_read(file, 0, (char *) &elf_ex, sizeof(elf_ex)); 1061 retval = kernel_read(file, 0, (char *)&elf_ex, sizeof(elf_ex));
1051 if (retval != sizeof(elf_ex)) 1062 if (retval != sizeof(elf_ex))
1052 goto out; 1063 goto out;
1053 1064
@@ -1056,7 +1067,7 @@ static int load_elf_library(struct file *file)
1056 1067
1057 /* First of all, some simple consistency checks */ 1068 /* First of all, some simple consistency checks */
1058 if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || 1069 if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
1059 !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap) 1070 !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap)
1060 goto out; 1071 goto out;
1061 1072
1062 /* Now read in all of the header information */ 1073 /* Now read in all of the header information */
@@ -1104,7 +1115,8 @@ static int load_elf_library(struct file *file)
1104 goto out_free_ph; 1115 goto out_free_ph;
1105 } 1116 }
1106 1117
1107 len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + ELF_MIN_ALIGN - 1); 1118 len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr +
1119 ELF_MIN_ALIGN - 1);
1108 bss = eppnt->p_memsz + eppnt->p_vaddr; 1120 bss = eppnt->p_memsz + eppnt->p_vaddr;
1109 if (bss > len) { 1121 if (bss > len) {
1110 down_write(&current->mm->mmap_sem); 1122 down_write(&current->mm->mmap_sem);
@@ -1163,7 +1175,7 @@ static int maydump(struct vm_area_struct *vma)
1163 if (vma->vm_flags & (VM_IO | VM_RESERVED)) 1175 if (vma->vm_flags & (VM_IO | VM_RESERVED))
1164 return 0; 1176 return 0;
1165 1177
1166 /* Dump shared memory only if mapped from an anonymous file. */ 1178 /* Dump shared memory only if mapped from an anonymous file. */
1167 if (vma->vm_flags & VM_SHARED) 1179 if (vma->vm_flags & VM_SHARED)
1168 return vma->vm_file->f_dentry->d_inode->i_nlink == 0; 1180 return vma->vm_file->f_dentry->d_inode->i_nlink == 0;
1169 1181
@@ -1174,7 +1186,7 @@ static int maydump(struct vm_area_struct *vma)
1174 return 1; 1186 return 1;
1175} 1187}
1176 1188
1177#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) 1189#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
1178 1190
1179/* An ELF note in memory */ 1191/* An ELF note in memory */
1180struct memelfnote 1192struct memelfnote
@@ -1277,11 +1289,11 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
1277} 1289}
1278 1290
1279/* 1291/*
1280 * fill up all the fields in prstatus from the given task struct, except registers 1292 * fill up all the fields in prstatus from the given task struct, except
1281 * which need to be filled up separately. 1293 * registers which need to be filled up separately.
1282 */ 1294 */
1283static void fill_prstatus(struct elf_prstatus *prstatus, 1295static void fill_prstatus(struct elf_prstatus *prstatus,
1284 struct task_struct *p, long signr) 1296 struct task_struct *p, long signr)
1285{ 1297{
1286 prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; 1298 prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
1287 prstatus->pr_sigpend = p->pending.signal.sig[0]; 1299 prstatus->pr_sigpend = p->pending.signal.sig[0];
@@ -1366,8 +1378,8 @@ struct elf_thread_status
1366 1378
1367/* 1379/*
1368 * In order to add the specific thread information for the elf file format, 1380 * In order to add the specific thread information for the elf file format,
1369 * we need to keep a linked list of every threads pr_status and then 1381 * we need to keep a linked list of every threads pr_status and then create
1370 * create a single section for them in the final core file. 1382 * a single section for them in the final core file.
1371 */ 1383 */
1372static int elf_dump_thread_status(long signr, struct elf_thread_status *t) 1384static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
1373{ 1385{
@@ -1378,19 +1390,23 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
1378 fill_prstatus(&t->prstatus, p, signr); 1390 fill_prstatus(&t->prstatus, p, signr);
1379 elf_core_copy_task_regs(p, &t->prstatus.pr_reg); 1391 elf_core_copy_task_regs(p, &t->prstatus.pr_reg);
1380 1392
1381 fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus), &(t->prstatus)); 1393 fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus),
1394 &(t->prstatus));
1382 t->num_notes++; 1395 t->num_notes++;
1383 sz += notesize(&t->notes[0]); 1396 sz += notesize(&t->notes[0]);
1384 1397
1385 if ((t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL, &t->fpu))) { 1398 if ((t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL,
1386 fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu), &(t->fpu)); 1399 &t->fpu))) {
1400 fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu),
1401 &(t->fpu));
1387 t->num_notes++; 1402 t->num_notes++;
1388 sz += notesize(&t->notes[1]); 1403 sz += notesize(&t->notes[1]);
1389 } 1404 }
1390 1405
1391#ifdef ELF_CORE_COPY_XFPREGS 1406#ifdef ELF_CORE_COPY_XFPREGS
1392 if (elf_core_copy_task_xfpregs(p, &t->xfpu)) { 1407 if (elf_core_copy_task_xfpregs(p, &t->xfpu)) {
1393 fill_note(&t->notes[2], "LINUX", NT_PRXFPREG, sizeof(t->xfpu), &t->xfpu); 1408 fill_note(&t->notes[2], "LINUX", NT_PRXFPREG, sizeof(t->xfpu),
1409 &t->xfpu);
1394 t->num_notes++; 1410 t->num_notes++;
1395 sz += notesize(&t->notes[2]); 1411 sz += notesize(&t->notes[2]);
1396 } 1412 }
@@ -1405,7 +1421,7 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
1405 * and then they are actually written out. If we run out of core limit 1421 * and then they are actually written out. If we run out of core limit
1406 * we just truncate. 1422 * we just truncate.
1407 */ 1423 */
1408static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) 1424static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1409{ 1425{
1410#define NUM_NOTES 6 1426#define NUM_NOTES 6
1411 int has_dumped = 0; 1427 int has_dumped = 0;
@@ -1434,12 +1450,12 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
1434 /* 1450 /*
1435 * We no longer stop all VM operations. 1451 * We no longer stop all VM operations.
1436 * 1452 *
1437 * This is because those proceses that could possibly change map_count or 1453 * This is because those proceses that could possibly change map_count
1438 * the mmap / vma pages are now blocked in do_exit on current finishing 1454 * or the mmap / vma pages are now blocked in do_exit on current
1439 * this core dump. 1455 * finishing this core dump.
1440 * 1456 *
1441 * Only ptrace can touch these memory addresses, but it doesn't change 1457 * Only ptrace can touch these memory addresses, but it doesn't change
1442 * the map_count or the pages allocated. So no possibility of crashing 1458 * the map_count or the pages allocated. So no possibility of crashing
1443 * exists while dumping the mm->vm_next areas to the core file. 1459 * exists while dumping the mm->vm_next areas to the core file.
1444 */ 1460 */
1445 1461
@@ -1501,7 +1517,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
1501#endif 1517#endif
1502 1518
1503 /* Set up header */ 1519 /* Set up header */
1504 fill_elf_header(elf, segs+1); /* including notes section */ 1520 fill_elf_header(elf, segs + 1); /* including notes section */
1505 1521
1506 has_dumped = 1; 1522 has_dumped = 1;
1507 current->flags |= PF_DUMPCORE; 1523 current->flags |= PF_DUMPCORE;
@@ -1511,24 +1527,24 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
1511 * with info from their /proc. 1527 * with info from their /proc.
1512 */ 1528 */
1513 1529
1514 fill_note(notes +0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus); 1530 fill_note(notes + 0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus);
1515
1516 fill_psinfo(psinfo, current->group_leader, current->mm); 1531 fill_psinfo(psinfo, current->group_leader, current->mm);
1517 fill_note(notes +1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); 1532 fill_note(notes + 1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
1518 1533
1519 numnote = 2; 1534 numnote = 2;
1520 1535
1521 auxv = (elf_addr_t *) current->mm->saved_auxv; 1536 auxv = (elf_addr_t *)current->mm->saved_auxv;
1522 1537
1523 i = 0; 1538 i = 0;
1524 do 1539 do
1525 i += 2; 1540 i += 2;
1526 while (auxv[i - 2] != AT_NULL); 1541 while (auxv[i - 2] != AT_NULL);
1527 fill_note(&notes[numnote++], "CORE", NT_AUXV, 1542 fill_note(&notes[numnote++], "CORE", NT_AUXV,
1528 i * sizeof (elf_addr_t), auxv); 1543 i * sizeof(elf_addr_t), auxv);
1529 1544
1530 /* Try to dump the FPU. */ 1545 /* Try to dump the FPU. */
1531 if ((prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs, fpu))) 1546 if ((prstatus->pr_fpvalid =
1547 elf_core_copy_task_fpregs(current, regs, fpu)))
1532 fill_note(notes + numnote++, 1548 fill_note(notes + numnote++,
1533 "CORE", NT_PRFPREG, sizeof(*fpu), fpu); 1549 "CORE", NT_PRFPREG, sizeof(*fpu), fpu);
1534#ifdef ELF_CORE_COPY_XFPREGS 1550#ifdef ELF_CORE_COPY_XFPREGS
@@ -1577,8 +1593,10 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
1577 phdr.p_memsz = sz; 1593 phdr.p_memsz = sz;
1578 offset += phdr.p_filesz; 1594 offset += phdr.p_filesz;
1579 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; 1595 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
1580 if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W; 1596 if (vma->vm_flags & VM_WRITE)
1581 if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X; 1597 phdr.p_flags |= PF_W;
1598 if (vma->vm_flags & VM_EXEC)
1599 phdr.p_flags |= PF_X;
1582 phdr.p_align = ELF_EXEC_PAGESIZE; 1600 phdr.p_align = ELF_EXEC_PAGESIZE;
1583 1601
1584 DUMP_WRITE(&phdr, sizeof(phdr)); 1602 DUMP_WRITE(&phdr, sizeof(phdr));
@@ -1595,7 +1613,9 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
1595 1613
1596 /* write out the thread status notes section */ 1614 /* write out the thread status notes section */
1597 list_for_each(t, &thread_list) { 1615 list_for_each(t, &thread_list) {
1598 struct elf_thread_status *tmp = list_entry(t, struct elf_thread_status, list); 1616 struct elf_thread_status *tmp =
1617 list_entry(t, struct elf_thread_status, list);
1618
1599 for (i = 0; i < tmp->num_notes; i++) 1619 for (i = 0; i < tmp->num_notes; i++)
1600 if (!writenote(&tmp->notes[i], file)) 1620 if (!writenote(&tmp->notes[i], file))
1601 goto end_coredump; 1621 goto end_coredump;
@@ -1612,18 +1632,19 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
1612 for (addr = vma->vm_start; 1632 for (addr = vma->vm_start;
1613 addr < vma->vm_end; 1633 addr < vma->vm_end;
1614 addr += PAGE_SIZE) { 1634 addr += PAGE_SIZE) {
1615 struct page* page; 1635 struct page *page;
1616 struct vm_area_struct *vma; 1636 struct vm_area_struct *vma;
1617 1637
1618 if (get_user_pages(current, current->mm, addr, 1, 0, 1, 1638 if (get_user_pages(current, current->mm, addr, 1, 0, 1,
1619 &page, &vma) <= 0) { 1639 &page, &vma) <= 0) {
1620 DUMP_SEEK (file->f_pos + PAGE_SIZE); 1640 DUMP_SEEK(file->f_pos + PAGE_SIZE);
1621 } else { 1641 } else {
1622 if (page == ZERO_PAGE(addr)) { 1642 if (page == ZERO_PAGE(addr)) {
1623 DUMP_SEEK (file->f_pos + PAGE_SIZE); 1643 DUMP_SEEK(file->f_pos + PAGE_SIZE);
1624 } else { 1644 } else {
1625 void *kaddr; 1645 void *kaddr;
1626 flush_cache_page(vma, addr, page_to_pfn(page)); 1646 flush_cache_page(vma, addr,
1647 page_to_pfn(page));
1627 kaddr = kmap(page); 1648 kaddr = kmap(page);
1628 if ((size += PAGE_SIZE) > limit || 1649 if ((size += PAGE_SIZE) > limit ||
1629 !dump_write(file, kaddr, 1650 !dump_write(file, kaddr,
@@ -1645,7 +1666,8 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
1645 1666
1646 if ((off_t)file->f_pos != offset) { 1667 if ((off_t)file->f_pos != offset) {
1647 /* Sanity check */ 1668 /* Sanity check */
1648 printk(KERN_WARNING "elf_core_dump: file->f_pos (%ld) != offset (%ld)\n", 1669 printk(KERN_WARNING
1670 "elf_core_dump: file->f_pos (%ld) != offset (%ld)\n",
1649 (off_t)file->f_pos, offset); 1671 (off_t)file->f_pos, offset);
1650 } 1672 }
1651 1673
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index a2e48c999c24..eba4e23b9ca0 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -435,9 +435,10 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
435 struct elf_fdpic_params *interp_params) 435 struct elf_fdpic_params *interp_params)
436{ 436{
437 unsigned long sp, csp, nitems; 437 unsigned long sp, csp, nitems;
438 elf_caddr_t *argv, *envp; 438 elf_caddr_t __user *argv, *envp;
439 size_t platform_len = 0, len; 439 size_t platform_len = 0, len;
440 char *k_platform, *u_platform, *p; 440 char *k_platform;
441 char __user *u_platform, *p;
441 long hwcap; 442 long hwcap;
442 int loop; 443 int loop;
443 444
@@ -462,12 +463,11 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
462 if (k_platform) { 463 if (k_platform) {
463 platform_len = strlen(k_platform) + 1; 464 platform_len = strlen(k_platform) + 1;
464 sp -= platform_len; 465 sp -= platform_len;
466 u_platform = (char __user *) sp;
465 if (__copy_to_user(u_platform, k_platform, platform_len) != 0) 467 if (__copy_to_user(u_platform, k_platform, platform_len) != 0)
466 return -EFAULT; 468 return -EFAULT;
467 } 469 }
468 470
469 u_platform = (char *) sp;
470
471#if defined(__i386__) && defined(CONFIG_SMP) 471#if defined(__i386__) && defined(CONFIG_SMP)
472 /* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions 472 /* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
473 * by the processes running on the same package. One thing we can do 473 * by the processes running on the same package. One thing we can do
@@ -490,7 +490,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
490 sp = (sp - len) & ~7UL; 490 sp = (sp - len) & ~7UL;
491 exec_params->map_addr = sp; 491 exec_params->map_addr = sp;
492 492
493 if (copy_to_user((void *) sp, exec_params->loadmap, len) != 0) 493 if (copy_to_user((void __user *) sp, exec_params->loadmap, len) != 0)
494 return -EFAULT; 494 return -EFAULT;
495 495
496 current->mm->context.exec_fdpic_loadmap = (unsigned long) sp; 496 current->mm->context.exec_fdpic_loadmap = (unsigned long) sp;
@@ -501,7 +501,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
501 sp = (sp - len) & ~7UL; 501 sp = (sp - len) & ~7UL;
502 interp_params->map_addr = sp; 502 interp_params->map_addr = sp;
503 503
504 if (copy_to_user((void *) sp, interp_params->loadmap, len) != 0) 504 if (copy_to_user((void __user *) sp, interp_params->loadmap, len) != 0)
505 return -EFAULT; 505 return -EFAULT;
506 506
507 current->mm->context.interp_fdpic_loadmap = (unsigned long) sp; 507 current->mm->context.interp_fdpic_loadmap = (unsigned long) sp;
@@ -527,7 +527,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
527 /* put the ELF interpreter info on the stack */ 527 /* put the ELF interpreter info on the stack */
528#define NEW_AUX_ENT(nr, id, val) \ 528#define NEW_AUX_ENT(nr, id, val) \
529 do { \ 529 do { \
530 struct { unsigned long _id, _val; } *ent = (void *) csp; \ 530 struct { unsigned long _id, _val; } __user *ent = (void __user *) csp; \
531 __put_user((id), &ent[nr]._id); \ 531 __put_user((id), &ent[nr]._id); \
532 __put_user((val), &ent[nr]._val); \ 532 __put_user((val), &ent[nr]._val); \
533 } while (0) 533 } while (0)
@@ -564,13 +564,13 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
564 564
565 /* allocate room for argv[] and envv[] */ 565 /* allocate room for argv[] and envv[] */
566 csp -= (bprm->envc + 1) * sizeof(elf_caddr_t); 566 csp -= (bprm->envc + 1) * sizeof(elf_caddr_t);
567 envp = (elf_caddr_t *) csp; 567 envp = (elf_caddr_t __user *) csp;
568 csp -= (bprm->argc + 1) * sizeof(elf_caddr_t); 568 csp -= (bprm->argc + 1) * sizeof(elf_caddr_t);
569 argv = (elf_caddr_t *) csp; 569 argv = (elf_caddr_t __user *) csp;
570 570
571 /* stack argc */ 571 /* stack argc */
572 csp -= sizeof(unsigned long); 572 csp -= sizeof(unsigned long);
573 __put_user(bprm->argc, (unsigned long *) csp); 573 __put_user(bprm->argc, (unsigned long __user *) csp);
574 574
575 BUG_ON(csp != sp); 575 BUG_ON(csp != sp);
576 576
@@ -581,7 +581,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
581 current->mm->arg_start = current->mm->start_stack - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p); 581 current->mm->arg_start = current->mm->start_stack - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p);
582#endif 582#endif
583 583
584 p = (char *) current->mm->arg_start; 584 p = (char __user *) current->mm->arg_start;
585 for (loop = bprm->argc; loop > 0; loop--) { 585 for (loop = bprm->argc; loop > 0; loop--) {
586 __put_user((elf_caddr_t) p, argv++); 586 __put_user((elf_caddr_t) p, argv++);
587 len = strnlen_user(p, PAGE_SIZE * MAX_ARG_PAGES); 587 len = strnlen_user(p, PAGE_SIZE * MAX_ARG_PAGES);
@@ -1025,7 +1025,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
1025 /* clear the bit between beginning of mapping and beginning of PT_LOAD */ 1025 /* clear the bit between beginning of mapping and beginning of PT_LOAD */
1026 if (prot & PROT_WRITE && disp > 0) { 1026 if (prot & PROT_WRITE && disp > 0) {
1027 kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp); 1027 kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp);
1028 clear_user((void *) maddr, disp); 1028 clear_user((void __user *) maddr, disp);
1029 maddr += disp; 1029 maddr += disp;
1030 } 1030 }
1031 1031
@@ -1059,7 +1059,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
1059 if (prot & PROT_WRITE && excess1 > 0) { 1059 if (prot & PROT_WRITE && excess1 > 0) {
1060 kdebug("clear[%d] ad=%lx sz=%lx", 1060 kdebug("clear[%d] ad=%lx sz=%lx",
1061 loop, maddr + phdr->p_filesz, excess1); 1061 loop, maddr + phdr->p_filesz, excess1);
1062 clear_user((void *) maddr + phdr->p_filesz, excess1); 1062 clear_user((void __user *) maddr + phdr->p_filesz, excess1);
1063 } 1063 }
1064 1064
1065#else 1065#else
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index d73d75591a39..07a4996cca3f 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -203,7 +203,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
203 goto _error; 203 goto _error;
204 204
205 if (files) { 205 if (files) {
206 steal_locks(files);
207 put_files_struct(files); 206 put_files_struct(files);
208 files = NULL; 207 files = NULL;
209 } 208 }
@@ -740,10 +739,10 @@ static int bm_fill_super(struct super_block * sb, void * data, int silent)
740 return err; 739 return err;
741} 740}
742 741
743static struct super_block *bm_get_sb(struct file_system_type *fs_type, 742static int bm_get_sb(struct file_system_type *fs_type,
744 int flags, const char *dev_name, void *data) 743 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
745{ 744{
746 return get_sb_single(fs_type, flags, data, bm_fill_super); 745 return get_sb_single(fs_type, flags, data, bm_fill_super, mnt);
747} 746}
748 747
749static struct linux_binfmt misc_format = { 748static struct linux_binfmt misc_format = {
diff --git a/fs/block_dev.c b/fs/block_dev.c
index f5958f413bd1..028d9fb9c2d5 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -300,10 +300,10 @@ static struct super_operations bdev_sops = {
300 .clear_inode = bdev_clear_inode, 300 .clear_inode = bdev_clear_inode,
301}; 301};
302 302
303static struct super_block *bd_get_sb(struct file_system_type *fs_type, 303static int bd_get_sb(struct file_system_type *fs_type,
304 int flags, const char *dev_name, void *data) 304 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
305{ 305{
306 return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576); 306 return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576, mnt);
307} 307}
308 308
309static struct file_system_type bd_type = { 309static struct file_system_type bd_type = {
@@ -414,21 +414,31 @@ EXPORT_SYMBOL(bdput);
414static struct block_device *bd_acquire(struct inode *inode) 414static struct block_device *bd_acquire(struct inode *inode)
415{ 415{
416 struct block_device *bdev; 416 struct block_device *bdev;
417
417 spin_lock(&bdev_lock); 418 spin_lock(&bdev_lock);
418 bdev = inode->i_bdev; 419 bdev = inode->i_bdev;
419 if (bdev && igrab(bdev->bd_inode)) { 420 if (bdev) {
421 atomic_inc(&bdev->bd_inode->i_count);
420 spin_unlock(&bdev_lock); 422 spin_unlock(&bdev_lock);
421 return bdev; 423 return bdev;
422 } 424 }
423 spin_unlock(&bdev_lock); 425 spin_unlock(&bdev_lock);
426
424 bdev = bdget(inode->i_rdev); 427 bdev = bdget(inode->i_rdev);
425 if (bdev) { 428 if (bdev) {
426 spin_lock(&bdev_lock); 429 spin_lock(&bdev_lock);
427 if (inode->i_bdev) 430 if (!inode->i_bdev) {
428 __bd_forget(inode); 431 /*
429 inode->i_bdev = bdev; 432 * We take an additional bd_inode->i_count for inode,
430 inode->i_mapping = bdev->bd_inode->i_mapping; 433 * and it's released in clear_inode() of inode.
431 list_add(&inode->i_devices, &bdev->bd_inodes); 434 * So, we can access it via ->i_mapping always
435 * without igrab().
436 */
437 atomic_inc(&bdev->bd_inode->i_count);
438 inode->i_bdev = bdev;
439 inode->i_mapping = bdev->bd_inode->i_mapping;
440 list_add(&inode->i_devices, &bdev->bd_inodes);
441 }
432 spin_unlock(&bdev_lock); 442 spin_unlock(&bdev_lock);
433 } 443 }
434 return bdev; 444 return bdev;
@@ -438,10 +448,18 @@ static struct block_device *bd_acquire(struct inode *inode)
438 448
439void bd_forget(struct inode *inode) 449void bd_forget(struct inode *inode)
440{ 450{
451 struct block_device *bdev = NULL;
452
441 spin_lock(&bdev_lock); 453 spin_lock(&bdev_lock);
442 if (inode->i_bdev) 454 if (inode->i_bdev) {
455 if (inode->i_sb != blockdev_superblock)
456 bdev = inode->i_bdev;
443 __bd_forget(inode); 457 __bd_forget(inode);
458 }
444 spin_unlock(&bdev_lock); 459 spin_unlock(&bdev_lock);
460
461 if (bdev)
462 iput(bdev->bd_inode);
445} 463}
446 464
447int bd_claim(struct block_device *bdev, void *holder) 465int bd_claim(struct block_device *bdev, void *holder)
diff --git a/fs/buffer.c b/fs/buffer.c
index 23f1f3a68077..373bb6292bdc 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -331,7 +331,6 @@ long do_fsync(struct file *file, int datasync)
331 goto out; 331 goto out;
332 } 332 }
333 333
334 current->flags |= PF_SYNCWRITE;
335 ret = filemap_fdatawrite(mapping); 334 ret = filemap_fdatawrite(mapping);
336 335
337 /* 336 /*
@@ -346,7 +345,6 @@ long do_fsync(struct file *file, int datasync)
346 err = filemap_fdatawait(mapping); 345 err = filemap_fdatawait(mapping);
347 if (!ret) 346 if (!ret)
348 ret = err; 347 ret = err;
349 current->flags &= ~PF_SYNCWRITE;
350out: 348out:
351 return ret; 349 return ret;
352} 350}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index fb7c11c2c913..f2e285457bee 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -166,8 +166,9 @@ cifs_put_super(struct super_block *sb)
166} 166}
167 167
168static int 168static int
169cifs_statfs(struct super_block *sb, struct kstatfs *buf) 169cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
170{ 170{
171 struct super_block *sb = dentry->d_sb;
171 int xid; 172 int xid;
172 int rc = -EOPNOTSUPP; 173 int rc = -EOPNOTSUPP;
173 struct cifs_sb_info *cifs_sb; 174 struct cifs_sb_info *cifs_sb;
@@ -460,9 +461,9 @@ struct super_operations cifs_super_ops = {
460 .remount_fs = cifs_remount, 461 .remount_fs = cifs_remount,
461}; 462};
462 463
463static struct super_block * 464static int
464cifs_get_sb(struct file_system_type *fs_type, 465cifs_get_sb(struct file_system_type *fs_type,
465 int flags, const char *dev_name, void *data) 466 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
466{ 467{
467 int rc; 468 int rc;
468 struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL); 469 struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
@@ -470,7 +471,7 @@ cifs_get_sb(struct file_system_type *fs_type,
470 cFYI(1, ("Devname: %s flags: %d ", dev_name, flags)); 471 cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
471 472
472 if (IS_ERR(sb)) 473 if (IS_ERR(sb))
473 return sb; 474 return PTR_ERR(sb);
474 475
475 sb->s_flags = flags; 476 sb->s_flags = flags;
476 477
@@ -478,10 +479,10 @@ cifs_get_sb(struct file_system_type *fs_type,
478 if (rc) { 479 if (rc) {
479 up_write(&sb->s_umount); 480 up_write(&sb->s_umount);
480 deactivate_super(sb); 481 deactivate_super(sb);
481 return ERR_PTR(rc); 482 return rc;
482 } 483 }
483 sb->s_flags |= MS_ACTIVE; 484 sb->s_flags |= MS_ACTIVE;
484 return sb; 485 return simple_set_mnt(mnt, sb);
485} 486}
486 487
487static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov, 488static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov,
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 3011df988bd5..a6384d83fdef 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -75,7 +75,7 @@ extern ssize_t cifs_user_write(struct file *file, const char __user *write_data,
75 size_t write_size, loff_t * poffset); 75 size_t write_size, loff_t * poffset);
76extern int cifs_lock(struct file *, int, struct file_lock *); 76extern int cifs_lock(struct file *, int, struct file_lock *);
77extern int cifs_fsync(struct file *, struct dentry *, int); 77extern int cifs_fsync(struct file *, struct dentry *, int);
78extern int cifs_flush(struct file *); 78extern int cifs_flush(struct file *, fl_owner_t id);
79extern int cifs_file_mmap(struct file * , struct vm_area_struct *); 79extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
80extern const struct file_operations cifs_dir_ops; 80extern const struct file_operations cifs_dir_ops;
81extern int cifs_dir_open(struct inode *inode, struct file *file); 81extern int cifs_dir_open(struct inode *inode, struct file *file);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index fafdcdffba62..616b140534be 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1084,9 +1084,9 @@ static int cifs_writepages(struct address_space *mapping,
1084 unsigned int bytes_written; 1084 unsigned int bytes_written;
1085 struct cifs_sb_info *cifs_sb; 1085 struct cifs_sb_info *cifs_sb;
1086 int done = 0; 1086 int done = 0;
1087 pgoff_t end = -1; 1087 pgoff_t end;
1088 pgoff_t index; 1088 pgoff_t index;
1089 int is_range = 0; 1089 int range_whole = 0;
1090 struct kvec iov[32]; 1090 struct kvec iov[32];
1091 int len; 1091 int len;
1092 int n_iov = 0; 1092 int n_iov = 0;
@@ -1127,16 +1127,14 @@ static int cifs_writepages(struct address_space *mapping,
1127 xid = GetXid(); 1127 xid = GetXid();
1128 1128
1129 pagevec_init(&pvec, 0); 1129 pagevec_init(&pvec, 0);
1130 if (wbc->sync_mode == WB_SYNC_NONE) 1130 if (wbc->range_cyclic) {
1131 index = mapping->writeback_index; /* Start from prev offset */ 1131 index = mapping->writeback_index; /* Start from prev offset */
1132 else { 1132 end = -1;
1133 index = 0; 1133 } else {
1134 scanned = 1; 1134 index = wbc->range_start >> PAGE_CACHE_SHIFT;
1135 } 1135 end = wbc->range_end >> PAGE_CACHE_SHIFT;
1136 if (wbc->start || wbc->end) { 1136 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
1137 index = wbc->start >> PAGE_CACHE_SHIFT; 1137 range_whole = 1;
1138 end = wbc->end >> PAGE_CACHE_SHIFT;
1139 is_range = 1;
1140 scanned = 1; 1138 scanned = 1;
1141 } 1139 }
1142retry: 1140retry:
@@ -1172,7 +1170,7 @@ retry:
1172 break; 1170 break;
1173 } 1171 }
1174 1172
1175 if (unlikely(is_range) && (page->index > end)) { 1173 if (!wbc->range_cyclic && page->index > end) {
1176 done = 1; 1174 done = 1;
1177 unlock_page(page); 1175 unlock_page(page);
1178 break; 1176 break;
@@ -1276,7 +1274,7 @@ retry:
1276 index = 0; 1274 index = 0;
1277 goto retry; 1275 goto retry;
1278 } 1276 }
1279 if (!is_range) 1277 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
1280 mapping->writeback_index = index; 1278 mapping->writeback_index = index;
1281 1279
1282 FreeXid(xid); 1280 FreeXid(xid);
@@ -1424,7 +1422,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1424 * As file closes, flush all cached write data for this inode checking 1422 * As file closes, flush all cached write data for this inode checking
1425 * for write behind errors. 1423 * for write behind errors.
1426 */ 1424 */
1427int cifs_flush(struct file *file) 1425int cifs_flush(struct file *file, fl_owner_t id)
1428{ 1426{
1429 struct inode * inode = file->f_dentry->d_inode; 1427 struct inode * inode = file->f_dentry->d_inode;
1430 int rc = 0; 1428 int rc = 0;
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 7c2642431fa5..cc66c681bd11 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -164,7 +164,7 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
164 return 0; 164 return 0;
165} 165}
166 166
167int coda_flush(struct file *coda_file) 167int coda_flush(struct file *coda_file, fl_owner_t id)
168{ 168{
169 unsigned short flags = coda_file->f_flags & ~O_EXCL; 169 unsigned short flags = coda_file->f_flags & ~O_EXCL;
170 unsigned short coda_flags = coda_flags_to_cflags(flags); 170 unsigned short coda_flags = coda_flags_to_cflags(flags);
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index ada1a81df6bd..87f1dc8aa24b 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -36,7 +36,7 @@
36/* VFS super_block ops */ 36/* VFS super_block ops */
37static void coda_clear_inode(struct inode *); 37static void coda_clear_inode(struct inode *);
38static void coda_put_super(struct super_block *); 38static void coda_put_super(struct super_block *);
39static int coda_statfs(struct super_block *sb, struct kstatfs *buf); 39static int coda_statfs(struct dentry *dentry, struct kstatfs *buf);
40 40
41static kmem_cache_t * coda_inode_cachep; 41static kmem_cache_t * coda_inode_cachep;
42 42
@@ -278,13 +278,13 @@ struct inode_operations coda_file_inode_operations = {
278 .setattr = coda_setattr, 278 .setattr = coda_setattr,
279}; 279};
280 280
281static int coda_statfs(struct super_block *sb, struct kstatfs *buf) 281static int coda_statfs(struct dentry *dentry, struct kstatfs *buf)
282{ 282{
283 int error; 283 int error;
284 284
285 lock_kernel(); 285 lock_kernel();
286 286
287 error = venus_statfs(sb, buf); 287 error = venus_statfs(dentry, buf);
288 288
289 unlock_kernel(); 289 unlock_kernel();
290 290
@@ -307,10 +307,10 @@ static int coda_statfs(struct super_block *sb, struct kstatfs *buf)
307 307
308/* init_coda: used by filesystems.c to register coda */ 308/* init_coda: used by filesystems.c to register coda */
309 309
310static struct super_block *coda_get_sb(struct file_system_type *fs_type, 310static int coda_get_sb(struct file_system_type *fs_type,
311 int flags, const char *dev_name, void *data) 311 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
312{ 312{
313 return get_sb_nodev(fs_type, flags, data, coda_fill_super); 313 return get_sb_nodev(fs_type, flags, data, coda_fill_super, mnt);
314} 314}
315 315
316struct file_system_type coda_fs_type = { 316struct file_system_type coda_fs_type = {
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 1bae99650a91..b040eba13a7d 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -611,7 +611,7 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
611 return error; 611 return error;
612} 612}
613 613
614int venus_statfs(struct super_block *sb, struct kstatfs *sfs) 614int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
615{ 615{
616 union inputArgs *inp; 616 union inputArgs *inp;
617 union outputArgs *outp; 617 union outputArgs *outp;
@@ -620,7 +620,7 @@ int venus_statfs(struct super_block *sb, struct kstatfs *sfs)
620 insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs)); 620 insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs));
621 UPARG(CODA_STATFS); 621 UPARG(CODA_STATFS);
622 622
623 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 623 error = coda_upcall(coda_sbp(dentry->d_sb), insize, &outsize, inp);
624 624
625 if (!error) { 625 if (!error) {
626 sfs->f_blocks = outp->coda_statfs.stat.f_blocks; 626 sfs->f_blocks = outp->coda_statfs.stat.f_blocks;
diff --git a/fs/compat.c b/fs/compat.c
index b1f64786a613..7e7e5bc4f3cf 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -197,7 +197,7 @@ asmlinkage long compat_sys_statfs(const char __user *path, struct compat_statfs
197 error = user_path_walk(path, &nd); 197 error = user_path_walk(path, &nd);
198 if (!error) { 198 if (!error) {
199 struct kstatfs tmp; 199 struct kstatfs tmp;
200 error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); 200 error = vfs_statfs(nd.dentry, &tmp);
201 if (!error) 201 if (!error)
202 error = put_compat_statfs(buf, &tmp); 202 error = put_compat_statfs(buf, &tmp);
203 path_release(&nd); 203 path_release(&nd);
@@ -215,7 +215,7 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user
215 file = fget(fd); 215 file = fget(fd);
216 if (!file) 216 if (!file)
217 goto out; 217 goto out;
218 error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); 218 error = vfs_statfs(file->f_dentry, &tmp);
219 if (!error) 219 if (!error)
220 error = put_compat_statfs(buf, &tmp); 220 error = put_compat_statfs(buf, &tmp);
221 fput(file); 221 fput(file);
@@ -265,7 +265,7 @@ asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, s
265 error = user_path_walk(path, &nd); 265 error = user_path_walk(path, &nd);
266 if (!error) { 266 if (!error) {
267 struct kstatfs tmp; 267 struct kstatfs tmp;
268 error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); 268 error = vfs_statfs(nd.dentry, &tmp);
269 if (!error) 269 if (!error)
270 error = put_compat_statfs64(buf, &tmp); 270 error = put_compat_statfs64(buf, &tmp);
271 path_release(&nd); 271 path_release(&nd);
@@ -286,7 +286,7 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c
286 file = fget(fd); 286 file = fget(fd);
287 if (!file) 287 if (!file)
288 goto out; 288 goto out;
289 error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); 289 error = vfs_statfs(file->f_dentry, &tmp);
290 if (!error) 290 if (!error)
291 error = put_compat_statfs64(buf, &tmp); 291 error = put_compat_statfs64(buf, &tmp);
292 fput(file); 292 fput(file);
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
index f920d30478e5..94dab7bdd851 100644
--- a/fs/configfs/mount.c
+++ b/fs/configfs/mount.c
@@ -103,10 +103,10 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent)
103 return 0; 103 return 0;
104} 104}
105 105
106static struct super_block *configfs_get_sb(struct file_system_type *fs_type, 106static int configfs_get_sb(struct file_system_type *fs_type,
107 int flags, const char *dev_name, void *data) 107 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
108{ 108{
109 return get_sb_single(fs_type, flags, data, configfs_fill_super); 109 return get_sb_single(fs_type, flags, data, configfs_fill_super, mnt);
110} 110}
111 111
112static struct file_system_type configfs_fs_type = { 112static struct file_system_type configfs_fs_type = {
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 9efcc3a164e8..c45d73860803 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -181,9 +181,7 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
181 struct page *page = NULL; 181 struct page *page = NULL;
182 182
183 if (blocknr + i < devsize) { 183 if (blocknr + i < devsize) {
184 page = read_cache_page(mapping, blocknr + i, 184 page = read_mapping_page(mapping, blocknr + i, NULL);
185 (filler_t *)mapping->a_ops->readpage,
186 NULL);
187 /* synchronous error? */ 185 /* synchronous error? */
188 if (IS_ERR(page)) 186 if (IS_ERR(page))
189 page = NULL; 187 page = NULL;
@@ -322,8 +320,10 @@ out:
322 return -EINVAL; 320 return -EINVAL;
323} 321}
324 322
325static int cramfs_statfs(struct super_block *sb, struct kstatfs *buf) 323static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf)
326{ 324{
325 struct super_block *sb = dentry->d_sb;
326
327 buf->f_type = CRAMFS_MAGIC; 327 buf->f_type = CRAMFS_MAGIC;
328 buf->f_bsize = PAGE_CACHE_SIZE; 328 buf->f_bsize = PAGE_CACHE_SIZE;
329 buf->f_blocks = CRAMFS_SB(sb)->blocks; 329 buf->f_blocks = CRAMFS_SB(sb)->blocks;
@@ -528,10 +528,11 @@ static struct super_operations cramfs_ops = {
528 .statfs = cramfs_statfs, 528 .statfs = cramfs_statfs,
529}; 529};
530 530
531static struct super_block *cramfs_get_sb(struct file_system_type *fs_type, 531static int cramfs_get_sb(struct file_system_type *fs_type,
532 int flags, const char *dev_name, void *data) 532 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
533{ 533{
534 return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super); 534 return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super,
535 mnt);
535} 536}
536 537
537static struct file_system_type cramfs_fs_type = { 538static struct file_system_type cramfs_fs_type = {
diff --git a/fs/dcache.c b/fs/dcache.c
index 940d188e5d14..313b54b2b8f2 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -359,12 +359,13 @@ restart:
359} 359}
360 360
361/* 361/*
362 * Throw away a dentry - free the inode, dput the parent. 362 * Throw away a dentry - free the inode, dput the parent. This requires that
363 * This requires that the LRU list has already been 363 * the LRU list has already been removed.
364 * removed. 364 *
365 * Called with dcache_lock, drops it and then regains. 365 * Called with dcache_lock, drops it and then regains.
366 * Called with dentry->d_lock held, drops it.
366 */ 367 */
367static inline void prune_one_dentry(struct dentry * dentry) 368static void prune_one_dentry(struct dentry * dentry)
368{ 369{
369 struct dentry * parent; 370 struct dentry * parent;
370 371
@@ -382,6 +383,8 @@ static inline void prune_one_dentry(struct dentry * dentry)
382/** 383/**
383 * prune_dcache - shrink the dcache 384 * prune_dcache - shrink the dcache
384 * @count: number of entries to try and free 385 * @count: number of entries to try and free
386 * @sb: if given, ignore dentries for other superblocks
387 * which are being unmounted.
385 * 388 *
386 * Shrink the dcache. This is done when we need 389 * Shrink the dcache. This is done when we need
387 * more memory, or simply when we need to unmount 390 * more memory, or simply when we need to unmount
@@ -392,16 +395,29 @@ static inline void prune_one_dentry(struct dentry * dentry)
392 * all the dentries are in use. 395 * all the dentries are in use.
393 */ 396 */
394 397
395static void prune_dcache(int count) 398static void prune_dcache(int count, struct super_block *sb)
396{ 399{
397 spin_lock(&dcache_lock); 400 spin_lock(&dcache_lock);
398 for (; count ; count--) { 401 for (; count ; count--) {
399 struct dentry *dentry; 402 struct dentry *dentry;
400 struct list_head *tmp; 403 struct list_head *tmp;
404 struct rw_semaphore *s_umount;
401 405
402 cond_resched_lock(&dcache_lock); 406 cond_resched_lock(&dcache_lock);
403 407
404 tmp = dentry_unused.prev; 408 tmp = dentry_unused.prev;
409 if (unlikely(sb)) {
410 /* Try to find a dentry for this sb, but don't try
411 * too hard, if they aren't near the tail they will
412 * be moved down again soon
413 */
414 int skip = count;
415 while (skip && tmp != &dentry_unused &&
416 list_entry(tmp, struct dentry, d_lru)->d_sb != sb) {
417 skip--;
418 tmp = tmp->prev;
419 }
420 }
405 if (tmp == &dentry_unused) 421 if (tmp == &dentry_unused)
406 break; 422 break;
407 list_del_init(tmp); 423 list_del_init(tmp);
@@ -427,7 +443,45 @@ static void prune_dcache(int count)
427 spin_unlock(&dentry->d_lock); 443 spin_unlock(&dentry->d_lock);
428 continue; 444 continue;
429 } 445 }
430 prune_one_dentry(dentry); 446 /*
447 * If the dentry is not DCACHED_REFERENCED, it is time
448 * to remove it from the dcache, provided the super block is
449 * NULL (which means we are trying to reclaim memory)
450 * or this dentry belongs to the same super block that
451 * we want to shrink.
452 */
453 /*
454 * If this dentry is for "my" filesystem, then I can prune it
455 * without taking the s_umount lock (I already hold it).
456 */
457 if (sb && dentry->d_sb == sb) {
458 prune_one_dentry(dentry);
459 continue;
460 }
461 /*
462 * ...otherwise we need to be sure this filesystem isn't being
463 * unmounted, otherwise we could race with
464 * generic_shutdown_super(), and end up holding a reference to
465 * an inode while the filesystem is unmounted.
466 * So we try to get s_umount, and make sure s_root isn't NULL.
467 * (Take a local copy of s_umount to avoid a use-after-free of
468 * `dentry').
469 */
470 s_umount = &dentry->d_sb->s_umount;
471 if (down_read_trylock(s_umount)) {
472 if (dentry->d_sb->s_root != NULL) {
473 prune_one_dentry(dentry);
474 up_read(s_umount);
475 continue;
476 }
477 up_read(s_umount);
478 }
479 spin_unlock(&dentry->d_lock);
480 /* Cannot remove the first dentry, and it isn't appropriate
481 * to move it to the head of the list, so give up, and try
482 * later
483 */
484 break;
431 } 485 }
432 spin_unlock(&dcache_lock); 486 spin_unlock(&dcache_lock);
433} 487}
@@ -630,46 +684,7 @@ void shrink_dcache_parent(struct dentry * parent)
630 int found; 684 int found;
631 685
632 while ((found = select_parent(parent)) != 0) 686 while ((found = select_parent(parent)) != 0)
633 prune_dcache(found); 687 prune_dcache(found, parent->d_sb);
634}
635
636/**
637 * shrink_dcache_anon - further prune the cache
638 * @head: head of d_hash list of dentries to prune
639 *
640 * Prune the dentries that are anonymous
641 *
642 * parsing d_hash list does not hlist_for_each_entry_rcu() as it
643 * done under dcache_lock.
644 *
645 */
646void shrink_dcache_anon(struct hlist_head *head)
647{
648 struct hlist_node *lp;
649 int found;
650 do {
651 found = 0;
652 spin_lock(&dcache_lock);
653 hlist_for_each(lp, head) {
654 struct dentry *this = hlist_entry(lp, struct dentry, d_hash);
655 if (!list_empty(&this->d_lru)) {
656 dentry_stat.nr_unused--;
657 list_del_init(&this->d_lru);
658 }
659
660 /*
661 * move only zero ref count dentries to the end
662 * of the unused list for prune_dcache
663 */
664 if (!atomic_read(&this->d_count)) {
665 list_add_tail(&this->d_lru, &dentry_unused);
666 dentry_stat.nr_unused++;
667 found++;
668 }
669 }
670 spin_unlock(&dcache_lock);
671 prune_dcache(found);
672 } while(found);
673} 688}
674 689
675/* 690/*
@@ -689,7 +704,7 @@ static int shrink_dcache_memory(int nr, gfp_t gfp_mask)
689 if (nr) { 704 if (nr) {
690 if (!(gfp_mask & __GFP_FS)) 705 if (!(gfp_mask & __GFP_FS))
691 return -1; 706 return -1;
692 prune_dcache(nr); 707 prune_dcache(nr, NULL);
693 } 708 }
694 return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure; 709 return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
695} 710}
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index b55b4ea9a676..440128ebef3b 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -111,11 +111,11 @@ static int debug_fill_super(struct super_block *sb, void *data, int silent)
111 return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files); 111 return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
112} 112}
113 113
114static struct super_block *debug_get_sb(struct file_system_type *fs_type, 114static int debug_get_sb(struct file_system_type *fs_type,
115 int flags, const char *dev_name, 115 int flags, const char *dev_name,
116 void *data) 116 void *data, struct vfsmount *mnt)
117{ 117{
118 return get_sb_single(fs_type, flags, data, debug_fill_super); 118 return get_sb_single(fs_type, flags, data, debug_fill_super, mnt);
119} 119}
120 120
121static struct file_system_type debug_fs_type = { 121static struct file_system_type debug_fs_type = {
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index 52f5059c4f31..51a97f132745 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -2549,11 +2549,11 @@ static int devfs_fill_super(struct super_block *sb, void *data, int silent)
2549 return -EINVAL; 2549 return -EINVAL;
2550} /* End Function devfs_fill_super */ 2550} /* End Function devfs_fill_super */
2551 2551
2552static struct super_block *devfs_get_sb(struct file_system_type *fs_type, 2552static int devfs_get_sb(struct file_system_type *fs_type,
2553 int flags, const char *dev_name, 2553 int flags, const char *dev_name,
2554 void *data) 2554 void *data, struct vfsmount *mnt)
2555{ 2555{
2556 return get_sb_single(fs_type, flags, data, devfs_fill_super); 2556 return get_sb_single(fs_type, flags, data, devfs_fill_super, mnt);
2557} 2557}
2558 2558
2559static struct file_system_type devfs_fs_type = { 2559static struct file_system_type devfs_fs_type = {
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 14c5620b5cab..f7aef5bb584a 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -130,10 +130,10 @@ fail:
130 return -ENOMEM; 130 return -ENOMEM;
131} 131}
132 132
133static struct super_block *devpts_get_sb(struct file_system_type *fs_type, 133static int devpts_get_sb(struct file_system_type *fs_type,
134 int flags, const char *dev_name, void *data) 134 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
135{ 135{
136 return get_sb_single(fs_type, flags, data, devpts_fill_super); 136 return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt);
137} 137}
138 138
139static struct file_system_type devpts_fs_type = { 139static struct file_system_type devpts_fs_type = {
diff --git a/fs/direct-io.c b/fs/direct-io.c
index b05d1b218776..538fb0418fba 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -162,7 +162,7 @@ static int dio_refill_pages(struct dio *dio)
162 NULL); /* vmas */ 162 NULL); /* vmas */
163 up_read(&current->mm->mmap_sem); 163 up_read(&current->mm->mmap_sem);
164 164
165 if (ret < 0 && dio->blocks_available && (dio->rw == WRITE)) { 165 if (ret < 0 && dio->blocks_available && (dio->rw & WRITE)) {
166 struct page *page = ZERO_PAGE(dio->curr_user_address); 166 struct page *page = ZERO_PAGE(dio->curr_user_address);
167 /* 167 /*
168 * A memory fault, but the filesystem has some outstanding 168 * A memory fault, but the filesystem has some outstanding
@@ -535,7 +535,7 @@ static int get_more_blocks(struct dio *dio)
535 map_bh->b_state = 0; 535 map_bh->b_state = 0;
536 map_bh->b_size = fs_count << dio->inode->i_blkbits; 536 map_bh->b_size = fs_count << dio->inode->i_blkbits;
537 537
538 create = dio->rw == WRITE; 538 create = dio->rw & WRITE;
539 if (dio->lock_type == DIO_LOCKING) { 539 if (dio->lock_type == DIO_LOCKING) {
540 if (dio->block_in_file < (i_size_read(dio->inode) >> 540 if (dio->block_in_file < (i_size_read(dio->inode) >>
541 dio->blkbits)) 541 dio->blkbits))
@@ -867,7 +867,7 @@ do_holes:
867 loff_t i_size_aligned; 867 loff_t i_size_aligned;
868 868
869 /* AKPM: eargh, -ENOTBLK is a hack */ 869 /* AKPM: eargh, -ENOTBLK is a hack */
870 if (dio->rw == WRITE) { 870 if (dio->rw & WRITE) {
871 page_cache_release(page); 871 page_cache_release(page);
872 return -ENOTBLK; 872 return -ENOTBLK;
873 } 873 }
@@ -1045,7 +1045,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
1045 } 1045 }
1046 } /* end iovec loop */ 1046 } /* end iovec loop */
1047 1047
1048 if (ret == -ENOTBLK && rw == WRITE) { 1048 if (ret == -ENOTBLK && (rw & WRITE)) {
1049 /* 1049 /*
1050 * The remaining part of the request will be 1050 * The remaining part of the request will be
1051 * be handled by buffered I/O when we return 1051 * be handled by buffered I/O when we return
@@ -1089,7 +1089,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
1089 if (dio->is_async) { 1089 if (dio->is_async) {
1090 int should_wait = 0; 1090 int should_wait = 0;
1091 1091
1092 if (dio->result < dio->size && rw == WRITE) { 1092 if (dio->result < dio->size && (rw & WRITE)) {
1093 dio->waiter = current; 1093 dio->waiter = current;
1094 should_wait = 1; 1094 should_wait = 1;
1095 } 1095 }
@@ -1142,7 +1142,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
1142 ret = transferred; 1142 ret = transferred;
1143 1143
1144 /* We could have also come here on an AIO file extend */ 1144 /* We could have also come here on an AIO file extend */
1145 if (!is_sync_kiocb(iocb) && rw == WRITE && 1145 if (!is_sync_kiocb(iocb) && (rw & WRITE) &&
1146 ret >= 0 && dio->result == dio->size) 1146 ret >= 0 && dio->result == dio->size)
1147 /* 1147 /*
1148 * For AIO writes where we have completed the 1148 * For AIO writes where we have completed the
@@ -1194,7 +1194,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
1194 int acquire_i_mutex = 0; 1194 int acquire_i_mutex = 0;
1195 1195
1196 if (rw & WRITE) 1196 if (rw & WRITE)
1197 current->flags |= PF_SYNCWRITE; 1197 rw = WRITE_SYNC;
1198 1198
1199 if (bdev) 1199 if (bdev)
1200 bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev)); 1200 bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev));
@@ -1270,7 +1270,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
1270 * even for AIO, we need to wait for i/o to complete before 1270 * even for AIO, we need to wait for i/o to complete before
1271 * returning in this case. 1271 * returning in this case.
1272 */ 1272 */
1273 dio->is_async = !is_sync_kiocb(iocb) && !((rw == WRITE) && 1273 dio->is_async = !is_sync_kiocb(iocb) && !((rw & WRITE) &&
1274 (end > i_size_read(inode))); 1274 (end > i_size_read(inode)));
1275 1275
1276 retval = direct_io_worker(rw, iocb, inode, iov, offset, 1276 retval = direct_io_worker(rw, iocb, inode, iov, offset,
@@ -1284,8 +1284,6 @@ out:
1284 mutex_unlock(&inode->i_mutex); 1284 mutex_unlock(&inode->i_mutex);
1285 else if (acquire_i_mutex) 1285 else if (acquire_i_mutex)
1286 mutex_lock(&inode->i_mutex); 1286 mutex_lock(&inode->i_mutex);
1287 if (rw & WRITE)
1288 current->flags &= ~PF_SYNCWRITE;
1289 return retval; 1287 return retval;
1290} 1288}
1291EXPORT_SYMBOL(__blockdev_direct_IO); 1289EXPORT_SYMBOL(__blockdev_direct_IO);
diff --git a/fs/efs/super.c b/fs/efs/super.c
index dff623e3ddbf..8ac2462ae5dd 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -15,13 +15,13 @@
15#include <linux/buffer_head.h> 15#include <linux/buffer_head.h>
16#include <linux/vfs.h> 16#include <linux/vfs.h>
17 17
18static int efs_statfs(struct super_block *s, struct kstatfs *buf); 18static int efs_statfs(struct dentry *dentry, struct kstatfs *buf);
19static int efs_fill_super(struct super_block *s, void *d, int silent); 19static int efs_fill_super(struct super_block *s, void *d, int silent);
20 20
21static struct super_block *efs_get_sb(struct file_system_type *fs_type, 21static int efs_get_sb(struct file_system_type *fs_type,
22 int flags, const char *dev_name, void *data) 22 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
23{ 23{
24 return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super); 24 return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super, mnt);
25} 25}
26 26
27static struct file_system_type efs_fs_type = { 27static struct file_system_type efs_fs_type = {
@@ -322,8 +322,8 @@ out_no_fs:
322 return -EINVAL; 322 return -EINVAL;
323} 323}
324 324
325static int efs_statfs(struct super_block *s, struct kstatfs *buf) { 325static int efs_statfs(struct dentry *dentry, struct kstatfs *buf) {
326 struct efs_sb_info *sb = SUPER_INFO(s); 326 struct efs_sb_info *sb = SUPER_INFO(dentry->d_sb);
327 327
328 buf->f_type = EFS_SUPER_MAGIC; /* efs magic number */ 328 buf->f_type = EFS_SUPER_MAGIC; /* efs magic number */
329 buf->f_bsize = EFS_BLOCKSIZE; /* blocksize */ 329 buf->f_bsize = EFS_BLOCKSIZE; /* blocksize */
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 1b4491cdd115..08e7e6a555ca 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -268,9 +268,9 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
268 int maxevents, long timeout); 268 int maxevents, long timeout);
269static int eventpollfs_delete_dentry(struct dentry *dentry); 269static int eventpollfs_delete_dentry(struct dentry *dentry);
270static struct inode *ep_eventpoll_inode(void); 270static struct inode *ep_eventpoll_inode(void);
271static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type, 271static int eventpollfs_get_sb(struct file_system_type *fs_type,
272 int flags, const char *dev_name, 272 int flags, const char *dev_name,
273 void *data); 273 void *data, struct vfsmount *mnt);
274 274
275/* 275/*
276 * This semaphore is used to serialize ep_free() and eventpoll_release_file(). 276 * This semaphore is used to serialize ep_free() and eventpoll_release_file().
@@ -337,20 +337,20 @@ static inline int ep_cmp_ffd(struct epoll_filefd *p1,
337/* Special initialization for the rb-tree node to detect linkage */ 337/* Special initialization for the rb-tree node to detect linkage */
338static inline void ep_rb_initnode(struct rb_node *n) 338static inline void ep_rb_initnode(struct rb_node *n)
339{ 339{
340 n->rb_parent = n; 340 rb_set_parent(n, n);
341} 341}
342 342
343/* Removes a node from the rb-tree and marks it for a fast is-linked check */ 343/* Removes a node from the rb-tree and marks it for a fast is-linked check */
344static inline void ep_rb_erase(struct rb_node *n, struct rb_root *r) 344static inline void ep_rb_erase(struct rb_node *n, struct rb_root *r)
345{ 345{
346 rb_erase(n, r); 346 rb_erase(n, r);
347 n->rb_parent = n; 347 rb_set_parent(n, n);
348} 348}
349 349
350/* Fast check to verify that the item is linked to the main rb-tree */ 350/* Fast check to verify that the item is linked to the main rb-tree */
351static inline int ep_rb_linked(struct rb_node *n) 351static inline int ep_rb_linked(struct rb_node *n)
352{ 352{
353 return n->rb_parent != n; 353 return rb_parent(n) != n;
354} 354}
355 355
356/* 356/*
@@ -1595,11 +1595,12 @@ eexit_1:
1595} 1595}
1596 1596
1597 1597
1598static struct super_block * 1598static int
1599eventpollfs_get_sb(struct file_system_type *fs_type, int flags, 1599eventpollfs_get_sb(struct file_system_type *fs_type, int flags,
1600 const char *dev_name, void *data) 1600 const char *dev_name, void *data, struct vfsmount *mnt)
1601{ 1601{
1602 return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC); 1602 return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC,
1603 mnt);
1603} 1604}
1604 1605
1605 1606
diff --git a/fs/exec.c b/fs/exec.c
index 3a79d97ac234..0b88bf646143 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -49,6 +49,7 @@
49#include <linux/rmap.h> 49#include <linux/rmap.h>
50#include <linux/acct.h> 50#include <linux/acct.h>
51#include <linux/cn_proc.h> 51#include <linux/cn_proc.h>
52#include <linux/audit.h>
52 53
53#include <asm/uaccess.h> 54#include <asm/uaccess.h>
54#include <asm/mmu_context.h> 55#include <asm/mmu_context.h>
@@ -865,7 +866,6 @@ int flush_old_exec(struct linux_binprm * bprm)
865 bprm->mm = NULL; /* We're using it now */ 866 bprm->mm = NULL; /* We're using it now */
866 867
867 /* This is the point of no return */ 868 /* This is the point of no return */
868 steal_locks(files);
869 put_files_struct(files); 869 put_files_struct(files);
870 870
871 current->sas_ss_sp = current->sas_ss_size = 0; 871 current->sas_ss_sp = current->sas_ss_size = 0;
@@ -1085,6 +1085,11 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
1085 /* kernel module loader fixup */ 1085 /* kernel module loader fixup */
1086 /* so we don't try to load run modprobe in kernel space. */ 1086 /* so we don't try to load run modprobe in kernel space. */
1087 set_fs(USER_DS); 1087 set_fs(USER_DS);
1088
1089 retval = audit_bprm(bprm);
1090 if (retval)
1091 return retval;
1092
1088 retval = -ENOENT; 1093 retval = -ENOENT;
1089 for (try=0; try<2; try++) { 1094 for (try=0; try<2; try++) {
1090 read_lock(&binfmt_lock); 1095 read_lock(&binfmt_lock);
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index d672aa9f4061..3c1c9aaaca6b 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -159,8 +159,7 @@ fail:
159static struct page * ext2_get_page(struct inode *dir, unsigned long n) 159static struct page * ext2_get_page(struct inode *dir, unsigned long n)
160{ 160{
161 struct address_space *mapping = dir->i_mapping; 161 struct address_space *mapping = dir->i_mapping;
162 struct page *page = read_cache_page(mapping, n, 162 struct page *page = read_mapping_page(mapping, n, NULL);
163 (filler_t*)mapping->a_ops->readpage, NULL);
164 if (!IS_ERR(page)) { 163 if (!IS_ERR(page)) {
165 wait_on_page_locked(page); 164 wait_on_page_locked(page);
166 kmap(page); 165 kmap(page);
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 7e30bae174ed..ee4ba759581e 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -39,7 +39,7 @@
39static void ext2_sync_super(struct super_block *sb, 39static void ext2_sync_super(struct super_block *sb,
40 struct ext2_super_block *es); 40 struct ext2_super_block *es);
41static int ext2_remount (struct super_block * sb, int * flags, char * data); 41static int ext2_remount (struct super_block * sb, int * flags, char * data);
42static int ext2_statfs (struct super_block * sb, struct kstatfs * buf); 42static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf);
43 43
44void ext2_error (struct super_block * sb, const char * function, 44void ext2_error (struct super_block * sb, const char * function,
45 const char * fmt, ...) 45 const char * fmt, ...)
@@ -834,9 +834,6 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
834 printk ("EXT2-fs: not enough memory\n"); 834 printk ("EXT2-fs: not enough memory\n");
835 goto failed_mount; 835 goto failed_mount;
836 } 836 }
837 percpu_counter_init(&sbi->s_freeblocks_counter);
838 percpu_counter_init(&sbi->s_freeinodes_counter);
839 percpu_counter_init(&sbi->s_dirs_counter);
840 bgl_lock_init(&sbi->s_blockgroup_lock); 837 bgl_lock_init(&sbi->s_blockgroup_lock);
841 sbi->s_debts = kmalloc(sbi->s_groups_count * sizeof(*sbi->s_debts), 838 sbi->s_debts = kmalloc(sbi->s_groups_count * sizeof(*sbi->s_debts),
842 GFP_KERNEL); 839 GFP_KERNEL);
@@ -863,6 +860,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
863 sbi->s_gdb_count = db_count; 860 sbi->s_gdb_count = db_count;
864 get_random_bytes(&sbi->s_next_generation, sizeof(u32)); 861 get_random_bytes(&sbi->s_next_generation, sizeof(u32));
865 spin_lock_init(&sbi->s_next_gen_lock); 862 spin_lock_init(&sbi->s_next_gen_lock);
863
864 percpu_counter_init(&sbi->s_freeblocks_counter,
865 ext2_count_free_blocks(sb));
866 percpu_counter_init(&sbi->s_freeinodes_counter,
867 ext2_count_free_inodes(sb));
868 percpu_counter_init(&sbi->s_dirs_counter,
869 ext2_count_dirs(sb));
866 /* 870 /*
867 * set up enough so that it can read an inode 871 * set up enough so that it can read an inode
868 */ 872 */
@@ -874,24 +878,18 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
874 if (!sb->s_root) { 878 if (!sb->s_root) {
875 iput(root); 879 iput(root);
876 printk(KERN_ERR "EXT2-fs: get root inode failed\n"); 880 printk(KERN_ERR "EXT2-fs: get root inode failed\n");
877 goto failed_mount2; 881 goto failed_mount3;
878 } 882 }
879 if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { 883 if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
880 dput(sb->s_root); 884 dput(sb->s_root);
881 sb->s_root = NULL; 885 sb->s_root = NULL;
882 printk(KERN_ERR "EXT2-fs: corrupt root inode, run e2fsck\n"); 886 printk(KERN_ERR "EXT2-fs: corrupt root inode, run e2fsck\n");
883 goto failed_mount2; 887 goto failed_mount3;
884 } 888 }
885 if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) 889 if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL))
886 ext2_warning(sb, __FUNCTION__, 890 ext2_warning(sb, __FUNCTION__,
887 "mounting ext3 filesystem as ext2"); 891 "mounting ext3 filesystem as ext2");
888 ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); 892 ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
889 percpu_counter_mod(&sbi->s_freeblocks_counter,
890 ext2_count_free_blocks(sb));
891 percpu_counter_mod(&sbi->s_freeinodes_counter,
892 ext2_count_free_inodes(sb));
893 percpu_counter_mod(&sbi->s_dirs_counter,
894 ext2_count_dirs(sb));
895 return 0; 893 return 0;
896 894
897cantfind_ext2: 895cantfind_ext2:
@@ -899,7 +897,10 @@ cantfind_ext2:
899 printk("VFS: Can't find an ext2 filesystem on dev %s.\n", 897 printk("VFS: Can't find an ext2 filesystem on dev %s.\n",
900 sb->s_id); 898 sb->s_id);
901 goto failed_mount; 899 goto failed_mount;
902 900failed_mount3:
901 percpu_counter_destroy(&sbi->s_freeblocks_counter);
902 percpu_counter_destroy(&sbi->s_freeinodes_counter);
903 percpu_counter_destroy(&sbi->s_dirs_counter);
903failed_mount2: 904failed_mount2:
904 for (i = 0; i < db_count; i++) 905 for (i = 0; i < db_count; i++)
905 brelse(sbi->s_group_desc[i]); 906 brelse(sbi->s_group_desc[i]);
@@ -1038,8 +1039,9 @@ restore_opts:
1038 return err; 1039 return err;
1039} 1040}
1040 1041
1041static int ext2_statfs (struct super_block * sb, struct kstatfs * buf) 1042static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)
1042{ 1043{
1044 struct super_block *sb = dentry->d_sb;
1043 struct ext2_sb_info *sbi = EXT2_SB(sb); 1045 struct ext2_sb_info *sbi = EXT2_SB(sb);
1044 unsigned long overhead; 1046 unsigned long overhead;
1045 int i; 1047 int i;
@@ -1087,10 +1089,10 @@ static int ext2_statfs (struct super_block * sb, struct kstatfs * buf)
1087 return 0; 1089 return 0;
1088} 1090}
1089 1091
1090static struct super_block *ext2_get_sb(struct file_system_type *fs_type, 1092static int ext2_get_sb(struct file_system_type *fs_type,
1091 int flags, const char *dev_name, void *data) 1093 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
1092{ 1094{
1093 return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super); 1095 return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super, mnt);
1094} 1096}
1095 1097
1096#ifdef CONFIG_QUOTA 1098#ifdef CONFIG_QUOTA
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index f37528ed222e..fbb0d4ed07d4 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -284,7 +284,7 @@ static void free_rb_tree_fname(struct rb_root *root)
284 * beginning of the loop and try to free the parent 284 * beginning of the loop and try to free the parent
285 * node. 285 * node.
286 */ 286 */
287 parent = n->rb_parent; 287 parent = rb_parent(n);
288 fname = rb_entry(n, struct fname, rb_hash); 288 fname = rb_entry(n, struct fname, rb_hash);
289 while (fname) { 289 while (fname) {
290 struct fname * old = fname; 290 struct fname * old = fname;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index f8a5266ea1ff..a60cc6ec130f 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -58,7 +58,7 @@ static int ext3_sync_fs(struct super_block *sb, int wait);
58static const char *ext3_decode_error(struct super_block * sb, int errno, 58static const char *ext3_decode_error(struct super_block * sb, int errno,
59 char nbuf[16]); 59 char nbuf[16]);
60static int ext3_remount (struct super_block * sb, int * flags, char * data); 60static int ext3_remount (struct super_block * sb, int * flags, char * data);
61static int ext3_statfs (struct super_block * sb, struct kstatfs * buf); 61static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf);
62static void ext3_unlockfs(struct super_block *sb); 62static void ext3_unlockfs(struct super_block *sb);
63static void ext3_write_super (struct super_block * sb); 63static void ext3_write_super (struct super_block * sb);
64static void ext3_write_super_lockfs(struct super_block *sb); 64static void ext3_write_super_lockfs(struct super_block *sb);
@@ -499,20 +499,21 @@ static void ext3_clear_inode(struct inode *inode)
499{ 499{
500 struct ext3_block_alloc_info *rsv = EXT3_I(inode)->i_block_alloc_info; 500 struct ext3_block_alloc_info *rsv = EXT3_I(inode)->i_block_alloc_info;
501#ifdef CONFIG_EXT3_FS_POSIX_ACL 501#ifdef CONFIG_EXT3_FS_POSIX_ACL
502 if (EXT3_I(inode)->i_acl && 502 if (EXT3_I(inode)->i_acl &&
503 EXT3_I(inode)->i_acl != EXT3_ACL_NOT_CACHED) { 503 EXT3_I(inode)->i_acl != EXT3_ACL_NOT_CACHED) {
504 posix_acl_release(EXT3_I(inode)->i_acl); 504 posix_acl_release(EXT3_I(inode)->i_acl);
505 EXT3_I(inode)->i_acl = EXT3_ACL_NOT_CACHED; 505 EXT3_I(inode)->i_acl = EXT3_ACL_NOT_CACHED;
506 } 506 }
507 if (EXT3_I(inode)->i_default_acl && 507 if (EXT3_I(inode)->i_default_acl &&
508 EXT3_I(inode)->i_default_acl != EXT3_ACL_NOT_CACHED) { 508 EXT3_I(inode)->i_default_acl != EXT3_ACL_NOT_CACHED) {
509 posix_acl_release(EXT3_I(inode)->i_default_acl); 509 posix_acl_release(EXT3_I(inode)->i_default_acl);
510 EXT3_I(inode)->i_default_acl = EXT3_ACL_NOT_CACHED; 510 EXT3_I(inode)->i_default_acl = EXT3_ACL_NOT_CACHED;
511 } 511 }
512#endif 512#endif
513 ext3_discard_reservation(inode); 513 ext3_discard_reservation(inode);
514 EXT3_I(inode)->i_block_alloc_info = NULL; 514 EXT3_I(inode)->i_block_alloc_info = NULL;
515 kfree(rsv); 515 if (unlikely(rsv))
516 kfree(rsv);
516} 517}
517 518
518static inline void ext3_show_quota_options(struct seq_file *seq, struct super_block *sb) 519static inline void ext3_show_quota_options(struct seq_file *seq, struct super_block *sb)
@@ -1579,9 +1580,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
1579 goto failed_mount; 1580 goto failed_mount;
1580 } 1581 }
1581 1582
1582 percpu_counter_init(&sbi->s_freeblocks_counter);
1583 percpu_counter_init(&sbi->s_freeinodes_counter);
1584 percpu_counter_init(&sbi->s_dirs_counter);
1585 bgl_lock_init(&sbi->s_blockgroup_lock); 1583 bgl_lock_init(&sbi->s_blockgroup_lock);
1586 1584
1587 for (i = 0; i < db_count; i++) { 1585 for (i = 0; i < db_count; i++) {
@@ -1601,6 +1599,14 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
1601 sbi->s_gdb_count = db_count; 1599 sbi->s_gdb_count = db_count;
1602 get_random_bytes(&sbi->s_next_generation, sizeof(u32)); 1600 get_random_bytes(&sbi->s_next_generation, sizeof(u32));
1603 spin_lock_init(&sbi->s_next_gen_lock); 1601 spin_lock_init(&sbi->s_next_gen_lock);
1602
1603 percpu_counter_init(&sbi->s_freeblocks_counter,
1604 ext3_count_free_blocks(sb));
1605 percpu_counter_init(&sbi->s_freeinodes_counter,
1606 ext3_count_free_inodes(sb));
1607 percpu_counter_init(&sbi->s_dirs_counter,
1608 ext3_count_dirs(sb));
1609
1604 /* per fileystem reservation list head & lock */ 1610 /* per fileystem reservation list head & lock */
1605 spin_lock_init(&sbi->s_rsv_window_lock); 1611 spin_lock_init(&sbi->s_rsv_window_lock);
1606 sbi->s_rsv_window_root = RB_ROOT; 1612 sbi->s_rsv_window_root = RB_ROOT;
@@ -1639,16 +1645,16 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
1639 if (!test_opt(sb, NOLOAD) && 1645 if (!test_opt(sb, NOLOAD) &&
1640 EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { 1646 EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
1641 if (ext3_load_journal(sb, es, journal_devnum)) 1647 if (ext3_load_journal(sb, es, journal_devnum))
1642 goto failed_mount2; 1648 goto failed_mount3;
1643 } else if (journal_inum) { 1649 } else if (journal_inum) {
1644 if (ext3_create_journal(sb, es, journal_inum)) 1650 if (ext3_create_journal(sb, es, journal_inum))
1645 goto failed_mount2; 1651 goto failed_mount3;
1646 } else { 1652 } else {
1647 if (!silent) 1653 if (!silent)
1648 printk (KERN_ERR 1654 printk (KERN_ERR
1649 "ext3: No journal on filesystem on %s\n", 1655 "ext3: No journal on filesystem on %s\n",
1650 sb->s_id); 1656 sb->s_id);
1651 goto failed_mount2; 1657 goto failed_mount3;
1652 } 1658 }
1653 1659
1654 /* We have now updated the journal if required, so we can 1660 /* We have now updated the journal if required, so we can
@@ -1671,7 +1677,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
1671 (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) { 1677 (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) {
1672 printk(KERN_ERR "EXT3-fs: Journal does not support " 1678 printk(KERN_ERR "EXT3-fs: Journal does not support "
1673 "requested data journaling mode\n"); 1679 "requested data journaling mode\n");
1674 goto failed_mount3; 1680 goto failed_mount4;
1675 } 1681 }
1676 default: 1682 default:
1677 break; 1683 break;
@@ -1694,13 +1700,13 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
1694 if (!sb->s_root) { 1700 if (!sb->s_root) {
1695 printk(KERN_ERR "EXT3-fs: get root inode failed\n"); 1701 printk(KERN_ERR "EXT3-fs: get root inode failed\n");
1696 iput(root); 1702 iput(root);
1697 goto failed_mount3; 1703 goto failed_mount4;
1698 } 1704 }
1699 if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { 1705 if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
1700 dput(sb->s_root); 1706 dput(sb->s_root);
1701 sb->s_root = NULL; 1707 sb->s_root = NULL;
1702 printk(KERN_ERR "EXT3-fs: corrupt root inode, run e2fsck\n"); 1708 printk(KERN_ERR "EXT3-fs: corrupt root inode, run e2fsck\n");
1703 goto failed_mount3; 1709 goto failed_mount4;
1704 } 1710 }
1705 1711
1706 ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY); 1712 ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
@@ -1723,13 +1729,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
1723 test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered": 1729 test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
1724 "writeback"); 1730 "writeback");
1725 1731
1726 percpu_counter_mod(&sbi->s_freeblocks_counter,
1727 ext3_count_free_blocks(sb));
1728 percpu_counter_mod(&sbi->s_freeinodes_counter,
1729 ext3_count_free_inodes(sb));
1730 percpu_counter_mod(&sbi->s_dirs_counter,
1731 ext3_count_dirs(sb));
1732
1733 lock_kernel(); 1732 lock_kernel();
1734 return 0; 1733 return 0;
1735 1734
@@ -1739,8 +1738,12 @@ cantfind_ext3:
1739 sb->s_id); 1738 sb->s_id);
1740 goto failed_mount; 1739 goto failed_mount;
1741 1740
1742failed_mount3: 1741failed_mount4:
1743 journal_destroy(sbi->s_journal); 1742 journal_destroy(sbi->s_journal);
1743failed_mount3:
1744 percpu_counter_destroy(&sbi->s_freeblocks_counter);
1745 percpu_counter_destroy(&sbi->s_freeinodes_counter);
1746 percpu_counter_destroy(&sbi->s_dirs_counter);
1744failed_mount2: 1747failed_mount2:
1745 for (i = 0; i < db_count; i++) 1748 for (i = 0; i < db_count; i++)
1746 brelse(sbi->s_group_desc[i]); 1749 brelse(sbi->s_group_desc[i]);
@@ -2318,8 +2321,9 @@ restore_opts:
2318 return err; 2321 return err;
2319} 2322}
2320 2323
2321static int ext3_statfs (struct super_block * sb, struct kstatfs * buf) 2324static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
2322{ 2325{
2326 struct super_block *sb = dentry->d_sb;
2323 struct ext3_sb_info *sbi = EXT3_SB(sb); 2327 struct ext3_sb_info *sbi = EXT3_SB(sb);
2324 struct ext3_super_block *es = sbi->s_es; 2328 struct ext3_super_block *es = sbi->s_es;
2325 unsigned long overhead; 2329 unsigned long overhead;
@@ -2646,10 +2650,10 @@ out:
2646 2650
2647#endif 2651#endif
2648 2652
2649static struct super_block *ext3_get_sb(struct file_system_type *fs_type, 2653static int ext3_get_sb(struct file_system_type *fs_type,
2650 int flags, const char *dev_name, void *data) 2654 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
2651{ 2655{
2652 return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super); 2656 return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super, mnt);
2653} 2657}
2654 2658
2655static struct file_system_type ext3_fs_type = { 2659static struct file_system_type ext3_fs_type = {
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index c1ce284f8a94..7c35d582ec10 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -539,18 +539,18 @@ static int fat_remount(struct super_block *sb, int *flags, char *data)
539 return 0; 539 return 0;
540} 540}
541 541
542static int fat_statfs(struct super_block *sb, struct kstatfs *buf) 542static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
543{ 543{
544 struct msdos_sb_info *sbi = MSDOS_SB(sb); 544 struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
545 545
546 /* If the count of free cluster is still unknown, counts it here. */ 546 /* If the count of free cluster is still unknown, counts it here. */
547 if (sbi->free_clusters == -1) { 547 if (sbi->free_clusters == -1) {
548 int err = fat_count_free_clusters(sb); 548 int err = fat_count_free_clusters(dentry->d_sb);
549 if (err) 549 if (err)
550 return err; 550 return err;
551 } 551 }
552 552
553 buf->f_type = sb->s_magic; 553 buf->f_type = dentry->d_sb->s_magic;
554 buf->f_bsize = sbi->cluster_size; 554 buf->f_bsize = sbi->cluster_size;
555 buf->f_blocks = sbi->max_cluster - FAT_START_ENT; 555 buf->f_blocks = sbi->max_cluster - FAT_START_ENT;
556 buf->f_bfree = sbi->free_clusters; 556 buf->f_bfree = sbi->free_clusters;
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 944652e9dde1..308f2b6b5026 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -210,4 +210,3 @@ int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs)
210 return err; 210 return err;
211} 211}
212 212
213EXPORT_SYMBOL_GPL(fat_sync_bhs);
diff --git a/fs/file_table.c b/fs/file_table.c
index bcea1998b4de..506d5307108d 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -300,5 +300,5 @@ void __init files_init(unsigned long mempages)
300 if (files_stat.max_files < NR_FILE) 300 if (files_stat.max_files < NR_FILE)
301 files_stat.max_files = NR_FILE; 301 files_stat.max_files = NR_FILE;
302 files_defer_init(); 302 files_defer_init();
303 percpu_counter_init(&nr_files); 303 percpu_counter_init(&nr_files, 0);
304} 304}
diff --git a/fs/freevxfs/vxfs_subr.c b/fs/freevxfs/vxfs_subr.c
index 50aae77651b2..c1be118fc067 100644
--- a/fs/freevxfs/vxfs_subr.c
+++ b/fs/freevxfs/vxfs_subr.c
@@ -71,8 +71,7 @@ vxfs_get_page(struct address_space *mapping, u_long n)
71{ 71{
72 struct page * pp; 72 struct page * pp;
73 73
74 pp = read_cache_page(mapping, n, 74 pp = read_mapping_page(mapping, n, NULL);
75 (filler_t*)mapping->a_ops->readpage, NULL);
76 75
77 if (!IS_ERR(pp)) { 76 if (!IS_ERR(pp)) {
78 wait_on_page_locked(pp); 77 wait_on_page_locked(pp);
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index b44c916d24a1..b74b791fc23b 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -40,6 +40,7 @@
40#include <linux/slab.h> 40#include <linux/slab.h>
41#include <linux/stat.h> 41#include <linux/stat.h>
42#include <linux/vfs.h> 42#include <linux/vfs.h>
43#include <linux/mount.h>
43 44
44#include "vxfs.h" 45#include "vxfs.h"
45#include "vxfs_extern.h" 46#include "vxfs_extern.h"
@@ -55,7 +56,7 @@ MODULE_ALIAS("vxfs"); /* makes mount -t vxfs autoload the module */
55 56
56 57
57static void vxfs_put_super(struct super_block *); 58static void vxfs_put_super(struct super_block *);
58static int vxfs_statfs(struct super_block *, struct kstatfs *); 59static int vxfs_statfs(struct dentry *, struct kstatfs *);
59static int vxfs_remount(struct super_block *, int *, char *); 60static int vxfs_remount(struct super_block *, int *, char *);
60 61
61static struct super_operations vxfs_super_ops = { 62static struct super_operations vxfs_super_ops = {
@@ -90,12 +91,12 @@ vxfs_put_super(struct super_block *sbp)
90 91
91/** 92/**
92 * vxfs_statfs - get filesystem information 93 * vxfs_statfs - get filesystem information
93 * @sbp: VFS superblock 94 * @dentry: VFS dentry to locate superblock
94 * @bufp: output buffer 95 * @bufp: output buffer
95 * 96 *
96 * Description: 97 * Description:
97 * vxfs_statfs fills the statfs buffer @bufp with information 98 * vxfs_statfs fills the statfs buffer @bufp with information
98 * about the filesystem described by @sbp. 99 * about the filesystem described by @dentry.
99 * 100 *
100 * Returns: 101 * Returns:
101 * Zero. 102 * Zero.
@@ -107,12 +108,12 @@ vxfs_put_super(struct super_block *sbp)
107 * This is everything but complete... 108 * This is everything but complete...
108 */ 109 */
109static int 110static int
110vxfs_statfs(struct super_block *sbp, struct kstatfs *bufp) 111vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
111{ 112{
112 struct vxfs_sb_info *infp = VXFS_SBI(sbp); 113 struct vxfs_sb_info *infp = VXFS_SBI(dentry->d_sb);
113 114
114 bufp->f_type = VXFS_SUPER_MAGIC; 115 bufp->f_type = VXFS_SUPER_MAGIC;
115 bufp->f_bsize = sbp->s_blocksize; 116 bufp->f_bsize = dentry->d_sb->s_blocksize;
116 bufp->f_blocks = infp->vsi_raw->vs_dsize; 117 bufp->f_blocks = infp->vsi_raw->vs_dsize;
117 bufp->f_bfree = infp->vsi_raw->vs_free; 118 bufp->f_bfree = infp->vsi_raw->vs_free;
118 bufp->f_bavail = 0; 119 bufp->f_bavail = 0;
@@ -241,10 +242,11 @@ out:
241/* 242/*
242 * The usual module blurb. 243 * The usual module blurb.
243 */ 244 */
244static struct super_block *vxfs_get_sb(struct file_system_type *fs_type, 245static int vxfs_get_sb(struct file_system_type *fs_type,
245 int flags, const char *dev_name, void *data) 246 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
246{ 247{
247 return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super); 248 return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super,
249 mnt);
248} 250}
249 251
250static struct file_system_type vxfs_fs_type = { 252static struct file_system_type vxfs_fs_type = {
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index f3fbe2d030f4..031b27a4bc9a 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -461,6 +461,8 @@ void sync_inodes_sb(struct super_block *sb, int wait)
461{ 461{
462 struct writeback_control wbc = { 462 struct writeback_control wbc = {
463 .sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_HOLD, 463 .sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_HOLD,
464 .range_start = 0,
465 .range_end = LLONG_MAX,
464 }; 466 };
465 unsigned long nr_dirty = read_page_state(nr_dirty); 467 unsigned long nr_dirty = read_page_state(nr_dirty);
466 unsigned long nr_unstable = read_page_state(nr_unstable); 468 unsigned long nr_unstable = read_page_state(nr_unstable);
@@ -559,6 +561,8 @@ int write_inode_now(struct inode *inode, int sync)
559 struct writeback_control wbc = { 561 struct writeback_control wbc = {
560 .nr_to_write = LONG_MAX, 562 .nr_to_write = LONG_MAX,
561 .sync_mode = WB_SYNC_ALL, 563 .sync_mode = WB_SYNC_ALL,
564 .range_start = 0,
565 .range_end = LLONG_MAX,
562 }; 566 };
563 567
564 if (!mapping_cap_writeback_dirty(inode->i_mapping)) 568 if (!mapping_cap_writeback_dirty(inode->i_mapping))
@@ -619,7 +623,6 @@ int generic_osync_inode(struct inode *inode, struct address_space *mapping, int
619 int need_write_inode_now = 0; 623 int need_write_inode_now = 0;
620 int err2; 624 int err2;
621 625
622 current->flags |= PF_SYNCWRITE;
623 if (what & OSYNC_DATA) 626 if (what & OSYNC_DATA)
624 err = filemap_fdatawrite(mapping); 627 err = filemap_fdatawrite(mapping);
625 if (what & (OSYNC_METADATA|OSYNC_DATA)) { 628 if (what & (OSYNC_METADATA|OSYNC_DATA)) {
@@ -632,7 +635,6 @@ int generic_osync_inode(struct inode *inode, struct address_space *mapping, int
632 if (!err) 635 if (!err)
633 err = err2; 636 err = err2;
634 } 637 }
635 current->flags &= ~PF_SYNCWRITE;
636 638
637 spin_lock(&inode_lock); 639 spin_lock(&inode_lock);
638 if ((inode->i_state & I_DIRTY) && 640 if ((inode->i_state & I_DIRTY) &&
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index fc342cf7c2cc..087f3b734f40 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -169,7 +169,7 @@ static int fuse_release(struct inode *inode, struct file *file)
169 return fuse_release_common(inode, file, 0); 169 return fuse_release_common(inode, file, 0);
170} 170}
171 171
172static int fuse_flush(struct file *file) 172static int fuse_flush(struct file *file, fl_owner_t id)
173{ 173{
174 struct inode *inode = file->f_dentry->d_inode; 174 struct inode *inode = file->f_dentry->d_inode;
175 struct fuse_conn *fc = get_fuse_conn(inode); 175 struct fuse_conn *fc = get_fuse_conn(inode);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 7627022446b2..a13c0f529058 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -236,8 +236,9 @@ static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr
236 /* fsid is left zero */ 236 /* fsid is left zero */
237} 237}
238 238
239static int fuse_statfs(struct super_block *sb, struct kstatfs *buf) 239static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
240{ 240{
241 struct super_block *sb = dentry->d_sb;
241 struct fuse_conn *fc = get_fuse_conn_super(sb); 242 struct fuse_conn *fc = get_fuse_conn_super(sb);
242 struct fuse_req *req; 243 struct fuse_req *req;
243 struct fuse_statfs_out outarg; 244 struct fuse_statfs_out outarg;
@@ -569,11 +570,11 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
569 return err; 570 return err;
570} 571}
571 572
572static struct super_block *fuse_get_sb(struct file_system_type *fs_type, 573static int fuse_get_sb(struct file_system_type *fs_type,
573 int flags, const char *dev_name, 574 int flags, const char *dev_name,
574 void *raw_data) 575 void *raw_data, struct vfsmount *mnt)
575{ 576{
576 return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super); 577 return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super, mnt);
577} 578}
578 579
579static struct file_system_type fuse_fs_type = { 580static struct file_system_type fuse_fs_type = {
diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index 1e44dcfe49c4..13231dd5ce66 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -280,7 +280,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
280 block = off >> PAGE_CACHE_SHIFT; 280 block = off >> PAGE_CACHE_SHIFT;
281 node->page_offset = off & ~PAGE_CACHE_MASK; 281 node->page_offset = off & ~PAGE_CACHE_MASK;
282 for (i = 0; i < tree->pages_per_bnode; i++) { 282 for (i = 0; i < tree->pages_per_bnode; i++) {
283 page = read_cache_page(mapping, block++, (filler_t *)mapping->a_ops->readpage, NULL); 283 page = read_mapping_page(mapping, block++, NULL);
284 if (IS_ERR(page)) 284 if (IS_ERR(page))
285 goto fail; 285 goto fail;
286 if (PageError(page)) { 286 if (PageError(page)) {
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index d20131ce4b95..400357994319 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -59,7 +59,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
59 unlock_new_inode(tree->inode); 59 unlock_new_inode(tree->inode);
60 60
61 mapping = tree->inode->i_mapping; 61 mapping = tree->inode->i_mapping;
62 page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage, NULL); 62 page = read_mapping_page(mapping, 0, NULL);
63 if (IS_ERR(page)) 63 if (IS_ERR(page))
64 goto free_tree; 64 goto free_tree;
65 65
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 1181d116117d..d9227bf14e86 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -80,8 +80,10 @@ static void hfs_put_super(struct super_block *sb)
80 * 80 *
81 * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks. 81 * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks.
82 */ 82 */
83static int hfs_statfs(struct super_block *sb, struct kstatfs *buf) 83static int hfs_statfs(struct dentry *dentry, struct kstatfs *buf)
84{ 84{
85 struct super_block *sb = dentry->d_sb;
86
85 buf->f_type = HFS_SUPER_MAGIC; 87 buf->f_type = HFS_SUPER_MAGIC;
86 buf->f_bsize = sb->s_blocksize; 88 buf->f_bsize = sb->s_blocksize;
87 buf->f_blocks = (u32)HFS_SB(sb)->fs_ablocks * HFS_SB(sb)->fs_div; 89 buf->f_blocks = (u32)HFS_SB(sb)->fs_ablocks * HFS_SB(sb)->fs_div;
@@ -413,10 +415,11 @@ bail:
413 return res; 415 return res;
414} 416}
415 417
416static struct super_block *hfs_get_sb(struct file_system_type *fs_type, 418static int hfs_get_sb(struct file_system_type *fs_type,
417 int flags, const char *dev_name, void *data) 419 int flags, const char *dev_name, void *data,
420 struct vfsmount *mnt)
418{ 421{
419 return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super); 422 return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super, mnt);
420} 423}
421 424
422static struct file_system_type hfs_fs_type = { 425static struct file_system_type hfs_fs_type = {
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c
index 9fb51632303c..d128a25b74d2 100644
--- a/fs/hfsplus/bitmap.c
+++ b/fs/hfsplus/bitmap.c
@@ -31,8 +31,7 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
31 dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len); 31 dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len);
32 mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); 32 mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
33 mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; 33 mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
34 page = read_cache_page(mapping, offset / PAGE_CACHE_BITS, 34 page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL);
35 (filler_t *)mapping->a_ops->readpage, NULL);
36 pptr = kmap(page); 35 pptr = kmap(page);
37 curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32; 36 curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
38 i = offset % 32; 37 i = offset % 32;
@@ -72,8 +71,8 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
72 offset += PAGE_CACHE_BITS; 71 offset += PAGE_CACHE_BITS;
73 if (offset >= size) 72 if (offset >= size)
74 break; 73 break;
75 page = read_cache_page(mapping, offset / PAGE_CACHE_BITS, 74 page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS,
76 (filler_t *)mapping->a_ops->readpage, NULL); 75 NULL);
77 curr = pptr = kmap(page); 76 curr = pptr = kmap(page);
78 if ((size ^ offset) / PAGE_CACHE_BITS) 77 if ((size ^ offset) / PAGE_CACHE_BITS)
79 end = pptr + PAGE_CACHE_BITS / 32; 78 end = pptr + PAGE_CACHE_BITS / 32;
@@ -119,8 +118,8 @@ found:
119 set_page_dirty(page); 118 set_page_dirty(page);
120 kunmap(page); 119 kunmap(page);
121 offset += PAGE_CACHE_BITS; 120 offset += PAGE_CACHE_BITS;
122 page = read_cache_page(mapping, offset / PAGE_CACHE_BITS, 121 page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS,
123 (filler_t *)mapping->a_ops->readpage, NULL); 122 NULL);
124 pptr = kmap(page); 123 pptr = kmap(page);
125 curr = pptr; 124 curr = pptr;
126 end = pptr + PAGE_CACHE_BITS / 32; 125 end = pptr + PAGE_CACHE_BITS / 32;
@@ -167,7 +166,7 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
167 mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); 166 mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
168 mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; 167 mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
169 pnr = offset / PAGE_CACHE_BITS; 168 pnr = offset / PAGE_CACHE_BITS;
170 page = read_cache_page(mapping, pnr, (filler_t *)mapping->a_ops->readpage, NULL); 169 page = read_mapping_page(mapping, pnr, NULL);
171 pptr = kmap(page); 170 pptr = kmap(page);
172 curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32; 171 curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
173 end = pptr + PAGE_CACHE_BITS / 32; 172 end = pptr + PAGE_CACHE_BITS / 32;
@@ -199,7 +198,7 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
199 break; 198 break;
200 set_page_dirty(page); 199 set_page_dirty(page);
201 kunmap(page); 200 kunmap(page);
202 page = read_cache_page(mapping, ++pnr, (filler_t *)mapping->a_ops->readpage, NULL); 201 page = read_mapping_page(mapping, ++pnr, NULL);
203 pptr = kmap(page); 202 pptr = kmap(page);
204 curr = pptr; 203 curr = pptr;
205 end = pptr + PAGE_CACHE_BITS / 32; 204 end = pptr + PAGE_CACHE_BITS / 32;
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 746abc9ecf70..77bf434da679 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -440,7 +440,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
440 block = off >> PAGE_CACHE_SHIFT; 440 block = off >> PAGE_CACHE_SHIFT;
441 node->page_offset = off & ~PAGE_CACHE_MASK; 441 node->page_offset = off & ~PAGE_CACHE_MASK;
442 for (i = 0; i < tree->pages_per_bnode; block++, i++) { 442 for (i = 0; i < tree->pages_per_bnode; block++, i++) {
443 page = read_cache_page(mapping, block, (filler_t *)mapping->a_ops->readpage, NULL); 443 page = read_mapping_page(mapping, block, NULL);
444 if (IS_ERR(page)) 444 if (IS_ERR(page))
445 goto fail; 445 goto fail;
446 if (PageError(page)) { 446 if (PageError(page)) {
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index effa8991999c..cfc852fdd1b5 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -38,7 +38,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
38 goto free_tree; 38 goto free_tree;
39 39
40 mapping = tree->inode->i_mapping; 40 mapping = tree->inode->i_mapping;
41 page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage, NULL); 41 page = read_mapping_page(mapping, 0, NULL);
42 if (IS_ERR(page)) 42 if (IS_ERR(page))
43 goto free_tree; 43 goto free_tree;
44 44
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 7843f792a4b7..0a92fa2336a2 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -212,8 +212,10 @@ static void hfsplus_put_super(struct super_block *sb)
212 sb->s_fs_info = NULL; 212 sb->s_fs_info = NULL;
213} 213}
214 214
215static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf) 215static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf)
216{ 216{
217 struct super_block *sb = dentry->d_sb;
218
217 buf->f_type = HFSPLUS_SUPER_MAGIC; 219 buf->f_type = HFSPLUS_SUPER_MAGIC;
218 buf->f_bsize = sb->s_blocksize; 220 buf->f_bsize = sb->s_blocksize;
219 buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift; 221 buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift;
@@ -450,10 +452,12 @@ static void hfsplus_destroy_inode(struct inode *inode)
450 452
451#define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) 453#define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info)
452 454
453static struct super_block *hfsplus_get_sb(struct file_system_type *fs_type, 455static int hfsplus_get_sb(struct file_system_type *fs_type,
454 int flags, const char *dev_name, void *data) 456 int flags, const char *dev_name, void *data,
457 struct vfsmount *mnt)
455{ 458{
456 return get_sb_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super); 459 return get_sb_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super,
460 mnt);
457} 461}
458 462
459static struct file_system_type hfsplus_fs_type = { 463static struct file_system_type hfsplus_fs_type = {
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index bf0f8e16e433..8e0d37743e7c 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -239,7 +239,7 @@ static int read_inode(struct inode *ino)
239 return(err); 239 return(err);
240} 240}
241 241
242int hostfs_statfs(struct super_block *sb, struct kstatfs *sf) 242int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
243{ 243{
244 /* do_statfs uses struct statfs64 internally, but the linux kernel 244 /* do_statfs uses struct statfs64 internally, but the linux kernel
245 * struct statfs still has 32-bit versions for most of these fields, 245 * struct statfs still has 32-bit versions for most of these fields,
@@ -252,7 +252,7 @@ int hostfs_statfs(struct super_block *sb, struct kstatfs *sf)
252 long long f_files; 252 long long f_files;
253 long long f_ffree; 253 long long f_ffree;
254 254
255 err = do_statfs(HOSTFS_I(sb->s_root->d_inode)->host_filename, 255 err = do_statfs(HOSTFS_I(dentry->d_sb->s_root->d_inode)->host_filename,
256 &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files, 256 &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
257 &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), 257 &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
258 &sf->f_namelen, sf->f_spare); 258 &sf->f_namelen, sf->f_spare);
@@ -993,11 +993,11 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
993 return(err); 993 return(err);
994} 994}
995 995
996static struct super_block *hostfs_read_sb(struct file_system_type *type, 996static int hostfs_read_sb(struct file_system_type *type,
997 int flags, const char *dev_name, 997 int flags, const char *dev_name,
998 void *data) 998 void *data, struct vfsmount *mnt)
999{ 999{
1000 return(get_sb_nodev(type, flags, data, hostfs_fill_sb_common)); 1000 return get_sb_nodev(type, flags, data, hostfs_fill_sb_common, mnt);
1001} 1001}
1002 1002
1003static struct file_system_type hostfs_type = { 1003static struct file_system_type hostfs_type = {
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index d72d8c87c996..f798480a363f 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -135,8 +135,9 @@ static unsigned count_bitmaps(struct super_block *s)
135 return count; 135 return count;
136} 136}
137 137
138static int hpfs_statfs(struct super_block *s, struct kstatfs *buf) 138static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf)
139{ 139{
140 struct super_block *s = dentry->d_sb;
140 struct hpfs_sb_info *sbi = hpfs_sb(s); 141 struct hpfs_sb_info *sbi = hpfs_sb(s);
141 lock_kernel(); 142 lock_kernel();
142 143
@@ -662,10 +663,11 @@ bail0:
662 return -EINVAL; 663 return -EINVAL;
663} 664}
664 665
665static struct super_block *hpfs_get_sb(struct file_system_type *fs_type, 666static int hpfs_get_sb(struct file_system_type *fs_type,
666 int flags, const char *dev_name, void *data) 667 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
667{ 668{
668 return get_sb_bdev(fs_type, flags, dev_name, data, hpfs_fill_super); 669 return get_sb_bdev(fs_type, flags, dev_name, data, hpfs_fill_super,
670 mnt);
669} 671}
670 672
671static struct file_system_type hpfs_fs_type = { 673static struct file_system_type hpfs_fs_type = {
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
index 5e6363be246f..3a9bdf58166f 100644
--- a/fs/hppfs/hppfs_kern.c
+++ b/fs/hppfs/hppfs_kern.c
@@ -616,7 +616,7 @@ static const struct file_operations hppfs_dir_fops = {
616 .fsync = hppfs_fsync, 616 .fsync = hppfs_fsync,
617}; 617};
618 618
619static int hppfs_statfs(struct super_block *sb, struct kstatfs *sf) 619static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf)
620{ 620{
621 sf->f_blocks = 0; 621 sf->f_blocks = 0;
622 sf->f_bfree = 0; 622 sf->f_bfree = 0;
@@ -769,11 +769,11 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
769 return(err); 769 return(err);
770} 770}
771 771
772static struct super_block *hppfs_read_super(struct file_system_type *type, 772static int hppfs_read_super(struct file_system_type *type,
773 int flags, const char *dev_name, 773 int flags, const char *dev_name,
774 void *data) 774 void *data, struct vfsmount *mnt)
775{ 775{
776 return(get_sb_nodev(type, flags, data, hppfs_fill_super)); 776 return get_sb_nodev(type, flags, data, hppfs_fill_super, mnt);
777} 777}
778 778
779static struct file_system_type hppfs_type = { 779static struct file_system_type hppfs_type = {
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 3a5b4e923455..e6410d8edd0e 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -59,7 +59,6 @@ static void huge_pagevec_release(struct pagevec *pvec)
59static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) 59static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
60{ 60{
61 struct inode *inode = file->f_dentry->d_inode; 61 struct inode *inode = file->f_dentry->d_inode;
62 struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode);
63 loff_t len, vma_len; 62 loff_t len, vma_len;
64 int ret; 63 int ret;
65 64
@@ -87,9 +86,10 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
87 if (!(vma->vm_flags & VM_WRITE) && len > inode->i_size) 86 if (!(vma->vm_flags & VM_WRITE) && len > inode->i_size)
88 goto out; 87 goto out;
89 88
90 if (vma->vm_flags & VM_MAYSHARE) 89 if (vma->vm_flags & VM_MAYSHARE &&
91 if (hugetlb_extend_reservation(info, len >> HPAGE_SHIFT) != 0) 90 hugetlb_reserve_pages(inode, vma->vm_pgoff >> (HPAGE_SHIFT-PAGE_SHIFT),
92 goto out; 91 len >> HPAGE_SHIFT))
92 goto out;
93 93
94 ret = 0; 94 ret = 0;
95 hugetlb_prefault_arch_hook(vma->vm_mm); 95 hugetlb_prefault_arch_hook(vma->vm_mm);
@@ -195,12 +195,8 @@ static void truncate_hugepages(struct inode *inode, loff_t lstart)
195 const pgoff_t start = lstart >> HPAGE_SHIFT; 195 const pgoff_t start = lstart >> HPAGE_SHIFT;
196 struct pagevec pvec; 196 struct pagevec pvec;
197 pgoff_t next; 197 pgoff_t next;
198 int i; 198 int i, freed = 0;
199 199
200 hugetlb_truncate_reservation(HUGETLBFS_I(inode),
201 lstart >> HPAGE_SHIFT);
202 if (!mapping->nrpages)
203 return;
204 pagevec_init(&pvec, 0); 200 pagevec_init(&pvec, 0);
205 next = start; 201 next = start;
206 while (1) { 202 while (1) {
@@ -221,10 +217,12 @@ static void truncate_hugepages(struct inode *inode, loff_t lstart)
221 truncate_huge_page(page); 217 truncate_huge_page(page);
222 unlock_page(page); 218 unlock_page(page);
223 hugetlb_put_quota(mapping); 219 hugetlb_put_quota(mapping);
220 freed++;
224 } 221 }
225 huge_pagevec_release(&pvec); 222 huge_pagevec_release(&pvec);
226 } 223 }
227 BUG_ON(!lstart && mapping->nrpages); 224 BUG_ON(!lstart && mapping->nrpages);
225 hugetlb_unreserve_pages(inode, start, freed);
228} 226}
229 227
230static void hugetlbfs_delete_inode(struct inode *inode) 228static void hugetlbfs_delete_inode(struct inode *inode)
@@ -366,6 +364,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
366 inode->i_mapping->a_ops = &hugetlbfs_aops; 364 inode->i_mapping->a_ops = &hugetlbfs_aops;
367 inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info; 365 inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info;
368 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 366 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
367 INIT_LIST_HEAD(&inode->i_mapping->private_list);
369 info = HUGETLBFS_I(inode); 368 info = HUGETLBFS_I(inode);
370 mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, NULL); 369 mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, NULL);
371 switch (mode & S_IFMT) { 370 switch (mode & S_IFMT) {
@@ -467,9 +466,9 @@ static int hugetlbfs_set_page_dirty(struct page *page)
467 return 0; 466 return 0;
468} 467}
469 468
470static int hugetlbfs_statfs(struct super_block *sb, struct kstatfs *buf) 469static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
471{ 470{
472 struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(sb); 471 struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb);
473 472
474 buf->f_type = HUGETLBFS_MAGIC; 473 buf->f_type = HUGETLBFS_MAGIC;
475 buf->f_bsize = HPAGE_SIZE; 474 buf->f_bsize = HPAGE_SIZE;
@@ -538,7 +537,6 @@ static struct inode *hugetlbfs_alloc_inode(struct super_block *sb)
538 hugetlbfs_inc_free_inodes(sbinfo); 537 hugetlbfs_inc_free_inodes(sbinfo);
539 return NULL; 538 return NULL;
540 } 539 }
541 p->prereserved_hpages = 0;
542 return &p->vfs_inode; 540 return &p->vfs_inode;
543} 541}
544 542
@@ -723,10 +721,10 @@ void hugetlb_put_quota(struct address_space *mapping)
723 } 721 }
724} 722}
725 723
726static struct super_block *hugetlbfs_get_sb(struct file_system_type *fs_type, 724static int hugetlbfs_get_sb(struct file_system_type *fs_type,
727 int flags, const char *dev_name, void *data) 725 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
728{ 726{
729 return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super); 727 return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super, mnt);
730} 728}
731 729
732static struct file_system_type hugetlbfs_fs_type = { 730static struct file_system_type hugetlbfs_fs_type = {
@@ -781,8 +779,7 @@ struct file *hugetlb_zero_setup(size_t size)
781 goto out_file; 779 goto out_file;
782 780
783 error = -ENOMEM; 781 error = -ENOMEM;
784 if (hugetlb_extend_reservation(HUGETLBFS_I(inode), 782 if (hugetlb_reserve_pages(inode, 0, size >> HPAGE_SHIFT))
785 size >> HPAGE_SHIFT) != 0)
786 goto out_inode; 783 goto out_inode;
787 784
788 d_instantiate(dentry, inode); 785 d_instantiate(dentry, inode);
diff --git a/fs/inotify.c b/fs/inotify.c
index 732ec4bd5774..723836a1f718 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -5,7 +5,10 @@
5 * John McCutchan <ttb@tentacle.dhs.org> 5 * John McCutchan <ttb@tentacle.dhs.org>
6 * Robert Love <rml@novell.com> 6 * Robert Love <rml@novell.com>
7 * 7 *
8 * Kernel API added by: Amy Griffis <amy.griffis@hp.com>
9 *
8 * Copyright (C) 2005 John McCutchan 10 * Copyright (C) 2005 John McCutchan
11 * Copyright 2006 Hewlett-Packard Development Company, L.P.
9 * 12 *
10 * This program is free software; you can redistribute it and/or modify it 13 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the 14 * under the terms of the GNU General Public License as published by the
@@ -20,35 +23,17 @@
20 23
21#include <linux/module.h> 24#include <linux/module.h>
22#include <linux/kernel.h> 25#include <linux/kernel.h>
23#include <linux/sched.h>
24#include <linux/spinlock.h> 26#include <linux/spinlock.h>
25#include <linux/idr.h> 27#include <linux/idr.h>
26#include <linux/slab.h> 28#include <linux/slab.h>
27#include <linux/fs.h> 29#include <linux/fs.h>
28#include <linux/file.h>
29#include <linux/mount.h>
30#include <linux/namei.h>
31#include <linux/poll.h>
32#include <linux/init.h> 30#include <linux/init.h>
33#include <linux/list.h> 31#include <linux/list.h>
34#include <linux/writeback.h> 32#include <linux/writeback.h>
35#include <linux/inotify.h> 33#include <linux/inotify.h>
36#include <linux/syscalls.h>
37
38#include <asm/ioctls.h>
39 34
40static atomic_t inotify_cookie; 35static atomic_t inotify_cookie;
41 36
42static kmem_cache_t *watch_cachep __read_mostly;
43static kmem_cache_t *event_cachep __read_mostly;
44
45static struct vfsmount *inotify_mnt __read_mostly;
46
47/* these are configurable via /proc/sys/fs/inotify/ */
48int inotify_max_user_instances __read_mostly;
49int inotify_max_user_watches __read_mostly;
50int inotify_max_queued_events __read_mostly;
51
52/* 37/*
53 * Lock ordering: 38 * Lock ordering:
54 * 39 *
@@ -56,327 +41,108 @@ int inotify_max_queued_events __read_mostly;
56 * iprune_mutex (synchronize shrink_icache_memory()) 41 * iprune_mutex (synchronize shrink_icache_memory())
57 * inode_lock (protects the super_block->s_inodes list) 42 * inode_lock (protects the super_block->s_inodes list)
58 * inode->inotify_mutex (protects inode->inotify_watches and watches->i_list) 43 * inode->inotify_mutex (protects inode->inotify_watches and watches->i_list)
59 * inotify_dev->mutex (protects inotify_device and watches->d_list) 44 * inotify_handle->mutex (protects inotify_handle and watches->h_list)
45 *
46 * The inode->inotify_mutex and inotify_handle->mutex and held during execution
47 * of a caller's event handler. Thus, the caller must not hold any locks
48 * taken in their event handler while calling any of the published inotify
49 * interfaces.
60 */ 50 */
61 51
62/* 52/*
63 * Lifetimes of the three main data structures--inotify_device, inode, and 53 * Lifetimes of the three main data structures--inotify_handle, inode, and
64 * inotify_watch--are managed by reference count. 54 * inotify_watch--are managed by reference count.
65 * 55 *
66 * inotify_device: Lifetime is from inotify_init() until release. Additional 56 * inotify_handle: Lifetime is from inotify_init() to inotify_destroy().
67 * references can bump the count via get_inotify_dev() and drop the count via 57 * Additional references can bump the count via get_inotify_handle() and drop
68 * put_inotify_dev(). 58 * the count via put_inotify_handle().
69 * 59 *
70 * inotify_watch: Lifetime is from create_watch() to destory_watch(). 60 * inotify_watch: for inotify's purposes, lifetime is from inotify_add_watch()
71 * Additional references can bump the count via get_inotify_watch() and drop 61 * to remove_watch_no_event(). Additional references can bump the count via
72 * the count via put_inotify_watch(). 62 * get_inotify_watch() and drop the count via put_inotify_watch(). The caller
63 * is reponsible for the final put after receiving IN_IGNORED, or when using
64 * IN_ONESHOT after receiving the first event. Inotify does the final put if
65 * inotify_destroy() is called.
73 * 66 *
74 * inode: Pinned so long as the inode is associated with a watch, from 67 * inode: Pinned so long as the inode is associated with a watch, from
75 * create_watch() to put_inotify_watch(). 68 * inotify_add_watch() to the final put_inotify_watch().
76 */ 69 */
77 70
78/* 71/*
79 * struct inotify_device - represents an inotify instance 72 * struct inotify_handle - represents an inotify instance
80 * 73 *
81 * This structure is protected by the mutex 'mutex'. 74 * This structure is protected by the mutex 'mutex'.
82 */ 75 */
83struct inotify_device { 76struct inotify_handle {
84 wait_queue_head_t wq; /* wait queue for i/o */
85 struct idr idr; /* idr mapping wd -> watch */ 77 struct idr idr; /* idr mapping wd -> watch */
86 struct mutex mutex; /* protects this bad boy */ 78 struct mutex mutex; /* protects this bad boy */
87 struct list_head events; /* list of queued events */
88 struct list_head watches; /* list of watches */ 79 struct list_head watches; /* list of watches */
89 atomic_t count; /* reference count */ 80 atomic_t count; /* reference count */
90 struct user_struct *user; /* user who opened this dev */
91 unsigned int queue_size; /* size of the queue (bytes) */
92 unsigned int event_count; /* number of pending events */
93 unsigned int max_events; /* maximum number of events */
94 u32 last_wd; /* the last wd allocated */ 81 u32 last_wd; /* the last wd allocated */
82 const struct inotify_operations *in_ops; /* inotify caller operations */
95}; 83};
96 84
97/* 85static inline void get_inotify_handle(struct inotify_handle *ih)
98 * struct inotify_kernel_event - An inotify event, originating from a watch and
99 * queued for user-space. A list of these is attached to each instance of the
100 * device. In read(), this list is walked and all events that can fit in the
101 * buffer are returned.
102 *
103 * Protected by dev->mutex of the device in which we are queued.
104 */
105struct inotify_kernel_event {
106 struct inotify_event event; /* the user-space event */
107 struct list_head list; /* entry in inotify_device's list */
108 char *name; /* filename, if any */
109};
110
111/*
112 * struct inotify_watch - represents a watch request on a specific inode
113 *
114 * d_list is protected by dev->mutex of the associated watch->dev.
115 * i_list and mask are protected by inode->inotify_mutex of the associated inode.
116 * dev, inode, and wd are never written to once the watch is created.
117 */
118struct inotify_watch {
119 struct list_head d_list; /* entry in inotify_device's list */
120 struct list_head i_list; /* entry in inode's list */
121 atomic_t count; /* reference count */
122 struct inotify_device *dev; /* associated device */
123 struct inode *inode; /* associated inode */
124 s32 wd; /* watch descriptor */
125 u32 mask; /* event mask for this watch */
126};
127
128#ifdef CONFIG_SYSCTL
129
130#include <linux/sysctl.h>
131
132static int zero;
133
134ctl_table inotify_table[] = {
135 {
136 .ctl_name = INOTIFY_MAX_USER_INSTANCES,
137 .procname = "max_user_instances",
138 .data = &inotify_max_user_instances,
139 .maxlen = sizeof(int),
140 .mode = 0644,
141 .proc_handler = &proc_dointvec_minmax,
142 .strategy = &sysctl_intvec,
143 .extra1 = &zero,
144 },
145 {
146 .ctl_name = INOTIFY_MAX_USER_WATCHES,
147 .procname = "max_user_watches",
148 .data = &inotify_max_user_watches,
149 .maxlen = sizeof(int),
150 .mode = 0644,
151 .proc_handler = &proc_dointvec_minmax,
152 .strategy = &sysctl_intvec,
153 .extra1 = &zero,
154 },
155 {
156 .ctl_name = INOTIFY_MAX_QUEUED_EVENTS,
157 .procname = "max_queued_events",
158 .data = &inotify_max_queued_events,
159 .maxlen = sizeof(int),
160 .mode = 0644,
161 .proc_handler = &proc_dointvec_minmax,
162 .strategy = &sysctl_intvec,
163 .extra1 = &zero
164 },
165 { .ctl_name = 0 }
166};
167#endif /* CONFIG_SYSCTL */
168
169static inline void get_inotify_dev(struct inotify_device *dev)
170{ 86{
171 atomic_inc(&dev->count); 87 atomic_inc(&ih->count);
172} 88}
173 89
174static inline void put_inotify_dev(struct inotify_device *dev) 90static inline void put_inotify_handle(struct inotify_handle *ih)
175{ 91{
176 if (atomic_dec_and_test(&dev->count)) { 92 if (atomic_dec_and_test(&ih->count)) {
177 atomic_dec(&dev->user->inotify_devs); 93 idr_destroy(&ih->idr);
178 free_uid(dev->user); 94 kfree(ih);
179 idr_destroy(&dev->idr);
180 kfree(dev);
181 } 95 }
182} 96}
183 97
184static inline void get_inotify_watch(struct inotify_watch *watch) 98/**
99 * get_inotify_watch - grab a reference to an inotify_watch
100 * @watch: watch to grab
101 */
102void get_inotify_watch(struct inotify_watch *watch)
185{ 103{
186 atomic_inc(&watch->count); 104 atomic_inc(&watch->count);
187} 105}
106EXPORT_SYMBOL_GPL(get_inotify_watch);
188 107
189/* 108/**
190 * put_inotify_watch - decrements the ref count on a given watch. cleans up 109 * put_inotify_watch - decrements the ref count on a given watch. cleans up
191 * the watch and its references if the count reaches zero. 110 * watch references if the count reaches zero. inotify_watch is freed by
111 * inotify callers via the destroy_watch() op.
112 * @watch: watch to release
192 */ 113 */
193static inline void put_inotify_watch(struct inotify_watch *watch) 114void put_inotify_watch(struct inotify_watch *watch)
194{ 115{
195 if (atomic_dec_and_test(&watch->count)) { 116 if (atomic_dec_and_test(&watch->count)) {
196 put_inotify_dev(watch->dev); 117 struct inotify_handle *ih = watch->ih;
197 iput(watch->inode);
198 kmem_cache_free(watch_cachep, watch);
199 }
200}
201
202/*
203 * kernel_event - create a new kernel event with the given parameters
204 *
205 * This function can sleep.
206 */
207static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie,
208 const char *name)
209{
210 struct inotify_kernel_event *kevent;
211
212 kevent = kmem_cache_alloc(event_cachep, GFP_KERNEL);
213 if (unlikely(!kevent))
214 return NULL;
215
216 /* we hand this out to user-space, so zero it just in case */
217 memset(&kevent->event, 0, sizeof(struct inotify_event));
218
219 kevent->event.wd = wd;
220 kevent->event.mask = mask;
221 kevent->event.cookie = cookie;
222
223 INIT_LIST_HEAD(&kevent->list);
224
225 if (name) {
226 size_t len, rem, event_size = sizeof(struct inotify_event);
227
228 /*
229 * We need to pad the filename so as to properly align an
230 * array of inotify_event structures. Because the structure is
231 * small and the common case is a small filename, we just round
232 * up to the next multiple of the structure's sizeof. This is
233 * simple and safe for all architectures.
234 */
235 len = strlen(name) + 1;
236 rem = event_size - len;
237 if (len > event_size) {
238 rem = event_size - (len % event_size);
239 if (len % event_size == 0)
240 rem = 0;
241 }
242
243 kevent->name = kmalloc(len + rem, GFP_KERNEL);
244 if (unlikely(!kevent->name)) {
245 kmem_cache_free(event_cachep, kevent);
246 return NULL;
247 }
248 memcpy(kevent->name, name, len);
249 if (rem)
250 memset(kevent->name + len, 0, rem);
251 kevent->event.len = len + rem;
252 } else {
253 kevent->event.len = 0;
254 kevent->name = NULL;
255 }
256
257 return kevent;
258}
259
260/*
261 * inotify_dev_get_event - return the next event in the given dev's queue
262 *
263 * Caller must hold dev->mutex.
264 */
265static inline struct inotify_kernel_event *
266inotify_dev_get_event(struct inotify_device *dev)
267{
268 return list_entry(dev->events.next, struct inotify_kernel_event, list);
269}
270
271/*
272 * inotify_dev_queue_event - add a new event to the given device
273 *
274 * Caller must hold dev->mutex. Can sleep (calls kernel_event()).
275 */
276static void inotify_dev_queue_event(struct inotify_device *dev,
277 struct inotify_watch *watch, u32 mask,
278 u32 cookie, const char *name)
279{
280 struct inotify_kernel_event *kevent, *last;
281
282 /* coalescing: drop this event if it is a dupe of the previous */
283 last = inotify_dev_get_event(dev);
284 if (last && last->event.mask == mask && last->event.wd == watch->wd &&
285 last->event.cookie == cookie) {
286 const char *lastname = last->name;
287
288 if (!name && !lastname)
289 return;
290 if (name && lastname && !strcmp(lastname, name))
291 return;
292 }
293
294 /* the queue overflowed and we already sent the Q_OVERFLOW event */
295 if (unlikely(dev->event_count > dev->max_events))
296 return;
297
298 /* if the queue overflows, we need to notify user space */
299 if (unlikely(dev->event_count == dev->max_events))
300 kevent = kernel_event(-1, IN_Q_OVERFLOW, cookie, NULL);
301 else
302 kevent = kernel_event(watch->wd, mask, cookie, name);
303
304 if (unlikely(!kevent))
305 return;
306
307 /* queue the event and wake up anyone waiting */
308 dev->event_count++;
309 dev->queue_size += sizeof(struct inotify_event) + kevent->event.len;
310 list_add_tail(&kevent->list, &dev->events);
311 wake_up_interruptible(&dev->wq);
312}
313
314/*
315 * remove_kevent - cleans up and ultimately frees the given kevent
316 *
317 * Caller must hold dev->mutex.
318 */
319static void remove_kevent(struct inotify_device *dev,
320 struct inotify_kernel_event *kevent)
321{
322 list_del(&kevent->list);
323
324 dev->event_count--;
325 dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len;
326
327 kfree(kevent->name);
328 kmem_cache_free(event_cachep, kevent);
329}
330 118
331/* 119 iput(watch->inode);
332 * inotify_dev_event_dequeue - destroy an event on the given device 120 ih->in_ops->destroy_watch(watch);
333 * 121 put_inotify_handle(ih);
334 * Caller must hold dev->mutex.
335 */
336static void inotify_dev_event_dequeue(struct inotify_device *dev)
337{
338 if (!list_empty(&dev->events)) {
339 struct inotify_kernel_event *kevent;
340 kevent = inotify_dev_get_event(dev);
341 remove_kevent(dev, kevent);
342 } 122 }
343} 123}
124EXPORT_SYMBOL_GPL(put_inotify_watch);
344 125
345/* 126/*
346 * inotify_dev_get_wd - returns the next WD for use by the given dev 127 * inotify_handle_get_wd - returns the next WD for use by the given handle
347 * 128 *
348 * Callers must hold dev->mutex. This function can sleep. 129 * Callers must hold ih->mutex. This function can sleep.
349 */ 130 */
350static int inotify_dev_get_wd(struct inotify_device *dev, 131static int inotify_handle_get_wd(struct inotify_handle *ih,
351 struct inotify_watch *watch) 132 struct inotify_watch *watch)
352{ 133{
353 int ret; 134 int ret;
354 135
355 do { 136 do {
356 if (unlikely(!idr_pre_get(&dev->idr, GFP_KERNEL))) 137 if (unlikely(!idr_pre_get(&ih->idr, GFP_KERNEL)))
357 return -ENOSPC; 138 return -ENOSPC;
358 ret = idr_get_new_above(&dev->idr, watch, dev->last_wd+1, &watch->wd); 139 ret = idr_get_new_above(&ih->idr, watch, ih->last_wd+1, &watch->wd);
359 } while (ret == -EAGAIN); 140 } while (ret == -EAGAIN);
360 141
361 return ret; 142 if (likely(!ret))
362} 143 ih->last_wd = watch->wd;
363 144
364/* 145 return ret;
365 * find_inode - resolve a user-given path to a specific inode and return a nd
366 */
367static int find_inode(const char __user *dirname, struct nameidata *nd,
368 unsigned flags)
369{
370 int error;
371
372 error = __user_walk(dirname, flags, nd);
373 if (error)
374 return error;
375 /* you can only watch an inode if you have read permissions on it */
376 error = vfs_permission(nd, MAY_READ);
377 if (error)
378 path_release(nd);
379 return error;
380} 146}
381 147
382/* 148/*
@@ -422,67 +188,18 @@ static void set_dentry_child_flags(struct inode *inode, int watched)
422} 188}
423 189
424/* 190/*
425 * create_watch - creates a watch on the given device. 191 * inotify_find_handle - find the watch associated with the given inode and
426 * 192 * handle
427 * Callers must hold dev->mutex. Calls inotify_dev_get_wd() so may sleep.
428 * Both 'dev' and 'inode' (by way of nameidata) need to be pinned.
429 */
430static struct inotify_watch *create_watch(struct inotify_device *dev,
431 u32 mask, struct inode *inode)
432{
433 struct inotify_watch *watch;
434 int ret;
435
436 if (atomic_read(&dev->user->inotify_watches) >=
437 inotify_max_user_watches)
438 return ERR_PTR(-ENOSPC);
439
440 watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL);
441 if (unlikely(!watch))
442 return ERR_PTR(-ENOMEM);
443
444 ret = inotify_dev_get_wd(dev, watch);
445 if (unlikely(ret)) {
446 kmem_cache_free(watch_cachep, watch);
447 return ERR_PTR(ret);
448 }
449
450 dev->last_wd = watch->wd;
451 watch->mask = mask;
452 atomic_set(&watch->count, 0);
453 INIT_LIST_HEAD(&watch->d_list);
454 INIT_LIST_HEAD(&watch->i_list);
455
456 /* save a reference to device and bump the count to make it official */
457 get_inotify_dev(dev);
458 watch->dev = dev;
459
460 /*
461 * Save a reference to the inode and bump the ref count to make it
462 * official. We hold a reference to nameidata, which makes this safe.
463 */
464 watch->inode = igrab(inode);
465
466 /* bump our own count, corresponding to our entry in dev->watches */
467 get_inotify_watch(watch);
468
469 atomic_inc(&dev->user->inotify_watches);
470
471 return watch;
472}
473
474/*
475 * inotify_find_dev - find the watch associated with the given inode and dev
476 * 193 *
477 * Callers must hold inode->inotify_mutex. 194 * Callers must hold inode->inotify_mutex.
478 */ 195 */
479static struct inotify_watch *inode_find_dev(struct inode *inode, 196static struct inotify_watch *inode_find_handle(struct inode *inode,
480 struct inotify_device *dev) 197 struct inotify_handle *ih)
481{ 198{
482 struct inotify_watch *watch; 199 struct inotify_watch *watch;
483 200
484 list_for_each_entry(watch, &inode->inotify_watches, i_list) { 201 list_for_each_entry(watch, &inode->inotify_watches, i_list) {
485 if (watch->dev == dev) 202 if (watch->ih == ih)
486 return watch; 203 return watch;
487 } 204 }
488 205
@@ -490,40 +207,40 @@ static struct inotify_watch *inode_find_dev(struct inode *inode,
490} 207}
491 208
492/* 209/*
493 * remove_watch_no_event - remove_watch() without the IN_IGNORED event. 210 * remove_watch_no_event - remove watch without the IN_IGNORED event.
211 *
212 * Callers must hold both inode->inotify_mutex and ih->mutex.
494 */ 213 */
495static void remove_watch_no_event(struct inotify_watch *watch, 214static void remove_watch_no_event(struct inotify_watch *watch,
496 struct inotify_device *dev) 215 struct inotify_handle *ih)
497{ 216{
498 list_del(&watch->i_list); 217 list_del(&watch->i_list);
499 list_del(&watch->d_list); 218 list_del(&watch->h_list);
500 219
501 if (!inotify_inode_watched(watch->inode)) 220 if (!inotify_inode_watched(watch->inode))
502 set_dentry_child_flags(watch->inode, 0); 221 set_dentry_child_flags(watch->inode, 0);
503 222
504 atomic_dec(&dev->user->inotify_watches); 223 idr_remove(&ih->idr, watch->wd);
505 idr_remove(&dev->idr, watch->wd);
506 put_inotify_watch(watch);
507} 224}
508 225
509/* 226/**
510 * remove_watch - Remove a watch from both the device and the inode. Sends 227 * inotify_remove_watch_locked - Remove a watch from both the handle and the
511 * the IN_IGNORED event to the given device signifying that the inode is no 228 * inode. Sends the IN_IGNORED event signifying that the inode is no longer
512 * longer watched. 229 * watched. May be invoked from a caller's event handler.
513 * 230 * @ih: inotify handle associated with watch
514 * Callers must hold both inode->inotify_mutex and dev->mutex. We drop a 231 * @watch: watch to remove
515 * reference to the inode before returning.
516 * 232 *
517 * The inode is not iput() so as to remain atomic. If the inode needs to be 233 * Callers must hold both inode->inotify_mutex and ih->mutex.
518 * iput(), the call returns one. Otherwise, it returns zero.
519 */ 234 */
520static void remove_watch(struct inotify_watch *watch,struct inotify_device *dev) 235void inotify_remove_watch_locked(struct inotify_handle *ih,
236 struct inotify_watch *watch)
521{ 237{
522 inotify_dev_queue_event(dev, watch, IN_IGNORED, 0, NULL); 238 remove_watch_no_event(watch, ih);
523 remove_watch_no_event(watch, dev); 239 ih->in_ops->handle_event(watch, watch->wd, IN_IGNORED, 0, NULL, NULL);
524} 240}
241EXPORT_SYMBOL_GPL(inotify_remove_watch_locked);
525 242
526/* Kernel API */ 243/* Kernel API for producing events */
527 244
528/* 245/*
529 * inotify_d_instantiate - instantiate dcache entry for inode 246 * inotify_d_instantiate - instantiate dcache entry for inode
@@ -563,9 +280,10 @@ void inotify_d_move(struct dentry *entry)
563 * @mask: event mask describing this event 280 * @mask: event mask describing this event
564 * @cookie: cookie for synchronization, or zero 281 * @cookie: cookie for synchronization, or zero
565 * @name: filename, if any 282 * @name: filename, if any
283 * @n_inode: inode associated with name
566 */ 284 */
567void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie, 285void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie,
568 const char *name) 286 const char *name, struct inode *n_inode)
569{ 287{
570 struct inotify_watch *watch, *next; 288 struct inotify_watch *watch, *next;
571 289
@@ -576,14 +294,13 @@ void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie,
576 list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) { 294 list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) {
577 u32 watch_mask = watch->mask; 295 u32 watch_mask = watch->mask;
578 if (watch_mask & mask) { 296 if (watch_mask & mask) {
579 struct inotify_device *dev = watch->dev; 297 struct inotify_handle *ih= watch->ih;
580 get_inotify_watch(watch); 298 mutex_lock(&ih->mutex);
581 mutex_lock(&dev->mutex);
582 inotify_dev_queue_event(dev, watch, mask, cookie, name);
583 if (watch_mask & IN_ONESHOT) 299 if (watch_mask & IN_ONESHOT)
584 remove_watch_no_event(watch, dev); 300 remove_watch_no_event(watch, ih);
585 mutex_unlock(&dev->mutex); 301 ih->in_ops->handle_event(watch, watch->wd, mask, cookie,
586 put_inotify_watch(watch); 302 name, n_inode);
303 mutex_unlock(&ih->mutex);
587 } 304 }
588 } 305 }
589 mutex_unlock(&inode->inotify_mutex); 306 mutex_unlock(&inode->inotify_mutex);
@@ -613,7 +330,8 @@ void inotify_dentry_parent_queue_event(struct dentry *dentry, u32 mask,
613 if (inotify_inode_watched(inode)) { 330 if (inotify_inode_watched(inode)) {
614 dget(parent); 331 dget(parent);
615 spin_unlock(&dentry->d_lock); 332 spin_unlock(&dentry->d_lock);
616 inotify_inode_queue_event(inode, mask, cookie, name); 333 inotify_inode_queue_event(inode, mask, cookie, name,
334 dentry->d_inode);
617 dput(parent); 335 dput(parent);
618 } else 336 } else
619 spin_unlock(&dentry->d_lock); 337 spin_unlock(&dentry->d_lock);
@@ -665,7 +383,7 @@ void inotify_unmount_inodes(struct list_head *list)
665 383
666 need_iput_tmp = need_iput; 384 need_iput_tmp = need_iput;
667 need_iput = NULL; 385 need_iput = NULL;
668 /* In case the remove_watch() drops a reference. */ 386 /* In case inotify_remove_watch_locked() drops a reference. */
669 if (inode != need_iput_tmp) 387 if (inode != need_iput_tmp)
670 __iget(inode); 388 __iget(inode);
671 else 389 else
@@ -694,11 +412,12 @@ void inotify_unmount_inodes(struct list_head *list)
694 mutex_lock(&inode->inotify_mutex); 412 mutex_lock(&inode->inotify_mutex);
695 watches = &inode->inotify_watches; 413 watches = &inode->inotify_watches;
696 list_for_each_entry_safe(watch, next_w, watches, i_list) { 414 list_for_each_entry_safe(watch, next_w, watches, i_list) {
697 struct inotify_device *dev = watch->dev; 415 struct inotify_handle *ih= watch->ih;
698 mutex_lock(&dev->mutex); 416 mutex_lock(&ih->mutex);
699 inotify_dev_queue_event(dev, watch, IN_UNMOUNT,0,NULL); 417 ih->in_ops->handle_event(watch, watch->wd, IN_UNMOUNT, 0,
700 remove_watch(watch, dev); 418 NULL, NULL);
701 mutex_unlock(&dev->mutex); 419 inotify_remove_watch_locked(ih, watch);
420 mutex_unlock(&ih->mutex);
702 } 421 }
703 mutex_unlock(&inode->inotify_mutex); 422 mutex_unlock(&inode->inotify_mutex);
704 iput(inode); 423 iput(inode);
@@ -718,432 +437,292 @@ void inotify_inode_is_dead(struct inode *inode)
718 437
719 mutex_lock(&inode->inotify_mutex); 438 mutex_lock(&inode->inotify_mutex);
720 list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) { 439 list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) {
721 struct inotify_device *dev = watch->dev; 440 struct inotify_handle *ih = watch->ih;
722 mutex_lock(&dev->mutex); 441 mutex_lock(&ih->mutex);
723 remove_watch(watch, dev); 442 inotify_remove_watch_locked(ih, watch);
724 mutex_unlock(&dev->mutex); 443 mutex_unlock(&ih->mutex);
725 } 444 }
726 mutex_unlock(&inode->inotify_mutex); 445 mutex_unlock(&inode->inotify_mutex);
727} 446}
728EXPORT_SYMBOL_GPL(inotify_inode_is_dead); 447EXPORT_SYMBOL_GPL(inotify_inode_is_dead);
729 448
730/* Device Interface */ 449/* Kernel Consumer API */
731 450
732static unsigned int inotify_poll(struct file *file, poll_table *wait) 451/**
452 * inotify_init - allocate and initialize an inotify instance
453 * @ops: caller's inotify operations
454 */
455struct inotify_handle *inotify_init(const struct inotify_operations *ops)
733{ 456{
734 struct inotify_device *dev = file->private_data; 457 struct inotify_handle *ih;
735 int ret = 0;
736 458
737 poll_wait(file, &dev->wq, wait); 459 ih = kmalloc(sizeof(struct inotify_handle), GFP_KERNEL);
738 mutex_lock(&dev->mutex); 460 if (unlikely(!ih))
739 if (!list_empty(&dev->events)) 461 return ERR_PTR(-ENOMEM);
740 ret = POLLIN | POLLRDNORM;
741 mutex_unlock(&dev->mutex);
742 462
743 return ret; 463 idr_init(&ih->idr);
464 INIT_LIST_HEAD(&ih->watches);
465 mutex_init(&ih->mutex);
466 ih->last_wd = 0;
467 ih->in_ops = ops;
468 atomic_set(&ih->count, 0);
469 get_inotify_handle(ih);
470
471 return ih;
744} 472}
473EXPORT_SYMBOL_GPL(inotify_init);
745 474
746static ssize_t inotify_read(struct file *file, char __user *buf, 475/**
747 size_t count, loff_t *pos) 476 * inotify_init_watch - initialize an inotify watch
477 * @watch: watch to initialize
478 */
479void inotify_init_watch(struct inotify_watch *watch)
748{ 480{
749 size_t event_size = sizeof (struct inotify_event); 481 INIT_LIST_HEAD(&watch->h_list);
750 struct inotify_device *dev; 482 INIT_LIST_HEAD(&watch->i_list);
751 char __user *start; 483 atomic_set(&watch->count, 0);
752 int ret; 484 get_inotify_watch(watch); /* initial get */
753 DEFINE_WAIT(wait);
754
755 start = buf;
756 dev = file->private_data;
757
758 while (1) {
759 int events;
760
761 prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE);
762
763 mutex_lock(&dev->mutex);
764 events = !list_empty(&dev->events);
765 mutex_unlock(&dev->mutex);
766 if (events) {
767 ret = 0;
768 break;
769 }
770
771 if (file->f_flags & O_NONBLOCK) {
772 ret = -EAGAIN;
773 break;
774 }
775
776 if (signal_pending(current)) {
777 ret = -EINTR;
778 break;
779 }
780
781 schedule();
782 }
783
784 finish_wait(&dev->wq, &wait);
785 if (ret)
786 return ret;
787
788 mutex_lock(&dev->mutex);
789 while (1) {
790 struct inotify_kernel_event *kevent;
791
792 ret = buf - start;
793 if (list_empty(&dev->events))
794 break;
795
796 kevent = inotify_dev_get_event(dev);
797 if (event_size + kevent->event.len > count)
798 break;
799
800 if (copy_to_user(buf, &kevent->event, event_size)) {
801 ret = -EFAULT;
802 break;
803 }
804 buf += event_size;
805 count -= event_size;
806
807 if (kevent->name) {
808 if (copy_to_user(buf, kevent->name, kevent->event.len)){
809 ret = -EFAULT;
810 break;
811 }
812 buf += kevent->event.len;
813 count -= kevent->event.len;
814 }
815
816 remove_kevent(dev, kevent);
817 }
818 mutex_unlock(&dev->mutex);
819
820 return ret;
821} 485}
486EXPORT_SYMBOL_GPL(inotify_init_watch);
822 487
823static int inotify_release(struct inode *ignored, struct file *file) 488/**
489 * inotify_destroy - clean up and destroy an inotify instance
490 * @ih: inotify handle
491 */
492void inotify_destroy(struct inotify_handle *ih)
824{ 493{
825 struct inotify_device *dev = file->private_data;
826
827 /* 494 /*
828 * Destroy all of the watches on this device. Unfortunately, not very 495 * Destroy all of the watches for this handle. Unfortunately, not very
829 * pretty. We cannot do a simple iteration over the list, because we 496 * pretty. We cannot do a simple iteration over the list, because we
830 * do not know the inode until we iterate to the watch. But we need to 497 * do not know the inode until we iterate to the watch. But we need to
831 * hold inode->inotify_mutex before dev->mutex. The following works. 498 * hold inode->inotify_mutex before ih->mutex. The following works.
832 */ 499 */
833 while (1) { 500 while (1) {
834 struct inotify_watch *watch; 501 struct inotify_watch *watch;
835 struct list_head *watches; 502 struct list_head *watches;
836 struct inode *inode; 503 struct inode *inode;
837 504
838 mutex_lock(&dev->mutex); 505 mutex_lock(&ih->mutex);
839 watches = &dev->watches; 506 watches = &ih->watches;
840 if (list_empty(watches)) { 507 if (list_empty(watches)) {
841 mutex_unlock(&dev->mutex); 508 mutex_unlock(&ih->mutex);
842 break; 509 break;
843 } 510 }
844 watch = list_entry(watches->next, struct inotify_watch, d_list); 511 watch = list_entry(watches->next, struct inotify_watch, h_list);
845 get_inotify_watch(watch); 512 get_inotify_watch(watch);
846 mutex_unlock(&dev->mutex); 513 mutex_unlock(&ih->mutex);
847 514
848 inode = watch->inode; 515 inode = watch->inode;
849 mutex_lock(&inode->inotify_mutex); 516 mutex_lock(&inode->inotify_mutex);
850 mutex_lock(&dev->mutex); 517 mutex_lock(&ih->mutex);
851 518
852 /* make sure we didn't race with another list removal */ 519 /* make sure we didn't race with another list removal */
853 if (likely(idr_find(&dev->idr, watch->wd))) 520 if (likely(idr_find(&ih->idr, watch->wd))) {
854 remove_watch_no_event(watch, dev); 521 remove_watch_no_event(watch, ih);
522 put_inotify_watch(watch);
523 }
855 524
856 mutex_unlock(&dev->mutex); 525 mutex_unlock(&ih->mutex);
857 mutex_unlock(&inode->inotify_mutex); 526 mutex_unlock(&inode->inotify_mutex);
858 put_inotify_watch(watch); 527 put_inotify_watch(watch);
859 } 528 }
860 529
861 /* destroy all of the events on this device */ 530 /* free this handle: the put matching the get in inotify_init() */
862 mutex_lock(&dev->mutex); 531 put_inotify_handle(ih);
863 while (!list_empty(&dev->events))
864 inotify_dev_event_dequeue(dev);
865 mutex_unlock(&dev->mutex);
866
867 /* free this device: the put matching the get in inotify_init() */
868 put_inotify_dev(dev);
869
870 return 0;
871} 532}
533EXPORT_SYMBOL_GPL(inotify_destroy);
872 534
873/* 535/**
874 * inotify_ignore - remove a given wd from this inotify instance. 536 * inotify_find_watch - find an existing watch for an (ih,inode) pair
537 * @ih: inotify handle
538 * @inode: inode to watch
539 * @watchp: pointer to existing inotify_watch
875 * 540 *
876 * Can sleep. 541 * Caller must pin given inode (via nameidata).
877 */ 542 */
878static int inotify_ignore(struct inotify_device *dev, s32 wd) 543s32 inotify_find_watch(struct inotify_handle *ih, struct inode *inode,
544 struct inotify_watch **watchp)
879{ 545{
880 struct inotify_watch *watch; 546 struct inotify_watch *old;
881 struct inode *inode; 547 int ret = -ENOENT;
882
883 mutex_lock(&dev->mutex);
884 watch = idr_find(&dev->idr, wd);
885 if (unlikely(!watch)) {
886 mutex_unlock(&dev->mutex);
887 return -EINVAL;
888 }
889 get_inotify_watch(watch);
890 inode = watch->inode;
891 mutex_unlock(&dev->mutex);
892 548
893 mutex_lock(&inode->inotify_mutex); 549 mutex_lock(&inode->inotify_mutex);
894 mutex_lock(&dev->mutex); 550 mutex_lock(&ih->mutex);
895 551
896 /* make sure that we did not race */ 552 old = inode_find_handle(inode, ih);
897 if (likely(idr_find(&dev->idr, wd) == watch)) 553 if (unlikely(old)) {
898 remove_watch(watch, dev); 554 get_inotify_watch(old); /* caller must put watch */
555 *watchp = old;
556 ret = old->wd;
557 }
899 558
900 mutex_unlock(&dev->mutex); 559 mutex_unlock(&ih->mutex);
901 mutex_unlock(&inode->inotify_mutex); 560 mutex_unlock(&inode->inotify_mutex);
902 put_inotify_watch(watch);
903 561
904 return 0; 562 return ret;
905} 563}
564EXPORT_SYMBOL_GPL(inotify_find_watch);
906 565
907static long inotify_ioctl(struct file *file, unsigned int cmd, 566/**
908 unsigned long arg) 567 * inotify_find_update_watch - find and update the mask of an existing watch
568 * @ih: inotify handle
569 * @inode: inode's watch to update
570 * @mask: mask of events to watch
571 *
572 * Caller must pin given inode (via nameidata).
573 */
574s32 inotify_find_update_watch(struct inotify_handle *ih, struct inode *inode,
575 u32 mask)
909{ 576{
910 struct inotify_device *dev; 577 struct inotify_watch *old;
911 void __user *p; 578 int mask_add = 0;
912 int ret = -ENOTTY; 579 int ret;
913
914 dev = file->private_data;
915 p = (void __user *) arg;
916
917 switch (cmd) {
918 case FIONREAD:
919 ret = put_user(dev->queue_size, (int __user *) p);
920 break;
921 }
922
923 return ret;
924}
925 580
926static const struct file_operations inotify_fops = { 581 if (mask & IN_MASK_ADD)
927 .poll = inotify_poll, 582 mask_add = 1;
928 .read = inotify_read,
929 .release = inotify_release,
930 .unlocked_ioctl = inotify_ioctl,
931 .compat_ioctl = inotify_ioctl,
932};
933 583
934asmlinkage long sys_inotify_init(void) 584 /* don't allow invalid bits: we don't want flags set */
935{ 585 mask &= IN_ALL_EVENTS | IN_ONESHOT;
936 struct inotify_device *dev; 586 if (unlikely(!mask))
937 struct user_struct *user; 587 return -EINVAL;
938 struct file *filp;
939 int fd, ret;
940
941 fd = get_unused_fd();
942 if (fd < 0)
943 return fd;
944
945 filp = get_empty_filp();
946 if (!filp) {
947 ret = -ENFILE;
948 goto out_put_fd;
949 }
950 588
951 user = get_uid(current->user); 589 mutex_lock(&inode->inotify_mutex);
952 if (unlikely(atomic_read(&user->inotify_devs) >= 590 mutex_lock(&ih->mutex);
953 inotify_max_user_instances)) {
954 ret = -EMFILE;
955 goto out_free_uid;
956 }
957 591
958 dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL); 592 /*
959 if (unlikely(!dev)) { 593 * Handle the case of re-adding a watch on an (inode,ih) pair that we
960 ret = -ENOMEM; 594 * are already watching. We just update the mask and return its wd.
961 goto out_free_uid; 595 */
596 old = inode_find_handle(inode, ih);
597 if (unlikely(!old)) {
598 ret = -ENOENT;
599 goto out;
962 } 600 }
963 601
964 filp->f_op = &inotify_fops; 602 if (mask_add)
965 filp->f_vfsmnt = mntget(inotify_mnt); 603 old->mask |= mask;
966 filp->f_dentry = dget(inotify_mnt->mnt_root); 604 else
967 filp->f_mapping = filp->f_dentry->d_inode->i_mapping; 605 old->mask = mask;
968 filp->f_mode = FMODE_READ; 606 ret = old->wd;
969 filp->f_flags = O_RDONLY; 607out:
970 filp->private_data = dev; 608 mutex_unlock(&ih->mutex);
971 609 mutex_unlock(&inode->inotify_mutex);
972 idr_init(&dev->idr);
973 INIT_LIST_HEAD(&dev->events);
974 INIT_LIST_HEAD(&dev->watches);
975 init_waitqueue_head(&dev->wq);
976 mutex_init(&dev->mutex);
977 dev->event_count = 0;
978 dev->queue_size = 0;
979 dev->max_events = inotify_max_queued_events;
980 dev->user = user;
981 dev->last_wd = 0;
982 atomic_set(&dev->count, 0);
983
984 get_inotify_dev(dev);
985 atomic_inc(&user->inotify_devs);
986 fd_install(fd, filp);
987
988 return fd;
989out_free_uid:
990 free_uid(user);
991 put_filp(filp);
992out_put_fd:
993 put_unused_fd(fd);
994 return ret; 610 return ret;
995} 611}
612EXPORT_SYMBOL_GPL(inotify_find_update_watch);
996 613
997asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) 614/**
615 * inotify_add_watch - add a watch to an inotify instance
616 * @ih: inotify handle
617 * @watch: caller allocated watch structure
618 * @inode: inode to watch
619 * @mask: mask of events to watch
620 *
621 * Caller must pin given inode (via nameidata).
622 * Caller must ensure it only calls inotify_add_watch() once per watch.
623 * Calls inotify_handle_get_wd() so may sleep.
624 */
625s32 inotify_add_watch(struct inotify_handle *ih, struct inotify_watch *watch,
626 struct inode *inode, u32 mask)
998{ 627{
999 struct inotify_watch *watch, *old; 628 int ret = 0;
1000 struct inode *inode;
1001 struct inotify_device *dev;
1002 struct nameidata nd;
1003 struct file *filp;
1004 int ret, fput_needed;
1005 int mask_add = 0;
1006 unsigned flags = 0;
1007
1008 filp = fget_light(fd, &fput_needed);
1009 if (unlikely(!filp))
1010 return -EBADF;
1011
1012 /* verify that this is indeed an inotify instance */
1013 if (unlikely(filp->f_op != &inotify_fops)) {
1014 ret = -EINVAL;
1015 goto fput_and_out;
1016 }
1017
1018 if (!(mask & IN_DONT_FOLLOW))
1019 flags |= LOOKUP_FOLLOW;
1020 if (mask & IN_ONLYDIR)
1021 flags |= LOOKUP_DIRECTORY;
1022
1023 ret = find_inode(path, &nd, flags);
1024 if (unlikely(ret))
1025 goto fput_and_out;
1026 629
1027 /* inode held in place by reference to nd; dev by fget on fd */ 630 /* don't allow invalid bits: we don't want flags set */
1028 inode = nd.dentry->d_inode; 631 mask &= IN_ALL_EVENTS | IN_ONESHOT;
1029 dev = filp->private_data; 632 if (unlikely(!mask))
633 return -EINVAL;
634 watch->mask = mask;
1030 635
1031 mutex_lock(&inode->inotify_mutex); 636 mutex_lock(&inode->inotify_mutex);
1032 mutex_lock(&dev->mutex); 637 mutex_lock(&ih->mutex);
1033
1034 if (mask & IN_MASK_ADD)
1035 mask_add = 1;
1036 638
1037 /* don't let user-space set invalid bits: we don't want flags set */ 639 /* Initialize a new watch */
1038 mask &= IN_ALL_EVENTS | IN_ONESHOT; 640 ret = inotify_handle_get_wd(ih, watch);
1039 if (unlikely(!mask)) { 641 if (unlikely(ret))
1040 ret = -EINVAL;
1041 goto out; 642 goto out;
1042 } 643 ret = watch->wd;
644
645 /* save a reference to handle and bump the count to make it official */
646 get_inotify_handle(ih);
647 watch->ih = ih;
1043 648
1044 /* 649 /*
1045 * Handle the case of re-adding a watch on an (inode,dev) pair that we 650 * Save a reference to the inode and bump the ref count to make it
1046 * are already watching. We just update the mask and return its wd. 651 * official. We hold a reference to nameidata, which makes this safe.
1047 */ 652 */
1048 old = inode_find_dev(inode, dev); 653 watch->inode = igrab(inode);
1049 if (unlikely(old)) {
1050 if (mask_add)
1051 old->mask |= mask;
1052 else
1053 old->mask = mask;
1054 ret = old->wd;
1055 goto out;
1056 }
1057
1058 watch = create_watch(dev, mask, inode);
1059 if (unlikely(IS_ERR(watch))) {
1060 ret = PTR_ERR(watch);
1061 goto out;
1062 }
1063 654
1064 if (!inotify_inode_watched(inode)) 655 if (!inotify_inode_watched(inode))
1065 set_dentry_child_flags(inode, 1); 656 set_dentry_child_flags(inode, 1);
1066 657
1067 /* Add the watch to the device's and the inode's list */ 658 /* Add the watch to the handle's and the inode's list */
1068 list_add(&watch->d_list, &dev->watches); 659 list_add(&watch->h_list, &ih->watches);
1069 list_add(&watch->i_list, &inode->inotify_watches); 660 list_add(&watch->i_list, &inode->inotify_watches);
1070 ret = watch->wd;
1071out: 661out:
1072 mutex_unlock(&dev->mutex); 662 mutex_unlock(&ih->mutex);
1073 mutex_unlock(&inode->inotify_mutex); 663 mutex_unlock(&inode->inotify_mutex);
1074 path_release(&nd);
1075fput_and_out:
1076 fput_light(filp, fput_needed);
1077 return ret; 664 return ret;
1078} 665}
666EXPORT_SYMBOL_GPL(inotify_add_watch);
1079 667
1080asmlinkage long sys_inotify_rm_watch(int fd, u32 wd) 668/**
669 * inotify_rm_wd - remove a watch from an inotify instance
670 * @ih: inotify handle
671 * @wd: watch descriptor to remove
672 *
673 * Can sleep.
674 */
675int inotify_rm_wd(struct inotify_handle *ih, u32 wd)
1081{ 676{
1082 struct file *filp; 677 struct inotify_watch *watch;
1083 struct inotify_device *dev; 678 struct inode *inode;
1084 int ret, fput_needed;
1085
1086 filp = fget_light(fd, &fput_needed);
1087 if (unlikely(!filp))
1088 return -EBADF;
1089 679
1090 /* verify that this is indeed an inotify instance */ 680 mutex_lock(&ih->mutex);
1091 if (unlikely(filp->f_op != &inotify_fops)) { 681 watch = idr_find(&ih->idr, wd);
1092 ret = -EINVAL; 682 if (unlikely(!watch)) {
1093 goto out; 683 mutex_unlock(&ih->mutex);
684 return -EINVAL;
1094 } 685 }
686 get_inotify_watch(watch);
687 inode = watch->inode;
688 mutex_unlock(&ih->mutex);
1095 689
1096 dev = filp->private_data; 690 mutex_lock(&inode->inotify_mutex);
1097 ret = inotify_ignore(dev, wd); 691 mutex_lock(&ih->mutex);
1098 692
1099out: 693 /* make sure that we did not race */
1100 fput_light(filp, fput_needed); 694 if (likely(idr_find(&ih->idr, wd) == watch))
1101 return ret; 695 inotify_remove_watch_locked(ih, watch);
696
697 mutex_unlock(&ih->mutex);
698 mutex_unlock(&inode->inotify_mutex);
699 put_inotify_watch(watch);
700
701 return 0;
1102} 702}
703EXPORT_SYMBOL_GPL(inotify_rm_wd);
1103 704
1104static struct super_block * 705/**
1105inotify_get_sb(struct file_system_type *fs_type, int flags, 706 * inotify_rm_watch - remove a watch from an inotify instance
1106 const char *dev_name, void *data) 707 * @ih: inotify handle
708 * @watch: watch to remove
709 *
710 * Can sleep.
711 */
712int inotify_rm_watch(struct inotify_handle *ih,
713 struct inotify_watch *watch)
1107{ 714{
1108 return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA); 715 return inotify_rm_wd(ih, watch->wd);
1109} 716}
1110 717EXPORT_SYMBOL_GPL(inotify_rm_watch);
1111static struct file_system_type inotify_fs_type = {
1112 .name = "inotifyfs",
1113 .get_sb = inotify_get_sb,
1114 .kill_sb = kill_anon_super,
1115};
1116 718
1117/* 719/*
1118 * inotify_setup - Our initialization function. Note that we cannnot return 720 * inotify_setup - core initialization function
1119 * error because we have compiled-in VFS hooks. So an (unlikely) failure here
1120 * must result in panic().
1121 */ 721 */
1122static int __init inotify_setup(void) 722static int __init inotify_setup(void)
1123{ 723{
1124 int ret;
1125
1126 ret = register_filesystem(&inotify_fs_type);
1127 if (unlikely(ret))
1128 panic("inotify: register_filesystem returned %d!\n", ret);
1129
1130 inotify_mnt = kern_mount(&inotify_fs_type);
1131 if (IS_ERR(inotify_mnt))
1132 panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt));
1133
1134 inotify_max_queued_events = 16384;
1135 inotify_max_user_instances = 128;
1136 inotify_max_user_watches = 8192;
1137
1138 atomic_set(&inotify_cookie, 0); 724 atomic_set(&inotify_cookie, 0);
1139 725
1140 watch_cachep = kmem_cache_create("inotify_watch_cache",
1141 sizeof(struct inotify_watch),
1142 0, SLAB_PANIC, NULL, NULL);
1143 event_cachep = kmem_cache_create("inotify_event_cache",
1144 sizeof(struct inotify_kernel_event),
1145 0, SLAB_PANIC, NULL, NULL);
1146
1147 return 0; 726 return 0;
1148} 727}
1149 728
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
new file mode 100644
index 000000000000..f2386442adee
--- /dev/null
+++ b/fs/inotify_user.c
@@ -0,0 +1,719 @@
1/*
2 * fs/inotify_user.c - inotify support for userspace
3 *
4 * Authors:
5 * John McCutchan <ttb@tentacle.dhs.org>
6 * Robert Love <rml@novell.com>
7 *
8 * Copyright (C) 2005 John McCutchan
9 * Copyright 2006 Hewlett-Packard Development Company, L.P.
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2, or (at your option) any
14 * later version.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 */
21
22#include <linux/kernel.h>
23#include <linux/sched.h>
24#include <linux/slab.h>
25#include <linux/fs.h>
26#include <linux/file.h>
27#include <linux/mount.h>
28#include <linux/namei.h>
29#include <linux/poll.h>
30#include <linux/init.h>
31#include <linux/list.h>
32#include <linux/inotify.h>
33#include <linux/syscalls.h>
34
35#include <asm/ioctls.h>
36
37static kmem_cache_t *watch_cachep __read_mostly;
38static kmem_cache_t *event_cachep __read_mostly;
39
40static struct vfsmount *inotify_mnt __read_mostly;
41
42/* these are configurable via /proc/sys/fs/inotify/ */
43int inotify_max_user_instances __read_mostly;
44int inotify_max_user_watches __read_mostly;
45int inotify_max_queued_events __read_mostly;
46
47/*
48 * Lock ordering:
49 *
50 * inotify_dev->up_mutex (ensures we don't re-add the same watch)
51 * inode->inotify_mutex (protects inode's watch list)
52 * inotify_handle->mutex (protects inotify_handle's watch list)
53 * inotify_dev->ev_mutex (protects device's event queue)
54 */
55
56/*
57 * Lifetimes of the main data structures:
58 *
59 * inotify_device: Lifetime is managed by reference count, from
60 * sys_inotify_init() until release. Additional references can bump the count
61 * via get_inotify_dev() and drop the count via put_inotify_dev().
62 *
63 * inotify_user_watch: Lifetime is from create_watch() to the receipt of an
64 * IN_IGNORED event from inotify, or when using IN_ONESHOT, to receipt of the
65 * first event, or to inotify_destroy().
66 */
67
68/*
69 * struct inotify_device - represents an inotify instance
70 *
71 * This structure is protected by the mutex 'mutex'.
72 */
73struct inotify_device {
74 wait_queue_head_t wq; /* wait queue for i/o */
75 struct mutex ev_mutex; /* protects event queue */
76 struct mutex up_mutex; /* synchronizes watch updates */
77 struct list_head events; /* list of queued events */
78 atomic_t count; /* reference count */
79 struct user_struct *user; /* user who opened this dev */
80 struct inotify_handle *ih; /* inotify handle */
81 unsigned int queue_size; /* size of the queue (bytes) */
82 unsigned int event_count; /* number of pending events */
83 unsigned int max_events; /* maximum number of events */
84};
85
86/*
87 * struct inotify_kernel_event - An inotify event, originating from a watch and
88 * queued for user-space. A list of these is attached to each instance of the
89 * device. In read(), this list is walked and all events that can fit in the
90 * buffer are returned.
91 *
92 * Protected by dev->ev_mutex of the device in which we are queued.
93 */
94struct inotify_kernel_event {
95 struct inotify_event event; /* the user-space event */
96 struct list_head list; /* entry in inotify_device's list */
97 char *name; /* filename, if any */
98};
99
100/*
101 * struct inotify_user_watch - our version of an inotify_watch, we add
102 * a reference to the associated inotify_device.
103 */
104struct inotify_user_watch {
105 struct inotify_device *dev; /* associated device */
106 struct inotify_watch wdata; /* inotify watch data */
107};
108
109#ifdef CONFIG_SYSCTL
110
111#include <linux/sysctl.h>
112
113static int zero;
114
115ctl_table inotify_table[] = {
116 {
117 .ctl_name = INOTIFY_MAX_USER_INSTANCES,
118 .procname = "max_user_instances",
119 .data = &inotify_max_user_instances,
120 .maxlen = sizeof(int),
121 .mode = 0644,
122 .proc_handler = &proc_dointvec_minmax,
123 .strategy = &sysctl_intvec,
124 .extra1 = &zero,
125 },
126 {
127 .ctl_name = INOTIFY_MAX_USER_WATCHES,
128 .procname = "max_user_watches",
129 .data = &inotify_max_user_watches,
130 .maxlen = sizeof(int),
131 .mode = 0644,
132 .proc_handler = &proc_dointvec_minmax,
133 .strategy = &sysctl_intvec,
134 .extra1 = &zero,
135 },
136 {
137 .ctl_name = INOTIFY_MAX_QUEUED_EVENTS,
138 .procname = "max_queued_events",
139 .data = &inotify_max_queued_events,
140 .maxlen = sizeof(int),
141 .mode = 0644,
142 .proc_handler = &proc_dointvec_minmax,
143 .strategy = &sysctl_intvec,
144 .extra1 = &zero
145 },
146 { .ctl_name = 0 }
147};
148#endif /* CONFIG_SYSCTL */
149
150static inline void get_inotify_dev(struct inotify_device *dev)
151{
152 atomic_inc(&dev->count);
153}
154
155static inline void put_inotify_dev(struct inotify_device *dev)
156{
157 if (atomic_dec_and_test(&dev->count)) {
158 atomic_dec(&dev->user->inotify_devs);
159 free_uid(dev->user);
160 kfree(dev);
161 }
162}
163
164/*
165 * free_inotify_user_watch - cleans up the watch and its references
166 */
167static void free_inotify_user_watch(struct inotify_watch *w)
168{
169 struct inotify_user_watch *watch;
170 struct inotify_device *dev;
171
172 watch = container_of(w, struct inotify_user_watch, wdata);
173 dev = watch->dev;
174
175 atomic_dec(&dev->user->inotify_watches);
176 put_inotify_dev(dev);
177 kmem_cache_free(watch_cachep, watch);
178}
179
180/*
181 * kernel_event - create a new kernel event with the given parameters
182 *
183 * This function can sleep.
184 */
185static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie,
186 const char *name)
187{
188 struct inotify_kernel_event *kevent;
189
190 kevent = kmem_cache_alloc(event_cachep, GFP_KERNEL);
191 if (unlikely(!kevent))
192 return NULL;
193
194 /* we hand this out to user-space, so zero it just in case */
195 memset(&kevent->event, 0, sizeof(struct inotify_event));
196
197 kevent->event.wd = wd;
198 kevent->event.mask = mask;
199 kevent->event.cookie = cookie;
200
201 INIT_LIST_HEAD(&kevent->list);
202
203 if (name) {
204 size_t len, rem, event_size = sizeof(struct inotify_event);
205
206 /*
207 * We need to pad the filename so as to properly align an
208 * array of inotify_event structures. Because the structure is
209 * small and the common case is a small filename, we just round
210 * up to the next multiple of the structure's sizeof. This is
211 * simple and safe for all architectures.
212 */
213 len = strlen(name) + 1;
214 rem = event_size - len;
215 if (len > event_size) {
216 rem = event_size - (len % event_size);
217 if (len % event_size == 0)
218 rem = 0;
219 }
220
221 kevent->name = kmalloc(len + rem, GFP_KERNEL);
222 if (unlikely(!kevent->name)) {
223 kmem_cache_free(event_cachep, kevent);
224 return NULL;
225 }
226 memcpy(kevent->name, name, len);
227 if (rem)
228 memset(kevent->name + len, 0, rem);
229 kevent->event.len = len + rem;
230 } else {
231 kevent->event.len = 0;
232 kevent->name = NULL;
233 }
234
235 return kevent;
236}
237
238/*
239 * inotify_dev_get_event - return the next event in the given dev's queue
240 *
241 * Caller must hold dev->ev_mutex.
242 */
243static inline struct inotify_kernel_event *
244inotify_dev_get_event(struct inotify_device *dev)
245{
246 return list_entry(dev->events.next, struct inotify_kernel_event, list);
247}
248
249/*
250 * inotify_dev_queue_event - event handler registered with core inotify, adds
251 * a new event to the given device
252 *
253 * Can sleep (calls kernel_event()).
254 */
255static void inotify_dev_queue_event(struct inotify_watch *w, u32 wd, u32 mask,
256 u32 cookie, const char *name,
257 struct inode *ignored)
258{
259 struct inotify_user_watch *watch;
260 struct inotify_device *dev;
261 struct inotify_kernel_event *kevent, *last;
262
263 watch = container_of(w, struct inotify_user_watch, wdata);
264 dev = watch->dev;
265
266 mutex_lock(&dev->ev_mutex);
267
268 /* we can safely put the watch as we don't reference it while
269 * generating the event
270 */
271 if (mask & IN_IGNORED || mask & IN_ONESHOT)
272 put_inotify_watch(w); /* final put */
273
274 /* coalescing: drop this event if it is a dupe of the previous */
275 last = inotify_dev_get_event(dev);
276 if (last && last->event.mask == mask && last->event.wd == wd &&
277 last->event.cookie == cookie) {
278 const char *lastname = last->name;
279
280 if (!name && !lastname)
281 goto out;
282 if (name && lastname && !strcmp(lastname, name))
283 goto out;
284 }
285
286 /* the queue overflowed and we already sent the Q_OVERFLOW event */
287 if (unlikely(dev->event_count > dev->max_events))
288 goto out;
289
290 /* if the queue overflows, we need to notify user space */
291 if (unlikely(dev->event_count == dev->max_events))
292 kevent = kernel_event(-1, IN_Q_OVERFLOW, cookie, NULL);
293 else
294 kevent = kernel_event(wd, mask, cookie, name);
295
296 if (unlikely(!kevent))
297 goto out;
298
299 /* queue the event and wake up anyone waiting */
300 dev->event_count++;
301 dev->queue_size += sizeof(struct inotify_event) + kevent->event.len;
302 list_add_tail(&kevent->list, &dev->events);
303 wake_up_interruptible(&dev->wq);
304
305out:
306 mutex_unlock(&dev->ev_mutex);
307}
308
309/*
310 * remove_kevent - cleans up and ultimately frees the given kevent
311 *
312 * Caller must hold dev->ev_mutex.
313 */
314static void remove_kevent(struct inotify_device *dev,
315 struct inotify_kernel_event *kevent)
316{
317 list_del(&kevent->list);
318
319 dev->event_count--;
320 dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len;
321
322 kfree(kevent->name);
323 kmem_cache_free(event_cachep, kevent);
324}
325
326/*
327 * inotify_dev_event_dequeue - destroy an event on the given device
328 *
329 * Caller must hold dev->ev_mutex.
330 */
331static void inotify_dev_event_dequeue(struct inotify_device *dev)
332{
333 if (!list_empty(&dev->events)) {
334 struct inotify_kernel_event *kevent;
335 kevent = inotify_dev_get_event(dev);
336 remove_kevent(dev, kevent);
337 }
338}
339
340/*
341 * find_inode - resolve a user-given path to a specific inode and return a nd
342 */
343static int find_inode(const char __user *dirname, struct nameidata *nd,
344 unsigned flags)
345{
346 int error;
347
348 error = __user_walk(dirname, flags, nd);
349 if (error)
350 return error;
351 /* you can only watch an inode if you have read permissions on it */
352 error = vfs_permission(nd, MAY_READ);
353 if (error)
354 path_release(nd);
355 return error;
356}
357
358/*
359 * create_watch - creates a watch on the given device.
360 *
361 * Callers must hold dev->up_mutex.
362 */
363static int create_watch(struct inotify_device *dev, struct inode *inode,
364 u32 mask)
365{
366 struct inotify_user_watch *watch;
367 int ret;
368
369 if (atomic_read(&dev->user->inotify_watches) >=
370 inotify_max_user_watches)
371 return -ENOSPC;
372
373 watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL);
374 if (unlikely(!watch))
375 return -ENOMEM;
376
377 /* save a reference to device and bump the count to make it official */
378 get_inotify_dev(dev);
379 watch->dev = dev;
380
381 atomic_inc(&dev->user->inotify_watches);
382
383 inotify_init_watch(&watch->wdata);
384 ret = inotify_add_watch(dev->ih, &watch->wdata, inode, mask);
385 if (ret < 0)
386 free_inotify_user_watch(&watch->wdata);
387
388 return ret;
389}
390
391/* Device Interface */
392
393static unsigned int inotify_poll(struct file *file, poll_table *wait)
394{
395 struct inotify_device *dev = file->private_data;
396 int ret = 0;
397
398 poll_wait(file, &dev->wq, wait);
399 mutex_lock(&dev->ev_mutex);
400 if (!list_empty(&dev->events))
401 ret = POLLIN | POLLRDNORM;
402 mutex_unlock(&dev->ev_mutex);
403
404 return ret;
405}
406
407static ssize_t inotify_read(struct file *file, char __user *buf,
408 size_t count, loff_t *pos)
409{
410 size_t event_size = sizeof (struct inotify_event);
411 struct inotify_device *dev;
412 char __user *start;
413 int ret;
414 DEFINE_WAIT(wait);
415
416 start = buf;
417 dev = file->private_data;
418
419 while (1) {
420 int events;
421
422 prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE);
423
424 mutex_lock(&dev->ev_mutex);
425 events = !list_empty(&dev->events);
426 mutex_unlock(&dev->ev_mutex);
427 if (events) {
428 ret = 0;
429 break;
430 }
431
432 if (file->f_flags & O_NONBLOCK) {
433 ret = -EAGAIN;
434 break;
435 }
436
437 if (signal_pending(current)) {
438 ret = -EINTR;
439 break;
440 }
441
442 schedule();
443 }
444
445 finish_wait(&dev->wq, &wait);
446 if (ret)
447 return ret;
448
449 mutex_lock(&dev->ev_mutex);
450 while (1) {
451 struct inotify_kernel_event *kevent;
452
453 ret = buf - start;
454 if (list_empty(&dev->events))
455 break;
456
457 kevent = inotify_dev_get_event(dev);
458 if (event_size + kevent->event.len > count)
459 break;
460
461 if (copy_to_user(buf, &kevent->event, event_size)) {
462 ret = -EFAULT;
463 break;
464 }
465 buf += event_size;
466 count -= event_size;
467
468 if (kevent->name) {
469 if (copy_to_user(buf, kevent->name, kevent->event.len)){
470 ret = -EFAULT;
471 break;
472 }
473 buf += kevent->event.len;
474 count -= kevent->event.len;
475 }
476
477 remove_kevent(dev, kevent);
478 }
479 mutex_unlock(&dev->ev_mutex);
480
481 return ret;
482}
483
484static int inotify_release(struct inode *ignored, struct file *file)
485{
486 struct inotify_device *dev = file->private_data;
487
488 inotify_destroy(dev->ih);
489
490 /* destroy all of the events on this device */
491 mutex_lock(&dev->ev_mutex);
492 while (!list_empty(&dev->events))
493 inotify_dev_event_dequeue(dev);
494 mutex_unlock(&dev->ev_mutex);
495
496 /* free this device: the put matching the get in inotify_init() */
497 put_inotify_dev(dev);
498
499 return 0;
500}
501
502static long inotify_ioctl(struct file *file, unsigned int cmd,
503 unsigned long arg)
504{
505 struct inotify_device *dev;
506 void __user *p;
507 int ret = -ENOTTY;
508
509 dev = file->private_data;
510 p = (void __user *) arg;
511
512 switch (cmd) {
513 case FIONREAD:
514 ret = put_user(dev->queue_size, (int __user *) p);
515 break;
516 }
517
518 return ret;
519}
520
521static const struct file_operations inotify_fops = {
522 .poll = inotify_poll,
523 .read = inotify_read,
524 .release = inotify_release,
525 .unlocked_ioctl = inotify_ioctl,
526 .compat_ioctl = inotify_ioctl,
527};
528
529static const struct inotify_operations inotify_user_ops = {
530 .handle_event = inotify_dev_queue_event,
531 .destroy_watch = free_inotify_user_watch,
532};
533
534asmlinkage long sys_inotify_init(void)
535{
536 struct inotify_device *dev;
537 struct inotify_handle *ih;
538 struct user_struct *user;
539 struct file *filp;
540 int fd, ret;
541
542 fd = get_unused_fd();
543 if (fd < 0)
544 return fd;
545
546 filp = get_empty_filp();
547 if (!filp) {
548 ret = -ENFILE;
549 goto out_put_fd;
550 }
551
552 user = get_uid(current->user);
553 if (unlikely(atomic_read(&user->inotify_devs) >=
554 inotify_max_user_instances)) {
555 ret = -EMFILE;
556 goto out_free_uid;
557 }
558
559 dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL);
560 if (unlikely(!dev)) {
561 ret = -ENOMEM;
562 goto out_free_uid;
563 }
564
565 ih = inotify_init(&inotify_user_ops);
566 if (unlikely(IS_ERR(ih))) {
567 ret = PTR_ERR(ih);
568 goto out_free_dev;
569 }
570 dev->ih = ih;
571
572 filp->f_op = &inotify_fops;
573 filp->f_vfsmnt = mntget(inotify_mnt);
574 filp->f_dentry = dget(inotify_mnt->mnt_root);
575 filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
576 filp->f_mode = FMODE_READ;
577 filp->f_flags = O_RDONLY;
578 filp->private_data = dev;
579
580 INIT_LIST_HEAD(&dev->events);
581 init_waitqueue_head(&dev->wq);
582 mutex_init(&dev->ev_mutex);
583 mutex_init(&dev->up_mutex);
584 dev->event_count = 0;
585 dev->queue_size = 0;
586 dev->max_events = inotify_max_queued_events;
587 dev->user = user;
588 atomic_set(&dev->count, 0);
589
590 get_inotify_dev(dev);
591 atomic_inc(&user->inotify_devs);
592 fd_install(fd, filp);
593
594 return fd;
595out_free_dev:
596 kfree(dev);
597out_free_uid:
598 free_uid(user);
599 put_filp(filp);
600out_put_fd:
601 put_unused_fd(fd);
602 return ret;
603}
604
605asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
606{
607 struct inode *inode;
608 struct inotify_device *dev;
609 struct nameidata nd;
610 struct file *filp;
611 int ret, fput_needed;
612 unsigned flags = 0;
613
614 filp = fget_light(fd, &fput_needed);
615 if (unlikely(!filp))
616 return -EBADF;
617
618 /* verify that this is indeed an inotify instance */
619 if (unlikely(filp->f_op != &inotify_fops)) {
620 ret = -EINVAL;
621 goto fput_and_out;
622 }
623
624 if (!(mask & IN_DONT_FOLLOW))
625 flags |= LOOKUP_FOLLOW;
626 if (mask & IN_ONLYDIR)
627 flags |= LOOKUP_DIRECTORY;
628
629 ret = find_inode(path, &nd, flags);
630 if (unlikely(ret))
631 goto fput_and_out;
632
633 /* inode held in place by reference to nd; dev by fget on fd */
634 inode = nd.dentry->d_inode;
635 dev = filp->private_data;
636
637 mutex_lock(&dev->up_mutex);
638 ret = inotify_find_update_watch(dev->ih, inode, mask);
639 if (ret == -ENOENT)
640 ret = create_watch(dev, inode, mask);
641 mutex_unlock(&dev->up_mutex);
642
643 path_release(&nd);
644fput_and_out:
645 fput_light(filp, fput_needed);
646 return ret;
647}
648
649asmlinkage long sys_inotify_rm_watch(int fd, u32 wd)
650{
651 struct file *filp;
652 struct inotify_device *dev;
653 int ret, fput_needed;
654
655 filp = fget_light(fd, &fput_needed);
656 if (unlikely(!filp))
657 return -EBADF;
658
659 /* verify that this is indeed an inotify instance */
660 if (unlikely(filp->f_op != &inotify_fops)) {
661 ret = -EINVAL;
662 goto out;
663 }
664
665 dev = filp->private_data;
666
667 /* we free our watch data when we get IN_IGNORED */
668 ret = inotify_rm_wd(dev->ih, wd);
669
670out:
671 fput_light(filp, fput_needed);
672 return ret;
673}
674
675static int
676inotify_get_sb(struct file_system_type *fs_type, int flags,
677 const char *dev_name, void *data, struct vfsmount *mnt)
678{
679 return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA, mnt);
680}
681
682static struct file_system_type inotify_fs_type = {
683 .name = "inotifyfs",
684 .get_sb = inotify_get_sb,
685 .kill_sb = kill_anon_super,
686};
687
688/*
689 * inotify_user_setup - Our initialization function. Note that we cannnot return
690 * error because we have compiled-in VFS hooks. So an (unlikely) failure here
691 * must result in panic().
692 */
693static int __init inotify_user_setup(void)
694{
695 int ret;
696
697 ret = register_filesystem(&inotify_fs_type);
698 if (unlikely(ret))
699 panic("inotify: register_filesystem returned %d!\n", ret);
700
701 inotify_mnt = kern_mount(&inotify_fs_type);
702 if (IS_ERR(inotify_mnt))
703 panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt));
704
705 inotify_max_queued_events = 16384;
706 inotify_max_user_instances = 128;
707 inotify_max_user_watches = 8192;
708
709 watch_cachep = kmem_cache_create("inotify_watch_cache",
710 sizeof(struct inotify_user_watch),
711 0, SLAB_PANIC, NULL, NULL);
712 event_cachep = kmem_cache_create("inotify_event_cache",
713 sizeof(struct inotify_kernel_event),
714 0, SLAB_PANIC, NULL, NULL);
715
716 return 0;
717}
718
719module_init(inotify_user_setup);
diff --git a/fs/ioprio.c b/fs/ioprio.c
index ca77008146c0..7fa76ed53c10 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -24,15 +24,21 @@
24#include <linux/blkdev.h> 24#include <linux/blkdev.h>
25#include <linux/capability.h> 25#include <linux/capability.h>
26#include <linux/syscalls.h> 26#include <linux/syscalls.h>
27#include <linux/security.h>
27 28
28static int set_task_ioprio(struct task_struct *task, int ioprio) 29static int set_task_ioprio(struct task_struct *task, int ioprio)
29{ 30{
31 int err;
30 struct io_context *ioc; 32 struct io_context *ioc;
31 33
32 if (task->uid != current->euid && 34 if (task->uid != current->euid &&
33 task->uid != current->uid && !capable(CAP_SYS_NICE)) 35 task->uid != current->uid && !capable(CAP_SYS_NICE))
34 return -EPERM; 36 return -EPERM;
35 37
38 err = security_task_setioprio(task, ioprio);
39 if (err)
40 return err;
41
36 task_lock(task); 42 task_lock(task);
37 43
38 task->ioprio = ioprio; 44 task->ioprio = ioprio;
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 70adbb98bad1..3f9c8ba1fa1f 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -56,7 +56,7 @@ static void isofs_put_super(struct super_block *sb)
56} 56}
57 57
58static void isofs_read_inode(struct inode *); 58static void isofs_read_inode(struct inode *);
59static int isofs_statfs (struct super_block *, struct kstatfs *); 59static int isofs_statfs (struct dentry *, struct kstatfs *);
60 60
61static kmem_cache_t *isofs_inode_cachep; 61static kmem_cache_t *isofs_inode_cachep;
62 62
@@ -901,8 +901,10 @@ out_freesbi:
901 return -EINVAL; 901 return -EINVAL;
902} 902}
903 903
904static int isofs_statfs (struct super_block *sb, struct kstatfs *buf) 904static int isofs_statfs (struct dentry *dentry, struct kstatfs *buf)
905{ 905{
906 struct super_block *sb = dentry->d_sb;
907
906 buf->f_type = ISOFS_SUPER_MAGIC; 908 buf->f_type = ISOFS_SUPER_MAGIC;
907 buf->f_bsize = sb->s_blocksize; 909 buf->f_bsize = sb->s_blocksize;
908 buf->f_blocks = (ISOFS_SB(sb)->s_nzones 910 buf->f_blocks = (ISOFS_SB(sb)->s_nzones
@@ -1399,10 +1401,11 @@ struct inode *isofs_iget(struct super_block *sb,
1399 return inode; 1401 return inode;
1400} 1402}
1401 1403
1402static struct super_block *isofs_get_sb(struct file_system_type *fs_type, 1404static int isofs_get_sb(struct file_system_type *fs_type,
1403 int flags, const char *dev_name, void *data) 1405 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
1404{ 1406{
1405 return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super); 1407 return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super,
1408 mnt);
1406} 1409}
1407 1410
1408static struct file_system_type iso9660_fs_type = { 1411static struct file_system_type iso9660_fs_type = {
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
index 3f5102b069db..47678a26c13b 100644
--- a/fs/jbd/checkpoint.c
+++ b/fs/jbd/checkpoint.c
@@ -24,29 +24,67 @@
24#include <linux/slab.h> 24#include <linux/slab.h>
25 25
26/* 26/*
27 * Unlink a buffer from a transaction. 27 * Unlink a buffer from a transaction checkpoint list.
28 * 28 *
29 * Called with j_list_lock held. 29 * Called with j_list_lock held.
30 */ 30 */
31 31static inline void __buffer_unlink_first(struct journal_head *jh)
32static inline void __buffer_unlink(struct journal_head *jh)
33{ 32{
34 transaction_t *transaction; 33 transaction_t *transaction = jh->b_cp_transaction;
35
36 transaction = jh->b_cp_transaction;
37 jh->b_cp_transaction = NULL;
38 34
39 jh->b_cpnext->b_cpprev = jh->b_cpprev; 35 jh->b_cpnext->b_cpprev = jh->b_cpprev;
40 jh->b_cpprev->b_cpnext = jh->b_cpnext; 36 jh->b_cpprev->b_cpnext = jh->b_cpnext;
41 if (transaction->t_checkpoint_list == jh) 37 if (transaction->t_checkpoint_list == jh) {
42 transaction->t_checkpoint_list = jh->b_cpnext; 38 transaction->t_checkpoint_list = jh->b_cpnext;
43 if (transaction->t_checkpoint_list == jh) 39 if (transaction->t_checkpoint_list == jh)
44 transaction->t_checkpoint_list = NULL; 40 transaction->t_checkpoint_list = NULL;
41 }
42}
43
44/*
45 * Unlink a buffer from a transaction checkpoint(io) list.
46 *
47 * Called with j_list_lock held.
48 */
49static inline void __buffer_unlink(struct journal_head *jh)
50{
51 transaction_t *transaction = jh->b_cp_transaction;
52
53 __buffer_unlink_first(jh);
54 if (transaction->t_checkpoint_io_list == jh) {
55 transaction->t_checkpoint_io_list = jh->b_cpnext;
56 if (transaction->t_checkpoint_io_list == jh)
57 transaction->t_checkpoint_io_list = NULL;
58 }
59}
60
61/*
62 * Move a buffer from the checkpoint list to the checkpoint io list
63 *
64 * Called with j_list_lock held
65 */
66static inline void __buffer_relink_io(struct journal_head *jh)
67{
68 transaction_t *transaction = jh->b_cp_transaction;
69
70 __buffer_unlink_first(jh);
71
72 if (!transaction->t_checkpoint_io_list) {
73 jh->b_cpnext = jh->b_cpprev = jh;
74 } else {
75 jh->b_cpnext = transaction->t_checkpoint_io_list;
76 jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev;
77 jh->b_cpprev->b_cpnext = jh;
78 jh->b_cpnext->b_cpprev = jh;
79 }
80 transaction->t_checkpoint_io_list = jh;
45} 81}
46 82
47/* 83/*
48 * Try to release a checkpointed buffer from its transaction. 84 * Try to release a checkpointed buffer from its transaction.
49 * Returns 1 if we released it. 85 * Returns 1 if we released it and 2 if we also released the
86 * whole transaction.
87 *
50 * Requires j_list_lock 88 * Requires j_list_lock
51 * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it 89 * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
52 */ 90 */
@@ -57,12 +95,11 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
57 95
58 if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) { 96 if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) {
59 JBUFFER_TRACE(jh, "remove from checkpoint list"); 97 JBUFFER_TRACE(jh, "remove from checkpoint list");
60 __journal_remove_checkpoint(jh); 98 ret = __journal_remove_checkpoint(jh) + 1;
61 jbd_unlock_bh_state(bh); 99 jbd_unlock_bh_state(bh);
62 journal_remove_journal_head(bh); 100 journal_remove_journal_head(bh);
63 BUFFER_TRACE(bh, "release"); 101 BUFFER_TRACE(bh, "release");
64 __brelse(bh); 102 __brelse(bh);
65 ret = 1;
66 } else { 103 } else {
67 jbd_unlock_bh_state(bh); 104 jbd_unlock_bh_state(bh);
68 } 105 }
@@ -117,83 +154,54 @@ static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh)
117} 154}
118 155
119/* 156/*
120 * Clean up a transaction's checkpoint list. 157 * Clean up transaction's list of buffers submitted for io.
121 * 158 * We wait for any pending IO to complete and remove any clean
122 * We wait for any pending IO to complete and make sure any clean 159 * buffers. Note that we take the buffers in the opposite ordering
123 * buffers are removed from the transaction. 160 * from the one in which they were submitted for IO.
124 *
125 * Return 1 if we performed any actions which might have destroyed the
126 * checkpoint. (journal_remove_checkpoint() deletes the transaction when
127 * the last checkpoint buffer is cleansed)
128 * 161 *
129 * Called with j_list_lock held. 162 * Called with j_list_lock held.
130 */ 163 */
131static int __cleanup_transaction(journal_t *journal, transaction_t *transaction) 164static void __wait_cp_io(journal_t *journal, transaction_t *transaction)
132{ 165{
133 struct journal_head *jh, *next_jh, *last_jh; 166 struct journal_head *jh;
134 struct buffer_head *bh; 167 struct buffer_head *bh;
135 int ret = 0; 168 tid_t this_tid;
136 169 int released = 0;
137 assert_spin_locked(&journal->j_list_lock); 170
138 jh = transaction->t_checkpoint_list; 171 this_tid = transaction->t_tid;
139 if (!jh) 172restart:
140 return 0; 173 /* Did somebody clean up the transaction in the meanwhile? */
141 174 if (journal->j_checkpoint_transactions != transaction ||
142 last_jh = jh->b_cpprev; 175 transaction->t_tid != this_tid)
143 next_jh = jh; 176 return;
144 do { 177 while (!released && transaction->t_checkpoint_io_list) {
145 jh = next_jh; 178 jh = transaction->t_checkpoint_io_list;
146 bh = jh2bh(jh); 179 bh = jh2bh(jh);
180 if (!jbd_trylock_bh_state(bh)) {
181 jbd_sync_bh(journal, bh);
182 spin_lock(&journal->j_list_lock);
183 goto restart;
184 }
147 if (buffer_locked(bh)) { 185 if (buffer_locked(bh)) {
148 atomic_inc(&bh->b_count); 186 atomic_inc(&bh->b_count);
149 spin_unlock(&journal->j_list_lock); 187 spin_unlock(&journal->j_list_lock);
188 jbd_unlock_bh_state(bh);
150 wait_on_buffer(bh); 189 wait_on_buffer(bh);
151 /* the journal_head may have gone by now */ 190 /* the journal_head may have gone by now */
152 BUFFER_TRACE(bh, "brelse"); 191 BUFFER_TRACE(bh, "brelse");
153 __brelse(bh); 192 __brelse(bh);
154 goto out_return_1; 193 spin_lock(&journal->j_list_lock);
194 goto restart;
155 } 195 }
156
157 /* 196 /*
158 * This is foul 197 * Now in whatever state the buffer currently is, we know that
198 * it has been written out and so we can drop it from the list
159 */ 199 */
160 if (!jbd_trylock_bh_state(bh)) { 200 released = __journal_remove_checkpoint(jh);
161 jbd_sync_bh(journal, bh); 201 jbd_unlock_bh_state(bh);
162 goto out_return_1; 202 journal_remove_journal_head(bh);
163 } 203 __brelse(bh);
164 204 }
165 if (jh->b_transaction != NULL) {
166 transaction_t *t = jh->b_transaction;
167 tid_t tid = t->t_tid;
168
169 spin_unlock(&journal->j_list_lock);
170 jbd_unlock_bh_state(bh);
171 log_start_commit(journal, tid);
172 log_wait_commit(journal, tid);
173 goto out_return_1;
174 }
175
176 /*
177 * AKPM: I think the buffer_jbddirty test is redundant - it
178 * shouldn't have NULL b_transaction?
179 */
180 next_jh = jh->b_cpnext;
181 if (!buffer_dirty(bh) && !buffer_jbddirty(bh)) {
182 BUFFER_TRACE(bh, "remove from checkpoint");
183 __journal_remove_checkpoint(jh);
184 jbd_unlock_bh_state(bh);
185 journal_remove_journal_head(bh);
186 __brelse(bh);
187 ret = 1;
188 } else {
189 jbd_unlock_bh_state(bh);
190 }
191 } while (jh != last_jh);
192
193 return ret;
194out_return_1:
195 spin_lock(&journal->j_list_lock);
196 return 1;
197} 205}
198 206
199#define NR_BATCH 64 207#define NR_BATCH 64
@@ -203,9 +211,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
203{ 211{
204 int i; 212 int i;
205 213
206 spin_unlock(&journal->j_list_lock);
207 ll_rw_block(SWRITE, *batch_count, bhs); 214 ll_rw_block(SWRITE, *batch_count, bhs);
208 spin_lock(&journal->j_list_lock);
209 for (i = 0; i < *batch_count; i++) { 215 for (i = 0; i < *batch_count; i++) {
210 struct buffer_head *bh = bhs[i]; 216 struct buffer_head *bh = bhs[i];
211 clear_buffer_jwrite(bh); 217 clear_buffer_jwrite(bh);
@@ -221,19 +227,43 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
221 * Return 1 if something happened which requires us to abort the current 227 * Return 1 if something happened which requires us to abort the current
222 * scan of the checkpoint list. 228 * scan of the checkpoint list.
223 * 229 *
224 * Called with j_list_lock held. 230 * Called with j_list_lock held and drops it if 1 is returned
225 * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it 231 * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
226 */ 232 */
227static int __flush_buffer(journal_t *journal, struct journal_head *jh, 233static int __process_buffer(journal_t *journal, struct journal_head *jh,
228 struct buffer_head **bhs, int *batch_count, 234 struct buffer_head **bhs, int *batch_count)
229 int *drop_count)
230{ 235{
231 struct buffer_head *bh = jh2bh(jh); 236 struct buffer_head *bh = jh2bh(jh);
232 int ret = 0; 237 int ret = 0;
233 238
234 if (buffer_dirty(bh) && !buffer_locked(bh) && jh->b_jlist == BJ_None) { 239 if (buffer_locked(bh)) {
235 J_ASSERT_JH(jh, jh->b_transaction == NULL); 240 atomic_inc(&bh->b_count);
241 spin_unlock(&journal->j_list_lock);
242 jbd_unlock_bh_state(bh);
243 wait_on_buffer(bh);
244 /* the journal_head may have gone by now */
245 BUFFER_TRACE(bh, "brelse");
246 __brelse(bh);
247 ret = 1;
248 } else if (jh->b_transaction != NULL) {
249 transaction_t *t = jh->b_transaction;
250 tid_t tid = t->t_tid;
236 251
252 spin_unlock(&journal->j_list_lock);
253 jbd_unlock_bh_state(bh);
254 log_start_commit(journal, tid);
255 log_wait_commit(journal, tid);
256 ret = 1;
257 } else if (!buffer_dirty(bh)) {
258 J_ASSERT_JH(jh, !buffer_jbddirty(bh));
259 BUFFER_TRACE(bh, "remove from checkpoint");
260 __journal_remove_checkpoint(jh);
261 spin_unlock(&journal->j_list_lock);
262 jbd_unlock_bh_state(bh);
263 journal_remove_journal_head(bh);
264 __brelse(bh);
265 ret = 1;
266 } else {
237 /* 267 /*
238 * Important: we are about to write the buffer, and 268 * Important: we are about to write the buffer, and
239 * possibly block, while still holding the journal lock. 269 * possibly block, while still holding the journal lock.
@@ -246,45 +276,30 @@ static int __flush_buffer(journal_t *journal, struct journal_head *jh,
246 J_ASSERT_BH(bh, !buffer_jwrite(bh)); 276 J_ASSERT_BH(bh, !buffer_jwrite(bh));
247 set_buffer_jwrite(bh); 277 set_buffer_jwrite(bh);
248 bhs[*batch_count] = bh; 278 bhs[*batch_count] = bh;
279 __buffer_relink_io(jh);
249 jbd_unlock_bh_state(bh); 280 jbd_unlock_bh_state(bh);
250 (*batch_count)++; 281 (*batch_count)++;
251 if (*batch_count == NR_BATCH) { 282 if (*batch_count == NR_BATCH) {
283 spin_unlock(&journal->j_list_lock);
252 __flush_batch(journal, bhs, batch_count); 284 __flush_batch(journal, bhs, batch_count);
253 ret = 1; 285 ret = 1;
254 } 286 }
255 } else {
256 int last_buffer = 0;
257 if (jh->b_cpnext == jh) {
258 /* We may be about to drop the transaction. Tell the
259 * caller that the lists have changed.
260 */
261 last_buffer = 1;
262 }
263 if (__try_to_free_cp_buf(jh)) {
264 (*drop_count)++;
265 ret = last_buffer;
266 }
267 } 287 }
268 return ret; 288 return ret;
269} 289}
270 290
271/* 291/*
272 * Perform an actual checkpoint. We don't write out only enough to 292 * Perform an actual checkpoint. We take the first transaction on the
273 * satisfy the current blocked requests: rather we submit a reasonably 293 * list of transactions to be checkpointed and send all its buffers
274 * sized chunk of the outstanding data to disk at once for 294 * to disk. We submit larger chunks of data at once.
275 * efficiency. __log_wait_for_space() will retry if we didn't free enough.
276 * 295 *
277 * However, we _do_ take into account the amount requested so that once
278 * the IO has been queued, we can return as soon as enough of it has
279 * completed to disk.
280 *
281 * The journal should be locked before calling this function. 296 * The journal should be locked before calling this function.
282 */ 297 */
283int log_do_checkpoint(journal_t *journal) 298int log_do_checkpoint(journal_t *journal)
284{ 299{
300 transaction_t *transaction;
301 tid_t this_tid;
285 int result; 302 int result;
286 int batch_count = 0;
287 struct buffer_head *bhs[NR_BATCH];
288 303
289 jbd_debug(1, "Start checkpoint\n"); 304 jbd_debug(1, "Start checkpoint\n");
290 305
@@ -299,79 +314,68 @@ int log_do_checkpoint(journal_t *journal)
299 return result; 314 return result;
300 315
301 /* 316 /*
302 * OK, we need to start writing disk blocks. Try to free up a 317 * OK, we need to start writing disk blocks. Take one transaction
303 * quarter of the log in a single checkpoint if we can. 318 * and write it.
304 */ 319 */
320 spin_lock(&journal->j_list_lock);
321 if (!journal->j_checkpoint_transactions)
322 goto out;
323 transaction = journal->j_checkpoint_transactions;
324 this_tid = transaction->t_tid;
325restart:
305 /* 326 /*
306 * AKPM: check this code. I had a feeling a while back that it 327 * If someone cleaned up this transaction while we slept, we're
307 * degenerates into a busy loop at unmount time. 328 * done (maybe it's a new transaction, but it fell at the same
329 * address).
308 */ 330 */
309 spin_lock(&journal->j_list_lock); 331 if (journal->j_checkpoint_transactions == transaction &&
310 while (journal->j_checkpoint_transactions) { 332 transaction->t_tid == this_tid) {
311 transaction_t *transaction; 333 int batch_count = 0;
312 struct journal_head *jh, *last_jh, *next_jh; 334 struct buffer_head *bhs[NR_BATCH];
313 int drop_count = 0; 335 struct journal_head *jh;
314 int cleanup_ret, retry = 0; 336 int retry = 0;
315 tid_t this_tid; 337
316 338 while (!retry && transaction->t_checkpoint_list) {
317 transaction = journal->j_checkpoint_transactions;
318 this_tid = transaction->t_tid;
319 jh = transaction->t_checkpoint_list;
320 last_jh = jh->b_cpprev;
321 next_jh = jh;
322 do {
323 struct buffer_head *bh; 339 struct buffer_head *bh;
324 340
325 jh = next_jh; 341 jh = transaction->t_checkpoint_list;
326 next_jh = jh->b_cpnext;
327 bh = jh2bh(jh); 342 bh = jh2bh(jh);
328 if (!jbd_trylock_bh_state(bh)) { 343 if (!jbd_trylock_bh_state(bh)) {
329 jbd_sync_bh(journal, bh); 344 jbd_sync_bh(journal, bh);
330 spin_lock(&journal->j_list_lock);
331 retry = 1; 345 retry = 1;
332 break; 346 break;
333 } 347 }
334 retry = __flush_buffer(journal, jh, bhs, &batch_count, &drop_count); 348 retry = __process_buffer(journal, jh, bhs,&batch_count);
335 if (cond_resched_lock(&journal->j_list_lock)) { 349 if (!retry && lock_need_resched(&journal->j_list_lock)){
350 spin_unlock(&journal->j_list_lock);
336 retry = 1; 351 retry = 1;
337 break; 352 break;
338 } 353 }
339 } while (jh != last_jh && !retry); 354 }
340 355
341 if (batch_count) { 356 if (batch_count) {
357 if (!retry) {
358 spin_unlock(&journal->j_list_lock);
359 retry = 1;
360 }
342 __flush_batch(journal, bhs, &batch_count); 361 __flush_batch(journal, bhs, &batch_count);
343 retry = 1;
344 } 362 }
345 363
364 if (retry) {
365 spin_lock(&journal->j_list_lock);
366 goto restart;
367 }
346 /* 368 /*
347 * If someone cleaned up this transaction while we slept, we're 369 * Now we have cleaned up the first transaction's checkpoint
348 * done 370 * list. Let's clean up the second one
349 */
350 if (journal->j_checkpoint_transactions != transaction)
351 break;
352 if (retry)
353 continue;
354 /*
355 * Maybe it's a new transaction, but it fell at the same
356 * address
357 */
358 if (transaction->t_tid != this_tid)
359 continue;
360 /*
361 * We have walked the whole transaction list without
362 * finding anything to write to disk. We had better be
363 * able to make some progress or we are in trouble.
364 */ 371 */
365 cleanup_ret = __cleanup_transaction(journal, transaction); 372 __wait_cp_io(journal, transaction);
366 J_ASSERT(drop_count != 0 || cleanup_ret != 0);
367 if (journal->j_checkpoint_transactions != transaction)
368 break;
369 } 373 }
374out:
370 spin_unlock(&journal->j_list_lock); 375 spin_unlock(&journal->j_list_lock);
371 result = cleanup_journal_tail(journal); 376 result = cleanup_journal_tail(journal);
372 if (result < 0) 377 if (result < 0)
373 return result; 378 return result;
374
375 return 0; 379 return 0;
376} 380}
377 381
@@ -456,52 +460,98 @@ int cleanup_journal_tail(journal_t *journal)
456/* Checkpoint list management */ 460/* Checkpoint list management */
457 461
458/* 462/*
463 * journal_clean_one_cp_list
464 *
465 * Find all the written-back checkpoint buffers in the given list and release them.
466 *
467 * Called with the journal locked.
468 * Called with j_list_lock held.
469 * Returns number of bufers reaped (for debug)
470 */
471
472static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
473{
474 struct journal_head *last_jh;
475 struct journal_head *next_jh = jh;
476 int ret, freed = 0;
477
478 *released = 0;
479 if (!jh)
480 return 0;
481
482 last_jh = jh->b_cpprev;
483 do {
484 jh = next_jh;
485 next_jh = jh->b_cpnext;
486 /* Use trylock because of the ranking */
487 if (jbd_trylock_bh_state(jh2bh(jh))) {
488 ret = __try_to_free_cp_buf(jh);
489 if (ret) {
490 freed++;
491 if (ret == 2) {
492 *released = 1;
493 return freed;
494 }
495 }
496 }
497 /*
498 * This function only frees up some memory
499 * if possible so we dont have an obligation
500 * to finish processing. Bail out if preemption
501 * requested:
502 */
503 if (need_resched())
504 return freed;
505 } while (jh != last_jh);
506
507 return freed;
508}
509
510/*
459 * journal_clean_checkpoint_list 511 * journal_clean_checkpoint_list
460 * 512 *
461 * Find all the written-back checkpoint buffers in the journal and release them. 513 * Find all the written-back checkpoint buffers in the journal and release them.
462 * 514 *
463 * Called with the journal locked. 515 * Called with the journal locked.
464 * Called with j_list_lock held. 516 * Called with j_list_lock held.
465 * Returns number of bufers reaped (for debug) 517 * Returns number of buffers reaped (for debug)
466 */ 518 */
467 519
468int __journal_clean_checkpoint_list(journal_t *journal) 520int __journal_clean_checkpoint_list(journal_t *journal)
469{ 521{
470 transaction_t *transaction, *last_transaction, *next_transaction; 522 transaction_t *transaction, *last_transaction, *next_transaction;
471 int ret = 0; 523 int ret = 0;
524 int released;
472 525
473 transaction = journal->j_checkpoint_transactions; 526 transaction = journal->j_checkpoint_transactions;
474 if (transaction == 0) 527 if (!transaction)
475 goto out; 528 goto out;
476 529
477 last_transaction = transaction->t_cpprev; 530 last_transaction = transaction->t_cpprev;
478 next_transaction = transaction; 531 next_transaction = transaction;
479 do { 532 do {
480 struct journal_head *jh;
481
482 transaction = next_transaction; 533 transaction = next_transaction;
483 next_transaction = transaction->t_cpnext; 534 next_transaction = transaction->t_cpnext;
484 jh = transaction->t_checkpoint_list; 535 ret += journal_clean_one_cp_list(transaction->
485 if (jh) { 536 t_checkpoint_list, &released);
486 struct journal_head *last_jh = jh->b_cpprev; 537 /*
487 struct journal_head *next_jh = jh; 538 * This function only frees up some memory if possible so we
488 539 * dont have an obligation to finish processing. Bail out if
489 do { 540 * preemption requested:
490 jh = next_jh; 541 */
491 next_jh = jh->b_cpnext; 542 if (need_resched())
492 /* Use trylock because of the ranknig */ 543 goto out;
493 if (jbd_trylock_bh_state(jh2bh(jh))) 544 if (released)
494 ret += __try_to_free_cp_buf(jh); 545 continue;
495 /* 546 /*
496 * This function only frees up some memory 547 * It is essential that we are as careful as in the case of
497 * if possible so we dont have an obligation 548 * t_checkpoint_list with removing the buffer from the list as
498 * to finish processing. Bail out if preemption 549 * we can possibly see not yet submitted buffers on io_list
499 * requested: 550 */
500 */ 551 ret += journal_clean_one_cp_list(transaction->
501 if (need_resched()) 552 t_checkpoint_io_list, &released);
502 goto out; 553 if (need_resched())
503 } while (jh != last_jh); 554 goto out;
504 }
505 } while (transaction != last_transaction); 555 } while (transaction != last_transaction);
506out: 556out:
507 return ret; 557 return ret;
@@ -516,18 +566,22 @@ out:
516 * buffer updates committed in that transaction have safely been stored 566 * buffer updates committed in that transaction have safely been stored
517 * elsewhere on disk. To achieve this, all of the buffers in a 567 * elsewhere on disk. To achieve this, all of the buffers in a
518 * transaction need to be maintained on the transaction's checkpoint 568 * transaction need to be maintained on the transaction's checkpoint
519 * list until they have been rewritten, at which point this function is 569 * lists until they have been rewritten, at which point this function is
520 * called to remove the buffer from the existing transaction's 570 * called to remove the buffer from the existing transaction's
521 * checkpoint list. 571 * checkpoint lists.
572 *
573 * The function returns 1 if it frees the transaction, 0 otherwise.
522 * 574 *
523 * This function is called with the journal locked. 575 * This function is called with the journal locked.
524 * This function is called with j_list_lock held. 576 * This function is called with j_list_lock held.
577 * This function is called with jbd_lock_bh_state(jh2bh(jh))
525 */ 578 */
526 579
527void __journal_remove_checkpoint(struct journal_head *jh) 580int __journal_remove_checkpoint(struct journal_head *jh)
528{ 581{
529 transaction_t *transaction; 582 transaction_t *transaction;
530 journal_t *journal; 583 journal_t *journal;
584 int ret = 0;
531 585
532 JBUFFER_TRACE(jh, "entry"); 586 JBUFFER_TRACE(jh, "entry");
533 587
@@ -538,8 +592,10 @@ void __journal_remove_checkpoint(struct journal_head *jh)
538 journal = transaction->t_journal; 592 journal = transaction->t_journal;
539 593
540 __buffer_unlink(jh); 594 __buffer_unlink(jh);
595 jh->b_cp_transaction = NULL;
541 596
542 if (transaction->t_checkpoint_list != NULL) 597 if (transaction->t_checkpoint_list != NULL ||
598 transaction->t_checkpoint_io_list != NULL)
543 goto out; 599 goto out;
544 JBUFFER_TRACE(jh, "transaction has no more buffers"); 600 JBUFFER_TRACE(jh, "transaction has no more buffers");
545 601
@@ -565,8 +621,10 @@ void __journal_remove_checkpoint(struct journal_head *jh)
565 /* Just in case anybody was waiting for more transactions to be 621 /* Just in case anybody was waiting for more transactions to be
566 checkpointed... */ 622 checkpointed... */
567 wake_up(&journal->j_wait_logspace); 623 wake_up(&journal->j_wait_logspace);
624 ret = 1;
568out: 625out:
569 JBUFFER_TRACE(jh, "exit"); 626 JBUFFER_TRACE(jh, "exit");
627 return ret;
570} 628}
571 629
572/* 630/*
@@ -628,6 +686,7 @@ void __journal_drop_transaction(journal_t *journal, transaction_t *transaction)
628 J_ASSERT(transaction->t_shadow_list == NULL); 686 J_ASSERT(transaction->t_shadow_list == NULL);
629 J_ASSERT(transaction->t_log_list == NULL); 687 J_ASSERT(transaction->t_log_list == NULL);
630 J_ASSERT(transaction->t_checkpoint_list == NULL); 688 J_ASSERT(transaction->t_checkpoint_list == NULL);
689 J_ASSERT(transaction->t_checkpoint_io_list == NULL);
631 J_ASSERT(transaction->t_updates == 0); 690 J_ASSERT(transaction->t_updates == 0);
632 J_ASSERT(journal->j_committing_transaction != transaction); 691 J_ASSERT(journal->j_committing_transaction != transaction);
633 J_ASSERT(journal->j_running_transaction != transaction); 692 J_ASSERT(journal->j_running_transaction != transaction);
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 002ad2bbc769..0971814c38b8 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -790,11 +790,22 @@ restart_loop:
790 jbd_unlock_bh_state(bh); 790 jbd_unlock_bh_state(bh);
791 } else { 791 } else {
792 J_ASSERT_BH(bh, !buffer_dirty(bh)); 792 J_ASSERT_BH(bh, !buffer_dirty(bh));
793 J_ASSERT_JH(jh, jh->b_next_transaction == NULL); 793 /* The buffer on BJ_Forget list and not jbddirty means
794 __journal_unfile_buffer(jh); 794 * it has been freed by this transaction and hence it
795 jbd_unlock_bh_state(bh); 795 * could not have been reallocated until this
796 journal_remove_journal_head(bh); /* needs a brelse */ 796 * transaction has committed. *BUT* it could be
797 release_buffer_page(bh); 797 * reallocated once we have written all the data to
798 * disk and before we process the buffer on BJ_Forget
799 * list. */
800 JBUFFER_TRACE(jh, "refile or unfile freed buffer");
801 __journal_refile_buffer(jh);
802 if (!jh->b_transaction) {
803 jbd_unlock_bh_state(bh);
804 /* needs a brelse */
805 journal_remove_journal_head(bh);
806 release_buffer_page(bh);
807 } else
808 jbd_unlock_bh_state(bh);
798 } 809 }
799 cond_resched_lock(&journal->j_list_lock); 810 cond_resched_lock(&journal->j_list_lock);
800 } 811 }
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index c609f5034fcd..508b2ea91f43 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -227,7 +227,8 @@ repeat_locked:
227 spin_unlock(&transaction->t_handle_lock); 227 spin_unlock(&transaction->t_handle_lock);
228 spin_unlock(&journal->j_state_lock); 228 spin_unlock(&journal->j_state_lock);
229out: 229out:
230 kfree(new_transaction); 230 if (unlikely(new_transaction)) /* It's usually NULL */
231 kfree(new_transaction);
231 return ret; 232 return ret;
232} 233}
233 234
@@ -724,7 +725,8 @@ done:
724 journal_cancel_revoke(handle, jh); 725 journal_cancel_revoke(handle, jh);
725 726
726out: 727out:
727 kfree(frozen_buffer); 728 if (unlikely(frozen_buffer)) /* It's usually NULL */
729 kfree(frozen_buffer);
728 730
729 JBUFFER_TRACE(jh, "exit"); 731 JBUFFER_TRACE(jh, "exit");
730 return error; 732 return error;
@@ -903,7 +905,8 @@ repeat:
903 jbd_unlock_bh_state(bh); 905 jbd_unlock_bh_state(bh);
904out: 906out:
905 journal_put_journal_head(jh); 907 journal_put_journal_head(jh);
906 kfree(committed_data); 908 if (unlikely(committed_data))
909 kfree(committed_data);
907 return err; 910 return err;
908} 911}
909 912
@@ -2038,7 +2041,8 @@ void __journal_refile_buffer(struct journal_head *jh)
2038 __journal_temp_unlink_buffer(jh); 2041 __journal_temp_unlink_buffer(jh);
2039 jh->b_transaction = jh->b_next_transaction; 2042 jh->b_transaction = jh->b_next_transaction;
2040 jh->b_next_transaction = NULL; 2043 jh->b_next_transaction = NULL;
2041 __journal_file_buffer(jh, jh->b_transaction, BJ_Metadata); 2044 __journal_file_buffer(jh, jh->b_transaction,
2045 was_dirty ? BJ_Metadata : BJ_Reserved);
2042 J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING); 2046 J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING);
2043 2047
2044 if (was_dirty) 2048 if (was_dirty)
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index 020cc097c539..9e46ea6da752 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -377,9 +377,9 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
377 377
378/* Get statistics of the file system. */ 378/* Get statistics of the file system. */
379static int 379static int
380jffs_statfs(struct super_block *sb, struct kstatfs *buf) 380jffs_statfs(struct dentry *dentry, struct kstatfs *buf)
381{ 381{
382 struct jffs_control *c = (struct jffs_control *) sb->s_fs_info; 382 struct jffs_control *c = (struct jffs_control *) dentry->d_sb->s_fs_info;
383 struct jffs_fmcontrol *fmc; 383 struct jffs_fmcontrol *fmc;
384 384
385 lock_kernel(); 385 lock_kernel();
@@ -1785,10 +1785,11 @@ static struct super_operations jffs_ops =
1785 .remount_fs = jffs_remount, 1785 .remount_fs = jffs_remount,
1786}; 1786};
1787 1787
1788static struct super_block *jffs_get_sb(struct file_system_type *fs_type, 1788static int jffs_get_sb(struct file_system_type *fs_type,
1789 int flags, const char *dev_name, void *data) 1789 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
1790{ 1790{
1791 return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super); 1791 return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super,
1792 mnt);
1792} 1793}
1793 1794
1794static struct file_system_type jffs_fs_type = { 1795static struct file_system_type jffs_fs_type = {
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
index 0ef207dfaf6f..5371a403130a 100644
--- a/fs/jffs/intrep.c
+++ b/fs/jffs/intrep.c
@@ -247,7 +247,7 @@ flash_safe_read(struct mtd_info *mtd, loff_t from,
247 D3(printk(KERN_NOTICE "flash_safe_read(%p, %08x, %p, %08x)\n", 247 D3(printk(KERN_NOTICE "flash_safe_read(%p, %08x, %p, %08x)\n",
248 mtd, (unsigned int) from, buf, count)); 248 mtd, (unsigned int) from, buf, count));
249 249
250 res = MTD_READ(mtd, from, count, &retlen, buf); 250 res = mtd->read(mtd, from, count, &retlen, buf);
251 if (retlen != count) { 251 if (retlen != count) {
252 panic("Didn't read all bytes in flash_safe_read(). Returned %d\n", res); 252 panic("Didn't read all bytes in flash_safe_read(). Returned %d\n", res);
253 } 253 }
@@ -262,7 +262,7 @@ flash_read_u32(struct mtd_info *mtd, loff_t from)
262 __u32 ret; 262 __u32 ret;
263 int res; 263 int res;
264 264
265 res = MTD_READ(mtd, from, 4, &retlen, (unsigned char *)&ret); 265 res = mtd->read(mtd, from, 4, &retlen, (unsigned char *)&ret);
266 if (retlen != 4) { 266 if (retlen != 4) {
267 printk("Didn't read all bytes in flash_read_u32(). Returned %d\n", res); 267 printk("Didn't read all bytes in flash_read_u32(). Returned %d\n", res);
268 return 0; 268 return 0;
@@ -282,7 +282,7 @@ flash_safe_write(struct mtd_info *mtd, loff_t to,
282 D3(printk(KERN_NOTICE "flash_safe_write(%p, %08x, %p, %08x)\n", 282 D3(printk(KERN_NOTICE "flash_safe_write(%p, %08x, %p, %08x)\n",
283 mtd, (unsigned int) to, buf, count)); 283 mtd, (unsigned int) to, buf, count));
284 284
285 res = MTD_WRITE(mtd, to, count, &retlen, buf); 285 res = mtd->write(mtd, to, count, &retlen, buf);
286 if (retlen != count) { 286 if (retlen != count) {
287 printk("Didn't write all bytes in flash_safe_write(). Returned %d\n", res); 287 printk("Didn't write all bytes in flash_safe_write(). Returned %d\n", res);
288 } 288 }
@@ -300,9 +300,9 @@ flash_safe_writev(struct mtd_info *mtd, const struct kvec *vecs,
300 300
301 D3(printk(KERN_NOTICE "flash_safe_writev(%p, %08x, %p)\n", 301 D3(printk(KERN_NOTICE "flash_safe_writev(%p, %08x, %p)\n",
302 mtd, (unsigned int) to, vecs)); 302 mtd, (unsigned int) to, vecs));
303 303
304 if (mtd->writev) { 304 if (mtd->writev) {
305 res = MTD_WRITEV(mtd, vecs, iovec_cnt, to, &retlen); 305 res = mtd->writev(mtd, vecs, iovec_cnt, to, &retlen);
306 return res ? res : retlen; 306 return res ? res : retlen;
307 } 307 }
308 /* Not implemented writev. Repeatedly use write - on the not so 308 /* Not implemented writev. Repeatedly use write - on the not so
@@ -312,7 +312,8 @@ flash_safe_writev(struct mtd_info *mtd, const struct kvec *vecs,
312 retlen=0; 312 retlen=0;
313 313
314 for (i=0; !res && i<iovec_cnt; i++) { 314 for (i=0; !res && i<iovec_cnt; i++) {
315 res = MTD_WRITE(mtd, to, vecs[i].iov_len, &retlen_a, vecs[i].iov_base); 315 res = mtd->write(mtd, to, vecs[i].iov_len, &retlen_a,
316 vecs[i].iov_base);
316 if (retlen_a != vecs[i].iov_len) { 317 if (retlen_a != vecs[i].iov_len) {
317 printk("Didn't write all bytes in flash_safe_writev(). Returned %d\n", res); 318 printk("Didn't write all bytes in flash_safe_writev(). Returned %d\n", res);
318 if (i != iovec_cnt-1) 319 if (i != iovec_cnt-1)
@@ -393,7 +394,7 @@ flash_erase_region(struct mtd_info *mtd, loff_t start,
393 set_current_state(TASK_UNINTERRUPTIBLE); 394 set_current_state(TASK_UNINTERRUPTIBLE);
394 add_wait_queue(&wait_q, &wait); 395 add_wait_queue(&wait_q, &wait);
395 396
396 if (MTD_ERASE(mtd, erase) < 0) { 397 if (mtd->erase(mtd, erase) < 0) {
397 set_current_state(TASK_RUNNING); 398 set_current_state(TASK_RUNNING);
398 remove_wait_queue(&wait_q, &wait); 399 remove_wait_queue(&wait_q, &wait);
399 kfree(erase); 400 kfree(erase);
diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile
index 77dc5561a04e..7f28ee0bd132 100644
--- a/fs/jffs2/Makefile
+++ b/fs/jffs2/Makefile
@@ -12,6 +12,9 @@ jffs2-y += symlink.o build.o erase.o background.o fs.o writev.o
12jffs2-y += super.o debug.o 12jffs2-y += super.o debug.o
13 13
14jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o 14jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o
15jffs2-$(CONFIG_JFFS2_FS_XATTR) += xattr.o xattr_trusted.o xattr_user.o
16jffs2-$(CONFIG_JFFS2_FS_SECURITY) += security.o
17jffs2-$(CONFIG_JFFS2_FS_POSIX_ACL) += acl.o
15jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o 18jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o
16jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o 19jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o
17jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o 20jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o
diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking
index b7943439b6ec..c8f0bd64e53e 100644
--- a/fs/jffs2/README.Locking
+++ b/fs/jffs2/README.Locking
@@ -150,3 +150,24 @@ the buffer.
150 150
151Ordering constraints: 151Ordering constraints:
152 Lock wbuf_sem last, after the alloc_sem or and f->sem. 152 Lock wbuf_sem last, after the alloc_sem or and f->sem.
153
154
155 c->xattr_sem
156 ------------
157
158This read/write semaphore protects against concurrent access to the
159xattr related objects which include stuff in superblock and ic->xref.
160In read-only path, write-semaphore is too much exclusion. It's enough
161by read-semaphore. But you must hold write-semaphore when updating,
162creating or deleting any xattr related object.
163
164Once xattr_sem released, there would be no assurance for the existence
165of those objects. Thus, a series of processes is often required to retry,
166when updating such a object is necessary under holding read semaphore.
167For example, do_jffs2_getxattr() holds read-semaphore to scan xref and
168xdatum at first. But it retries this process with holding write-semaphore
169after release read-semaphore, if it's necessary to load name/value pair
170from medium.
171
172Ordering constraints:
173 Lock xattr_sem last, after the alloc_sem.
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
new file mode 100644
index 000000000000..320dd48b834e
--- /dev/null
+++ b/fs/jffs2/acl.c
@@ -0,0 +1,485 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
11#include <linux/kernel.h>
12#include <linux/slab.h>
13#include <linux/fs.h>
14#include <linux/time.h>
15#include <linux/crc32.h>
16#include <linux/jffs2.h>
17#include <linux/xattr.h>
18#include <linux/posix_acl_xattr.h>
19#include <linux/mtd/mtd.h>
20#include "nodelist.h"
21
22static size_t jffs2_acl_size(int count)
23{
24 if (count <= 4) {
25 return sizeof(struct jffs2_acl_header)
26 + count * sizeof(struct jffs2_acl_entry_short);
27 } else {
28 return sizeof(struct jffs2_acl_header)
29 + 4 * sizeof(struct jffs2_acl_entry_short)
30 + (count - 4) * sizeof(struct jffs2_acl_entry);
31 }
32}
33
34static int jffs2_acl_count(size_t size)
35{
36 size_t s;
37
38 size -= sizeof(struct jffs2_acl_header);
39 s = size - 4 * sizeof(struct jffs2_acl_entry_short);
40 if (s < 0) {
41 if (size % sizeof(struct jffs2_acl_entry_short))
42 return -1;
43 return size / sizeof(struct jffs2_acl_entry_short);
44 } else {
45 if (s % sizeof(struct jffs2_acl_entry))
46 return -1;
47 return s / sizeof(struct jffs2_acl_entry) + 4;
48 }
49}
50
51static struct posix_acl *jffs2_acl_from_medium(void *value, size_t size)
52{
53 void *end = value + size;
54 struct jffs2_acl_header *header = value;
55 struct jffs2_acl_entry *entry;
56 struct posix_acl *acl;
57 uint32_t ver;
58 int i, count;
59
60 if (!value)
61 return NULL;
62 if (size < sizeof(struct jffs2_acl_header))
63 return ERR_PTR(-EINVAL);
64 ver = je32_to_cpu(header->a_version);
65 if (ver != JFFS2_ACL_VERSION) {
66 JFFS2_WARNING("Invalid ACL version. (=%u)\n", ver);
67 return ERR_PTR(-EINVAL);
68 }
69
70 value += sizeof(struct jffs2_acl_header);
71 count = jffs2_acl_count(size);
72 if (count < 0)
73 return ERR_PTR(-EINVAL);
74 if (count == 0)
75 return NULL;
76
77 acl = posix_acl_alloc(count, GFP_KERNEL);
78 if (!acl)
79 return ERR_PTR(-ENOMEM);
80
81 for (i=0; i < count; i++) {
82 entry = value;
83 if (value + sizeof(struct jffs2_acl_entry_short) > end)
84 goto fail;
85 acl->a_entries[i].e_tag = je16_to_cpu(entry->e_tag);
86 acl->a_entries[i].e_perm = je16_to_cpu(entry->e_perm);
87 switch (acl->a_entries[i].e_tag) {
88 case ACL_USER_OBJ:
89 case ACL_GROUP_OBJ:
90 case ACL_MASK:
91 case ACL_OTHER:
92 value += sizeof(struct jffs2_acl_entry_short);
93 acl->a_entries[i].e_id = ACL_UNDEFINED_ID;
94 break;
95
96 case ACL_USER:
97 case ACL_GROUP:
98 value += sizeof(struct jffs2_acl_entry);
99 if (value > end)
100 goto fail;
101 acl->a_entries[i].e_id = je32_to_cpu(entry->e_id);
102 break;
103
104 default:
105 goto fail;
106 }
107 }
108 if (value != end)
109 goto fail;
110 return acl;
111 fail:
112 posix_acl_release(acl);
113 return ERR_PTR(-EINVAL);
114}
115
116static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size)
117{
118 struct jffs2_acl_header *header;
119 struct jffs2_acl_entry *entry;
120 void *e;
121 size_t i;
122
123 *size = jffs2_acl_size(acl->a_count);
124 header = kmalloc(sizeof(*header) + acl->a_count * sizeof(*entry), GFP_KERNEL);
125 if (!header)
126 return ERR_PTR(-ENOMEM);
127 header->a_version = cpu_to_je32(JFFS2_ACL_VERSION);
128 e = header + 1;
129 for (i=0; i < acl->a_count; i++) {
130 entry = e;
131 entry->e_tag = cpu_to_je16(acl->a_entries[i].e_tag);
132 entry->e_perm = cpu_to_je16(acl->a_entries[i].e_perm);
133 switch(acl->a_entries[i].e_tag) {
134 case ACL_USER:
135 case ACL_GROUP:
136 entry->e_id = cpu_to_je32(acl->a_entries[i].e_id);
137 e += sizeof(struct jffs2_acl_entry);
138 break;
139
140 case ACL_USER_OBJ:
141 case ACL_GROUP_OBJ:
142 case ACL_MASK:
143 case ACL_OTHER:
144 e += sizeof(struct jffs2_acl_entry_short);
145 break;
146
147 default:
148 goto fail;
149 }
150 }
151 return header;
152 fail:
153 kfree(header);
154 return ERR_PTR(-EINVAL);
155}
156
157static struct posix_acl *jffs2_iget_acl(struct inode *inode, struct posix_acl **i_acl)
158{
159 struct posix_acl *acl = JFFS2_ACL_NOT_CACHED;
160
161 spin_lock(&inode->i_lock);
162 if (*i_acl != JFFS2_ACL_NOT_CACHED)
163 acl = posix_acl_dup(*i_acl);
164 spin_unlock(&inode->i_lock);
165 return acl;
166}
167
168static void jffs2_iset_acl(struct inode *inode, struct posix_acl **i_acl, struct posix_acl *acl)
169{
170 spin_lock(&inode->i_lock);
171 if (*i_acl != JFFS2_ACL_NOT_CACHED)
172 posix_acl_release(*i_acl);
173 *i_acl = posix_acl_dup(acl);
174 spin_unlock(&inode->i_lock);
175}
176
177static struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
178{
179 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
180 struct posix_acl *acl;
181 char *value = NULL;
182 int rc, xprefix;
183
184 switch (type) {
185 case ACL_TYPE_ACCESS:
186 acl = jffs2_iget_acl(inode, &f->i_acl_access);
187 if (acl != JFFS2_ACL_NOT_CACHED)
188 return acl;
189 xprefix = JFFS2_XPREFIX_ACL_ACCESS;
190 break;
191 case ACL_TYPE_DEFAULT:
192 acl = jffs2_iget_acl(inode, &f->i_acl_default);
193 if (acl != JFFS2_ACL_NOT_CACHED)
194 return acl;
195 xprefix = JFFS2_XPREFIX_ACL_DEFAULT;
196 break;
197 default:
198 return ERR_PTR(-EINVAL);
199 }
200 rc = do_jffs2_getxattr(inode, xprefix, "", NULL, 0);
201 if (rc > 0) {
202 value = kmalloc(rc, GFP_KERNEL);
203 if (!value)
204 return ERR_PTR(-ENOMEM);
205 rc = do_jffs2_getxattr(inode, xprefix, "", value, rc);
206 }
207 if (rc > 0) {
208 acl = jffs2_acl_from_medium(value, rc);
209 } else if (rc == -ENODATA || rc == -ENOSYS) {
210 acl = NULL;
211 } else {
212 acl = ERR_PTR(rc);
213 }
214 if (value)
215 kfree(value);
216 if (!IS_ERR(acl)) {
217 switch (type) {
218 case ACL_TYPE_ACCESS:
219 jffs2_iset_acl(inode, &f->i_acl_access, acl);
220 break;
221 case ACL_TYPE_DEFAULT:
222 jffs2_iset_acl(inode, &f->i_acl_default, acl);
223 break;
224 }
225 }
226 return acl;
227}
228
229static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
230{
231 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
232 size_t size = 0;
233 char *value = NULL;
234 int rc, xprefix;
235
236 if (S_ISLNK(inode->i_mode))
237 return -EOPNOTSUPP;
238
239 switch (type) {
240 case ACL_TYPE_ACCESS:
241 xprefix = JFFS2_XPREFIX_ACL_ACCESS;
242 if (acl) {
243 mode_t mode = inode->i_mode;
244 rc = posix_acl_equiv_mode(acl, &mode);
245 if (rc < 0)
246 return rc;
247 if (inode->i_mode != mode) {
248 inode->i_mode = mode;
249 jffs2_dirty_inode(inode);
250 }
251 if (rc == 0)
252 acl = NULL;
253 }
254 break;
255 case ACL_TYPE_DEFAULT:
256 xprefix = JFFS2_XPREFIX_ACL_DEFAULT;
257 if (!S_ISDIR(inode->i_mode))
258 return acl ? -EACCES : 0;
259 break;
260 default:
261 return -EINVAL;
262 }
263 if (acl) {
264 value = jffs2_acl_to_medium(acl, &size);
265 if (IS_ERR(value))
266 return PTR_ERR(value);
267 }
268
269 rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0);
270 if (value)
271 kfree(value);
272 if (!rc) {
273 switch(type) {
274 case ACL_TYPE_ACCESS:
275 jffs2_iset_acl(inode, &f->i_acl_access, acl);
276 break;
277 case ACL_TYPE_DEFAULT:
278 jffs2_iset_acl(inode, &f->i_acl_default, acl);
279 break;
280 }
281 }
282 return rc;
283}
284
285static int jffs2_check_acl(struct inode *inode, int mask)
286{
287 struct posix_acl *acl;
288 int rc;
289
290 acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
291 if (IS_ERR(acl))
292 return PTR_ERR(acl);
293 if (acl) {
294 rc = posix_acl_permission(inode, acl, mask);
295 posix_acl_release(acl);
296 return rc;
297 }
298 return -EAGAIN;
299}
300
301int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd)
302{
303 return generic_permission(inode, mask, jffs2_check_acl);
304}
305
306int jffs2_init_acl(struct inode *inode, struct inode *dir)
307{
308 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
309 struct posix_acl *acl = NULL, *clone;
310 mode_t mode;
311 int rc = 0;
312
313 f->i_acl_access = JFFS2_ACL_NOT_CACHED;
314 f->i_acl_default = JFFS2_ACL_NOT_CACHED;
315 if (!S_ISLNK(inode->i_mode)) {
316 acl = jffs2_get_acl(dir, ACL_TYPE_DEFAULT);
317 if (IS_ERR(acl))
318 return PTR_ERR(acl);
319 if (!acl)
320 inode->i_mode &= ~current->fs->umask;
321 }
322 if (acl) {
323 if (S_ISDIR(inode->i_mode)) {
324 rc = jffs2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
325 if (rc)
326 goto cleanup;
327 }
328 clone = posix_acl_clone(acl, GFP_KERNEL);
329 rc = -ENOMEM;
330 if (!clone)
331 goto cleanup;
332 mode = inode->i_mode;
333 rc = posix_acl_create_masq(clone, &mode);
334 if (rc >= 0) {
335 inode->i_mode = mode;
336 if (rc > 0)
337 rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
338 }
339 posix_acl_release(clone);
340 }
341 cleanup:
342 posix_acl_release(acl);
343 return rc;
344}
345
346void jffs2_clear_acl(struct inode *inode)
347{
348 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
349
350 if (f->i_acl_access && f->i_acl_access != JFFS2_ACL_NOT_CACHED) {
351 posix_acl_release(f->i_acl_access);
352 f->i_acl_access = JFFS2_ACL_NOT_CACHED;
353 }
354 if (f->i_acl_default && f->i_acl_default != JFFS2_ACL_NOT_CACHED) {
355 posix_acl_release(f->i_acl_default);
356 f->i_acl_default = JFFS2_ACL_NOT_CACHED;
357 }
358}
359
360int jffs2_acl_chmod(struct inode *inode)
361{
362 struct posix_acl *acl, *clone;
363 int rc;
364
365 if (S_ISLNK(inode->i_mode))
366 return -EOPNOTSUPP;
367 acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
368 if (IS_ERR(acl) || !acl)
369 return PTR_ERR(acl);
370 clone = posix_acl_clone(acl, GFP_KERNEL);
371 posix_acl_release(acl);
372 if (!clone)
373 return -ENOMEM;
374 rc = posix_acl_chmod_masq(clone, inode->i_mode);
375 if (!rc)
376 rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
377 posix_acl_release(clone);
378 return rc;
379}
380
381static size_t jffs2_acl_access_listxattr(struct inode *inode, char *list, size_t list_size,
382 const char *name, size_t name_len)
383{
384 const int retlen = sizeof(POSIX_ACL_XATTR_ACCESS);
385
386 if (list && retlen <= list_size)
387 strcpy(list, POSIX_ACL_XATTR_ACCESS);
388 return retlen;
389}
390
391static size_t jffs2_acl_default_listxattr(struct inode *inode, char *list, size_t list_size,
392 const char *name, size_t name_len)
393{
394 const int retlen = sizeof(POSIX_ACL_XATTR_DEFAULT);
395
396 if (list && retlen <= list_size)
397 strcpy(list, POSIX_ACL_XATTR_DEFAULT);
398 return retlen;
399}
400
401static int jffs2_acl_getxattr(struct inode *inode, int type, void *buffer, size_t size)
402{
403 struct posix_acl *acl;
404 int rc;
405
406 acl = jffs2_get_acl(inode, type);
407 if (IS_ERR(acl))
408 return PTR_ERR(acl);
409 if (!acl)
410 return -ENODATA;
411 rc = posix_acl_to_xattr(acl, buffer, size);
412 posix_acl_release(acl);
413
414 return rc;
415}
416
417static int jffs2_acl_access_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
418{
419 if (name[0] != '\0')
420 return -EINVAL;
421 return jffs2_acl_getxattr(inode, ACL_TYPE_ACCESS, buffer, size);
422}
423
424static int jffs2_acl_default_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
425{
426 if (name[0] != '\0')
427 return -EINVAL;
428 return jffs2_acl_getxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
429}
430
431static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, size_t size)
432{
433 struct posix_acl *acl;
434 int rc;
435
436 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
437 return -EPERM;
438
439 if (value) {
440 acl = posix_acl_from_xattr(value, size);
441 if (IS_ERR(acl))
442 return PTR_ERR(acl);
443 if (acl) {
444 rc = posix_acl_valid(acl);
445 if (rc)
446 goto out;
447 }
448 } else {
449 acl = NULL;
450 }
451 rc = jffs2_set_acl(inode, type, acl);
452 out:
453 posix_acl_release(acl);
454 return rc;
455}
456
457static int jffs2_acl_access_setxattr(struct inode *inode, const char *name,
458 const void *buffer, size_t size, int flags)
459{
460 if (name[0] != '\0')
461 return -EINVAL;
462 return jffs2_acl_setxattr(inode, ACL_TYPE_ACCESS, buffer, size);
463}
464
465static int jffs2_acl_default_setxattr(struct inode *inode, const char *name,
466 const void *buffer, size_t size, int flags)
467{
468 if (name[0] != '\0')
469 return -EINVAL;
470 return jffs2_acl_setxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
471}
472
473struct xattr_handler jffs2_acl_access_xattr_handler = {
474 .prefix = POSIX_ACL_XATTR_ACCESS,
475 .list = jffs2_acl_access_listxattr,
476 .get = jffs2_acl_access_getxattr,
477 .set = jffs2_acl_access_setxattr,
478};
479
480struct xattr_handler jffs2_acl_default_xattr_handler = {
481 .prefix = POSIX_ACL_XATTR_DEFAULT,
482 .list = jffs2_acl_default_listxattr,
483 .get = jffs2_acl_default_getxattr,
484 .set = jffs2_acl_default_setxattr,
485};
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
new file mode 100644
index 000000000000..8893bd1a6ba7
--- /dev/null
+++ b/fs/jffs2/acl.h
@@ -0,0 +1,45 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
11struct jffs2_acl_entry {
12 jint16_t e_tag;
13 jint16_t e_perm;
14 jint32_t e_id;
15};
16
17struct jffs2_acl_entry_short {
18 jint16_t e_tag;
19 jint16_t e_perm;
20};
21
22struct jffs2_acl_header {
23 jint32_t a_version;
24};
25
26#ifdef CONFIG_JFFS2_FS_POSIX_ACL
27
28#define JFFS2_ACL_NOT_CACHED ((void *)-1)
29
30extern int jffs2_permission(struct inode *, int, struct nameidata *);
31extern int jffs2_acl_chmod(struct inode *);
32extern int jffs2_init_acl(struct inode *, struct inode *);
33extern void jffs2_clear_acl(struct inode *);
34
35extern struct xattr_handler jffs2_acl_access_xattr_handler;
36extern struct xattr_handler jffs2_acl_default_xattr_handler;
37
38#else
39
40#define jffs2_permission NULL
41#define jffs2_acl_chmod(inode) (0)
42#define jffs2_init_acl(inode,dir) (0)
43#define jffs2_clear_acl(inode)
44
45#endif /* CONFIG_JFFS2_FS_POSIX_ACL */
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index 70f7a896c04a..02826967ab58 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -160,6 +160,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
160 ic->scan_dents = NULL; 160 ic->scan_dents = NULL;
161 cond_resched(); 161 cond_resched();
162 } 162 }
163 jffs2_build_xattr_subsystem(c);
163 c->flags &= ~JFFS2_SB_FLAG_BUILDING; 164 c->flags &= ~JFFS2_SB_FLAG_BUILDING;
164 165
165 dbg_fsbuild("FS build complete\n"); 166 dbg_fsbuild("FS build complete\n");
@@ -178,6 +179,7 @@ exit:
178 jffs2_free_full_dirent(fd); 179 jffs2_free_full_dirent(fd);
179 } 180 }
180 } 181 }
182 jffs2_clear_xattr_subsystem(c);
181 } 183 }
182 184
183 return ret; 185 return ret;
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c
index e7944e665b9f..7001ba26c067 100644
--- a/fs/jffs2/compr.c
+++ b/fs/jffs2/compr.c
@@ -412,7 +412,7 @@ void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
412 kfree(comprbuf); 412 kfree(comprbuf);
413} 413}
414 414
415int jffs2_compressors_init(void) 415int __init jffs2_compressors_init(void)
416{ 416{
417/* Registering compressors */ 417/* Registering compressors */
418#ifdef CONFIG_JFFS2_ZLIB 418#ifdef CONFIG_JFFS2_ZLIB
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h
index a77e830d85c5..509b8b1c0811 100644
--- a/fs/jffs2/compr.h
+++ b/fs/jffs2/compr.h
@@ -23,8 +23,8 @@
23#include <linux/errno.h> 23#include <linux/errno.h>
24#include <linux/fs.h> 24#include <linux/fs.h>
25#include <linux/jffs2.h> 25#include <linux/jffs2.h>
26#include <linux/jffs2_fs_i.h> 26#include "jffs2_fs_i.h"
27#include <linux/jffs2_fs_sb.h> 27#include "jffs2_fs_sb.h"
28#include "nodelist.h" 28#include "nodelist.h"
29 29
30#define JFFS2_RUBINMIPS_PRIORITY 10 30#define JFFS2_RUBINMIPS_PRIORITY 10
diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c
index 1fe17de713e8..72b4fc13a106 100644
--- a/fs/jffs2/debug.c
+++ b/fs/jffs2/debug.c
@@ -192,13 +192,13 @@ __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
192 else 192 else
193 my_dirty_size += totlen; 193 my_dirty_size += totlen;
194 194
195 if ((!ref2->next_phys) != (ref2 == jeb->last_node)) { 195 if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) {
196 JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), last_node is at %#08x (mem %p).\n", 196 JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
197 ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys, 197 ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2),
198 ref_offset(jeb->last_node), jeb->last_node); 198 ref_offset(jeb->last_node), jeb->last_node);
199 goto error; 199 goto error;
200 } 200 }
201 ref2 = ref2->next_phys; 201 ref2 = ref_next(ref2);
202 } 202 }
203 203
204 if (my_used_size != jeb->used_size) { 204 if (my_used_size != jeb->used_size) {
@@ -268,9 +268,9 @@ __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
268 } 268 }
269 269
270 printk(JFFS2_DBG); 270 printk(JFFS2_DBG);
271 for (ref = jeb->first_node; ; ref = ref->next_phys) { 271 for (ref = jeb->first_node; ; ref = ref_next(ref)) {
272 printk("%#08x(%#x)", ref_offset(ref), ref->__totlen); 272 printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
273 if (ref->next_phys) 273 if (ref_next(ref))
274 printk("->"); 274 printk("->");
275 else 275 else
276 break; 276 break;
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
index 162af6dfe292..5fa494a792b2 100644
--- a/fs/jffs2/debug.h
+++ b/fs/jffs2/debug.h
@@ -171,6 +171,12 @@
171#define dbg_memalloc(fmt, ...) 171#define dbg_memalloc(fmt, ...)
172#endif 172#endif
173 173
174/* Watch the XATTR subsystem */
175#ifdef JFFS2_DBG_XATTR_MESSAGES
176#define dbg_xattr(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__)
177#else
178#define dbg_xattr(fmt, ...)
179#endif
174 180
175/* "Sanity" checks */ 181/* "Sanity" checks */
176void 182void
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 8bc7a5018e40..edd8371fc6a5 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -17,8 +17,8 @@
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/crc32.h> 18#include <linux/crc32.h>
19#include <linux/jffs2.h> 19#include <linux/jffs2.h>
20#include <linux/jffs2_fs_i.h> 20#include "jffs2_fs_i.h"
21#include <linux/jffs2_fs_sb.h> 21#include "jffs2_fs_sb.h"
22#include <linux/time.h> 22#include <linux/time.h>
23#include "nodelist.h" 23#include "nodelist.h"
24 24
@@ -57,7 +57,12 @@ struct inode_operations jffs2_dir_inode_operations =
57 .rmdir = jffs2_rmdir, 57 .rmdir = jffs2_rmdir,
58 .mknod = jffs2_mknod, 58 .mknod = jffs2_mknod,
59 .rename = jffs2_rename, 59 .rename = jffs2_rename,
60 .permission = jffs2_permission,
60 .setattr = jffs2_setattr, 61 .setattr = jffs2_setattr,
62 .setxattr = jffs2_setxattr,
63 .getxattr = jffs2_getxattr,
64 .listxattr = jffs2_listxattr,
65 .removexattr = jffs2_removexattr
61}; 66};
62 67
63/***********************************************************************/ 68/***********************************************************************/
@@ -78,6 +83,9 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
78 83
79 D1(printk(KERN_DEBUG "jffs2_lookup()\n")); 84 D1(printk(KERN_DEBUG "jffs2_lookup()\n"));
80 85
86 if (target->d_name.len > JFFS2_MAX_NAME_LEN)
87 return ERR_PTR(-ENAMETOOLONG);
88
81 dir_f = JFFS2_INODE_INFO(dir_i); 89 dir_f = JFFS2_INODE_INFO(dir_i);
82 c = JFFS2_SB_INFO(dir_i->i_sb); 90 c = JFFS2_SB_INFO(dir_i->i_sb);
83 91
@@ -206,12 +214,15 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
206 ret = jffs2_do_create(c, dir_f, f, ri, 214 ret = jffs2_do_create(c, dir_f, f, ri,
207 dentry->d_name.name, dentry->d_name.len); 215 dentry->d_name.name, dentry->d_name.len);
208 216
209 if (ret) { 217 if (ret)
210 make_bad_inode(inode); 218 goto fail;
211 iput(inode); 219
212 jffs2_free_raw_inode(ri); 220 ret = jffs2_init_security(inode, dir_i);
213 return ret; 221 if (ret)
214 } 222 goto fail;
223 ret = jffs2_init_acl(inode, dir_i);
224 if (ret)
225 goto fail;
215 226
216 dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime)); 227 dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
217 228
@@ -221,6 +232,12 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
221 D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n", 232 D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n",
222 inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages)); 233 inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages));
223 return 0; 234 return 0;
235
236 fail:
237 make_bad_inode(inode);
238 iput(inode);
239 jffs2_free_raw_inode(ri);
240 return ret;
224} 241}
225 242
226/***********************************************************************/ 243/***********************************************************************/
@@ -291,7 +308,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
291 struct jffs2_full_dnode *fn; 308 struct jffs2_full_dnode *fn;
292 struct jffs2_full_dirent *fd; 309 struct jffs2_full_dirent *fd;
293 int namelen; 310 int namelen;
294 uint32_t alloclen, phys_ofs; 311 uint32_t alloclen;
295 int ret, targetlen = strlen(target); 312 int ret, targetlen = strlen(target);
296 313
297 /* FIXME: If you care. We'd need to use frags for the target 314 /* FIXME: If you care. We'd need to use frags for the target
@@ -310,8 +327,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
310 * Just the node will do for now, though 327 * Just the node will do for now, though
311 */ 328 */
312 namelen = dentry->d_name.len; 329 namelen = dentry->d_name.len;
313 ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen, 330 ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &alloclen,
314 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); 331 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
315 332
316 if (ret) { 333 if (ret) {
317 jffs2_free_raw_inode(ri); 334 jffs2_free_raw_inode(ri);
@@ -339,7 +356,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
339 ri->data_crc = cpu_to_je32(crc32(0, target, targetlen)); 356 ri->data_crc = cpu_to_je32(crc32(0, target, targetlen));
340 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 357 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
341 358
342 fn = jffs2_write_dnode(c, f, ri, target, targetlen, phys_ofs, ALLOC_NORMAL); 359 fn = jffs2_write_dnode(c, f, ri, target, targetlen, ALLOC_NORMAL);
343 360
344 jffs2_free_raw_inode(ri); 361 jffs2_free_raw_inode(ri);
345 362
@@ -371,8 +388,20 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
371 up(&f->sem); 388 up(&f->sem);
372 389
373 jffs2_complete_reservation(c); 390 jffs2_complete_reservation(c);
374 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, 391
375 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 392 ret = jffs2_init_security(inode, dir_i);
393 if (ret) {
394 jffs2_clear_inode(inode);
395 return ret;
396 }
397 ret = jffs2_init_acl(inode, dir_i);
398 if (ret) {
399 jffs2_clear_inode(inode);
400 return ret;
401 }
402
403 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
404 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
376 if (ret) { 405 if (ret) {
377 /* Eep. */ 406 /* Eep. */
378 jffs2_clear_inode(inode); 407 jffs2_clear_inode(inode);
@@ -404,7 +433,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
404 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); 433 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
405 rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); 434 rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
406 435
407 fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); 436 fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL);
408 437
409 if (IS_ERR(fd)) { 438 if (IS_ERR(fd)) {
410 /* dirent failed to write. Delete the inode normally 439 /* dirent failed to write. Delete the inode normally
@@ -442,7 +471,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
442 struct jffs2_full_dnode *fn; 471 struct jffs2_full_dnode *fn;
443 struct jffs2_full_dirent *fd; 472 struct jffs2_full_dirent *fd;
444 int namelen; 473 int namelen;
445 uint32_t alloclen, phys_ofs; 474 uint32_t alloclen;
446 int ret; 475 int ret;
447 476
448 mode |= S_IFDIR; 477 mode |= S_IFDIR;
@@ -457,8 +486,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
457 * Just the node will do for now, though 486 * Just the node will do for now, though
458 */ 487 */
459 namelen = dentry->d_name.len; 488 namelen = dentry->d_name.len;
460 ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, 489 ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
461 JFFS2_SUMMARY_INODE_SIZE); 490 JFFS2_SUMMARY_INODE_SIZE);
462 491
463 if (ret) { 492 if (ret) {
464 jffs2_free_raw_inode(ri); 493 jffs2_free_raw_inode(ri);
@@ -483,7 +512,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
483 ri->data_crc = cpu_to_je32(0); 512 ri->data_crc = cpu_to_je32(0);
484 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 513 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
485 514
486 fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); 515 fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
487 516
488 jffs2_free_raw_inode(ri); 517 jffs2_free_raw_inode(ri);
489 518
@@ -501,8 +530,20 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
501 up(&f->sem); 530 up(&f->sem);
502 531
503 jffs2_complete_reservation(c); 532 jffs2_complete_reservation(c);
504 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, 533
505 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 534 ret = jffs2_init_security(inode, dir_i);
535 if (ret) {
536 jffs2_clear_inode(inode);
537 return ret;
538 }
539 ret = jffs2_init_acl(inode, dir_i);
540 if (ret) {
541 jffs2_clear_inode(inode);
542 return ret;
543 }
544
545 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
546 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
506 if (ret) { 547 if (ret) {
507 /* Eep. */ 548 /* Eep. */
508 jffs2_clear_inode(inode); 549 jffs2_clear_inode(inode);
@@ -534,7 +575,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
534 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); 575 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
535 rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); 576 rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
536 577
537 fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); 578 fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL);
538 579
539 if (IS_ERR(fd)) { 580 if (IS_ERR(fd)) {
540 /* dirent failed to write. Delete the inode normally 581 /* dirent failed to write. Delete the inode normally
@@ -588,12 +629,12 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
588 struct jffs2_full_dnode *fn; 629 struct jffs2_full_dnode *fn;
589 struct jffs2_full_dirent *fd; 630 struct jffs2_full_dirent *fd;
590 int namelen; 631 int namelen;
591 jint16_t dev; 632 union jffs2_device_node dev;
592 int devlen = 0; 633 int devlen = 0;
593 uint32_t alloclen, phys_ofs; 634 uint32_t alloclen;
594 int ret; 635 int ret;
595 636
596 if (!old_valid_dev(rdev)) 637 if (!new_valid_dev(rdev))
597 return -EINVAL; 638 return -EINVAL;
598 639
599 ri = jffs2_alloc_raw_inode(); 640 ri = jffs2_alloc_raw_inode();
@@ -602,17 +643,15 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
602 643
603 c = JFFS2_SB_INFO(dir_i->i_sb); 644 c = JFFS2_SB_INFO(dir_i->i_sb);
604 645
605 if (S_ISBLK(mode) || S_ISCHR(mode)) { 646 if (S_ISBLK(mode) || S_ISCHR(mode))
606 dev = cpu_to_je16(old_encode_dev(rdev)); 647 devlen = jffs2_encode_dev(&dev, rdev);
607 devlen = sizeof(dev);
608 }
609 648
610 /* Try to reserve enough space for both node and dirent. 649 /* Try to reserve enough space for both node and dirent.
611 * Just the node will do for now, though 650 * Just the node will do for now, though
612 */ 651 */
613 namelen = dentry->d_name.len; 652 namelen = dentry->d_name.len;
614 ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, 653 ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &alloclen,
615 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); 654 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
616 655
617 if (ret) { 656 if (ret) {
618 jffs2_free_raw_inode(ri); 657 jffs2_free_raw_inode(ri);
@@ -639,7 +678,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
639 ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen)); 678 ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen));
640 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 679 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
641 680
642 fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, ALLOC_NORMAL); 681 fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, ALLOC_NORMAL);
643 682
644 jffs2_free_raw_inode(ri); 683 jffs2_free_raw_inode(ri);
645 684
@@ -657,8 +696,20 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
657 up(&f->sem); 696 up(&f->sem);
658 697
659 jffs2_complete_reservation(c); 698 jffs2_complete_reservation(c);
660 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, 699
661 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 700 ret = jffs2_init_security(inode, dir_i);
701 if (ret) {
702 jffs2_clear_inode(inode);
703 return ret;
704 }
705 ret = jffs2_init_acl(inode, dir_i);
706 if (ret) {
707 jffs2_clear_inode(inode);
708 return ret;
709 }
710
711 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
712 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
662 if (ret) { 713 if (ret) {
663 /* Eep. */ 714 /* Eep. */
664 jffs2_clear_inode(inode); 715 jffs2_clear_inode(inode);
@@ -693,7 +744,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
693 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); 744 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
694 rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); 745 rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
695 746
696 fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); 747 fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL);
697 748
698 if (IS_ERR(fd)) { 749 if (IS_ERR(fd)) {
699 /* dirent failed to write. Delete the inode normally 750 /* dirent failed to write. Delete the inode normally
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index dad68fdffe9e..1862e8bc101d 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -30,7 +30,6 @@ static void jffs2_erase_callback(struct erase_info *);
30#endif 30#endif
31static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset); 31static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset);
32static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); 32static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
33static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
34static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); 33static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
35 34
36static void jffs2_erase_block(struct jffs2_sb_info *c, 35static void jffs2_erase_block(struct jffs2_sb_info *c,
@@ -136,7 +135,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
136 c->used_size -= jeb->used_size; 135 c->used_size -= jeb->used_size;
137 c->dirty_size -= jeb->dirty_size; 136 c->dirty_size -= jeb->dirty_size;
138 jeb->wasted_size = jeb->used_size = jeb->dirty_size = jeb->free_size = 0; 137 jeb->wasted_size = jeb->used_size = jeb->dirty_size = jeb->free_size = 0;
139 jffs2_free_all_node_refs(c, jeb); 138 jffs2_free_jeb_node_refs(c, jeb);
140 list_add(&jeb->list, &c->erasing_list); 139 list_add(&jeb->list, &c->erasing_list);
141 spin_unlock(&c->erase_completion_lock); 140 spin_unlock(&c->erase_completion_lock);
142 141
@@ -231,6 +230,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
231 at the end of the linked list. Stash it and continue 230 at the end of the linked list. Stash it and continue
232 from the beginning of the list */ 231 from the beginning of the list */
233 ic = (struct jffs2_inode_cache *)(*prev); 232 ic = (struct jffs2_inode_cache *)(*prev);
233 BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
234 prev = &ic->nodes; 234 prev = &ic->nodes;
235 continue; 235 continue;
236 } 236 }
@@ -283,22 +283,27 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
283 jffs2_del_ino_cache(c, ic); 283 jffs2_del_ino_cache(c, ic);
284} 284}
285 285
286static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 286void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
287{ 287{
288 struct jffs2_raw_node_ref *ref; 288 struct jffs2_raw_node_ref *block, *ref;
289 D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset)); 289 D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset));
290 while(jeb->first_node) {
291 ref = jeb->first_node;
292 jeb->first_node = ref->next_phys;
293 290
294 /* Remove from the inode-list */ 291 block = ref = jeb->first_node;
295 if (ref->next_in_ino) 292
293 while (ref) {
294 if (ref->flash_offset == REF_LINK_NODE) {
295 ref = ref->next_in_ino;
296 jffs2_free_refblock(block);
297 block = ref;
298 continue;
299 }
300 if (ref->flash_offset != REF_EMPTY_NODE && ref->next_in_ino)
296 jffs2_remove_node_refs_from_ino_list(c, ref, jeb); 301 jffs2_remove_node_refs_from_ino_list(c, ref, jeb);
297 /* else it was a non-inode node or already removed, so don't bother */ 302 /* else it was a non-inode node or already removed, so don't bother */
298 303
299 jffs2_free_raw_node_ref(ref); 304 ref++;
300 } 305 }
301 jeb->last_node = NULL; 306 jeb->first_node = jeb->last_node = NULL;
302} 307}
303 308
304static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *bad_offset) 309static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *bad_offset)
@@ -351,7 +356,6 @@ fail:
351 356
352static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 357static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
353{ 358{
354 struct jffs2_raw_node_ref *marker_ref = NULL;
355 size_t retlen; 359 size_t retlen;
356 int ret; 360 int ret;
357 uint32_t bad_offset; 361 uint32_t bad_offset;
@@ -373,12 +377,8 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
373 goto filebad; 377 goto filebad;
374 } 378 }
375 379
376 jeb->first_node = jeb->last_node = NULL; 380 /* Everything else got zeroed before the erase */
377 jeb->free_size = c->sector_size; 381 jeb->free_size = c->sector_size;
378 jeb->used_size = 0;
379 jeb->dirty_size = 0;
380 jeb->wasted_size = 0;
381
382 } else { 382 } else {
383 383
384 struct kvec vecs[1]; 384 struct kvec vecs[1];
@@ -388,11 +388,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
388 .totlen = cpu_to_je32(c->cleanmarker_size) 388 .totlen = cpu_to_je32(c->cleanmarker_size)
389 }; 389 };
390 390
391 marker_ref = jffs2_alloc_raw_node_ref(); 391 jffs2_prealloc_raw_node_refs(c, jeb, 1);
392 if (!marker_ref) {
393 printk(KERN_WARNING "Failed to allocate raw node ref for clean marker. Refiling\n");
394 goto refile;
395 }
396 392
397 marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); 393 marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4));
398 394
@@ -408,21 +404,13 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
408 printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n", 404 printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n",
409 jeb->offset, sizeof(marker), retlen); 405 jeb->offset, sizeof(marker), retlen);
410 406
411 jffs2_free_raw_node_ref(marker_ref);
412 goto filebad; 407 goto filebad;
413 } 408 }
414 409
415 marker_ref->next_in_ino = NULL; 410 /* Everything else got zeroed before the erase */
416 marker_ref->next_phys = NULL; 411 jeb->free_size = c->sector_size;
417 marker_ref->flash_offset = jeb->offset | REF_NORMAL; 412 /* FIXME Special case for cleanmarker in empty block */
418 marker_ref->__totlen = c->cleanmarker_size; 413 jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
419
420 jeb->first_node = jeb->last_node = marker_ref;
421
422 jeb->free_size = c->sector_size - c->cleanmarker_size;
423 jeb->used_size = c->cleanmarker_size;
424 jeb->dirty_size = 0;
425 jeb->wasted_size = 0;
426 } 414 }
427 415
428 spin_lock(&c->erase_completion_lock); 416 spin_lock(&c->erase_completion_lock);
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 9f4171213e58..bb8844f40e48 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -54,7 +54,12 @@ const struct file_operations jffs2_file_operations =
54 54
55struct inode_operations jffs2_file_inode_operations = 55struct inode_operations jffs2_file_inode_operations =
56{ 56{
57 .setattr = jffs2_setattr 57 .permission = jffs2_permission,
58 .setattr = jffs2_setattr,
59 .setxattr = jffs2_setxattr,
60 .getxattr = jffs2_getxattr,
61 .listxattr = jffs2_listxattr,
62 .removexattr = jffs2_removexattr
58}; 63};
59 64
60struct address_space_operations jffs2_file_address_operations = 65struct address_space_operations jffs2_file_address_operations =
@@ -129,13 +134,13 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg,
129 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 134 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
130 struct jffs2_raw_inode ri; 135 struct jffs2_raw_inode ri;
131 struct jffs2_full_dnode *fn; 136 struct jffs2_full_dnode *fn;
132 uint32_t phys_ofs, alloc_len; 137 uint32_t alloc_len;
133 138
134 D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", 139 D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
135 (unsigned int)inode->i_size, pageofs)); 140 (unsigned int)inode->i_size, pageofs));
136 141
137 ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len, 142 ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
138 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); 143 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
139 if (ret) 144 if (ret)
140 return ret; 145 return ret;
141 146
@@ -161,7 +166,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg,
161 ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); 166 ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
162 ri.data_crc = cpu_to_je32(0); 167 ri.data_crc = cpu_to_je32(0);
163 168
164 fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_NORMAL); 169 fn = jffs2_write_dnode(c, f, &ri, NULL, 0, ALLOC_NORMAL);
165 170
166 if (IS_ERR(fn)) { 171 if (IS_ERR(fn)) {
167 ret = PTR_ERR(fn); 172 ret = PTR_ERR(fn);
@@ -215,12 +220,20 @@ static int jffs2_commit_write (struct file *filp, struct page *pg,
215 D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n", 220 D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n",
216 inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags)); 221 inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags));
217 222
218 if (!start && end == PAGE_CACHE_SIZE) { 223 if (end == PAGE_CACHE_SIZE) {
219 /* We need to avoid deadlock with page_cache_read() in 224 if (!start) {
220 jffs2_garbage_collect_pass(). So we have to mark the 225 /* We need to avoid deadlock with page_cache_read() in
221 page up to date, to prevent page_cache_read() from 226 jffs2_garbage_collect_pass(). So we have to mark the
222 trying to re-lock it. */ 227 page up to date, to prevent page_cache_read() from
223 SetPageUptodate(pg); 228 trying to re-lock it. */
229 SetPageUptodate(pg);
230 } else {
231 /* When writing out the end of a page, write out the
232 _whole_ page. This helps to reduce the number of
233 nodes in files which have many short writes, like
234 syslog files. */
235 start = aligned_start = 0;
236 }
224 } 237 }
225 238
226 ri = jffs2_alloc_raw_inode(); 239 ri = jffs2_alloc_raw_inode();
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 09e5d10b8840..2900ec3ec3af 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -33,11 +33,11 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
33 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 33 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
34 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 34 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
35 struct jffs2_raw_inode *ri; 35 struct jffs2_raw_inode *ri;
36 unsigned short dev; 36 union jffs2_device_node dev;
37 unsigned char *mdata = NULL; 37 unsigned char *mdata = NULL;
38 int mdatalen = 0; 38 int mdatalen = 0;
39 unsigned int ivalid; 39 unsigned int ivalid;
40 uint32_t phys_ofs, alloclen; 40 uint32_t alloclen;
41 int ret; 41 int ret;
42 D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); 42 D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino));
43 ret = inode_change_ok(inode, iattr); 43 ret = inode_change_ok(inode, iattr);
@@ -51,20 +51,24 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
51 it out again with the appropriate data attached */ 51 it out again with the appropriate data attached */
52 if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { 52 if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
53 /* For these, we don't actually need to read the old node */ 53 /* For these, we don't actually need to read the old node */
54 dev = old_encode_dev(inode->i_rdev); 54 mdatalen = jffs2_encode_dev(&dev, inode->i_rdev);
55 mdata = (char *)&dev; 55 mdata = (char *)&dev;
56 mdatalen = sizeof(dev);
57 D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen)); 56 D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));
58 } else if (S_ISLNK(inode->i_mode)) { 57 } else if (S_ISLNK(inode->i_mode)) {
58 down(&f->sem);
59 mdatalen = f->metadata->size; 59 mdatalen = f->metadata->size;
60 mdata = kmalloc(f->metadata->size, GFP_USER); 60 mdata = kmalloc(f->metadata->size, GFP_USER);
61 if (!mdata) 61 if (!mdata) {
62 up(&f->sem);
62 return -ENOMEM; 63 return -ENOMEM;
64 }
63 ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen); 65 ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);
64 if (ret) { 66 if (ret) {
67 up(&f->sem);
65 kfree(mdata); 68 kfree(mdata);
66 return ret; 69 return ret;
67 } 70 }
71 up(&f->sem);
68 D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen)); 72 D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen));
69 } 73 }
70 74
@@ -75,8 +79,8 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
75 return -ENOMEM; 79 return -ENOMEM;
76 } 80 }
77 81
78 ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, 82 ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &alloclen,
79 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); 83 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
80 if (ret) { 84 if (ret) {
81 jffs2_free_raw_inode(ri); 85 jffs2_free_raw_inode(ri);
82 if (S_ISLNK(inode->i_mode & S_IFMT)) 86 if (S_ISLNK(inode->i_mode & S_IFMT))
@@ -127,7 +131,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
127 else 131 else
128 ri->data_crc = cpu_to_je32(0); 132 ri->data_crc = cpu_to_je32(0);
129 133
130 new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, phys_ofs, ALLOC_NORMAL); 134 new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, ALLOC_NORMAL);
131 if (S_ISLNK(inode->i_mode)) 135 if (S_ISLNK(inode->i_mode))
132 kfree(mdata); 136 kfree(mdata);
133 137
@@ -180,12 +184,17 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
180 184
181int jffs2_setattr(struct dentry *dentry, struct iattr *iattr) 185int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
182{ 186{
183 return jffs2_do_setattr(dentry->d_inode, iattr); 187 int rc;
188
189 rc = jffs2_do_setattr(dentry->d_inode, iattr);
190 if (!rc && (iattr->ia_valid & ATTR_MODE))
191 rc = jffs2_acl_chmod(dentry->d_inode);
192 return rc;
184} 193}
185 194
186int jffs2_statfs(struct super_block *sb, struct kstatfs *buf) 195int jffs2_statfs(struct dentry *dentry, struct kstatfs *buf)
187{ 196{
188 struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); 197 struct jffs2_sb_info *c = JFFS2_SB_INFO(dentry->d_sb);
189 unsigned long avail; 198 unsigned long avail;
190 199
191 buf->f_type = JFFS2_SUPER_MAGIC; 200 buf->f_type = JFFS2_SUPER_MAGIC;
@@ -219,6 +228,7 @@ void jffs2_clear_inode (struct inode *inode)
219 228
220 D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); 229 D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));
221 230
231 jffs2_xattr_delete_inode(c, f->inocache);
222 jffs2_do_clear_inode(c, f); 232 jffs2_do_clear_inode(c, f);
223} 233}
224 234
@@ -227,6 +237,8 @@ void jffs2_read_inode (struct inode *inode)
227 struct jffs2_inode_info *f; 237 struct jffs2_inode_info *f;
228 struct jffs2_sb_info *c; 238 struct jffs2_sb_info *c;
229 struct jffs2_raw_inode latest_node; 239 struct jffs2_raw_inode latest_node;
240 union jffs2_device_node jdev;
241 dev_t rdev = 0;
230 int ret; 242 int ret;
231 243
232 D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); 244 D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
@@ -258,7 +270,6 @@ void jffs2_read_inode (struct inode *inode)
258 inode->i_blocks = (inode->i_size + 511) >> 9; 270 inode->i_blocks = (inode->i_size + 511) >> 9;
259 271
260 switch (inode->i_mode & S_IFMT) { 272 switch (inode->i_mode & S_IFMT) {
261 jint16_t rdev;
262 273
263 case S_IFLNK: 274 case S_IFLNK:
264 inode->i_op = &jffs2_symlink_inode_operations; 275 inode->i_op = &jffs2_symlink_inode_operations;
@@ -292,8 +303,16 @@ void jffs2_read_inode (struct inode *inode)
292 case S_IFBLK: 303 case S_IFBLK:
293 case S_IFCHR: 304 case S_IFCHR:
294 /* Read the device numbers from the media */ 305 /* Read the device numbers from the media */
306 if (f->metadata->size != sizeof(jdev.old) &&
307 f->metadata->size != sizeof(jdev.new)) {
308 printk(KERN_NOTICE "Device node has strange size %d\n", f->metadata->size);
309 up(&f->sem);
310 jffs2_do_clear_inode(c, f);
311 make_bad_inode(inode);
312 return;
313 }
295 D1(printk(KERN_DEBUG "Reading device numbers from flash\n")); 314 D1(printk(KERN_DEBUG "Reading device numbers from flash\n"));
296 if (jffs2_read_dnode(c, f, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) { 315 if (jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size) < 0) {
297 /* Eep */ 316 /* Eep */
298 printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); 317 printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino);
299 up(&f->sem); 318 up(&f->sem);
@@ -301,12 +320,15 @@ void jffs2_read_inode (struct inode *inode)
301 make_bad_inode(inode); 320 make_bad_inode(inode);
302 return; 321 return;
303 } 322 }
323 if (f->metadata->size == sizeof(jdev.old))
324 rdev = old_decode_dev(je16_to_cpu(jdev.old));
325 else
326 rdev = new_decode_dev(je32_to_cpu(jdev.new));
304 327
305 case S_IFSOCK: 328 case S_IFSOCK:
306 case S_IFIFO: 329 case S_IFIFO:
307 inode->i_op = &jffs2_file_inode_operations; 330 inode->i_op = &jffs2_file_inode_operations;
308 init_special_inode(inode, inode->i_mode, 331 init_special_inode(inode, inode->i_mode, rdev);
309 old_decode_dev((je16_to_cpu(rdev))));
310 break; 332 break;
311 333
312 default: 334 default:
@@ -492,6 +514,8 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
492 } 514 }
493 memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *)); 515 memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *));
494 516
517 jffs2_init_xattr_subsystem(c);
518
495 if ((ret = jffs2_do_mount_fs(c))) 519 if ((ret = jffs2_do_mount_fs(c)))
496 goto out_inohash; 520 goto out_inohash;
497 521
@@ -526,6 +550,7 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
526 else 550 else
527 kfree(c->blocks); 551 kfree(c->blocks);
528 out_inohash: 552 out_inohash:
553 jffs2_clear_xattr_subsystem(c);
529 kfree(c->inocache_list); 554 kfree(c->inocache_list);
530 out_wbuf: 555 out_wbuf:
531 jffs2_flash_cleanup(c); 556 jffs2_flash_cleanup(c);
@@ -639,13 +664,6 @@ static int jffs2_flash_setup(struct jffs2_sb_info *c) {
639 return ret; 664 return ret;
640 } 665 }
641 666
642 /* add setups for other bizarre flashes here... */
643 if (jffs2_nor_ecc(c)) {
644 ret = jffs2_nor_ecc_flash_setup(c);
645 if (ret)
646 return ret;
647 }
648
649 /* and Dataflash */ 667 /* and Dataflash */
650 if (jffs2_dataflash(c)) { 668 if (jffs2_dataflash(c)) {
651 ret = jffs2_dataflash_setup(c); 669 ret = jffs2_dataflash_setup(c);
@@ -669,11 +687,6 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c) {
669 jffs2_nand_flash_cleanup(c); 687 jffs2_nand_flash_cleanup(c);
670 } 688 }
671 689
672 /* add cleanups for other bizarre flashes here... */
673 if (jffs2_nor_ecc(c)) {
674 jffs2_nor_ecc_flash_cleanup(c);
675 }
676
677 /* and DataFlash */ 690 /* and DataFlash */
678 if (jffs2_dataflash(c)) { 691 if (jffs2_dataflash(c)) {
679 jffs2_dataflash_cleanup(c); 692 jffs2_dataflash_cleanup(c);
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index f9ffece453a3..477c526d638b 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -125,6 +125,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
125 struct jffs2_eraseblock *jeb; 125 struct jffs2_eraseblock *jeb;
126 struct jffs2_raw_node_ref *raw; 126 struct jffs2_raw_node_ref *raw;
127 int ret = 0, inum, nlink; 127 int ret = 0, inum, nlink;
128 int xattr = 0;
128 129
129 if (down_interruptible(&c->alloc_sem)) 130 if (down_interruptible(&c->alloc_sem))
130 return -EINTR; 131 return -EINTR;
@@ -138,7 +139,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
138 the node CRCs etc. Do it now. */ 139 the node CRCs etc. Do it now. */
139 140
140 /* checked_ino is protected by the alloc_sem */ 141 /* checked_ino is protected by the alloc_sem */
141 if (c->checked_ino > c->highest_ino) { 142 if (c->checked_ino > c->highest_ino && xattr) {
142 printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", 143 printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n",
143 c->unchecked_size); 144 c->unchecked_size);
144 jffs2_dbg_dump_block_lists_nolock(c); 145 jffs2_dbg_dump_block_lists_nolock(c);
@@ -148,6 +149,9 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
148 149
149 spin_unlock(&c->erase_completion_lock); 150 spin_unlock(&c->erase_completion_lock);
150 151
152 if (!xattr)
153 xattr = jffs2_verify_xattr(c);
154
151 spin_lock(&c->inocache_lock); 155 spin_lock(&c->inocache_lock);
152 156
153 ic = jffs2_get_ino_cache(c, c->checked_ino++); 157 ic = jffs2_get_ino_cache(c, c->checked_ino++);
@@ -181,6 +185,10 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
181 and trigger the BUG() above while we haven't yet 185 and trigger the BUG() above while we haven't yet
182 finished checking all its nodes */ 186 finished checking all its nodes */
183 D1(printk(KERN_DEBUG "Waiting for ino #%u to finish reading\n", ic->ino)); 187 D1(printk(KERN_DEBUG "Waiting for ino #%u to finish reading\n", ic->ino));
188 /* We need to come back again for the _same_ inode. We've
189 made no progress in this case, but that should be OK */
190 c->checked_ino--;
191
184 up(&c->alloc_sem); 192 up(&c->alloc_sem);
185 sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); 193 sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
186 return 0; 194 return 0;
@@ -231,7 +239,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
231 239
232 while(ref_obsolete(raw)) { 240 while(ref_obsolete(raw)) {
233 D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw))); 241 D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw)));
234 raw = raw->next_phys; 242 raw = ref_next(raw);
235 if (unlikely(!raw)) { 243 if (unlikely(!raw)) {
236 printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n"); 244 printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n");
237 printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n", 245 printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n",
@@ -248,16 +256,37 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
248 256
249 if (!raw->next_in_ino) { 257 if (!raw->next_in_ino) {
250 /* Inode-less node. Clean marker, snapshot or something like that */ 258 /* Inode-less node. Clean marker, snapshot or something like that */
251 /* FIXME: If it's something that needs to be copied, including something
252 we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */
253 spin_unlock(&c->erase_completion_lock); 259 spin_unlock(&c->erase_completion_lock);
254 jffs2_mark_node_obsolete(c, raw); 260 if (ref_flags(raw) == REF_PRISTINE) {
261 /* It's an unknown node with JFFS2_FEATURE_RWCOMPAT_COPY */
262 jffs2_garbage_collect_pristine(c, NULL, raw);
263 } else {
264 /* Just mark it obsolete */
265 jffs2_mark_node_obsolete(c, raw);
266 }
255 up(&c->alloc_sem); 267 up(&c->alloc_sem);
256 goto eraseit_lock; 268 goto eraseit_lock;
257 } 269 }
258 270
259 ic = jffs2_raw_ref_to_ic(raw); 271 ic = jffs2_raw_ref_to_ic(raw);
260 272
273#ifdef CONFIG_JFFS2_FS_XATTR
274 /* When 'ic' refers xattr_datum/xattr_ref, this node is GCed as xattr.
275 * We can decide whether this node is inode or xattr by ic->class. */
276 if (ic->class == RAWNODE_CLASS_XATTR_DATUM
277 || ic->class == RAWNODE_CLASS_XATTR_REF) {
278 BUG_ON(raw->next_in_ino != (void *)ic);
279 spin_unlock(&c->erase_completion_lock);
280
281 if (ic->class == RAWNODE_CLASS_XATTR_DATUM) {
282 ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
283 } else {
284 ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
285 }
286 goto release_sem;
287 }
288#endif
289
261 /* We need to hold the inocache. Either the erase_completion_lock or 290 /* We need to hold the inocache. Either the erase_completion_lock or
262 the inocache_lock are sufficient; we trade down since the inocache_lock 291 the inocache_lock are sufficient; we trade down since the inocache_lock
263 causes less contention. */ 292 causes less contention. */
@@ -499,7 +528,6 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
499 struct jffs2_raw_node_ref *raw) 528 struct jffs2_raw_node_ref *raw)
500{ 529{
501 union jffs2_node_union *node; 530 union jffs2_node_union *node;
502 struct jffs2_raw_node_ref *nraw;
503 size_t retlen; 531 size_t retlen;
504 int ret; 532 int ret;
505 uint32_t phys_ofs, alloclen; 533 uint32_t phys_ofs, alloclen;
@@ -508,15 +536,16 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
508 536
509 D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw))); 537 D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw)));
510 538
511 rawlen = ref_totlen(c, c->gcblock, raw); 539 alloclen = rawlen = ref_totlen(c, c->gcblock, raw);
512 540
513 /* Ask for a small amount of space (or the totlen if smaller) because we 541 /* Ask for a small amount of space (or the totlen if smaller) because we
514 don't want to force wastage of the end of a block if splitting would 542 don't want to force wastage of the end of a block if splitting would
515 work. */ 543 work. */
516 ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + 544 if (ic && alloclen > sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN)
517 JFFS2_MIN_DATA_LEN, rawlen), &phys_ofs, &alloclen, rawlen); 545 alloclen = sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN;
518 /* this is not the exact summary size of it, 546
519 it is only an upper estimation */ 547 ret = jffs2_reserve_space_gc(c, alloclen, &alloclen, rawlen);
548 /* 'rawlen' is not the exact summary size; it is only an upper estimation */
520 549
521 if (ret) 550 if (ret)
522 return ret; 551 return ret;
@@ -580,22 +609,17 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
580 } 609 }
581 break; 610 break;
582 default: 611 default:
583 printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", 612 /* If it's inode-less, we don't _know_ what it is. Just copy it intact */
584 ref_offset(raw), je16_to_cpu(node->u.nodetype)); 613 if (ic) {
585 goto bail; 614 printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n",
586 } 615 ref_offset(raw), je16_to_cpu(node->u.nodetype));
587 616 goto bail;
588 nraw = jffs2_alloc_raw_node_ref(); 617 }
589 if (!nraw) {
590 ret = -ENOMEM;
591 goto out_node;
592 } 618 }
593 619
594 /* OK, all the CRCs are good; this node can just be copied as-is. */ 620 /* OK, all the CRCs are good; this node can just be copied as-is. */
595 retry: 621 retry:
596 nraw->flash_offset = phys_ofs; 622 phys_ofs = write_ofs(c);
597 nraw->__totlen = rawlen;
598 nraw->next_phys = NULL;
599 623
600 ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node); 624 ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node);
601 625
@@ -603,17 +627,11 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
603 printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", 627 printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n",
604 rawlen, phys_ofs, ret, retlen); 628 rawlen, phys_ofs, ret, retlen);
605 if (retlen) { 629 if (retlen) {
606 /* Doesn't belong to any inode */ 630 jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
607 nraw->next_in_ino = NULL;
608
609 nraw->flash_offset |= REF_OBSOLETE;
610 jffs2_add_physical_node_ref(c, nraw);
611 jffs2_mark_node_obsolete(c, nraw);
612 } else { 631 } else {
613 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset); 632 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", phys_ofs);
614 jffs2_free_raw_node_ref(nraw);
615 } 633 }
616 if (!retried && (nraw = jffs2_alloc_raw_node_ref())) { 634 if (!retried) {
617 /* Try to reallocate space and retry */ 635 /* Try to reallocate space and retry */
618 uint32_t dummy; 636 uint32_t dummy;
619 struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size]; 637 struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size];
@@ -625,7 +643,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
625 jffs2_dbg_acct_sanity_check(c,jeb); 643 jffs2_dbg_acct_sanity_check(c,jeb);
626 jffs2_dbg_acct_paranoia_check(c, jeb); 644 jffs2_dbg_acct_paranoia_check(c, jeb);
627 645
628 ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy, rawlen); 646 ret = jffs2_reserve_space_gc(c, rawlen, &dummy, rawlen);
629 /* this is not the exact summary size of it, 647 /* this is not the exact summary size of it,
630 it is only an upper estimation */ 648 it is only an upper estimation */
631 649
@@ -638,25 +656,13 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
638 goto retry; 656 goto retry;
639 } 657 }
640 D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); 658 D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
641 jffs2_free_raw_node_ref(nraw);
642 } 659 }
643 660
644 jffs2_free_raw_node_ref(nraw);
645 if (!ret) 661 if (!ret)
646 ret = -EIO; 662 ret = -EIO;
647 goto out_node; 663 goto out_node;
648 } 664 }
649 nraw->flash_offset |= REF_PRISTINE; 665 jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, rawlen, ic);
650 jffs2_add_physical_node_ref(c, nraw);
651
652 /* Link into per-inode list. This is safe because of the ic
653 state being INO_STATE_GC. Note that if we're doing this
654 for an inode which is in-core, the 'nraw' pointer is then
655 going to be fetched from ic->nodes by our caller. */
656 spin_lock(&c->erase_completion_lock);
657 nraw->next_in_ino = ic->nodes;
658 ic->nodes = nraw;
659 spin_unlock(&c->erase_completion_lock);
660 666
661 jffs2_mark_node_obsolete(c, raw); 667 jffs2_mark_node_obsolete(c, raw);
662 D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); 668 D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw)));
@@ -675,19 +681,16 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
675 struct jffs2_full_dnode *new_fn; 681 struct jffs2_full_dnode *new_fn;
676 struct jffs2_raw_inode ri; 682 struct jffs2_raw_inode ri;
677 struct jffs2_node_frag *last_frag; 683 struct jffs2_node_frag *last_frag;
678 jint16_t dev; 684 union jffs2_device_node dev;
679 char *mdata = NULL, mdatalen = 0; 685 char *mdata = NULL, mdatalen = 0;
680 uint32_t alloclen, phys_ofs, ilen; 686 uint32_t alloclen, ilen;
681 int ret; 687 int ret;
682 688
683 if (S_ISBLK(JFFS2_F_I_MODE(f)) || 689 if (S_ISBLK(JFFS2_F_I_MODE(f)) ||
684 S_ISCHR(JFFS2_F_I_MODE(f)) ) { 690 S_ISCHR(JFFS2_F_I_MODE(f)) ) {
685 /* For these, we don't actually need to read the old node */ 691 /* For these, we don't actually need to read the old node */
686 /* FIXME: for minor or major > 255. */ 692 mdatalen = jffs2_encode_dev(&dev, JFFS2_F_I_RDEV(f));
687 dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) |
688 JFFS2_F_I_RDEV_MIN(f)));
689 mdata = (char *)&dev; 693 mdata = (char *)&dev;
690 mdatalen = sizeof(dev);
691 D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen)); 694 D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen));
692 } else if (S_ISLNK(JFFS2_F_I_MODE(f))) { 695 } else if (S_ISLNK(JFFS2_F_I_MODE(f))) {
693 mdatalen = fn->size; 696 mdatalen = fn->size;
@@ -706,7 +709,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
706 709
707 } 710 }
708 711
709 ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen, 712 ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &alloclen,
710 JFFS2_SUMMARY_INODE_SIZE); 713 JFFS2_SUMMARY_INODE_SIZE);
711 if (ret) { 714 if (ret) {
712 printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n", 715 printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n",
@@ -744,7 +747,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
744 ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); 747 ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
745 ri.data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); 748 ri.data_crc = cpu_to_je32(crc32(0, mdata, mdatalen));
746 749
747 new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, phys_ofs, ALLOC_GC); 750 new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, ALLOC_GC);
748 751
749 if (IS_ERR(new_fn)) { 752 if (IS_ERR(new_fn)) {
750 printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn)); 753 printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn));
@@ -765,7 +768,7 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er
765{ 768{
766 struct jffs2_full_dirent *new_fd; 769 struct jffs2_full_dirent *new_fd;
767 struct jffs2_raw_dirent rd; 770 struct jffs2_raw_dirent rd;
768 uint32_t alloclen, phys_ofs; 771 uint32_t alloclen;
769 int ret; 772 int ret;
770 773
771 rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 774 rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -787,14 +790,14 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er
787 rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); 790 rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8));
788 rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); 791 rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize));
789 792
790 ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen, 793 ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &alloclen,
791 JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize)); 794 JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize));
792 if (ret) { 795 if (ret) {
793 printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n", 796 printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n",
794 sizeof(rd)+rd.nsize, ret); 797 sizeof(rd)+rd.nsize, ret);
795 return ret; 798 return ret;
796 } 799 }
797 new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, phys_ofs, ALLOC_GC); 800 new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, ALLOC_GC);
798 801
799 if (IS_ERR(new_fd)) { 802 if (IS_ERR(new_fd)) {
800 printk(KERN_WARNING "jffs2_write_dirent in garbage_collect_dirent failed: %ld\n", PTR_ERR(new_fd)); 803 printk(KERN_WARNING "jffs2_write_dirent in garbage_collect_dirent failed: %ld\n", PTR_ERR(new_fd));
@@ -922,7 +925,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras
922 struct jffs2_raw_inode ri; 925 struct jffs2_raw_inode ri;
923 struct jffs2_node_frag *frag; 926 struct jffs2_node_frag *frag;
924 struct jffs2_full_dnode *new_fn; 927 struct jffs2_full_dnode *new_fn;
925 uint32_t alloclen, phys_ofs, ilen; 928 uint32_t alloclen, ilen;
926 int ret; 929 int ret;
927 930
928 D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n", 931 D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n",
@@ -1001,14 +1004,14 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras
1001 ri.data_crc = cpu_to_je32(0); 1004 ri.data_crc = cpu_to_je32(0);
1002 ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); 1005 ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
1003 1006
1004 ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen, 1007 ret = jffs2_reserve_space_gc(c, sizeof(ri), &alloclen,
1005 JFFS2_SUMMARY_INODE_SIZE); 1008 JFFS2_SUMMARY_INODE_SIZE);
1006 if (ret) { 1009 if (ret) {
1007 printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n", 1010 printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n",
1008 sizeof(ri), ret); 1011 sizeof(ri), ret);
1009 return ret; 1012 return ret;
1010 } 1013 }
1011 new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_GC); 1014 new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, ALLOC_GC);
1012 1015
1013 if (IS_ERR(new_fn)) { 1016 if (IS_ERR(new_fn)) {
1014 printk(KERN_WARNING "Error writing new hole node: %ld\n", PTR_ERR(new_fn)); 1017 printk(KERN_WARNING "Error writing new hole node: %ld\n", PTR_ERR(new_fn));
@@ -1070,7 +1073,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
1070{ 1073{
1071 struct jffs2_full_dnode *new_fn; 1074 struct jffs2_full_dnode *new_fn;
1072 struct jffs2_raw_inode ri; 1075 struct jffs2_raw_inode ri;
1073 uint32_t alloclen, phys_ofs, offset, orig_end, orig_start; 1076 uint32_t alloclen, offset, orig_end, orig_start;
1074 int ret = 0; 1077 int ret = 0;
1075 unsigned char *comprbuf = NULL, *writebuf; 1078 unsigned char *comprbuf = NULL, *writebuf;
1076 unsigned long pg; 1079 unsigned long pg;
@@ -1227,7 +1230,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
1227 uint32_t cdatalen; 1230 uint32_t cdatalen;
1228 uint16_t comprtype = JFFS2_COMPR_NONE; 1231 uint16_t comprtype = JFFS2_COMPR_NONE;
1229 1232
1230 ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, 1233 ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN,
1231 &alloclen, JFFS2_SUMMARY_INODE_SIZE); 1234 &alloclen, JFFS2_SUMMARY_INODE_SIZE);
1232 1235
1233 if (ret) { 1236 if (ret) {
@@ -1264,7 +1267,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
1264 ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); 1267 ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
1265 ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); 1268 ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));
1266 1269
1267 new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, phys_ofs, ALLOC_GC); 1270 new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, ALLOC_GC);
1268 1271
1269 jffs2_free_comprbuf(comprbuf, writebuf); 1272 jffs2_free_comprbuf(comprbuf, writebuf);
1270 1273
diff --git a/fs/jffs2/histo.h b/fs/jffs2/histo.h
deleted file mode 100644
index 22a93a08210c..000000000000
--- a/fs/jffs2/histo.h
+++ /dev/null
@@ -1,3 +0,0 @@
1/* This file provides the bit-probabilities for the input file */
2#define BIT_DIVIDER 629
3static int bits[9] = { 179,167,183,165,159,198,178,119,}; /* ia32 .so files */
diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h
new file mode 100644
index 000000000000..2e0cc8e00b85
--- /dev/null
+++ b/fs/jffs2/jffs2_fs_i.h
@@ -0,0 +1,55 @@
1/* $Id: jffs2_fs_i.h,v 1.19 2005/11/07 11:14:52 gleixner Exp $ */
2
3#ifndef _JFFS2_FS_I
4#define _JFFS2_FS_I
5
6#include <linux/version.h>
7#include <linux/rbtree.h>
8#include <linux/posix_acl.h>
9#include <asm/semaphore.h>
10
11struct jffs2_inode_info {
12 /* We need an internal mutex similar to inode->i_mutex.
13 Unfortunately, we can't used the existing one, because
14 either the GC would deadlock, or we'd have to release it
15 before letting GC proceed. Or we'd have to put ugliness
16 into the GC code so it didn't attempt to obtain the i_mutex
17 for the inode(s) which are already locked */
18 struct semaphore sem;
19
20 /* The highest (datanode) version number used for this ino */
21 uint32_t highest_version;
22
23 /* List of data fragments which make up the file */
24 struct rb_root fragtree;
25
26 /* There may be one datanode which isn't referenced by any of the
27 above fragments, if it contains a metadata update but no actual
28 data - or if this is a directory inode */
29 /* This also holds the _only_ dnode for symlinks/device nodes,
30 etc. */
31 struct jffs2_full_dnode *metadata;
32
33 /* Directory entries */
34 struct jffs2_full_dirent *dents;
35
36 /* The target path if this is the inode of a symlink */
37 unsigned char *target;
38
39 /* Some stuff we just have to keep in-core at all times, for each inode. */
40 struct jffs2_inode_cache *inocache;
41
42 uint16_t flags;
43 uint8_t usercompr;
44#if !defined (__ECOS)
45#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2)
46 struct inode vfs_inode;
47#endif
48#endif
49#ifdef CONFIG_JFFS2_FS_POSIX_ACL
50 struct posix_acl *i_acl_access;
51 struct posix_acl *i_acl_default;
52#endif
53};
54
55#endif /* _JFFS2_FS_I */
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
new file mode 100644
index 000000000000..935fec1b1201
--- /dev/null
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -0,0 +1,133 @@
1/* $Id: jffs2_fs_sb.h,v 1.54 2005/09/21 13:37:34 dedekind Exp $ */
2
3#ifndef _JFFS2_FS_SB
4#define _JFFS2_FS_SB
5
6#include <linux/types.h>
7#include <linux/spinlock.h>
8#include <linux/workqueue.h>
9#include <linux/completion.h>
10#include <asm/semaphore.h>
11#include <linux/timer.h>
12#include <linux/wait.h>
13#include <linux/list.h>
14#include <linux/rwsem.h>
15
16#define JFFS2_SB_FLAG_RO 1
17#define JFFS2_SB_FLAG_SCANNING 2 /* Flash scanning is in progress */
18#define JFFS2_SB_FLAG_BUILDING 4 /* File system building is in progress */
19
20struct jffs2_inodirty;
21
22/* A struct for the overall file system control. Pointers to
23 jffs2_sb_info structs are named `c' in the source code.
24 Nee jffs_control
25*/
26struct jffs2_sb_info {
27 struct mtd_info *mtd;
28
29 uint32_t highest_ino;
30 uint32_t checked_ino;
31
32 unsigned int flags;
33
34 struct task_struct *gc_task; /* GC task struct */
35 struct completion gc_thread_start; /* GC thread start completion */
36 struct completion gc_thread_exit; /* GC thread exit completion port */
37
38 struct semaphore alloc_sem; /* Used to protect all the following
39 fields, and also to protect against
40 out-of-order writing of nodes. And GC. */
41 uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER
42 (i.e. zero for OOB CLEANMARKER */
43
44 uint32_t flash_size;
45 uint32_t used_size;
46 uint32_t dirty_size;
47 uint32_t wasted_size;
48 uint32_t free_size;
49 uint32_t erasing_size;
50 uint32_t bad_size;
51 uint32_t sector_size;
52 uint32_t unchecked_size;
53
54 uint32_t nr_free_blocks;
55 uint32_t nr_erasing_blocks;
56
57 /* Number of free blocks there must be before we... */
58 uint8_t resv_blocks_write; /* ... allow a normal filesystem write */
59 uint8_t resv_blocks_deletion; /* ... allow a normal filesystem deletion */
60 uint8_t resv_blocks_gctrigger; /* ... wake up the GC thread */
61 uint8_t resv_blocks_gcbad; /* ... pick a block from the bad_list to GC */
62 uint8_t resv_blocks_gcmerge; /* ... merge pages when garbage collecting */
63
64 uint32_t nospc_dirty_size;
65
66 uint32_t nr_blocks;
67 struct jffs2_eraseblock *blocks; /* The whole array of blocks. Used for getting blocks
68 * from the offset (blocks[ofs / sector_size]) */
69 struct jffs2_eraseblock *nextblock; /* The block we're currently filling */
70
71 struct jffs2_eraseblock *gcblock; /* The block we're currently garbage-collecting */
72
73 struct list_head clean_list; /* Blocks 100% full of clean data */
74 struct list_head very_dirty_list; /* Blocks with lots of dirty space */
75 struct list_head dirty_list; /* Blocks with some dirty space */
76 struct list_head erasable_list; /* Blocks which are completely dirty, and need erasing */
77 struct list_head erasable_pending_wbuf_list; /* Blocks which need erasing but only after the current wbuf is flushed */
78 struct list_head erasing_list; /* Blocks which are currently erasing */
79 struct list_head erase_pending_list; /* Blocks which need erasing now */
80 struct list_head erase_complete_list; /* Blocks which are erased and need the clean marker written to them */
81 struct list_head free_list; /* Blocks which are free and ready to be used */
82 struct list_head bad_list; /* Bad blocks. */
83 struct list_head bad_used_list; /* Bad blocks with valid data in. */
84
85 spinlock_t erase_completion_lock; /* Protect free_list and erasing_list
86 against erase completion handler */
87 wait_queue_head_t erase_wait; /* For waiting for erases to complete */
88
89 wait_queue_head_t inocache_wq;
90 struct jffs2_inode_cache **inocache_list;
91 spinlock_t inocache_lock;
92
93 /* Sem to allow jffs2_garbage_collect_deletion_dirent to
94 drop the erase_completion_lock while it's holding a pointer
95 to an obsoleted node. I don't like this. Alternatives welcomed. */
96 struct semaphore erase_free_sem;
97
98 uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
99
100#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
101 /* Write-behind buffer for NAND flash */
102 unsigned char *wbuf;
103 unsigned char *oobbuf;
104 uint32_t wbuf_ofs;
105 uint32_t wbuf_len;
106 struct jffs2_inodirty *wbuf_inodes;
107
108 struct rw_semaphore wbuf_sem; /* Protects the write buffer */
109
110 /* Information about out-of-band area usage... */
111 struct nand_ecclayout *ecclayout;
112 uint32_t badblock_pos;
113 uint32_t fsdata_pos;
114 uint32_t fsdata_len;
115#endif
116
117 struct jffs2_summary *summary; /* Summary information */
118
119#ifdef CONFIG_JFFS2_FS_XATTR
120#define XATTRINDEX_HASHSIZE (57)
121 uint32_t highest_xid;
122 struct list_head xattrindex[XATTRINDEX_HASHSIZE];
123 struct list_head xattr_unchecked;
124 struct jffs2_xattr_ref *xref_temp;
125 struct rw_semaphore xattr_sem;
126 uint32_t xdatum_mem_usage;
127 uint32_t xdatum_mem_threshold;
128#endif
129 /* OS-private pointer for getting back to master superblock info */
130 void *os_priv;
131};
132
133#endif /* _JFFS2_FB_SB */
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
index 036cbd11c004..4889d0700c0e 100644
--- a/fs/jffs2/malloc.c
+++ b/fs/jffs2/malloc.c
@@ -26,6 +26,10 @@ static kmem_cache_t *tmp_dnode_info_slab;
26static kmem_cache_t *raw_node_ref_slab; 26static kmem_cache_t *raw_node_ref_slab;
27static kmem_cache_t *node_frag_slab; 27static kmem_cache_t *node_frag_slab;
28static kmem_cache_t *inode_cache_slab; 28static kmem_cache_t *inode_cache_slab;
29#ifdef CONFIG_JFFS2_FS_XATTR
30static kmem_cache_t *xattr_datum_cache;
31static kmem_cache_t *xattr_ref_cache;
32#endif
29 33
30int __init jffs2_create_slab_caches(void) 34int __init jffs2_create_slab_caches(void)
31{ 35{
@@ -53,8 +57,8 @@ int __init jffs2_create_slab_caches(void)
53 if (!tmp_dnode_info_slab) 57 if (!tmp_dnode_info_slab)
54 goto err; 58 goto err;
55 59
56 raw_node_ref_slab = kmem_cache_create("jffs2_raw_node_ref", 60 raw_node_ref_slab = kmem_cache_create("jffs2_refblock",
57 sizeof(struct jffs2_raw_node_ref), 61 sizeof(struct jffs2_raw_node_ref) * (REFS_PER_BLOCK + 1),
58 0, 0, NULL, NULL); 62 0, 0, NULL, NULL);
59 if (!raw_node_ref_slab) 63 if (!raw_node_ref_slab)
60 goto err; 64 goto err;
@@ -68,8 +72,24 @@ int __init jffs2_create_slab_caches(void)
68 inode_cache_slab = kmem_cache_create("jffs2_inode_cache", 72 inode_cache_slab = kmem_cache_create("jffs2_inode_cache",
69 sizeof(struct jffs2_inode_cache), 73 sizeof(struct jffs2_inode_cache),
70 0, 0, NULL, NULL); 74 0, 0, NULL, NULL);
71 if (inode_cache_slab) 75 if (!inode_cache_slab)
72 return 0; 76 goto err;
77
78#ifdef CONFIG_JFFS2_FS_XATTR
79 xattr_datum_cache = kmem_cache_create("jffs2_xattr_datum",
80 sizeof(struct jffs2_xattr_datum),
81 0, 0, NULL, NULL);
82 if (!xattr_datum_cache)
83 goto err;
84
85 xattr_ref_cache = kmem_cache_create("jffs2_xattr_ref",
86 sizeof(struct jffs2_xattr_ref),
87 0, 0, NULL, NULL);
88 if (!xattr_ref_cache)
89 goto err;
90#endif
91
92 return 0;
73 err: 93 err:
74 jffs2_destroy_slab_caches(); 94 jffs2_destroy_slab_caches();
75 return -ENOMEM; 95 return -ENOMEM;
@@ -91,6 +111,12 @@ void jffs2_destroy_slab_caches(void)
91 kmem_cache_destroy(node_frag_slab); 111 kmem_cache_destroy(node_frag_slab);
92 if(inode_cache_slab) 112 if(inode_cache_slab)
93 kmem_cache_destroy(inode_cache_slab); 113 kmem_cache_destroy(inode_cache_slab);
114#ifdef CONFIG_JFFS2_FS_XATTR
115 if (xattr_datum_cache)
116 kmem_cache_destroy(xattr_datum_cache);
117 if (xattr_ref_cache)
118 kmem_cache_destroy(xattr_ref_cache);
119#endif
94} 120}
95 121
96struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize) 122struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize)
@@ -164,15 +190,65 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x)
164 kmem_cache_free(tmp_dnode_info_slab, x); 190 kmem_cache_free(tmp_dnode_info_slab, x);
165} 191}
166 192
167struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) 193struct jffs2_raw_node_ref *jffs2_alloc_refblock(void)
168{ 194{
169 struct jffs2_raw_node_ref *ret; 195 struct jffs2_raw_node_ref *ret;
196
170 ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); 197 ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL);
171 dbg_memalloc("%p\n", ret); 198 if (ret) {
199 int i = 0;
200 for (i=0; i < REFS_PER_BLOCK; i++) {
201 ret[i].flash_offset = REF_EMPTY_NODE;
202 ret[i].next_in_ino = NULL;
203 }
204 ret[i].flash_offset = REF_LINK_NODE;
205 ret[i].next_in_ino = NULL;
206 }
172 return ret; 207 return ret;
173} 208}
174 209
175void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) 210int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
211 struct jffs2_eraseblock *jeb, int nr)
212{
213 struct jffs2_raw_node_ref **p, *ref;
214 int i = nr;
215
216 dbg_memalloc("%d\n", nr);
217
218 p = &jeb->last_node;
219 ref = *p;
220
221 dbg_memalloc("Reserving %d refs for block @0x%08x\n", nr, jeb->offset);
222
223 /* If jeb->last_node is really a valid node then skip over it */
224 if (ref && ref->flash_offset != REF_EMPTY_NODE)
225 ref++;
226
227 while (i) {
228 if (!ref) {
229 dbg_memalloc("Allocating new refblock linked from %p\n", p);
230 ref = *p = jffs2_alloc_refblock();
231 if (!ref)
232 return -ENOMEM;
233 }
234 if (ref->flash_offset == REF_LINK_NODE) {
235 p = &ref->next_in_ino;
236 ref = *p;
237 continue;
238 }
239 i--;
240 ref++;
241 }
242 jeb->allocated_refs = nr;
243
244 dbg_memalloc("Reserved %d refs for block @0x%08x, last_node is %p (%08x,%p)\n",
245 nr, jeb->offset, jeb->last_node, jeb->last_node->flash_offset,
246 jeb->last_node->next_in_ino);
247
248 return 0;
249}
250
251void jffs2_free_refblock(struct jffs2_raw_node_ref *x)
176{ 252{
177 dbg_memalloc("%p\n", x); 253 dbg_memalloc("%p\n", x);
178 kmem_cache_free(raw_node_ref_slab, x); 254 kmem_cache_free(raw_node_ref_slab, x);
@@ -205,3 +281,40 @@ void jffs2_free_inode_cache(struct jffs2_inode_cache *x)
205 dbg_memalloc("%p\n", x); 281 dbg_memalloc("%p\n", x);
206 kmem_cache_free(inode_cache_slab, x); 282 kmem_cache_free(inode_cache_slab, x);
207} 283}
284
285#ifdef CONFIG_JFFS2_FS_XATTR
286struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void)
287{
288 struct jffs2_xattr_datum *xd;
289 xd = kmem_cache_alloc(xattr_datum_cache, GFP_KERNEL);
290 dbg_memalloc("%p\n", xd);
291
292 memset(xd, 0, sizeof(struct jffs2_xattr_datum));
293 xd->class = RAWNODE_CLASS_XATTR_DATUM;
294 INIT_LIST_HEAD(&xd->xindex);
295 return xd;
296}
297
298void jffs2_free_xattr_datum(struct jffs2_xattr_datum *xd)
299{
300 dbg_memalloc("%p\n", xd);
301 kmem_cache_free(xattr_datum_cache, xd);
302}
303
304struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
305{
306 struct jffs2_xattr_ref *ref;
307 ref = kmem_cache_alloc(xattr_ref_cache, GFP_KERNEL);
308 dbg_memalloc("%p\n", ref);
309
310 memset(ref, 0, sizeof(struct jffs2_xattr_ref));
311 ref->class = RAWNODE_CLASS_XATTR_REF;
312 return ref;
313}
314
315void jffs2_free_xattr_ref(struct jffs2_xattr_ref *ref)
316{
317 dbg_memalloc("%p\n", ref);
318 kmem_cache_free(xattr_ref_cache, ref);
319}
320#endif
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 1d46677afd17..927dfe42ba76 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -438,8 +438,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
438 if (c->mtd->point) { 438 if (c->mtd->point) {
439 err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer); 439 err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
440 if (!err && retlen < tn->csize) { 440 if (!err && retlen < tn->csize) {
441 JFFS2_WARNING("MTD point returned len too short: %zu " 441 JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
442 "instead of %u.\n", retlen, tn->csize);
443 c->mtd->unpoint(c->mtd, buffer, ofs, len); 442 c->mtd->unpoint(c->mtd, buffer, ofs, len);
444 } else if (err) 443 } else if (err)
445 JFFS2_WARNING("MTD point failed: error code %d.\n", err); 444 JFFS2_WARNING("MTD point failed: error code %d.\n", err);
@@ -462,8 +461,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
462 } 461 }
463 462
464 if (retlen != len) { 463 if (retlen != len) {
465 JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", 464 JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len);
466 ofs, retlen, len);
467 err = -EIO; 465 err = -EIO;
468 goto free_out; 466 goto free_out;
469 } 467 }
@@ -940,6 +938,7 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c)
940 this = c->inocache_list[i]; 938 this = c->inocache_list[i];
941 while (this) { 939 while (this) {
942 next = this->next; 940 next = this->next;
941 jffs2_xattr_free_inode(c, this);
943 jffs2_free_inode_cache(this); 942 jffs2_free_inode_cache(this);
944 this = next; 943 this = next;
945 } 944 }
@@ -954,9 +953,13 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c)
954 953
955 for (i=0; i<c->nr_blocks; i++) { 954 for (i=0; i<c->nr_blocks; i++) {
956 this = c->blocks[i].first_node; 955 this = c->blocks[i].first_node;
957 while(this) { 956 while (this) {
958 next = this->next_phys; 957 if (this[REFS_PER_BLOCK].flash_offset == REF_LINK_NODE)
959 jffs2_free_raw_node_ref(this); 958 next = this[REFS_PER_BLOCK].next_in_ino;
959 else
960 next = NULL;
961
962 jffs2_free_refblock(this);
960 this = next; 963 this = next;
961 } 964 }
962 c->blocks[i].first_node = c->blocks[i].last_node = NULL; 965 c->blocks[i].first_node = c->blocks[i].last_node = NULL;
@@ -1047,3 +1050,169 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c)
1047 cond_resched(); 1050 cond_resched();
1048 } 1051 }
1049} 1052}
1053
1054struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
1055 struct jffs2_eraseblock *jeb,
1056 uint32_t ofs, uint32_t len,
1057 struct jffs2_inode_cache *ic)
1058{
1059 struct jffs2_raw_node_ref *ref;
1060
1061 BUG_ON(!jeb->allocated_refs);
1062 jeb->allocated_refs--;
1063
1064 ref = jeb->last_node;
1065
1066 dbg_noderef("Last node at %p is (%08x,%p)\n", ref, ref->flash_offset,
1067 ref->next_in_ino);
1068
1069 while (ref->flash_offset != REF_EMPTY_NODE) {
1070 if (ref->flash_offset == REF_LINK_NODE)
1071 ref = ref->next_in_ino;
1072 else
1073 ref++;
1074 }
1075
1076 dbg_noderef("New ref is %p (%08x becomes %08x,%p) len 0x%x\n", ref,
1077 ref->flash_offset, ofs, ref->next_in_ino, len);
1078
1079 ref->flash_offset = ofs;
1080
1081 if (!jeb->first_node) {
1082 jeb->first_node = ref;
1083 BUG_ON(ref_offset(ref) != jeb->offset);
1084 } else if (unlikely(ref_offset(ref) != jeb->offset + c->sector_size - jeb->free_size)) {
1085 uint32_t last_len = ref_totlen(c, jeb, jeb->last_node);
1086
1087 JFFS2_ERROR("Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n",
1088 ref, ref_offset(ref), ref_offset(ref)+len,
1089 ref_offset(jeb->last_node),
1090 ref_offset(jeb->last_node)+last_len);
1091 BUG();
1092 }
1093 jeb->last_node = ref;
1094
1095 if (ic) {
1096 ref->next_in_ino = ic->nodes;
1097 ic->nodes = ref;
1098 } else {
1099 ref->next_in_ino = NULL;
1100 }
1101
1102 switch(ref_flags(ref)) {
1103 case REF_UNCHECKED:
1104 c->unchecked_size += len;
1105 jeb->unchecked_size += len;
1106 break;
1107
1108 case REF_NORMAL:
1109 case REF_PRISTINE:
1110 c->used_size += len;
1111 jeb->used_size += len;
1112 break;
1113
1114 case REF_OBSOLETE:
1115 c->dirty_size += len;
1116 jeb->dirty_size += len;
1117 break;
1118 }
1119 c->free_size -= len;
1120 jeb->free_size -= len;
1121
1122#ifdef TEST_TOTLEN
1123 /* Set (and test) __totlen field... for now */
1124 ref->__totlen = len;
1125 ref_totlen(c, jeb, ref);
1126#endif
1127 return ref;
1128}
1129
1130/* No locking, no reservation of 'ref'. Do not use on a live file system */
1131int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
1132 uint32_t size)
1133{
1134 if (!size)
1135 return 0;
1136 if (unlikely(size > jeb->free_size)) {
1137 printk(KERN_CRIT "Dirty space 0x%x larger then free_size 0x%x (wasted 0x%x)\n",
1138 size, jeb->free_size, jeb->wasted_size);
1139 BUG();
1140 }
1141 /* REF_EMPTY_NODE is !obsolete, so that works OK */
1142 if (jeb->last_node && ref_obsolete(jeb->last_node)) {
1143#ifdef TEST_TOTLEN
1144 jeb->last_node->__totlen += size;
1145#endif
1146 c->dirty_size += size;
1147 c->free_size -= size;
1148 jeb->dirty_size += size;
1149 jeb->free_size -= size;
1150 } else {
1151 uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size;
1152 ofs |= REF_OBSOLETE;
1153
1154 jffs2_link_node_ref(c, jeb, ofs, size, NULL);
1155 }
1156
1157 return 0;
1158}
1159
1160/* Calculate totlen from surrounding nodes or eraseblock */
1161static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
1162 struct jffs2_eraseblock *jeb,
1163 struct jffs2_raw_node_ref *ref)
1164{
1165 uint32_t ref_end;
1166 struct jffs2_raw_node_ref *next_ref = ref_next(ref);
1167
1168 if (next_ref)
1169 ref_end = ref_offset(next_ref);
1170 else {
1171 if (!jeb)
1172 jeb = &c->blocks[ref->flash_offset / c->sector_size];
1173
1174 /* Last node in block. Use free_space */
1175 if (unlikely(ref != jeb->last_node)) {
1176 printk(KERN_CRIT "ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n",
1177 ref, ref_offset(ref), jeb->last_node, jeb->last_node?ref_offset(jeb->last_node):0);
1178 BUG();
1179 }
1180 ref_end = jeb->offset + c->sector_size - jeb->free_size;
1181 }
1182 return ref_end - ref_offset(ref);
1183}
1184
1185uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
1186 struct jffs2_raw_node_ref *ref)
1187{
1188 uint32_t ret;
1189
1190 ret = __ref_totlen(c, jeb, ref);
1191
1192#ifdef TEST_TOTLEN
1193 if (unlikely(ret != ref->__totlen)) {
1194 if (!jeb)
1195 jeb = &c->blocks[ref->flash_offset / c->sector_size];
1196
1197 printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
1198 ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
1199 ret, ref->__totlen);
1200 if (ref_next(ref)) {
1201 printk(KERN_CRIT "next %p (0x%08x-0x%08x)\n", ref_next(ref), ref_offset(ref_next(ref)),
1202 ref_offset(ref_next(ref))+ref->__totlen);
1203 } else
1204 printk(KERN_CRIT "No next ref. jeb->last_node is %p\n", jeb->last_node);
1205
1206 printk(KERN_CRIT "jeb->wasted_size %x, dirty_size %x, used_size %x, free_size %x\n", jeb->wasted_size, jeb->dirty_size, jeb->used_size, jeb->free_size);
1207
1208#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
1209 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
1210#endif
1211
1212 WARN_ON(1);
1213
1214 ret = ref->__totlen;
1215 }
1216#endif /* TEST_TOTLEN */
1217 return ret;
1218}
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 23a67bb3052f..b16c60bbcf6e 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -18,8 +18,10 @@
18#include <linux/fs.h> 18#include <linux/fs.h>
19#include <linux/types.h> 19#include <linux/types.h>
20#include <linux/jffs2.h> 20#include <linux/jffs2.h>
21#include <linux/jffs2_fs_sb.h> 21#include "jffs2_fs_sb.h"
22#include <linux/jffs2_fs_i.h> 22#include "jffs2_fs_i.h"
23#include "xattr.h"
24#include "acl.h"
23#include "summary.h" 25#include "summary.h"
24 26
25#ifdef __ECOS 27#ifdef __ECOS
@@ -75,14 +77,50 @@
75struct jffs2_raw_node_ref 77struct jffs2_raw_node_ref
76{ 78{
77 struct jffs2_raw_node_ref *next_in_ino; /* Points to the next raw_node_ref 79 struct jffs2_raw_node_ref *next_in_ino; /* Points to the next raw_node_ref
78 for this inode. If this is the last, it points to the inode_cache 80 for this object. If this _is_ the last, it points to the inode_cache,
79 for this inode instead. The inode_cache will have NULL in the first 81 xattr_ref or xattr_datum instead. The common part of those structures
80 word so you know when you've got there :) */ 82 has NULL in the first word. See jffs2_raw_ref_to_ic() below */
81 struct jffs2_raw_node_ref *next_phys;
82 uint32_t flash_offset; 83 uint32_t flash_offset;
84#define TEST_TOTLEN
85#ifdef TEST_TOTLEN
83 uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */ 86 uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */
87#endif
84}; 88};
85 89
90#define REF_LINK_NODE ((int32_t)-1)
91#define REF_EMPTY_NODE ((int32_t)-2)
92
93/* Use blocks of about 256 bytes */
94#define REFS_PER_BLOCK ((255/sizeof(struct jffs2_raw_node_ref))-1)
95
96static inline struct jffs2_raw_node_ref *ref_next(struct jffs2_raw_node_ref *ref)
97{
98 ref++;
99
100 /* Link to another block of refs */
101 if (ref->flash_offset == REF_LINK_NODE) {
102 ref = ref->next_in_ino;
103 if (!ref)
104 return ref;
105 }
106
107 /* End of chain */
108 if (ref->flash_offset == REF_EMPTY_NODE)
109 return NULL;
110
111 return ref;
112}
113
114static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
115{
116 while(raw->next_in_ino)
117 raw = raw->next_in_ino;
118
119 /* NB. This can be a jffs2_xattr_datum or jffs2_xattr_ref and
120 not actually a jffs2_inode_cache. Check ->class */
121 return ((struct jffs2_inode_cache *)raw);
122}
123
86 /* flash_offset & 3 always has to be zero, because nodes are 124 /* flash_offset & 3 always has to be zero, because nodes are
87 always aligned at 4 bytes. So we have a couple of extra bits 125 always aligned at 4 bytes. So we have a couple of extra bits
88 to play with, which indicate the node's status; see below: */ 126 to play with, which indicate the node's status; see below: */
@@ -95,6 +133,11 @@ struct jffs2_raw_node_ref
95#define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE) 133#define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE)
96#define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0) 134#define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0)
97 135
136/* NB: REF_PRISTINE for an inode-less node (ref->next_in_ino == NULL) indicates
137 it is an unknown node of type JFFS2_NODETYPE_RWCOMPAT_COPY, so it'll get
138 copied. If you need to do anything different to GC inode-less nodes, then
139 you need to modify gc.c accordingly. */
140
98/* For each inode in the filesystem, we need to keep a record of 141/* For each inode in the filesystem, we need to keep a record of
99 nlink, because it would be a PITA to scan the whole directory tree 142 nlink, because it would be a PITA to scan the whole directory tree
100 at read_inode() time to calculate it, and to keep sufficient information 143 at read_inode() time to calculate it, and to keep sufficient information
@@ -103,15 +146,27 @@ struct jffs2_raw_node_ref
103 a pointer to the first physical node which is part of this inode, too. 146 a pointer to the first physical node which is part of this inode, too.
104*/ 147*/
105struct jffs2_inode_cache { 148struct jffs2_inode_cache {
149 /* First part of structure is shared with other objects which
150 can terminate the raw node refs' next_in_ino list -- which
151 currently struct jffs2_xattr_datum and struct jffs2_xattr_ref. */
152
106 struct jffs2_full_dirent *scan_dents; /* Used during scan to hold 153 struct jffs2_full_dirent *scan_dents; /* Used during scan to hold
107 temporary lists of dirents, and later must be set to 154 temporary lists of dirents, and later must be set to
108 NULL to mark the end of the raw_node_ref->next_in_ino 155 NULL to mark the end of the raw_node_ref->next_in_ino
109 chain. */ 156 chain. */
110 struct jffs2_inode_cache *next;
111 struct jffs2_raw_node_ref *nodes; 157 struct jffs2_raw_node_ref *nodes;
158 uint8_t class; /* It's used for identification */
159
160 /* end of shared structure */
161
162 uint8_t flags;
163 uint16_t state;
112 uint32_t ino; 164 uint32_t ino;
165 struct jffs2_inode_cache *next;
166#ifdef CONFIG_JFFS2_FS_XATTR
167 struct jffs2_xattr_ref *xref;
168#endif
113 int nlink; 169 int nlink;
114 int state;
115}; 170};
116 171
117/* Inode states for 'state' above. We need the 'GC' state to prevent 172/* Inode states for 'state' above. We need the 'GC' state to prevent
@@ -125,8 +180,16 @@ struct jffs2_inode_cache {
125#define INO_STATE_READING 5 /* In read_inode() */ 180#define INO_STATE_READING 5 /* In read_inode() */
126#define INO_STATE_CLEARING 6 /* In clear_inode() */ 181#define INO_STATE_CLEARING 6 /* In clear_inode() */
127 182
183#define INO_FLAGS_XATTR_CHECKED 0x01 /* has no duplicate xattr_ref */
184
185#define RAWNODE_CLASS_INODE_CACHE 0
186#define RAWNODE_CLASS_XATTR_DATUM 1
187#define RAWNODE_CLASS_XATTR_REF 2
188
128#define INOCACHE_HASHSIZE 128 189#define INOCACHE_HASHSIZE 128
129 190
191#define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)
192
130/* 193/*
131 Larger representation of a raw node, kept in-core only when the 194 Larger representation of a raw node, kept in-core only when the
132 struct inode for this particular ino is instantiated. 195 struct inode for this particular ino is instantiated.
@@ -192,6 +255,7 @@ struct jffs2_eraseblock
192 uint32_t wasted_size; 255 uint32_t wasted_size;
193 uint32_t free_size; /* Note that sector_size - free_size 256 uint32_t free_size; /* Note that sector_size - free_size
194 is the address of the first free space */ 257 is the address of the first free space */
258 uint32_t allocated_refs;
195 struct jffs2_raw_node_ref *first_node; 259 struct jffs2_raw_node_ref *first_node;
196 struct jffs2_raw_node_ref *last_node; 260 struct jffs2_raw_node_ref *last_node;
197 261
@@ -203,57 +267,7 @@ static inline int jffs2_blocks_use_vmalloc(struct jffs2_sb_info *c)
203 return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024); 267 return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024);
204} 268}
205 269
206/* Calculate totlen from surrounding nodes or eraseblock */ 270#define ref_totlen(a, b, c) __jffs2_ref_totlen((a), (b), (c))
207static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
208 struct jffs2_eraseblock *jeb,
209 struct jffs2_raw_node_ref *ref)
210{
211 uint32_t ref_end;
212
213 if (ref->next_phys)
214 ref_end = ref_offset(ref->next_phys);
215 else {
216 if (!jeb)
217 jeb = &c->blocks[ref->flash_offset / c->sector_size];
218
219 /* Last node in block. Use free_space */
220 BUG_ON(ref != jeb->last_node);
221 ref_end = jeb->offset + c->sector_size - jeb->free_size;
222 }
223 return ref_end - ref_offset(ref);
224}
225
226static inline uint32_t ref_totlen(struct jffs2_sb_info *c,
227 struct jffs2_eraseblock *jeb,
228 struct jffs2_raw_node_ref *ref)
229{
230 uint32_t ret;
231
232#if CONFIG_JFFS2_FS_DEBUG > 0
233 if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) {
234 printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n",
235 jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref));
236 BUG();
237 }
238#endif
239
240#if 1
241 ret = ref->__totlen;
242#else
243 /* This doesn't actually work yet */
244 ret = __ref_totlen(c, jeb, ref);
245 if (ret != ref->__totlen) {
246 printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
247 ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
248 ret, ref->__totlen);
249 if (!jeb)
250 jeb = &c->blocks[ref->flash_offset / c->sector_size];
251 jffs2_dbg_dump_node_refs_nolock(c, jeb);
252 BUG();
253 }
254#endif
255 return ret;
256}
257 271
258#define ALLOC_NORMAL 0 /* Normal allocation */ 272#define ALLOC_NORMAL 0 /* Normal allocation */
259#define ALLOC_DELETION 1 /* Deletion node. Best to allow it */ 273#define ALLOC_DELETION 1 /* Deletion node. Best to allow it */
@@ -268,13 +282,15 @@ static inline uint32_t ref_totlen(struct jffs2_sb_info *c,
268 282
269#define PAD(x) (((x)+3)&~3) 283#define PAD(x) (((x)+3)&~3)
270 284
271static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw) 285static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
272{ 286{
273 while(raw->next_in_ino) { 287 if (old_valid_dev(rdev)) {
274 raw = raw->next_in_ino; 288 jdev->old = cpu_to_je16(old_encode_dev(rdev));
289 return sizeof(jdev->old);
290 } else {
291 jdev->new = cpu_to_je32(new_encode_dev(rdev));
292 return sizeof(jdev->new);
275 } 293 }
276
277 return ((struct jffs2_inode_cache *)raw);
278} 294}
279 295
280static inline struct jffs2_node_frag *frag_first(struct rb_root *root) 296static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
@@ -299,7 +315,6 @@ static inline struct jffs2_node_frag *frag_last(struct rb_root *root)
299 return rb_entry(node, struct jffs2_node_frag, rb); 315 return rb_entry(node, struct jffs2_node_frag, rb);
300} 316}
301 317
302#define rb_parent(rb) ((rb)->rb_parent)
303#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb) 318#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb)
304#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb) 319#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb)
305#define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb) 320#define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb)
@@ -324,28 +339,44 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t
324int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); 339int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn);
325void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); 340void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size);
326int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); 341int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn);
342struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
343 struct jffs2_eraseblock *jeb,
344 uint32_t ofs, uint32_t len,
345 struct jffs2_inode_cache *ic);
346extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c,
347 struct jffs2_eraseblock *jeb,
348 struct jffs2_raw_node_ref *ref);
327 349
328/* nodemgmt.c */ 350/* nodemgmt.c */
329int jffs2_thread_should_wake(struct jffs2_sb_info *c); 351int jffs2_thread_should_wake(struct jffs2_sb_info *c);
330int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, 352int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
331 uint32_t *len, int prio, uint32_t sumsize); 353 uint32_t *len, int prio, uint32_t sumsize);
332int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, 354int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
333 uint32_t *len, uint32_t sumsize); 355 uint32_t *len, uint32_t sumsize);
334int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new); 356struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
357 uint32_t ofs, uint32_t len,
358 struct jffs2_inode_cache *ic);
335void jffs2_complete_reservation(struct jffs2_sb_info *c); 359void jffs2_complete_reservation(struct jffs2_sb_info *c);
336void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); 360void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw);
337 361
338/* write.c */ 362/* write.c */
339int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri); 363int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri);
340 364
341struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode); 365struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
342struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode); 366 struct jffs2_raw_inode *ri, const unsigned char *data,
367 uint32_t datalen, int alloc_mode);
368struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
369 struct jffs2_raw_dirent *rd, const unsigned char *name,
370 uint32_t namelen, int alloc_mode);
343int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 371int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
344 struct jffs2_raw_inode *ri, unsigned char *buf, 372 struct jffs2_raw_inode *ri, unsigned char *buf,
345 uint32_t offset, uint32_t writelen, uint32_t *retlen); 373 uint32_t offset, uint32_t writelen, uint32_t *retlen);
346int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen); 374int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f,
347int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f, uint32_t time); 375 struct jffs2_raw_inode *ri, const char *name, int namelen);
348int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time); 376int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name,
377 int namelen, struct jffs2_inode_info *dead_f, uint32_t time);
378int jffs2_do_link(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino,
379 uint8_t type, const char *name, int namelen, uint32_t time);
349 380
350 381
351/* readinode.c */ 382/* readinode.c */
@@ -368,12 +399,19 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void);
368void jffs2_free_raw_inode(struct jffs2_raw_inode *); 399void jffs2_free_raw_inode(struct jffs2_raw_inode *);
369struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void); 400struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void);
370void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *); 401void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *);
371struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void); 402int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
372void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *); 403 struct jffs2_eraseblock *jeb, int nr);
404void jffs2_free_refblock(struct jffs2_raw_node_ref *);
373struct jffs2_node_frag *jffs2_alloc_node_frag(void); 405struct jffs2_node_frag *jffs2_alloc_node_frag(void);
374void jffs2_free_node_frag(struct jffs2_node_frag *); 406void jffs2_free_node_frag(struct jffs2_node_frag *);
375struct jffs2_inode_cache *jffs2_alloc_inode_cache(void); 407struct jffs2_inode_cache *jffs2_alloc_inode_cache(void);
376void jffs2_free_inode_cache(struct jffs2_inode_cache *); 408void jffs2_free_inode_cache(struct jffs2_inode_cache *);
409#ifdef CONFIG_JFFS2_FS_XATTR
410struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void);
411void jffs2_free_xattr_datum(struct jffs2_xattr_datum *);
412struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void);
413void jffs2_free_xattr_ref(struct jffs2_xattr_ref *);
414#endif
377 415
378/* gc.c */ 416/* gc.c */
379int jffs2_garbage_collect_pass(struct jffs2_sb_info *c); 417int jffs2_garbage_collect_pass(struct jffs2_sb_info *c);
@@ -393,12 +431,14 @@ int jffs2_fill_scan_buf(struct jffs2_sb_info *c, void *buf,
393 uint32_t ofs, uint32_t len); 431 uint32_t ofs, uint32_t len);
394struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino); 432struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino);
395int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); 433int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
434int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t size);
396 435
397/* build.c */ 436/* build.c */
398int jffs2_do_mount_fs(struct jffs2_sb_info *c); 437int jffs2_do_mount_fs(struct jffs2_sb_info *c);
399 438
400/* erase.c */ 439/* erase.c */
401void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count); 440void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count);
441void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
402 442
403#ifdef CONFIG_JFFS2_FS_WRITEBUFFER 443#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
404/* wbuf.c */ 444/* wbuf.c */
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 49127a1f0458..8bedfd2ff689 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -23,13 +23,12 @@
23 * jffs2_reserve_space - request physical space to write nodes to flash 23 * jffs2_reserve_space - request physical space to write nodes to flash
24 * @c: superblock info 24 * @c: superblock info
25 * @minsize: Minimum acceptable size of allocation 25 * @minsize: Minimum acceptable size of allocation
26 * @ofs: Returned value of node offset
27 * @len: Returned value of allocation length 26 * @len: Returned value of allocation length
28 * @prio: Allocation type - ALLOC_{NORMAL,DELETION} 27 * @prio: Allocation type - ALLOC_{NORMAL,DELETION}
29 * 28 *
30 * Requests a block of physical space on the flash. Returns zero for success 29 * Requests a block of physical space on the flash. Returns zero for success
31 * and puts 'ofs' and 'len' into the appriopriate place, or returns -ENOSPC 30 * and puts 'len' into the appropriate place, or returns -ENOSPC or other
32 * or other error if appropriate. 31 * error if appropriate. Doesn't return len since that's
33 * 32 *
34 * If it returns zero, jffs2_reserve_space() also downs the per-filesystem 33 * If it returns zero, jffs2_reserve_space() also downs the per-filesystem
35 * allocation semaphore, to prevent more than one allocation from being 34 * allocation semaphore, to prevent more than one allocation from being
@@ -40,9 +39,9 @@
40 */ 39 */
41 40
42static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, 41static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
43 uint32_t *ofs, uint32_t *len, uint32_t sumsize); 42 uint32_t *len, uint32_t sumsize);
44 43
45int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, 44int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
46 uint32_t *len, int prio, uint32_t sumsize) 45 uint32_t *len, int prio, uint32_t sumsize)
47{ 46{
48 int ret = -EAGAIN; 47 int ret = -EAGAIN;
@@ -132,19 +131,21 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs
132 spin_lock(&c->erase_completion_lock); 131 spin_lock(&c->erase_completion_lock);
133 } 132 }
134 133
135 ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize); 134 ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
136 if (ret) { 135 if (ret) {
137 D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret)); 136 D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret));
138 } 137 }
139 } 138 }
140 spin_unlock(&c->erase_completion_lock); 139 spin_unlock(&c->erase_completion_lock);
140 if (!ret)
141 ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
141 if (ret) 142 if (ret)
142 up(&c->alloc_sem); 143 up(&c->alloc_sem);
143 return ret; 144 return ret;
144} 145}
145 146
146int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, 147int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
147 uint32_t *len, uint32_t sumsize) 148 uint32_t *len, uint32_t sumsize)
148{ 149{
149 int ret = -EAGAIN; 150 int ret = -EAGAIN;
150 minsize = PAD(minsize); 151 minsize = PAD(minsize);
@@ -153,12 +154,15 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *
153 154
154 spin_lock(&c->erase_completion_lock); 155 spin_lock(&c->erase_completion_lock);
155 while(ret == -EAGAIN) { 156 while(ret == -EAGAIN) {
156 ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize); 157 ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
157 if (ret) { 158 if (ret) {
158 D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret)); 159 D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
159 } 160 }
160 } 161 }
161 spin_unlock(&c->erase_completion_lock); 162 spin_unlock(&c->erase_completion_lock);
163 if (!ret)
164 ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
165
162 return ret; 166 return ret;
163} 167}
164 168
@@ -259,10 +263,11 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
259} 263}
260 264
261/* Called with alloc sem _and_ erase_completion_lock */ 265/* Called with alloc sem _and_ erase_completion_lock */
262static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, uint32_t sumsize) 266static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
267 uint32_t *len, uint32_t sumsize)
263{ 268{
264 struct jffs2_eraseblock *jeb = c->nextblock; 269 struct jffs2_eraseblock *jeb = c->nextblock;
265 uint32_t reserved_size; /* for summary information at the end of the jeb */ 270 uint32_t reserved_size; /* for summary information at the end of the jeb */
266 int ret; 271 int ret;
267 272
268 restart: 273 restart:
@@ -312,6 +317,8 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
312 } 317 }
313 } else { 318 } else {
314 if (jeb && minsize > jeb->free_size) { 319 if (jeb && minsize > jeb->free_size) {
320 uint32_t waste;
321
315 /* Skip the end of this block and file it as having some dirty space */ 322 /* Skip the end of this block and file it as having some dirty space */
316 /* If there's a pending write to it, flush now */ 323 /* If there's a pending write to it, flush now */
317 324
@@ -324,10 +331,26 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
324 goto restart; 331 goto restart;
325 } 332 }
326 333
327 c->wasted_size += jeb->free_size; 334 spin_unlock(&c->erase_completion_lock);
328 c->free_size -= jeb->free_size; 335
329 jeb->wasted_size += jeb->free_size; 336 ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
330 jeb->free_size = 0; 337 if (ret)
338 return ret;
339 /* Just lock it again and continue. Nothing much can change because
340 we hold c->alloc_sem anyway. In fact, it's not entirely clear why
341 we hold c->erase_completion_lock in the majority of this function...
342 but that's a question for another (more caffeine-rich) day. */
343 spin_lock(&c->erase_completion_lock);
344
345 waste = jeb->free_size;
346 jffs2_link_node_ref(c, jeb,
347 (jeb->offset + c->sector_size - waste) | REF_OBSOLETE,
348 waste, NULL);
349 /* FIXME: that made it count as dirty. Convert to wasted */
350 jeb->dirty_size -= waste;
351 c->dirty_size -= waste;
352 jeb->wasted_size += waste;
353 c->wasted_size += waste;
331 354
332 jffs2_close_nextblock(c, jeb); 355 jffs2_close_nextblock(c, jeb);
333 jeb = NULL; 356 jeb = NULL;
@@ -349,7 +372,6 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
349 } 372 }
350 /* OK, jeb (==c->nextblock) is now pointing at a block which definitely has 373 /* OK, jeb (==c->nextblock) is now pointing at a block which definitely has
351 enough space */ 374 enough space */
352 *ofs = jeb->offset + (c->sector_size - jeb->free_size);
353 *len = jeb->free_size - reserved_size; 375 *len = jeb->free_size - reserved_size;
354 376
355 if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && 377 if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size &&
@@ -365,7 +387,8 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
365 spin_lock(&c->erase_completion_lock); 387 spin_lock(&c->erase_completion_lock);
366 } 388 }
367 389
368 D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n", *len, *ofs)); 390 D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n",
391 *len, jeb->offset + (c->sector_size - jeb->free_size)));
369 return 0; 392 return 0;
370} 393}
371 394
@@ -374,7 +397,6 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
374 * @c: superblock info 397 * @c: superblock info
375 * @new: new node reference to add 398 * @new: new node reference to add
376 * @len: length of this physical node 399 * @len: length of this physical node
377 * @dirty: dirty flag for new node
378 * 400 *
379 * Should only be used to report nodes for which space has been allocated 401 * Should only be used to report nodes for which space has been allocated
380 * by jffs2_reserve_space. 402 * by jffs2_reserve_space.
@@ -382,42 +404,30 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
382 * Must be called with the alloc_sem held. 404 * Must be called with the alloc_sem held.
383 */ 405 */
384 406
385int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new) 407struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
408 uint32_t ofs, uint32_t len,
409 struct jffs2_inode_cache *ic)
386{ 410{
387 struct jffs2_eraseblock *jeb; 411 struct jffs2_eraseblock *jeb;
388 uint32_t len; 412 struct jffs2_raw_node_ref *new;
389 413
390 jeb = &c->blocks[new->flash_offset / c->sector_size]; 414 jeb = &c->blocks[ofs / c->sector_size];
391 len = ref_totlen(c, jeb, new);
392 415
393 D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len)); 416 D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n",
417 ofs & ~3, ofs & 3, len));
394#if 1 418#if 1
395 /* we could get some obsolete nodes after nextblock was refiled 419 /* Allow non-obsolete nodes only to be added at the end of c->nextblock,
396 in wbuf.c */ 420 if c->nextblock is set. Note that wbuf.c will file obsolete nodes
397 if ((c->nextblock || !ref_obsolete(new)) 421 even after refiling c->nextblock */
398 &&(jeb != c->nextblock || ref_offset(new) != jeb->offset + (c->sector_size - jeb->free_size))) { 422 if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
423 && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
399 printk(KERN_WARNING "argh. node added in wrong place\n"); 424 printk(KERN_WARNING "argh. node added in wrong place\n");
400 jffs2_free_raw_node_ref(new); 425 return ERR_PTR(-EINVAL);
401 return -EINVAL;
402 } 426 }
403#endif 427#endif
404 spin_lock(&c->erase_completion_lock); 428 spin_lock(&c->erase_completion_lock);
405 429
406 if (!jeb->first_node) 430 new = jffs2_link_node_ref(c, jeb, ofs, len, ic);
407 jeb->first_node = new;
408 if (jeb->last_node)
409 jeb->last_node->next_phys = new;
410 jeb->last_node = new;
411
412 jeb->free_size -= len;
413 c->free_size -= len;
414 if (ref_obsolete(new)) {
415 jeb->dirty_size += len;
416 c->dirty_size += len;
417 } else {
418 jeb->used_size += len;
419 c->used_size += len;
420 }
421 431
422 if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) { 432 if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) {
423 /* If it lives on the dirty_list, jffs2_reserve_space will put it there */ 433 /* If it lives on the dirty_list, jffs2_reserve_space will put it there */
@@ -438,7 +448,7 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r
438 448
439 spin_unlock(&c->erase_completion_lock); 449 spin_unlock(&c->erase_completion_lock);
440 450
441 return 0; 451 return new;
442} 452}
443 453
444 454
@@ -470,8 +480,9 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
470 struct jffs2_unknown_node n; 480 struct jffs2_unknown_node n;
471 int ret, addedsize; 481 int ret, addedsize;
472 size_t retlen; 482 size_t retlen;
483 uint32_t freed_len;
473 484
474 if(!ref) { 485 if(unlikely(!ref)) {
475 printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n"); 486 printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n");
476 return; 487 return;
477 } 488 }
@@ -499,32 +510,34 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
499 510
500 spin_lock(&c->erase_completion_lock); 511 spin_lock(&c->erase_completion_lock);
501 512
513 freed_len = ref_totlen(c, jeb, ref);
514
502 if (ref_flags(ref) == REF_UNCHECKED) { 515 if (ref_flags(ref) == REF_UNCHECKED) {
503 D1(if (unlikely(jeb->unchecked_size < ref_totlen(c, jeb, ref))) { 516 D1(if (unlikely(jeb->unchecked_size < freed_len)) {
504 printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n", 517 printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n",
505 ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); 518 freed_len, blocknr, ref->flash_offset, jeb->used_size);
506 BUG(); 519 BUG();
507 }) 520 })
508 D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); 521 D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), freed_len));
509 jeb->unchecked_size -= ref_totlen(c, jeb, ref); 522 jeb->unchecked_size -= freed_len;
510 c->unchecked_size -= ref_totlen(c, jeb, ref); 523 c->unchecked_size -= freed_len;
511 } else { 524 } else {
512 D1(if (unlikely(jeb->used_size < ref_totlen(c, jeb, ref))) { 525 D1(if (unlikely(jeb->used_size < freed_len)) {
513 printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n", 526 printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n",
514 ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); 527 freed_len, blocknr, ref->flash_offset, jeb->used_size);
515 BUG(); 528 BUG();
516 }) 529 })
517 D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); 530 D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), freed_len));
518 jeb->used_size -= ref_totlen(c, jeb, ref); 531 jeb->used_size -= freed_len;
519 c->used_size -= ref_totlen(c, jeb, ref); 532 c->used_size -= freed_len;
520 } 533 }
521 534
522 // Take care, that wasted size is taken into concern 535 // Take care, that wasted size is taken into concern
523 if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + ref_totlen(c, jeb, ref))) && jeb != c->nextblock) { 536 if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + freed_len)) && jeb != c->nextblock) {
524 D1(printk(KERN_DEBUG "Dirtying\n")); 537 D1(printk("Dirtying\n"));
525 addedsize = ref_totlen(c, jeb, ref); 538 addedsize = freed_len;
526 jeb->dirty_size += ref_totlen(c, jeb, ref); 539 jeb->dirty_size += freed_len;
527 c->dirty_size += ref_totlen(c, jeb, ref); 540 c->dirty_size += freed_len;
528 541
529 /* Convert wasted space to dirty, if not a bad block */ 542 /* Convert wasted space to dirty, if not a bad block */
530 if (jeb->wasted_size) { 543 if (jeb->wasted_size) {
@@ -543,10 +556,10 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
543 } 556 }
544 } 557 }
545 } else { 558 } else {
546 D1(printk(KERN_DEBUG "Wasting\n")); 559 D1(printk("Wasting\n"));
547 addedsize = 0; 560 addedsize = 0;
548 jeb->wasted_size += ref_totlen(c, jeb, ref); 561 jeb->wasted_size += freed_len;
549 c->wasted_size += ref_totlen(c, jeb, ref); 562 c->wasted_size += freed_len;
550 } 563 }
551 ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; 564 ref->flash_offset = ref_offset(ref) | REF_OBSOLETE;
552 565
@@ -622,7 +635,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
622 /* The erase_free_sem is locked, and has been since before we marked the node obsolete 635 /* The erase_free_sem is locked, and has been since before we marked the node obsolete
623 and potentially put its eraseblock onto the erase_pending_list. Thus, we know that 636 and potentially put its eraseblock onto the erase_pending_list. Thus, we know that
624 the block hasn't _already_ been erased, and that 'ref' itself hasn't been freed yet 637 the block hasn't _already_ been erased, and that 'ref' itself hasn't been freed yet
625 by jffs2_free_all_node_refs() in erase.c. Which is nice. */ 638 by jffs2_free_jeb_node_refs() in erase.c. Which is nice. */
626 639
627 D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref_offset(ref))); 640 D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref_offset(ref)));
628 ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n); 641 ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n);
@@ -634,8 +647,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
634 printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen); 647 printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen);
635 goto out_erase_sem; 648 goto out_erase_sem;
636 } 649 }
637 if (PAD(je32_to_cpu(n.totlen)) != PAD(ref_totlen(c, jeb, ref))) { 650 if (PAD(je32_to_cpu(n.totlen)) != PAD(freed_len)) {
638 printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), ref_totlen(c, jeb, ref)); 651 printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), freed_len);
639 goto out_erase_sem; 652 goto out_erase_sem;
640 } 653 }
641 if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) { 654 if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) {
@@ -671,6 +684,10 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
671 spin_lock(&c->erase_completion_lock); 684 spin_lock(&c->erase_completion_lock);
672 685
673 ic = jffs2_raw_ref_to_ic(ref); 686 ic = jffs2_raw_ref_to_ic(ref);
687 /* It seems we should never call jffs2_mark_node_obsolete() for
688 XATTR nodes.... yet. Make sure we notice if/when we change
689 that :) */
690 BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
674 for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino)) 691 for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino))
675 ; 692 ;
676 693
@@ -683,51 +700,6 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
683 spin_unlock(&c->erase_completion_lock); 700 spin_unlock(&c->erase_completion_lock);
684 } 701 }
685 702
686
687 /* Merge with the next node in the physical list, if there is one
688 and if it's also obsolete and if it doesn't belong to any inode */
689 if (ref->next_phys && ref_obsolete(ref->next_phys) &&
690 !ref->next_phys->next_in_ino) {
691 struct jffs2_raw_node_ref *n = ref->next_phys;
692
693 spin_lock(&c->erase_completion_lock);
694
695 ref->__totlen += n->__totlen;
696 ref->next_phys = n->next_phys;
697 if (jeb->last_node == n) jeb->last_node = ref;
698 if (jeb->gc_node == n) {
699 /* gc will be happy continuing gc on this node */
700 jeb->gc_node=ref;
701 }
702 spin_unlock(&c->erase_completion_lock);
703
704 jffs2_free_raw_node_ref(n);
705 }
706
707 /* Also merge with the previous node in the list, if there is one
708 and that one is obsolete */
709 if (ref != jeb->first_node ) {
710 struct jffs2_raw_node_ref *p = jeb->first_node;
711
712 spin_lock(&c->erase_completion_lock);
713
714 while (p->next_phys != ref)
715 p = p->next_phys;
716
717 if (ref_obsolete(p) && !ref->next_in_ino) {
718 p->__totlen += ref->__totlen;
719 if (jeb->last_node == ref) {
720 jeb->last_node = p;
721 }
722 if (jeb->gc_node == ref) {
723 /* gc will be happy continuing gc on this node */
724 jeb->gc_node=p;
725 }
726 p->next_phys = ref->next_phys;
727 jffs2_free_raw_node_ref(ref);
728 }
729 spin_unlock(&c->erase_completion_lock);
730 }
731 out_erase_sem: 703 out_erase_sem:
732 up(&c->erase_free_sem); 704 up(&c->erase_free_sem);
733} 705}
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index d307cf548625..6b5223565405 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -31,9 +31,7 @@ struct kvec;
31#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode) 31#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode)
32#define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid) 32#define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid)
33#define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid) 33#define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid)
34 34#define JFFS2_F_I_RDEV(f) (OFNI_EDONI_2SFFJ(f)->i_rdev)
35#define JFFS2_F_I_RDEV_MIN(f) (iminor(OFNI_EDONI_2SFFJ(f)))
36#define JFFS2_F_I_RDEV_MAJ(f) (imajor(OFNI_EDONI_2SFFJ(f)))
37 35
38#define ITIME(sec) ((struct timespec){sec, 0}) 36#define ITIME(sec) ((struct timespec){sec, 0})
39#define I_SEC(tv) ((tv).tv_sec) 37#define I_SEC(tv) ((tv).tv_sec)
@@ -60,6 +58,10 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
60 f->target = NULL; 58 f->target = NULL;
61 f->flags = 0; 59 f->flags = 0;
62 f->usercompr = 0; 60 f->usercompr = 0;
61#ifdef CONFIG_JFFS2_FS_POSIX_ACL
62 f->i_acl_access = JFFS2_ACL_NOT_CACHED;
63 f->i_acl_default = JFFS2_ACL_NOT_CACHED;
64#endif
63} 65}
64 66
65 67
@@ -90,13 +92,10 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
90#define jffs2_flash_writev(a,b,c,d,e,f) jffs2_flash_direct_writev(a,b,c,d,e) 92#define jffs2_flash_writev(a,b,c,d,e,f) jffs2_flash_direct_writev(a,b,c,d,e)
91#define jffs2_wbuf_timeout NULL 93#define jffs2_wbuf_timeout NULL
92#define jffs2_wbuf_process NULL 94#define jffs2_wbuf_process NULL
93#define jffs2_nor_ecc(c) (0)
94#define jffs2_dataflash(c) (0) 95#define jffs2_dataflash(c) (0)
95#define jffs2_nor_wbuf_flash(c) (0)
96#define jffs2_nor_ecc_flash_setup(c) (0)
97#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0)
98#define jffs2_dataflash_setup(c) (0) 96#define jffs2_dataflash_setup(c) (0)
99#define jffs2_dataflash_cleanup(c) do {} while (0) 97#define jffs2_dataflash_cleanup(c) do {} while (0)
98#define jffs2_nor_wbuf_flash(c) (0)
100#define jffs2_nor_wbuf_flash_setup(c) (0) 99#define jffs2_nor_wbuf_flash_setup(c) (0)
101#define jffs2_nor_wbuf_flash_cleanup(c) do {} while (0) 100#define jffs2_nor_wbuf_flash_cleanup(c) do {} while (0)
102 101
@@ -107,9 +106,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
107#ifdef CONFIG_JFFS2_SUMMARY 106#ifdef CONFIG_JFFS2_SUMMARY
108#define jffs2_can_mark_obsolete(c) (0) 107#define jffs2_can_mark_obsolete(c) (0)
109#else 108#else
110#define jffs2_can_mark_obsolete(c) \ 109#define jffs2_can_mark_obsolete(c) (c->mtd->flags & (MTD_BIT_WRITEABLE))
111 ((c->mtd->type == MTD_NORFLASH && !(c->mtd->flags & (MTD_ECC|MTD_PROGRAM_REGIONS))) || \
112 c->mtd->type == MTD_RAM)
113#endif 110#endif
114 111
115#define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH) 112#define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH)
@@ -133,15 +130,11 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c);
133int jffs2_nand_flash_setup(struct jffs2_sb_info *c); 130int jffs2_nand_flash_setup(struct jffs2_sb_info *c);
134void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c); 131void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c);
135 132
136#define jffs2_nor_ecc(c) (c->mtd->type == MTD_NORFLASH && (c->mtd->flags & MTD_ECC))
137int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c);
138void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c);
139
140#define jffs2_dataflash(c) (c->mtd->type == MTD_DATAFLASH) 133#define jffs2_dataflash(c) (c->mtd->type == MTD_DATAFLASH)
141int jffs2_dataflash_setup(struct jffs2_sb_info *c); 134int jffs2_dataflash_setup(struct jffs2_sb_info *c);
142void jffs2_dataflash_cleanup(struct jffs2_sb_info *c); 135void jffs2_dataflash_cleanup(struct jffs2_sb_info *c);
143 136
144#define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && (c->mtd->flags & MTD_PROGRAM_REGIONS)) 137#define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && ! (c->mtd->flags & MTD_BIT_WRITEABLE))
145int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c); 138int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c);
146void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c); 139void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c);
147 140
@@ -182,7 +175,7 @@ void jffs2_clear_inode (struct inode *);
182void jffs2_dirty_inode(struct inode *inode); 175void jffs2_dirty_inode(struct inode *inode);
183struct inode *jffs2_new_inode (struct inode *dir_i, int mode, 176struct inode *jffs2_new_inode (struct inode *dir_i, int mode,
184 struct jffs2_raw_inode *ri); 177 struct jffs2_raw_inode *ri);
185int jffs2_statfs (struct super_block *, struct kstatfs *); 178int jffs2_statfs (struct dentry *, struct kstatfs *);
186void jffs2_write_super (struct super_block *); 179void jffs2_write_super (struct super_block *);
187int jffs2_remount_fs (struct super_block *, int *, char *); 180int jffs2_remount_fs (struct super_block *, int *, char *);
188int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); 181int jffs2_do_fill_super(struct super_block *sb, void *data, int silent);
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index f1695642d0f7..5fec012b02ed 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -66,7 +66,7 @@ static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
66 jffs2_free_full_dnode(tn->fn); 66 jffs2_free_full_dnode(tn->fn);
67 jffs2_free_tmp_dnode_info(tn); 67 jffs2_free_tmp_dnode_info(tn);
68 68
69 this = this->rb_parent; 69 this = rb_parent(this);
70 if (!this) 70 if (!this)
71 break; 71 break;
72 72
@@ -116,19 +116,42 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
116 uint32_t *latest_mctime, uint32_t *mctime_ver) 116 uint32_t *latest_mctime, uint32_t *mctime_ver)
117{ 117{
118 struct jffs2_full_dirent *fd; 118 struct jffs2_full_dirent *fd;
119 uint32_t crc;
119 120
120 /* The direntry nodes are checked during the flash scanning */
121 BUG_ON(ref_flags(ref) == REF_UNCHECKED);
122 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ 121 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
123 BUG_ON(ref_obsolete(ref)); 122 BUG_ON(ref_obsolete(ref));
124 123
125 /* Sanity check */ 124 crc = crc32(0, rd, sizeof(*rd) - 8);
126 if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { 125 if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
127 JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", 126 JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n",
128 ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); 127 ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
129 return 1; 128 return 1;
130 } 129 }
131 130
131 /* If we've never checked the CRCs on this node, check them now */
132 if (ref_flags(ref) == REF_UNCHECKED) {
133 struct jffs2_eraseblock *jeb;
134 int len;
135
136 /* Sanity check */
137 if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
138 JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
139 ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
140 return 1;
141 }
142
143 jeb = &c->blocks[ref->flash_offset / c->sector_size];
144 len = ref_totlen(c, jeb, ref);
145
146 spin_lock(&c->erase_completion_lock);
147 jeb->used_size += len;
148 jeb->unchecked_size -= len;
149 c->used_size += len;
150 c->unchecked_size -= len;
151 ref->flash_offset = ref_offset(ref) | REF_PRISTINE;
152 spin_unlock(&c->erase_completion_lock);
153 }
154
132 fd = jffs2_alloc_full_dirent(rd->nsize + 1); 155 fd = jffs2_alloc_full_dirent(rd->nsize + 1);
133 if (unlikely(!fd)) 156 if (unlikely(!fd))
134 return -ENOMEM; 157 return -ENOMEM;
@@ -198,13 +221,21 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
198 struct jffs2_tmp_dnode_info *tn; 221 struct jffs2_tmp_dnode_info *tn;
199 uint32_t len, csize; 222 uint32_t len, csize;
200 int ret = 1; 223 int ret = 1;
224 uint32_t crc;
201 225
202 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ 226 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
203 BUG_ON(ref_obsolete(ref)); 227 BUG_ON(ref_obsolete(ref));
204 228
229 crc = crc32(0, rd, sizeof(*rd) - 8);
230 if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
231 JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n",
232 ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
233 return 1;
234 }
235
205 tn = jffs2_alloc_tmp_dnode_info(); 236 tn = jffs2_alloc_tmp_dnode_info();
206 if (!tn) { 237 if (!tn) {
207 JFFS2_ERROR("failed to allocate tn (%d bytes).\n", sizeof(*tn)); 238 JFFS2_ERROR("failed to allocate tn (%zu bytes).\n", sizeof(*tn));
208 return -ENOMEM; 239 return -ENOMEM;
209 } 240 }
210 241
@@ -213,14 +244,6 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
213 244
214 /* If we've never checked the CRCs on this node, check them now */ 245 /* If we've never checked the CRCs on this node, check them now */
215 if (ref_flags(ref) == REF_UNCHECKED) { 246 if (ref_flags(ref) == REF_UNCHECKED) {
216 uint32_t crc;
217
218 crc = crc32(0, rd, sizeof(*rd) - 8);
219 if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
220 JFFS2_NOTICE("header CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
221 ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
222 goto free_out;
223 }
224 247
225 /* Sanity checks */ 248 /* Sanity checks */
226 if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || 249 if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
@@ -343,7 +366,7 @@ free_out:
343 * Helper function for jffs2_get_inode_nodes(). 366 * Helper function for jffs2_get_inode_nodes().
344 * It is called every time an unknown node is found. 367 * It is called every time an unknown node is found.
345 * 368 *
346 * Returns: 0 on succes; 369 * Returns: 0 on success;
347 * 1 if the node should be marked obsolete; 370 * 1 if the node should be marked obsolete;
348 * negative error code on failure. 371 * negative error code on failure.
349 */ 372 */
@@ -354,37 +377,30 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
354 377
355 un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); 378 un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
356 379
357 if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { 380 switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
358 /* Hmmm. This should have been caught at scan time. */
359 JFFS2_NOTICE("node header CRC failed at %#08x. But it must have been OK earlier.\n", ref_offset(ref));
360 jffs2_dbg_dump_node(c, ref_offset(ref));
361 return 1;
362 } else {
363 switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
364 381
365 case JFFS2_FEATURE_INCOMPAT: 382 case JFFS2_FEATURE_INCOMPAT:
366 JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n", 383 JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
367 je16_to_cpu(un->nodetype), ref_offset(ref)); 384 je16_to_cpu(un->nodetype), ref_offset(ref));
368 /* EEP */ 385 /* EEP */
369 BUG(); 386 BUG();
370 break; 387 break;
371 388
372 case JFFS2_FEATURE_ROCOMPAT: 389 case JFFS2_FEATURE_ROCOMPAT:
373 JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n", 390 JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
374 je16_to_cpu(un->nodetype), ref_offset(ref)); 391 je16_to_cpu(un->nodetype), ref_offset(ref));
375 BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO)); 392 BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
376 break; 393 break;
377 394
378 case JFFS2_FEATURE_RWCOMPAT_COPY: 395 case JFFS2_FEATURE_RWCOMPAT_COPY:
379 JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n", 396 JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
380 je16_to_cpu(un->nodetype), ref_offset(ref)); 397 je16_to_cpu(un->nodetype), ref_offset(ref));
381 break; 398 break;
382 399
383 case JFFS2_FEATURE_RWCOMPAT_DELETE: 400 case JFFS2_FEATURE_RWCOMPAT_DELETE:
384 JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", 401 JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
385 je16_to_cpu(un->nodetype), ref_offset(ref)); 402 je16_to_cpu(un->nodetype), ref_offset(ref));
386 return 1; 403 return 1;
387 }
388 } 404 }
389 405
390 return 0; 406 return 0;
@@ -434,7 +450,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
434 } 450 }
435 451
436 if (retlen < len) { 452 if (retlen < len) {
437 JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", 453 JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n",
438 offs, retlen, len); 454 offs, retlen, len);
439 return -EIO; 455 return -EIO;
440 } 456 }
@@ -542,13 +558,25 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
542 } 558 }
543 559
544 if (retlen < len) { 560 if (retlen < len) {
545 JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ref_offset(ref), retlen, len); 561 JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", ref_offset(ref), retlen, len);
546 err = -EIO; 562 err = -EIO;
547 goto free_out; 563 goto free_out;
548 } 564 }
549 565
550 node = (union jffs2_node_union *)bufstart; 566 node = (union jffs2_node_union *)bufstart;
551 567
568 /* No need to mask in the valid bit; it shouldn't be invalid */
569 if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) {
570 JFFS2_NOTICE("Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x}\n",
571 ref_offset(ref), je16_to_cpu(node->u.magic),
572 je16_to_cpu(node->u.nodetype),
573 je32_to_cpu(node->u.totlen),
574 je32_to_cpu(node->u.hdr_crc));
575 jffs2_dbg_dump_node(c, ref_offset(ref));
576 jffs2_mark_node_obsolete(c, ref);
577 goto cont;
578 }
579
552 switch (je16_to_cpu(node->u.nodetype)) { 580 switch (je16_to_cpu(node->u.nodetype)) {
553 581
554 case JFFS2_NODETYPE_DIRENT: 582 case JFFS2_NODETYPE_DIRENT:
@@ -606,6 +634,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
606 goto free_out; 634 goto free_out;
607 635
608 } 636 }
637 cont:
609 spin_lock(&c->erase_completion_lock); 638 spin_lock(&c->erase_completion_lock);
610 } 639 }
611 640
@@ -679,12 +708,12 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
679 jffs2_mark_node_obsolete(c, fn->raw); 708 jffs2_mark_node_obsolete(c, fn->raw);
680 709
681 BUG_ON(rb->rb_left); 710 BUG_ON(rb->rb_left);
682 if (rb->rb_parent && rb->rb_parent->rb_left == rb) { 711 if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) {
683 /* We were then left-hand child of our parent. We need 712 /* We were then left-hand child of our parent. We need
684 * to move our own right-hand child into our place. */ 713 * to move our own right-hand child into our place. */
685 repl_rb = rb->rb_right; 714 repl_rb = rb->rb_right;
686 if (repl_rb) 715 if (repl_rb)
687 repl_rb->rb_parent = rb->rb_parent; 716 rb_set_parent(repl_rb, rb_parent(rb));
688 } else 717 } else
689 repl_rb = NULL; 718 repl_rb = NULL;
690 719
@@ -692,14 +721,14 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
692 721
693 /* Remove the spent tn from the tree; don't bother rebalancing 722 /* Remove the spent tn from the tree; don't bother rebalancing
694 * but put our right-hand child in our own place. */ 723 * but put our right-hand child in our own place. */
695 if (tn->rb.rb_parent) { 724 if (rb_parent(&tn->rb)) {
696 if (tn->rb.rb_parent->rb_left == &tn->rb) 725 if (rb_parent(&tn->rb)->rb_left == &tn->rb)
697 tn->rb.rb_parent->rb_left = repl_rb; 726 rb_parent(&tn->rb)->rb_left = repl_rb;
698 else if (tn->rb.rb_parent->rb_right == &tn->rb) 727 else if (rb_parent(&tn->rb)->rb_right == &tn->rb)
699 tn->rb.rb_parent->rb_right = repl_rb; 728 rb_parent(&tn->rb)->rb_right = repl_rb;
700 else BUG(); 729 else BUG();
701 } else if (tn->rb.rb_right) 730 } else if (tn->rb.rb_right)
702 tn->rb.rb_right->rb_parent = NULL; 731 rb_set_parent(tn->rb.rb_right, NULL);
703 732
704 jffs2_free_tmp_dnode_info(tn); 733 jffs2_free_tmp_dnode_info(tn);
705 if (ret) { 734 if (ret) {
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index cf55b221fc2b..61618080b86f 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -65,6 +65,28 @@ static inline uint32_t EMPTY_SCAN_SIZE(uint32_t sector_size) {
65 return DEFAULT_EMPTY_SCAN_SIZE; 65 return DEFAULT_EMPTY_SCAN_SIZE;
66} 66}
67 67
68static int file_dirty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
69{
70 int ret;
71
72 if ((ret = jffs2_prealloc_raw_node_refs(c, jeb, 1)))
73 return ret;
74 if ((ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size)))
75 return ret;
76 /* Turned wasted size into dirty, since we apparently
77 think it's recoverable now. */
78 jeb->dirty_size += jeb->wasted_size;
79 c->dirty_size += jeb->wasted_size;
80 c->wasted_size -= jeb->wasted_size;
81 jeb->wasted_size = 0;
82 if (VERYDIRTY(c, jeb->dirty_size)) {
83 list_add(&jeb->list, &c->very_dirty_list);
84 } else {
85 list_add(&jeb->list, &c->dirty_list);
86 }
87 return 0;
88}
89
68int jffs2_scan_medium(struct jffs2_sb_info *c) 90int jffs2_scan_medium(struct jffs2_sb_info *c)
69{ 91{
70 int i, ret; 92 int i, ret;
@@ -170,34 +192,20 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
170 (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { 192 (!c->nextblock || c->nextblock->free_size < jeb->free_size)) {
171 /* Better candidate for the next writes to go to */ 193 /* Better candidate for the next writes to go to */
172 if (c->nextblock) { 194 if (c->nextblock) {
173 c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; 195 ret = file_dirty(c, c->nextblock);
174 c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; 196 if (ret)
175 c->free_size -= c->nextblock->free_size; 197 return ret;
176 c->wasted_size -= c->nextblock->wasted_size;
177 c->nextblock->free_size = c->nextblock->wasted_size = 0;
178 if (VERYDIRTY(c, c->nextblock->dirty_size)) {
179 list_add(&c->nextblock->list, &c->very_dirty_list);
180 } else {
181 list_add(&c->nextblock->list, &c->dirty_list);
182 }
183 /* deleting summary information of the old nextblock */ 198 /* deleting summary information of the old nextblock */
184 jffs2_sum_reset_collected(c->summary); 199 jffs2_sum_reset_collected(c->summary);
185 } 200 }
186 /* update collected summary infromation for the current nextblock */ 201 /* update collected summary information for the current nextblock */
187 jffs2_sum_move_collected(c, s); 202 jffs2_sum_move_collected(c, s);
188 D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x\n", jeb->offset)); 203 D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x\n", jeb->offset));
189 c->nextblock = jeb; 204 c->nextblock = jeb;
190 } else { 205 } else {
191 jeb->dirty_size += jeb->free_size + jeb->wasted_size; 206 ret = file_dirty(c, jeb);
192 c->dirty_size += jeb->free_size + jeb->wasted_size; 207 if (ret)
193 c->free_size -= jeb->free_size; 208 return ret;
194 c->wasted_size -= jeb->wasted_size;
195 jeb->free_size = jeb->wasted_size = 0;
196 if (VERYDIRTY(c, jeb->dirty_size)) {
197 list_add(&jeb->list, &c->very_dirty_list);
198 } else {
199 list_add(&jeb->list, &c->dirty_list);
200 }
201 } 209 }
202 break; 210 break;
203 211
@@ -222,9 +230,6 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
222 } 230 }
223 } 231 }
224 232
225 if (jffs2_sum_active() && s)
226 kfree(s);
227
228 /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */ 233 /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */
229 if (c->nextblock && (c->nextblock->dirty_size)) { 234 if (c->nextblock && (c->nextblock->dirty_size)) {
230 c->nextblock->wasted_size += c->nextblock->dirty_size; 235 c->nextblock->wasted_size += c->nextblock->dirty_size;
@@ -242,11 +247,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
242 247
243 D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n", 248 D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n",
244 skip)); 249 skip));
245 c->nextblock->wasted_size += skip; 250 jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
246 c->wasted_size += skip; 251 jffs2_scan_dirty_space(c, c->nextblock, skip);
247
248 c->nextblock->free_size -= skip;
249 c->free_size -= skip;
250 } 252 }
251#endif 253#endif
252 if (c->nr_erasing_blocks) { 254 if (c->nr_erasing_blocks) {
@@ -266,6 +268,9 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
266 else 268 else
267 c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); 269 c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size);
268#endif 270#endif
271 if (s)
272 kfree(s);
273
269 return ret; 274 return ret;
270} 275}
271 276
@@ -290,7 +295,7 @@ int jffs2_fill_scan_buf (struct jffs2_sb_info *c, void *buf,
290int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 295int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
291{ 296{
292 if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size 297 if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size
293 && (!jeb->first_node || !jeb->first_node->next_phys) ) 298 && (!jeb->first_node || !ref_next(jeb->first_node)) )
294 return BLK_STATE_CLEANMARKER; 299 return BLK_STATE_CLEANMARKER;
295 300
296 /* move blocks with max 4 byte dirty space to cleanlist */ 301 /* move blocks with max 4 byte dirty space to cleanlist */
@@ -306,11 +311,119 @@ int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *je
306 return BLK_STATE_ALLDIRTY; 311 return BLK_STATE_ALLDIRTY;
307} 312}
308 313
314#ifdef CONFIG_JFFS2_FS_XATTR
315static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
316 struct jffs2_raw_xattr *rx, uint32_t ofs,
317 struct jffs2_summary *s)
318{
319 struct jffs2_xattr_datum *xd;
320 uint32_t totlen, crc;
321 int err;
322
323 crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4);
324 if (crc != je32_to_cpu(rx->node_crc)) {
325 if (je32_to_cpu(rx->node_crc) != 0xffffffff)
326 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
327 ofs, je32_to_cpu(rx->node_crc), crc);
328 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
329 return err;
330 return 0;
331 }
332
333 totlen = PAD(sizeof(*rx) + rx->name_len + 1 + je16_to_cpu(rx->value_len));
334 if (totlen != je32_to_cpu(rx->totlen)) {
335 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n",
336 ofs, je32_to_cpu(rx->totlen), totlen);
337 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
338 return err;
339 return 0;
340 }
341
342 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version));
343 if (IS_ERR(xd)) {
344 if (PTR_ERR(xd) == -EEXIST) {
345 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen)))))
346 return err;
347 return 0;
348 }
349 return PTR_ERR(xd);
350 }
351 xd->xprefix = rx->xprefix;
352 xd->name_len = rx->name_len;
353 xd->value_len = je16_to_cpu(rx->value_len);
354 xd->data_crc = je32_to_cpu(rx->data_crc);
355
356 xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
357 /* FIXME */ xd->node->next_in_ino = (void *)xd;
358
359 if (jffs2_sum_active())
360 jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
361 dbg_xattr("scaning xdatum at %#08x (xid=%u, version=%u)\n",
362 ofs, xd->xid, xd->version);
363 return 0;
364}
365
366static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
367 struct jffs2_raw_xref *rr, uint32_t ofs,
368 struct jffs2_summary *s)
369{
370 struct jffs2_xattr_ref *ref;
371 uint32_t crc;
372 int err;
373
374 crc = crc32(0, rr, sizeof(*rr) - 4);
375 if (crc != je32_to_cpu(rr->node_crc)) {
376 if (je32_to_cpu(rr->node_crc) != 0xffffffff)
377 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
378 ofs, je32_to_cpu(rr->node_crc), crc);
379 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen)))))
380 return err;
381 return 0;
382 }
383
384 if (PAD(sizeof(struct jffs2_raw_xref)) != je32_to_cpu(rr->totlen)) {
385 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%zd\n",
386 ofs, je32_to_cpu(rr->totlen),
387 PAD(sizeof(struct jffs2_raw_xref)));
388 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rr->totlen))))
389 return err;
390 return 0;
391 }
392
393 ref = jffs2_alloc_xattr_ref();
394 if (!ref)
395 return -ENOMEM;
396
397 /* BEFORE jffs2_build_xattr_subsystem() called,
398 * ref->xid is used to store 32bit xid, xd is not used
399 * ref->ino is used to store 32bit inode-number, ic is not used
400 * Thoes variables are declared as union, thus using those
401 * are exclusive. In a similar way, ref->next is temporarily
402 * used to chain all xattr_ref object. It's re-chained to
403 * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly.
404 */
405 ref->ino = je32_to_cpu(rr->ino);
406 ref->xid = je32_to_cpu(rr->xid);
407 ref->next = c->xref_temp;
408 c->xref_temp = ref;
409
410 ref->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), NULL);
411 /* FIXME */ ref->node->next_in_ino = (void *)ref;
412
413 if (jffs2_sum_active())
414 jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
415 dbg_xattr("scan xref at %#08x (xid=%u, ino=%u)\n",
416 ofs, ref->xid, ref->ino);
417 return 0;
418}
419#endif
420
421/* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into
422 the flash, XIP-style */
309static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 423static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
310 unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { 424 unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
311 struct jffs2_unknown_node *node; 425 struct jffs2_unknown_node *node;
312 struct jffs2_unknown_node crcnode; 426 struct jffs2_unknown_node crcnode;
313 struct jffs2_sum_marker *sm;
314 uint32_t ofs, prevofs; 427 uint32_t ofs, prevofs;
315 uint32_t hdr_crc, buf_ofs, buf_len; 428 uint32_t hdr_crc, buf_ofs, buf_len;
316 int err; 429 int err;
@@ -344,44 +457,75 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
344#endif 457#endif
345 458
346 if (jffs2_sum_active()) { 459 if (jffs2_sum_active()) {
347 sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL); 460 struct jffs2_sum_marker *sm;
348 if (!sm) { 461 void *sumptr = NULL;
349 return -ENOMEM; 462 uint32_t sumlen;
350 } 463
351 464 if (!buf_size) {
352 err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size - 465 /* XIP case. Just look, point at the summary if it's there */
353 sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker)); 466 sm = (void *)buf + c->sector_size - sizeof(*sm);
354 if (err) { 467 if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
355 kfree(sm); 468 sumptr = buf + je32_to_cpu(sm->offset);
356 return err; 469 sumlen = c->sector_size - je32_to_cpu(sm->offset);
357 } 470 }
358 471 } else {
359 if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) { 472 /* If NAND flash, read a whole page of it. Else just the end */
360 err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random); 473 if (c->wbuf_pagesize)
361 if (err) { 474 buf_len = c->wbuf_pagesize;
362 kfree(sm); 475 else
476 buf_len = sizeof(*sm);
477
478 /* Read as much as we want into the _end_ of the preallocated buffer */
479 err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,
480 jeb->offset + c->sector_size - buf_len,
481 buf_len);
482 if (err)
363 return err; 483 return err;
484
485 sm = (void *)buf + buf_size - sizeof(*sm);
486 if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
487 sumlen = c->sector_size - je32_to_cpu(sm->offset);
488 sumptr = buf + buf_size - sumlen;
489
490 /* Now, make sure the summary itself is available */
491 if (sumlen > buf_size) {
492 /* Need to kmalloc for this. */
493 sumptr = kmalloc(sumlen, GFP_KERNEL);
494 if (!sumptr)
495 return -ENOMEM;
496 memcpy(sumptr + sumlen - buf_len, buf + buf_size - buf_len, buf_len);
497 }
498 if (buf_len < sumlen) {
499 /* Need to read more so that the entire summary node is present */
500 err = jffs2_fill_scan_buf(c, sumptr,
501 jeb->offset + c->sector_size - sumlen,
502 sumlen - buf_len);
503 if (err)
504 return err;
505 }
364 } 506 }
507
365 } 508 }
366 509
367 kfree(sm); 510 if (sumptr) {
511 err = jffs2_sum_scan_sumnode(c, jeb, sumptr, sumlen, &pseudo_random);
368 512
369 ofs = jeb->offset; 513 if (buf_size && sumlen > buf_size)
370 prevofs = jeb->offset - 1; 514 kfree(sumptr);
515 /* If it returns with a real error, bail.
516 If it returns positive, that's a block classification
517 (i.e. BLK_STATE_xxx) so return that too.
518 If it returns zero, fall through to full scan. */
519 if (err)
520 return err;
521 }
371 } 522 }
372 523
373 buf_ofs = jeb->offset; 524 buf_ofs = jeb->offset;
374 525
375 if (!buf_size) { 526 if (!buf_size) {
527 /* This is the XIP case -- we're reading _directly_ from the flash chip */
376 buf_len = c->sector_size; 528 buf_len = c->sector_size;
377
378 if (jffs2_sum_active()) {
379 /* must reread because of summary test */
380 err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
381 if (err)
382 return err;
383 }
384
385 } else { 529 } else {
386 buf_len = EMPTY_SCAN_SIZE(c->sector_size); 530 buf_len = EMPTY_SCAN_SIZE(c->sector_size);
387 err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); 531 err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
@@ -418,7 +562,10 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
418 if (ofs) { 562 if (ofs) {
419 D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset, 563 D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset,
420 jeb->offset + ofs)); 564 jeb->offset + ofs));
421 DIRTY_SPACE(ofs); 565 if ((err = jffs2_prealloc_raw_node_refs(c, jeb, 1)))
566 return err;
567 if ((err = jffs2_scan_dirty_space(c, jeb, ofs)))
568 return err;
422 } 569 }
423 570
424 /* Now ofs is a complete physical flash offset as it always was... */ 571 /* Now ofs is a complete physical flash offset as it always was... */
@@ -433,6 +580,11 @@ scan_more:
433 580
434 jffs2_dbg_acct_paranoia_check_nolock(c, jeb); 581 jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
435 582
583 /* Make sure there are node refs available for use */
584 err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
585 if (err)
586 return err;
587
436 cond_resched(); 588 cond_resched();
437 589
438 if (ofs & 3) { 590 if (ofs & 3) {
@@ -442,7 +594,8 @@ scan_more:
442 } 594 }
443 if (ofs == prevofs) { 595 if (ofs == prevofs) {
444 printk(KERN_WARNING "ofs 0x%08x has already been seen. Skipping\n", ofs); 596 printk(KERN_WARNING "ofs 0x%08x has already been seen. Skipping\n", ofs);
445 DIRTY_SPACE(4); 597 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
598 return err;
446 ofs += 4; 599 ofs += 4;
447 continue; 600 continue;
448 } 601 }
@@ -451,7 +604,8 @@ scan_more:
451 if (jeb->offset + c->sector_size < ofs + sizeof(*node)) { 604 if (jeb->offset + c->sector_size < ofs + sizeof(*node)) {
452 D1(printk(KERN_DEBUG "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading\n", sizeof(struct jffs2_unknown_node), 605 D1(printk(KERN_DEBUG "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading\n", sizeof(struct jffs2_unknown_node),
453 jeb->offset, c->sector_size, ofs, sizeof(*node))); 606 jeb->offset, c->sector_size, ofs, sizeof(*node)));
454 DIRTY_SPACE((jeb->offset + c->sector_size)-ofs); 607 if ((err = jffs2_scan_dirty_space(c, jeb, (jeb->offset + c->sector_size)-ofs)))
608 return err;
455 break; 609 break;
456 } 610 }
457 611
@@ -481,7 +635,8 @@ scan_more:
481 if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) { 635 if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) {
482 printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", 636 printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n",
483 empty_start, ofs); 637 empty_start, ofs);
484 DIRTY_SPACE(ofs-empty_start); 638 if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start)))
639 return err;
485 goto scan_more; 640 goto scan_more;
486 } 641 }
487 642
@@ -494,7 +649,7 @@ scan_more:
494 /* If we're only checking the beginning of a block with a cleanmarker, 649 /* If we're only checking the beginning of a block with a cleanmarker,
495 bail now */ 650 bail now */
496 if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && 651 if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) &&
497 c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_phys) { 652 c->cleanmarker_size && !jeb->dirty_size && !ref_next(jeb->first_node)) {
498 D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size))); 653 D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size)));
499 return BLK_STATE_CLEANMARKER; 654 return BLK_STATE_CLEANMARKER;
500 } 655 }
@@ -518,20 +673,23 @@ scan_more:
518 673
519 if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) { 674 if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) {
520 printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs); 675 printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs);
521 DIRTY_SPACE(4); 676 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
677 return err;
522 ofs += 4; 678 ofs += 4;
523 continue; 679 continue;
524 } 680 }
525 if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) { 681 if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) {
526 D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x\n", ofs)); 682 D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x\n", ofs));
527 DIRTY_SPACE(4); 683 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
684 return err;
528 ofs += 4; 685 ofs += 4;
529 continue; 686 continue;
530 } 687 }
531 if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) { 688 if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) {
532 printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs); 689 printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs);
533 printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n"); 690 printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n");
534 DIRTY_SPACE(4); 691 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
692 return err;
535 ofs += 4; 693 ofs += 4;
536 continue; 694 continue;
537 } 695 }
@@ -540,7 +698,8 @@ scan_more:
540 noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", 698 noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n",
541 JFFS2_MAGIC_BITMASK, ofs, 699 JFFS2_MAGIC_BITMASK, ofs,
542 je16_to_cpu(node->magic)); 700 je16_to_cpu(node->magic));
543 DIRTY_SPACE(4); 701 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
702 return err;
544 ofs += 4; 703 ofs += 4;
545 continue; 704 continue;
546 } 705 }
@@ -557,7 +716,8 @@ scan_more:
557 je32_to_cpu(node->totlen), 716 je32_to_cpu(node->totlen),
558 je32_to_cpu(node->hdr_crc), 717 je32_to_cpu(node->hdr_crc),
559 hdr_crc); 718 hdr_crc);
560 DIRTY_SPACE(4); 719 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
720 return err;
561 ofs += 4; 721 ofs += 4;
562 continue; 722 continue;
563 } 723 }
@@ -568,7 +728,8 @@ scan_more:
568 printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", 728 printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n",
569 ofs, je32_to_cpu(node->totlen)); 729 ofs, je32_to_cpu(node->totlen));
570 printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n"); 730 printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n");
571 DIRTY_SPACE(4); 731 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
732 return err;
572 ofs += 4; 733 ofs += 4;
573 continue; 734 continue;
574 } 735 }
@@ -576,7 +737,8 @@ scan_more:
576 if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) { 737 if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) {
577 /* Wheee. This is an obsoleted node */ 738 /* Wheee. This is an obsoleted node */
578 D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs)); 739 D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs));
579 DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); 740 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
741 return err;
580 ofs += PAD(je32_to_cpu(node->totlen)); 742 ofs += PAD(je32_to_cpu(node->totlen));
581 continue; 743 continue;
582 } 744 }
@@ -614,30 +776,59 @@ scan_more:
614 ofs += PAD(je32_to_cpu(node->totlen)); 776 ofs += PAD(je32_to_cpu(node->totlen));
615 break; 777 break;
616 778
779#ifdef CONFIG_JFFS2_FS_XATTR
780 case JFFS2_NODETYPE_XATTR:
781 if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
782 buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
783 D1(printk(KERN_DEBUG "Fewer than %d bytes (xattr node)"
784 " left to end of buf. Reading 0x%x at 0x%08x\n",
785 je32_to_cpu(node->totlen), buf_len, ofs));
786 err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
787 if (err)
788 return err;
789 buf_ofs = ofs;
790 node = (void *)buf;
791 }
792 err = jffs2_scan_xattr_node(c, jeb, (void *)node, ofs, s);
793 if (err)
794 return err;
795 ofs += PAD(je32_to_cpu(node->totlen));
796 break;
797 case JFFS2_NODETYPE_XREF:
798 if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
799 buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
800 D1(printk(KERN_DEBUG "Fewer than %d bytes (xref node)"
801 " left to end of buf. Reading 0x%x at 0x%08x\n",
802 je32_to_cpu(node->totlen), buf_len, ofs));
803 err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
804 if (err)
805 return err;
806 buf_ofs = ofs;
807 node = (void *)buf;
808 }
809 err = jffs2_scan_xref_node(c, jeb, (void *)node, ofs, s);
810 if (err)
811 return err;
812 ofs += PAD(je32_to_cpu(node->totlen));
813 break;
814#endif /* CONFIG_JFFS2_FS_XATTR */
815
617 case JFFS2_NODETYPE_CLEANMARKER: 816 case JFFS2_NODETYPE_CLEANMARKER:
618 D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); 817 D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs));
619 if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { 818 if (je32_to_cpu(node->totlen) != c->cleanmarker_size) {
620 printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", 819 printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n",
621 ofs, je32_to_cpu(node->totlen), c->cleanmarker_size); 820 ofs, je32_to_cpu(node->totlen), c->cleanmarker_size);
622 DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); 821 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
822 return err;
623 ofs += PAD(sizeof(struct jffs2_unknown_node)); 823 ofs += PAD(sizeof(struct jffs2_unknown_node));
624 } else if (jeb->first_node) { 824 } else if (jeb->first_node) {
625 printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset); 825 printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset);
626 DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); 826 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
827 return err;
627 ofs += PAD(sizeof(struct jffs2_unknown_node)); 828 ofs += PAD(sizeof(struct jffs2_unknown_node));
628 } else { 829 } else {
629 struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); 830 jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL);
630 if (!marker_ref) {
631 printk(KERN_NOTICE "Failed to allocate node ref for clean marker\n");
632 return -ENOMEM;
633 }
634 marker_ref->next_in_ino = NULL;
635 marker_ref->next_phys = NULL;
636 marker_ref->flash_offset = ofs | REF_NORMAL;
637 marker_ref->__totlen = c->cleanmarker_size;
638 jeb->first_node = jeb->last_node = marker_ref;
639 831
640 USED_SPACE(PAD(c->cleanmarker_size));
641 ofs += PAD(c->cleanmarker_size); 832 ofs += PAD(c->cleanmarker_size);
642 } 833 }
643 break; 834 break;
@@ -645,7 +836,8 @@ scan_more:
645 case JFFS2_NODETYPE_PADDING: 836 case JFFS2_NODETYPE_PADDING:
646 if (jffs2_sum_active()) 837 if (jffs2_sum_active())
647 jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen)); 838 jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen));
648 DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); 839 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
840 return err;
649 ofs += PAD(je32_to_cpu(node->totlen)); 841 ofs += PAD(je32_to_cpu(node->totlen));
650 break; 842 break;
651 843
@@ -656,7 +848,8 @@ scan_more:
656 c->flags |= JFFS2_SB_FLAG_RO; 848 c->flags |= JFFS2_SB_FLAG_RO;
657 if (!(jffs2_is_readonly(c))) 849 if (!(jffs2_is_readonly(c)))
658 return -EROFS; 850 return -EROFS;
659 DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); 851 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
852 return err;
660 ofs += PAD(je32_to_cpu(node->totlen)); 853 ofs += PAD(je32_to_cpu(node->totlen));
661 break; 854 break;
662 855
@@ -666,15 +859,21 @@ scan_more:
666 859
667 case JFFS2_FEATURE_RWCOMPAT_DELETE: 860 case JFFS2_FEATURE_RWCOMPAT_DELETE:
668 D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); 861 D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
669 DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); 862 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
863 return err;
670 ofs += PAD(je32_to_cpu(node->totlen)); 864 ofs += PAD(je32_to_cpu(node->totlen));
671 break; 865 break;
672 866
673 case JFFS2_FEATURE_RWCOMPAT_COPY: 867 case JFFS2_FEATURE_RWCOMPAT_COPY: {
674 D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); 868 D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
675 USED_SPACE(PAD(je32_to_cpu(node->totlen))); 869
870 jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(node->totlen)), NULL);
871
872 /* We can't summarise nodes we don't grok */
873 jffs2_sum_disable_collecting(s);
676 ofs += PAD(je32_to_cpu(node->totlen)); 874 ofs += PAD(je32_to_cpu(node->totlen));
677 break; 875 break;
876 }
678 } 877 }
679 } 878 }
680 } 879 }
@@ -687,9 +886,9 @@ scan_more:
687 } 886 }
688 } 887 }
689 888
690 D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, 889 D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n",
691 jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size)); 890 jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size));
692 891
693 /* mark_node_obsolete can add to wasted !! */ 892 /* mark_node_obsolete can add to wasted !! */
694 if (jeb->wasted_size) { 893 if (jeb->wasted_size) {
695 jeb->dirty_size += jeb->wasted_size; 894 jeb->dirty_size += jeb->wasted_size;
@@ -730,9 +929,9 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin
730static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 929static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
731 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) 930 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s)
732{ 931{
733 struct jffs2_raw_node_ref *raw;
734 struct jffs2_inode_cache *ic; 932 struct jffs2_inode_cache *ic;
735 uint32_t ino = je32_to_cpu(ri->ino); 933 uint32_t ino = je32_to_cpu(ri->ino);
934 int err;
736 935
737 D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); 936 D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs));
738 937
@@ -745,12 +944,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
745 Which means that the _full_ amount of time to get to proper write mode with GC 944 Which means that the _full_ amount of time to get to proper write mode with GC
746 operational may actually be _longer_ than before. Sucks to be me. */ 945 operational may actually be _longer_ than before. Sucks to be me. */
747 946
748 raw = jffs2_alloc_raw_node_ref();
749 if (!raw) {
750 printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n");
751 return -ENOMEM;
752 }
753
754 ic = jffs2_get_ino_cache(c, ino); 947 ic = jffs2_get_ino_cache(c, ino);
755 if (!ic) { 948 if (!ic) {
756 /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the 949 /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the
@@ -762,30 +955,17 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
762 printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", 955 printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
763 ofs, je32_to_cpu(ri->node_crc), crc); 956 ofs, je32_to_cpu(ri->node_crc), crc);
764 /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ 957 /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
765 DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen))); 958 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen)))))
766 jffs2_free_raw_node_ref(raw); 959 return err;
767 return 0; 960 return 0;
768 } 961 }
769 ic = jffs2_scan_make_ino_cache(c, ino); 962 ic = jffs2_scan_make_ino_cache(c, ino);
770 if (!ic) { 963 if (!ic)
771 jffs2_free_raw_node_ref(raw);
772 return -ENOMEM; 964 return -ENOMEM;
773 }
774 } 965 }
775 966
776 /* Wheee. It worked */ 967 /* Wheee. It worked */
777 968 jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic);
778 raw->flash_offset = ofs | REF_UNCHECKED;
779 raw->__totlen = PAD(je32_to_cpu(ri->totlen));
780 raw->next_phys = NULL;
781 raw->next_in_ino = ic->nodes;
782
783 ic->nodes = raw;
784 if (!jeb->first_node)
785 jeb->first_node = raw;
786 if (jeb->last_node)
787 jeb->last_node->next_phys = raw;
788 jeb->last_node = raw;
789 969
790 D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", 970 D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n",
791 je32_to_cpu(ri->ino), je32_to_cpu(ri->version), 971 je32_to_cpu(ri->ino), je32_to_cpu(ri->version),
@@ -794,8 +974,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
794 974
795 pseudo_random += je32_to_cpu(ri->version); 975 pseudo_random += je32_to_cpu(ri->version);
796 976
797 UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen)));
798
799 if (jffs2_sum_active()) { 977 if (jffs2_sum_active()) {
800 jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset); 978 jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset);
801 } 979 }
@@ -806,10 +984,10 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
806static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 984static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
807 struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s) 985 struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s)
808{ 986{
809 struct jffs2_raw_node_ref *raw;
810 struct jffs2_full_dirent *fd; 987 struct jffs2_full_dirent *fd;
811 struct jffs2_inode_cache *ic; 988 struct jffs2_inode_cache *ic;
812 uint32_t crc; 989 uint32_t crc;
990 int err;
813 991
814 D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs)); 992 D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs));
815 993
@@ -821,7 +999,8 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
821 printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", 999 printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
822 ofs, je32_to_cpu(rd->node_crc), crc); 1000 ofs, je32_to_cpu(rd->node_crc), crc);
823 /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ 1001 /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
824 DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); 1002 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
1003 return err;
825 return 0; 1004 return 0;
826 } 1005 }
827 1006
@@ -842,40 +1021,23 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
842 jffs2_free_full_dirent(fd); 1021 jffs2_free_full_dirent(fd);
843 /* FIXME: Why do we believe totlen? */ 1022 /* FIXME: Why do we believe totlen? */
844 /* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */ 1023 /* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */
845 DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); 1024 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
1025 return err;
846 return 0; 1026 return 0;
847 } 1027 }
848 raw = jffs2_alloc_raw_node_ref();
849 if (!raw) {
850 jffs2_free_full_dirent(fd);
851 printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n");
852 return -ENOMEM;
853 }
854 ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino)); 1028 ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino));
855 if (!ic) { 1029 if (!ic) {
856 jffs2_free_full_dirent(fd); 1030 jffs2_free_full_dirent(fd);
857 jffs2_free_raw_node_ref(raw);
858 return -ENOMEM; 1031 return -ENOMEM;
859 } 1032 }
860 1033
861 raw->__totlen = PAD(je32_to_cpu(rd->totlen)); 1034 fd->raw = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rd->totlen)), ic);
862 raw->flash_offset = ofs | REF_PRISTINE;
863 raw->next_phys = NULL;
864 raw->next_in_ino = ic->nodes;
865 ic->nodes = raw;
866 if (!jeb->first_node)
867 jeb->first_node = raw;
868 if (jeb->last_node)
869 jeb->last_node->next_phys = raw;
870 jeb->last_node = raw;
871 1035
872 fd->raw = raw;
873 fd->next = NULL; 1036 fd->next = NULL;
874 fd->version = je32_to_cpu(rd->version); 1037 fd->version = je32_to_cpu(rd->version);
875 fd->ino = je32_to_cpu(rd->ino); 1038 fd->ino = je32_to_cpu(rd->ino);
876 fd->nhash = full_name_hash(fd->name, rd->nsize); 1039 fd->nhash = full_name_hash(fd->name, rd->nsize);
877 fd->type = rd->type; 1040 fd->type = rd->type;
878 USED_SPACE(PAD(je32_to_cpu(rd->totlen)));
879 jffs2_add_fd_to_list(c, fd, &ic->scan_dents); 1041 jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
880 1042
881 if (jffs2_sum_active()) { 1043 if (jffs2_sum_active()) {
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
new file mode 100644
index 000000000000..52a9894a6364
--- /dev/null
+++ b/fs/jffs2/security.c
@@ -0,0 +1,82 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
11#include <linux/kernel.h>
12#include <linux/slab.h>
13#include <linux/fs.h>
14#include <linux/time.h>
15#include <linux/pagemap.h>
16#include <linux/highmem.h>
17#include <linux/crc32.h>
18#include <linux/jffs2.h>
19#include <linux/xattr.h>
20#include <linux/mtd/mtd.h>
21#include <linux/security.h>
22#include "nodelist.h"
23
24/* ---- Initial Security Label Attachment -------------- */
25int jffs2_init_security(struct inode *inode, struct inode *dir)
26{
27 int rc;
28 size_t len;
29 void *value;
30 char *name;
31
32 rc = security_inode_init_security(inode, dir, &name, &value, &len);
33 if (rc) {
34 if (rc == -EOPNOTSUPP)
35 return 0;
36 return rc;
37 }
38 rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
39
40 kfree(name);
41 kfree(value);
42 return rc;
43}
44
45/* ---- XATTR Handler for "security.*" ----------------- */
46static int jffs2_security_getxattr(struct inode *inode, const char *name,
47 void *buffer, size_t size)
48{
49 if (!strcmp(name, ""))
50 return -EINVAL;
51
52 return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size);
53}
54
55static int jffs2_security_setxattr(struct inode *inode, const char *name, const void *buffer,
56 size_t size, int flags)
57{
58 if (!strcmp(name, ""))
59 return -EINVAL;
60
61 return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size, flags);
62}
63
64static size_t jffs2_security_listxattr(struct inode *inode, char *list, size_t list_size,
65 const char *name, size_t name_len)
66{
67 size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1;
68
69 if (list && retlen <= list_size) {
70 strcpy(list, XATTR_SECURITY_PREFIX);
71 strcpy(list + XATTR_SECURITY_PREFIX_LEN, name);
72 }
73
74 return retlen;
75}
76
77struct xattr_handler jffs2_security_xattr_handler = {
78 .prefix = XATTR_SECURITY_PREFIX,
79 .list = jffs2_security_listxattr,
80 .set = jffs2_security_setxattr,
81 .get = jffs2_security_getxattr
82};
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index fb9cec61fcf2..0b02fc79e4d1 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -5,6 +5,7 @@
5 * Zoltan Sogor <weth@inf.u-szeged.hu>, 5 * Zoltan Sogor <weth@inf.u-szeged.hu>,
6 * Patrik Kluba <pajko@halom.u-szeged.hu>, 6 * Patrik Kluba <pajko@halom.u-szeged.hu>,
7 * University of Szeged, Hungary 7 * University of Szeged, Hungary
8 * 2005 KaiGai Kohei <kaigai@ak.jp.nec.com>
8 * 9 *
9 * For licensing information, see the file 'LICENCE' in this directory. 10 * For licensing information, see the file 'LICENCE' in this directory.
10 * 11 *
@@ -81,6 +82,19 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item)
81 dbg_summary("dirent (%u) added to summary\n", 82 dbg_summary("dirent (%u) added to summary\n",
82 je32_to_cpu(item->d.ino)); 83 je32_to_cpu(item->d.ino));
83 break; 84 break;
85#ifdef CONFIG_JFFS2_FS_XATTR
86 case JFFS2_NODETYPE_XATTR:
87 s->sum_size += JFFS2_SUMMARY_XATTR_SIZE;
88 s->sum_num++;
89 dbg_summary("xattr (xid=%u, version=%u) added to summary\n",
90 je32_to_cpu(item->x.xid), je32_to_cpu(item->x.version));
91 break;
92 case JFFS2_NODETYPE_XREF:
93 s->sum_size += JFFS2_SUMMARY_XREF_SIZE;
94 s->sum_num++;
95 dbg_summary("xref added to summary\n");
96 break;
97#endif
84 default: 98 default:
85 JFFS2_WARNING("UNKNOWN node type %u\n", 99 JFFS2_WARNING("UNKNOWN node type %u\n",
86 je16_to_cpu(item->u.nodetype)); 100 je16_to_cpu(item->u.nodetype));
@@ -141,6 +155,40 @@ int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *r
141 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); 155 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
142} 156}
143 157
158#ifdef CONFIG_JFFS2_FS_XATTR
159int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs)
160{
161 struct jffs2_sum_xattr_mem *temp;
162
163 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
164 if (!temp)
165 return -ENOMEM;
166
167 temp->nodetype = rx->nodetype;
168 temp->xid = rx->xid;
169 temp->version = rx->version;
170 temp->offset = cpu_to_je32(ofs);
171 temp->totlen = rx->totlen;
172 temp->next = NULL;
173
174 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
175}
176
177int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs)
178{
179 struct jffs2_sum_xref_mem *temp;
180
181 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
182 if (!temp)
183 return -ENOMEM;
184
185 temp->nodetype = rr->nodetype;
186 temp->offset = cpu_to_je32(ofs);
187 temp->next = NULL;
188
189 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
190}
191#endif
144/* Cleanup every collected summary information */ 192/* Cleanup every collected summary information */
145 193
146static void jffs2_sum_clean_collected(struct jffs2_summary *s) 194static void jffs2_sum_clean_collected(struct jffs2_summary *s)
@@ -259,7 +307,40 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
259 307
260 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); 308 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
261 } 309 }
310#ifdef CONFIG_JFFS2_FS_XATTR
311 case JFFS2_NODETYPE_XATTR: {
312 struct jffs2_sum_xattr_mem *temp;
313 if (je32_to_cpu(node->x.version) == 0xffffffff)
314 return 0;
315 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
316 if (!temp)
317 goto no_mem;
318
319 temp->nodetype = node->x.nodetype;
320 temp->xid = node->x.xid;
321 temp->version = node->x.version;
322 temp->totlen = node->x.totlen;
323 temp->offset = cpu_to_je32(ofs);
324 temp->next = NULL;
325
326 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
327 }
328 case JFFS2_NODETYPE_XREF: {
329 struct jffs2_sum_xref_mem *temp;
330
331 if (je32_to_cpu(node->r.ino) == 0xffffffff
332 && je32_to_cpu(node->r.xid) == 0xffffffff)
333 return 0;
334 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
335 if (!temp)
336 goto no_mem;
337 temp->nodetype = node->r.nodetype;
338 temp->offset = cpu_to_je32(ofs);
339 temp->next = NULL;
262 340
341 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
342 }
343#endif
263 case JFFS2_NODETYPE_PADDING: 344 case JFFS2_NODETYPE_PADDING:
264 dbg_summary("node PADDING\n"); 345 dbg_summary("node PADDING\n");
265 c->summary->sum_padded += je32_to_cpu(node->u.totlen); 346 c->summary->sum_padded += je32_to_cpu(node->u.totlen);
@@ -288,23 +369,41 @@ no_mem:
288 return -ENOMEM; 369 return -ENOMEM;
289} 370}
290 371
372static struct jffs2_raw_node_ref *sum_link_node_ref(struct jffs2_sb_info *c,
373 struct jffs2_eraseblock *jeb,
374 uint32_t ofs, uint32_t len,
375 struct jffs2_inode_cache *ic)
376{
377 /* If there was a gap, mark it dirty */
378 if ((ofs & ~3) > c->sector_size - jeb->free_size) {
379 /* Ew. Summary doesn't actually tell us explicitly about dirty space */
380 jffs2_scan_dirty_space(c, jeb, (ofs & ~3) - (c->sector_size - jeb->free_size));
381 }
382
383 return jffs2_link_node_ref(c, jeb, jeb->offset + ofs, len, ic);
384}
291 385
292/* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ 386/* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */
293 387
294static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 388static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
295 struct jffs2_raw_summary *summary, uint32_t *pseudo_random) 389 struct jffs2_raw_summary *summary, uint32_t *pseudo_random)
296{ 390{
297 struct jffs2_raw_node_ref *raw;
298 struct jffs2_inode_cache *ic; 391 struct jffs2_inode_cache *ic;
299 struct jffs2_full_dirent *fd; 392 struct jffs2_full_dirent *fd;
300 void *sp; 393 void *sp;
301 int i, ino; 394 int i, ino;
395 int err;
302 396
303 sp = summary->sum; 397 sp = summary->sum;
304 398
305 for (i=0; i<je32_to_cpu(summary->sum_num); i++) { 399 for (i=0; i<je32_to_cpu(summary->sum_num); i++) {
306 dbg_summary("processing summary index %d\n", i); 400 dbg_summary("processing summary index %d\n", i);
307 401
402 /* Make sure there's a spare ref for dirty space */
403 err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
404 if (err)
405 return err;
406
308 switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { 407 switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) {
309 case JFFS2_NODETYPE_INODE: { 408 case JFFS2_NODETYPE_INODE: {
310 struct jffs2_sum_inode_flash *spi; 409 struct jffs2_sum_inode_flash *spi;
@@ -312,38 +411,20 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
312 411
313 ino = je32_to_cpu(spi->inode); 412 ino = je32_to_cpu(spi->inode);
314 413
315 dbg_summary("Inode at 0x%08x\n", 414 dbg_summary("Inode at 0x%08x-0x%08x\n",
316 jeb->offset + je32_to_cpu(spi->offset)); 415 jeb->offset + je32_to_cpu(spi->offset),
317 416 jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spi->totlen));
318 raw = jffs2_alloc_raw_node_ref();
319 if (!raw) {
320 JFFS2_NOTICE("allocation of node reference failed\n");
321 kfree(summary);
322 return -ENOMEM;
323 }
324 417
325 ic = jffs2_scan_make_ino_cache(c, ino); 418 ic = jffs2_scan_make_ino_cache(c, ino);
326 if (!ic) { 419 if (!ic) {
327 JFFS2_NOTICE("scan_make_ino_cache failed\n"); 420 JFFS2_NOTICE("scan_make_ino_cache failed\n");
328 jffs2_free_raw_node_ref(raw);
329 kfree(summary);
330 return -ENOMEM; 421 return -ENOMEM;
331 } 422 }
332 423
333 raw->flash_offset = (jeb->offset + je32_to_cpu(spi->offset)) | REF_UNCHECKED; 424 sum_link_node_ref(c, jeb, je32_to_cpu(spi->offset) | REF_UNCHECKED,
334 raw->__totlen = PAD(je32_to_cpu(spi->totlen)); 425 PAD(je32_to_cpu(spi->totlen)), ic);
335 raw->next_phys = NULL;
336 raw->next_in_ino = ic->nodes;
337
338 ic->nodes = raw;
339 if (!jeb->first_node)
340 jeb->first_node = raw;
341 if (jeb->last_node)
342 jeb->last_node->next_phys = raw;
343 jeb->last_node = raw;
344 *pseudo_random += je32_to_cpu(spi->version);
345 426
346 UNCHECKED_SPACE(PAD(je32_to_cpu(spi->totlen))); 427 *pseudo_random += je32_to_cpu(spi->version);
347 428
348 sp += JFFS2_SUMMARY_INODE_SIZE; 429 sp += JFFS2_SUMMARY_INODE_SIZE;
349 430
@@ -354,52 +435,33 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
354 struct jffs2_sum_dirent_flash *spd; 435 struct jffs2_sum_dirent_flash *spd;
355 spd = sp; 436 spd = sp;
356 437
357 dbg_summary("Dirent at 0x%08x\n", 438 dbg_summary("Dirent at 0x%08x-0x%08x\n",
358 jeb->offset + je32_to_cpu(spd->offset)); 439 jeb->offset + je32_to_cpu(spd->offset),
440 jeb->offset + je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen));
441
359 442
360 fd = jffs2_alloc_full_dirent(spd->nsize+1); 443 fd = jffs2_alloc_full_dirent(spd->nsize+1);
361 if (!fd) { 444 if (!fd)
362 kfree(summary);
363 return -ENOMEM; 445 return -ENOMEM;
364 }
365 446
366 memcpy(&fd->name, spd->name, spd->nsize); 447 memcpy(&fd->name, spd->name, spd->nsize);
367 fd->name[spd->nsize] = 0; 448 fd->name[spd->nsize] = 0;
368 449
369 raw = jffs2_alloc_raw_node_ref();
370 if (!raw) {
371 jffs2_free_full_dirent(fd);
372 JFFS2_NOTICE("allocation of node reference failed\n");
373 kfree(summary);
374 return -ENOMEM;
375 }
376
377 ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); 450 ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino));
378 if (!ic) { 451 if (!ic) {
379 jffs2_free_full_dirent(fd); 452 jffs2_free_full_dirent(fd);
380 jffs2_free_raw_node_ref(raw);
381 kfree(summary);
382 return -ENOMEM; 453 return -ENOMEM;
383 } 454 }
384 455
385 raw->__totlen = PAD(je32_to_cpu(spd->totlen)); 456 fd->raw = sum_link_node_ref(c, jeb, je32_to_cpu(spd->offset) | REF_UNCHECKED,
386 raw->flash_offset = (jeb->offset + je32_to_cpu(spd->offset)) | REF_PRISTINE; 457 PAD(je32_to_cpu(spd->totlen)), ic);
387 raw->next_phys = NULL; 458
388 raw->next_in_ino = ic->nodes;
389 ic->nodes = raw;
390 if (!jeb->first_node)
391 jeb->first_node = raw;
392 if (jeb->last_node)
393 jeb->last_node->next_phys = raw;
394 jeb->last_node = raw;
395
396 fd->raw = raw;
397 fd->next = NULL; 459 fd->next = NULL;
398 fd->version = je32_to_cpu(spd->version); 460 fd->version = je32_to_cpu(spd->version);
399 fd->ino = je32_to_cpu(spd->ino); 461 fd->ino = je32_to_cpu(spd->ino);
400 fd->nhash = full_name_hash(fd->name, spd->nsize); 462 fd->nhash = full_name_hash(fd->name, spd->nsize);
401 fd->type = spd->type; 463 fd->type = spd->type;
402 USED_SPACE(PAD(je32_to_cpu(spd->totlen))); 464
403 jffs2_add_fd_to_list(c, fd, &ic->scan_dents); 465 jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
404 466
405 *pseudo_random += je32_to_cpu(spd->version); 467 *pseudo_random += je32_to_cpu(spd->version);
@@ -408,48 +470,105 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
408 470
409 break; 471 break;
410 } 472 }
473#ifdef CONFIG_JFFS2_FS_XATTR
474 case JFFS2_NODETYPE_XATTR: {
475 struct jffs2_xattr_datum *xd;
476 struct jffs2_sum_xattr_flash *spx;
477
478 spx = (struct jffs2_sum_xattr_flash *)sp;
479 dbg_summary("xattr at %#08x-%#08x (xid=%u, version=%u)\n",
480 jeb->offset + je32_to_cpu(spx->offset),
481 jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen),
482 je32_to_cpu(spx->xid), je32_to_cpu(spx->version));
483
484 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
485 je32_to_cpu(spx->version));
486 if (IS_ERR(xd)) {
487 if (PTR_ERR(xd) == -EEXIST) {
488 /* a newer version of xd exists */
489 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen))))
490 return err;
491 sp += JFFS2_SUMMARY_XATTR_SIZE;
492 break;
493 }
494 JFFS2_NOTICE("allocation of xattr_datum failed\n");
495 return PTR_ERR(xd);
496 }
497
498 xd->node = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
499 PAD(je32_to_cpu(spx->totlen)), NULL);
500 /* FIXME */ xd->node->next_in_ino = (void *)xd;
501
502 *pseudo_random += je32_to_cpu(spx->xid);
503 sp += JFFS2_SUMMARY_XATTR_SIZE;
504
505 break;
506 }
507 case JFFS2_NODETYPE_XREF: {
508 struct jffs2_xattr_ref *ref;
509 struct jffs2_sum_xref_flash *spr;
510
511 spr = (struct jffs2_sum_xref_flash *)sp;
512 dbg_summary("xref at %#08x-%#08x\n",
513 jeb->offset + je32_to_cpu(spr->offset),
514 jeb->offset + je32_to_cpu(spr->offset) +
515 (uint32_t)PAD(sizeof(struct jffs2_raw_xref)));
516
517 ref = jffs2_alloc_xattr_ref();
518 if (!ref) {
519 JFFS2_NOTICE("allocation of xattr_datum failed\n");
520 return -ENOMEM;
521 }
522 ref->ino = 0xfffffffe;
523 ref->xid = 0xfffffffd;
524 ref->next = c->xref_temp;
525 c->xref_temp = ref;
411 526
527 ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
528 PAD(sizeof(struct jffs2_raw_xref)), NULL);
529 /* FIXME */ ref->node->next_in_ino = (void *)ref;
530
531 *pseudo_random += ref->node->flash_offset;
532 sp += JFFS2_SUMMARY_XREF_SIZE;
533
534 break;
535 }
536#endif
412 default : { 537 default : {
413 JFFS2_WARNING("Unsupported node type found in summary! Exiting..."); 538 uint16_t nodetype = je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype);
414 kfree(summary); 539 JFFS2_WARNING("Unsupported node type %x found in summary! Exiting...\n", nodetype);
415 return -EIO; 540 if ((nodetype & JFFS2_COMPAT_MASK) == JFFS2_FEATURE_INCOMPAT)
541 return -EIO;
542
543 /* For compatible node types, just fall back to the full scan */
544 c->wasted_size -= jeb->wasted_size;
545 c->free_size += c->sector_size - jeb->free_size;
546 c->used_size -= jeb->used_size;
547 c->dirty_size -= jeb->dirty_size;
548 jeb->wasted_size = jeb->used_size = jeb->dirty_size = 0;
549 jeb->free_size = c->sector_size;
550
551 jffs2_free_jeb_node_refs(c, jeb);
552 return -ENOTRECOVERABLE;
416 } 553 }
417 } 554 }
418 } 555 }
419
420 kfree(summary);
421 return 0; 556 return 0;
422} 557}
423 558
424/* Process the summary node - called from jffs2_scan_eraseblock() */ 559/* Process the summary node - called from jffs2_scan_eraseblock() */
425
426int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 560int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
427 uint32_t ofs, uint32_t *pseudo_random) 561 struct jffs2_raw_summary *summary, uint32_t sumsize,
562 uint32_t *pseudo_random)
428{ 563{
429 struct jffs2_unknown_node crcnode; 564 struct jffs2_unknown_node crcnode;
430 struct jffs2_raw_node_ref *cache_ref; 565 int ret, ofs;
431 struct jffs2_raw_summary *summary;
432 int ret, sumsize;
433 uint32_t crc; 566 uint32_t crc;
434 567
435 sumsize = c->sector_size - ofs; 568 ofs = c->sector_size - sumsize;
436 ofs += jeb->offset;
437 569
438 dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", 570 dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
439 jeb->offset, ofs, sumsize); 571 jeb->offset, jeb->offset + ofs, sumsize);
440
441 summary = kmalloc(sumsize, GFP_KERNEL);
442
443 if (!summary) {
444 return -ENOMEM;
445 }
446
447 ret = jffs2_fill_scan_buf(c, (unsigned char *)summary, ofs, sumsize);
448
449 if (ret) {
450 kfree(summary);
451 return ret;
452 }
453 572
454 /* OK, now check for node validity and CRC */ 573 /* OK, now check for node validity and CRC */
455 crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 574 crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -486,66 +605,49 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
486 605
487 dbg_summary("Summary : CLEANMARKER node \n"); 606 dbg_summary("Summary : CLEANMARKER node \n");
488 607
608 ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
609 if (ret)
610 return ret;
611
489 if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) { 612 if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) {
490 dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", 613 dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n",
491 je32_to_cpu(summary->cln_mkr), c->cleanmarker_size); 614 je32_to_cpu(summary->cln_mkr), c->cleanmarker_size);
492 UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); 615 if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
616 return ret;
493 } else if (jeb->first_node) { 617 } else if (jeb->first_node) {
494 dbg_summary("CLEANMARKER node not first node in block " 618 dbg_summary("CLEANMARKER node not first node in block "
495 "(0x%08x)\n", jeb->offset); 619 "(0x%08x)\n", jeb->offset);
496 UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); 620 if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
621 return ret;
497 } else { 622 } else {
498 struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); 623 jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL,
499 624 je32_to_cpu(summary->cln_mkr), NULL);
500 if (!marker_ref) {
501 JFFS2_NOTICE("Failed to allocate node ref for clean marker\n");
502 kfree(summary);
503 return -ENOMEM;
504 }
505
506 marker_ref->next_in_ino = NULL;
507 marker_ref->next_phys = NULL;
508 marker_ref->flash_offset = jeb->offset | REF_NORMAL;
509 marker_ref->__totlen = je32_to_cpu(summary->cln_mkr);
510 jeb->first_node = jeb->last_node = marker_ref;
511
512 USED_SPACE( PAD(je32_to_cpu(summary->cln_mkr)) );
513 } 625 }
514 } 626 }
515 627
516 if (je32_to_cpu(summary->padded)) {
517 DIRTY_SPACE(je32_to_cpu(summary->padded));
518 }
519
520 ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random); 628 ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random);
629 /* -ENOTRECOVERABLE isn't a fatal error -- it means we should do a full
630 scan of this eraseblock. So return zero */
631 if (ret == -ENOTRECOVERABLE)
632 return 0;
521 if (ret) 633 if (ret)
522 return ret; 634 return ret; /* real error */
523 635
524 /* for PARANOIA_CHECK */ 636 /* for PARANOIA_CHECK */
525 cache_ref = jffs2_alloc_raw_node_ref(); 637 ret = jffs2_prealloc_raw_node_refs(c, jeb, 2);
526 638 if (ret)
527 if (!cache_ref) { 639 return ret;
528 JFFS2_NOTICE("Failed to allocate node ref for cache\n");
529 return -ENOMEM;
530 }
531
532 cache_ref->next_in_ino = NULL;
533 cache_ref->next_phys = NULL;
534 cache_ref->flash_offset = ofs | REF_NORMAL;
535 cache_ref->__totlen = sumsize;
536
537 if (!jeb->first_node)
538 jeb->first_node = cache_ref;
539 if (jeb->last_node)
540 jeb->last_node->next_phys = cache_ref;
541 jeb->last_node = cache_ref;
542 640
543 USED_SPACE(sumsize); 641 sum_link_node_ref(c, jeb, ofs | REF_NORMAL, sumsize, NULL);
544 642
545 jeb->wasted_size += jeb->free_size; 643 if (unlikely(jeb->free_size)) {
546 c->wasted_size += jeb->free_size; 644 JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n",
547 c->free_size -= jeb->free_size; 645 jeb->free_size, jeb->offset);
548 jeb->free_size = 0; 646 jeb->wasted_size += jeb->free_size;
647 c->wasted_size += jeb->free_size;
648 c->free_size -= jeb->free_size;
649 jeb->free_size = 0;
650 }
549 651
550 return jffs2_scan_classify_jeb(c, jeb); 652 return jffs2_scan_classify_jeb(c, jeb);
551 653
@@ -564,6 +666,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
564 union jffs2_sum_mem *temp; 666 union jffs2_sum_mem *temp;
565 struct jffs2_sum_marker *sm; 667 struct jffs2_sum_marker *sm;
566 struct kvec vecs[2]; 668 struct kvec vecs[2];
669 uint32_t sum_ofs;
567 void *wpage; 670 void *wpage;
568 int ret; 671 int ret;
569 size_t retlen; 672 size_t retlen;
@@ -581,16 +684,17 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
581 wpage = c->summary->sum_buf; 684 wpage = c->summary->sum_buf;
582 685
583 while (c->summary->sum_num) { 686 while (c->summary->sum_num) {
687 temp = c->summary->sum_list_head;
584 688
585 switch (je16_to_cpu(c->summary->sum_list_head->u.nodetype)) { 689 switch (je16_to_cpu(temp->u.nodetype)) {
586 case JFFS2_NODETYPE_INODE: { 690 case JFFS2_NODETYPE_INODE: {
587 struct jffs2_sum_inode_flash *sino_ptr = wpage; 691 struct jffs2_sum_inode_flash *sino_ptr = wpage;
588 692
589 sino_ptr->nodetype = c->summary->sum_list_head->i.nodetype; 693 sino_ptr->nodetype = temp->i.nodetype;
590 sino_ptr->inode = c->summary->sum_list_head->i.inode; 694 sino_ptr->inode = temp->i.inode;
591 sino_ptr->version = c->summary->sum_list_head->i.version; 695 sino_ptr->version = temp->i.version;
592 sino_ptr->offset = c->summary->sum_list_head->i.offset; 696 sino_ptr->offset = temp->i.offset;
593 sino_ptr->totlen = c->summary->sum_list_head->i.totlen; 697 sino_ptr->totlen = temp->i.totlen;
594 698
595 wpage += JFFS2_SUMMARY_INODE_SIZE; 699 wpage += JFFS2_SUMMARY_INODE_SIZE;
596 700
@@ -600,30 +704,60 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
600 case JFFS2_NODETYPE_DIRENT: { 704 case JFFS2_NODETYPE_DIRENT: {
601 struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage; 705 struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage;
602 706
603 sdrnt_ptr->nodetype = c->summary->sum_list_head->d.nodetype; 707 sdrnt_ptr->nodetype = temp->d.nodetype;
604 sdrnt_ptr->totlen = c->summary->sum_list_head->d.totlen; 708 sdrnt_ptr->totlen = temp->d.totlen;
605 sdrnt_ptr->offset = c->summary->sum_list_head->d.offset; 709 sdrnt_ptr->offset = temp->d.offset;
606 sdrnt_ptr->pino = c->summary->sum_list_head->d.pino; 710 sdrnt_ptr->pino = temp->d.pino;
607 sdrnt_ptr->version = c->summary->sum_list_head->d.version; 711 sdrnt_ptr->version = temp->d.version;
608 sdrnt_ptr->ino = c->summary->sum_list_head->d.ino; 712 sdrnt_ptr->ino = temp->d.ino;
609 sdrnt_ptr->nsize = c->summary->sum_list_head->d.nsize; 713 sdrnt_ptr->nsize = temp->d.nsize;
610 sdrnt_ptr->type = c->summary->sum_list_head->d.type; 714 sdrnt_ptr->type = temp->d.type;
611 715
612 memcpy(sdrnt_ptr->name, c->summary->sum_list_head->d.name, 716 memcpy(sdrnt_ptr->name, temp->d.name,
613 c->summary->sum_list_head->d.nsize); 717 temp->d.nsize);
614 718
615 wpage += JFFS2_SUMMARY_DIRENT_SIZE(c->summary->sum_list_head->d.nsize); 719 wpage += JFFS2_SUMMARY_DIRENT_SIZE(temp->d.nsize);
616 720
617 break; 721 break;
618 } 722 }
723#ifdef CONFIG_JFFS2_FS_XATTR
724 case JFFS2_NODETYPE_XATTR: {
725 struct jffs2_sum_xattr_flash *sxattr_ptr = wpage;
726
727 temp = c->summary->sum_list_head;
728 sxattr_ptr->nodetype = temp->x.nodetype;
729 sxattr_ptr->xid = temp->x.xid;
730 sxattr_ptr->version = temp->x.version;
731 sxattr_ptr->offset = temp->x.offset;
732 sxattr_ptr->totlen = temp->x.totlen;
733
734 wpage += JFFS2_SUMMARY_XATTR_SIZE;
735 break;
736 }
737 case JFFS2_NODETYPE_XREF: {
738 struct jffs2_sum_xref_flash *sxref_ptr = wpage;
619 739
740 temp = c->summary->sum_list_head;
741 sxref_ptr->nodetype = temp->r.nodetype;
742 sxref_ptr->offset = temp->r.offset;
743
744 wpage += JFFS2_SUMMARY_XREF_SIZE;
745 break;
746 }
747#endif
620 default : { 748 default : {
621 BUG(); /* unknown node in summary information */ 749 if ((je16_to_cpu(temp->u.nodetype) & JFFS2_COMPAT_MASK)
750 == JFFS2_FEATURE_RWCOMPAT_COPY) {
751 dbg_summary("Writing unknown RWCOMPAT_COPY node type %x\n",
752 je16_to_cpu(temp->u.nodetype));
753 jffs2_sum_disable_collecting(c->summary);
754 } else {
755 BUG(); /* unknown node in summary information */
756 }
622 } 757 }
623 } 758 }
624 759
625 temp = c->summary->sum_list_head; 760 c->summary->sum_list_head = temp->u.next;
626 c->summary->sum_list_head = c->summary->sum_list_head->u.next;
627 kfree(temp); 761 kfree(temp);
628 762
629 c->summary->sum_num--; 763 c->summary->sum_num--;
@@ -645,25 +779,34 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
645 vecs[1].iov_base = c->summary->sum_buf; 779 vecs[1].iov_base = c->summary->sum_buf;
646 vecs[1].iov_len = datasize; 780 vecs[1].iov_len = datasize;
647 781
648 dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n", 782 sum_ofs = jeb->offset + c->sector_size - jeb->free_size;
649 jeb->offset + c->sector_size - jeb->free_size);
650 783
651 spin_unlock(&c->erase_completion_lock); 784 dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n",
652 ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size - 785 sum_ofs);
653 jeb->free_size, &retlen, 0);
654 spin_lock(&c->erase_completion_lock);
655 786
787 ret = jffs2_flash_writev(c, vecs, 2, sum_ofs, &retlen, 0);
656 788
657 if (ret || (retlen != infosize)) { 789 if (ret || (retlen != infosize)) {
658 JFFS2_WARNING("Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", 790
659 infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen); 791 JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n",
792 infosize, sum_ofs, ret, retlen);
793
794 if (retlen) {
795 /* Waste remaining space */
796 spin_lock(&c->erase_completion_lock);
797 jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL);
798 spin_unlock(&c->erase_completion_lock);
799 }
660 800
661 c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; 801 c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
662 WASTED_SPACE(infosize);
663 802
664 return 1; 803 return 0;
665 } 804 }
666 805
806 spin_lock(&c->erase_completion_lock);
807 jffs2_link_node_ref(c, jeb, sum_ofs | REF_NORMAL, infosize, NULL);
808 spin_unlock(&c->erase_completion_lock);
809
667 return 0; 810 return 0;
668} 811}
669 812
@@ -671,13 +814,16 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
671 814
672int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) 815int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
673{ 816{
674 struct jffs2_raw_node_ref *summary_ref; 817 int datasize, infosize, padsize;
675 int datasize, infosize, padsize, ret;
676 struct jffs2_eraseblock *jeb; 818 struct jffs2_eraseblock *jeb;
819 int ret;
677 820
678 dbg_summary("called\n"); 821 dbg_summary("called\n");
679 822
823 spin_unlock(&c->erase_completion_lock);
824
680 jeb = c->nextblock; 825 jeb = c->nextblock;
826 jffs2_prealloc_raw_node_refs(c, jeb, 1);
681 827
682 if (!c->summary->sum_num || !c->summary->sum_list_head) { 828 if (!c->summary->sum_num || !c->summary->sum_list_head) {
683 JFFS2_WARNING("Empty summary info!!!\n"); 829 JFFS2_WARNING("Empty summary info!!!\n");
@@ -696,35 +842,11 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
696 jffs2_sum_disable_collecting(c->summary); 842 jffs2_sum_disable_collecting(c->summary);
697 843
698 JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize); 844 JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize);
845 spin_lock(&c->erase_completion_lock);
699 return 0; 846 return 0;
700 } 847 }
701 848
702 ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); 849 ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize);
703 if (ret)
704 return 0; /* can't write out summary, block is marked as NOSUM_SIZE */
705
706 /* for ACCT_PARANOIA_CHECK */
707 spin_unlock(&c->erase_completion_lock);
708 summary_ref = jffs2_alloc_raw_node_ref();
709 spin_lock(&c->erase_completion_lock); 850 spin_lock(&c->erase_completion_lock);
710 851 return ret;
711 if (!summary_ref) {
712 JFFS2_NOTICE("Failed to allocate node ref for summary\n");
713 return -ENOMEM;
714 }
715
716 summary_ref->next_in_ino = NULL;
717 summary_ref->next_phys = NULL;
718 summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL;
719 summary_ref->__totlen = infosize;
720
721 if (!jeb->first_node)
722 jeb->first_node = summary_ref;
723 if (jeb->last_node)
724 jeb->last_node->next_phys = summary_ref;
725 jeb->last_node = summary_ref;
726
727 USED_SPACE(infosize);
728
729 return 0;
730} 852}
diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h
index b7a678be1709..6bf1f6aa4552 100644
--- a/fs/jffs2/summary.h
+++ b/fs/jffs2/summary.h
@@ -18,23 +18,6 @@
18#include <linux/uio.h> 18#include <linux/uio.h>
19#include <linux/jffs2.h> 19#include <linux/jffs2.h>
20 20
21#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \
22 c->free_size -= _x; c->dirty_size += _x; \
23 jeb->free_size -= _x ; jeb->dirty_size += _x; \
24 }while(0)
25#define USED_SPACE(x) do { typeof(x) _x = (x); \
26 c->free_size -= _x; c->used_size += _x; \
27 jeb->free_size -= _x ; jeb->used_size += _x; \
28 }while(0)
29#define WASTED_SPACE(x) do { typeof(x) _x = (x); \
30 c->free_size -= _x; c->wasted_size += _x; \
31 jeb->free_size -= _x ; jeb->wasted_size += _x; \
32 }while(0)
33#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \
34 c->free_size -= _x; c->unchecked_size += _x; \
35 jeb->free_size -= _x ; jeb->unchecked_size += _x; \
36 }while(0)
37
38#define BLK_STATE_ALLFF 0 21#define BLK_STATE_ALLFF 0
39#define BLK_STATE_CLEAN 1 22#define BLK_STATE_CLEAN 1
40#define BLK_STATE_PARTDIRTY 2 23#define BLK_STATE_PARTDIRTY 2
@@ -45,6 +28,8 @@
45#define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff 28#define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff
46#define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash)) 29#define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash))
47#define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x)) 30#define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x))
31#define JFFS2_SUMMARY_XATTR_SIZE (sizeof(struct jffs2_sum_xattr_flash))
32#define JFFS2_SUMMARY_XREF_SIZE (sizeof(struct jffs2_sum_xref_flash))
48 33
49/* Summary structures used on flash */ 34/* Summary structures used on flash */
50 35
@@ -75,11 +60,28 @@ struct jffs2_sum_dirent_flash
75 uint8_t name[0]; /* dirent name */ 60 uint8_t name[0]; /* dirent name */
76} __attribute__((packed)); 61} __attribute__((packed));
77 62
63struct jffs2_sum_xattr_flash
64{
65 jint16_t nodetype; /* == JFFS2_NODETYPE_XATR */
66 jint32_t xid; /* xattr identifier */
67 jint32_t version; /* version number */
68 jint32_t offset; /* offset on jeb */
69 jint32_t totlen; /* node length */
70} __attribute__((packed));
71
72struct jffs2_sum_xref_flash
73{
74 jint16_t nodetype; /* == JFFS2_NODETYPE_XREF */
75 jint32_t offset; /* offset on jeb */
76} __attribute__((packed));
77
78union jffs2_sum_flash 78union jffs2_sum_flash
79{ 79{
80 struct jffs2_sum_unknown_flash u; 80 struct jffs2_sum_unknown_flash u;
81 struct jffs2_sum_inode_flash i; 81 struct jffs2_sum_inode_flash i;
82 struct jffs2_sum_dirent_flash d; 82 struct jffs2_sum_dirent_flash d;
83 struct jffs2_sum_xattr_flash x;
84 struct jffs2_sum_xref_flash r;
83}; 85};
84 86
85/* Summary structures used in the memory */ 87/* Summary structures used in the memory */
@@ -114,11 +116,30 @@ struct jffs2_sum_dirent_mem
114 uint8_t name[0]; /* dirent name */ 116 uint8_t name[0]; /* dirent name */
115} __attribute__((packed)); 117} __attribute__((packed));
116 118
119struct jffs2_sum_xattr_mem
120{
121 union jffs2_sum_mem *next;
122 jint16_t nodetype;
123 jint32_t xid;
124 jint32_t version;
125 jint32_t offset;
126 jint32_t totlen;
127} __attribute__((packed));
128
129struct jffs2_sum_xref_mem
130{
131 union jffs2_sum_mem *next;
132 jint16_t nodetype;
133 jint32_t offset;
134} __attribute__((packed));
135
117union jffs2_sum_mem 136union jffs2_sum_mem
118{ 137{
119 struct jffs2_sum_unknown_mem u; 138 struct jffs2_sum_unknown_mem u;
120 struct jffs2_sum_inode_mem i; 139 struct jffs2_sum_inode_mem i;
121 struct jffs2_sum_dirent_mem d; 140 struct jffs2_sum_dirent_mem d;
141 struct jffs2_sum_xattr_mem x;
142 struct jffs2_sum_xref_mem r;
122}; 143};
123 144
124/* Summary related information stored in superblock */ 145/* Summary related information stored in superblock */
@@ -159,8 +180,11 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c);
159int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size); 180int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size);
160int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs); 181int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs);
161int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs); 182int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs);
183int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs);
184int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs);
162int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 185int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
163 uint32_t ofs, uint32_t *pseudo_random); 186 struct jffs2_raw_summary *summary, uint32_t sumlen,
187 uint32_t *pseudo_random);
164 188
165#else /* SUMMARY DISABLED */ 189#else /* SUMMARY DISABLED */
166 190
@@ -176,7 +200,9 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
176#define jffs2_sum_add_padding_mem(a,b) 200#define jffs2_sum_add_padding_mem(a,b)
177#define jffs2_sum_add_inode_mem(a,b,c) 201#define jffs2_sum_add_inode_mem(a,b,c)
178#define jffs2_sum_add_dirent_mem(a,b,c) 202#define jffs2_sum_add_dirent_mem(a,b,c)
179#define jffs2_sum_scan_sumnode(a,b,c,d) (0) 203#define jffs2_sum_add_xattr_mem(a,b,c)
204#define jffs2_sum_add_xref_mem(a,b,c)
205#define jffs2_sum_scan_sumnode(a,b,c,d,e) (0)
180 206
181#endif /* CONFIG_JFFS2_SUMMARY */ 207#endif /* CONFIG_JFFS2_SUMMARY */
182 208
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index ffd8e84b22cc..2378a662c256 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -111,9 +111,10 @@ static int jffs2_sb_set(struct super_block *sb, void *data)
111 return 0; 111 return 0;
112} 112}
113 113
114static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, 114static int jffs2_get_sb_mtd(struct file_system_type *fs_type,
115 int flags, const char *dev_name, 115 int flags, const char *dev_name,
116 void *data, struct mtd_info *mtd) 116 void *data, struct mtd_info *mtd,
117 struct vfsmount *mnt)
117{ 118{
118 struct super_block *sb; 119 struct super_block *sb;
119 struct jffs2_sb_info *c; 120 struct jffs2_sb_info *c;
@@ -121,19 +122,20 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type,
121 122
122 c = kmalloc(sizeof(*c), GFP_KERNEL); 123 c = kmalloc(sizeof(*c), GFP_KERNEL);
123 if (!c) 124 if (!c)
124 return ERR_PTR(-ENOMEM); 125 return -ENOMEM;
125 memset(c, 0, sizeof(*c)); 126 memset(c, 0, sizeof(*c));
126 c->mtd = mtd; 127 c->mtd = mtd;
127 128
128 sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); 129 sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c);
129 130
130 if (IS_ERR(sb)) 131 if (IS_ERR(sb))
131 goto out_put; 132 goto out_error;
132 133
133 if (sb->s_root) { 134 if (sb->s_root) {
134 /* New mountpoint for JFFS2 which is already mounted */ 135 /* New mountpoint for JFFS2 which is already mounted */
135 D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", 136 D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n",
136 mtd->index, mtd->name)); 137 mtd->index, mtd->name));
138 ret = simple_set_mnt(mnt, sb);
137 goto out_put; 139 goto out_put;
138 } 140 }
139 141
@@ -151,51 +153,57 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type,
151 153
152 sb->s_op = &jffs2_super_operations; 154 sb->s_op = &jffs2_super_operations;
153 sb->s_flags = flags | MS_NOATIME; 155 sb->s_flags = flags | MS_NOATIME;
154 156 sb->s_xattr = jffs2_xattr_handlers;
157#ifdef CONFIG_JFFS2_FS_POSIX_ACL
158 sb->s_flags |= MS_POSIXACL;
159#endif
155 ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); 160 ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
156 161
157 if (ret) { 162 if (ret) {
158 /* Failure case... */ 163 /* Failure case... */
159 up_write(&sb->s_umount); 164 up_write(&sb->s_umount);
160 deactivate_super(sb); 165 deactivate_super(sb);
161 return ERR_PTR(ret); 166 return ret;
162 } 167 }
163 168
164 sb->s_flags |= MS_ACTIVE; 169 sb->s_flags |= MS_ACTIVE;
165 return sb; 170 return simple_set_mnt(mnt, sb);
166 171
172out_error:
173 ret = PTR_ERR(sb);
167 out_put: 174 out_put:
168 kfree(c); 175 kfree(c);
169 put_mtd_device(mtd); 176 put_mtd_device(mtd);
170 177
171 return sb; 178 return ret;
172} 179}
173 180
174static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type, 181static int jffs2_get_sb_mtdnr(struct file_system_type *fs_type,
175 int flags, const char *dev_name, 182 int flags, const char *dev_name,
176 void *data, int mtdnr) 183 void *data, int mtdnr,
184 struct vfsmount *mnt)
177{ 185{
178 struct mtd_info *mtd; 186 struct mtd_info *mtd;
179 187
180 mtd = get_mtd_device(NULL, mtdnr); 188 mtd = get_mtd_device(NULL, mtdnr);
181 if (!mtd) { 189 if (!mtd) {
182 D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); 190 D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr));
183 return ERR_PTR(-EINVAL); 191 return -EINVAL;
184 } 192 }
185 193
186 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); 194 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
187} 195}
188 196
189static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, 197static int jffs2_get_sb(struct file_system_type *fs_type,
190 int flags, const char *dev_name, 198 int flags, const char *dev_name,
191 void *data) 199 void *data, struct vfsmount *mnt)
192{ 200{
193 int err; 201 int err;
194 struct nameidata nd; 202 struct nameidata nd;
195 int mtdnr; 203 int mtdnr;
196 204
197 if (!dev_name) 205 if (!dev_name)
198 return ERR_PTR(-EINVAL); 206 return -EINVAL;
199 207
200 D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name)); 208 D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name));
201 209
@@ -217,7 +225,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type,
217 mtd = get_mtd_device(NULL, mtdnr); 225 mtd = get_mtd_device(NULL, mtdnr);
218 if (mtd) { 226 if (mtd) {
219 if (!strcmp(mtd->name, dev_name+4)) 227 if (!strcmp(mtd->name, dev_name+4))
220 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); 228 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
221 put_mtd_device(mtd); 229 put_mtd_device(mtd);
222 } 230 }
223 } 231 }
@@ -230,7 +238,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type,
230 if (!*endptr) { 238 if (!*endptr) {
231 /* It was a valid number */ 239 /* It was a valid number */
232 D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr)); 240 D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr));
233 return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); 241 return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt);
234 } 242 }
235 } 243 }
236 } 244 }
@@ -244,7 +252,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type,
244 err, nd.dentry->d_inode)); 252 err, nd.dentry->d_inode));
245 253
246 if (err) 254 if (err)
247 return ERR_PTR(err); 255 return err;
248 256
249 err = -EINVAL; 257 err = -EINVAL;
250 258
@@ -266,11 +274,11 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type,
266 mtdnr = iminor(nd.dentry->d_inode); 274 mtdnr = iminor(nd.dentry->d_inode);
267 path_release(&nd); 275 path_release(&nd);
268 276
269 return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); 277 return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt);
270 278
271out: 279out:
272 path_release(&nd); 280 path_release(&nd);
273 return ERR_PTR(err); 281 return err;
274} 282}
275 283
276static void jffs2_put_super (struct super_block *sb) 284static void jffs2_put_super (struct super_block *sb)
@@ -293,6 +301,7 @@ static void jffs2_put_super (struct super_block *sb)
293 kfree(c->blocks); 301 kfree(c->blocks);
294 jffs2_flash_cleanup(c); 302 jffs2_flash_cleanup(c);
295 kfree(c->inocache_list); 303 kfree(c->inocache_list);
304 jffs2_clear_xattr_subsystem(c);
296 if (c->mtd->sync) 305 if (c->mtd->sync)
297 c->mtd->sync(c->mtd); 306 c->mtd->sync(c->mtd);
298 307
@@ -320,6 +329,18 @@ static int __init init_jffs2_fs(void)
320{ 329{
321 int ret; 330 int ret;
322 331
332 /* Paranoia checks for on-medium structures. If we ask GCC
333 to pack them with __attribute__((packed)) then it _also_
334 assumes that they're not aligned -- so it emits crappy
335 code on some architectures. Ideally we want an attribute
336 which means just 'no padding', without the alignment
337 thing. But GCC doesn't have that -- we have to just
338 hope the structs are the right sizes, instead. */
339 BUG_ON(sizeof(struct jffs2_unknown_node) != 12);
340 BUG_ON(sizeof(struct jffs2_raw_dirent) != 40);
341 BUG_ON(sizeof(struct jffs2_raw_inode) != 68);
342 BUG_ON(sizeof(struct jffs2_raw_summary) != 32);
343
323 printk(KERN_INFO "JFFS2 version 2.2." 344 printk(KERN_INFO "JFFS2 version 2.2."
324#ifdef CONFIG_JFFS2_FS_WRITEBUFFER 345#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
325 " (NAND)" 346 " (NAND)"
@@ -327,7 +348,7 @@ static int __init init_jffs2_fs(void)
327#ifdef CONFIG_JFFS2_SUMMARY 348#ifdef CONFIG_JFFS2_SUMMARY
328 " (SUMMARY) " 349 " (SUMMARY) "
329#endif 350#endif
330 " (C) 2001-2003 Red Hat, Inc.\n"); 351 " (C) 2001-2006 Red Hat, Inc.\n");
331 352
332 jffs2_inode_cachep = kmem_cache_create("jffs2_i", 353 jffs2_inode_cachep = kmem_cache_create("jffs2_i",
333 sizeof(struct jffs2_inode_info), 354 sizeof(struct jffs2_inode_info),
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index d55754fe8925..fc211b6e9b03 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -24,7 +24,12 @@ struct inode_operations jffs2_symlink_inode_operations =
24{ 24{
25 .readlink = generic_readlink, 25 .readlink = generic_readlink,
26 .follow_link = jffs2_follow_link, 26 .follow_link = jffs2_follow_link,
27 .setattr = jffs2_setattr 27 .permission = jffs2_permission,
28 .setattr = jffs2_setattr,
29 .setxattr = jffs2_setxattr,
30 .getxattr = jffs2_getxattr,
31 .listxattr = jffs2_listxattr,
32 .removexattr = jffs2_removexattr
28}; 33};
29 34
30static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) 35static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 4cebf0e57c46..a7f153f79ecb 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -156,69 +156,130 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock
156 jffs2_erase_pending_trigger(c); 156 jffs2_erase_pending_trigger(c);
157 } 157 }
158 158
159 /* Adjust its size counts accordingly */ 159 if (!jffs2_prealloc_raw_node_refs(c, jeb, 1)) {
160 c->wasted_size += jeb->free_size; 160 uint32_t oldfree = jeb->free_size;
161 c->free_size -= jeb->free_size; 161
162 jeb->wasted_size += jeb->free_size; 162 jffs2_link_node_ref(c, jeb,
163 jeb->free_size = 0; 163 (jeb->offset+c->sector_size-oldfree) | REF_OBSOLETE,
164 oldfree, NULL);
165 /* convert to wasted */
166 c->wasted_size += oldfree;
167 jeb->wasted_size += oldfree;
168 c->dirty_size -= oldfree;
169 jeb->dirty_size -= oldfree;
170 }
164 171
165 jffs2_dbg_dump_block_lists_nolock(c); 172 jffs2_dbg_dump_block_lists_nolock(c);
166 jffs2_dbg_acct_sanity_check_nolock(c,jeb); 173 jffs2_dbg_acct_sanity_check_nolock(c,jeb);
167 jffs2_dbg_acct_paranoia_check_nolock(c, jeb); 174 jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
168} 175}
169 176
177static struct jffs2_raw_node_ref **jffs2_incore_replace_raw(struct jffs2_sb_info *c,
178 struct jffs2_inode_info *f,
179 struct jffs2_raw_node_ref *raw,
180 union jffs2_node_union *node)
181{
182 struct jffs2_node_frag *frag;
183 struct jffs2_full_dirent *fd;
184
185 dbg_noderef("incore_replace_raw: node at %p is {%04x,%04x}\n",
186 node, je16_to_cpu(node->u.magic), je16_to_cpu(node->u.nodetype));
187
188 BUG_ON(je16_to_cpu(node->u.magic) != 0x1985 &&
189 je16_to_cpu(node->u.magic) != 0);
190
191 switch (je16_to_cpu(node->u.nodetype)) {
192 case JFFS2_NODETYPE_INODE:
193 if (f->metadata && f->metadata->raw == raw) {
194 dbg_noderef("Will replace ->raw in f->metadata at %p\n", f->metadata);
195 return &f->metadata->raw;
196 }
197 frag = jffs2_lookup_node_frag(&f->fragtree, je32_to_cpu(node->i.offset));
198 BUG_ON(!frag);
199 /* Find a frag which refers to the full_dnode we want to modify */
200 while (!frag->node || frag->node->raw != raw) {
201 frag = frag_next(frag);
202 BUG_ON(!frag);
203 }
204 dbg_noderef("Will replace ->raw in full_dnode at %p\n", frag->node);
205 return &frag->node->raw;
206
207 case JFFS2_NODETYPE_DIRENT:
208 for (fd = f->dents; fd; fd = fd->next) {
209 if (fd->raw == raw) {
210 dbg_noderef("Will replace ->raw in full_dirent at %p\n", fd);
211 return &fd->raw;
212 }
213 }
214 BUG();
215
216 default:
217 dbg_noderef("Don't care about replacing raw for nodetype %x\n",
218 je16_to_cpu(node->u.nodetype));
219 break;
220 }
221 return NULL;
222}
223
170/* Recover from failure to write wbuf. Recover the nodes up to the 224/* Recover from failure to write wbuf. Recover the nodes up to the
171 * wbuf, not the one which we were starting to try to write. */ 225 * wbuf, not the one which we were starting to try to write. */
172 226
173static void jffs2_wbuf_recover(struct jffs2_sb_info *c) 227static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
174{ 228{
175 struct jffs2_eraseblock *jeb, *new_jeb; 229 struct jffs2_eraseblock *jeb, *new_jeb;
176 struct jffs2_raw_node_ref **first_raw, **raw; 230 struct jffs2_raw_node_ref *raw, *next, *first_raw = NULL;
177 size_t retlen; 231 size_t retlen;
178 int ret; 232 int ret;
233 int nr_refile = 0;
179 unsigned char *buf; 234 unsigned char *buf;
180 uint32_t start, end, ofs, len; 235 uint32_t start, end, ofs, len;
181 236
182 spin_lock(&c->erase_completion_lock);
183
184 jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; 237 jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
185 238
239 spin_lock(&c->erase_completion_lock);
186 jffs2_block_refile(c, jeb, REFILE_NOTEMPTY); 240 jffs2_block_refile(c, jeb, REFILE_NOTEMPTY);
241 spin_unlock(&c->erase_completion_lock);
242
243 BUG_ON(!ref_obsolete(jeb->last_node));
187 244
188 /* Find the first node to be recovered, by skipping over every 245 /* Find the first node to be recovered, by skipping over every
189 node which ends before the wbuf starts, or which is obsolete. */ 246 node which ends before the wbuf starts, or which is obsolete. */
190 first_raw = &jeb->first_node; 247 for (next = raw = jeb->first_node; next; raw = next) {
191 while (*first_raw && 248 next = ref_next(raw);
192 (ref_obsolete(*first_raw) || 249
193 (ref_offset(*first_raw)+ref_totlen(c, jeb, *first_raw)) < c->wbuf_ofs)) { 250 if (ref_obsolete(raw) ||
194 D1(printk(KERN_DEBUG "Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n", 251 (next && ref_offset(next) <= c->wbuf_ofs)) {
195 ref_offset(*first_raw), ref_flags(*first_raw), 252 dbg_noderef("Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n",
196 (ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw)), 253 ref_offset(raw), ref_flags(raw),
197 c->wbuf_ofs)); 254 (ref_offset(raw) + ref_totlen(c, jeb, raw)),
198 first_raw = &(*first_raw)->next_phys; 255 c->wbuf_ofs);
256 continue;
257 }
258 dbg_noderef("First node to be recovered is at 0x%08x(%d)-0x%08x\n",
259 ref_offset(raw), ref_flags(raw),
260 (ref_offset(raw) + ref_totlen(c, jeb, raw)));
261
262 first_raw = raw;
263 break;
199 } 264 }
200 265
201 if (!*first_raw) { 266 if (!first_raw) {
202 /* All nodes were obsolete. Nothing to recover. */ 267 /* All nodes were obsolete. Nothing to recover. */
203 D1(printk(KERN_DEBUG "No non-obsolete nodes to be recovered. Just filing block bad\n")); 268 D1(printk(KERN_DEBUG "No non-obsolete nodes to be recovered. Just filing block bad\n"));
204 spin_unlock(&c->erase_completion_lock); 269 c->wbuf_len = 0;
205 return; 270 return;
206 } 271 }
207 272
208 start = ref_offset(*first_raw); 273 start = ref_offset(first_raw);
209 end = ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw); 274 end = ref_offset(jeb->last_node);
210 275 nr_refile = 1;
211 /* Find the last node to be recovered */
212 raw = first_raw;
213 while ((*raw)) {
214 if (!ref_obsolete(*raw))
215 end = ref_offset(*raw) + ref_totlen(c, jeb, *raw);
216 276
217 raw = &(*raw)->next_phys; 277 /* Count the number of refs which need to be copied */
218 } 278 while ((raw = ref_next(raw)) != jeb->last_node)
219 spin_unlock(&c->erase_completion_lock); 279 nr_refile++;
220 280
221 D1(printk(KERN_DEBUG "wbuf recover %08x-%08x\n", start, end)); 281 dbg_noderef("wbuf recover %08x-%08x (%d bytes in %d nodes)\n",
282 start, end, end - start, nr_refile);
222 283
223 buf = NULL; 284 buf = NULL;
224 if (start < c->wbuf_ofs) { 285 if (start < c->wbuf_ofs) {
@@ -233,28 +294,37 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
233 } 294 }
234 295
235 /* Do the read... */ 296 /* Do the read... */
236 if (jffs2_cleanmarker_oob(c)) 297 ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf);
237 ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo);
238 else
239 ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf);
240 298
241 if (ret == -EBADMSG && retlen == c->wbuf_ofs - start) { 299 /* ECC recovered ? */
242 /* ECC recovered */ 300 if ((ret == -EUCLEAN || ret == -EBADMSG) &&
301 (retlen == c->wbuf_ofs - start))
243 ret = 0; 302 ret = 0;
244 } 303
245 if (ret || retlen != c->wbuf_ofs - start) { 304 if (ret || retlen != c->wbuf_ofs - start) {
246 printk(KERN_CRIT "Old data are already lost in wbuf recovery. Data loss ensues.\n"); 305 printk(KERN_CRIT "Old data are already lost in wbuf recovery. Data loss ensues.\n");
247 306
248 kfree(buf); 307 kfree(buf);
249 buf = NULL; 308 buf = NULL;
250 read_failed: 309 read_failed:
251 first_raw = &(*first_raw)->next_phys; 310 first_raw = ref_next(first_raw);
311 nr_refile--;
312 while (first_raw && ref_obsolete(first_raw)) {
313 first_raw = ref_next(first_raw);
314 nr_refile--;
315 }
316
252 /* If this was the only node to be recovered, give up */ 317 /* If this was the only node to be recovered, give up */
253 if (!(*first_raw)) 318 if (!first_raw) {
319 c->wbuf_len = 0;
254 return; 320 return;
321 }
255 322
256 /* It wasn't. Go on and try to recover nodes complete in the wbuf */ 323 /* It wasn't. Go on and try to recover nodes complete in the wbuf */
257 start = ref_offset(*first_raw); 324 start = ref_offset(first_raw);
325 dbg_noderef("wbuf now recover %08x-%08x (%d bytes in %d nodes)\n",
326 start, end, end - start, nr_refile);
327
258 } else { 328 } else {
259 /* Read succeeded. Copy the remaining data from the wbuf */ 329 /* Read succeeded. Copy the remaining data from the wbuf */
260 memcpy(buf + (c->wbuf_ofs - start), c->wbuf, end - c->wbuf_ofs); 330 memcpy(buf + (c->wbuf_ofs - start), c->wbuf, end - c->wbuf_ofs);
@@ -263,14 +333,23 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
263 /* OK... we're to rewrite (end-start) bytes of data from first_raw onwards. 333 /* OK... we're to rewrite (end-start) bytes of data from first_raw onwards.
264 Either 'buf' contains the data, or we find it in the wbuf */ 334 Either 'buf' contains the data, or we find it in the wbuf */
265 335
266
267 /* ... and get an allocation of space from a shiny new block instead */ 336 /* ... and get an allocation of space from a shiny new block instead */
268 ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len, JFFS2_SUMMARY_NOSUM_SIZE); 337 ret = jffs2_reserve_space_gc(c, end-start, &len, JFFS2_SUMMARY_NOSUM_SIZE);
269 if (ret) { 338 if (ret) {
270 printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n"); 339 printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n");
271 kfree(buf); 340 kfree(buf);
272 return; 341 return;
273 } 342 }
343
344 ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, nr_refile);
345 if (ret) {
346 printk(KERN_WARNING "Failed to allocate node refs for wbuf recovery. Data loss ensues.\n");
347 kfree(buf);
348 return;
349 }
350
351 ofs = write_ofs(c);
352
274 if (end-start >= c->wbuf_pagesize) { 353 if (end-start >= c->wbuf_pagesize) {
275 /* Need to do another write immediately, but it's possible 354 /* Need to do another write immediately, but it's possible
276 that this is just because the wbuf itself is completely 355 that this is just because the wbuf itself is completely
@@ -288,36 +367,22 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
288 if (breakme++ == 20) { 367 if (breakme++ == 20) {
289 printk(KERN_NOTICE "Faking write error at 0x%08x\n", ofs); 368 printk(KERN_NOTICE "Faking write error at 0x%08x\n", ofs);
290 breakme = 0; 369 breakme = 0;
291 c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen, 370 c->mtd->write(c->mtd, ofs, towrite, &retlen,
292 brokenbuf, NULL, c->oobinfo); 371 brokenbuf);
293 ret = -EIO; 372 ret = -EIO;
294 } else 373 } else
295#endif 374#endif
296 if (jffs2_cleanmarker_oob(c)) 375 ret = c->mtd->write(c->mtd, ofs, towrite, &retlen,
297 ret = c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen, 376 rewrite_buf);
298 rewrite_buf, NULL, c->oobinfo);
299 else
300 ret = c->mtd->write(c->mtd, ofs, towrite, &retlen, rewrite_buf);
301 377
302 if (ret || retlen != towrite) { 378 if (ret || retlen != towrite) {
303 /* Argh. We tried. Really we did. */ 379 /* Argh. We tried. Really we did. */
304 printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n"); 380 printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
305 kfree(buf); 381 kfree(buf);
306 382
307 if (retlen) { 383 if (retlen)
308 struct jffs2_raw_node_ref *raw2; 384 jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, ref_totlen(c, jeb, first_raw), NULL);
309
310 raw2 = jffs2_alloc_raw_node_ref();
311 if (!raw2)
312 return;
313 385
314 raw2->flash_offset = ofs | REF_OBSOLETE;
315 raw2->__totlen = ref_totlen(c, jeb, *first_raw);
316 raw2->next_phys = NULL;
317 raw2->next_in_ino = NULL;
318
319 jffs2_add_physical_node_ref(c, raw2);
320 }
321 return; 386 return;
322 } 387 }
323 printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs); 388 printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs);
@@ -326,12 +391,10 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
326 c->wbuf_ofs = ofs + towrite; 391 c->wbuf_ofs = ofs + towrite;
327 memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len); 392 memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len);
328 /* Don't muck about with c->wbuf_inodes. False positives are harmless. */ 393 /* Don't muck about with c->wbuf_inodes. False positives are harmless. */
329 kfree(buf);
330 } else { 394 } else {
331 /* OK, now we're left with the dregs in whichever buffer we're using */ 395 /* OK, now we're left with the dregs in whichever buffer we're using */
332 if (buf) { 396 if (buf) {
333 memcpy(c->wbuf, buf, end-start); 397 memcpy(c->wbuf, buf, end-start);
334 kfree(buf);
335 } else { 398 } else {
336 memmove(c->wbuf, c->wbuf + (start - c->wbuf_ofs), end - start); 399 memmove(c->wbuf, c->wbuf + (start - c->wbuf_ofs), end - start);
337 } 400 }
@@ -343,62 +406,111 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
343 new_jeb = &c->blocks[ofs / c->sector_size]; 406 new_jeb = &c->blocks[ofs / c->sector_size];
344 407
345 spin_lock(&c->erase_completion_lock); 408 spin_lock(&c->erase_completion_lock);
346 if (new_jeb->first_node) { 409 for (raw = first_raw; raw != jeb->last_node; raw = ref_next(raw)) {
347 /* Odd, but possible with ST flash later maybe */ 410 uint32_t rawlen = ref_totlen(c, jeb, raw);
348 new_jeb->last_node->next_phys = *first_raw; 411 struct jffs2_inode_cache *ic;
349 } else { 412 struct jffs2_raw_node_ref *new_ref;
350 new_jeb->first_node = *first_raw; 413 struct jffs2_raw_node_ref **adjust_ref = NULL;
351 } 414 struct jffs2_inode_info *f = NULL;
352
353 raw = first_raw;
354 while (*raw) {
355 uint32_t rawlen = ref_totlen(c, jeb, *raw);
356 415
357 D1(printk(KERN_DEBUG "Refiling block of %08x at %08x(%d) to %08x\n", 416 D1(printk(KERN_DEBUG "Refiling block of %08x at %08x(%d) to %08x\n",
358 rawlen, ref_offset(*raw), ref_flags(*raw), ofs)); 417 rawlen, ref_offset(raw), ref_flags(raw), ofs));
418
419 ic = jffs2_raw_ref_to_ic(raw);
420
421 /* Ick. This XATTR mess should be fixed shortly... */
422 if (ic && ic->class == RAWNODE_CLASS_XATTR_DATUM) {
423 struct jffs2_xattr_datum *xd = (void *)ic;
424 BUG_ON(xd->node != raw);
425 adjust_ref = &xd->node;
426 raw->next_in_ino = NULL;
427 ic = NULL;
428 } else if (ic && ic->class == RAWNODE_CLASS_XATTR_REF) {
429 struct jffs2_xattr_datum *xr = (void *)ic;
430 BUG_ON(xr->node != raw);
431 adjust_ref = &xr->node;
432 raw->next_in_ino = NULL;
433 ic = NULL;
434 } else if (ic && ic->class == RAWNODE_CLASS_INODE_CACHE) {
435 struct jffs2_raw_node_ref **p = &ic->nodes;
436
437 /* Remove the old node from the per-inode list */
438 while (*p && *p != (void *)ic) {
439 if (*p == raw) {
440 (*p) = (raw->next_in_ino);
441 raw->next_in_ino = NULL;
442 break;
443 }
444 p = &((*p)->next_in_ino);
445 }
359 446
360 if (ref_obsolete(*raw)) { 447 if (ic->state == INO_STATE_PRESENT && !ref_obsolete(raw)) {
361 /* Shouldn't really happen much */ 448 /* If it's an in-core inode, then we have to adjust any
362 new_jeb->dirty_size += rawlen; 449 full_dirent or full_dnode structure to point to the
363 new_jeb->free_size -= rawlen; 450 new version instead of the old */
364 c->dirty_size += rawlen; 451 f = jffs2_gc_fetch_inode(c, ic->ino, ic->nlink);
365 } else { 452 if (IS_ERR(f)) {
366 new_jeb->used_size += rawlen; 453 /* Should never happen; it _must_ be present */
367 new_jeb->free_size -= rawlen; 454 JFFS2_ERROR("Failed to iget() ino #%u, err %ld\n",
455 ic->ino, PTR_ERR(f));
456 BUG();
457 }
458 /* We don't lock f->sem. There's a number of ways we could
459 end up in here with it already being locked, and nobody's
460 going to modify it on us anyway because we hold the
461 alloc_sem. We're only changing one ->raw pointer too,
462 which we can get away with without upsetting readers. */
463 adjust_ref = jffs2_incore_replace_raw(c, f, raw,
464 (void *)(buf?:c->wbuf) + (ref_offset(raw) - start));
465 } else if (unlikely(ic->state != INO_STATE_PRESENT &&
466 ic->state != INO_STATE_CHECKEDABSENT &&
467 ic->state != INO_STATE_GC)) {
468 JFFS2_ERROR("Inode #%u is in strange state %d!\n", ic->ino, ic->state);
469 BUG();
470 }
471 }
472
473 new_ref = jffs2_link_node_ref(c, new_jeb, ofs | ref_flags(raw), rawlen, ic);
474
475 if (adjust_ref) {
476 BUG_ON(*adjust_ref != raw);
477 *adjust_ref = new_ref;
478 }
479 if (f)
480 jffs2_gc_release_inode(c, f);
481
482 if (!ref_obsolete(raw)) {
368 jeb->dirty_size += rawlen; 483 jeb->dirty_size += rawlen;
369 jeb->used_size -= rawlen; 484 jeb->used_size -= rawlen;
370 c->dirty_size += rawlen; 485 c->dirty_size += rawlen;
486 c->used_size -= rawlen;
487 raw->flash_offset = ref_offset(raw) | REF_OBSOLETE;
488 BUG_ON(raw->next_in_ino);
371 } 489 }
372 c->free_size -= rawlen;
373 (*raw)->flash_offset = ofs | ref_flags(*raw);
374 ofs += rawlen; 490 ofs += rawlen;
375 new_jeb->last_node = *raw;
376
377 raw = &(*raw)->next_phys;
378 } 491 }
379 492
493 kfree(buf);
494
380 /* Fix up the original jeb now it's on the bad_list */ 495 /* Fix up the original jeb now it's on the bad_list */
381 *first_raw = NULL; 496 if (first_raw == jeb->first_node) {
382 if (first_raw == &jeb->first_node) {
383 jeb->last_node = NULL;
384 D1(printk(KERN_DEBUG "Failing block at %08x is now empty. Moving to erase_pending_list\n", jeb->offset)); 497 D1(printk(KERN_DEBUG "Failing block at %08x is now empty. Moving to erase_pending_list\n", jeb->offset));
385 list_del(&jeb->list); 498 list_del(&jeb->list);
386 list_add(&jeb->list, &c->erase_pending_list); 499 list_add(&jeb->list, &c->erase_pending_list);
387 c->nr_erasing_blocks++; 500 c->nr_erasing_blocks++;
388 jffs2_erase_pending_trigger(c); 501 jffs2_erase_pending_trigger(c);
389 } 502 }
390 else
391 jeb->last_node = container_of(first_raw, struct jffs2_raw_node_ref, next_phys);
392 503
393 jffs2_dbg_acct_sanity_check_nolock(c, jeb); 504 jffs2_dbg_acct_sanity_check_nolock(c, jeb);
394 jffs2_dbg_acct_paranoia_check_nolock(c, jeb); 505 jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
395 506
396 jffs2_dbg_acct_sanity_check_nolock(c, new_jeb); 507 jffs2_dbg_acct_sanity_check_nolock(c, new_jeb);
397 jffs2_dbg_acct_paranoia_check_nolock(c, new_jeb); 508 jffs2_dbg_acct_paranoia_check_nolock(c, new_jeb);
398 509
399 spin_unlock(&c->erase_completion_lock); 510 spin_unlock(&c->erase_completion_lock);
400 511
401 D1(printk(KERN_DEBUG "wbuf recovery completed OK\n")); 512 D1(printk(KERN_DEBUG "wbuf recovery completed OK. wbuf_ofs 0x%08x, len 0x%x\n", c->wbuf_ofs, c->wbuf_len));
513
402} 514}
403 515
404/* Meaning of pad argument: 516/* Meaning of pad argument:
@@ -412,6 +524,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
412 524
413static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) 525static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
414{ 526{
527 struct jffs2_eraseblock *wbuf_jeb;
415 int ret; 528 int ret;
416 size_t retlen; 529 size_t retlen;
417 530
@@ -429,6 +542,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
429 if (!c->wbuf_len) /* already checked c->wbuf above */ 542 if (!c->wbuf_len) /* already checked c->wbuf above */
430 return 0; 543 return 0;
431 544
545 wbuf_jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
546 if (jffs2_prealloc_raw_node_refs(c, wbuf_jeb, c->nextblock->allocated_refs + 1))
547 return -ENOMEM;
548
432 /* claim remaining space on the page 549 /* claim remaining space on the page
433 this happens, if we have a change to a new block, 550 this happens, if we have a change to a new block,
434 or if fsync forces us to flush the writebuffer. 551 or if fsync forces us to flush the writebuffer.
@@ -458,15 +575,12 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
458 if (breakme++ == 20) { 575 if (breakme++ == 20) {
459 printk(KERN_NOTICE "Faking write error at 0x%08x\n", c->wbuf_ofs); 576 printk(KERN_NOTICE "Faking write error at 0x%08x\n", c->wbuf_ofs);
460 breakme = 0; 577 breakme = 0;
461 c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, 578 c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen,
462 &retlen, brokenbuf, NULL, c->oobinfo); 579 brokenbuf);
463 ret = -EIO; 580 ret = -EIO;
464 } else 581 } else
465#endif 582#endif
466 583
467 if (jffs2_cleanmarker_oob(c))
468 ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo);
469 else
470 ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf); 584 ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf);
471 585
472 if (ret || retlen != c->wbuf_pagesize) { 586 if (ret || retlen != c->wbuf_pagesize) {
@@ -483,32 +597,34 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
483 return ret; 597 return ret;
484 } 598 }
485 599
486 spin_lock(&c->erase_completion_lock);
487
488 /* Adjust free size of the block if we padded. */ 600 /* Adjust free size of the block if we padded. */
489 if (pad) { 601 if (pad) {
490 struct jffs2_eraseblock *jeb; 602 uint32_t waste = c->wbuf_pagesize - c->wbuf_len;
491
492 jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
493 603
494 D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of %sblock at %08x\n", 604 D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of %sblock at %08x\n",
495 (jeb==c->nextblock)?"next":"", jeb->offset)); 605 (wbuf_jeb==c->nextblock)?"next":"", wbuf_jeb->offset));
496 606
497 /* wbuf_pagesize - wbuf_len is the amount of space that's to be 607 /* wbuf_pagesize - wbuf_len is the amount of space that's to be
498 padded. If there is less free space in the block than that, 608 padded. If there is less free space in the block than that,
499 something screwed up */ 609 something screwed up */
500 if (jeb->free_size < (c->wbuf_pagesize - c->wbuf_len)) { 610 if (wbuf_jeb->free_size < waste) {
501 printk(KERN_CRIT "jffs2_flush_wbuf(): Accounting error. wbuf at 0x%08x has 0x%03x bytes, 0x%03x left.\n", 611 printk(KERN_CRIT "jffs2_flush_wbuf(): Accounting error. wbuf at 0x%08x has 0x%03x bytes, 0x%03x left.\n",
502 c->wbuf_ofs, c->wbuf_len, c->wbuf_pagesize-c->wbuf_len); 612 c->wbuf_ofs, c->wbuf_len, waste);
503 printk(KERN_CRIT "jffs2_flush_wbuf(): But free_size for block at 0x%08x is only 0x%08x\n", 613 printk(KERN_CRIT "jffs2_flush_wbuf(): But free_size for block at 0x%08x is only 0x%08x\n",
504 jeb->offset, jeb->free_size); 614 wbuf_jeb->offset, wbuf_jeb->free_size);
505 BUG(); 615 BUG();
506 } 616 }
507 jeb->free_size -= (c->wbuf_pagesize - c->wbuf_len); 617
508 c->free_size -= (c->wbuf_pagesize - c->wbuf_len); 618 spin_lock(&c->erase_completion_lock);
509 jeb->wasted_size += (c->wbuf_pagesize - c->wbuf_len); 619
510 c->wasted_size += (c->wbuf_pagesize - c->wbuf_len); 620 jffs2_link_node_ref(c, wbuf_jeb, (c->wbuf_ofs + c->wbuf_len) | REF_OBSOLETE, waste, NULL);
511 } 621 /* FIXME: that made it count as dirty. Convert to wasted */
622 wbuf_jeb->dirty_size -= waste;
623 c->dirty_size -= waste;
624 wbuf_jeb->wasted_size += waste;
625 c->wasted_size += waste;
626 } else
627 spin_lock(&c->erase_completion_lock);
512 628
513 /* Stick any now-obsoleted blocks on the erase_pending_list */ 629 /* Stick any now-obsoleted blocks on the erase_pending_list */
514 jffs2_refile_wbuf_blocks(c); 630 jffs2_refile_wbuf_blocks(c);
@@ -603,20 +719,30 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c)
603 719
604 return ret; 720 return ret;
605} 721}
606int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) 722
723static size_t jffs2_fill_wbuf(struct jffs2_sb_info *c, const uint8_t *buf,
724 size_t len)
607{ 725{
608 struct kvec outvecs[3]; 726 if (len && !c->wbuf_len && (len >= c->wbuf_pagesize))
609 uint32_t totlen = 0; 727 return 0;
610 uint32_t split_ofs = 0; 728
611 uint32_t old_totlen; 729 if (len > (c->wbuf_pagesize - c->wbuf_len))
612 int ret, splitvec = -1; 730 len = c->wbuf_pagesize - c->wbuf_len;
613 int invec, outvec; 731 memcpy(c->wbuf + c->wbuf_len, buf, len);
614 size_t wbuf_retlen; 732 c->wbuf_len += (uint32_t) len;
615 unsigned char *wbuf_ptr; 733 return len;
616 size_t donelen = 0; 734}
735
736int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs,
737 unsigned long count, loff_t to, size_t *retlen,
738 uint32_t ino)
739{
740 struct jffs2_eraseblock *jeb;
741 size_t wbuf_retlen, donelen = 0;
617 uint32_t outvec_to = to; 742 uint32_t outvec_to = to;
743 int ret, invec;
618 744
619 /* If not NAND flash, don't bother */ 745 /* If not writebuffered flash, don't bother */
620 if (!jffs2_is_writebuffered(c)) 746 if (!jffs2_is_writebuffered(c))
621 return jffs2_flash_direct_writev(c, invecs, count, to, retlen); 747 return jffs2_flash_direct_writev(c, invecs, count, to, retlen);
622 748
@@ -629,34 +755,22 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig
629 memset(c->wbuf,0xff,c->wbuf_pagesize); 755 memset(c->wbuf,0xff,c->wbuf_pagesize);
630 } 756 }
631 757
632 /* Fixup the wbuf if we are moving to a new eraseblock. The checks below 758 /*
633 fail for ECC'd NOR because cleanmarker == 16, so a block starts at 759 * Sanity checks on target address. It's permitted to write
634 xxx0010. */ 760 * at PAD(c->wbuf_len+c->wbuf_ofs), and it's permitted to
635 if (jffs2_nor_ecc(c)) { 761 * write at the beginning of a new erase block. Anything else,
636 if (((c->wbuf_ofs % c->sector_size) == 0) && !c->wbuf_len) { 762 * and you die. New block starts at xxx000c (0-b = block
637 c->wbuf_ofs = PAGE_DIV(to); 763 * header)
638 c->wbuf_len = PAGE_MOD(to); 764 */
639 memset(c->wbuf,0xff,c->wbuf_pagesize);
640 }
641 }
642
643 /* Sanity checks on target address.
644 It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs),
645 and it's permitted to write at the beginning of a new
646 erase block. Anything else, and you die.
647 New block starts at xxx000c (0-b = block header)
648 */
649 if (SECTOR_ADDR(to) != SECTOR_ADDR(c->wbuf_ofs)) { 765 if (SECTOR_ADDR(to) != SECTOR_ADDR(c->wbuf_ofs)) {
650 /* It's a write to a new block */ 766 /* It's a write to a new block */
651 if (c->wbuf_len) { 767 if (c->wbuf_len) {
652 D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx causes flush of wbuf at 0x%08x\n", (unsigned long)to, c->wbuf_ofs)); 768 D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx "
769 "causes flush of wbuf at 0x%08x\n",
770 (unsigned long)to, c->wbuf_ofs));
653 ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT); 771 ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT);
654 if (ret) { 772 if (ret)
655 /* the underlying layer has to check wbuf_len to do the cleanup */ 773 goto outerr;
656 D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret));
657 *retlen = 0;
658 goto exit;
659 }
660 } 774 }
661 /* set pointer to new block */ 775 /* set pointer to new block */
662 c->wbuf_ofs = PAGE_DIV(to); 776 c->wbuf_ofs = PAGE_DIV(to);
@@ -665,165 +779,70 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig
665 779
666 if (to != PAD(c->wbuf_ofs + c->wbuf_len)) { 780 if (to != PAD(c->wbuf_ofs + c->wbuf_len)) {
667 /* We're not writing immediately after the writebuffer. Bad. */ 781 /* We're not writing immediately after the writebuffer. Bad. */
668 printk(KERN_CRIT "jffs2_flash_writev(): Non-contiguous write to %08lx\n", (unsigned long)to); 782 printk(KERN_CRIT "jffs2_flash_writev(): Non-contiguous write "
783 "to %08lx\n", (unsigned long)to);
669 if (c->wbuf_len) 784 if (c->wbuf_len)
670 printk(KERN_CRIT "wbuf was previously %08x-%08x\n", 785 printk(KERN_CRIT "wbuf was previously %08x-%08x\n",
671 c->wbuf_ofs, c->wbuf_ofs+c->wbuf_len); 786 c->wbuf_ofs, c->wbuf_ofs+c->wbuf_len);
672 BUG(); 787 BUG();
673 } 788 }
674 789
675 /* Note outvecs[3] above. We know count is never greater than 2 */ 790 /* adjust alignment offset */
676 if (count > 2) { 791 if (c->wbuf_len != PAGE_MOD(to)) {
677 printk(KERN_CRIT "jffs2_flash_writev(): count is %ld\n", count); 792 c->wbuf_len = PAGE_MOD(to);
678 BUG(); 793 /* take care of alignment to next page */
679 } 794 if (!c->wbuf_len) {
680 795 c->wbuf_len = c->wbuf_pagesize;
681 invec = 0; 796 ret = __jffs2_flush_wbuf(c, NOPAD);
682 outvec = 0; 797 if (ret)
683 798 goto outerr;
684 /* Fill writebuffer first, if already in use */
685 if (c->wbuf_len) {
686 uint32_t invec_ofs = 0;
687
688 /* adjust alignment offset */
689 if (c->wbuf_len != PAGE_MOD(to)) {
690 c->wbuf_len = PAGE_MOD(to);
691 /* take care of alignment to next page */
692 if (!c->wbuf_len)
693 c->wbuf_len = c->wbuf_pagesize;
694 }
695
696 while(c->wbuf_len < c->wbuf_pagesize) {
697 uint32_t thislen;
698
699 if (invec == count)
700 goto alldone;
701
702 thislen = c->wbuf_pagesize - c->wbuf_len;
703
704 if (thislen >= invecs[invec].iov_len)
705 thislen = invecs[invec].iov_len;
706
707 invec_ofs = thislen;
708
709 memcpy(c->wbuf + c->wbuf_len, invecs[invec].iov_base, thislen);
710 c->wbuf_len += thislen;
711 donelen += thislen;
712 /* Get next invec, if actual did not fill the buffer */
713 if (c->wbuf_len < c->wbuf_pagesize)
714 invec++;
715 }
716
717 /* write buffer is full, flush buffer */
718 ret = __jffs2_flush_wbuf(c, NOPAD);
719 if (ret) {
720 /* the underlying layer has to check wbuf_len to do the cleanup */
721 D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret));
722 /* Retlen zero to make sure our caller doesn't mark the space dirty.
723 We've already done everything that's necessary */
724 *retlen = 0;
725 goto exit;
726 }
727 outvec_to += donelen;
728 c->wbuf_ofs = outvec_to;
729
730 /* All invecs done ? */
731 if (invec == count)
732 goto alldone;
733
734 /* Set up the first outvec, containing the remainder of the
735 invec we partially used */
736 if (invecs[invec].iov_len > invec_ofs) {
737 outvecs[0].iov_base = invecs[invec].iov_base+invec_ofs;
738 totlen = outvecs[0].iov_len = invecs[invec].iov_len-invec_ofs;
739 if (totlen > c->wbuf_pagesize) {
740 splitvec = outvec;
741 split_ofs = outvecs[0].iov_len - PAGE_MOD(totlen);
742 }
743 outvec++;
744 }
745 invec++;
746 }
747
748 /* OK, now we've flushed the wbuf and the start of the bits
749 we have been asked to write, now to write the rest.... */
750
751 /* totlen holds the amount of data still to be written */
752 old_totlen = totlen;
753 for ( ; invec < count; invec++,outvec++ ) {
754 outvecs[outvec].iov_base = invecs[invec].iov_base;
755 totlen += outvecs[outvec].iov_len = invecs[invec].iov_len;
756 if (PAGE_DIV(totlen) != PAGE_DIV(old_totlen)) {
757 splitvec = outvec;
758 split_ofs = outvecs[outvec].iov_len - PAGE_MOD(totlen);
759 old_totlen = totlen;
760 } 799 }
761 } 800 }
762 801
763 /* Now the outvecs array holds all the remaining data to write */ 802 for (invec = 0; invec < count; invec++) {
764 /* Up to splitvec,split_ofs is to be written immediately. The rest 803 int vlen = invecs[invec].iov_len;
765 goes into the (now-empty) wbuf */ 804 uint8_t *v = invecs[invec].iov_base;
766
767 if (splitvec != -1) {
768 uint32_t remainder;
769
770 remainder = outvecs[splitvec].iov_len - split_ofs;
771 outvecs[splitvec].iov_len = split_ofs;
772
773 /* We did cross a page boundary, so we write some now */
774 if (jffs2_cleanmarker_oob(c))
775 ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo);
776 else
777 ret = jffs2_flash_direct_writev(c, outvecs, splitvec+1, outvec_to, &wbuf_retlen);
778
779 if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) {
780 /* At this point we have no problem,
781 c->wbuf is empty. However refile nextblock to avoid
782 writing again to same address.
783 */
784 struct jffs2_eraseblock *jeb;
785 805
786 spin_lock(&c->erase_completion_lock); 806 wbuf_retlen = jffs2_fill_wbuf(c, v, vlen);
787 807
788 jeb = &c->blocks[outvec_to / c->sector_size]; 808 if (c->wbuf_len == c->wbuf_pagesize) {
789 jffs2_block_refile(c, jeb, REFILE_ANYWAY); 809 ret = __jffs2_flush_wbuf(c, NOPAD);
790 810 if (ret)
791 *retlen = 0; 811 goto outerr;
792 spin_unlock(&c->erase_completion_lock);
793 goto exit;
794 } 812 }
795 813 vlen -= wbuf_retlen;
814 outvec_to += wbuf_retlen;
796 donelen += wbuf_retlen; 815 donelen += wbuf_retlen;
797 c->wbuf_ofs = PAGE_DIV(outvec_to) + PAGE_DIV(totlen); 816 v += wbuf_retlen;
798 817
799 if (remainder) { 818 if (vlen >= c->wbuf_pagesize) {
800 outvecs[splitvec].iov_base += split_ofs; 819 ret = c->mtd->write(c->mtd, outvec_to, PAGE_DIV(vlen),
801 outvecs[splitvec].iov_len = remainder; 820 &wbuf_retlen, v);
802 } else { 821 if (ret < 0 || wbuf_retlen != PAGE_DIV(vlen))
803 splitvec++; 822 goto outfile;
823
824 vlen -= wbuf_retlen;
825 outvec_to += wbuf_retlen;
826 c->wbuf_ofs = outvec_to;
827 donelen += wbuf_retlen;
828 v += wbuf_retlen;
804 } 829 }
805 830
806 } else { 831 wbuf_retlen = jffs2_fill_wbuf(c, v, vlen);
807 splitvec = 0; 832 if (c->wbuf_len == c->wbuf_pagesize) {
808 } 833 ret = __jffs2_flush_wbuf(c, NOPAD);
809 834 if (ret)
810 /* Now splitvec points to the start of the bits we have to copy 835 goto outerr;
811 into the wbuf */ 836 }
812 wbuf_ptr = c->wbuf;
813 837
814 for ( ; splitvec < outvec; splitvec++) { 838 outvec_to += wbuf_retlen;
815 /* Don't copy the wbuf into itself */ 839 donelen += wbuf_retlen;
816 if (outvecs[splitvec].iov_base == c->wbuf)
817 continue;
818 memcpy(wbuf_ptr, outvecs[splitvec].iov_base, outvecs[splitvec].iov_len);
819 wbuf_ptr += outvecs[splitvec].iov_len;
820 donelen += outvecs[splitvec].iov_len;
821 } 840 }
822 c->wbuf_len = wbuf_ptr - c->wbuf;
823 841
824 /* If there's a remainder in the wbuf and it's a non-GC write, 842 /*
825 remember that the wbuf affects this ino */ 843 * If there's a remainder in the wbuf and it's a non-GC write,
826alldone: 844 * remember that the wbuf affects this ino
845 */
827 *retlen = donelen; 846 *retlen = donelen;
828 847
829 if (jffs2_sum_active()) { 848 if (jffs2_sum_active()) {
@@ -836,8 +855,24 @@ alldone:
836 jffs2_wbuf_dirties_inode(c, ino); 855 jffs2_wbuf_dirties_inode(c, ino);
837 856
838 ret = 0; 857 ret = 0;
858 up_write(&c->wbuf_sem);
859 return ret;
839 860
840exit: 861outfile:
862 /*
863 * At this point we have no problem, c->wbuf is empty. However
864 * refile nextblock to avoid writing again to same address.
865 */
866
867 spin_lock(&c->erase_completion_lock);
868
869 jeb = &c->blocks[outvec_to / c->sector_size];
870 jffs2_block_refile(c, jeb, REFILE_ANYWAY);
871
872 spin_unlock(&c->erase_completion_lock);
873
874outerr:
875 *retlen = 0;
841 up_write(&c->wbuf_sem); 876 up_write(&c->wbuf_sem);
842 return ret; 877 return ret;
843} 878}
@@ -846,7 +881,8 @@ exit:
846 * This is the entry for flash write. 881 * This is the entry for flash write.
847 * Check, if we work on NAND FLASH, if so build an kvec and write it via vritev 882 * Check, if we work on NAND FLASH, if so build an kvec and write it via vritev
848*/ 883*/
849int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf) 884int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
885 size_t *retlen, const u_char *buf)
850{ 886{
851 struct kvec vecs[1]; 887 struct kvec vecs[1];
852 888
@@ -871,25 +907,23 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re
871 907
872 /* Read flash */ 908 /* Read flash */
873 down_read(&c->wbuf_sem); 909 down_read(&c->wbuf_sem);
874 if (jffs2_cleanmarker_oob(c)) 910 ret = c->mtd->read(c->mtd, ofs, len, retlen, buf);
875 ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo); 911
876 else 912 if ( (ret == -EBADMSG || ret == -EUCLEAN) && (*retlen == len) ) {
877 ret = c->mtd->read(c->mtd, ofs, len, retlen, buf); 913 if (ret == -EBADMSG)
878 914 printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx)"
879 if ( (ret == -EBADMSG) && (*retlen == len) ) { 915 " returned ECC error\n", len, ofs);
880 printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n",
881 len, ofs);
882 /* 916 /*
883 * We have the raw data without ECC correction in the buffer, maybe 917 * We have the raw data without ECC correction in the buffer,
884 * we are lucky and all data or parts are correct. We check the node. 918 * maybe we are lucky and all data or parts are correct. We
885 * If data are corrupted node check will sort it out. 919 * check the node. If data are corrupted node check will sort
886 * We keep this block, it will fail on write or erase and the we 920 * it out. We keep this block, it will fail on write or erase
887 * mark it bad. Or should we do that now? But we should give him a chance. 921 * and the we mark it bad. Or should we do that now? But we
888 * Maybe we had a system crash or power loss before the ecc write or 922 * should give him a chance. Maybe we had a system crash or
889 * a erase was completed. 923 * power loss before the ecc write or a erase was completed.
890 * So we return success. :) 924 * So we return success. :)
891 */ 925 */
892 ret = 0; 926 ret = 0;
893 } 927 }
894 928
895 /* if no writebuffer available or write buffer empty, return */ 929 /* if no writebuffer available or write buffer empty, return */
@@ -911,7 +945,7 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re
911 orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */ 945 orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */
912 if (orbf > len) /* is write beyond write buffer ? */ 946 if (orbf > len) /* is write beyond write buffer ? */
913 goto exit; 947 goto exit;
914 lwbf = len - orbf; /* number of bytes to copy */ 948 lwbf = len - orbf; /* number of bytes to copy */
915 if (lwbf > c->wbuf_len) 949 if (lwbf > c->wbuf_len)
916 lwbf = c->wbuf_len; 950 lwbf = c->wbuf_len;
917 } 951 }
@@ -923,158 +957,159 @@ exit:
923 return ret; 957 return ret;
924} 958}
925 959
960#define NR_OOB_SCAN_PAGES 4
961
926/* 962/*
927 * Check, if the out of band area is empty 963 * Check, if the out of band area is empty
928 */ 964 */
929int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int mode) 965int jffs2_check_oob_empty(struct jffs2_sb_info *c,
966 struct jffs2_eraseblock *jeb, int mode)
930{ 967{
931 unsigned char *buf; 968 int i, page, ret;
932 int ret = 0; 969 int oobsize = c->mtd->oobsize;
933 int i,len,page; 970 struct mtd_oob_ops ops;
934 size_t retlen; 971
935 int oob_size; 972 ops.len = NR_OOB_SCAN_PAGES * oobsize;
936 973 ops.ooblen = oobsize;
937 /* allocate a buffer for all oob data in this sector */ 974 ops.oobbuf = c->oobbuf;
938 oob_size = c->mtd->oobsize; 975 ops.ooboffs = 0;
939 len = 4 * oob_size; 976 ops.datbuf = NULL;
940 buf = kmalloc(len, GFP_KERNEL); 977 ops.mode = MTD_OOB_PLACE;
941 if (!buf) { 978
942 printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n"); 979 ret = c->mtd->read_oob(c->mtd, jeb->offset, &ops);
943 return -ENOMEM;
944 }
945 /*
946 * if mode = 0, we scan for a total empty oob area, else we have
947 * to take care of the cleanmarker in the first page of the block
948 */
949 ret = jffs2_flash_read_oob(c, jeb->offset, len , &retlen, buf);
950 if (ret) { 980 if (ret) {
951 D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); 981 D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
952 goto out; 982 "failed %d for block at %08x\n", ret, jeb->offset));
983 return ret;
953 } 984 }
954 985
955 if (retlen < len) { 986 if (ops.retlen < ops.len) {
956 D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read " 987 D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
957 "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset)); 988 "returned short read (%zd bytes not %d) for block "
958 ret = -EIO; 989 "at %08x\n", ops.retlen, ops.len, jeb->offset));
959 goto out; 990 return -EIO;
960 } 991 }
961 992
962 /* Special check for first page */ 993 /* Special check for first page */
963 for(i = 0; i < oob_size ; i++) { 994 for(i = 0; i < oobsize ; i++) {
964 /* Yeah, we know about the cleanmarker. */ 995 /* Yeah, we know about the cleanmarker. */
965 if (mode && i >= c->fsdata_pos && 996 if (mode && i >= c->fsdata_pos &&
966 i < c->fsdata_pos + c->fsdata_len) 997 i < c->fsdata_pos + c->fsdata_len)
967 continue; 998 continue;
968 999
969 if (buf[i] != 0xFF) { 1000 if (ops.oobbuf[i] != 0xFF) {
970 D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n", 1001 D2(printk(KERN_DEBUG "Found %02x at %x in OOB for "
971 buf[i], i, jeb->offset)); 1002 "%08x\n", ops.oobbuf[i], i, jeb->offset));
972 ret = 1; 1003 return 1;
973 goto out;
974 } 1004 }
975 } 1005 }
976 1006
977 /* we know, we are aligned :) */ 1007 /* we know, we are aligned :) */
978 for (page = oob_size; page < len; page += sizeof(long)) { 1008 for (page = oobsize; page < ops.len; page += sizeof(long)) {
979 unsigned long dat = *(unsigned long *)(&buf[page]); 1009 long dat = *(long *)(&ops.oobbuf[page]);
980 if(dat != -1) { 1010 if(dat != -1)
981 ret = 1; 1011 return 1;
982 goto out;
983 }
984 } 1012 }
985 1013 return 0;
986out:
987 kfree(buf);
988
989 return ret;
990} 1014}
991 1015
992/* 1016/*
993* Scan for a valid cleanmarker and for bad blocks 1017 * Scan for a valid cleanmarker and for bad blocks
994* For virtual blocks (concatenated physical blocks) check the cleanmarker 1018 */
995* only in the first page of the first physical block, but scan for bad blocks in all 1019int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c,
996* physical blocks 1020 struct jffs2_eraseblock *jeb)
997*/
998int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
999{ 1021{
1000 struct jffs2_unknown_node n; 1022 struct jffs2_unknown_node n;
1001 unsigned char buf[2 * NAND_MAX_OOBSIZE]; 1023 struct mtd_oob_ops ops;
1002 unsigned char *p; 1024 int oobsize = c->mtd->oobsize;
1003 int ret, i, cnt, retval = 0; 1025 unsigned char *p,*b;
1004 size_t retlen, offset; 1026 int i, ret;
1005 int oob_size; 1027 size_t offset = jeb->offset;
1006 1028
1007 offset = jeb->offset; 1029 /* Check first if the block is bad. */
1008 oob_size = c->mtd->oobsize; 1030 if (c->mtd->block_isbad(c->mtd, offset)) {
1009 1031 D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker()"
1010 /* Loop through the physical blocks */ 1032 ": Bad block at %08x\n", jeb->offset));
1011 for (cnt = 0; cnt < (c->sector_size / c->mtd->erasesize); cnt++) { 1033 return 2;
1012 /* Check first if the block is bad. */ 1034 }
1013 if (c->mtd->block_isbad (c->mtd, offset)) {
1014 D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Bad block at %08x\n", jeb->offset));
1015 return 2;
1016 }
1017 /*
1018 * We read oob data from page 0 and 1 of the block.
1019 * page 0 contains cleanmarker and badblock info
1020 * page 1 contains failure count of this block
1021 */
1022 ret = c->mtd->read_oob (c->mtd, offset, oob_size << 1, &retlen, buf);
1023 1035
1024 if (ret) { 1036 ops.len = oobsize;
1025 D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); 1037 ops.ooblen = oobsize;
1026 return ret; 1038 ops.oobbuf = c->oobbuf;
1027 } 1039 ops.ooboffs = 0;
1028 if (retlen < (oob_size << 1)) { 1040 ops.datbuf = NULL;
1029 D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB return short read (%zd bytes not %d) for block at %08x\n", retlen, oob_size << 1, jeb->offset)); 1041 ops.mode = MTD_OOB_PLACE;
1030 return -EIO;
1031 }
1032 1042
1033 /* Check cleanmarker only on the first physical block */ 1043 ret = c->mtd->read_oob(c->mtd, offset, &ops);
1034 if (!cnt) { 1044 if (ret) {
1035 n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK); 1045 D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): "
1036 n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER); 1046 "Read OOB failed %d for block at %08x\n",
1037 n.totlen = cpu_to_je32 (8); 1047 ret, jeb->offset));
1038 p = (unsigned char *) &n; 1048 return ret;
1049 }
1039 1050
1040 for (i = 0; i < c->fsdata_len; i++) { 1051 if (ops.retlen < ops.len) {
1041 if (buf[c->fsdata_pos + i] != p[i]) { 1052 D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): "
1042 retval = 1; 1053 "Read OOB return short read (%zd bytes not %d) "
1043 } 1054 "for block at %08x\n", ops.retlen, ops.len,
1044 } 1055 jeb->offset));
1045 D1(if (retval == 1) { 1056 return -EIO;
1046 printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): Cleanmarker node not detected in block at %08x\n", jeb->offset);
1047 printk(KERN_WARNING "OOB at %08x was ", offset);
1048 for (i=0; i < oob_size; i++) {
1049 printk("%02x ", buf[i]);
1050 }
1051 printk("\n");
1052 })
1053 }
1054 offset += c->mtd->erasesize;
1055 } 1057 }
1056 return retval; 1058
1059 n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
1060 n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
1061 n.totlen = cpu_to_je32 (8);
1062 p = (unsigned char *) &n;
1063 b = c->oobbuf + c->fsdata_pos;
1064
1065 for (i = c->fsdata_len; i; i--) {
1066 if (*b++ != *p++)
1067 ret = 1;
1068 }
1069
1070 D1(if (ret == 1) {
1071 printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): "
1072 "Cleanmarker node not detected in block at %08x\n",
1073 offset);
1074 printk(KERN_WARNING "OOB at %08zx was ", offset);
1075 for (i=0; i < oobsize; i++)
1076 printk("%02x ", c->oobbuf[i]);
1077 printk("\n");
1078 });
1079 return ret;
1057} 1080}
1058 1081
1059int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 1082int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c,
1083 struct jffs2_eraseblock *jeb)
1060{ 1084{
1061 struct jffs2_unknown_node n; 1085 struct jffs2_unknown_node n;
1062 int ret; 1086 int ret;
1063 size_t retlen; 1087 struct mtd_oob_ops ops;
1064 1088
1065 n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 1089 n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
1066 n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); 1090 n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
1067 n.totlen = cpu_to_je32(8); 1091 n.totlen = cpu_to_je32(8);
1068 1092
1069 ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n); 1093 ops.len = c->fsdata_len;
1094 ops.ooblen = c->fsdata_len;;
1095 ops.oobbuf = (uint8_t *)&n;
1096 ops.ooboffs = c->fsdata_pos;
1097 ops.datbuf = NULL;
1098 ops.mode = MTD_OOB_PLACE;
1099
1100 ret = c->mtd->write_oob(c->mtd, jeb->offset, &ops);
1070 1101
1071 if (ret) { 1102 if (ret) {
1072 D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); 1103 D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
1104 "Write failed for block at %08x: error %d\n",
1105 jeb->offset, ret));
1073 return ret; 1106 return ret;
1074 } 1107 }
1075 if (retlen != c->fsdata_len) { 1108 if (ops.retlen != ops.len) {
1076 D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Short write for block at %08x: %zd not %d\n", jeb->offset, retlen, c->fsdata_len)); 1109 D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
1077 return ret; 1110 "Short write for block at %08x: %zd not %d\n",
1111 jeb->offset, ops.retlen, ops.len));
1112 return -EIO;
1078 } 1113 }
1079 return 0; 1114 return 0;
1080} 1115}
@@ -1108,18 +1143,9 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *
1108 return 1; 1143 return 1;
1109} 1144}
1110 1145
1111#define NAND_JFFS2_OOB16_FSDALEN 8
1112
1113static struct nand_oobinfo jffs2_oobinfo_docecc = {
1114 .useecc = MTD_NANDECC_PLACE,
1115 .eccbytes = 6,
1116 .eccpos = {0,1,2,3,4,5}
1117};
1118
1119
1120static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c) 1146static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
1121{ 1147{
1122 struct nand_oobinfo *oinfo = &c->mtd->oobinfo; 1148 struct nand_ecclayout *oinfo = c->mtd->ecclayout;
1123 1149
1124 /* Do this only, if we have an oob buffer */ 1150 /* Do this only, if we have an oob buffer */
1125 if (!c->mtd->oobsize) 1151 if (!c->mtd->oobsize)
@@ -1129,33 +1155,23 @@ static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
1129 c->cleanmarker_size = 0; 1155 c->cleanmarker_size = 0;
1130 1156
1131 /* Should we use autoplacement ? */ 1157 /* Should we use autoplacement ? */
1132 if (oinfo && oinfo->useecc == MTD_NANDECC_AUTOPLACE) { 1158 if (!oinfo) {
1133 D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n")); 1159 D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));
1134 /* Get the position of the free bytes */ 1160 return -EINVAL;
1135 if (!oinfo->oobfree[0][1]) { 1161 }
1136 printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep. Autoplacement selected and no empty space in oob\n");
1137 return -ENOSPC;
1138 }
1139 c->fsdata_pos = oinfo->oobfree[0][0];
1140 c->fsdata_len = oinfo->oobfree[0][1];
1141 if (c->fsdata_len > 8)
1142 c->fsdata_len = 8;
1143 } else {
1144 /* This is just a legacy fallback and should go away soon */
1145 switch(c->mtd->ecctype) {
1146 case MTD_ECC_RS_DiskOnChip:
1147 printk(KERN_WARNING "JFFS2 using DiskOnChip hardware ECC without autoplacement. Fix it!\n");
1148 c->oobinfo = &jffs2_oobinfo_docecc;
1149 c->fsdata_pos = 6;
1150 c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN;
1151 c->badblock_pos = 15;
1152 break;
1153 1162
1154 default: 1163 D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
1155 D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n")); 1164 /* Get the position of the free bytes */
1156 return -EINVAL; 1165 if (!oinfo->oobfree[0].length) {
1157 } 1166 printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep."
1167 " Autoplacement selected and no empty space in oob\n");
1168 return -ENOSPC;
1158 } 1169 }
1170 c->fsdata_pos = oinfo->oobfree[0].offset;
1171 c->fsdata_len = oinfo->oobfree[0].length;
1172 if (c->fsdata_len > 8)
1173 c->fsdata_len = 8;
1174
1159 return 0; 1175 return 0;
1160} 1176}
1161 1177
@@ -1165,13 +1181,17 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
1165 1181
1166 /* Initialise write buffer */ 1182 /* Initialise write buffer */
1167 init_rwsem(&c->wbuf_sem); 1183 init_rwsem(&c->wbuf_sem);
1168 c->wbuf_pagesize = c->mtd->oobblock; 1184 c->wbuf_pagesize = c->mtd->writesize;
1169 c->wbuf_ofs = 0xFFFFFFFF; 1185 c->wbuf_ofs = 0xFFFFFFFF;
1170 1186
1171 c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); 1187 c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
1172 if (!c->wbuf) 1188 if (!c->wbuf)
1173 return -ENOMEM; 1189 return -ENOMEM;
1174 1190
1191 c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->mtd->oobsize, GFP_KERNEL);
1192 if (!c->oobbuf)
1193 return -ENOMEM;
1194
1175 res = jffs2_nand_set_oobinfo(c); 1195 res = jffs2_nand_set_oobinfo(c);
1176 1196
1177#ifdef BREAKME 1197#ifdef BREAKME
@@ -1189,6 +1209,7 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
1189void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c) 1209void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
1190{ 1210{
1191 kfree(c->wbuf); 1211 kfree(c->wbuf);
1212 kfree(c->oobbuf);
1192} 1213}
1193 1214
1194int jffs2_dataflash_setup(struct jffs2_sb_info *c) { 1215int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
@@ -1236,33 +1257,14 @@ void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) {
1236 kfree(c->wbuf); 1257 kfree(c->wbuf);
1237} 1258}
1238 1259
1239int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) {
1240 /* Cleanmarker is actually larger on the flashes */
1241 c->cleanmarker_size = 16;
1242
1243 /* Initialize write buffer */
1244 init_rwsem(&c->wbuf_sem);
1245 c->wbuf_pagesize = c->mtd->eccsize;
1246 c->wbuf_ofs = 0xFFFFFFFF;
1247
1248 c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
1249 if (!c->wbuf)
1250 return -ENOMEM;
1251
1252 return 0;
1253}
1254
1255void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c) {
1256 kfree(c->wbuf);
1257}
1258
1259int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) { 1260int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) {
1260 /* Cleanmarker currently occupies a whole programming region */ 1261 /* Cleanmarker currently occupies whole programming regions,
1261 c->cleanmarker_size = MTD_PROGREGION_SIZE(c->mtd); 1262 * either one or 2 for 8Byte STMicro flashes. */
1263 c->cleanmarker_size = max(16u, c->mtd->writesize);
1262 1264
1263 /* Initialize write buffer */ 1265 /* Initialize write buffer */
1264 init_rwsem(&c->wbuf_sem); 1266 init_rwsem(&c->wbuf_sem);
1265 c->wbuf_pagesize = MTD_PROGREGION_SIZE(c->mtd); 1267 c->wbuf_pagesize = c->mtd->writesize;
1266 c->wbuf_ofs = 0xFFFFFFFF; 1268 c->wbuf_ofs = 0xFFFFFFFF;
1267 1269
1268 c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); 1270 c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 1342f0158e9b..67176792e138 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -37,7 +37,6 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint
37 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; 37 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
38 f->inocache->state = INO_STATE_PRESENT; 38 f->inocache->state = INO_STATE_PRESENT;
39 39
40
41 jffs2_add_ino_cache(c, f->inocache); 40 jffs2_add_ino_cache(c, f->inocache);
42 D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino)); 41 D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino));
43 ri->ino = cpu_to_je32(f->inocache->ino); 42 ri->ino = cpu_to_je32(f->inocache->ino);
@@ -57,12 +56,14 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint
57/* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, 56/* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it,
58 write it to the flash, link it into the existing inode/fragment list */ 57 write it to the flash, link it into the existing inode/fragment list */
59 58
60struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode) 59struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
60 struct jffs2_raw_inode *ri, const unsigned char *data,
61 uint32_t datalen, int alloc_mode)
61 62
62{ 63{
63 struct jffs2_raw_node_ref *raw;
64 struct jffs2_full_dnode *fn; 64 struct jffs2_full_dnode *fn;
65 size_t retlen; 65 size_t retlen;
66 uint32_t flash_ofs;
66 struct kvec vecs[2]; 67 struct kvec vecs[2];
67 int ret; 68 int ret;
68 int retried = 0; 69 int retried = 0;
@@ -78,34 +79,21 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
78 vecs[1].iov_base = (unsigned char *)data; 79 vecs[1].iov_base = (unsigned char *)data;
79 vecs[1].iov_len = datalen; 80 vecs[1].iov_len = datalen;
80 81
81 jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
82
83 if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { 82 if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) {
84 printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); 83 printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen);
85 } 84 }
86 raw = jffs2_alloc_raw_node_ref();
87 if (!raw)
88 return ERR_PTR(-ENOMEM);
89 85
90 fn = jffs2_alloc_full_dnode(); 86 fn = jffs2_alloc_full_dnode();
91 if (!fn) { 87 if (!fn)
92 jffs2_free_raw_node_ref(raw);
93 return ERR_PTR(-ENOMEM); 88 return ERR_PTR(-ENOMEM);
94 }
95
96 fn->ofs = je32_to_cpu(ri->offset);
97 fn->size = je32_to_cpu(ri->dsize);
98 fn->frags = 0;
99 89
100 /* check number of valid vecs */ 90 /* check number of valid vecs */
101 if (!datalen || !data) 91 if (!datalen || !data)
102 cnt = 1; 92 cnt = 1;
103 retry: 93 retry:
104 fn->raw = raw; 94 flash_ofs = write_ofs(c);
105 95
106 raw->flash_offset = flash_ofs; 96 jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
107 raw->__totlen = PAD(sizeof(*ri)+datalen);
108 raw->next_phys = NULL;
109 97
110 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) { 98 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) {
111 BUG_ON(!retried); 99 BUG_ON(!retried);
@@ -125,22 +113,16 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
125 113
126 /* Mark the space as dirtied */ 114 /* Mark the space as dirtied */
127 if (retlen) { 115 if (retlen) {
128 /* Doesn't belong to any inode */
129 raw->next_in_ino = NULL;
130
131 /* Don't change raw->size to match retlen. We may have 116 /* Don't change raw->size to match retlen. We may have
132 written the node header already, and only the data will 117 written the node header already, and only the data will
133 seem corrupted, in which case the scan would skip over 118 seem corrupted, in which case the scan would skip over
134 any node we write before the original intended end of 119 any node we write before the original intended end of
135 this node */ 120 this node */
136 raw->flash_offset |= REF_OBSOLETE; 121 jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*ri)+datalen), NULL);
137 jffs2_add_physical_node_ref(c, raw);
138 jffs2_mark_node_obsolete(c, raw);
139 } else { 122 } else {
140 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); 123 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs);
141 jffs2_free_raw_node_ref(raw);
142 } 124 }
143 if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) { 125 if (!retried && alloc_mode != ALLOC_NORETRY) {
144 /* Try to reallocate space and retry */ 126 /* Try to reallocate space and retry */
145 uint32_t dummy; 127 uint32_t dummy;
146 struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; 128 struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
@@ -153,19 +135,20 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
153 jffs2_dbg_acct_paranoia_check(c, jeb); 135 jffs2_dbg_acct_paranoia_check(c, jeb);
154 136
155 if (alloc_mode == ALLOC_GC) { 137 if (alloc_mode == ALLOC_GC) {
156 ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, 138 ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &dummy,
157 &dummy, JFFS2_SUMMARY_INODE_SIZE); 139 JFFS2_SUMMARY_INODE_SIZE);
158 } else { 140 } else {
159 /* Locking pain */ 141 /* Locking pain */
160 up(&f->sem); 142 up(&f->sem);
161 jffs2_complete_reservation(c); 143 jffs2_complete_reservation(c);
162 144
163 ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, 145 ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy,
164 &dummy, alloc_mode, JFFS2_SUMMARY_INODE_SIZE); 146 alloc_mode, JFFS2_SUMMARY_INODE_SIZE);
165 down(&f->sem); 147 down(&f->sem);
166 } 148 }
167 149
168 if (!ret) { 150 if (!ret) {
151 flash_ofs = write_ofs(c);
169 D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); 152 D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
170 153
171 jffs2_dbg_acct_sanity_check(c,jeb); 154 jffs2_dbg_acct_sanity_check(c,jeb);
@@ -174,7 +157,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
174 goto retry; 157 goto retry;
175 } 158 }
176 D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); 159 D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
177 jffs2_free_raw_node_ref(raw);
178 } 160 }
179 /* Release the full_dnode which is now useless, and return */ 161 /* Release the full_dnode which is now useless, and return */
180 jffs2_free_full_dnode(fn); 162 jffs2_free_full_dnode(fn);
@@ -188,20 +170,17 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
188 if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || 170 if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) ||
189 ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && 171 ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) &&
190 (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { 172 (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) {
191 raw->flash_offset |= REF_PRISTINE; 173 flash_ofs |= REF_PRISTINE;
192 } else { 174 } else {
193 raw->flash_offset |= REF_NORMAL; 175 flash_ofs |= REF_NORMAL;
194 } 176 }
195 jffs2_add_physical_node_ref(c, raw); 177 fn->raw = jffs2_add_physical_node_ref(c, flash_ofs, PAD(sizeof(*ri)+datalen), f->inocache);
196 178 fn->ofs = je32_to_cpu(ri->offset);
197 /* Link into per-inode list */ 179 fn->size = je32_to_cpu(ri->dsize);
198 spin_lock(&c->erase_completion_lock); 180 fn->frags = 0;
199 raw->next_in_ino = f->inocache->nodes;
200 f->inocache->nodes = raw;
201 spin_unlock(&c->erase_completion_lock);
202 181
203 D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", 182 D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n",
204 flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), 183 flash_ofs & ~3, flash_ofs & 3, je32_to_cpu(ri->dsize),
205 je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), 184 je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc),
206 je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); 185 je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen)));
207 186
@@ -212,12 +191,14 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
212 return fn; 191 return fn;
213} 192}
214 193
215struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode) 194struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
195 struct jffs2_raw_dirent *rd, const unsigned char *name,
196 uint32_t namelen, int alloc_mode)
216{ 197{
217 struct jffs2_raw_node_ref *raw;
218 struct jffs2_full_dirent *fd; 198 struct jffs2_full_dirent *fd;
219 size_t retlen; 199 size_t retlen;
220 struct kvec vecs[2]; 200 struct kvec vecs[2];
201 uint32_t flash_ofs;
221 int retried = 0; 202 int retried = 0;
222 int ret; 203 int ret;
223 204
@@ -228,26 +209,16 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
228 D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { 209 D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) {
229 printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); 210 printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n");
230 BUG(); 211 BUG();
231 } 212 });
232 );
233 213
234 vecs[0].iov_base = rd; 214 vecs[0].iov_base = rd;
235 vecs[0].iov_len = sizeof(*rd); 215 vecs[0].iov_len = sizeof(*rd);
236 vecs[1].iov_base = (unsigned char *)name; 216 vecs[1].iov_base = (unsigned char *)name;
237 vecs[1].iov_len = namelen; 217 vecs[1].iov_len = namelen;
238 218
239 jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
240
241 raw = jffs2_alloc_raw_node_ref();
242
243 if (!raw)
244 return ERR_PTR(-ENOMEM);
245
246 fd = jffs2_alloc_full_dirent(namelen+1); 219 fd = jffs2_alloc_full_dirent(namelen+1);
247 if (!fd) { 220 if (!fd)
248 jffs2_free_raw_node_ref(raw);
249 return ERR_PTR(-ENOMEM); 221 return ERR_PTR(-ENOMEM);
250 }
251 222
252 fd->version = je32_to_cpu(rd->version); 223 fd->version = je32_to_cpu(rd->version);
253 fd->ino = je32_to_cpu(rd->ino); 224 fd->ino = je32_to_cpu(rd->ino);
@@ -257,11 +228,9 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
257 fd->name[namelen]=0; 228 fd->name[namelen]=0;
258 229
259 retry: 230 retry:
260 fd->raw = raw; 231 flash_ofs = write_ofs(c);
261 232
262 raw->flash_offset = flash_ofs; 233 jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
263 raw->__totlen = PAD(sizeof(*rd)+namelen);
264 raw->next_phys = NULL;
265 234
266 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { 235 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) {
267 BUG_ON(!retried); 236 BUG_ON(!retried);
@@ -280,15 +249,11 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
280 sizeof(*rd)+namelen, flash_ofs, ret, retlen); 249 sizeof(*rd)+namelen, flash_ofs, ret, retlen);
281 /* Mark the space as dirtied */ 250 /* Mark the space as dirtied */
282 if (retlen) { 251 if (retlen) {
283 raw->next_in_ino = NULL; 252 jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*rd)+namelen), NULL);
284 raw->flash_offset |= REF_OBSOLETE;
285 jffs2_add_physical_node_ref(c, raw);
286 jffs2_mark_node_obsolete(c, raw);
287 } else { 253 } else {
288 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); 254 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs);
289 jffs2_free_raw_node_ref(raw);
290 } 255 }
291 if (!retried && (raw = jffs2_alloc_raw_node_ref())) { 256 if (!retried) {
292 /* Try to reallocate space and retry */ 257 /* Try to reallocate space and retry */
293 uint32_t dummy; 258 uint32_t dummy;
294 struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; 259 struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
@@ -301,39 +266,33 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
301 jffs2_dbg_acct_paranoia_check(c, jeb); 266 jffs2_dbg_acct_paranoia_check(c, jeb);
302 267
303 if (alloc_mode == ALLOC_GC) { 268 if (alloc_mode == ALLOC_GC) {
304 ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, 269 ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &dummy,
305 &dummy, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 270 JFFS2_SUMMARY_DIRENT_SIZE(namelen));
306 } else { 271 } else {
307 /* Locking pain */ 272 /* Locking pain */
308 up(&f->sem); 273 up(&f->sem);
309 jffs2_complete_reservation(c); 274 jffs2_complete_reservation(c);
310 275
311 ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, 276 ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy,
312 &dummy, alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 277 alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
313 down(&f->sem); 278 down(&f->sem);
314 } 279 }
315 280
316 if (!ret) { 281 if (!ret) {
282 flash_ofs = write_ofs(c);
317 D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); 283 D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
318 jffs2_dbg_acct_sanity_check(c,jeb); 284 jffs2_dbg_acct_sanity_check(c,jeb);
319 jffs2_dbg_acct_paranoia_check(c, jeb); 285 jffs2_dbg_acct_paranoia_check(c, jeb);
320 goto retry; 286 goto retry;
321 } 287 }
322 D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); 288 D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
323 jffs2_free_raw_node_ref(raw);
324 } 289 }
325 /* Release the full_dnode which is now useless, and return */ 290 /* Release the full_dnode which is now useless, and return */
326 jffs2_free_full_dirent(fd); 291 jffs2_free_full_dirent(fd);
327 return ERR_PTR(ret?ret:-EIO); 292 return ERR_PTR(ret?ret:-EIO);
328 } 293 }
329 /* Mark the space used */ 294 /* Mark the space used */
330 raw->flash_offset |= REF_PRISTINE; 295 fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | REF_PRISTINE, PAD(sizeof(*rd)+namelen), f->inocache);
331 jffs2_add_physical_node_ref(c, raw);
332
333 spin_lock(&c->erase_completion_lock);
334 raw->next_in_ino = f->inocache->nodes;
335 f->inocache->nodes = raw;
336 spin_unlock(&c->erase_completion_lock);
337 296
338 if (retried) { 297 if (retried) {
339 jffs2_dbg_acct_sanity_check(c,NULL); 298 jffs2_dbg_acct_sanity_check(c,NULL);
@@ -359,14 +318,14 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
359 struct jffs2_full_dnode *fn; 318 struct jffs2_full_dnode *fn;
360 unsigned char *comprbuf = NULL; 319 unsigned char *comprbuf = NULL;
361 uint16_t comprtype = JFFS2_COMPR_NONE; 320 uint16_t comprtype = JFFS2_COMPR_NONE;
362 uint32_t phys_ofs, alloclen; 321 uint32_t alloclen;
363 uint32_t datalen, cdatalen; 322 uint32_t datalen, cdatalen;
364 int retried = 0; 323 int retried = 0;
365 324
366 retry: 325 retry:
367 D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset)); 326 D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset));
368 327
369 ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, 328 ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN,
370 &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); 329 &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
371 if (ret) { 330 if (ret) {
372 D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); 331 D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret));
@@ -394,7 +353,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
394 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 353 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
395 ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); 354 ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));
396 355
397 fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, phys_ofs, ALLOC_NORETRY); 356 fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, ALLOC_NORETRY);
398 357
399 jffs2_free_comprbuf(comprbuf, buf); 358 jffs2_free_comprbuf(comprbuf, buf);
400 359
@@ -448,13 +407,13 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
448 struct jffs2_raw_dirent *rd; 407 struct jffs2_raw_dirent *rd;
449 struct jffs2_full_dnode *fn; 408 struct jffs2_full_dnode *fn;
450 struct jffs2_full_dirent *fd; 409 struct jffs2_full_dirent *fd;
451 uint32_t alloclen, phys_ofs; 410 uint32_t alloclen;
452 int ret; 411 int ret;
453 412
454 /* Try to reserve enough space for both node and dirent. 413 /* Try to reserve enough space for both node and dirent.
455 * Just the node will do for now, though 414 * Just the node will do for now, though
456 */ 415 */
457 ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, 416 ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
458 JFFS2_SUMMARY_INODE_SIZE); 417 JFFS2_SUMMARY_INODE_SIZE);
459 D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); 418 D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
460 if (ret) { 419 if (ret) {
@@ -465,7 +424,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
465 ri->data_crc = cpu_to_je32(0); 424 ri->data_crc = cpu_to_je32(0);
466 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 425 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
467 426
468 fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); 427 fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
469 428
470 D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n", 429 D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n",
471 jemode_to_cpu(ri->mode))); 430 jemode_to_cpu(ri->mode)));
@@ -484,7 +443,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
484 443
485 up(&f->sem); 444 up(&f->sem);
486 jffs2_complete_reservation(c); 445 jffs2_complete_reservation(c);
487 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, 446 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
488 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 447 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
489 448
490 if (ret) { 449 if (ret) {
@@ -516,7 +475,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
516 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); 475 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
517 rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); 476 rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
518 477
519 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); 478 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL);
520 479
521 jffs2_free_raw_dirent(rd); 480 jffs2_free_raw_dirent(rd);
522 481
@@ -545,7 +504,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
545{ 504{
546 struct jffs2_raw_dirent *rd; 505 struct jffs2_raw_dirent *rd;
547 struct jffs2_full_dirent *fd; 506 struct jffs2_full_dirent *fd;
548 uint32_t alloclen, phys_ofs; 507 uint32_t alloclen;
549 int ret; 508 int ret;
550 509
551 if (1 /* alternative branch needs testing */ || 510 if (1 /* alternative branch needs testing */ ||
@@ -556,7 +515,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
556 if (!rd) 515 if (!rd)
557 return -ENOMEM; 516 return -ENOMEM;
558 517
559 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, 518 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
560 ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 519 ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
561 if (ret) { 520 if (ret) {
562 jffs2_free_raw_dirent(rd); 521 jffs2_free_raw_dirent(rd);
@@ -580,7 +539,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
580 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); 539 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
581 rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); 540 rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
582 541
583 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION); 542 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_DELETION);
584 543
585 jffs2_free_raw_dirent(rd); 544 jffs2_free_raw_dirent(rd);
586 545
@@ -659,14 +618,14 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
659{ 618{
660 struct jffs2_raw_dirent *rd; 619 struct jffs2_raw_dirent *rd;
661 struct jffs2_full_dirent *fd; 620 struct jffs2_full_dirent *fd;
662 uint32_t alloclen, phys_ofs; 621 uint32_t alloclen;
663 int ret; 622 int ret;
664 623
665 rd = jffs2_alloc_raw_dirent(); 624 rd = jffs2_alloc_raw_dirent();
666 if (!rd) 625 if (!rd)
667 return -ENOMEM; 626 return -ENOMEM;
668 627
669 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, 628 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
670 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 629 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
671 if (ret) { 630 if (ret) {
672 jffs2_free_raw_dirent(rd); 631 jffs2_free_raw_dirent(rd);
@@ -692,7 +651,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
692 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); 651 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
693 rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); 652 rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
694 653
695 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); 654 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL);
696 655
697 jffs2_free_raw_dirent(rd); 656 jffs2_free_raw_dirent(rd);
698 657
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
new file mode 100644
index 000000000000..2d82e250be34
--- /dev/null
+++ b/fs/jffs2/xattr.c
@@ -0,0 +1,1238 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
11#include <linux/kernel.h>
12#include <linux/slab.h>
13#include <linux/fs.h>
14#include <linux/time.h>
15#include <linux/pagemap.h>
16#include <linux/highmem.h>
17#include <linux/crc32.h>
18#include <linux/jffs2.h>
19#include <linux/xattr.h>
20#include <linux/mtd/mtd.h>
21#include "nodelist.h"
22/* -------- xdatum related functions ----------------
23 * xattr_datum_hashkey(xprefix, xname, xvalue, xsize)
24 * is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is
25 * the index of the xattr name/value pair cache (c->xattrindex).
26 * unload_xattr_datum(c, xd)
27 * is used to release xattr name/value pair and detach from c->xattrindex.
28 * reclaim_xattr_datum(c)
29 * is used to reclaim xattr name/value pairs on the xattr name/value pair cache when
30 * memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold
31 * is hard coded as 32KiB.
32 * delete_xattr_datum_node(c, xd)
33 * is used to delete a jffs2 node is dominated by xdatum. When EBS(Erase Block Summary) is
34 * enabled, it overwrites the obsolete node by myself.
35 * delete_xattr_datum(c, xd)
36 * is used to delete jffs2_xattr_datum object. It must be called with 0-value of reference
37 * counter. (It means how many jffs2_xattr_ref object refers this xdatum.)
38 * do_verify_xattr_datum(c, xd)
39 * is used to load the xdatum informations without name/value pair from the medium.
40 * It's necessary once, because those informations are not collected during mounting
41 * process when EBS is enabled.
42 * 0 will be returned, if success. An negative return value means recoverable error, and
43 * positive return value means unrecoverable error. Thus, caller must remove this xdatum
44 * and xref when it returned positive value.
45 * do_load_xattr_datum(c, xd)
46 * is used to load name/value pair from the medium.
47 * The meanings of return value is same as do_verify_xattr_datum().
48 * load_xattr_datum(c, xd)
49 * is used to be as a wrapper of do_verify_xattr_datum() and do_load_xattr_datum().
50 * If xd need to call do_verify_xattr_datum() at first, it's called before calling
51 * do_load_xattr_datum(). The meanings of return value is same as do_verify_xattr_datum().
52 * save_xattr_datum(c, xd)
53 * is used to write xdatum to medium. xd->version will be incremented.
54 * create_xattr_datum(c, xprefix, xname, xvalue, xsize)
55 * is used to create new xdatum and write to medium.
56 * -------------------------------------------------- */
57
58static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
59{
60 int name_len = strlen(xname);
61
62 return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize);
63}
64
65static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
66{
67 /* must be called under down_write(xattr_sem) */
68 D1(dbg_xattr("%s: xid=%u, version=%u\n", __FUNCTION__, xd->xid, xd->version));
69 if (xd->xname) {
70 c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len);
71 kfree(xd->xname);
72 }
73
74 list_del_init(&xd->xindex);
75 xd->hashkey = 0;
76 xd->xname = NULL;
77 xd->xvalue = NULL;
78}
79
80static void reclaim_xattr_datum(struct jffs2_sb_info *c)
81{
82 /* must be called under down_write(xattr_sem) */
83 struct jffs2_xattr_datum *xd, *_xd;
84 uint32_t target, before;
85 static int index = 0;
86 int count;
87
88 if (c->xdatum_mem_threshold > c->xdatum_mem_usage)
89 return;
90
91 before = c->xdatum_mem_usage;
92 target = c->xdatum_mem_usage * 4 / 5; /* 20% reduction */
93 for (count = 0; count < XATTRINDEX_HASHSIZE; count++) {
94 list_for_each_entry_safe(xd, _xd, &c->xattrindex[index], xindex) {
95 if (xd->flags & JFFS2_XFLAGS_HOT) {
96 xd->flags &= ~JFFS2_XFLAGS_HOT;
97 } else if (!(xd->flags & JFFS2_XFLAGS_BIND)) {
98 unload_xattr_datum(c, xd);
99 }
100 if (c->xdatum_mem_usage <= target)
101 goto out;
102 }
103 index = (index+1) % XATTRINDEX_HASHSIZE;
104 }
105 out:
106 JFFS2_NOTICE("xdatum_mem_usage from %u byte to %u byte (%u byte reclaimed)\n",
107 before, c->xdatum_mem_usage, before - c->xdatum_mem_usage);
108}
109
110static void delete_xattr_datum_node(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
111{
112 /* must be called under down_write(xattr_sem) */
113 struct jffs2_raw_xattr rx;
114 size_t length;
115 int rc;
116
117 if (!xd->node) {
118 JFFS2_WARNING("xdatum (xid=%u) is removed twice.\n", xd->xid);
119 return;
120 }
121 if (jffs2_sum_active()) {
122 memset(&rx, 0xff, sizeof(struct jffs2_raw_xattr));
123 rc = jffs2_flash_read(c, ref_offset(xd->node),
124 sizeof(struct jffs2_unknown_node),
125 &length, (char *)&rx);
126 if (rc || length != sizeof(struct jffs2_unknown_node)) {
127 JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
128 rc, sizeof(struct jffs2_unknown_node),
129 length, ref_offset(xd->node));
130 }
131 rc = jffs2_flash_write(c, ref_offset(xd->node), sizeof(rx),
132 &length, (char *)&rx);
133 if (rc || length != sizeof(struct jffs2_raw_xattr)) {
134 JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu ar %#08x\n",
135 rc, sizeof(rx), length, ref_offset(xd->node));
136 }
137 }
138 spin_lock(&c->erase_completion_lock);
139 xd->node->next_in_ino = NULL;
140 spin_unlock(&c->erase_completion_lock);
141 jffs2_mark_node_obsolete(c, xd->node);
142 xd->node = NULL;
143}
144
145static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
146{
147 /* must be called under down_write(xattr_sem) */
148 BUG_ON(xd->refcnt);
149
150 unload_xattr_datum(c, xd);
151 if (xd->node) {
152 delete_xattr_datum_node(c, xd);
153 xd->node = NULL;
154 }
155 jffs2_free_xattr_datum(xd);
156}
157
158static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
159{
160 /* must be called under down_write(xattr_sem) */
161 struct jffs2_eraseblock *jeb;
162 struct jffs2_raw_xattr rx;
163 size_t readlen;
164 uint32_t crc, totlen;
165 int rc;
166
167 BUG_ON(!xd->node);
168 BUG_ON(ref_flags(xd->node) != REF_UNCHECKED);
169
170 rc = jffs2_flash_read(c, ref_offset(xd->node), sizeof(rx), &readlen, (char *)&rx);
171 if (rc || readlen != sizeof(rx)) {
172 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
173 rc, sizeof(rx), readlen, ref_offset(xd->node));
174 return rc ? rc : -EIO;
175 }
176 crc = crc32(0, &rx, sizeof(rx) - 4);
177 if (crc != je32_to_cpu(rx.node_crc)) {
178 if (je32_to_cpu(rx.node_crc) != 0xffffffff)
179 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
180 ref_offset(xd->node), je32_to_cpu(rx.hdr_crc), crc);
181 return EIO;
182 }
183 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
184 if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK
185 || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR
186 || je32_to_cpu(rx.totlen) != totlen
187 || je32_to_cpu(rx.xid) != xd->xid
188 || je32_to_cpu(rx.version) != xd->version) {
189 JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, "
190 "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n",
191 ref_offset(xd->node), je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK,
192 je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR,
193 je32_to_cpu(rx.totlen), totlen,
194 je32_to_cpu(rx.xid), xd->xid,
195 je32_to_cpu(rx.version), xd->version);
196 return EIO;
197 }
198 xd->xprefix = rx.xprefix;
199 xd->name_len = rx.name_len;
200 xd->value_len = je16_to_cpu(rx.value_len);
201 xd->data_crc = je32_to_cpu(rx.data_crc);
202
203 /* This JFFS2_NODETYPE_XATTR node is checked */
204 jeb = &c->blocks[ref_offset(xd->node) / c->sector_size];
205 totlen = PAD(je32_to_cpu(rx.totlen));
206
207 spin_lock(&c->erase_completion_lock);
208 c->unchecked_size -= totlen; c->used_size += totlen;
209 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
210 xd->node->flash_offset = ref_offset(xd->node) | REF_PRISTINE;
211 spin_unlock(&c->erase_completion_lock);
212
213 /* unchecked xdatum is chained with c->xattr_unchecked */
214 list_del_init(&xd->xindex);
215
216 dbg_xattr("success on verfying xdatum (xid=%u, version=%u)\n",
217 xd->xid, xd->version);
218
219 return 0;
220}
221
222static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
223{
224 /* must be called under down_write(xattr_sem) */
225 char *data;
226 size_t readlen;
227 uint32_t crc, length;
228 int i, ret, retry = 0;
229
230 BUG_ON(!xd->node);
231 BUG_ON(ref_flags(xd->node) != REF_PRISTINE);
232 BUG_ON(!list_empty(&xd->xindex));
233 retry:
234 length = xd->name_len + 1 + xd->value_len;
235 data = kmalloc(length, GFP_KERNEL);
236 if (!data)
237 return -ENOMEM;
238
239 ret = jffs2_flash_read(c, ref_offset(xd->node)+sizeof(struct jffs2_raw_xattr),
240 length, &readlen, data);
241
242 if (ret || length!=readlen) {
243 JFFS2_WARNING("jffs2_flash_read() returned %d, request=%d, readlen=%zu, at %#08x\n",
244 ret, length, readlen, ref_offset(xd->node));
245 kfree(data);
246 return ret ? ret : -EIO;
247 }
248
249 data[xd->name_len] = '\0';
250 crc = crc32(0, data, length);
251 if (crc != xd->data_crc) {
252 JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XREF)"
253 " at %#08x, read: 0x%08x calculated: 0x%08x\n",
254 ref_offset(xd->node), xd->data_crc, crc);
255 kfree(data);
256 return EIO;
257 }
258
259 xd->flags |= JFFS2_XFLAGS_HOT;
260 xd->xname = data;
261 xd->xvalue = data + xd->name_len+1;
262
263 c->xdatum_mem_usage += length;
264
265 xd->hashkey = xattr_datum_hashkey(xd->xprefix, xd->xname, xd->xvalue, xd->value_len);
266 i = xd->hashkey % XATTRINDEX_HASHSIZE;
267 list_add(&xd->xindex, &c->xattrindex[i]);
268 if (!retry) {
269 retry = 1;
270 reclaim_xattr_datum(c);
271 if (!xd->xname)
272 goto retry;
273 }
274
275 dbg_xattr("success on loading xdatum (xid=%u, xprefix=%u, xname='%s')\n",
276 xd->xid, xd->xprefix, xd->xname);
277
278 return 0;
279}
280
281static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
282{
283 /* must be called under down_write(xattr_sem);
284 * rc < 0 : recoverable error, try again
285 * rc = 0 : success
286 * rc > 0 : Unrecoverable error, this node should be deleted.
287 */
288 int rc = 0;
289 BUG_ON(xd->xname);
290 if (!xd->node)
291 return EIO;
292 if (unlikely(ref_flags(xd->node) != REF_PRISTINE)) {
293 rc = do_verify_xattr_datum(c, xd);
294 if (rc > 0) {
295 list_del_init(&xd->xindex);
296 delete_xattr_datum_node(c, xd);
297 }
298 }
299 if (!rc)
300 rc = do_load_xattr_datum(c, xd);
301 return rc;
302}
303
304static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
305{
306 /* must be called under down_write(xattr_sem) */
307 struct jffs2_raw_node_ref *raw;
308 struct jffs2_raw_xattr rx;
309 struct kvec vecs[2];
310 size_t length;
311 int rc, totlen;
312 uint32_t phys_ofs = write_ofs(c);
313
314 BUG_ON(!xd->xname);
315
316 vecs[0].iov_base = &rx;
317 vecs[0].iov_len = PAD(sizeof(rx));
318 vecs[1].iov_base = xd->xname;
319 vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
320 totlen = vecs[0].iov_len + vecs[1].iov_len;
321
322 /* Setup raw-xattr */
323 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
324 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
325 rx.totlen = cpu_to_je32(PAD(totlen));
326 rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4));
327
328 rx.xid = cpu_to_je32(xd->xid);
329 rx.version = cpu_to_je32(++xd->version);
330 rx.xprefix = xd->xprefix;
331 rx.name_len = xd->name_len;
332 rx.value_len = cpu_to_je16(xd->value_len);
333 rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len));
334 rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4));
335
336 rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0);
337 if (rc || totlen != length) {
338 JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%zu, at %#08x\n",
339 rc, totlen, length, phys_ofs);
340 rc = rc ? rc : -EIO;
341 if (length)
342 jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(totlen), NULL);
343
344 return rc;
345 }
346
347 /* success */
348 raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), NULL);
349 /* FIXME */ raw->next_in_ino = (void *)xd;
350
351 if (xd->node)
352 delete_xattr_datum_node(c, xd);
353 xd->node = raw;
354
355 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n",
356 xd->xid, xd->version, xd->xprefix, xd->xname);
357
358 return 0;
359}
360
361static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
362 int xprefix, const char *xname,
363 const char *xvalue, int xsize)
364{
365 /* must be called under down_write(xattr_sem) */
366 struct jffs2_xattr_datum *xd;
367 uint32_t hashkey, name_len;
368 char *data;
369 int i, rc;
370
371 /* Search xattr_datum has same xname/xvalue by index */
372 hashkey = xattr_datum_hashkey(xprefix, xname, xvalue, xsize);
373 i = hashkey % XATTRINDEX_HASHSIZE;
374 list_for_each_entry(xd, &c->xattrindex[i], xindex) {
375 if (xd->hashkey==hashkey
376 && xd->xprefix==xprefix
377 && xd->value_len==xsize
378 && !strcmp(xd->xname, xname)
379 && !memcmp(xd->xvalue, xvalue, xsize)) {
380 xd->refcnt++;
381 return xd;
382 }
383 }
384
385 /* Not found, Create NEW XATTR-Cache */
386 name_len = strlen(xname);
387
388 xd = jffs2_alloc_xattr_datum();
389 if (!xd)
390 return ERR_PTR(-ENOMEM);
391
392 data = kmalloc(name_len + 1 + xsize, GFP_KERNEL);
393 if (!data) {
394 jffs2_free_xattr_datum(xd);
395 return ERR_PTR(-ENOMEM);
396 }
397 strcpy(data, xname);
398 memcpy(data + name_len + 1, xvalue, xsize);
399
400 xd->refcnt = 1;
401 xd->xid = ++c->highest_xid;
402 xd->flags |= JFFS2_XFLAGS_HOT;
403 xd->xprefix = xprefix;
404
405 xd->hashkey = hashkey;
406 xd->xname = data;
407 xd->xvalue = data + name_len + 1;
408 xd->name_len = name_len;
409 xd->value_len = xsize;
410 xd->data_crc = crc32(0, data, xd->name_len + 1 + xd->value_len);
411
412 rc = save_xattr_datum(c, xd);
413 if (rc) {
414 kfree(xd->xname);
415 jffs2_free_xattr_datum(xd);
416 return ERR_PTR(rc);
417 }
418
419 /* Insert Hash Index */
420 i = hashkey % XATTRINDEX_HASHSIZE;
421 list_add(&xd->xindex, &c->xattrindex[i]);
422
423 c->xdatum_mem_usage += (xd->name_len + 1 + xd->value_len);
424 reclaim_xattr_datum(c);
425
426 return xd;
427}
428
429/* -------- xref related functions ------------------
430 * verify_xattr_ref(c, ref)
431 * is used to load xref information from medium. Because summary data does not
432 * contain xid/ino, it's necessary to verify once while mounting process.
433 * delete_xattr_ref_node(c, ref)
434 * is used to delete a jffs2 node is dominated by xref. When EBS is enabled,
435 * it overwrites the obsolete node by myself.
436 * delete_xattr_ref(c, ref)
437 * is used to delete jffs2_xattr_ref object. If the reference counter of xdatum
438 * is refered by this xref become 0, delete_xattr_datum() is called later.
439 * save_xattr_ref(c, ref)
440 * is used to write xref to medium.
441 * create_xattr_ref(c, ic, xd)
442 * is used to create a new xref and write to medium.
443 * jffs2_xattr_delete_inode(c, ic)
444 * is called to remove xrefs related to obsolete inode when inode is unlinked.
445 * jffs2_xattr_free_inode(c, ic)
446 * is called to release xattr related objects when unmounting.
447 * check_xattr_ref_inode(c, ic)
448 * is used to confirm inode does not have duplicate xattr name/value pair.
449 * -------------------------------------------------- */
450static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
451{
452 struct jffs2_eraseblock *jeb;
453 struct jffs2_raw_xref rr;
454 size_t readlen;
455 uint32_t crc, totlen;
456 int rc;
457
458 BUG_ON(ref_flags(ref->node) != REF_UNCHECKED);
459
460 rc = jffs2_flash_read(c, ref_offset(ref->node), sizeof(rr), &readlen, (char *)&rr);
461 if (rc || sizeof(rr) != readlen) {
462 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n",
463 rc, sizeof(rr), readlen, ref_offset(ref->node));
464 return rc ? rc : -EIO;
465 }
466 /* obsolete node */
467 crc = crc32(0, &rr, sizeof(rr) - 4);
468 if (crc != je32_to_cpu(rr.node_crc)) {
469 if (je32_to_cpu(rr.node_crc) != 0xffffffff)
470 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
471 ref_offset(ref->node), je32_to_cpu(rr.node_crc), crc);
472 return EIO;
473 }
474 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
475 || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF
476 || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {
477 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "
478 "nodetype=%#04x/%#04x, totlen=%u/%zu\n",
479 ref_offset(ref->node), je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
480 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
481 je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
482 return EIO;
483 }
484 ref->ino = je32_to_cpu(rr.ino);
485 ref->xid = je32_to_cpu(rr.xid);
486
487 /* fixup superblock/eraseblock info */
488 jeb = &c->blocks[ref_offset(ref->node) / c->sector_size];
489 totlen = PAD(sizeof(rr));
490
491 spin_lock(&c->erase_completion_lock);
492 c->unchecked_size -= totlen; c->used_size += totlen;
493 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
494 ref->node->flash_offset = ref_offset(ref->node) | REF_PRISTINE;
495 spin_unlock(&c->erase_completion_lock);
496
497 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",
498 ref->ino, ref->xid, ref_offset(ref->node));
499 return 0;
500}
501
502static void delete_xattr_ref_node(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
503{
504 struct jffs2_raw_xref rr;
505 size_t length;
506 int rc;
507
508 if (jffs2_sum_active()) {
509 memset(&rr, 0xff, sizeof(rr));
510 rc = jffs2_flash_read(c, ref_offset(ref->node),
511 sizeof(struct jffs2_unknown_node),
512 &length, (char *)&rr);
513 if (rc || length != sizeof(struct jffs2_unknown_node)) {
514 JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
515 rc, sizeof(struct jffs2_unknown_node),
516 length, ref_offset(ref->node));
517 }
518 rc = jffs2_flash_write(c, ref_offset(ref->node), sizeof(rr),
519 &length, (char *)&rr);
520 if (rc || length != sizeof(struct jffs2_raw_xref)) {
521 JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu at %#08x\n",
522 rc, sizeof(rr), length, ref_offset(ref->node));
523 }
524 }
525 spin_lock(&c->erase_completion_lock);
526 ref->node->next_in_ino = NULL;
527 spin_unlock(&c->erase_completion_lock);
528 jffs2_mark_node_obsolete(c, ref->node);
529 ref->node = NULL;
530}
531
532static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
533{
534 /* must be called under down_write(xattr_sem) */
535 struct jffs2_xattr_datum *xd;
536
537 BUG_ON(!ref->node);
538 delete_xattr_ref_node(c, ref);
539
540 xd = ref->xd;
541 xd->refcnt--;
542 if (!xd->refcnt)
543 delete_xattr_datum(c, xd);
544 jffs2_free_xattr_ref(ref);
545}
546
547static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
548{
549 /* must be called under down_write(xattr_sem) */
550 struct jffs2_raw_node_ref *raw;
551 struct jffs2_raw_xref rr;
552 size_t length;
553 uint32_t phys_ofs = write_ofs(c);
554 int ret;
555
556 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
557 rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF);
558 rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
559 rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4));
560
561 rr.ino = cpu_to_je32(ref->ic->ino);
562 rr.xid = cpu_to_je32(ref->xd->xid);
563 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));
564
565 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);
566 if (ret || sizeof(rr) != length) {
567 JFFS2_WARNING("jffs2_flash_write() returned %d, request=%zu, retlen=%zu, at %#08x\n",
568 ret, sizeof(rr), length, phys_ofs);
569 ret = ret ? ret : -EIO;
570 if (length)
571 jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(sizeof(rr)), NULL);
572
573 return ret;
574 }
575
576 raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), NULL);
577 /* FIXME */ raw->next_in_ino = (void *)ref;
578 if (ref->node)
579 delete_xattr_ref_node(c, ref);
580 ref->node = raw;
581
582 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);
583
584 return 0;
585}
586
587static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic,
588 struct jffs2_xattr_datum *xd)
589{
590 /* must be called under down_write(xattr_sem) */
591 struct jffs2_xattr_ref *ref;
592 int ret;
593
594 ref = jffs2_alloc_xattr_ref();
595 if (!ref)
596 return ERR_PTR(-ENOMEM);
597 ref->ic = ic;
598 ref->xd = xd;
599
600 ret = save_xattr_ref(c, ref);
601 if (ret) {
602 jffs2_free_xattr_ref(ref);
603 return ERR_PTR(ret);
604 }
605
606 /* Chain to inode */
607 ref->next = ic->xref;
608 ic->xref = ref;
609
610 return ref; /* success */
611}
612
613void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
614{
615 /* It's called from jffs2_clear_inode() on inode removing.
616 When an inode with XATTR is removed, those XATTRs must be removed. */
617 struct jffs2_xattr_ref *ref, *_ref;
618
619 if (!ic || ic->nlink > 0)
620 return;
621
622 down_write(&c->xattr_sem);
623 for (ref = ic->xref; ref; ref = _ref) {
624 _ref = ref->next;
625 delete_xattr_ref(c, ref);
626 }
627 ic->xref = NULL;
628 up_write(&c->xattr_sem);
629}
630
631void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
632{
633 /* It's called from jffs2_free_ino_caches() until unmounting FS. */
634 struct jffs2_xattr_datum *xd;
635 struct jffs2_xattr_ref *ref, *_ref;
636
637 down_write(&c->xattr_sem);
638 for (ref = ic->xref; ref; ref = _ref) {
639 _ref = ref->next;
640 xd = ref->xd;
641 xd->refcnt--;
642 if (!xd->refcnt) {
643 unload_xattr_datum(c, xd);
644 jffs2_free_xattr_datum(xd);
645 }
646 jffs2_free_xattr_ref(ref);
647 }
648 ic->xref = NULL;
649 up_write(&c->xattr_sem);
650}
651
652static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
653{
654 /* success of check_xattr_ref_inode() means taht inode (ic) dose not have
655 * duplicate name/value pairs. If duplicate name/value pair would be found,
656 * one will be removed.
657 */
658 struct jffs2_xattr_ref *ref, *cmp, **pref;
659 int rc = 0;
660
661 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
662 return 0;
663 down_write(&c->xattr_sem);
664 retry:
665 rc = 0;
666 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
667 if (!ref->xd->xname) {
668 rc = load_xattr_datum(c, ref->xd);
669 if (unlikely(rc > 0)) {
670 *pref = ref->next;
671 delete_xattr_ref(c, ref);
672 goto retry;
673 } else if (unlikely(rc < 0))
674 goto out;
675 }
676 for (cmp=ref->next, pref=&ref->next; cmp; pref=&cmp->next, cmp=cmp->next) {
677 if (!cmp->xd->xname) {
678 ref->xd->flags |= JFFS2_XFLAGS_BIND;
679 rc = load_xattr_datum(c, cmp->xd);
680 ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
681 if (unlikely(rc > 0)) {
682 *pref = cmp->next;
683 delete_xattr_ref(c, cmp);
684 goto retry;
685 } else if (unlikely(rc < 0))
686 goto out;
687 }
688 if (ref->xd->xprefix == cmp->xd->xprefix
689 && !strcmp(ref->xd->xname, cmp->xd->xname)) {
690 *pref = cmp->next;
691 delete_xattr_ref(c, cmp);
692 goto retry;
693 }
694 }
695 }
696 ic->flags |= INO_FLAGS_XATTR_CHECKED;
697 out:
698 up_write(&c->xattr_sem);
699
700 return rc;
701}
702
703/* -------- xattr subsystem functions ---------------
704 * jffs2_init_xattr_subsystem(c)
705 * is used to initialize semaphore and list_head, and some variables.
706 * jffs2_find_xattr_datum(c, xid)
707 * is used to lookup xdatum while scanning process.
708 * jffs2_clear_xattr_subsystem(c)
709 * is used to release any xattr related objects.
710 * jffs2_build_xattr_subsystem(c)
711 * is used to associate xdatum and xref while super block building process.
712 * jffs2_setup_xattr_datum(c, xid, version)
713 * is used to insert xdatum while scanning process.
714 * -------------------------------------------------- */
715void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c)
716{
717 int i;
718
719 for (i=0; i < XATTRINDEX_HASHSIZE; i++)
720 INIT_LIST_HEAD(&c->xattrindex[i]);
721 INIT_LIST_HEAD(&c->xattr_unchecked);
722 c->xref_temp = NULL;
723
724 init_rwsem(&c->xattr_sem);
725 c->xdatum_mem_usage = 0;
726 c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */
727}
728
729static struct jffs2_xattr_datum *jffs2_find_xattr_datum(struct jffs2_sb_info *c, uint32_t xid)
730{
731 struct jffs2_xattr_datum *xd;
732 int i = xid % XATTRINDEX_HASHSIZE;
733
734 /* It's only used in scanning/building process. */
735 BUG_ON(!(c->flags & (JFFS2_SB_FLAG_SCANNING|JFFS2_SB_FLAG_BUILDING)));
736
737 list_for_each_entry(xd, &c->xattrindex[i], xindex) {
738 if (xd->xid==xid)
739 return xd;
740 }
741 return NULL;
742}
743
744void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
745{
746 struct jffs2_xattr_datum *xd, *_xd;
747 struct jffs2_xattr_ref *ref, *_ref;
748 int i;
749
750 for (ref=c->xref_temp; ref; ref = _ref) {
751 _ref = ref->next;
752 jffs2_free_xattr_ref(ref);
753 }
754 c->xref_temp = NULL;
755
756 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
757 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
758 list_del(&xd->xindex);
759 if (xd->xname)
760 kfree(xd->xname);
761 jffs2_free_xattr_datum(xd);
762 }
763 }
764}
765
766void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
767{
768 struct jffs2_xattr_ref *ref, *_ref;
769 struct jffs2_xattr_datum *xd, *_xd;
770 struct jffs2_inode_cache *ic;
771 int i, xdatum_count =0, xdatum_unchecked_count = 0, xref_count = 0;
772
773 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
774
775 /* Phase.1 */
776 for (ref=c->xref_temp; ref; ref=_ref) {
777 _ref = ref->next;
778 /* checking REF_UNCHECKED nodes */
779 if (ref_flags(ref->node) != REF_PRISTINE) {
780 if (verify_xattr_ref(c, ref)) {
781 delete_xattr_ref_node(c, ref);
782 jffs2_free_xattr_ref(ref);
783 continue;
784 }
785 }
786 /* At this point, ref->xid and ref->ino contain XID and inode number.
787 ref->xd and ref->ic are not valid yet. */
788 xd = jffs2_find_xattr_datum(c, ref->xid);
789 ic = jffs2_get_ino_cache(c, ref->ino);
790 if (!xd || !ic) {
791 if (ref_flags(ref->node) != REF_UNCHECKED)
792 JFFS2_WARNING("xref(ino=%u, xid=%u) is orphan. \n",
793 ref->ino, ref->xid);
794 delete_xattr_ref_node(c, ref);
795 jffs2_free_xattr_ref(ref);
796 continue;
797 }
798 ref->xd = xd;
799 ref->ic = ic;
800 xd->refcnt++;
801 ref->next = ic->xref;
802 ic->xref = ref;
803 xref_count++;
804 }
805 c->xref_temp = NULL;
806 /* After this, ref->xid/ino are NEVER used. */
807
808 /* Phase.2 */
809 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
810 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
811 list_del_init(&xd->xindex);
812 if (!xd->refcnt) {
813 if (ref_flags(xd->node) != REF_UNCHECKED)
814 JFFS2_WARNING("orphan xdatum(xid=%u, version=%u) at %#08x\n",
815 xd->xid, xd->version, ref_offset(xd->node));
816 delete_xattr_datum(c, xd);
817 continue;
818 }
819 if (ref_flags(xd->node) != REF_PRISTINE) {
820 dbg_xattr("unchecked xdatum(xid=%u) at %#08x\n",
821 xd->xid, ref_offset(xd->node));
822 list_add(&xd->xindex, &c->xattr_unchecked);
823 xdatum_unchecked_count++;
824 }
825 xdatum_count++;
826 }
827 }
828 /* build complete */
829 JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum (%u unchecked) and "
830 "%u of xref found.\n", xdatum_count, xdatum_unchecked_count, xref_count);
831}
832
833struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
834 uint32_t xid, uint32_t version)
835{
836 struct jffs2_xattr_datum *xd, *_xd;
837
838 _xd = jffs2_find_xattr_datum(c, xid);
839 if (_xd) {
840 dbg_xattr("duplicate xdatum (xid=%u, version=%u/%u) at %#08x\n",
841 xid, version, _xd->version, ref_offset(_xd->node));
842 if (version < _xd->version)
843 return ERR_PTR(-EEXIST);
844 }
845 xd = jffs2_alloc_xattr_datum();
846 if (!xd)
847 return ERR_PTR(-ENOMEM);
848 xd->xid = xid;
849 xd->version = version;
850 if (xd->xid > c->highest_xid)
851 c->highest_xid = xd->xid;
852 list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);
853
854 if (_xd) {
855 list_del_init(&_xd->xindex);
856 delete_xattr_datum_node(c, _xd);
857 jffs2_free_xattr_datum(_xd);
858 }
859 return xd;
860}
861
862/* -------- xattr subsystem functions ---------------
863 * xprefix_to_handler(xprefix)
864 * is used to translate xprefix into xattr_handler.
865 * jffs2_listxattr(dentry, buffer, size)
866 * is an implementation of listxattr handler on jffs2.
867 * do_jffs2_getxattr(inode, xprefix, xname, buffer, size)
868 * is an implementation of getxattr handler on jffs2.
869 * do_jffs2_setxattr(inode, xprefix, xname, buffer, size, flags)
870 * is an implementation of setxattr handler on jffs2.
871 * -------------------------------------------------- */
872struct xattr_handler *jffs2_xattr_handlers[] = {
873 &jffs2_user_xattr_handler,
874#ifdef CONFIG_JFFS2_FS_SECURITY
875 &jffs2_security_xattr_handler,
876#endif
877#ifdef CONFIG_JFFS2_FS_POSIX_ACL
878 &jffs2_acl_access_xattr_handler,
879 &jffs2_acl_default_xattr_handler,
880#endif
881 &jffs2_trusted_xattr_handler,
882 NULL
883};
884
885static struct xattr_handler *xprefix_to_handler(int xprefix) {
886 struct xattr_handler *ret;
887
888 switch (xprefix) {
889 case JFFS2_XPREFIX_USER:
890 ret = &jffs2_user_xattr_handler;
891 break;
892#ifdef CONFIG_JFFS2_FS_SECURITY
893 case JFFS2_XPREFIX_SECURITY:
894 ret = &jffs2_security_xattr_handler;
895 break;
896#endif
897#ifdef CONFIG_JFFS2_FS_POSIX_ACL
898 case JFFS2_XPREFIX_ACL_ACCESS:
899 ret = &jffs2_acl_access_xattr_handler;
900 break;
901 case JFFS2_XPREFIX_ACL_DEFAULT:
902 ret = &jffs2_acl_default_xattr_handler;
903 break;
904#endif
905 case JFFS2_XPREFIX_TRUSTED:
906 ret = &jffs2_trusted_xattr_handler;
907 break;
908 default:
909 ret = NULL;
910 break;
911 }
912 return ret;
913}
914
915ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
916{
917 struct inode *inode = dentry->d_inode;
918 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
919 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
920 struct jffs2_inode_cache *ic = f->inocache;
921 struct jffs2_xattr_ref *ref, **pref;
922 struct jffs2_xattr_datum *xd;
923 struct xattr_handler *xhandle;
924 ssize_t len, rc;
925 int retry = 0;
926
927 rc = check_xattr_ref_inode(c, ic);
928 if (unlikely(rc))
929 return rc;
930
931 down_read(&c->xattr_sem);
932 retry:
933 len = 0;
934 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
935 BUG_ON(ref->ic != ic);
936 xd = ref->xd;
937 if (!xd->xname) {
938 /* xdatum is unchached */
939 if (!retry) {
940 retry = 1;
941 up_read(&c->xattr_sem);
942 down_write(&c->xattr_sem);
943 goto retry;
944 } else {
945 rc = load_xattr_datum(c, xd);
946 if (unlikely(rc > 0)) {
947 *pref = ref->next;
948 delete_xattr_ref(c, ref);
949 goto retry;
950 } else if (unlikely(rc < 0))
951 goto out;
952 }
953 }
954 xhandle = xprefix_to_handler(xd->xprefix);
955 if (!xhandle)
956 continue;
957 if (buffer) {
958 rc = xhandle->list(inode, buffer+len, size-len, xd->xname, xd->name_len);
959 } else {
960 rc = xhandle->list(inode, NULL, 0, xd->xname, xd->name_len);
961 }
962 if (rc < 0)
963 goto out;
964 len += rc;
965 }
966 rc = len;
967 out:
968 if (!retry) {
969 up_read(&c->xattr_sem);
970 } else {
971 up_write(&c->xattr_sem);
972 }
973 return rc;
974}
975
976int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
977 char *buffer, size_t size)
978{
979 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
980 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
981 struct jffs2_inode_cache *ic = f->inocache;
982 struct jffs2_xattr_datum *xd;
983 struct jffs2_xattr_ref *ref, **pref;
984 int rc, retry = 0;
985
986 rc = check_xattr_ref_inode(c, ic);
987 if (unlikely(rc))
988 return rc;
989
990 down_read(&c->xattr_sem);
991 retry:
992 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
993 BUG_ON(ref->ic!=ic);
994
995 xd = ref->xd;
996 if (xd->xprefix != xprefix)
997 continue;
998 if (!xd->xname) {
999 /* xdatum is unchached */
1000 if (!retry) {
1001 retry = 1;
1002 up_read(&c->xattr_sem);
1003 down_write(&c->xattr_sem);
1004 goto retry;
1005 } else {
1006 rc = load_xattr_datum(c, xd);
1007 if (unlikely(rc > 0)) {
1008 *pref = ref->next;
1009 delete_xattr_ref(c, ref);
1010 goto retry;
1011 } else if (unlikely(rc < 0)) {
1012 goto out;
1013 }
1014 }
1015 }
1016 if (!strcmp(xname, xd->xname)) {
1017 rc = xd->value_len;
1018 if (buffer) {
1019 if (size < rc) {
1020 rc = -ERANGE;
1021 } else {
1022 memcpy(buffer, xd->xvalue, rc);
1023 }
1024 }
1025 goto out;
1026 }
1027 }
1028 rc = -ENODATA;
1029 out:
1030 if (!retry) {
1031 up_read(&c->xattr_sem);
1032 } else {
1033 up_write(&c->xattr_sem);
1034 }
1035 return rc;
1036}
1037
1038int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1039 const char *buffer, size_t size, int flags)
1040{
1041 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1042 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1043 struct jffs2_inode_cache *ic = f->inocache;
1044 struct jffs2_xattr_datum *xd;
1045 struct jffs2_xattr_ref *ref, *newref, **pref;
1046 uint32_t length, request;
1047 int rc;
1048
1049 rc = check_xattr_ref_inode(c, ic);
1050 if (unlikely(rc))
1051 return rc;
1052
1053 request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size);
1054 rc = jffs2_reserve_space(c, request, &length,
1055 ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE);
1056 if (rc) {
1057 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1058 return rc;
1059 }
1060
1061 /* Find existing xattr */
1062 down_write(&c->xattr_sem);
1063 retry:
1064 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
1065 xd = ref->xd;
1066 if (xd->xprefix != xprefix)
1067 continue;
1068 if (!xd->xname) {
1069 rc = load_xattr_datum(c, xd);
1070 if (unlikely(rc > 0)) {
1071 *pref = ref->next;
1072 delete_xattr_ref(c, ref);
1073 goto retry;
1074 } else if (unlikely(rc < 0))
1075 goto out;
1076 }
1077 if (!strcmp(xd->xname, xname)) {
1078 if (flags & XATTR_CREATE) {
1079 rc = -EEXIST;
1080 goto out;
1081 }
1082 if (!buffer) {
1083 *pref = ref->next;
1084 delete_xattr_ref(c, ref);
1085 rc = 0;
1086 goto out;
1087 }
1088 goto found;
1089 }
1090 }
1091 /* not found */
1092 if (flags & XATTR_REPLACE) {
1093 rc = -ENODATA;
1094 goto out;
1095 }
1096 if (!buffer) {
1097 rc = -EINVAL;
1098 goto out;
1099 }
1100 found:
1101 xd = create_xattr_datum(c, xprefix, xname, buffer, size);
1102 if (IS_ERR(xd)) {
1103 rc = PTR_ERR(xd);
1104 goto out;
1105 }
1106 up_write(&c->xattr_sem);
1107 jffs2_complete_reservation(c);
1108
1109 /* create xattr_ref */
1110 request = PAD(sizeof(struct jffs2_raw_xref));
1111 rc = jffs2_reserve_space(c, request, &length,
1112 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE);
1113 if (rc) {
1114 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1115 down_write(&c->xattr_sem);
1116 xd->refcnt--;
1117 if (!xd->refcnt)
1118 delete_xattr_datum(c, xd);
1119 up_write(&c->xattr_sem);
1120 return rc;
1121 }
1122 down_write(&c->xattr_sem);
1123 if (ref)
1124 *pref = ref->next;
1125 newref = create_xattr_ref(c, ic, xd);
1126 if (IS_ERR(newref)) {
1127 if (ref) {
1128 ref->next = ic->xref;
1129 ic->xref = ref;
1130 }
1131 rc = PTR_ERR(newref);
1132 xd->refcnt--;
1133 if (!xd->refcnt)
1134 delete_xattr_datum(c, xd);
1135 } else if (ref) {
1136 delete_xattr_ref(c, ref);
1137 }
1138 out:
1139 up_write(&c->xattr_sem);
1140 jffs2_complete_reservation(c);
1141 return rc;
1142}
1143
1144/* -------- garbage collector functions -------------
1145 * jffs2_garbage_collect_xattr_datum(c, xd)
1146 * is used to move xdatum into new node.
1147 * jffs2_garbage_collect_xattr_ref(c, ref)
1148 * is used to move xref into new node.
1149 * jffs2_verify_xattr(c)
1150 * is used to call do_verify_xattr_datum() before garbage collecting.
1151 * -------------------------------------------------- */
1152int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
1153{
1154 uint32_t totlen, length, old_ofs;
1155 int rc = -EINVAL;
1156
1157 down_write(&c->xattr_sem);
1158 BUG_ON(!xd->node);
1159
1160 old_ofs = ref_offset(xd->node);
1161 totlen = ref_totlen(c, c->gcblock, xd->node);
1162 if (totlen < sizeof(struct jffs2_raw_xattr))
1163 goto out;
1164
1165 if (!xd->xname) {
1166 rc = load_xattr_datum(c, xd);
1167 if (unlikely(rc > 0)) {
1168 delete_xattr_datum_node(c, xd);
1169 rc = 0;
1170 goto out;
1171 } else if (unlikely(rc < 0))
1172 goto out;
1173 }
1174 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE);
1175 if (rc || length < totlen) {
1176 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen);
1177 rc = rc ? rc : -EBADFD;
1178 goto out;
1179 }
1180 rc = save_xattr_datum(c, xd);
1181 if (!rc)
1182 dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n",
1183 xd->xid, xd->version, old_ofs, ref_offset(xd->node));
1184 out:
1185 up_write(&c->xattr_sem);
1186 return rc;
1187}
1188
1189
1190int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
1191{
1192 uint32_t totlen, length, old_ofs;
1193 int rc = -EINVAL;
1194
1195 down_write(&c->xattr_sem);
1196 BUG_ON(!ref->node);
1197
1198 old_ofs = ref_offset(ref->node);
1199 totlen = ref_totlen(c, c->gcblock, ref->node);
1200 if (totlen != sizeof(struct jffs2_raw_xref))
1201 goto out;
1202
1203 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);
1204 if (rc || length < totlen) {
1205 JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n",
1206 __FUNCTION__, rc, totlen);
1207 rc = rc ? rc : -EBADFD;
1208 goto out;
1209 }
1210 rc = save_xattr_ref(c, ref);
1211 if (!rc)
1212 dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n",
1213 ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node));
1214 out:
1215 up_write(&c->xattr_sem);
1216 return rc;
1217}
1218
1219int jffs2_verify_xattr(struct jffs2_sb_info *c)
1220{
1221 struct jffs2_xattr_datum *xd, *_xd;
1222 int rc;
1223
1224 down_write(&c->xattr_sem);
1225 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
1226 rc = do_verify_xattr_datum(c, xd);
1227 if (rc == 0) {
1228 list_del_init(&xd->xindex);
1229 break;
1230 } else if (rc > 0) {
1231 list_del_init(&xd->xindex);
1232 delete_xattr_datum_node(c, xd);
1233 }
1234 }
1235 up_write(&c->xattr_sem);
1236
1237 return list_empty(&c->xattr_unchecked) ? 1 : 0;
1238}
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
new file mode 100644
index 000000000000..2c199856c582
--- /dev/null
+++ b/fs/jffs2/xattr.h
@@ -0,0 +1,116 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
11#ifndef _JFFS2_FS_XATTR_H_
12#define _JFFS2_FS_XATTR_H_
13
14#include <linux/xattr.h>
15#include <linux/list.h>
16
17#define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */
18#define JFFS2_XFLAGS_BIND (0x02) /* This datum is not reclaimed */
19
20struct jffs2_xattr_datum
21{
22 void *always_null;
23 struct jffs2_raw_node_ref *node;
24 uint8_t class;
25 uint8_t flags;
26 uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */
27
28 struct list_head xindex; /* chained from c->xattrindex[n] */
29 uint32_t refcnt; /* # of xattr_ref refers this */
30 uint32_t xid;
31 uint32_t version;
32
33 uint32_t data_crc;
34 uint32_t hashkey;
35 char *xname; /* XATTR name without prefix */
36 uint32_t name_len; /* length of xname */
37 char *xvalue; /* XATTR value */
38 uint32_t value_len; /* length of xvalue */
39};
40
41struct jffs2_inode_cache;
42struct jffs2_xattr_ref
43{
44 void *always_null;
45 struct jffs2_raw_node_ref *node;
46 uint8_t class;
47 uint8_t flags; /* Currently unused */
48 u16 unused;
49
50 union {
51 struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */
52 uint32_t ino; /* only used in scanning/building */
53 };
54 union {
55 struct jffs2_xattr_datum *xd; /* reference to jffs2_xattr_datum */
56 uint32_t xid; /* only used in sccanning/building */
57 };
58 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */
59};
60
61#ifdef CONFIG_JFFS2_FS_XATTR
62
63extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c);
64extern void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c);
65extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c);
66
67extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
68 uint32_t xid, uint32_t version);
69
70extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
71extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
72
73extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd);
74extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref);
75extern int jffs2_verify_xattr(struct jffs2_sb_info *c);
76
77extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
78 char *buffer, size_t size);
79extern int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
80 const char *buffer, size_t size, int flags);
81
82extern struct xattr_handler *jffs2_xattr_handlers[];
83extern struct xattr_handler jffs2_user_xattr_handler;
84extern struct xattr_handler jffs2_trusted_xattr_handler;
85
86extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
87#define jffs2_getxattr generic_getxattr
88#define jffs2_setxattr generic_setxattr
89#define jffs2_removexattr generic_removexattr
90
91#else
92
93#define jffs2_init_xattr_subsystem(c)
94#define jffs2_build_xattr_subsystem(c)
95#define jffs2_clear_xattr_subsystem(c)
96
97#define jffs2_xattr_delete_inode(c, ic)
98#define jffs2_xattr_free_inode(c, ic)
99#define jffs2_verify_xattr(c) (1)
100
101#define jffs2_xattr_handlers NULL
102#define jffs2_listxattr NULL
103#define jffs2_getxattr NULL
104#define jffs2_setxattr NULL
105#define jffs2_removexattr NULL
106
107#endif /* CONFIG_JFFS2_FS_XATTR */
108
109#ifdef CONFIG_JFFS2_FS_SECURITY
110extern int jffs2_init_security(struct inode *inode, struct inode *dir);
111extern struct xattr_handler jffs2_security_xattr_handler;
112#else
113#define jffs2_init_security(inode,dir) (0)
114#endif /* CONFIG_JFFS2_FS_SECURITY */
115
116#endif /* _JFFS2_FS_XATTR_H_ */
diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c
new file mode 100644
index 000000000000..ed046e19dbfa
--- /dev/null
+++ b/fs/jffs2/xattr_trusted.c
@@ -0,0 +1,52 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
11#include <linux/kernel.h>
12#include <linux/fs.h>
13#include <linux/jffs2.h>
14#include <linux/xattr.h>
15#include <linux/mtd/mtd.h>
16#include "nodelist.h"
17
18static int jffs2_trusted_getxattr(struct inode *inode, const char *name,
19 void *buffer, size_t size)
20{
21 if (!strcmp(name, ""))
22 return -EINVAL;
23 return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size);
24}
25
26static int jffs2_trusted_setxattr(struct inode *inode, const char *name, const void *buffer,
27 size_t size, int flags)
28{
29 if (!strcmp(name, ""))
30 return -EINVAL;
31 return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size, flags);
32}
33
34static size_t jffs2_trusted_listxattr(struct inode *inode, char *list, size_t list_size,
35 const char *name, size_t name_len)
36{
37 size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1;
38
39 if (list && retlen<=list_size) {
40 strcpy(list, XATTR_TRUSTED_PREFIX);
41 strcpy(list + XATTR_TRUSTED_PREFIX_LEN, name);
42 }
43
44 return retlen;
45}
46
47struct xattr_handler jffs2_trusted_xattr_handler = {
48 .prefix = XATTR_TRUSTED_PREFIX,
49 .list = jffs2_trusted_listxattr,
50 .set = jffs2_trusted_setxattr,
51 .get = jffs2_trusted_getxattr
52};
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
new file mode 100644
index 000000000000..2f8e9aa01ea0
--- /dev/null
+++ b/fs/jffs2/xattr_user.c
@@ -0,0 +1,52 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
11#include <linux/kernel.h>
12#include <linux/fs.h>
13#include <linux/jffs2.h>
14#include <linux/xattr.h>
15#include <linux/mtd/mtd.h>
16#include "nodelist.h"
17
18static int jffs2_user_getxattr(struct inode *inode, const char *name,
19 void *buffer, size_t size)
20{
21 if (!strcmp(name, ""))
22 return -EINVAL;
23 return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size);
24}
25
26static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer,
27 size_t size, int flags)
28{
29 if (!strcmp(name, ""))
30 return -EINVAL;
31 return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size, flags);
32}
33
34static size_t jffs2_user_listxattr(struct inode *inode, char *list, size_t list_size,
35 const char *name, size_t name_len)
36{
37 size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1;
38
39 if (list && retlen <= list_size) {
40 strcpy(list, XATTR_USER_PREFIX);
41 strcpy(list + XATTR_USER_PREFIX_LEN, name);
42 }
43
44 return retlen;
45}
46
47struct xattr_handler jffs2_user_xattr_handler = {
48 .prefix = XATTR_USER_PREFIX,
49 .list = jffs2_user_listxattr,
50 .set = jffs2_user_setxattr,
51 .get = jffs2_user_getxattr
52};
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 2b220dd6b4e7..7f6e88039700 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -632,10 +632,9 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,
632 } 632 }
633 SetPageUptodate(page); 633 SetPageUptodate(page);
634 } else { 634 } else {
635 page = read_cache_page(mapping, page_index, 635 page = read_mapping_page(mapping, page_index, NULL);
636 (filler_t *)mapping->a_ops->readpage, NULL);
637 if (IS_ERR(page) || !PageUptodate(page)) { 636 if (IS_ERR(page) || !PageUptodate(page)) {
638 jfs_err("read_cache_page failed!"); 637 jfs_err("read_mapping_page failed!");
639 return NULL; 638 return NULL;
640 } 639 }
641 lock_page(page); 640 lock_page(page);
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index db6f41d6dd60..73d2aba084c6 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -139,9 +139,9 @@ static void jfs_destroy_inode(struct inode *inode)
139 kmem_cache_free(jfs_inode_cachep, ji); 139 kmem_cache_free(jfs_inode_cachep, ji);
140} 140}
141 141
142static int jfs_statfs(struct super_block *sb, struct kstatfs *buf) 142static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf)
143{ 143{
144 struct jfs_sb_info *sbi = JFS_SBI(sb); 144 struct jfs_sb_info *sbi = JFS_SBI(dentry->d_sb);
145 s64 maxinodes; 145 s64 maxinodes;
146 struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap; 146 struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap;
147 147
@@ -565,10 +565,11 @@ static void jfs_unlockfs(struct super_block *sb)
565 } 565 }
566} 566}
567 567
568static struct super_block *jfs_get_sb(struct file_system_type *fs_type, 568static int jfs_get_sb(struct file_system_type *fs_type,
569 int flags, const char *dev_name, void *data) 569 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
570{ 570{
571 return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super); 571 return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super,
572 mnt);
572} 573}
573 574
574static int jfs_sync_fs(struct super_block *sb, int wait) 575static int jfs_sync_fs(struct super_block *sb, int wait)
diff --git a/fs/libfs.c b/fs/libfs.c
index 7145ba7a48d0..1b1156381787 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -20,9 +20,9 @@ int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
20 return 0; 20 return 0;
21} 21}
22 22
23int simple_statfs(struct super_block *sb, struct kstatfs *buf) 23int simple_statfs(struct dentry *dentry, struct kstatfs *buf)
24{ 24{
25 buf->f_type = sb->s_magic; 25 buf->f_type = dentry->d_sb->s_magic;
26 buf->f_bsize = PAGE_CACHE_SIZE; 26 buf->f_bsize = PAGE_CACHE_SIZE;
27 buf->f_namelen = NAME_MAX; 27 buf->f_namelen = NAME_MAX;
28 return 0; 28 return 0;
@@ -196,9 +196,9 @@ struct inode_operations simple_dir_inode_operations = {
196 * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that 196 * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
197 * will never be mountable) 197 * will never be mountable)
198 */ 198 */
199struct super_block * 199int get_sb_pseudo(struct file_system_type *fs_type, char *name,
200get_sb_pseudo(struct file_system_type *fs_type, char *name, 200 struct super_operations *ops, unsigned long magic,
201 struct super_operations *ops, unsigned long magic) 201 struct vfsmount *mnt)
202{ 202{
203 struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); 203 struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
204 static struct super_operations default_ops = {.statfs = simple_statfs}; 204 static struct super_operations default_ops = {.statfs = simple_statfs};
@@ -207,7 +207,7 @@ get_sb_pseudo(struct file_system_type *fs_type, char *name,
207 struct qstr d_name = {.name = name, .len = strlen(name)}; 207 struct qstr d_name = {.name = name, .len = strlen(name)};
208 208
209 if (IS_ERR(s)) 209 if (IS_ERR(s))
210 return s; 210 return PTR_ERR(s);
211 211
212 s->s_flags = MS_NOUSER; 212 s->s_flags = MS_NOUSER;
213 s->s_maxbytes = ~0ULL; 213 s->s_maxbytes = ~0ULL;
@@ -232,12 +232,12 @@ get_sb_pseudo(struct file_system_type *fs_type, char *name,
232 d_instantiate(dentry, root); 232 d_instantiate(dentry, root);
233 s->s_root = dentry; 233 s->s_root = dentry;
234 s->s_flags |= MS_ACTIVE; 234 s->s_flags |= MS_ACTIVE;
235 return s; 235 return simple_set_mnt(mnt, s);
236 236
237Enomem: 237Enomem:
238 up_write(&s->s_umount); 238 up_write(&s->s_umount);
239 deactivate_super(s); 239 deactivate_super(s);
240 return ERR_PTR(-ENOMEM); 240 return -ENOMEM;
241} 241}
242 242
243int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) 243int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
diff --git a/fs/locks.c b/fs/locks.c
index ab61a8b54829..1ad29c9b6252 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -703,7 +703,7 @@ EXPORT_SYMBOL(posix_test_lock);
703 * from a broken NFS client. But broken NFS clients have a lot more to 703 * from a broken NFS client. But broken NFS clients have a lot more to
704 * worry about than proper deadlock detection anyway... --okir 704 * worry about than proper deadlock detection anyway... --okir
705 */ 705 */
706int posix_locks_deadlock(struct file_lock *caller_fl, 706static int posix_locks_deadlock(struct file_lock *caller_fl,
707 struct file_lock *block_fl) 707 struct file_lock *block_fl)
708{ 708{
709 struct list_head *tmp; 709 struct list_head *tmp;
@@ -722,8 +722,6 @@ next_task:
722 return 0; 722 return 0;
723} 723}
724 724
725EXPORT_SYMBOL(posix_locks_deadlock);
726
727/* Try to create a FLOCK lock on filp. We always insert new FLOCK locks 725/* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
728 * at the head of the list, but that's secret knowledge known only to 726 * at the head of the list, but that's secret knowledge known only to
729 * flock_lock_file and posix_lock_file. 727 * flock_lock_file and posix_lock_file.
@@ -794,7 +792,8 @@ out:
794static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock) 792static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock)
795{ 793{
796 struct file_lock *fl; 794 struct file_lock *fl;
797 struct file_lock *new_fl, *new_fl2; 795 struct file_lock *new_fl = NULL;
796 struct file_lock *new_fl2 = NULL;
798 struct file_lock *left = NULL; 797 struct file_lock *left = NULL;
799 struct file_lock *right = NULL; 798 struct file_lock *right = NULL;
800 struct file_lock **before; 799 struct file_lock **before;
@@ -803,9 +802,15 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
803 /* 802 /*
804 * We may need two file_lock structures for this operation, 803 * We may need two file_lock structures for this operation,
805 * so we get them in advance to avoid races. 804 * so we get them in advance to avoid races.
805 *
806 * In some cases we can be sure, that no new locks will be needed
806 */ 807 */
807 new_fl = locks_alloc_lock(); 808 if (!(request->fl_flags & FL_ACCESS) &&
808 new_fl2 = locks_alloc_lock(); 809 (request->fl_type != F_UNLCK ||
810 request->fl_start != 0 || request->fl_end != OFFSET_MAX)) {
811 new_fl = locks_alloc_lock();
812 new_fl2 = locks_alloc_lock();
813 }
809 814
810 lock_kernel(); 815 lock_kernel();
811 if (request->fl_type != F_UNLCK) { 816 if (request->fl_type != F_UNLCK) {
@@ -834,14 +839,7 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
834 if (request->fl_flags & FL_ACCESS) 839 if (request->fl_flags & FL_ACCESS)
835 goto out; 840 goto out;
836 841
837 error = -ENOLCK; /* "no luck" */
838 if (!(new_fl && new_fl2))
839 goto out;
840
841 /* 842 /*
842 * We've allocated the new locks in advance, so there are no
843 * errors possible (and no blocking operations) from here on.
844 *
845 * Find the first old lock with the same owner as the new lock. 843 * Find the first old lock with the same owner as the new lock.
846 */ 844 */
847 845
@@ -938,10 +936,25 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
938 before = &fl->fl_next; 936 before = &fl->fl_next;
939 } 937 }
940 938
939 /*
940 * The above code only modifies existing locks in case of
941 * merging or replacing. If new lock(s) need to be inserted
942 * all modifications are done bellow this, so it's safe yet to
943 * bail out.
944 */
945 error = -ENOLCK; /* "no luck" */
946 if (right && left == right && !new_fl2)
947 goto out;
948
941 error = 0; 949 error = 0;
942 if (!added) { 950 if (!added) {
943 if (request->fl_type == F_UNLCK) 951 if (request->fl_type == F_UNLCK)
944 goto out; 952 goto out;
953
954 if (!new_fl) {
955 error = -ENOLCK;
956 goto out;
957 }
945 locks_copy_lock(new_fl, request); 958 locks_copy_lock(new_fl, request);
946 locks_insert_lock(before, new_fl); 959 locks_insert_lock(before, new_fl);
947 new_fl = NULL; 960 new_fl = NULL;
@@ -1881,19 +1894,18 @@ out:
1881 */ 1894 */
1882void locks_remove_posix(struct file *filp, fl_owner_t owner) 1895void locks_remove_posix(struct file *filp, fl_owner_t owner)
1883{ 1896{
1884 struct file_lock lock, **before; 1897 struct file_lock lock;
1885 1898
1886 /* 1899 /*
1887 * If there are no locks held on this file, we don't need to call 1900 * If there are no locks held on this file, we don't need to call
1888 * posix_lock_file(). Another process could be setting a lock on this 1901 * posix_lock_file(). Another process could be setting a lock on this
1889 * file at the same time, but we wouldn't remove that lock anyway. 1902 * file at the same time, but we wouldn't remove that lock anyway.
1890 */ 1903 */
1891 before = &filp->f_dentry->d_inode->i_flock; 1904 if (!filp->f_dentry->d_inode->i_flock)
1892 if (*before == NULL)
1893 return; 1905 return;
1894 1906
1895 lock.fl_type = F_UNLCK; 1907 lock.fl_type = F_UNLCK;
1896 lock.fl_flags = FL_POSIX; 1908 lock.fl_flags = FL_POSIX | FL_CLOSE;
1897 lock.fl_start = 0; 1909 lock.fl_start = 0;
1898 lock.fl_end = OFFSET_MAX; 1910 lock.fl_end = OFFSET_MAX;
1899 lock.fl_owner = owner; 1911 lock.fl_owner = owner;
@@ -1902,25 +1914,11 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
1902 lock.fl_ops = NULL; 1914 lock.fl_ops = NULL;
1903 lock.fl_lmops = NULL; 1915 lock.fl_lmops = NULL;
1904 1916
1905 if (filp->f_op && filp->f_op->lock != NULL) { 1917 if (filp->f_op && filp->f_op->lock != NULL)
1906 filp->f_op->lock(filp, F_SETLK, &lock); 1918 filp->f_op->lock(filp, F_SETLK, &lock);
1907 goto out; 1919 else
1908 } 1920 posix_lock_file(filp, &lock);
1909 1921
1910 /* Can't use posix_lock_file here; we need to remove it no matter
1911 * which pid we have.
1912 */
1913 lock_kernel();
1914 while (*before != NULL) {
1915 struct file_lock *fl = *before;
1916 if (IS_POSIX(fl) && posix_same_owner(fl, &lock)) {
1917 locks_delete_lock(before);
1918 continue;
1919 }
1920 before = &fl->fl_next;
1921 }
1922 unlock_kernel();
1923out:
1924 if (lock.fl_ops && lock.fl_ops->fl_release_private) 1922 if (lock.fl_ops && lock.fl_ops->fl_release_private)
1925 lock.fl_ops->fl_release_private(&lock); 1923 lock.fl_ops->fl_release_private(&lock);
1926} 1924}
@@ -2206,63 +2204,6 @@ int lock_may_write(struct inode *inode, loff_t start, unsigned long len)
2206 2204
2207EXPORT_SYMBOL(lock_may_write); 2205EXPORT_SYMBOL(lock_may_write);
2208 2206
2209static inline void __steal_locks(struct file *file, fl_owner_t from)
2210{
2211 struct inode *inode = file->f_dentry->d_inode;
2212 struct file_lock *fl = inode->i_flock;
2213
2214 while (fl) {
2215 if (fl->fl_file == file && fl->fl_owner == from)
2216 fl->fl_owner = current->files;
2217 fl = fl->fl_next;
2218 }
2219}
2220
2221/* When getting ready for executing a binary, we make sure that current
2222 * has a files_struct on its own. Before dropping the old files_struct,
2223 * we take over ownership of all locks for all file descriptors we own.
2224 * Note that we may accidentally steal a lock for a file that a sibling
2225 * has created since the unshare_files() call.
2226 */
2227void steal_locks(fl_owner_t from)
2228{
2229 struct files_struct *files = current->files;
2230 int i, j;
2231 struct fdtable *fdt;
2232
2233 if (from == files)
2234 return;
2235
2236 lock_kernel();
2237 j = 0;
2238
2239 /*
2240 * We are not taking a ref to the file structures, so
2241 * we need to acquire ->file_lock.
2242 */
2243 spin_lock(&files->file_lock);
2244 fdt = files_fdtable(files);
2245 for (;;) {
2246 unsigned long set;
2247 i = j * __NFDBITS;
2248 if (i >= fdt->max_fdset || i >= fdt->max_fds)
2249 break;
2250 set = fdt->open_fds->fds_bits[j++];
2251 while (set) {
2252 if (set & 1) {
2253 struct file *file = fdt->fd[i];
2254 if (file)
2255 __steal_locks(file, from);
2256 }
2257 i++;
2258 set >>= 1;
2259 }
2260 }
2261 spin_unlock(&files->file_lock);
2262 unlock_kernel();
2263}
2264EXPORT_SYMBOL(steal_locks);
2265
2266static int __init filelock_init(void) 2207static int __init filelock_init(void)
2267{ 2208{
2268 filelock_cache = kmem_cache_create("file_lock_cache", 2209 filelock_cache = kmem_cache_create("file_lock_cache",
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index 69224d1fe043..2b0a389d1987 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -60,8 +60,7 @@ static int dir_commit_chunk(struct page *page, unsigned from, unsigned to)
60static struct page * dir_get_page(struct inode *dir, unsigned long n) 60static struct page * dir_get_page(struct inode *dir, unsigned long n)
61{ 61{
62 struct address_space *mapping = dir->i_mapping; 62 struct address_space *mapping = dir->i_mapping;
63 struct page *page = read_cache_page(mapping, n, 63 struct page *page = read_mapping_page(mapping, n, NULL);
64 (filler_t*)mapping->a_ops->readpage, NULL);
65 if (!IS_ERR(page)) { 64 if (!IS_ERR(page)) {
66 wait_on_page_locked(page); 65 wait_on_page_locked(page);
67 kmap(page); 66 kmap(page);
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 2dcccf1d1b7f..a6fb509b7341 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -19,7 +19,7 @@
19 19
20static void minix_read_inode(struct inode * inode); 20static void minix_read_inode(struct inode * inode);
21static int minix_write_inode(struct inode * inode, int wait); 21static int minix_write_inode(struct inode * inode, int wait);
22static int minix_statfs(struct super_block *sb, struct kstatfs *buf); 22static int minix_statfs(struct dentry *dentry, struct kstatfs *buf);
23static int minix_remount (struct super_block * sb, int * flags, char * data); 23static int minix_remount (struct super_block * sb, int * flags, char * data);
24 24
25static void minix_delete_inode(struct inode *inode) 25static void minix_delete_inode(struct inode *inode)
@@ -296,11 +296,11 @@ out_bad_sb:
296 return -EINVAL; 296 return -EINVAL;
297} 297}
298 298
299static int minix_statfs(struct super_block *sb, struct kstatfs *buf) 299static int minix_statfs(struct dentry *dentry, struct kstatfs *buf)
300{ 300{
301 struct minix_sb_info *sbi = minix_sb(sb); 301 struct minix_sb_info *sbi = minix_sb(dentry->d_sb);
302 buf->f_type = sb->s_magic; 302 buf->f_type = dentry->d_sb->s_magic;
303 buf->f_bsize = sb->s_blocksize; 303 buf->f_bsize = dentry->d_sb->s_blocksize;
304 buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size; 304 buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size;
305 buf->f_bfree = minix_count_free_blocks(sbi); 305 buf->f_bfree = minix_count_free_blocks(sbi);
306 buf->f_bavail = buf->f_bfree; 306 buf->f_bavail = buf->f_bfree;
@@ -559,10 +559,11 @@ void minix_truncate(struct inode * inode)
559 V2_minix_truncate(inode); 559 V2_minix_truncate(inode);
560} 560}
561 561
562static struct super_block *minix_get_sb(struct file_system_type *fs_type, 562static int minix_get_sb(struct file_system_type *fs_type,
563 int flags, const char *dev_name, void *data) 563 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
564{ 564{
565 return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super); 565 return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super,
566 mnt);
566} 567}
567 568
568static struct file_system_type minix_fs_type = { 569static struct file_system_type minix_fs_type = {
diff --git a/fs/mpage.c b/fs/mpage.c
index 9bf2eb30e6f4..1e4598247d0b 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -707,9 +707,9 @@ mpage_writepages(struct address_space *mapping,
707 struct pagevec pvec; 707 struct pagevec pvec;
708 int nr_pages; 708 int nr_pages;
709 pgoff_t index; 709 pgoff_t index;
710 pgoff_t end = -1; /* Inclusive */ 710 pgoff_t end; /* Inclusive */
711 int scanned = 0; 711 int scanned = 0;
712 int is_range = 0; 712 int range_whole = 0;
713 713
714 if (wbc->nonblocking && bdi_write_congested(bdi)) { 714 if (wbc->nonblocking && bdi_write_congested(bdi)) {
715 wbc->encountered_congestion = 1; 715 wbc->encountered_congestion = 1;
@@ -721,16 +721,14 @@ mpage_writepages(struct address_space *mapping,
721 writepage = mapping->a_ops->writepage; 721 writepage = mapping->a_ops->writepage;
722 722
723 pagevec_init(&pvec, 0); 723 pagevec_init(&pvec, 0);
724 if (wbc->sync_mode == WB_SYNC_NONE) { 724 if (wbc->range_cyclic) {
725 index = mapping->writeback_index; /* Start from prev offset */ 725 index = mapping->writeback_index; /* Start from prev offset */
726 end = -1;
726 } else { 727 } else {
727 index = 0; /* whole-file sweep */ 728 index = wbc->range_start >> PAGE_CACHE_SHIFT;
728 scanned = 1; 729 end = wbc->range_end >> PAGE_CACHE_SHIFT;
729 } 730 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
730 if (wbc->start || wbc->end) { 731 range_whole = 1;
731 index = wbc->start >> PAGE_CACHE_SHIFT;
732 end = wbc->end >> PAGE_CACHE_SHIFT;
733 is_range = 1;
734 scanned = 1; 732 scanned = 1;
735 } 733 }
736retry: 734retry:
@@ -759,7 +757,7 @@ retry:
759 continue; 757 continue;
760 } 758 }
761 759
762 if (unlikely(is_range) && page->index > end) { 760 if (!wbc->range_cyclic && page->index > end) {
763 done = 1; 761 done = 1;
764 unlock_page(page); 762 unlock_page(page);
765 continue; 763 continue;
@@ -810,7 +808,7 @@ retry:
810 index = 0; 808 index = 0;
811 goto retry; 809 goto retry;
812 } 810 }
813 if (!is_range) 811 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
814 mapping->writeback_index = index; 812 mapping->writeback_index = index;
815 if (bio) 813 if (bio)
816 mpage_bio_submit(WRITE, bio); 814 mpage_bio_submit(WRITE, bio);
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 5b76ccd19e3f..9e44158a7540 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -661,11 +661,12 @@ static int msdos_fill_super(struct super_block *sb, void *data, int silent)
661 return 0; 661 return 0;
662} 662}
663 663
664static struct super_block *msdos_get_sb(struct file_system_type *fs_type, 664static int msdos_get_sb(struct file_system_type *fs_type,
665 int flags, const char *dev_name, 665 int flags, const char *dev_name,
666 void *data) 666 void *data, struct vfsmount *mnt)
667{ 667{
668 return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super); 668 return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super,
669 mnt);
669} 670}
670 671
671static struct file_system_type msdos_fs_type = { 672static struct file_system_type msdos_fs_type = {
diff --git a/fs/namei.c b/fs/namei.c
index d6e2ee251736..bb4a3e40e432 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1127,7 +1127,7 @@ out:
1127 if (likely(retval == 0)) { 1127 if (likely(retval == 0)) {
1128 if (unlikely(current->audit_context && nd && nd->dentry && 1128 if (unlikely(current->audit_context && nd && nd->dentry &&
1129 nd->dentry->d_inode)) 1129 nd->dentry->d_inode))
1130 audit_inode(name, nd->dentry->d_inode, flags); 1130 audit_inode(name, nd->dentry->d_inode);
1131 } 1131 }
1132out_fail: 1132out_fail:
1133 return retval; 1133 return retval;
@@ -2577,8 +2577,7 @@ static char *page_getlink(struct dentry * dentry, struct page **ppage)
2577{ 2577{
2578 struct page * page; 2578 struct page * page;
2579 struct address_space *mapping = dentry->d_inode->i_mapping; 2579 struct address_space *mapping = dentry->d_inode->i_mapping;
2580 page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage, 2580 page = read_mapping_page(mapping, 0, NULL);
2581 NULL);
2582 if (IS_ERR(page)) 2581 if (IS_ERR(page))
2583 goto sync_fail; 2582 goto sync_fail;
2584 wait_on_page_locked(page); 2583 wait_on_page_locked(page);
diff --git a/fs/namespace.c b/fs/namespace.c
index bf478addb852..c13072a5f1ee 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -86,6 +86,15 @@ struct vfsmount *alloc_vfsmnt(const char *name)
86 return mnt; 86 return mnt;
87} 87}
88 88
89int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)
90{
91 mnt->mnt_sb = sb;
92 mnt->mnt_root = dget(sb->s_root);
93 return 0;
94}
95
96EXPORT_SYMBOL(simple_set_mnt);
97
89void free_vfsmnt(struct vfsmount *mnt) 98void free_vfsmnt(struct vfsmount *mnt)
90{ 99{
91 kfree(mnt->mnt_devname); 100 kfree(mnt->mnt_devname);
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index a1f3e972c6ef..90d2ea28f333 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -39,7 +39,7 @@
39 39
40static void ncp_delete_inode(struct inode *); 40static void ncp_delete_inode(struct inode *);
41static void ncp_put_super(struct super_block *); 41static void ncp_put_super(struct super_block *);
42static int ncp_statfs(struct super_block *, struct kstatfs *); 42static int ncp_statfs(struct dentry *, struct kstatfs *);
43 43
44static kmem_cache_t * ncp_inode_cachep; 44static kmem_cache_t * ncp_inode_cachep;
45 45
@@ -724,13 +724,14 @@ static void ncp_put_super(struct super_block *sb)
724 kfree(server); 724 kfree(server);
725} 725}
726 726
727static int ncp_statfs(struct super_block *sb, struct kstatfs *buf) 727static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
728{ 728{
729 struct dentry* d; 729 struct dentry* d;
730 struct inode* i; 730 struct inode* i;
731 struct ncp_inode_info* ni; 731 struct ncp_inode_info* ni;
732 struct ncp_server* s; 732 struct ncp_server* s;
733 struct ncp_volume_info vi; 733 struct ncp_volume_info vi;
734 struct super_block *sb = dentry->d_sb;
734 int err; 735 int err;
735 __u8 dh; 736 __u8 dh;
736 737
@@ -957,10 +958,10 @@ out:
957 return result; 958 return result;
958} 959}
959 960
960static struct super_block *ncp_get_sb(struct file_system_type *fs_type, 961static int ncp_get_sb(struct file_system_type *fs_type,
961 int flags, const char *dev_name, void *data) 962 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
962{ 963{
963 return get_sb_nodev(fs_type, flags, data, ncp_fill_super); 964 return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt);
964} 965}
965 966
966static struct file_system_type ncp_fs_type = { 967static struct file_system_type ncp_fs_type = {
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index fade02c15e6e..fa05c027ea11 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -43,7 +43,7 @@ static int nfs_file_mmap(struct file *, struct vm_area_struct *);
43static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); 43static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
44static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); 44static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t);
45static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t); 45static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t);
46static int nfs_file_flush(struct file *); 46static int nfs_file_flush(struct file *, fl_owner_t id);
47static int nfs_fsync(struct file *, struct dentry *dentry, int datasync); 47static int nfs_fsync(struct file *, struct dentry *dentry, int datasync);
48static int nfs_check_flags(int flags); 48static int nfs_check_flags(int flags);
49static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); 49static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
@@ -188,7 +188,7 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
188 * 188 *
189 */ 189 */
190static int 190static int
191nfs_file_flush(struct file *file) 191nfs_file_flush(struct file *file, fl_owner_t id)
192{ 192{
193 struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; 193 struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
194 struct inode *inode = file->f_dentry->d_inode; 194 struct inode *inode = file->f_dentry->d_inode;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index d0b991a92327..937fbfc381bb 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -65,7 +65,7 @@ static int nfs_write_inode(struct inode *,int);
65static void nfs_delete_inode(struct inode *); 65static void nfs_delete_inode(struct inode *);
66static void nfs_clear_inode(struct inode *); 66static void nfs_clear_inode(struct inode *);
67static void nfs_umount_begin(struct super_block *); 67static void nfs_umount_begin(struct super_block *);
68static int nfs_statfs(struct super_block *, struct kstatfs *); 68static int nfs_statfs(struct dentry *, struct kstatfs *);
69static int nfs_show_options(struct seq_file *, struct vfsmount *); 69static int nfs_show_options(struct seq_file *, struct vfsmount *);
70static int nfs_show_stats(struct seq_file *, struct vfsmount *); 70static int nfs_show_stats(struct seq_file *, struct vfsmount *);
71static void nfs_zap_acl_cache(struct inode *); 71static void nfs_zap_acl_cache(struct inode *);
@@ -534,8 +534,9 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
534} 534}
535 535
536static int 536static int
537nfs_statfs(struct super_block *sb, struct kstatfs *buf) 537nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
538{ 538{
539 struct super_block *sb = dentry->d_sb;
539 struct nfs_server *server = NFS_SB(sb); 540 struct nfs_server *server = NFS_SB(sb);
540 unsigned char blockbits; 541 unsigned char blockbits;
541 unsigned long blockres; 542 unsigned long blockres;
@@ -1690,8 +1691,8 @@ static int nfs_compare_super(struct super_block *sb, void *data)
1690 return !nfs_compare_fh(&old->fh, &server->fh); 1691 return !nfs_compare_fh(&old->fh, &server->fh);
1691} 1692}
1692 1693
1693static struct super_block *nfs_get_sb(struct file_system_type *fs_type, 1694static int nfs_get_sb(struct file_system_type *fs_type,
1694 int flags, const char *dev_name, void *raw_data) 1695 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
1695{ 1696{
1696 int error; 1697 int error;
1697 struct nfs_server *server = NULL; 1698 struct nfs_server *server = NULL;
@@ -1699,14 +1700,14 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
1699 struct nfs_fh *root; 1700 struct nfs_fh *root;
1700 struct nfs_mount_data *data = raw_data; 1701 struct nfs_mount_data *data = raw_data;
1701 1702
1702 s = ERR_PTR(-EINVAL); 1703 error = -EINVAL;
1703 if (data == NULL) { 1704 if (data == NULL) {
1704 dprintk("%s: missing data argument\n", __FUNCTION__); 1705 dprintk("%s: missing data argument\n", __FUNCTION__);
1705 goto out_err; 1706 goto out_err_noserver;
1706 } 1707 }
1707 if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { 1708 if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
1708 dprintk("%s: bad mount version\n", __FUNCTION__); 1709 dprintk("%s: bad mount version\n", __FUNCTION__);
1709 goto out_err; 1710 goto out_err_noserver;
1710 } 1711 }
1711 switch (data->version) { 1712 switch (data->version) {
1712 case 1: 1713 case 1:
@@ -1718,7 +1719,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
1718 dprintk("%s: mount structure version %d does not support NFSv3\n", 1719 dprintk("%s: mount structure version %d does not support NFSv3\n",
1719 __FUNCTION__, 1720 __FUNCTION__,
1720 data->version); 1721 data->version);
1721 goto out_err; 1722 goto out_err_noserver;
1722 } 1723 }
1723 data->root.size = NFS2_FHSIZE; 1724 data->root.size = NFS2_FHSIZE;
1724 memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); 1725 memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
@@ -1727,24 +1728,24 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
1727 dprintk("%s: mount structure version %d does not support strong security\n", 1728 dprintk("%s: mount structure version %d does not support strong security\n",
1728 __FUNCTION__, 1729 __FUNCTION__,
1729 data->version); 1730 data->version);
1730 goto out_err; 1731 goto out_err_noserver;
1731 } 1732 }
1732 case 5: 1733 case 5:
1733 memset(data->context, 0, sizeof(data->context)); 1734 memset(data->context, 0, sizeof(data->context));
1734 } 1735 }
1735#ifndef CONFIG_NFS_V3 1736#ifndef CONFIG_NFS_V3
1736 /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ 1737 /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
1737 s = ERR_PTR(-EPROTONOSUPPORT); 1738 error = -EPROTONOSUPPORT;
1738 if (data->flags & NFS_MOUNT_VER3) { 1739 if (data->flags & NFS_MOUNT_VER3) {
1739 dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); 1740 dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
1740 goto out_err; 1741 goto out_err_noserver;
1741 } 1742 }
1742#endif /* CONFIG_NFS_V3 */ 1743#endif /* CONFIG_NFS_V3 */
1743 1744
1744 s = ERR_PTR(-ENOMEM); 1745 error = -ENOMEM;
1745 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); 1746 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
1746 if (!server) 1747 if (!server)
1747 goto out_err; 1748 goto out_err_noserver;
1748 /* Zero out the NFS state stuff */ 1749 /* Zero out the NFS state stuff */
1749 init_nfsv4_state(server); 1750 init_nfsv4_state(server);
1750 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); 1751 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
@@ -1754,7 +1755,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
1754 root->size = data->root.size; 1755 root->size = data->root.size;
1755 else 1756 else
1756 root->size = NFS2_FHSIZE; 1757 root->size = NFS2_FHSIZE;
1757 s = ERR_PTR(-EINVAL); 1758 error = -EINVAL;
1758 if (root->size > sizeof(root->data)) { 1759 if (root->size > sizeof(root->data)) {
1759 dprintk("%s: invalid root filehandle\n", __FUNCTION__); 1760 dprintk("%s: invalid root filehandle\n", __FUNCTION__);
1760 goto out_err; 1761 goto out_err;
@@ -1770,15 +1771,20 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
1770 } 1771 }
1771 1772
1772 /* Fire up rpciod if not yet running */ 1773 /* Fire up rpciod if not yet running */
1773 s = ERR_PTR(rpciod_up()); 1774 error = rpciod_up();
1774 if (IS_ERR(s)) { 1775 if (error < 0) {
1775 dprintk("%s: couldn't start rpciod! Error = %ld\n", 1776 dprintk("%s: couldn't start rpciod! Error = %d\n",
1776 __FUNCTION__, PTR_ERR(s)); 1777 __FUNCTION__, error);
1777 goto out_err; 1778 goto out_err;
1778 } 1779 }
1779 1780
1780 s = sget(fs_type, nfs_compare_super, nfs_set_super, server); 1781 s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
1781 if (IS_ERR(s) || s->s_root) 1782 if (IS_ERR(s)) {
1783 error = PTR_ERR(s);
1784 goto out_err_rpciod;
1785 }
1786
1787 if (s->s_root)
1782 goto out_rpciod_down; 1788 goto out_rpciod_down;
1783 1789
1784 s->s_flags = flags; 1790 s->s_flags = flags;
@@ -1787,15 +1793,22 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
1787 if (error) { 1793 if (error) {
1788 up_write(&s->s_umount); 1794 up_write(&s->s_umount);
1789 deactivate_super(s); 1795 deactivate_super(s);
1790 return ERR_PTR(error); 1796 return error;
1791 } 1797 }
1792 s->s_flags |= MS_ACTIVE; 1798 s->s_flags |= MS_ACTIVE;
1793 return s; 1799 return simple_set_mnt(mnt, s);
1800
1794out_rpciod_down: 1801out_rpciod_down:
1795 rpciod_down(); 1802 rpciod_down();
1803 kfree(server);
1804 return simple_set_mnt(mnt, s);
1805
1806out_err_rpciod:
1807 rpciod_down();
1796out_err: 1808out_err:
1797 kfree(server); 1809 kfree(server);
1798 return s; 1810out_err_noserver:
1811 return error;
1799} 1812}
1800 1813
1801static void nfs_kill_super(struct super_block *s) 1814static void nfs_kill_super(struct super_block *s)
@@ -2032,8 +2045,8 @@ nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
2032 return dst; 2045 return dst;
2033} 2046}
2034 2047
2035static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, 2048static int nfs4_get_sb(struct file_system_type *fs_type,
2036 int flags, const char *dev_name, void *raw_data) 2049 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
2037{ 2050{
2038 int error; 2051 int error;
2039 struct nfs_server *server; 2052 struct nfs_server *server;
@@ -2043,16 +2056,16 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
2043 2056
2044 if (data == NULL) { 2057 if (data == NULL) {
2045 dprintk("%s: missing data argument\n", __FUNCTION__); 2058 dprintk("%s: missing data argument\n", __FUNCTION__);
2046 return ERR_PTR(-EINVAL); 2059 return -EINVAL;
2047 } 2060 }
2048 if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { 2061 if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
2049 dprintk("%s: bad mount version\n", __FUNCTION__); 2062 dprintk("%s: bad mount version\n", __FUNCTION__);
2050 return ERR_PTR(-EINVAL); 2063 return -EINVAL;
2051 } 2064 }
2052 2065
2053 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); 2066 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
2054 if (!server) 2067 if (!server)
2055 return ERR_PTR(-ENOMEM); 2068 return -ENOMEM;
2056 /* Zero out the NFS state stuff */ 2069 /* Zero out the NFS state stuff */
2057 init_nfsv4_state(server); 2070 init_nfsv4_state(server);
2058 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); 2071 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
@@ -2074,33 +2087,41 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
2074 2087
2075 /* We now require that the mount process passes the remote address */ 2088 /* We now require that the mount process passes the remote address */
2076 if (data->host_addrlen != sizeof(server->addr)) { 2089 if (data->host_addrlen != sizeof(server->addr)) {
2077 s = ERR_PTR(-EINVAL); 2090 error = -EINVAL;
2078 goto out_free; 2091 goto out_free;
2079 } 2092 }
2080 if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { 2093 if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) {
2081 s = ERR_PTR(-EFAULT); 2094 error = -EFAULT;
2082 goto out_free; 2095 goto out_free;
2083 } 2096 }
2084 if (server->addr.sin_family != AF_INET || 2097 if (server->addr.sin_family != AF_INET ||
2085 server->addr.sin_addr.s_addr == INADDR_ANY) { 2098 server->addr.sin_addr.s_addr == INADDR_ANY) {
2086 dprintk("%s: mount program didn't pass remote IP address!\n", 2099 dprintk("%s: mount program didn't pass remote IP address!\n",
2087 __FUNCTION__); 2100 __FUNCTION__);
2088 s = ERR_PTR(-EINVAL); 2101 error = -EINVAL;
2089 goto out_free; 2102 goto out_free;
2090 } 2103 }
2091 2104
2092 /* Fire up rpciod if not yet running */ 2105 /* Fire up rpciod if not yet running */
2093 s = ERR_PTR(rpciod_up()); 2106 error = rpciod_up();
2094 if (IS_ERR(s)) { 2107 if (error < 0) {
2095 dprintk("%s: couldn't start rpciod! Error = %ld\n", 2108 dprintk("%s: couldn't start rpciod! Error = %d\n",
2096 __FUNCTION__, PTR_ERR(s)); 2109 __FUNCTION__, error);
2097 goto out_free; 2110 goto out_free;
2098 } 2111 }
2099 2112
2100 s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); 2113 s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
2101 2114 if (IS_ERR(s)) {
2102 if (IS_ERR(s) || s->s_root) 2115 error = PTR_ERR(s);
2103 goto out_free; 2116 goto out_free;
2117 }
2118
2119 if (s->s_root) {
2120 kfree(server->mnt_path);
2121 kfree(server->hostname);
2122 kfree(server);
2123 return simple_set_mnt(mnt, s);
2124 }
2104 2125
2105 s->s_flags = flags; 2126 s->s_flags = flags;
2106 2127
@@ -2108,17 +2129,17 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
2108 if (error) { 2129 if (error) {
2109 up_write(&s->s_umount); 2130 up_write(&s->s_umount);
2110 deactivate_super(s); 2131 deactivate_super(s);
2111 return ERR_PTR(error); 2132 return error;
2112 } 2133 }
2113 s->s_flags |= MS_ACTIVE; 2134 s->s_flags |= MS_ACTIVE;
2114 return s; 2135 return simple_set_mnt(mnt, s);
2115out_err: 2136out_err:
2116 s = (struct super_block *)p; 2137 error = PTR_ERR(p);
2117out_free: 2138out_free:
2118 kfree(server->mnt_path); 2139 kfree(server->mnt_path);
2119 kfree(server->hostname); 2140 kfree(server->hostname);
2120 kfree(server); 2141 kfree(server);
2121 return s; 2142 return error;
2122} 2143}
2123 2144
2124static void nfs4_kill_super(struct super_block *sb) 2145static void nfs4_kill_super(struct super_block *sb)
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index de3998f15f10..5446a0861d1d 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1310,7 +1310,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1310 if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) || 1310 if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) ||
1311 (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | 1311 (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
1312 FATTR4_WORD1_SPACE_TOTAL))) { 1312 FATTR4_WORD1_SPACE_TOTAL))) {
1313 status = vfs_statfs(dentry->d_inode->i_sb, &statfs); 1313 status = vfs_statfs(dentry, &statfs);
1314 if (status) 1314 if (status)
1315 goto out_nfserr; 1315 goto out_nfserr;
1316 } 1316 }
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 3ef017b3b5bd..a1810e6a93e5 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -494,10 +494,10 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
494 return simple_fill_super(sb, 0x6e667364, nfsd_files); 494 return simple_fill_super(sb, 0x6e667364, nfsd_files);
495} 495}
496 496
497static struct super_block *nfsd_get_sb(struct file_system_type *fs_type, 497static int nfsd_get_sb(struct file_system_type *fs_type,
498 int flags, const char *dev_name, void *data) 498 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
499{ 499{
500 return get_sb_single(fs_type, flags, data, nfsd_fill_super); 500 return get_sb_single(fs_type, flags, data, nfsd_fill_super, mnt);
501} 501}
502 502
503static struct file_system_type nfsd_fs_type = { 503static struct file_system_type nfsd_fs_type = {
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 1d65f13f458c..245eaa1fb59b 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1737,7 +1737,7 @@ int
1737nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat) 1737nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
1738{ 1738{
1739 int err = fh_verify(rqstp, fhp, 0, MAY_NOP); 1739 int err = fh_verify(rqstp, fhp, 0, MAY_NOP);
1740 if (!err && vfs_statfs(fhp->fh_dentry->d_inode->i_sb,stat)) 1740 if (!err && vfs_statfs(fhp->fh_dentry,stat))
1741 err = nfserr_io; 1741 err = nfserr_io;
1742 return err; 1742 return err;
1743} 1743}
diff --git a/fs/ntfs/aops.h b/fs/ntfs/aops.h
index 3b74e66ca2ff..325ce261a107 100644
--- a/fs/ntfs/aops.h
+++ b/fs/ntfs/aops.h
@@ -86,8 +86,7 @@ static inline void ntfs_unmap_page(struct page *page)
86static inline struct page *ntfs_map_page(struct address_space *mapping, 86static inline struct page *ntfs_map_page(struct address_space *mapping,
87 unsigned long index) 87 unsigned long index)
88{ 88{
89 struct page *page = read_cache_page(mapping, index, 89 struct page *page = read_mapping_page(mapping, index, NULL);
90 (filler_t*)mapping->a_ops->readpage, NULL);
91 90
92 if (!IS_ERR(page)) { 91 if (!IS_ERR(page)) {
93 wait_on_page_locked(page); 92 wait_on_page_locked(page);
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index 1663f5c3c6aa..6708e1d68a9e 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -2529,8 +2529,7 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)
2529 end >>= PAGE_CACHE_SHIFT; 2529 end >>= PAGE_CACHE_SHIFT;
2530 /* If there is a first partial page, need to do it the slow way. */ 2530 /* If there is a first partial page, need to do it the slow way. */
2531 if (start_ofs) { 2531 if (start_ofs) {
2532 page = read_cache_page(mapping, idx, 2532 page = read_mapping_page(mapping, idx, NULL);
2533 (filler_t*)mapping->a_ops->readpage, NULL);
2534 if (IS_ERR(page)) { 2533 if (IS_ERR(page)) {
2535 ntfs_error(vol->sb, "Failed to read first partial " 2534 ntfs_error(vol->sb, "Failed to read first partial "
2536 "page (sync error, index 0x%lx).", idx); 2535 "page (sync error, index 0x%lx).", idx);
@@ -2600,8 +2599,7 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)
2600 } 2599 }
2601 /* If there is a last partial page, need to do it the slow way. */ 2600 /* If there is a last partial page, need to do it the slow way. */
2602 if (end_ofs) { 2601 if (end_ofs) {
2603 page = read_cache_page(mapping, idx, 2602 page = read_mapping_page(mapping, idx, NULL);
2604 (filler_t*)mapping->a_ops->readpage, NULL);
2605 if (IS_ERR(page)) { 2603 if (IS_ERR(page)) {
2606 ntfs_error(vol->sb, "Failed to read last partial page " 2604 ntfs_error(vol->sb, "Failed to read last partial page "
2607 "(sync error, index 0x%lx).", idx); 2605 "(sync error, index 0x%lx).", idx);
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index c63a83e8da98..88292f9e4b9b 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -231,8 +231,7 @@ do_non_resident_extend:
231 * Read the page. If the page is not present, this will zero 231 * Read the page. If the page is not present, this will zero
232 * the uninitialized regions for us. 232 * the uninitialized regions for us.
233 */ 233 */
234 page = read_cache_page(mapping, index, 234 page = read_mapping_page(mapping, index, NULL);
235 (filler_t*)mapping->a_ops->readpage, NULL);
236 if (IS_ERR(page)) { 235 if (IS_ERR(page)) {
237 err = PTR_ERR(page); 236 err = PTR_ERR(page);
238 goto init_err_out; 237 goto init_err_out;
@@ -1484,14 +1483,15 @@ static inline void ntfs_flush_dcache_pages(struct page **pages,
1484 unsigned nr_pages) 1483 unsigned nr_pages)
1485{ 1484{
1486 BUG_ON(!nr_pages); 1485 BUG_ON(!nr_pages);
1486 /*
1487 * Warning: Do not do the decrement at the same time as the call to
1488 * flush_dcache_page() because it is a NULL macro on i386 and hence the
1489 * decrement never happens so the loop never terminates.
1490 */
1487 do { 1491 do {
1488 /* 1492 --nr_pages;
1489 * Warning: Do not do the decrement at the same time as the
1490 * call because flush_dcache_page() is a NULL macro on i386
1491 * and hence the decrement never happens.
1492 */
1493 flush_dcache_page(pages[nr_pages]); 1493 flush_dcache_page(pages[nr_pages]);
1494 } while (--nr_pages > 0); 1494 } while (nr_pages > 0);
1495} 1495}
1496 1496
1497/** 1497/**
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 27833f6df49f..0e14acea3f8b 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -2601,10 +2601,10 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,
2601 2601
2602/** 2602/**
2603 * ntfs_statfs - return information about mounted NTFS volume 2603 * ntfs_statfs - return information about mounted NTFS volume
2604 * @sb: super block of mounted volume 2604 * @dentry: dentry from mounted volume
2605 * @sfs: statfs structure in which to return the information 2605 * @sfs: statfs structure in which to return the information
2606 * 2606 *
2607 * Return information about the mounted NTFS volume @sb in the statfs structure 2607 * Return information about the mounted NTFS volume @dentry in the statfs structure
2608 * pointed to by @sfs (this is initialized with zeros before ntfs_statfs is 2608 * pointed to by @sfs (this is initialized with zeros before ntfs_statfs is
2609 * called). We interpret the values to be correct of the moment in time at 2609 * called). We interpret the values to be correct of the moment in time at
2610 * which we are called. Most values are variable otherwise and this isn't just 2610 * which we are called. Most values are variable otherwise and this isn't just
@@ -2617,8 +2617,9 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,
2617 * 2617 *
2618 * Return 0 on success or -errno on error. 2618 * Return 0 on success or -errno on error.
2619 */ 2619 */
2620static int ntfs_statfs(struct super_block *sb, struct kstatfs *sfs) 2620static int ntfs_statfs(struct dentry *dentry, struct kstatfs *sfs)
2621{ 2621{
2622 struct super_block *sb = dentry->d_sb;
2622 s64 size; 2623 s64 size;
2623 ntfs_volume *vol = NTFS_SB(sb); 2624 ntfs_volume *vol = NTFS_SB(sb);
2624 ntfs_inode *mft_ni = NTFS_I(vol->mft_ino); 2625 ntfs_inode *mft_ni = NTFS_I(vol->mft_ino);
@@ -3093,10 +3094,11 @@ struct kmem_cache *ntfs_index_ctx_cache;
3093/* Driver wide mutex. */ 3094/* Driver wide mutex. */
3094DEFINE_MUTEX(ntfs_lock); 3095DEFINE_MUTEX(ntfs_lock);
3095 3096
3096static struct super_block *ntfs_get_sb(struct file_system_type *fs_type, 3097static int ntfs_get_sb(struct file_system_type *fs_type,
3097 int flags, const char *dev_name, void *data) 3098 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
3098{ 3099{
3099 return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super); 3100 return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super,
3101 mnt);
3100} 3102}
3101 3103
3102static struct file_system_type ntfs_fs_type = { 3104static struct file_system_type ntfs_fs_type = {
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
index 7e88e24b3471..7273d9fa6bab 100644
--- a/fs/ocfs2/dlm/dlmfs.c
+++ b/fs/ocfs2/dlm/dlmfs.c
@@ -574,10 +574,10 @@ static struct inode_operations dlmfs_file_inode_operations = {
574 .getattr = simple_getattr, 574 .getattr = simple_getattr,
575}; 575};
576 576
577static struct super_block *dlmfs_get_sb(struct file_system_type *fs_type, 577static int dlmfs_get_sb(struct file_system_type *fs_type,
578 int flags, const char *dev_name, void *data) 578 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
579{ 579{
580 return get_sb_nodev(fs_type, flags, data, dlmfs_fill_super); 580 return get_sb_nodev(fs_type, flags, data, dlmfs_fill_super, mnt);
581} 581}
582 582
583static struct file_system_type dlmfs_fs_type = { 583static struct file_system_type dlmfs_fs_type = {
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 949b3dac30f1..cdf73393f094 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -100,7 +100,7 @@ static int ocfs2_initialize_mem_caches(void);
100static void ocfs2_free_mem_caches(void); 100static void ocfs2_free_mem_caches(void);
101static void ocfs2_delete_osb(struct ocfs2_super *osb); 101static void ocfs2_delete_osb(struct ocfs2_super *osb);
102 102
103static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf); 103static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf);
104 104
105static int ocfs2_sync_fs(struct super_block *sb, int wait); 105static int ocfs2_sync_fs(struct super_block *sb, int wait);
106 106
@@ -672,12 +672,14 @@ read_super_error:
672 return status; 672 return status;
673} 673}
674 674
675static struct super_block *ocfs2_get_sb(struct file_system_type *fs_type, 675static int ocfs2_get_sb(struct file_system_type *fs_type,
676 int flags, 676 int flags,
677 const char *dev_name, 677 const char *dev_name,
678 void *data) 678 void *data,
679 struct vfsmount *mnt)
679{ 680{
680 return get_sb_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super); 681 return get_sb_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super,
682 mnt);
681} 683}
682 684
683static struct file_system_type ocfs2_fs_type = { 685static struct file_system_type ocfs2_fs_type = {
@@ -855,7 +857,7 @@ static void ocfs2_put_super(struct super_block *sb)
855 mlog_exit_void(); 857 mlog_exit_void();
856} 858}
857 859
858static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf) 860static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf)
859{ 861{
860 struct ocfs2_super *osb; 862 struct ocfs2_super *osb;
861 u32 numbits, freebits; 863 u32 numbits, freebits;
@@ -864,9 +866,9 @@ static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf)
864 struct buffer_head *bh = NULL; 866 struct buffer_head *bh = NULL;
865 struct inode *inode = NULL; 867 struct inode *inode = NULL;
866 868
867 mlog_entry("(%p, %p)\n", sb, buf); 869 mlog_entry("(%p, %p)\n", dentry->d_sb, buf);
868 870
869 osb = OCFS2_SB(sb); 871 osb = OCFS2_SB(dentry->d_sb);
870 872
871 inode = ocfs2_get_system_file_inode(osb, 873 inode = ocfs2_get_system_file_inode(osb,
872 GLOBAL_BITMAP_SYSTEM_INODE, 874 GLOBAL_BITMAP_SYSTEM_INODE,
@@ -889,7 +891,7 @@ static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf)
889 freebits = numbits - le32_to_cpu(bm_lock->id1.bitmap1.i_used); 891 freebits = numbits - le32_to_cpu(bm_lock->id1.bitmap1.i_used);
890 892
891 buf->f_type = OCFS2_SUPER_MAGIC; 893 buf->f_type = OCFS2_SUPER_MAGIC;
892 buf->f_bsize = sb->s_blocksize; 894 buf->f_bsize = dentry->d_sb->s_blocksize;
893 buf->f_namelen = OCFS2_MAX_FILENAME_LEN; 895 buf->f_namelen = OCFS2_MAX_FILENAME_LEN;
894 buf->f_blocks = ((sector_t) numbits) * 896 buf->f_blocks = ((sector_t) numbits) *
895 (osb->s_clustersize >> osb->sb->s_blocksize_bits); 897 (osb->s_clustersize >> osb->sb->s_blocksize_bits);
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index f6986bd79e75..0c8a1294ec96 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -64,8 +64,7 @@ static char *ocfs2_page_getlink(struct dentry * dentry,
64{ 64{
65 struct page * page; 65 struct page * page;
66 struct address_space *mapping = dentry->d_inode->i_mapping; 66 struct address_space *mapping = dentry->d_inode->i_mapping;
67 page = read_cache_page(mapping, 0, 67 page = read_mapping_page(mapping, 0, NULL);
68 (filler_t *)mapping->a_ops->readpage, NULL);
69 if (IS_ERR(page)) 68 if (IS_ERR(page))
70 goto sync_fail; 69 goto sync_fail;
71 wait_on_page_locked(page); 70 wait_on_page_locked(page);
diff --git a/fs/open.c b/fs/open.c
index 317b7c7f38a7..5fb16e5267dc 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -31,18 +31,18 @@
31 31
32#include <asm/unistd.h> 32#include <asm/unistd.h>
33 33
34int vfs_statfs(struct super_block *sb, struct kstatfs *buf) 34int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
35{ 35{
36 int retval = -ENODEV; 36 int retval = -ENODEV;
37 37
38 if (sb) { 38 if (dentry) {
39 retval = -ENOSYS; 39 retval = -ENOSYS;
40 if (sb->s_op->statfs) { 40 if (dentry->d_sb->s_op->statfs) {
41 memset(buf, 0, sizeof(*buf)); 41 memset(buf, 0, sizeof(*buf));
42 retval = security_sb_statfs(sb); 42 retval = security_sb_statfs(dentry);
43 if (retval) 43 if (retval)
44 return retval; 44 return retval;
45 retval = sb->s_op->statfs(sb, buf); 45 retval = dentry->d_sb->s_op->statfs(dentry, buf);
46 if (retval == 0 && buf->f_frsize == 0) 46 if (retval == 0 && buf->f_frsize == 0)
47 buf->f_frsize = buf->f_bsize; 47 buf->f_frsize = buf->f_bsize;
48 } 48 }
@@ -52,12 +52,12 @@ int vfs_statfs(struct super_block *sb, struct kstatfs *buf)
52 52
53EXPORT_SYMBOL(vfs_statfs); 53EXPORT_SYMBOL(vfs_statfs);
54 54
55static int vfs_statfs_native(struct super_block *sb, struct statfs *buf) 55static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf)
56{ 56{
57 struct kstatfs st; 57 struct kstatfs st;
58 int retval; 58 int retval;
59 59
60 retval = vfs_statfs(sb, &st); 60 retval = vfs_statfs(dentry, &st);
61 if (retval) 61 if (retval)
62 return retval; 62 return retval;
63 63
@@ -95,12 +95,12 @@ static int vfs_statfs_native(struct super_block *sb, struct statfs *buf)
95 return 0; 95 return 0;
96} 96}
97 97
98static int vfs_statfs64(struct super_block *sb, struct statfs64 *buf) 98static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf)
99{ 99{
100 struct kstatfs st; 100 struct kstatfs st;
101 int retval; 101 int retval;
102 102
103 retval = vfs_statfs(sb, &st); 103 retval = vfs_statfs(dentry, &st);
104 if (retval) 104 if (retval)
105 return retval; 105 return retval;
106 106
@@ -130,7 +130,7 @@ asmlinkage long sys_statfs(const char __user * path, struct statfs __user * buf)
130 error = user_path_walk(path, &nd); 130 error = user_path_walk(path, &nd);
131 if (!error) { 131 if (!error) {
132 struct statfs tmp; 132 struct statfs tmp;
133 error = vfs_statfs_native(nd.dentry->d_inode->i_sb, &tmp); 133 error = vfs_statfs_native(nd.dentry, &tmp);
134 if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 134 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
135 error = -EFAULT; 135 error = -EFAULT;
136 path_release(&nd); 136 path_release(&nd);
@@ -149,7 +149,7 @@ asmlinkage long sys_statfs64(const char __user *path, size_t sz, struct statfs64
149 error = user_path_walk(path, &nd); 149 error = user_path_walk(path, &nd);
150 if (!error) { 150 if (!error) {
151 struct statfs64 tmp; 151 struct statfs64 tmp;
152 error = vfs_statfs64(nd.dentry->d_inode->i_sb, &tmp); 152 error = vfs_statfs64(nd.dentry, &tmp);
153 if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 153 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
154 error = -EFAULT; 154 error = -EFAULT;
155 path_release(&nd); 155 path_release(&nd);
@@ -168,7 +168,7 @@ asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user * buf)
168 file = fget(fd); 168 file = fget(fd);
169 if (!file) 169 if (!file)
170 goto out; 170 goto out;
171 error = vfs_statfs_native(file->f_dentry->d_inode->i_sb, &tmp); 171 error = vfs_statfs_native(file->f_dentry, &tmp);
172 if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 172 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
173 error = -EFAULT; 173 error = -EFAULT;
174 fput(file); 174 fput(file);
@@ -189,7 +189,7 @@ asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, struct statfs64 __user
189 file = fget(fd); 189 file = fget(fd);
190 if (!file) 190 if (!file)
191 goto out; 191 goto out;
192 error = vfs_statfs64(file->f_dentry->d_inode->i_sb, &tmp); 192 error = vfs_statfs64(file->f_dentry, &tmp);
193 if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 193 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
194 error = -EFAULT; 194 error = -EFAULT;
195 fput(file); 195 fput(file);
@@ -633,7 +633,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
633 dentry = file->f_dentry; 633 dentry = file->f_dentry;
634 inode = dentry->d_inode; 634 inode = dentry->d_inode;
635 635
636 audit_inode(NULL, inode, 0); 636 audit_inode(NULL, inode);
637 637
638 err = -EROFS; 638 err = -EROFS;
639 if (IS_RDONLY(inode)) 639 if (IS_RDONLY(inode))
@@ -786,7 +786,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
786 if (file) { 786 if (file) {
787 struct dentry * dentry; 787 struct dentry * dentry;
788 dentry = file->f_dentry; 788 dentry = file->f_dentry;
789 audit_inode(NULL, dentry->d_inode, 0); 789 audit_inode(NULL, dentry->d_inode);
790 error = chown_common(dentry, user, group); 790 error = chown_common(dentry, user, group);
791 fput(file); 791 fput(file);
792 } 792 }
@@ -1152,7 +1152,7 @@ int filp_close(struct file *filp, fl_owner_t id)
1152 } 1152 }
1153 1153
1154 if (filp->f_op && filp->f_op->flush) 1154 if (filp->f_op && filp->f_op->flush)
1155 retval = filp->f_op->flush(filp); 1155 retval = filp->f_op->flush(filp, id);
1156 1156
1157 dnotify_flush(filp, id); 1157 dnotify_flush(filp, id);
1158 locks_remove_posix(filp, id); 1158 locks_remove_posix(filp, id);
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index 0f14276a2e51..464e2bce0203 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -1054,10 +1054,10 @@ out_no_root:
1054 return -ENOMEM; 1054 return -ENOMEM;
1055} 1055}
1056 1056
1057static struct super_block *openprom_get_sb(struct file_system_type *fs_type, 1057static int openprom_get_sb(struct file_system_type *fs_type,
1058 int flags, const char *dev_name, void *data) 1058 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
1059{ 1059{
1060 return get_sb_single(fs_type, flags, data, openprom_fill_super); 1060 return get_sb_single(fs_type, flags, data, openprom_fill_super, mnt);
1061} 1061}
1062 1062
1063static struct file_system_type openprom_fs_type = { 1063static struct file_system_type openprom_fs_type = {
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 7ef1f094de91..2ef313a96b66 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -329,6 +329,7 @@ void delete_partition(struct gendisk *disk, int part)
329 p->ios[0] = p->ios[1] = 0; 329 p->ios[0] = p->ios[1] = 0;
330 p->sectors[0] = p->sectors[1] = 0; 330 p->sectors[0] = p->sectors[1] = 0;
331 devfs_remove("%s/part%d", disk->devfs_name, part); 331 devfs_remove("%s/part%d", disk->devfs_name, part);
332 sysfs_remove_link(&p->kobj, "subsystem");
332 if (p->holder_dir) 333 if (p->holder_dir)
333 kobject_unregister(p->holder_dir); 334 kobject_unregister(p->holder_dir);
334 kobject_uevent(&p->kobj, KOBJ_REMOVE); 335 kobject_uevent(&p->kobj, KOBJ_REMOVE);
@@ -363,6 +364,7 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
363 kobject_add(&p->kobj); 364 kobject_add(&p->kobj);
364 if (!disk->part_uevent_suppress) 365 if (!disk->part_uevent_suppress)
365 kobject_uevent(&p->kobj, KOBJ_ADD); 366 kobject_uevent(&p->kobj, KOBJ_ADD);
367 sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem");
366 partition_sysfs_add_subdir(p); 368 partition_sysfs_add_subdir(p);
367 disk->part[part-1] = p; 369 disk->part[part-1] = p;
368} 370}
@@ -398,6 +400,7 @@ static void disk_sysfs_symlinks(struct gendisk *disk)
398 kfree(disk_name); 400 kfree(disk_name);
399 } 401 }
400 } 402 }
403 sysfs_create_link(&disk->kobj, &block_subsys.kset.kobj, "subsystem");
401} 404}
402 405
403/* Not exported, helper to add_disk(). */ 406/* Not exported, helper to add_disk(). */
@@ -481,6 +484,10 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
481 sector_t from = state->parts[p].from; 484 sector_t from = state->parts[p].from;
482 if (!size) 485 if (!size)
483 continue; 486 continue;
487 if (from + size > get_capacity(disk)) {
488 printk(" %s: p%d exceeds device capacity\n",
489 disk->disk_name, p);
490 }
484 add_partition(disk, p, from, size); 491 add_partition(disk, p, from, size);
485#ifdef CONFIG_BLK_DEV_MD 492#ifdef CONFIG_BLK_DEV_MD
486 if (state->parts[p].flags) 493 if (state->parts[p].flags)
@@ -496,8 +503,8 @@ unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
496 struct address_space *mapping = bdev->bd_inode->i_mapping; 503 struct address_space *mapping = bdev->bd_inode->i_mapping;
497 struct page *page; 504 struct page *page;
498 505
499 page = read_cache_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)), 506 page = read_mapping_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)),
500 (filler_t *)mapping->a_ops->readpage, NULL); 507 NULL);
501 if (!IS_ERR(page)) { 508 if (!IS_ERR(page)) {
502 wait_on_page_locked(page); 509 wait_on_page_locked(page);
503 if (!PageUptodate(page)) 510 if (!PageUptodate(page))
@@ -548,5 +555,6 @@ void del_gendisk(struct gendisk *disk)
548 put_device(disk->driverfs_dev); 555 put_device(disk->driverfs_dev);
549 disk->driverfs_dev = NULL; 556 disk->driverfs_dev = NULL;
550 } 557 }
558 sysfs_remove_link(&disk->kobj, "subsystem");
551 kobject_del(&disk->kobj); 559 kobject_del(&disk->kobj);
552} 560}
diff --git a/fs/pipe.c b/fs/pipe.c
index 5acd8954aaa0..20352573e025 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -979,12 +979,11 @@ no_files:
979 * any operations on the root directory. However, we need a non-trivial 979 * any operations on the root directory. However, we need a non-trivial
980 * d_name - pipe: will go nicely and kill the special-casing in procfs. 980 * d_name - pipe: will go nicely and kill the special-casing in procfs.
981 */ 981 */
982 982static int pipefs_get_sb(struct file_system_type *fs_type,
983static struct super_block * 983 int flags, const char *dev_name, void *data,
984pipefs_get_sb(struct file_system_type *fs_type, int flags, 984 struct vfsmount *mnt)
985 const char *dev_name, void *data)
986{ 985{
987 return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC); 986 return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC, mnt);
988} 987}
989 988
990static struct file_system_type pipe_fs_type = { 989static struct file_system_type pipe_fs_type = {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 6cc77dc3f3ff..6afff725a8c9 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1019,8 +1019,8 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
1019 if (current != task) 1019 if (current != task)
1020 return -EPERM; 1020 return -EPERM;
1021 1021
1022 if (count > PAGE_SIZE) 1022 if (count >= PAGE_SIZE)
1023 count = PAGE_SIZE; 1023 count = PAGE_SIZE - 1;
1024 1024
1025 if (*ppos != 0) { 1025 if (*ppos != 0) {
1026 /* No partial writes. */ 1026 /* No partial writes. */
@@ -1033,6 +1033,7 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
1033 if (copy_from_user(page, buf, count)) 1033 if (copy_from_user(page, buf, count))
1034 goto out_free_page; 1034 goto out_free_page;
1035 1035
1036 page[count] = '\0';
1036 loginuid = simple_strtoul(page, &tmp, 10); 1037 loginuid = simple_strtoul(page, &tmp, 10);
1037 if (tmp == page) { 1038 if (tmp == page) {
1038 length = -EINVAL; 1039 length = -EINVAL;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index c3fd3611112f..9995356ce73e 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -26,10 +26,10 @@ struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc
26struct proc_dir_entry *proc_sys_root; 26struct proc_dir_entry *proc_sys_root;
27#endif 27#endif
28 28
29static struct super_block *proc_get_sb(struct file_system_type *fs_type, 29static int proc_get_sb(struct file_system_type *fs_type,
30 int flags, const char *dev_name, void *data) 30 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
31{ 31{
32 return get_sb_single(fs_type, flags, data, proc_fill_super); 32 return get_sb_single(fs_type, flags, data, proc_fill_super, mnt);
33} 33}
34 34
35static struct file_system_type proc_fs_type = { 35static struct file_system_type proc_fs_type = {
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 2ecd46f85e9f..2f24c46f72a1 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -128,7 +128,7 @@ static struct inode *qnx4_alloc_inode(struct super_block *sb);
128static void qnx4_destroy_inode(struct inode *inode); 128static void qnx4_destroy_inode(struct inode *inode);
129static void qnx4_read_inode(struct inode *); 129static void qnx4_read_inode(struct inode *);
130static int qnx4_remount(struct super_block *sb, int *flags, char *data); 130static int qnx4_remount(struct super_block *sb, int *flags, char *data);
131static int qnx4_statfs(struct super_block *, struct kstatfs *); 131static int qnx4_statfs(struct dentry *, struct kstatfs *);
132 132
133static struct super_operations qnx4_sops = 133static struct super_operations qnx4_sops =
134{ 134{
@@ -282,8 +282,10 @@ unsigned long qnx4_block_map( struct inode *inode, long iblock )
282 return block; 282 return block;
283} 283}
284 284
285static int qnx4_statfs(struct super_block *sb, struct kstatfs *buf) 285static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf)
286{ 286{
287 struct super_block *sb = dentry->d_sb;
288
287 lock_kernel(); 289 lock_kernel();
288 290
289 buf->f_type = sb->s_magic; 291 buf->f_type = sb->s_magic;
@@ -561,10 +563,11 @@ static void destroy_inodecache(void)
561 "qnx4_inode_cache: not all structures were freed\n"); 563 "qnx4_inode_cache: not all structures were freed\n");
562} 564}
563 565
564static struct super_block *qnx4_get_sb(struct file_system_type *fs_type, 566static int qnx4_get_sb(struct file_system_type *fs_type,
565 int flags, const char *dev_name, void *data) 567 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
566{ 568{
567 return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super); 569 return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super,
570 mnt);
568} 571}
569 572
570static struct file_system_type qnx4_fs_type = { 573static struct file_system_type qnx4_fs_type = {
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 14bd2246fb6d..b9677335cc8d 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -185,16 +185,17 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent)
185 return 0; 185 return 0;
186} 186}
187 187
188struct super_block *ramfs_get_sb(struct file_system_type *fs_type, 188int ramfs_get_sb(struct file_system_type *fs_type,
189 int flags, const char *dev_name, void *data) 189 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
190{ 190{
191 return get_sb_nodev(fs_type, flags, data, ramfs_fill_super); 191 return get_sb_nodev(fs_type, flags, data, ramfs_fill_super, mnt);
192} 192}
193 193
194static struct super_block *rootfs_get_sb(struct file_system_type *fs_type, 194static int rootfs_get_sb(struct file_system_type *fs_type,
195 int flags, const char *dev_name, void *data) 195 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
196{ 196{
197 return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super); 197 return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super,
198 mnt);
198} 199}
199 200
200static struct file_system_type ramfs_fs_type = { 201static struct file_system_type ramfs_fs_type = {
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index cae2abbc0c71..00f1321e9209 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -60,7 +60,7 @@ static int is_any_reiserfs_magic_string(struct reiserfs_super_block *rs)
60} 60}
61 61
62static int reiserfs_remount(struct super_block *s, int *flags, char *data); 62static int reiserfs_remount(struct super_block *s, int *flags, char *data);
63static int reiserfs_statfs(struct super_block *s, struct kstatfs *buf); 63static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf);
64 64
65static int reiserfs_sync_fs(struct super_block *s, int wait) 65static int reiserfs_sync_fs(struct super_block *s, int wait)
66{ 66{
@@ -1938,15 +1938,15 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
1938 return errval; 1938 return errval;
1939} 1939}
1940 1940
1941static int reiserfs_statfs(struct super_block *s, struct kstatfs *buf) 1941static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1942{ 1942{
1943 struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s); 1943 struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(dentry->d_sb);
1944 1944
1945 buf->f_namelen = (REISERFS_MAX_NAME(s->s_blocksize)); 1945 buf->f_namelen = (REISERFS_MAX_NAME(s->s_blocksize));
1946 buf->f_bfree = sb_free_blocks(rs); 1946 buf->f_bfree = sb_free_blocks(rs);
1947 buf->f_bavail = buf->f_bfree; 1947 buf->f_bavail = buf->f_bfree;
1948 buf->f_blocks = sb_block_count(rs) - sb_bmap_nr(rs) - 1; 1948 buf->f_blocks = sb_block_count(rs) - sb_bmap_nr(rs) - 1;
1949 buf->f_bsize = s->s_blocksize; 1949 buf->f_bsize = dentry->d_sb->s_blocksize;
1950 /* changed to accommodate gcc folks. */ 1950 /* changed to accommodate gcc folks. */
1951 buf->f_type = REISERFS_SUPER_MAGIC; 1951 buf->f_type = REISERFS_SUPER_MAGIC;
1952 return 0; 1952 return 0;
@@ -2249,11 +2249,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
2249 2249
2250#endif 2250#endif
2251 2251
2252static struct super_block *get_super_block(struct file_system_type *fs_type, 2252static int get_super_block(struct file_system_type *fs_type,
2253 int flags, const char *dev_name, 2253 int flags, const char *dev_name,
2254 void *data) 2254 void *data, struct vfsmount *mnt)
2255{ 2255{
2256 return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super); 2256 return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super,
2257 mnt);
2257} 2258}
2258 2259
2259static int __init init_reiserfs_fs(void) 2260static int __init init_reiserfs_fs(void)
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index ffb79c48c5bf..39fedaa88a0c 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -452,8 +452,7 @@ static struct page *reiserfs_get_page(struct inode *dir, unsigned long n)
452 /* We can deadlock if we try to free dentries, 452 /* We can deadlock if we try to free dentries,
453 and an unlink/rmdir has just occured - GFP_NOFS avoids this */ 453 and an unlink/rmdir has just occured - GFP_NOFS avoids this */
454 mapping_set_gfp_mask(mapping, GFP_NOFS); 454 mapping_set_gfp_mask(mapping, GFP_NOFS);
455 page = read_cache_page(mapping, n, 455 page = read_mapping_page(mapping, n, NULL);
456 (filler_t *) mapping->a_ops->readpage, NULL);
457 if (!IS_ERR(page)) { 456 if (!IS_ERR(page)) {
458 wait_on_page_locked(page); 457 wait_on_page_locked(page);
459 kmap(page); 458 kmap(page);
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index 9b9eda7b335c..283fbc6b8eea 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -179,12 +179,12 @@ outnobh:
179/* That's simple too. */ 179/* That's simple too. */
180 180
181static int 181static int
182romfs_statfs(struct super_block *sb, struct kstatfs *buf) 182romfs_statfs(struct dentry *dentry, struct kstatfs *buf)
183{ 183{
184 buf->f_type = ROMFS_MAGIC; 184 buf->f_type = ROMFS_MAGIC;
185 buf->f_bsize = ROMBSIZE; 185 buf->f_bsize = ROMBSIZE;
186 buf->f_bfree = buf->f_bavail = buf->f_ffree; 186 buf->f_bfree = buf->f_bavail = buf->f_ffree;
187 buf->f_blocks = (romfs_maxsize(sb)+ROMBSIZE-1)>>ROMBSBITS; 187 buf->f_blocks = (romfs_maxsize(dentry->d_sb)+ROMBSIZE-1)>>ROMBSBITS;
188 buf->f_namelen = ROMFS_MAXFN; 188 buf->f_namelen = ROMFS_MAXFN;
189 return 0; 189 return 0;
190} 190}
@@ -607,10 +607,11 @@ static struct super_operations romfs_ops = {
607 .remount_fs = romfs_remount, 607 .remount_fs = romfs_remount,
608}; 608};
609 609
610static struct super_block *romfs_get_sb(struct file_system_type *fs_type, 610static int romfs_get_sb(struct file_system_type *fs_type,
611 int flags, const char *dev_name, void *data) 611 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
612{ 612{
613 return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super); 613 return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super,
614 mnt);
614} 615}
615 616
616static struct file_system_type romfs_fs_type = { 617static struct file_system_type romfs_fs_type = {
diff --git a/fs/select.c b/fs/select.c
index a8109baa5e46..9c4f0f2604f1 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -546,37 +546,38 @@ struct poll_list {
546 546
547#define POLLFD_PER_PAGE ((PAGE_SIZE-sizeof(struct poll_list)) / sizeof(struct pollfd)) 547#define POLLFD_PER_PAGE ((PAGE_SIZE-sizeof(struct poll_list)) / sizeof(struct pollfd))
548 548
549static void do_pollfd(unsigned int num, struct pollfd * fdpage, 549/*
550 poll_table ** pwait, int *count) 550 * Fish for pollable events on the pollfd->fd file descriptor. We're only
551 * interested in events matching the pollfd->events mask, and the result
552 * matching that mask is both recorded in pollfd->revents and returned. The
553 * pwait poll_table will be used by the fd-provided poll handler for waiting,
554 * if non-NULL.
555 */
556static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait)
551{ 557{
552 int i; 558 unsigned int mask;
553 559 int fd;
554 for (i = 0; i < num; i++) { 560
555 int fd; 561 mask = 0;
556 unsigned int mask; 562 fd = pollfd->fd;
557 struct pollfd *fdp; 563 if (fd >= 0) {
558 564 int fput_needed;
559 mask = 0; 565 struct file * file;
560 fdp = fdpage+i; 566
561 fd = fdp->fd; 567 file = fget_light(fd, &fput_needed);
562 if (fd >= 0) { 568 mask = POLLNVAL;
563 int fput_needed; 569 if (file != NULL) {
564 struct file * file = fget_light(fd, &fput_needed); 570 mask = DEFAULT_POLLMASK;
565 mask = POLLNVAL; 571 if (file->f_op && file->f_op->poll)
566 if (file != NULL) { 572 mask = file->f_op->poll(file, pwait);
567 mask = DEFAULT_POLLMASK; 573 /* Mask out unneeded events. */
568 if (file->f_op && file->f_op->poll) 574 mask &= pollfd->events | POLLERR | POLLHUP;
569 mask = file->f_op->poll(file, *pwait); 575 fput_light(file, fput_needed);
570 mask &= fdp->events | POLLERR | POLLHUP;
571 fput_light(file, fput_needed);
572 }
573 if (mask) {
574 *pwait = NULL;
575 (*count)++;
576 }
577 } 576 }
578 fdp->revents = mask;
579 } 577 }
578 pollfd->revents = mask;
579
580 return mask;
580} 581}
581 582
582static int do_poll(unsigned int nfds, struct poll_list *list, 583static int do_poll(unsigned int nfds, struct poll_list *list,
@@ -594,11 +595,29 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
594 long __timeout; 595 long __timeout;
595 596
596 set_current_state(TASK_INTERRUPTIBLE); 597 set_current_state(TASK_INTERRUPTIBLE);
597 walk = list; 598 for (walk = list; walk != NULL; walk = walk->next) {
598 while(walk != NULL) { 599 struct pollfd * pfd, * pfd_end;
599 do_pollfd( walk->len, walk->entries, &pt, &count); 600
600 walk = walk->next; 601 pfd = walk->entries;
602 pfd_end = pfd + walk->len;
603 for (; pfd != pfd_end; pfd++) {
604 /*
605 * Fish for events. If we found one, record it
606 * and kill the poll_table, so we don't
607 * needlessly register any other waiters after
608 * this. They'll get immediately deregistered
609 * when we break out and return.
610 */
611 if (do_pollfd(pfd, pt)) {
612 count++;
613 pt = NULL;
614 }
615 }
601 } 616 }
617 /*
618 * All waiters have already been registered, so don't provide
619 * a poll_table to them on the next loop iteration.
620 */
602 pt = NULL; 621 pt = NULL;
603 if (count || !*timeout || signal_pending(current)) 622 if (count || !*timeout || signal_pending(current))
604 break; 623 break;
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index fdeabc0a34f7..506ff87c1d4b 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -48,7 +48,7 @@
48 48
49static void smb_delete_inode(struct inode *); 49static void smb_delete_inode(struct inode *);
50static void smb_put_super(struct super_block *); 50static void smb_put_super(struct super_block *);
51static int smb_statfs(struct super_block *, struct kstatfs *); 51static int smb_statfs(struct dentry *, struct kstatfs *);
52static int smb_show_options(struct seq_file *, struct vfsmount *); 52static int smb_show_options(struct seq_file *, struct vfsmount *);
53 53
54static kmem_cache_t *smb_inode_cachep; 54static kmem_cache_t *smb_inode_cachep;
@@ -641,13 +641,13 @@ out_no_server:
641} 641}
642 642
643static int 643static int
644smb_statfs(struct super_block *sb, struct kstatfs *buf) 644smb_statfs(struct dentry *dentry, struct kstatfs *buf)
645{ 645{
646 int result; 646 int result;
647 647
648 lock_kernel(); 648 lock_kernel();
649 649
650 result = smb_proc_dskattr(sb, buf); 650 result = smb_proc_dskattr(dentry, buf);
651 651
652 unlock_kernel(); 652 unlock_kernel();
653 653
@@ -782,10 +782,10 @@ out:
782 return error; 782 return error;
783} 783}
784 784
785static struct super_block *smb_get_sb(struct file_system_type *fs_type, 785static int smb_get_sb(struct file_system_type *fs_type,
786 int flags, const char *dev_name, void *data) 786 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
787{ 787{
788 return get_sb_nodev(fs_type, flags, data, smb_fill_super); 788 return get_sb_nodev(fs_type, flags, data, smb_fill_super, mnt);
789} 789}
790 790
791static struct file_system_type smb_fs_type = { 791static struct file_system_type smb_fs_type = {
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index b1b878b81730..c3495059889d 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -3226,9 +3226,9 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr)
3226} 3226}
3227 3227
3228int 3228int
3229smb_proc_dskattr(struct super_block *sb, struct kstatfs *attr) 3229smb_proc_dskattr(struct dentry *dentry, struct kstatfs *attr)
3230{ 3230{
3231 struct smb_sb_info *server = SMB_SB(sb); 3231 struct smb_sb_info *server = SMB_SB(dentry->d_sb);
3232 int result; 3232 int result;
3233 char *p; 3233 char *p;
3234 long unit; 3234 long unit;
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h
index 47664597e6b1..972ed7dad388 100644
--- a/fs/smbfs/proto.h
+++ b/fs/smbfs/proto.h
@@ -29,7 +29,7 @@ extern int smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr);
29extern int smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr); 29extern int smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr);
30extern int smb_proc_setattr_unix(struct dentry *d, struct iattr *attr, unsigned int major, unsigned int minor); 30extern int smb_proc_setattr_unix(struct dentry *d, struct iattr *attr, unsigned int major, unsigned int minor);
31extern int smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr); 31extern int smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr);
32extern int smb_proc_dskattr(struct super_block *sb, struct kstatfs *attr); 32extern int smb_proc_dskattr(struct dentry *dentry, struct kstatfs *attr);
33extern int smb_proc_read_link(struct smb_sb_info *server, struct dentry *d, char *buffer, int len); 33extern int smb_proc_read_link(struct smb_sb_info *server, struct dentry *d, char *buffer, int len);
34extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const char *oldpath); 34extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const char *oldpath);
35extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry); 35extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry);
diff --git a/fs/splice.c b/fs/splice.c
index a285fd746dc0..05fd2787be98 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -55,31 +55,43 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe,
55 struct pipe_buffer *buf) 55 struct pipe_buffer *buf)
56{ 56{
57 struct page *page = buf->page; 57 struct page *page = buf->page;
58 struct address_space *mapping = page_mapping(page); 58 struct address_space *mapping;
59 59
60 lock_page(page); 60 lock_page(page);
61 61
62 WARN_ON(!PageUptodate(page)); 62 mapping = page_mapping(page);
63 if (mapping) {
64 WARN_ON(!PageUptodate(page));
63 65
64 /* 66 /*
65 * At least for ext2 with nobh option, we need to wait on writeback 67 * At least for ext2 with nobh option, we need to wait on
66 * completing on this page, since we'll remove it from the pagecache. 68 * writeback completing on this page, since we'll remove it
67 * Otherwise truncate wont wait on the page, allowing the disk 69 * from the pagecache. Otherwise truncate wont wait on the
68 * blocks to be reused by someone else before we actually wrote our 70 * page, allowing the disk blocks to be reused by someone else
69 * data to them. fs corruption ensues. 71 * before we actually wrote our data to them. fs corruption
70 */ 72 * ensues.
71 wait_on_page_writeback(page); 73 */
74 wait_on_page_writeback(page);
72 75
73 if (PagePrivate(page)) 76 if (PagePrivate(page))
74 try_to_release_page(page, mapping_gfp_mask(mapping)); 77 try_to_release_page(page, mapping_gfp_mask(mapping));
75 78
76 if (!remove_mapping(mapping, page)) { 79 /*
77 unlock_page(page); 80 * If we succeeded in removing the mapping, set LRU flag
78 return 1; 81 * and return good.
82 */
83 if (remove_mapping(mapping, page)) {
84 buf->flags |= PIPE_BUF_FLAG_LRU;
85 return 0;
86 }
79 } 87 }
80 88
81 buf->flags |= PIPE_BUF_FLAG_LRU; 89 /*
82 return 0; 90 * Raced with truncate or failed to remove page from current
91 * address space, unlock and return failure.
92 */
93 unlock_page(page);
94 return 1;
83} 95}
84 96
85static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe, 97static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe,
diff --git a/fs/super.c b/fs/super.c
index a66f66bb8049..057b5325b7ef 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -231,7 +231,7 @@ void generic_shutdown_super(struct super_block *sb)
231 if (root) { 231 if (root) {
232 sb->s_root = NULL; 232 sb->s_root = NULL;
233 shrink_dcache_parent(root); 233 shrink_dcache_parent(root);
234 shrink_dcache_anon(&sb->s_anon); 234 shrink_dcache_sb(sb);
235 dput(root); 235 dput(root);
236 fsync_super(sb); 236 fsync_super(sb);
237 lock_super(sb); 237 lock_super(sb);
@@ -486,7 +486,7 @@ asmlinkage long sys_ustat(unsigned dev, struct ustat __user * ubuf)
486 s = user_get_super(new_decode_dev(dev)); 486 s = user_get_super(new_decode_dev(dev));
487 if (s == NULL) 487 if (s == NULL)
488 goto out; 488 goto out;
489 err = vfs_statfs(s, &sbuf); 489 err = vfs_statfs(s->s_root, &sbuf);
490 drop_super(s); 490 drop_super(s);
491 if (err) 491 if (err)
492 goto out; 492 goto out;
@@ -676,9 +676,10 @@ static void bdev_uevent(struct block_device *bdev, enum kobject_action action)
676 } 676 }
677} 677}
678 678
679struct super_block *get_sb_bdev(struct file_system_type *fs_type, 679int get_sb_bdev(struct file_system_type *fs_type,
680 int flags, const char *dev_name, void *data, 680 int flags, const char *dev_name, void *data,
681 int (*fill_super)(struct super_block *, void *, int)) 681 int (*fill_super)(struct super_block *, void *, int),
682 struct vfsmount *mnt)
682{ 683{
683 struct block_device *bdev; 684 struct block_device *bdev;
684 struct super_block *s; 685 struct super_block *s;
@@ -686,7 +687,7 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
686 687
687 bdev = open_bdev_excl(dev_name, flags, fs_type); 688 bdev = open_bdev_excl(dev_name, flags, fs_type);
688 if (IS_ERR(bdev)) 689 if (IS_ERR(bdev))
689 return (struct super_block *)bdev; 690 return PTR_ERR(bdev);
690 691
691 /* 692 /*
692 * once the super is inserted into the list by sget, s_umount 693 * once the super is inserted into the list by sget, s_umount
@@ -697,15 +698,17 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
697 s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); 698 s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
698 mutex_unlock(&bdev->bd_mount_mutex); 699 mutex_unlock(&bdev->bd_mount_mutex);
699 if (IS_ERR(s)) 700 if (IS_ERR(s))
700 goto out; 701 goto error_s;
701 702
702 if (s->s_root) { 703 if (s->s_root) {
703 if ((flags ^ s->s_flags) & MS_RDONLY) { 704 if ((flags ^ s->s_flags) & MS_RDONLY) {
704 up_write(&s->s_umount); 705 up_write(&s->s_umount);
705 deactivate_super(s); 706 deactivate_super(s);
706 s = ERR_PTR(-EBUSY); 707 error = -EBUSY;
708 goto error_bdev;
707 } 709 }
708 goto out; 710
711 close_bdev_excl(bdev);
709 } else { 712 } else {
710 char b[BDEVNAME_SIZE]; 713 char b[BDEVNAME_SIZE];
711 714
@@ -716,18 +719,21 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
716 if (error) { 719 if (error) {
717 up_write(&s->s_umount); 720 up_write(&s->s_umount);
718 deactivate_super(s); 721 deactivate_super(s);
719 s = ERR_PTR(error); 722 goto error;
720 } else {
721 s->s_flags |= MS_ACTIVE;
722 bdev_uevent(bdev, KOBJ_MOUNT);
723 } 723 }
724
725 s->s_flags |= MS_ACTIVE;
726 bdev_uevent(bdev, KOBJ_MOUNT);
724 } 727 }
725 728
726 return s; 729 return simple_set_mnt(mnt, s);
727 730
728out: 731error_s:
732 error = PTR_ERR(s);
733error_bdev:
729 close_bdev_excl(bdev); 734 close_bdev_excl(bdev);
730 return s; 735error:
736 return error;
731} 737}
732 738
733EXPORT_SYMBOL(get_sb_bdev); 739EXPORT_SYMBOL(get_sb_bdev);
@@ -744,15 +750,16 @@ void kill_block_super(struct super_block *sb)
744 750
745EXPORT_SYMBOL(kill_block_super); 751EXPORT_SYMBOL(kill_block_super);
746 752
747struct super_block *get_sb_nodev(struct file_system_type *fs_type, 753int get_sb_nodev(struct file_system_type *fs_type,
748 int flags, void *data, 754 int flags, void *data,
749 int (*fill_super)(struct super_block *, void *, int)) 755 int (*fill_super)(struct super_block *, void *, int),
756 struct vfsmount *mnt)
750{ 757{
751 int error; 758 int error;
752 struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); 759 struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
753 760
754 if (IS_ERR(s)) 761 if (IS_ERR(s))
755 return s; 762 return PTR_ERR(s);
756 763
757 s->s_flags = flags; 764 s->s_flags = flags;
758 765
@@ -760,10 +767,10 @@ struct super_block *get_sb_nodev(struct file_system_type *fs_type,
760 if (error) { 767 if (error) {
761 up_write(&s->s_umount); 768 up_write(&s->s_umount);
762 deactivate_super(s); 769 deactivate_super(s);
763 return ERR_PTR(error); 770 return error;
764 } 771 }
765 s->s_flags |= MS_ACTIVE; 772 s->s_flags |= MS_ACTIVE;
766 return s; 773 return simple_set_mnt(mnt, s);
767} 774}
768 775
769EXPORT_SYMBOL(get_sb_nodev); 776EXPORT_SYMBOL(get_sb_nodev);
@@ -773,94 +780,102 @@ static int compare_single(struct super_block *s, void *p)
773 return 1; 780 return 1;
774} 781}
775 782
776struct super_block *get_sb_single(struct file_system_type *fs_type, 783int get_sb_single(struct file_system_type *fs_type,
777 int flags, void *data, 784 int flags, void *data,
778 int (*fill_super)(struct super_block *, void *, int)) 785 int (*fill_super)(struct super_block *, void *, int),
786 struct vfsmount *mnt)
779{ 787{
780 struct super_block *s; 788 struct super_block *s;
781 int error; 789 int error;
782 790
783 s = sget(fs_type, compare_single, set_anon_super, NULL); 791 s = sget(fs_type, compare_single, set_anon_super, NULL);
784 if (IS_ERR(s)) 792 if (IS_ERR(s))
785 return s; 793 return PTR_ERR(s);
786 if (!s->s_root) { 794 if (!s->s_root) {
787 s->s_flags = flags; 795 s->s_flags = flags;
788 error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); 796 error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
789 if (error) { 797 if (error) {
790 up_write(&s->s_umount); 798 up_write(&s->s_umount);
791 deactivate_super(s); 799 deactivate_super(s);
792 return ERR_PTR(error); 800 return error;
793 } 801 }
794 s->s_flags |= MS_ACTIVE; 802 s->s_flags |= MS_ACTIVE;
795 } 803 }
796 do_remount_sb(s, flags, data, 0); 804 do_remount_sb(s, flags, data, 0);
797 return s; 805 return simple_set_mnt(mnt, s);
798} 806}
799 807
800EXPORT_SYMBOL(get_sb_single); 808EXPORT_SYMBOL(get_sb_single);
801 809
802struct vfsmount * 810struct vfsmount *
803do_kern_mount(const char *fstype, int flags, const char *name, void *data) 811vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
804{ 812{
805 struct file_system_type *type = get_fs_type(fstype);
806 struct super_block *sb = ERR_PTR(-ENOMEM);
807 struct vfsmount *mnt; 813 struct vfsmount *mnt;
808 int error;
809 char *secdata = NULL; 814 char *secdata = NULL;
815 int error;
810 816
811 if (!type) 817 if (!type)
812 return ERR_PTR(-ENODEV); 818 return ERR_PTR(-ENODEV);
813 819
820 error = -ENOMEM;
814 mnt = alloc_vfsmnt(name); 821 mnt = alloc_vfsmnt(name);
815 if (!mnt) 822 if (!mnt)
816 goto out; 823 goto out;
817 824
818 if (data) { 825 if (data) {
819 secdata = alloc_secdata(); 826 secdata = alloc_secdata();
820 if (!secdata) { 827 if (!secdata)
821 sb = ERR_PTR(-ENOMEM);
822 goto out_mnt; 828 goto out_mnt;
823 }
824 829
825 error = security_sb_copy_data(type, data, secdata); 830 error = security_sb_copy_data(type, data, secdata);
826 if (error) { 831 if (error)
827 sb = ERR_PTR(error);
828 goto out_free_secdata; 832 goto out_free_secdata;
829 }
830 } 833 }
831 834
832 sb = type->get_sb(type, flags, name, data); 835 error = type->get_sb(type, flags, name, data, mnt);
833 if (IS_ERR(sb)) 836 if (error < 0)
834 goto out_free_secdata; 837 goto out_free_secdata;
835 error = security_sb_kern_mount(sb, secdata); 838
839 error = security_sb_kern_mount(mnt->mnt_sb, secdata);
836 if (error) 840 if (error)
837 goto out_sb; 841 goto out_sb;
838 mnt->mnt_sb = sb; 842
839 mnt->mnt_root = dget(sb->s_root); 843 mnt->mnt_mountpoint = mnt->mnt_root;
840 mnt->mnt_mountpoint = sb->s_root;
841 mnt->mnt_parent = mnt; 844 mnt->mnt_parent = mnt;
842 up_write(&sb->s_umount); 845 up_write(&mnt->mnt_sb->s_umount);
843 free_secdata(secdata); 846 free_secdata(secdata);
844 put_filesystem(type);
845 return mnt; 847 return mnt;
846out_sb: 848out_sb:
847 up_write(&sb->s_umount); 849 dput(mnt->mnt_root);
848 deactivate_super(sb); 850 up_write(&mnt->mnt_sb->s_umount);
849 sb = ERR_PTR(error); 851 deactivate_super(mnt->mnt_sb);
850out_free_secdata: 852out_free_secdata:
851 free_secdata(secdata); 853 free_secdata(secdata);
852out_mnt: 854out_mnt:
853 free_vfsmnt(mnt); 855 free_vfsmnt(mnt);
854out: 856out:
857 return ERR_PTR(error);
858}
859
860EXPORT_SYMBOL_GPL(vfs_kern_mount);
861
862struct vfsmount *
863do_kern_mount(const char *fstype, int flags, const char *name, void *data)
864{
865 struct file_system_type *type = get_fs_type(fstype);
866 struct vfsmount *mnt;
867 if (!type)
868 return ERR_PTR(-ENODEV);
869 mnt = vfs_kern_mount(type, flags, name, data);
855 put_filesystem(type); 870 put_filesystem(type);
856 return (struct vfsmount *)sb; 871 return mnt;
857} 872}
858 873
859EXPORT_SYMBOL_GPL(do_kern_mount); 874EXPORT_SYMBOL_GPL(do_kern_mount);
860 875
861struct vfsmount *kern_mount(struct file_system_type *type) 876struct vfsmount *kern_mount(struct file_system_type *type)
862{ 877{
863 return do_kern_mount(type->name, 0, type->name, NULL); 878 return vfs_kern_mount(type, 0, type->name, NULL);
864} 879}
865 880
866EXPORT_SYMBOL(kern_mount); 881EXPORT_SYMBOL(kern_mount);
diff --git a/fs/sync.c b/fs/sync.c
index aab5ffe77e9f..955aef04da28 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -100,7 +100,7 @@ asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
100 } 100 }
101 101
102 if (nbytes == 0) 102 if (nbytes == 0)
103 endbyte = -1; 103 endbyte = LLONG_MAX;
104 else 104 else
105 endbyte--; /* inclusive */ 105 endbyte--; /* inclusive */
106 106
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index f1117e885bd6..40190c489271 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -66,10 +66,10 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
66 return 0; 66 return 0;
67} 67}
68 68
69static struct super_block *sysfs_get_sb(struct file_system_type *fs_type, 69static int sysfs_get_sb(struct file_system_type *fs_type,
70 int flags, const char *dev_name, void *data) 70 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
71{ 71{
72 return get_sb_single(fs_type, flags, data, sysfs_fill_super); 72 return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt);
73} 73}
74 74
75static struct file_system_type sysfs_fs_type = { 75static struct file_system_type sysfs_fs_type = {
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index d7074341ee87..f2bef962d309 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -53,8 +53,7 @@ static int dir_commit_chunk(struct page *page, unsigned from, unsigned to)
53static struct page * dir_get_page(struct inode *dir, unsigned long n) 53static struct page * dir_get_page(struct inode *dir, unsigned long n)
54{ 54{
55 struct address_space *mapping = dir->i_mapping; 55 struct address_space *mapping = dir->i_mapping;
56 struct page *page = read_cache_page(mapping, n, 56 struct page *page = read_mapping_page(mapping, n, NULL);
57 (filler_t*)mapping->a_ops->readpage, NULL);
58 if (!IS_ERR(page)) { 57 if (!IS_ERR(page)) {
59 wait_on_page_locked(page); 58 wait_on_page_locked(page);
60 kmap(page); 59 kmap(page);
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 3ff89cc5833a..58b2d22142ba 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -85,8 +85,9 @@ static void sysv_put_super(struct super_block *sb)
85 kfree(sbi); 85 kfree(sbi);
86} 86}
87 87
88static int sysv_statfs(struct super_block *sb, struct kstatfs *buf) 88static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf)
89{ 89{
90 struct super_block *sb = dentry->d_sb;
90 struct sysv_sb_info *sbi = SYSV_SB(sb); 91 struct sysv_sb_info *sbi = SYSV_SB(sb);
91 92
92 buf->f_type = sb->s_magic; 93 buf->f_type = sb->s_magic;
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
index e92b991e6dda..876639b93321 100644
--- a/fs/sysv/super.c
+++ b/fs/sysv/super.c
@@ -506,16 +506,17 @@ failed:
506 506
507/* Every kernel module contains stuff like this. */ 507/* Every kernel module contains stuff like this. */
508 508
509static struct super_block *sysv_get_sb(struct file_system_type *fs_type, 509static int sysv_get_sb(struct file_system_type *fs_type,
510 int flags, const char *dev_name, void *data) 510 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
511{ 511{
512 return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super); 512 return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super,
513 mnt);
513} 514}
514 515
515static struct super_block *v7_get_sb(struct file_system_type *fs_type, 516static int v7_get_sb(struct file_system_type *fs_type,
516 int flags, const char *dev_name, void *data) 517 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
517{ 518{
518 return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super); 519 return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super, mnt);
519} 520}
520 521
521static struct file_system_type sysv_fs_type = { 522static struct file_system_type sysv_fs_type = {
diff --git a/fs/udf/super.c b/fs/udf/super.c
index e45789fe38e8..44fe2cb0bbb2 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -91,13 +91,13 @@ static void udf_load_partdesc(struct super_block *, struct buffer_head *);
91static void udf_open_lvid(struct super_block *); 91static void udf_open_lvid(struct super_block *);
92static void udf_close_lvid(struct super_block *); 92static void udf_close_lvid(struct super_block *);
93static unsigned int udf_count_free(struct super_block *); 93static unsigned int udf_count_free(struct super_block *);
94static int udf_statfs(struct super_block *, struct kstatfs *); 94static int udf_statfs(struct dentry *, struct kstatfs *);
95 95
96/* UDF filesystem type */ 96/* UDF filesystem type */
97static struct super_block *udf_get_sb(struct file_system_type *fs_type, 97static int udf_get_sb(struct file_system_type *fs_type,
98 int flags, const char *dev_name, void *data) 98 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
99{ 99{
100 return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super); 100 return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super, mnt);
101} 101}
102 102
103static struct file_system_type udf_fstype = { 103static struct file_system_type udf_fstype = {
@@ -1779,8 +1779,10 @@ udf_put_super(struct super_block *sb)
1779 * Written, tested, and released. 1779 * Written, tested, and released.
1780 */ 1780 */
1781static int 1781static int
1782udf_statfs(struct super_block *sb, struct kstatfs *buf) 1782udf_statfs(struct dentry *dentry, struct kstatfs *buf)
1783{ 1783{
1784 struct super_block *sb = dentry->d_sb;
1785
1784 buf->f_type = UDF_SUPER_MAGIC; 1786 buf->f_type = UDF_SUPER_MAGIC;
1785 buf->f_bsize = sb->s_blocksize; 1787 buf->f_bsize = sb->s_blocksize;
1786 buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)); 1788 buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb));
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index db98a4c71e63..fe5ab2aa2899 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -1113,8 +1113,9 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
1113 return 0; 1113 return 0;
1114} 1114}
1115 1115
1116static int ufs_statfs (struct super_block *sb, struct kstatfs *buf) 1116static int ufs_statfs (struct dentry *dentry, struct kstatfs *buf)
1117{ 1117{
1118 struct super_block *sb = dentry->d_sb;
1118 struct ufs_sb_private_info * uspi; 1119 struct ufs_sb_private_info * uspi;
1119 struct ufs_super_block_first * usb1; 1120 struct ufs_super_block_first * usb1;
1120 struct ufs_super_block * usb; 1121 struct ufs_super_block * usb;
@@ -1311,10 +1312,10 @@ out:
1311 1312
1312#endif 1313#endif
1313 1314
1314static struct super_block *ufs_get_sb(struct file_system_type *fs_type, 1315static int ufs_get_sb(struct file_system_type *fs_type,
1315 int flags, const char *dev_name, void *data) 1316 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
1316{ 1317{
1317 return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super); 1318 return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super, mnt);
1318} 1319}
1319 1320
1320static struct file_system_type ufs_fs_type = { 1321static struct file_system_type ufs_fs_type = {
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index a56cec3be5f0..9a8f48bae956 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -1023,11 +1023,12 @@ static int vfat_fill_super(struct super_block *sb, void *data, int silent)
1023 return 0; 1023 return 0;
1024} 1024}
1025 1025
1026static struct super_block *vfat_get_sb(struct file_system_type *fs_type, 1026static int vfat_get_sb(struct file_system_type *fs_type,
1027 int flags, const char *dev_name, 1027 int flags, const char *dev_name,
1028 void *data) 1028 void *data, struct vfsmount *mnt)
1029{ 1029{
1030 return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super); 1030 return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super,
1031 mnt);
1031} 1032}
1032 1033
1033static struct file_system_type vfat_fs_type = { 1034static struct file_system_type vfat_fs_type = {
diff --git a/fs/xattr.c b/fs/xattr.c
index e416190f5e9c..c32f15b5f60f 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -242,7 +242,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
242 if (!f) 242 if (!f)
243 return error; 243 return error;
244 dentry = f->f_dentry; 244 dentry = f->f_dentry;
245 audit_inode(NULL, dentry->d_inode, 0); 245 audit_inode(NULL, dentry->d_inode);
246 error = setxattr(dentry, name, value, size, flags); 246 error = setxattr(dentry, name, value, size, flags);
247 fput(f); 247 fput(f);
248 return error; 248 return error;
@@ -469,7 +469,7 @@ sys_fremovexattr(int fd, char __user *name)
469 if (!f) 469 if (!f)
470 return error; 470 return error;
471 dentry = f->f_dentry; 471 dentry = f->f_dentry;
472 audit_inode(NULL, dentry->d_inode, 0); 472 audit_inode(NULL, dentry->d_inode);
473 error = removexattr(dentry, name); 473 error = removexattr(dentry, name);
474 fput(f); 474 fput(f);
475 return error; 475 return error;
diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig
index bac27d66151d..26b364c9d62c 100644
--- a/fs/xfs/Kconfig
+++ b/fs/xfs/Kconfig
@@ -1,6 +1,5 @@
1config XFS_FS 1config XFS_FS
2 tristate "XFS filesystem support" 2 tristate "XFS filesystem support"
3 select EXPORTFS if NFSD!=n
4 help 3 help
5 XFS is a high performance journaling filesystem which originated 4 XFS is a high performance journaling filesystem which originated
6 on the SGI IRIX platform. It is completely multi-threaded, can 5 on the SGI IRIX platform. It is completely multi-threaded, can
@@ -18,11 +17,6 @@ config XFS_FS
18 system of your root partition is compiled as a module, you'll need 17 system of your root partition is compiled as a module, you'll need
19 to use an initial ramdisk (initrd) to boot. 18 to use an initial ramdisk (initrd) to boot.
20 19
21config XFS_EXPORT
22 bool
23 depends on XFS_FS && EXPORTFS
24 default y
25
26config XFS_QUOTA 20config XFS_QUOTA
27 bool "XFS Quota support" 21 bool "XFS Quota support"
28 depends on XFS_FS 22 depends on XFS_FS
@@ -65,18 +59,19 @@ config XFS_POSIX_ACL
65 If you don't know what Access Control Lists are, say N. 59 If you don't know what Access Control Lists are, say N.
66 60
67config XFS_RT 61config XFS_RT
68 bool "XFS Realtime support (EXPERIMENTAL)" 62 bool "XFS Realtime subvolume support"
69 depends on XFS_FS && EXPERIMENTAL 63 depends on XFS_FS
70 help 64 help
71 If you say Y here you will be able to mount and use XFS filesystems 65 If you say Y here you will be able to mount and use XFS filesystems
72 which contain a realtime subvolume. The realtime subvolume is a 66 which contain a realtime subvolume. The realtime subvolume is a
73 separate area of disk space where only file data is stored. The 67 separate area of disk space where only file data is stored. It was
74 realtime subvolume is designed to provide very deterministic 68 originally designed to provide deterministic data rates suitable
75 data rates suitable for media streaming applications. 69 for media streaming applications, but is also useful as a generic
76 70 mechanism for ensuring data and metadata/log I/Os are completely
77 See the xfs man page in section 5 for a bit more information. 71 separated. Regular file I/Os are isolated to a separate device
72 from all other requests, and this can be done quite transparently
73 to applications via the inherit-realtime directory inode flag.
78 74
79 This feature is unsupported at this time, is not yet fully 75 See the xfs man page in section 5 for additional information.
80 functional, and may cause serious problems.
81 76
82 If unsure, say N. 77 If unsure, say N.
diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6
index 5d73eaa1971f..9e7f85986d0d 100644
--- a/fs/xfs/Makefile-linux-2.6
+++ b/fs/xfs/Makefile-linux-2.6
@@ -59,7 +59,6 @@ xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o
59xfs-$(CONFIG_PROC_FS) += $(XFS_LINUX)/xfs_stats.o 59xfs-$(CONFIG_PROC_FS) += $(XFS_LINUX)/xfs_stats.o
60xfs-$(CONFIG_SYSCTL) += $(XFS_LINUX)/xfs_sysctl.o 60xfs-$(CONFIG_SYSCTL) += $(XFS_LINUX)/xfs_sysctl.o
61xfs-$(CONFIG_COMPAT) += $(XFS_LINUX)/xfs_ioctl32.o 61xfs-$(CONFIG_COMPAT) += $(XFS_LINUX)/xfs_ioctl32.o
62xfs-$(CONFIG_XFS_EXPORT) += $(XFS_LINUX)/xfs_export.o
63 62
64 63
65xfs-y += xfs_alloc.o \ 64xfs-y += xfs_alloc.o \
@@ -73,14 +72,12 @@ xfs-y += xfs_alloc.o \
73 xfs_btree.o \ 72 xfs_btree.o \
74 xfs_buf_item.o \ 73 xfs_buf_item.o \
75 xfs_da_btree.o \ 74 xfs_da_btree.o \
76 xfs_dir.o \
77 xfs_dir2.o \ 75 xfs_dir2.o \
78 xfs_dir2_block.o \ 76 xfs_dir2_block.o \
79 xfs_dir2_data.o \ 77 xfs_dir2_data.o \
80 xfs_dir2_leaf.o \ 78 xfs_dir2_leaf.o \
81 xfs_dir2_node.o \ 79 xfs_dir2_node.o \
82 xfs_dir2_sf.o \ 80 xfs_dir2_sf.o \
83 xfs_dir_leaf.o \
84 xfs_error.o \ 81 xfs_error.o \
85 xfs_extfree_item.o \ 82 xfs_extfree_item.o \
86 xfs_fsops.o \ 83 xfs_fsops.o \
@@ -117,6 +114,7 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \
117 kmem.o \ 114 kmem.o \
118 xfs_aops.o \ 115 xfs_aops.o \
119 xfs_buf.o \ 116 xfs_buf.o \
117 xfs_export.o \
120 xfs_file.o \ 118 xfs_file.o \
121 xfs_fs_subr.o \ 119 xfs_fs_subr.o \
122 xfs_globals.o \ 120 xfs_globals.o \
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h
index 2cfd33d4d8aa..939bd84bc7ee 100644
--- a/fs/xfs/linux-2.6/kmem.h
+++ b/fs/xfs/linux-2.6/kmem.h
@@ -23,42 +23,6 @@
23#include <linux/mm.h> 23#include <linux/mm.h>
24 24
25/* 25/*
26 * Process flags handling
27 */
28
29#define PFLAGS_TEST_NOIO() (current->flags & PF_NOIO)
30#define PFLAGS_TEST_FSTRANS() (current->flags & PF_FSTRANS)
31
32#define PFLAGS_SET_NOIO() do { \
33 current->flags |= PF_NOIO; \
34} while (0)
35
36#define PFLAGS_CLEAR_NOIO() do { \
37 current->flags &= ~PF_NOIO; \
38} while (0)
39
40/* these could be nested, so we save state */
41#define PFLAGS_SET_FSTRANS(STATEP) do { \
42 *(STATEP) = current->flags; \
43 current->flags |= PF_FSTRANS; \
44} while (0)
45
46#define PFLAGS_CLEAR_FSTRANS(STATEP) do { \
47 *(STATEP) = current->flags; \
48 current->flags &= ~PF_FSTRANS; \
49} while (0)
50
51/* Restore the PF_FSTRANS state to what was saved in STATEP */
52#define PFLAGS_RESTORE_FSTRANS(STATEP) do { \
53 current->flags = ((current->flags & ~PF_FSTRANS) | \
54 (*(STATEP) & PF_FSTRANS)); \
55} while (0)
56
57#define PFLAGS_DUP(OSTATEP, NSTATEP) do { \
58 *(NSTATEP) = *(OSTATEP); \
59} while (0)
60
61/*
62 * General memory allocation interfaces 26 * General memory allocation interfaces
63 */ 27 */
64 28
@@ -83,7 +47,7 @@ kmem_flags_convert(unsigned int __nocast flags)
83 lflags = GFP_ATOMIC | __GFP_NOWARN; 47 lflags = GFP_ATOMIC | __GFP_NOWARN;
84 } else { 48 } else {
85 lflags = GFP_KERNEL | __GFP_NOWARN; 49 lflags = GFP_KERNEL | __GFP_NOWARN;
86 if (PFLAGS_TEST_FSTRANS() || (flags & KM_NOFS)) 50 if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS))
87 lflags &= ~__GFP_FS; 51 lflags &= ~__GFP_FS;
88 } 52 }
89 return lflags; 53 return lflags;
diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/linux-2.6/mrlock.h
index 1b262b790d9c..32e1ce0f04c9 100644
--- a/fs/xfs/linux-2.6/mrlock.h
+++ b/fs/xfs/linux-2.6/mrlock.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -28,7 +28,7 @@ typedef struct {
28} mrlock_t; 28} mrlock_t;
29 29
30#define mrinit(mrp, name) \ 30#define mrinit(mrp, name) \
31 ( (mrp)->mr_writer = 0, init_rwsem(&(mrp)->mr_lock) ) 31 do { (mrp)->mr_writer = 0; init_rwsem(&(mrp)->mr_lock); } while (0)
32#define mrlock_init(mrp, t,n,s) mrinit(mrp, n) 32#define mrlock_init(mrp, t,n,s) mrinit(mrp, n)
33#define mrfree(mrp) do { } while (0) 33#define mrfree(mrp) do { } while (0)
34#define mraccess(mrp) mraccessf(mrp, 0) 34#define mraccess(mrp) mraccessf(mrp, 0)
diff --git a/fs/xfs/linux-2.6/sema.h b/fs/xfs/linux-2.6/sema.h
index 194a84490bd1..b25090094cca 100644
--- a/fs/xfs/linux-2.6/sema.h
+++ b/fs/xfs/linux-2.6/sema.h
@@ -34,20 +34,21 @@ typedef struct semaphore sema_t;
34#define initnsema(sp, val, name) sema_init(sp, val) 34#define initnsema(sp, val, name) sema_init(sp, val)
35#define psema(sp, b) down(sp) 35#define psema(sp, b) down(sp)
36#define vsema(sp) up(sp) 36#define vsema(sp) up(sp)
37#define valusema(sp) (atomic_read(&(sp)->count)) 37#define freesema(sema) do { } while (0)
38#define freesema(sema) 38
39static inline int issemalocked(sema_t *sp)
40{
41 return down_trylock(sp) || (up(sp), 0);
42}
39 43
40/* 44/*
41 * Map cpsema (try to get the sema) to down_trylock. We need to switch 45 * Map cpsema (try to get the sema) to down_trylock. We need to switch
42 * the return values since cpsema returns 1 (acquired) 0 (failed) and 46 * the return values since cpsema returns 1 (acquired) 0 (failed) and
43 * down_trylock returns the reverse 0 (acquired) 1 (failed). 47 * down_trylock returns the reverse 0 (acquired) 1 (failed).
44 */ 48 */
45 49static inline int cpsema(sema_t *sp)
46#define cpsema(sp) (down_trylock(sp) ? 0 : 1) 50{
47 51 return down_trylock(sp) ? 0 : 1;
48/* 52}
49 * Didn't do cvsema(sp). Not sure how to map this to up/down/...
50 * It does a vsema if the values is < 0 other wise nothing.
51 */
52 53
53#endif /* __XFS_SUPPORT_SEMA_H__ */ 54#endif /* __XFS_SUPPORT_SEMA_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 4d191ef39b67..3e807b828e22 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -21,7 +21,6 @@
21#include "xfs_inum.h" 21#include "xfs_inum.h"
22#include "xfs_sb.h" 22#include "xfs_sb.h"
23#include "xfs_ag.h" 23#include "xfs_ag.h"
24#include "xfs_dir.h"
25#include "xfs_dir2.h" 24#include "xfs_dir2.h"
26#include "xfs_trans.h" 25#include "xfs_trans.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
@@ -29,7 +28,6 @@
29#include "xfs_bmap_btree.h" 28#include "xfs_bmap_btree.h"
30#include "xfs_alloc_btree.h" 29#include "xfs_alloc_btree.h"
31#include "xfs_ialloc_btree.h" 30#include "xfs_ialloc_btree.h"
32#include "xfs_dir_sf.h"
33#include "xfs_dir2_sf.h" 31#include "xfs_dir2_sf.h"
34#include "xfs_attr_sf.h" 32#include "xfs_attr_sf.h"
35#include "xfs_dinode.h" 33#include "xfs_dinode.h"
@@ -76,7 +74,7 @@ xfs_page_trace(
76 int mask) 74 int mask)
77{ 75{
78 xfs_inode_t *ip; 76 xfs_inode_t *ip;
79 vnode_t *vp = vn_from_inode(inode); 77 bhv_vnode_t *vp = vn_from_inode(inode);
80 loff_t isize = i_size_read(inode); 78 loff_t isize = i_size_read(inode);
81 loff_t offset = page_offset(page); 79 loff_t offset = page_offset(page);
82 int delalloc = -1, unmapped = -1, unwritten = -1; 80 int delalloc = -1, unmapped = -1, unwritten = -1;
@@ -136,9 +134,10 @@ xfs_destroy_ioend(
136 134
137 for (bh = ioend->io_buffer_head; bh; bh = next) { 135 for (bh = ioend->io_buffer_head; bh; bh = next) {
138 next = bh->b_private; 136 next = bh->b_private;
139 bh->b_end_io(bh, ioend->io_uptodate); 137 bh->b_end_io(bh, !ioend->io_error);
140 } 138 }
141 139 if (unlikely(ioend->io_error))
140 vn_ioerror(ioend->io_vnode, ioend->io_error, __FILE__,__LINE__);
142 vn_iowake(ioend->io_vnode); 141 vn_iowake(ioend->io_vnode);
143 mempool_free(ioend, xfs_ioend_pool); 142 mempool_free(ioend, xfs_ioend_pool);
144} 143}
@@ -180,13 +179,12 @@ xfs_end_bio_unwritten(
180 void *data) 179 void *data)
181{ 180{
182 xfs_ioend_t *ioend = data; 181 xfs_ioend_t *ioend = data;
183 vnode_t *vp = ioend->io_vnode; 182 bhv_vnode_t *vp = ioend->io_vnode;
184 xfs_off_t offset = ioend->io_offset; 183 xfs_off_t offset = ioend->io_offset;
185 size_t size = ioend->io_size; 184 size_t size = ioend->io_size;
186 int error;
187 185
188 if (ioend->io_uptodate) 186 if (likely(!ioend->io_error))
189 VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error); 187 bhv_vop_bmap(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL);
190 xfs_destroy_ioend(ioend); 188 xfs_destroy_ioend(ioend);
191} 189}
192 190
@@ -211,7 +209,7 @@ xfs_alloc_ioend(
211 * all the I/O from calling the completion routine too early. 209 * all the I/O from calling the completion routine too early.
212 */ 210 */
213 atomic_set(&ioend->io_remaining, 1); 211 atomic_set(&ioend->io_remaining, 1);
214 ioend->io_uptodate = 1; /* cleared if any I/O fails */ 212 ioend->io_error = 0;
215 ioend->io_list = NULL; 213 ioend->io_list = NULL;
216 ioend->io_type = type; 214 ioend->io_type = type;
217 ioend->io_vnode = vn_from_inode(inode); 215 ioend->io_vnode = vn_from_inode(inode);
@@ -239,10 +237,10 @@ xfs_map_blocks(
239 xfs_iomap_t *mapp, 237 xfs_iomap_t *mapp,
240 int flags) 238 int flags)
241{ 239{
242 vnode_t *vp = vn_from_inode(inode); 240 bhv_vnode_t *vp = vn_from_inode(inode);
243 int error, nmaps = 1; 241 int error, nmaps = 1;
244 242
245 VOP_BMAP(vp, offset, count, flags, mapp, &nmaps, error); 243 error = bhv_vop_bmap(vp, offset, count, flags, mapp, &nmaps);
246 if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE))) 244 if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE)))
247 VMODIFY(vp); 245 VMODIFY(vp);
248 return -error; 246 return -error;
@@ -271,16 +269,14 @@ xfs_end_bio(
271 if (bio->bi_size) 269 if (bio->bi_size)
272 return 1; 270 return 1;
273 271
274 ASSERT(ioend);
275 ASSERT(atomic_read(&bio->bi_cnt) >= 1); 272 ASSERT(atomic_read(&bio->bi_cnt) >= 1);
273 ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error;
276 274
277 /* Toss bio and pass work off to an xfsdatad thread */ 275 /* Toss bio and pass work off to an xfsdatad thread */
278 if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
279 ioend->io_uptodate = 0;
280 bio->bi_private = NULL; 276 bio->bi_private = NULL;
281 bio->bi_end_io = NULL; 277 bio->bi_end_io = NULL;
282
283 bio_put(bio); 278 bio_put(bio);
279
284 xfs_finish_ioend(ioend); 280 xfs_finish_ioend(ioend);
285 return 0; 281 return 0;
286} 282}
@@ -1127,7 +1123,7 @@ xfs_vm_writepage(
1127 * then mark the page dirty again and leave the page 1123 * then mark the page dirty again and leave the page
1128 * as is. 1124 * as is.
1129 */ 1125 */
1130 if (PFLAGS_TEST_FSTRANS() && need_trans) 1126 if (current_test_flags(PF_FSTRANS) && need_trans)
1131 goto out_fail; 1127 goto out_fail;
1132 1128
1133 /* 1129 /*
@@ -1158,6 +1154,18 @@ out_unlock:
1158 return error; 1154 return error;
1159} 1155}
1160 1156
1157STATIC int
1158xfs_vm_writepages(
1159 struct address_space *mapping,
1160 struct writeback_control *wbc)
1161{
1162 struct bhv_vnode *vp = vn_from_inode(mapping->host);
1163
1164 if (VN_TRUNC(vp))
1165 VUNTRUNCATE(vp);
1166 return generic_writepages(mapping, wbc);
1167}
1168
1161/* 1169/*
1162 * Called to move a page into cleanable state - and from there 1170 * Called to move a page into cleanable state - and from there
1163 * to be released. Possibly the page is already clean. We always 1171 * to be released. Possibly the page is already clean. We always
@@ -1204,7 +1212,7 @@ xfs_vm_releasepage(
1204 /* If we are already inside a transaction or the thread cannot 1212 /* If we are already inside a transaction or the thread cannot
1205 * do I/O, we cannot release this page. 1213 * do I/O, we cannot release this page.
1206 */ 1214 */
1207 if (PFLAGS_TEST_FSTRANS()) 1215 if (current_test_flags(PF_FSTRANS))
1208 return 0; 1216 return 0;
1209 1217
1210 /* 1218 /*
@@ -1231,7 +1239,7 @@ __xfs_get_blocks(
1231 int direct, 1239 int direct,
1232 bmapi_flags_t flags) 1240 bmapi_flags_t flags)
1233{ 1241{
1234 vnode_t *vp = vn_from_inode(inode); 1242 bhv_vnode_t *vp = vn_from_inode(inode);
1235 xfs_iomap_t iomap; 1243 xfs_iomap_t iomap;
1236 xfs_off_t offset; 1244 xfs_off_t offset;
1237 ssize_t size; 1245 ssize_t size;
@@ -1241,8 +1249,8 @@ __xfs_get_blocks(
1241 offset = (xfs_off_t)iblock << inode->i_blkbits; 1249 offset = (xfs_off_t)iblock << inode->i_blkbits;
1242 ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); 1250 ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
1243 size = bh_result->b_size; 1251 size = bh_result->b_size;
1244 VOP_BMAP(vp, offset, size, 1252 error = bhv_vop_bmap(vp, offset, size,
1245 create ? flags : BMAPI_READ, &iomap, &niomap, error); 1253 create ? flags : BMAPI_READ, &iomap, &niomap);
1246 if (error) 1254 if (error)
1247 return -error; 1255 return -error;
1248 if (niomap == 0) 1256 if (niomap == 0)
@@ -1370,13 +1378,13 @@ xfs_vm_direct_IO(
1370{ 1378{
1371 struct file *file = iocb->ki_filp; 1379 struct file *file = iocb->ki_filp;
1372 struct inode *inode = file->f_mapping->host; 1380 struct inode *inode = file->f_mapping->host;
1373 vnode_t *vp = vn_from_inode(inode); 1381 bhv_vnode_t *vp = vn_from_inode(inode);
1374 xfs_iomap_t iomap; 1382 xfs_iomap_t iomap;
1375 int maps = 1; 1383 int maps = 1;
1376 int error; 1384 int error;
1377 ssize_t ret; 1385 ssize_t ret;
1378 1386
1379 VOP_BMAP(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps, error); 1387 error = bhv_vop_bmap(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps);
1380 if (error) 1388 if (error)
1381 return -error; 1389 return -error;
1382 1390
@@ -1409,14 +1417,12 @@ xfs_vm_bmap(
1409 sector_t block) 1417 sector_t block)
1410{ 1418{
1411 struct inode *inode = (struct inode *)mapping->host; 1419 struct inode *inode = (struct inode *)mapping->host;
1412 vnode_t *vp = vn_from_inode(inode); 1420 bhv_vnode_t *vp = vn_from_inode(inode);
1413 int error;
1414 1421
1415 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); 1422 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
1416 1423 bhv_vop_rwlock(vp, VRWLOCK_READ);
1417 VOP_RWLOCK(vp, VRWLOCK_READ); 1424 bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF);
1418 VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error); 1425 bhv_vop_rwunlock(vp, VRWLOCK_READ);
1419 VOP_RWUNLOCK(vp, VRWLOCK_READ);
1420 return generic_block_bmap(mapping, block, xfs_get_blocks); 1426 return generic_block_bmap(mapping, block, xfs_get_blocks);
1421} 1427}
1422 1428
@@ -1452,6 +1458,7 @@ struct address_space_operations xfs_address_space_operations = {
1452 .readpage = xfs_vm_readpage, 1458 .readpage = xfs_vm_readpage,
1453 .readpages = xfs_vm_readpages, 1459 .readpages = xfs_vm_readpages,
1454 .writepage = xfs_vm_writepage, 1460 .writepage = xfs_vm_writepage,
1461 .writepages = xfs_vm_writepages,
1455 .sync_page = block_sync_page, 1462 .sync_page = block_sync_page,
1456 .releasepage = xfs_vm_releasepage, 1463 .releasepage = xfs_vm_releasepage,
1457 .invalidatepage = xfs_vm_invalidatepage, 1464 .invalidatepage = xfs_vm_invalidatepage,
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h
index 60716543c68b..706d8c781b8a 100644
--- a/fs/xfs/linux-2.6/xfs_aops.h
+++ b/fs/xfs/linux-2.6/xfs_aops.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2005 Silicon Graphics, Inc. 2 * Copyright (c) 2005-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -30,9 +30,9 @@ typedef void (*xfs_ioend_func_t)(void *);
30typedef struct xfs_ioend { 30typedef struct xfs_ioend {
31 struct xfs_ioend *io_list; /* next ioend in chain */ 31 struct xfs_ioend *io_list; /* next ioend in chain */
32 unsigned int io_type; /* delalloc / unwritten */ 32 unsigned int io_type; /* delalloc / unwritten */
33 unsigned int io_uptodate; /* I/O status register */ 33 int io_error; /* I/O error code */
34 atomic_t io_remaining; /* hold count */ 34 atomic_t io_remaining; /* hold count */
35 struct vnode *io_vnode; /* file being written to */ 35 struct bhv_vnode *io_vnode; /* file being written to */
36 struct buffer_head *io_buffer_head;/* buffer linked list head */ 36 struct buffer_head *io_buffer_head;/* buffer linked list head */
37 struct buffer_head *io_buffer_tail;/* buffer linked list tail */ 37 struct buffer_head *io_buffer_tail;/* buffer linked list tail */
38 size_t io_size; /* size of the extent */ 38 size_t io_size; /* size of the extent */
@@ -43,4 +43,4 @@ typedef struct xfs_ioend {
43extern struct address_space_operations xfs_address_space_operations; 43extern struct address_space_operations xfs_address_space_operations;
44extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int); 44extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int);
45 45
46#endif /* __XFS_IOPS_H__ */ 46#endif /* __XFS_AOPS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index b768ea910bbe..5fb75d9151f2 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -21,7 +21,6 @@
21#include "xfs_log.h" 21#include "xfs_log.h"
22#include "xfs_trans.h" 22#include "xfs_trans.h"
23#include "xfs_sb.h" 23#include "xfs_sb.h"
24#include "xfs_dir.h"
25#include "xfs_mount.h" 24#include "xfs_mount.h"
26#include "xfs_export.h" 25#include "xfs_export.h"
27 26
@@ -97,7 +96,7 @@ xfs_fs_encode_fh(
97 int len; 96 int len;
98 int is64 = 0; 97 int is64 = 0;
99#if XFS_BIG_INUMS 98#if XFS_BIG_INUMS
100 vfs_t *vfs = vfs_from_sb(inode->i_sb); 99 bhv_vfs_t *vfs = vfs_from_sb(inode->i_sb);
101 100
102 if (!(vfs->vfs_flag & VFS_32BITINODES)) { 101 if (!(vfs->vfs_flag & VFS_32BITINODES)) {
103 /* filesystem may contain 64bit inode numbers */ 102 /* filesystem may contain 64bit inode numbers */
@@ -136,13 +135,13 @@ xfs_fs_get_dentry(
136 struct super_block *sb, 135 struct super_block *sb,
137 void *data) 136 void *data)
138{ 137{
139 vnode_t *vp; 138 bhv_vnode_t *vp;
140 struct inode *inode; 139 struct inode *inode;
141 struct dentry *result; 140 struct dentry *result;
142 vfs_t *vfsp = vfs_from_sb(sb); 141 bhv_vfs_t *vfsp = vfs_from_sb(sb);
143 int error; 142 int error;
144 143
145 VFS_VGET(vfsp, &vp, (fid_t *)data, error); 144 error = bhv_vfs_vget(vfsp, &vp, (fid_t *)data);
146 if (error || vp == NULL) 145 if (error || vp == NULL)
147 return ERR_PTR(-ESTALE) ; 146 return ERR_PTR(-ESTALE) ;
148 147
@@ -160,12 +159,12 @@ xfs_fs_get_parent(
160 struct dentry *child) 159 struct dentry *child)
161{ 160{
162 int error; 161 int error;
163 vnode_t *vp, *cvp; 162 bhv_vnode_t *vp, *cvp;
164 struct dentry *parent; 163 struct dentry *parent;
165 164
166 cvp = NULL; 165 cvp = NULL;
167 vp = vn_from_inode(child->d_inode); 166 vp = vn_from_inode(child->d_inode);
168 VOP_LOOKUP(vp, &dotdot, &cvp, 0, NULL, NULL, error); 167 error = bhv_vop_lookup(vp, &dotdot, &cvp, 0, NULL, NULL);
169 if (unlikely(error)) 168 if (unlikely(error))
170 return ERR_PTR(-error); 169 return ERR_PTR(-error);
171 170
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index c847416f6d10..70662371bb11 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -21,7 +21,6 @@
21#include "xfs_inum.h" 21#include "xfs_inum.h"
22#include "xfs_sb.h" 22#include "xfs_sb.h"
23#include "xfs_ag.h" 23#include "xfs_ag.h"
24#include "xfs_dir.h"
25#include "xfs_dir2.h" 24#include "xfs_dir2.h"
26#include "xfs_trans.h" 25#include "xfs_trans.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_alloc.h" 31#include "xfs_alloc.h"
33#include "xfs_btree.h" 32#include "xfs_btree.h"
34#include "xfs_attr_sf.h" 33#include "xfs_attr_sf.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
38#include "xfs_inode.h" 36#include "xfs_inode.h"
@@ -58,15 +56,12 @@ __xfs_file_read(
58{ 56{
59 struct iovec iov = {buf, count}; 57 struct iovec iov = {buf, count};
60 struct file *file = iocb->ki_filp; 58 struct file *file = iocb->ki_filp;
61 vnode_t *vp = vn_from_inode(file->f_dentry->d_inode); 59 bhv_vnode_t *vp = vn_from_inode(file->f_dentry->d_inode);
62 ssize_t rval;
63 60
64 BUG_ON(iocb->ki_pos != pos); 61 BUG_ON(iocb->ki_pos != pos);
65
66 if (unlikely(file->f_flags & O_DIRECT)) 62 if (unlikely(file->f_flags & O_DIRECT))
67 ioflags |= IO_ISDIRECT; 63 ioflags |= IO_ISDIRECT;
68 VOP_READ(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval); 64 return bhv_vop_read(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL);
69 return rval;
70} 65}
71 66
72STATIC ssize_t 67STATIC ssize_t
@@ -100,15 +95,12 @@ __xfs_file_write(
100 struct iovec iov = {(void __user *)buf, count}; 95 struct iovec iov = {(void __user *)buf, count};
101 struct file *file = iocb->ki_filp; 96 struct file *file = iocb->ki_filp;
102 struct inode *inode = file->f_mapping->host; 97 struct inode *inode = file->f_mapping->host;
103 vnode_t *vp = vn_from_inode(inode); 98 bhv_vnode_t *vp = vn_from_inode(inode);
104 ssize_t rval;
105 99
106 BUG_ON(iocb->ki_pos != pos); 100 BUG_ON(iocb->ki_pos != pos);
107 if (unlikely(file->f_flags & O_DIRECT)) 101 if (unlikely(file->f_flags & O_DIRECT))
108 ioflags |= IO_ISDIRECT; 102 ioflags |= IO_ISDIRECT;
109 103 return bhv_vop_write(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL);
110 VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
111 return rval;
112} 104}
113 105
114STATIC ssize_t 106STATIC ssize_t
@@ -140,7 +132,7 @@ __xfs_file_readv(
140 loff_t *ppos) 132 loff_t *ppos)
141{ 133{
142 struct inode *inode = file->f_mapping->host; 134 struct inode *inode = file->f_mapping->host;
143 vnode_t *vp = vn_from_inode(inode); 135 bhv_vnode_t *vp = vn_from_inode(inode);
144 struct kiocb kiocb; 136 struct kiocb kiocb;
145 ssize_t rval; 137 ssize_t rval;
146 138
@@ -149,7 +141,8 @@ __xfs_file_readv(
149 141
150 if (unlikely(file->f_flags & O_DIRECT)) 142 if (unlikely(file->f_flags & O_DIRECT))
151 ioflags |= IO_ISDIRECT; 143 ioflags |= IO_ISDIRECT;
152 VOP_READ(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval); 144 rval = bhv_vop_read(vp, &kiocb, iov, nr_segs,
145 &kiocb.ki_pos, ioflags, NULL);
153 146
154 *ppos = kiocb.ki_pos; 147 *ppos = kiocb.ki_pos;
155 return rval; 148 return rval;
@@ -184,7 +177,7 @@ __xfs_file_writev(
184 loff_t *ppos) 177 loff_t *ppos)
185{ 178{
186 struct inode *inode = file->f_mapping->host; 179 struct inode *inode = file->f_mapping->host;
187 vnode_t *vp = vn_from_inode(inode); 180 bhv_vnode_t *vp = vn_from_inode(inode);
188 struct kiocb kiocb; 181 struct kiocb kiocb;
189 ssize_t rval; 182 ssize_t rval;
190 183
@@ -193,7 +186,8 @@ __xfs_file_writev(
193 if (unlikely(file->f_flags & O_DIRECT)) 186 if (unlikely(file->f_flags & O_DIRECT))
194 ioflags |= IO_ISDIRECT; 187 ioflags |= IO_ISDIRECT;
195 188
196 VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval); 189 rval = bhv_vop_write(vp, &kiocb, iov, nr_segs,
190 &kiocb.ki_pos, ioflags, NULL);
197 191
198 *ppos = kiocb.ki_pos; 192 *ppos = kiocb.ki_pos;
199 return rval; 193 return rval;
@@ -227,11 +221,8 @@ xfs_file_sendfile(
227 read_actor_t actor, 221 read_actor_t actor,
228 void *target) 222 void *target)
229{ 223{
230 vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); 224 return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode),
231 ssize_t rval; 225 filp, pos, 0, count, actor, target, NULL);
232
233 VOP_SENDFILE(vp, filp, pos, 0, count, actor, target, NULL, rval);
234 return rval;
235} 226}
236 227
237STATIC ssize_t 228STATIC ssize_t
@@ -242,11 +233,8 @@ xfs_file_sendfile_invis(
242 read_actor_t actor, 233 read_actor_t actor,
243 void *target) 234 void *target)
244{ 235{
245 vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); 236 return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode),
246 ssize_t rval; 237 filp, pos, IO_INVIS, count, actor, target, NULL);
247
248 VOP_SENDFILE(vp, filp, pos, IO_INVIS, count, actor, target, NULL, rval);
249 return rval;
250} 238}
251 239
252STATIC ssize_t 240STATIC ssize_t
@@ -257,11 +245,8 @@ xfs_file_splice_read(
257 size_t len, 245 size_t len,
258 unsigned int flags) 246 unsigned int flags)
259{ 247{
260 vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode); 248 return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode),
261 ssize_t rval; 249 infilp, ppos, pipe, len, flags, 0, NULL);
262
263 VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, 0, NULL, rval);
264 return rval;
265} 250}
266 251
267STATIC ssize_t 252STATIC ssize_t
@@ -272,11 +257,9 @@ xfs_file_splice_read_invis(
272 size_t len, 257 size_t len,
273 unsigned int flags) 258 unsigned int flags)
274{ 259{
275 vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode); 260 return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode),
276 ssize_t rval; 261 infilp, ppos, pipe, len, flags, IO_INVIS,
277 262 NULL);
278 VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, IO_INVIS, NULL, rval);
279 return rval;
280} 263}
281 264
282STATIC ssize_t 265STATIC ssize_t
@@ -287,11 +270,8 @@ xfs_file_splice_write(
287 size_t len, 270 size_t len,
288 unsigned int flags) 271 unsigned int flags)
289{ 272{
290 vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode); 273 return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode),
291 ssize_t rval; 274 pipe, outfilp, ppos, len, flags, 0, NULL);
292
293 VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, 0, NULL, rval);
294 return rval;
295} 275}
296 276
297STATIC ssize_t 277STATIC ssize_t
@@ -302,11 +282,9 @@ xfs_file_splice_write_invis(
302 size_t len, 282 size_t len,
303 unsigned int flags) 283 unsigned int flags)
304{ 284{
305 vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode); 285 return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode),
306 ssize_t rval; 286 pipe, outfilp, ppos, len, flags, IO_INVIS,
307 287 NULL);
308 VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, IO_INVIS, NULL, rval);
309 return rval;
310} 288}
311 289
312STATIC int 290STATIC int
@@ -314,13 +292,17 @@ xfs_file_open(
314 struct inode *inode, 292 struct inode *inode,
315 struct file *filp) 293 struct file *filp)
316{ 294{
317 vnode_t *vp = vn_from_inode(inode);
318 int error;
319
320 if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) 295 if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
321 return -EFBIG; 296 return -EFBIG;
322 VOP_OPEN(vp, NULL, error); 297 return -bhv_vop_open(vn_from_inode(inode), NULL);
323 return -error; 298}
299
300STATIC int
301xfs_file_close(
302 struct file *filp)
303{
304 return -bhv_vop_close(vn_from_inode(filp->f_dentry->d_inode), 0,
305 file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL);
324} 306}
325 307
326STATIC int 308STATIC int
@@ -328,12 +310,11 @@ xfs_file_release(
328 struct inode *inode, 310 struct inode *inode,
329 struct file *filp) 311 struct file *filp)
330{ 312{
331 vnode_t *vp = vn_from_inode(inode); 313 bhv_vnode_t *vp = vn_from_inode(inode);
332 int error = 0;
333 314
334 if (vp) 315 if (vp)
335 VOP_RELEASE(vp, error); 316 return -bhv_vop_release(vp);
336 return -error; 317 return 0;
337} 318}
338 319
339STATIC int 320STATIC int
@@ -342,15 +323,14 @@ xfs_file_fsync(
342 struct dentry *dentry, 323 struct dentry *dentry,
343 int datasync) 324 int datasync)
344{ 325{
345 struct inode *inode = dentry->d_inode; 326 bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
346 vnode_t *vp = vn_from_inode(inode);
347 int error;
348 int flags = FSYNC_WAIT; 327 int flags = FSYNC_WAIT;
349 328
350 if (datasync) 329 if (datasync)
351 flags |= FSYNC_DATA; 330 flags |= FSYNC_DATA;
352 VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error); 331 if (VN_TRUNC(vp))
353 return -error; 332 VUNTRUNCATE(vp);
333 return -bhv_vop_fsync(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1);
354} 334}
355 335
356#ifdef CONFIG_XFS_DMAPI 336#ifdef CONFIG_XFS_DMAPI
@@ -361,16 +341,11 @@ xfs_vm_nopage(
361 int *type) 341 int *type)
362{ 342{
363 struct inode *inode = area->vm_file->f_dentry->d_inode; 343 struct inode *inode = area->vm_file->f_dentry->d_inode;
364 vnode_t *vp = vn_from_inode(inode); 344 bhv_vnode_t *vp = vn_from_inode(inode);
365 xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
366 int error;
367 345
368 ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI); 346 ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
369 347 if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), area, 0))
370 error = XFS_SEND_MMAP(mp, area, 0);
371 if (error)
372 return NULL; 348 return NULL;
373
374 return filemap_nopage(area, address, type); 349 return filemap_nopage(area, address, type);
375} 350}
376#endif /* CONFIG_XFS_DMAPI */ 351#endif /* CONFIG_XFS_DMAPI */
@@ -382,7 +357,7 @@ xfs_file_readdir(
382 filldir_t filldir) 357 filldir_t filldir)
383{ 358{
384 int error = 0; 359 int error = 0;
385 vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); 360 bhv_vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode);
386 uio_t uio; 361 uio_t uio;
387 iovec_t iov; 362 iovec_t iov;
388 int eof = 0; 363 int eof = 0;
@@ -417,7 +392,7 @@ xfs_file_readdir(
417 392
418 start_offset = uio.uio_offset; 393 start_offset = uio.uio_offset;
419 394
420 VOP_READDIR(vp, &uio, NULL, &eof, error); 395 error = bhv_vop_readdir(vp, &uio, NULL, &eof);
421 if ((uio.uio_offset == start_offset) || error) { 396 if ((uio.uio_offset == start_offset) || error) {
422 size = 0; 397 size = 0;
423 break; 398 break;
@@ -456,38 +431,28 @@ xfs_file_mmap(
456 struct file *filp, 431 struct file *filp,
457 struct vm_area_struct *vma) 432 struct vm_area_struct *vma)
458{ 433{
459 struct inode *ip = filp->f_dentry->d_inode;
460 vnode_t *vp = vn_from_inode(ip);
461 vattr_t vattr;
462 int error;
463
464 vma->vm_ops = &xfs_file_vm_ops; 434 vma->vm_ops = &xfs_file_vm_ops;
465 435
466#ifdef CONFIG_XFS_DMAPI 436#ifdef CONFIG_XFS_DMAPI
467 if (vp->v_vfsp->vfs_flag & VFS_DMI) { 437 if (vn_from_inode(filp->f_dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
468 vma->vm_ops = &xfs_dmapi_file_vm_ops; 438 vma->vm_ops = &xfs_dmapi_file_vm_ops;
469 }
470#endif /* CONFIG_XFS_DMAPI */ 439#endif /* CONFIG_XFS_DMAPI */
471 440
472 vattr.va_mask = XFS_AT_UPDATIME; 441 file_accessed(filp);
473 VOP_SETATTR(vp, &vattr, XFS_AT_UPDATIME, NULL, error);
474 if (likely(!error))
475 __vn_revalidate(vp, &vattr); /* update flags */
476 return 0; 442 return 0;
477} 443}
478 444
479
480STATIC long 445STATIC long
481xfs_file_ioctl( 446xfs_file_ioctl(
482 struct file *filp, 447 struct file *filp,
483 unsigned int cmd, 448 unsigned int cmd,
484 unsigned long arg) 449 unsigned long p)
485{ 450{
486 int error; 451 int error;
487 struct inode *inode = filp->f_dentry->d_inode; 452 struct inode *inode = filp->f_dentry->d_inode;
488 vnode_t *vp = vn_from_inode(inode); 453 bhv_vnode_t *vp = vn_from_inode(inode);
489 454
490 VOP_IOCTL(vp, inode, filp, 0, cmd, (void __user *)arg, error); 455 error = bhv_vop_ioctl(vp, inode, filp, 0, cmd, (void __user *)p);
491 VMODIFY(vp); 456 VMODIFY(vp);
492 457
493 /* NOTE: some of the ioctl's return positive #'s as a 458 /* NOTE: some of the ioctl's return positive #'s as a
@@ -503,13 +468,13 @@ STATIC long
503xfs_file_ioctl_invis( 468xfs_file_ioctl_invis(
504 struct file *filp, 469 struct file *filp,
505 unsigned int cmd, 470 unsigned int cmd,
506 unsigned long arg) 471 unsigned long p)
507{ 472{
508 struct inode *inode = filp->f_dentry->d_inode;
509 vnode_t *vp = vn_from_inode(inode);
510 int error; 473 int error;
474 struct inode *inode = filp->f_dentry->d_inode;
475 bhv_vnode_t *vp = vn_from_inode(inode);
511 476
512 VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error); 477 error = bhv_vop_ioctl(vp, inode, filp, IO_INVIS, cmd, (void __user *)p);
513 VMODIFY(vp); 478 VMODIFY(vp);
514 479
515 /* NOTE: some of the ioctl's return positive #'s as a 480 /* NOTE: some of the ioctl's return positive #'s as a
@@ -528,7 +493,7 @@ xfs_vm_mprotect(
528 struct vm_area_struct *vma, 493 struct vm_area_struct *vma,
529 unsigned int newflags) 494 unsigned int newflags)
530{ 495{
531 vnode_t *vp = vn_from_inode(vma->vm_file->f_dentry->d_inode); 496 bhv_vnode_t *vp = vn_from_inode(vma->vm_file->f_dentry->d_inode);
532 int error = 0; 497 int error = 0;
533 498
534 if (vp->v_vfsp->vfs_flag & VFS_DMI) { 499 if (vp->v_vfsp->vfs_flag & VFS_DMI) {
@@ -554,24 +519,19 @@ STATIC int
554xfs_file_open_exec( 519xfs_file_open_exec(
555 struct inode *inode) 520 struct inode *inode)
556{ 521{
557 vnode_t *vp = vn_from_inode(inode); 522 bhv_vnode_t *vp = vn_from_inode(inode);
558 xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
559 int error = 0;
560 xfs_inode_t *ip;
561 523
562 if (vp->v_vfsp->vfs_flag & VFS_DMI) { 524 if (unlikely(vp->v_vfsp->vfs_flag & VFS_DMI)) {
563 ip = xfs_vtoi(vp); 525 xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
564 if (!ip) { 526 xfs_inode_t *ip = xfs_vtoi(vp);
565 error = -EINVAL; 527
566 goto open_exec_out; 528 if (!ip)
567 } 529 return -EINVAL;
568 if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)) { 530 if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ))
569 error = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, 531 return -XFS_SEND_DATA(mp, DM_EVENT_READ, vp,
570 0, 0, 0, NULL); 532 0, 0, 0, NULL);
571 }
572 } 533 }
573open_exec_out: 534 return 0;
574 return error;
575} 535}
576#endif /* HAVE_FOP_OPEN_EXEC */ 536#endif /* HAVE_FOP_OPEN_EXEC */
577 537
@@ -592,6 +552,7 @@ const struct file_operations xfs_file_operations = {
592#endif 552#endif
593 .mmap = xfs_file_mmap, 553 .mmap = xfs_file_mmap,
594 .open = xfs_file_open, 554 .open = xfs_file_open,
555 .flush = xfs_file_close,
595 .release = xfs_file_release, 556 .release = xfs_file_release,
596 .fsync = xfs_file_fsync, 557 .fsync = xfs_file_fsync,
597#ifdef HAVE_FOP_OPEN_EXEC 558#ifdef HAVE_FOP_OPEN_EXEC
@@ -616,6 +577,7 @@ const struct file_operations xfs_invis_file_operations = {
616#endif 577#endif
617 .mmap = xfs_file_mmap, 578 .mmap = xfs_file_mmap,
618 .open = xfs_file_open, 579 .open = xfs_file_open,
580 .flush = xfs_file_close,
619 .release = xfs_file_release, 581 .release = xfs_file_release,
620 .fsync = xfs_file_fsync, 582 .fsync = xfs_file_fsync,
621}; 583};
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c
index 575f2a790f31..dc0562828e76 100644
--- a/fs/xfs/linux-2.6/xfs_fs_subr.c
+++ b/fs/xfs/linux-2.6/xfs_fs_subr.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2002,2005-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -15,40 +15,12 @@
15 * along with this program; if not, write the Free Software Foundation, 15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */ 17 */
18
19#include "xfs.h" 18#include "xfs.h"
20 19
21/* 20int fs_noerr(void) { return 0; }
22 * Stub for no-op vnode operations that return error status. 21int fs_nosys(void) { return ENOSYS; }
23 */ 22void fs_noval(void) { return; }
24int
25fs_noerr(void)
26{
27 return 0;
28}
29 23
30/*
31 * Operation unsupported under this file system.
32 */
33int
34fs_nosys(void)
35{
36 return ENOSYS;
37}
38
39/*
40 * Stub for inactive, strategy, and read/write lock/unlock. Does nothing.
41 */
42/* ARGSUSED */
43void
44fs_noval(void)
45{
46}
47
48/*
49 * vnode pcache layer for vnode_tosspages.
50 * 'last' parameter unused but left in for IRIX compatibility
51 */
52void 24void
53fs_tosspages( 25fs_tosspages(
54 bhv_desc_t *bdp, 26 bhv_desc_t *bdp,
@@ -56,18 +28,13 @@ fs_tosspages(
56 xfs_off_t last, 28 xfs_off_t last,
57 int fiopt) 29 int fiopt)
58{ 30{
59 vnode_t *vp = BHV_TO_VNODE(bdp); 31 bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
60 struct inode *ip = vn_to_inode(vp); 32 struct inode *ip = vn_to_inode(vp);
61 33
62 if (VN_CACHED(vp)) 34 if (VN_CACHED(vp))
63 truncate_inode_pages(ip->i_mapping, first); 35 truncate_inode_pages(ip->i_mapping, first);
64} 36}
65 37
66
67/*
68 * vnode pcache layer for vnode_flushinval_pages.
69 * 'last' parameter unused but left in for IRIX compatibility
70 */
71void 38void
72fs_flushinval_pages( 39fs_flushinval_pages(
73 bhv_desc_t *bdp, 40 bhv_desc_t *bdp,
@@ -75,20 +42,17 @@ fs_flushinval_pages(
75 xfs_off_t last, 42 xfs_off_t last,
76 int fiopt) 43 int fiopt)
77{ 44{
78 vnode_t *vp = BHV_TO_VNODE(bdp); 45 bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
79 struct inode *ip = vn_to_inode(vp); 46 struct inode *ip = vn_to_inode(vp);
80 47
81 if (VN_CACHED(vp)) { 48 if (VN_CACHED(vp)) {
49 if (VN_TRUNC(vp))
50 VUNTRUNCATE(vp);
82 filemap_write_and_wait(ip->i_mapping); 51 filemap_write_and_wait(ip->i_mapping);
83
84 truncate_inode_pages(ip->i_mapping, first); 52 truncate_inode_pages(ip->i_mapping, first);
85 } 53 }
86} 54}
87 55
88/*
89 * vnode pcache layer for vnode_flush_pages.
90 * 'last' parameter unused but left in for IRIX compatibility
91 */
92int 56int
93fs_flush_pages( 57fs_flush_pages(
94 bhv_desc_t *bdp, 58 bhv_desc_t *bdp,
@@ -97,15 +61,16 @@ fs_flush_pages(
97 uint64_t flags, 61 uint64_t flags,
98 int fiopt) 62 int fiopt)
99{ 63{
100 vnode_t *vp = BHV_TO_VNODE(bdp); 64 bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
101 struct inode *ip = vn_to_inode(vp); 65 struct inode *ip = vn_to_inode(vp);
102 66
103 if (VN_CACHED(vp)) { 67 if (VN_DIRTY(vp)) {
68 if (VN_TRUNC(vp))
69 VUNTRUNCATE(vp);
104 filemap_fdatawrite(ip->i_mapping); 70 filemap_fdatawrite(ip->i_mapping);
105 if (flags & XFS_B_ASYNC) 71 if (flags & XFS_B_ASYNC)
106 return 0; 72 return 0;
107 filemap_fdatawait(ip->i_mapping); 73 filemap_fdatawait(ip->i_mapping);
108 } 74 }
109
110 return 0; 75 return 0;
111} 76}
diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c
index 6e8085f34635..6c162c3dde7e 100644
--- a/fs/xfs/linux-2.6/xfs_globals.c
+++ b/fs/xfs/linux-2.6/xfs_globals.c
@@ -45,6 +45,7 @@ xfs_param_t xfs_params = {
45 .xfs_buf_age = { 1*100, 15*100, 7200*100}, 45 .xfs_buf_age = { 1*100, 15*100, 7200*100},
46 .inherit_nosym = { 0, 0, 1 }, 46 .inherit_nosym = { 0, 0, 1 },
47 .rotorstep = { 1, 1, 255 }, 47 .rotorstep = { 1, 1, 255 },
48 .inherit_nodfrg = { 0, 1, 1 },
48}; 49};
49 50
50/* 51/*
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 84478491609b..6e52a5dd38d8 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -31,7 +30,6 @@
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_attr_sf.h" 33#include "xfs_attr_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
@@ -78,7 +76,7 @@ xfs_find_handle(
78 xfs_handle_t handle; 76 xfs_handle_t handle;
79 xfs_fsop_handlereq_t hreq; 77 xfs_fsop_handlereq_t hreq;
80 struct inode *inode; 78 struct inode *inode;
81 struct vnode *vp; 79 bhv_vnode_t *vp;
82 80
83 if (copy_from_user(&hreq, arg, sizeof(hreq))) 81 if (copy_from_user(&hreq, arg, sizeof(hreq)))
84 return -XFS_ERROR(EFAULT); 82 return -XFS_ERROR(EFAULT);
@@ -192,7 +190,7 @@ xfs_vget_fsop_handlereq(
192 xfs_mount_t *mp, 190 xfs_mount_t *mp,
193 struct inode *parinode, /* parent inode pointer */ 191 struct inode *parinode, /* parent inode pointer */
194 xfs_fsop_handlereq_t *hreq, 192 xfs_fsop_handlereq_t *hreq,
195 vnode_t **vp, 193 bhv_vnode_t **vp,
196 struct inode **inode) 194 struct inode **inode)
197{ 195{
198 void __user *hanp; 196 void __user *hanp;
@@ -202,7 +200,7 @@ xfs_vget_fsop_handlereq(
202 xfs_handle_t handle; 200 xfs_handle_t handle;
203 xfs_inode_t *ip; 201 xfs_inode_t *ip;
204 struct inode *inodep; 202 struct inode *inodep;
205 vnode_t *vpp; 203 bhv_vnode_t *vpp;
206 xfs_ino_t ino; 204 xfs_ino_t ino;
207 __u32 igen; 205 __u32 igen;
208 int error; 206 int error;
@@ -277,7 +275,7 @@ xfs_open_by_handle(
277 struct file *filp; 275 struct file *filp;
278 struct inode *inode; 276 struct inode *inode;
279 struct dentry *dentry; 277 struct dentry *dentry;
280 vnode_t *vp; 278 bhv_vnode_t *vp;
281 xfs_fsop_handlereq_t hreq; 279 xfs_fsop_handlereq_t hreq;
282 280
283 if (!capable(CAP_SYS_ADMIN)) 281 if (!capable(CAP_SYS_ADMIN))
@@ -362,7 +360,7 @@ xfs_readlink_by_handle(
362 struct uio auio; 360 struct uio auio;
363 struct inode *inode; 361 struct inode *inode;
364 xfs_fsop_handlereq_t hreq; 362 xfs_fsop_handlereq_t hreq;
365 vnode_t *vp; 363 bhv_vnode_t *vp;
366 __u32 olen; 364 __u32 olen;
367 365
368 if (!capable(CAP_SYS_ADMIN)) 366 if (!capable(CAP_SYS_ADMIN))
@@ -393,9 +391,11 @@ xfs_readlink_by_handle(
393 auio.uio_segflg = UIO_USERSPACE; 391 auio.uio_segflg = UIO_USERSPACE;
394 auio.uio_resid = olen; 392 auio.uio_resid = olen;
395 393
396 VOP_READLINK(vp, &auio, IO_INVIS, NULL, error); 394 error = bhv_vop_readlink(vp, &auio, IO_INVIS, NULL);
397
398 VN_RELE(vp); 395 VN_RELE(vp);
396 if (error)
397 return -error;
398
399 return (olen - auio.uio_resid); 399 return (olen - auio.uio_resid);
400} 400}
401 401
@@ -411,7 +411,7 @@ xfs_fssetdm_by_handle(
411 xfs_fsop_setdm_handlereq_t dmhreq; 411 xfs_fsop_setdm_handlereq_t dmhreq;
412 struct inode *inode; 412 struct inode *inode;
413 bhv_desc_t *bdp; 413 bhv_desc_t *bdp;
414 vnode_t *vp; 414 bhv_vnode_t *vp;
415 415
416 if (!capable(CAP_MKNOD)) 416 if (!capable(CAP_MKNOD))
417 return -XFS_ERROR(EPERM); 417 return -XFS_ERROR(EPERM);
@@ -452,7 +452,7 @@ xfs_attrlist_by_handle(
452 attrlist_cursor_kern_t *cursor; 452 attrlist_cursor_kern_t *cursor;
453 xfs_fsop_attrlist_handlereq_t al_hreq; 453 xfs_fsop_attrlist_handlereq_t al_hreq;
454 struct inode *inode; 454 struct inode *inode;
455 vnode_t *vp; 455 bhv_vnode_t *vp;
456 char *kbuf; 456 char *kbuf;
457 457
458 if (!capable(CAP_SYS_ADMIN)) 458 if (!capable(CAP_SYS_ADMIN))
@@ -472,8 +472,8 @@ xfs_attrlist_by_handle(
472 goto out_vn_rele; 472 goto out_vn_rele;
473 473
474 cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; 474 cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
475 VOP_ATTR_LIST(vp, kbuf, al_hreq.buflen, al_hreq.flags, 475 error = bhv_vop_attr_list(vp, kbuf, al_hreq.buflen, al_hreq.flags,
476 cursor, NULL, error); 476 cursor, NULL);
477 if (error) 477 if (error)
478 goto out_kfree; 478 goto out_kfree;
479 479
@@ -490,7 +490,7 @@ xfs_attrlist_by_handle(
490 490
491STATIC int 491STATIC int
492xfs_attrmulti_attr_get( 492xfs_attrmulti_attr_get(
493 struct vnode *vp, 493 bhv_vnode_t *vp,
494 char *name, 494 char *name,
495 char __user *ubuf, 495 char __user *ubuf,
496 __uint32_t *len, 496 __uint32_t *len,
@@ -505,7 +505,7 @@ xfs_attrmulti_attr_get(
505 if (!kbuf) 505 if (!kbuf)
506 return ENOMEM; 506 return ENOMEM;
507 507
508 VOP_ATTR_GET(vp, name, kbuf, len, flags, NULL, error); 508 error = bhv_vop_attr_get(vp, name, kbuf, len, flags, NULL);
509 if (error) 509 if (error)
510 goto out_kfree; 510 goto out_kfree;
511 511
@@ -519,7 +519,7 @@ xfs_attrmulti_attr_get(
519 519
520STATIC int 520STATIC int
521xfs_attrmulti_attr_set( 521xfs_attrmulti_attr_set(
522 struct vnode *vp, 522 bhv_vnode_t *vp,
523 char *name, 523 char *name,
524 const char __user *ubuf, 524 const char __user *ubuf,
525 __uint32_t len, 525 __uint32_t len,
@@ -542,7 +542,7 @@ xfs_attrmulti_attr_set(
542 if (copy_from_user(kbuf, ubuf, len)) 542 if (copy_from_user(kbuf, ubuf, len))
543 goto out_kfree; 543 goto out_kfree;
544 544
545 VOP_ATTR_SET(vp, name, kbuf, len, flags, NULL, error); 545 error = bhv_vop_attr_set(vp, name, kbuf, len, flags, NULL);
546 546
547 out_kfree: 547 out_kfree:
548 kfree(kbuf); 548 kfree(kbuf);
@@ -551,20 +551,15 @@ xfs_attrmulti_attr_set(
551 551
552STATIC int 552STATIC int
553xfs_attrmulti_attr_remove( 553xfs_attrmulti_attr_remove(
554 struct vnode *vp, 554 bhv_vnode_t *vp,
555 char *name, 555 char *name,
556 __uint32_t flags) 556 __uint32_t flags)
557{ 557{
558 int error;
559
560
561 if (IS_RDONLY(&vp->v_inode)) 558 if (IS_RDONLY(&vp->v_inode))
562 return -EROFS; 559 return -EROFS;
563 if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode)) 560 if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
564 return EPERM; 561 return EPERM;
565 562 return bhv_vop_attr_remove(vp, name, flags, NULL);
566 VOP_ATTR_REMOVE(vp, name, flags, NULL, error);
567 return error;
568} 563}
569 564
570STATIC int 565STATIC int
@@ -578,7 +573,7 @@ xfs_attrmulti_by_handle(
578 xfs_attr_multiop_t *ops; 573 xfs_attr_multiop_t *ops;
579 xfs_fsop_attrmulti_handlereq_t am_hreq; 574 xfs_fsop_attrmulti_handlereq_t am_hreq;
580 struct inode *inode; 575 struct inode *inode;
581 vnode_t *vp; 576 bhv_vnode_t *vp;
582 unsigned int i, size; 577 unsigned int i, size;
583 char *attr_name; 578 char *attr_name;
584 579
@@ -658,7 +653,7 @@ xfs_attrmulti_by_handle(
658STATIC int 653STATIC int
659xfs_ioc_space( 654xfs_ioc_space(
660 bhv_desc_t *bdp, 655 bhv_desc_t *bdp,
661 vnode_t *vp, 656 bhv_vnode_t *vp,
662 struct file *filp, 657 struct file *filp,
663 int flags, 658 int flags,
664 unsigned int cmd, 659 unsigned int cmd,
@@ -682,7 +677,7 @@ xfs_ioc_fsgeometry(
682 677
683STATIC int 678STATIC int
684xfs_ioc_xattr( 679xfs_ioc_xattr(
685 vnode_t *vp, 680 bhv_vnode_t *vp,
686 xfs_inode_t *ip, 681 xfs_inode_t *ip,
687 struct file *filp, 682 struct file *filp,
688 unsigned int cmd, 683 unsigned int cmd,
@@ -711,7 +706,7 @@ xfs_ioctl(
711 void __user *arg) 706 void __user *arg)
712{ 707{
713 int error; 708 int error;
714 vnode_t *vp; 709 bhv_vnode_t *vp;
715 xfs_inode_t *ip; 710 xfs_inode_t *ip;
716 xfs_mount_t *mp; 711 xfs_mount_t *mp;
717 712
@@ -962,7 +957,7 @@ xfs_ioctl(
962STATIC int 957STATIC int
963xfs_ioc_space( 958xfs_ioc_space(
964 bhv_desc_t *bdp, 959 bhv_desc_t *bdp,
965 vnode_t *vp, 960 bhv_vnode_t *vp,
966 struct file *filp, 961 struct file *filp,
967 int ioflags, 962 int ioflags,
968 unsigned int cmd, 963 unsigned int cmd,
@@ -1153,14 +1148,14 @@ xfs_di2lxflags(
1153 1148
1154STATIC int 1149STATIC int
1155xfs_ioc_xattr( 1150xfs_ioc_xattr(
1156 vnode_t *vp, 1151 bhv_vnode_t *vp,
1157 xfs_inode_t *ip, 1152 xfs_inode_t *ip,
1158 struct file *filp, 1153 struct file *filp,
1159 unsigned int cmd, 1154 unsigned int cmd,
1160 void __user *arg) 1155 void __user *arg)
1161{ 1156{
1162 struct fsxattr fa; 1157 struct fsxattr fa;
1163 struct vattr *vattr; 1158 struct bhv_vattr *vattr;
1164 int error = 0; 1159 int error = 0;
1165 int attr_flags; 1160 int attr_flags;
1166 unsigned int flags; 1161 unsigned int flags;
@@ -1173,7 +1168,7 @@ xfs_ioc_xattr(
1173 case XFS_IOC_FSGETXATTR: { 1168 case XFS_IOC_FSGETXATTR: {
1174 vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ 1169 vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
1175 XFS_AT_NEXTENTS | XFS_AT_PROJID; 1170 XFS_AT_NEXTENTS | XFS_AT_PROJID;
1176 VOP_GETATTR(vp, vattr, 0, NULL, error); 1171 error = bhv_vop_getattr(vp, vattr, 0, NULL);
1177 if (unlikely(error)) { 1172 if (unlikely(error)) {
1178 error = -error; 1173 error = -error;
1179 break; 1174 break;
@@ -1206,7 +1201,7 @@ xfs_ioc_xattr(
1206 vattr->va_extsize = fa.fsx_extsize; 1201 vattr->va_extsize = fa.fsx_extsize;
1207 vattr->va_projid = fa.fsx_projid; 1202 vattr->va_projid = fa.fsx_projid;
1208 1203
1209 VOP_SETATTR(vp, vattr, attr_flags, NULL, error); 1204 error = bhv_vop_setattr(vp, vattr, attr_flags, NULL);
1210 if (likely(!error)) 1205 if (likely(!error))
1211 __vn_revalidate(vp, vattr); /* update flags */ 1206 __vn_revalidate(vp, vattr); /* update flags */
1212 error = -error; 1207 error = -error;
@@ -1216,7 +1211,7 @@ xfs_ioc_xattr(
1216 case XFS_IOC_FSGETXATTRA: { 1211 case XFS_IOC_FSGETXATTRA: {
1217 vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ 1212 vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
1218 XFS_AT_ANEXTENTS | XFS_AT_PROJID; 1213 XFS_AT_ANEXTENTS | XFS_AT_PROJID;
1219 VOP_GETATTR(vp, vattr, 0, NULL, error); 1214 error = bhv_vop_getattr(vp, vattr, 0, NULL);
1220 if (unlikely(error)) { 1215 if (unlikely(error)) {
1221 error = -error; 1216 error = -error;
1222 break; 1217 break;
@@ -1262,7 +1257,7 @@ xfs_ioc_xattr(
1262 vattr->va_xflags = xfs_merge_ioc_xflags(flags, 1257 vattr->va_xflags = xfs_merge_ioc_xflags(flags,
1263 xfs_ip2xflags(ip)); 1258 xfs_ip2xflags(ip));
1264 1259
1265 VOP_SETATTR(vp, vattr, attr_flags, NULL, error); 1260 error = bhv_vop_setattr(vp, vattr, attr_flags, NULL);
1266 if (likely(!error)) 1261 if (likely(!error))
1267 __vn_revalidate(vp, vattr); /* update flags */ 1262 __vn_revalidate(vp, vattr); /* update flags */
1268 error = -error; 1263 error = -error;
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index 251bfe451a3f..601f01c92f7f 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -114,7 +114,7 @@ xfs_compat_ioctl(
114 unsigned long arg) 114 unsigned long arg)
115{ 115{
116 struct inode *inode = file->f_dentry->d_inode; 116 struct inode *inode = file->f_dentry->d_inode;
117 vnode_t *vp = vn_from_inode(inode); 117 bhv_vnode_t *vp = vn_from_inode(inode);
118 int error; 118 int error;
119 119
120 switch (cmd) { 120 switch (cmd) {
@@ -193,7 +193,7 @@ xfs_compat_ioctl(
193 return -ENOIOCTLCMD; 193 return -ENOIOCTLCMD;
194 } 194 }
195 195
196 VOP_IOCTL(vp, inode, file, mode, cmd, (void __user *)arg, error); 196 error = bhv_vop_ioctl(vp, inode, file, mode, cmd, (void __user *)arg);
197 VMODIFY(vp); 197 VMODIFY(vp);
198 198
199 return error; 199 return error;
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 2e2e275c786f..12810baeb5d4 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
@@ -61,7 +59,7 @@
61 */ 59 */
62xfs_inode_t * 60xfs_inode_t *
63xfs_vtoi( 61xfs_vtoi(
64 struct vnode *vp) 62 bhv_vnode_t *vp)
65{ 63{
66 bhv_desc_t *bdp; 64 bhv_desc_t *bdp;
67 65
@@ -80,7 +78,7 @@ void
80xfs_synchronize_atime( 78xfs_synchronize_atime(
81 xfs_inode_t *ip) 79 xfs_inode_t *ip)
82{ 80{
83 vnode_t *vp; 81 bhv_vnode_t *vp;
84 82
85 vp = XFS_ITOV_NULL(ip); 83 vp = XFS_ITOV_NULL(ip);
86 if (vp) { 84 if (vp) {
@@ -200,14 +198,10 @@ xfs_ichgtime_fast(
200STATIC void 198STATIC void
201xfs_validate_fields( 199xfs_validate_fields(
202 struct inode *ip, 200 struct inode *ip,
203 struct vattr *vattr) 201 bhv_vattr_t *vattr)
204{ 202{
205 vnode_t *vp = vn_from_inode(ip);
206 int error;
207
208 vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS; 203 vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS;
209 VOP_GETATTR(vp, vattr, ATTR_LAZY, NULL, error); 204 if (!bhv_vop_getattr(vn_from_inode(ip), vattr, ATTR_LAZY, NULL)) {
210 if (likely(!error)) {
211 ip->i_nlink = vattr->va_nlink; 205 ip->i_nlink = vattr->va_nlink;
212 ip->i_blocks = vattr->va_nblocks; 206 ip->i_blocks = vattr->va_nblocks;
213 207
@@ -225,7 +219,7 @@ xfs_validate_fields(
225 */ 219 */
226STATIC int 220STATIC int
227xfs_init_security( 221xfs_init_security(
228 struct vnode *vp, 222 bhv_vnode_t *vp,
229 struct inode *dir) 223 struct inode *dir)
230{ 224{
231 struct inode *ip = vn_to_inode(vp); 225 struct inode *ip = vn_to_inode(vp);
@@ -241,7 +235,7 @@ xfs_init_security(
241 return -error; 235 return -error;
242 } 236 }
243 237
244 VOP_ATTR_SET(vp, name, value, length, ATTR_SECURE, NULL, error); 238 error = bhv_vop_attr_set(vp, name, value, length, ATTR_SECURE, NULL);
245 if (!error) 239 if (!error)
246 VMODIFY(vp); 240 VMODIFY(vp);
247 241
@@ -264,13 +258,12 @@ xfs_has_fs_struct(struct task_struct *task)
264 258
265STATIC inline void 259STATIC inline void
266xfs_cleanup_inode( 260xfs_cleanup_inode(
267 vnode_t *dvp, 261 bhv_vnode_t *dvp,
268 vnode_t *vp, 262 bhv_vnode_t *vp,
269 struct dentry *dentry, 263 struct dentry *dentry,
270 int mode) 264 int mode)
271{ 265{
272 struct dentry teardown = {}; 266 struct dentry teardown = {};
273 int error;
274 267
275 /* Oh, the horror. 268 /* Oh, the horror.
276 * If we can't add the ACL or we fail in 269 * If we can't add the ACL or we fail in
@@ -281,9 +274,9 @@ xfs_cleanup_inode(
281 teardown.d_name = dentry->d_name; 274 teardown.d_name = dentry->d_name;
282 275
283 if (S_ISDIR(mode)) 276 if (S_ISDIR(mode))
284 VOP_RMDIR(dvp, &teardown, NULL, error); 277 bhv_vop_rmdir(dvp, &teardown, NULL);
285 else 278 else
286 VOP_REMOVE(dvp, &teardown, NULL, error); 279 bhv_vop_remove(dvp, &teardown, NULL);
287 VN_RELE(vp); 280 VN_RELE(vp);
288} 281}
289 282
@@ -295,8 +288,8 @@ xfs_vn_mknod(
295 dev_t rdev) 288 dev_t rdev)
296{ 289{
297 struct inode *ip; 290 struct inode *ip;
298 vattr_t vattr = { 0 }; 291 bhv_vattr_t vattr = { 0 };
299 vnode_t *vp = NULL, *dvp = vn_from_inode(dir); 292 bhv_vnode_t *vp = NULL, *dvp = vn_from_inode(dir);
300 xfs_acl_t *default_acl = NULL; 293 xfs_acl_t *default_acl = NULL;
301 attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; 294 attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS;
302 int error; 295 int error;
@@ -330,10 +323,10 @@ xfs_vn_mknod(
330 vattr.va_mask |= XFS_AT_RDEV; 323 vattr.va_mask |= XFS_AT_RDEV;
331 /*FALLTHROUGH*/ 324 /*FALLTHROUGH*/
332 case S_IFREG: 325 case S_IFREG:
333 VOP_CREATE(dvp, dentry, &vattr, &vp, NULL, error); 326 error = bhv_vop_create(dvp, dentry, &vattr, &vp, NULL);
334 break; 327 break;
335 case S_IFDIR: 328 case S_IFDIR:
336 VOP_MKDIR(dvp, dentry, &vattr, &vp, NULL, error); 329 error = bhv_vop_mkdir(dvp, dentry, &vattr, &vp, NULL);
337 break; 330 break;
338 default: 331 default:
339 error = EINVAL; 332 error = EINVAL;
@@ -396,14 +389,14 @@ xfs_vn_lookup(
396 struct dentry *dentry, 389 struct dentry *dentry,
397 struct nameidata *nd) 390 struct nameidata *nd)
398{ 391{
399 struct vnode *vp = vn_from_inode(dir), *cvp; 392 bhv_vnode_t *vp = vn_from_inode(dir), *cvp;
400 int error; 393 int error;
401 394
402 if (dentry->d_name.len >= MAXNAMELEN) 395 if (dentry->d_name.len >= MAXNAMELEN)
403 return ERR_PTR(-ENAMETOOLONG); 396 return ERR_PTR(-ENAMETOOLONG);
404 397
405 VOP_LOOKUP(vp, dentry, &cvp, 0, NULL, NULL, error); 398 error = bhv_vop_lookup(vp, dentry, &cvp, 0, NULL, NULL);
406 if (error) { 399 if (unlikely(error)) {
407 if (unlikely(error != ENOENT)) 400 if (unlikely(error != ENOENT))
408 return ERR_PTR(-error); 401 return ERR_PTR(-error);
409 d_add(dentry, NULL); 402 d_add(dentry, NULL);
@@ -420,9 +413,9 @@ xfs_vn_link(
420 struct dentry *dentry) 413 struct dentry *dentry)
421{ 414{
422 struct inode *ip; /* inode of guy being linked to */ 415 struct inode *ip; /* inode of guy being linked to */
423 vnode_t *tdvp; /* target directory for new name/link */ 416 bhv_vnode_t *tdvp; /* target directory for new name/link */
424 vnode_t *vp; /* vp of name being linked */ 417 bhv_vnode_t *vp; /* vp of name being linked */
425 vattr_t vattr; 418 bhv_vattr_t vattr;
426 int error; 419 int error;
427 420
428 ip = old_dentry->d_inode; /* inode being linked to */ 421 ip = old_dentry->d_inode; /* inode being linked to */
@@ -432,7 +425,7 @@ xfs_vn_link(
432 tdvp = vn_from_inode(dir); 425 tdvp = vn_from_inode(dir);
433 vp = vn_from_inode(ip); 426 vp = vn_from_inode(ip);
434 427
435 VOP_LINK(tdvp, vp, dentry, NULL, error); 428 error = bhv_vop_link(tdvp, vp, dentry, NULL);
436 if (likely(!error)) { 429 if (likely(!error)) {
437 VMODIFY(tdvp); 430 VMODIFY(tdvp);
438 VN_HOLD(vp); 431 VN_HOLD(vp);
@@ -448,14 +441,14 @@ xfs_vn_unlink(
448 struct dentry *dentry) 441 struct dentry *dentry)
449{ 442{
450 struct inode *inode; 443 struct inode *inode;
451 vnode_t *dvp; /* directory containing name to remove */ 444 bhv_vnode_t *dvp; /* directory containing name to remove */
452 vattr_t vattr; 445 bhv_vattr_t vattr;
453 int error; 446 int error;
454 447
455 inode = dentry->d_inode; 448 inode = dentry->d_inode;
456 dvp = vn_from_inode(dir); 449 dvp = vn_from_inode(dir);
457 450
458 VOP_REMOVE(dvp, dentry, NULL, error); 451 error = bhv_vop_remove(dvp, dentry, NULL);
459 if (likely(!error)) { 452 if (likely(!error)) {
460 xfs_validate_fields(dir, &vattr); /* size needs update */ 453 xfs_validate_fields(dir, &vattr); /* size needs update */
461 xfs_validate_fields(inode, &vattr); 454 xfs_validate_fields(inode, &vattr);
@@ -470,27 +463,26 @@ xfs_vn_symlink(
470 const char *symname) 463 const char *symname)
471{ 464{
472 struct inode *ip; 465 struct inode *ip;
473 vattr_t vattr = { 0 }; 466 bhv_vattr_t va = { 0 };
474 vnode_t *dvp; /* directory containing name of symlink */ 467 bhv_vnode_t *dvp; /* directory containing name of symlink */
475 vnode_t *cvp; /* used to lookup symlink to put in dentry */ 468 bhv_vnode_t *cvp; /* used to lookup symlink to put in dentry */
476 int error; 469 int error;
477 470
478 dvp = vn_from_inode(dir); 471 dvp = vn_from_inode(dir);
479 cvp = NULL; 472 cvp = NULL;
480 473
481 vattr.va_mode = S_IFLNK | 474 va.va_mode = S_IFLNK |
482 (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO); 475 (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO);
483 vattr.va_mask = XFS_AT_TYPE|XFS_AT_MODE; 476 va.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
484 477
485 error = 0; 478 error = bhv_vop_symlink(dvp, dentry, &va, (char *)symname, &cvp, NULL);
486 VOP_SYMLINK(dvp, dentry, &vattr, (char *)symname, &cvp, NULL, error);
487 if (likely(!error && cvp)) { 479 if (likely(!error && cvp)) {
488 error = xfs_init_security(cvp, dir); 480 error = xfs_init_security(cvp, dir);
489 if (likely(!error)) { 481 if (likely(!error)) {
490 ip = vn_to_inode(cvp); 482 ip = vn_to_inode(cvp);
491 d_instantiate(dentry, ip); 483 d_instantiate(dentry, ip);
492 xfs_validate_fields(dir, &vattr); 484 xfs_validate_fields(dir, &va);
493 xfs_validate_fields(ip, &vattr); 485 xfs_validate_fields(ip, &va);
494 } else { 486 } else {
495 xfs_cleanup_inode(dvp, cvp, dentry, 0); 487 xfs_cleanup_inode(dvp, cvp, dentry, 0);
496 } 488 }
@@ -504,11 +496,11 @@ xfs_vn_rmdir(
504 struct dentry *dentry) 496 struct dentry *dentry)
505{ 497{
506 struct inode *inode = dentry->d_inode; 498 struct inode *inode = dentry->d_inode;
507 vnode_t *dvp = vn_from_inode(dir); 499 bhv_vnode_t *dvp = vn_from_inode(dir);
508 vattr_t vattr; 500 bhv_vattr_t vattr;
509 int error; 501 int error;
510 502
511 VOP_RMDIR(dvp, dentry, NULL, error); 503 error = bhv_vop_rmdir(dvp, dentry, NULL);
512 if (likely(!error)) { 504 if (likely(!error)) {
513 xfs_validate_fields(inode, &vattr); 505 xfs_validate_fields(inode, &vattr);
514 xfs_validate_fields(dir, &vattr); 506 xfs_validate_fields(dir, &vattr);
@@ -524,15 +516,15 @@ xfs_vn_rename(
524 struct dentry *ndentry) 516 struct dentry *ndentry)
525{ 517{
526 struct inode *new_inode = ndentry->d_inode; 518 struct inode *new_inode = ndentry->d_inode;
527 vnode_t *fvp; /* from directory */ 519 bhv_vnode_t *fvp; /* from directory */
528 vnode_t *tvp; /* target directory */ 520 bhv_vnode_t *tvp; /* target directory */
529 vattr_t vattr; 521 bhv_vattr_t vattr;
530 int error; 522 int error;
531 523
532 fvp = vn_from_inode(odir); 524 fvp = vn_from_inode(odir);
533 tvp = vn_from_inode(ndir); 525 tvp = vn_from_inode(ndir);
534 526
535 VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error); 527 error = bhv_vop_rename(fvp, odentry, tvp, ndentry, NULL);
536 if (likely(!error)) { 528 if (likely(!error)) {
537 if (new_inode) 529 if (new_inode)
538 xfs_validate_fields(new_inode, &vattr); 530 xfs_validate_fields(new_inode, &vattr);
@@ -553,7 +545,7 @@ xfs_vn_follow_link(
553 struct dentry *dentry, 545 struct dentry *dentry,
554 struct nameidata *nd) 546 struct nameidata *nd)
555{ 547{
556 vnode_t *vp; 548 bhv_vnode_t *vp;
557 uio_t *uio; 549 uio_t *uio;
558 iovec_t iov; 550 iovec_t iov;
559 int error; 551 int error;
@@ -586,8 +578,8 @@ xfs_vn_follow_link(
586 uio->uio_resid = MAXPATHLEN; 578 uio->uio_resid = MAXPATHLEN;
587 uio->uio_iovcnt = 1; 579 uio->uio_iovcnt = 1;
588 580
589 VOP_READLINK(vp, uio, 0, NULL, error); 581 error = bhv_vop_readlink(vp, uio, 0, NULL);
590 if (error) { 582 if (unlikely(error)) {
591 kfree(link); 583 kfree(link);
592 link = ERR_PTR(-error); 584 link = ERR_PTR(-error);
593 } else { 585 } else {
@@ -618,12 +610,7 @@ xfs_vn_permission(
618 int mode, 610 int mode,
619 struct nameidata *nd) 611 struct nameidata *nd)
620{ 612{
621 vnode_t *vp = vn_from_inode(inode); 613 return -bhv_vop_access(vn_from_inode(inode), mode << 6, NULL);
622 int error;
623
624 mode <<= 6; /* convert from linux to vnode access bits */
625 VOP_ACCESS(vp, mode, NULL, error);
626 return -error;
627} 614}
628#else 615#else
629#define xfs_vn_permission NULL 616#define xfs_vn_permission NULL
@@ -636,14 +623,14 @@ xfs_vn_getattr(
636 struct kstat *stat) 623 struct kstat *stat)
637{ 624{
638 struct inode *inode = dentry->d_inode; 625 struct inode *inode = dentry->d_inode;
639 vnode_t *vp = vn_from_inode(inode); 626 bhv_vnode_t *vp = vn_from_inode(inode);
640 int error = 0; 627 int error = 0;
641 628
642 if (unlikely(vp->v_flag & VMODIFIED)) 629 if (unlikely(vp->v_flag & VMODIFIED))
643 error = vn_revalidate(vp); 630 error = vn_revalidate(vp);
644 if (!error) 631 if (!error)
645 generic_fillattr(inode, stat); 632 generic_fillattr(inode, stat);
646 return 0; 633 return -error;
647} 634}
648 635
649STATIC int 636STATIC int
@@ -653,8 +640,8 @@ xfs_vn_setattr(
653{ 640{
654 struct inode *inode = dentry->d_inode; 641 struct inode *inode = dentry->d_inode;
655 unsigned int ia_valid = attr->ia_valid; 642 unsigned int ia_valid = attr->ia_valid;
656 vnode_t *vp = vn_from_inode(inode); 643 bhv_vnode_t *vp = vn_from_inode(inode);
657 vattr_t vattr = { 0 }; 644 bhv_vattr_t vattr = { 0 };
658 int flags = 0; 645 int flags = 0;
659 int error; 646 int error;
660 647
@@ -697,7 +684,7 @@ xfs_vn_setattr(
697 flags |= ATTR_NONBLOCK; 684 flags |= ATTR_NONBLOCK;
698#endif 685#endif
699 686
700 VOP_SETATTR(vp, &vattr, flags, NULL, error); 687 error = bhv_vop_setattr(vp, &vattr, flags, NULL);
701 if (likely(!error)) 688 if (likely(!error))
702 __vn_revalidate(vp, &vattr); 689 __vn_revalidate(vp, &vattr);
703 return -error; 690 return -error;
@@ -718,7 +705,7 @@ xfs_vn_setxattr(
718 size_t size, 705 size_t size,
719 int flags) 706 int flags)
720{ 707{
721 vnode_t *vp = vn_from_inode(dentry->d_inode); 708 bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
722 char *attr = (char *)name; 709 char *attr = (char *)name;
723 attrnames_t *namesp; 710 attrnames_t *namesp;
724 int xflags = 0; 711 int xflags = 0;
@@ -748,7 +735,7 @@ xfs_vn_getxattr(
748 void *data, 735 void *data,
749 size_t size) 736 size_t size)
750{ 737{
751 vnode_t *vp = vn_from_inode(dentry->d_inode); 738 bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
752 char *attr = (char *)name; 739 char *attr = (char *)name;
753 attrnames_t *namesp; 740 attrnames_t *namesp;
754 int xflags = 0; 741 int xflags = 0;
@@ -777,7 +764,7 @@ xfs_vn_listxattr(
777 char *data, 764 char *data,
778 size_t size) 765 size_t size)
779{ 766{
780 vnode_t *vp = vn_from_inode(dentry->d_inode); 767 bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
781 int error, xflags = ATTR_KERNAMELS; 768 int error, xflags = ATTR_KERNAMELS;
782 ssize_t result; 769 ssize_t result;
783 770
@@ -796,7 +783,7 @@ xfs_vn_removexattr(
796 struct dentry *dentry, 783 struct dentry *dentry,
797 const char *name) 784 const char *name)
798{ 785{
799 vnode_t *vp = vn_from_inode(dentry->d_inode); 786 bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
800 char *attr = (char *)name; 787 char *attr = (char *)name;
801 attrnames_t *namesp; 788 attrnames_t *namesp;
802 int xflags = 0; 789 int xflags = 0;
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index e9fe43d74768..aa26ab906c88 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -134,14 +134,21 @@ BUFFER_FNS(PrivateStart, unwritten);
134#define xfs_buf_age_centisecs xfs_params.xfs_buf_age.val 134#define xfs_buf_age_centisecs xfs_params.xfs_buf_age.val
135#define xfs_inherit_nosymlinks xfs_params.inherit_nosym.val 135#define xfs_inherit_nosymlinks xfs_params.inherit_nosym.val
136#define xfs_rotorstep xfs_params.rotorstep.val 136#define xfs_rotorstep xfs_params.rotorstep.val
137#define xfs_inherit_nodefrag xfs_params.inherit_nodfrg.val
137 138
138#ifndef raw_smp_processor_id 139#define current_cpu() (raw_smp_processor_id())
139#define raw_smp_processor_id() smp_processor_id()
140#endif
141#define current_cpu() raw_smp_processor_id()
142#define current_pid() (current->pid) 140#define current_pid() (current->pid)
143#define current_fsuid(cred) (current->fsuid) 141#define current_fsuid(cred) (current->fsuid)
144#define current_fsgid(cred) (current->fsgid) 142#define current_fsgid(cred) (current->fsgid)
143#define current_set_flags(f) (current->flags |= (f))
144#define current_test_flags(f) (current->flags & (f))
145#define current_clear_flags(f) (current->flags & ~(f))
146#define current_set_flags_nested(sp, f) \
147 (*(sp) = current->flags, current->flags |= (f))
148#define current_clear_flags_nested(sp, f) \
149 (*(sp) = current->flags, current->flags &= ~(f))
150#define current_restore_flags_nested(sp, f) \
151 (current->flags = ((current->flags & ~(f)) | (*(sp) & (f))))
145 152
146#define NBPP PAGE_SIZE 153#define NBPP PAGE_SIZE
147#define DPPSHFT (PAGE_SHIFT - 9) 154#define DPPSHFT (PAGE_SHIFT - 9)
@@ -187,25 +194,9 @@ BUFFER_FNS(PrivateStart, unwritten);
187/* bytes to clicks */ 194/* bytes to clicks */
188#define btoc(x) (((__psunsigned_t)(x)+(NBPC-1))>>BPCSHIFT) 195#define btoc(x) (((__psunsigned_t)(x)+(NBPC-1))>>BPCSHIFT)
189 196
190#ifndef ENOATTR
191#define ENOATTR ENODATA /* Attribute not found */ 197#define ENOATTR ENODATA /* Attribute not found */
192#endif 198#define EWRONGFS EINVAL /* Mount with wrong filesystem type */
193 199#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
194/* Note: EWRONGFS never visible outside the kernel */
195#define EWRONGFS EINVAL /* Mount with wrong filesystem type */
196
197/*
198 * XXX EFSCORRUPTED needs a real value in errno.h. asm-i386/errno.h won't
199 * return codes out of its known range in errno.
200 * XXX Also note: needs to be < 1000 and fairly unique on Linux (mustn't
201 * conflict with any code we use already or any code a driver may use)
202 * XXX Some options (currently we do #2):
203 * 1/ New error code ["Filesystem is corrupted", _after_ glibc updated]
204 * 2/ 990 ["Unknown error 990"]
205 * 3/ EUCLEAN ["Structure needs cleaning"]
206 * 4/ Convert EFSCORRUPTED to EIO [just prior to return into userspace]
207 */
208#define EFSCORRUPTED 990 /* Filesystem is corrupted */
209 200
210#define SYNCHRONIZE() barrier() 201#define SYNCHRONIZE() barrier()
211#define __return_address __builtin_return_address(0) 202#define __return_address __builtin_return_address(0)
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 67efe3308980..5d9cfd91ad08 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
@@ -206,7 +204,7 @@ xfs_read(
206 xfs_fsize_t n; 204 xfs_fsize_t n;
207 xfs_inode_t *ip; 205 xfs_inode_t *ip;
208 xfs_mount_t *mp; 206 xfs_mount_t *mp;
209 vnode_t *vp; 207 bhv_vnode_t *vp;
210 unsigned long seg; 208 unsigned long seg;
211 209
212 ip = XFS_BHVTOI(bdp); 210 ip = XFS_BHVTOI(bdp);
@@ -258,7 +256,7 @@ xfs_read(
258 256
259 if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && 257 if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
260 !(ioflags & IO_INVIS)) { 258 !(ioflags & IO_INVIS)) {
261 vrwlock_t locktype = VRWLOCK_READ; 259 bhv_vrwlock_t locktype = VRWLOCK_READ;
262 int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags); 260 int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
263 261
264 ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, 262 ret = -XFS_SEND_DATA(mp, DM_EVENT_READ,
@@ -271,7 +269,7 @@ xfs_read(
271 } 269 }
272 270
273 if (unlikely((ioflags & IO_ISDIRECT) && VN_CACHED(vp))) 271 if (unlikely((ioflags & IO_ISDIRECT) && VN_CACHED(vp)))
274 VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(*offset)), 272 bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
275 -1, FI_REMAPF_LOCKED); 273 -1, FI_REMAPF_LOCKED);
276 274
277 xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore, 275 xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
@@ -313,7 +311,7 @@ xfs_sendfile(
313 311
314 if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) && 312 if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
315 (!(ioflags & IO_INVIS))) { 313 (!(ioflags & IO_INVIS))) {
316 vrwlock_t locktype = VRWLOCK_READ; 314 bhv_vrwlock_t locktype = VRWLOCK_READ;
317 int error; 315 int error;
318 316
319 error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), 317 error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
@@ -357,7 +355,7 @@ xfs_splice_read(
357 355
358 if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) && 356 if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
359 (!(ioflags & IO_INVIS))) { 357 (!(ioflags & IO_INVIS))) {
360 vrwlock_t locktype = VRWLOCK_READ; 358 bhv_vrwlock_t locktype = VRWLOCK_READ;
361 int error; 359 int error;
362 360
363 error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), 361 error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
@@ -401,7 +399,7 @@ xfs_splice_write(
401 399
402 if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) && 400 if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) &&
403 (!(ioflags & IO_INVIS))) { 401 (!(ioflags & IO_INVIS))) {
404 vrwlock_t locktype = VRWLOCK_WRITE; 402 bhv_vrwlock_t locktype = VRWLOCK_WRITE;
405 int error; 403 int error;
406 404
407 error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp), 405 error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
@@ -458,7 +456,7 @@ xfs_zero_last_block(
458 last_fsb = XFS_B_TO_FSBT(mp, isize); 456 last_fsb = XFS_B_TO_FSBT(mp, isize);
459 nimaps = 1; 457 nimaps = 1;
460 error = XFS_BMAPI(mp, NULL, io, last_fsb, 1, 0, NULL, 0, &imap, 458 error = XFS_BMAPI(mp, NULL, io, last_fsb, 1, 0, NULL, 0, &imap,
461 &nimaps, NULL); 459 &nimaps, NULL, NULL);
462 if (error) { 460 if (error) {
463 return error; 461 return error;
464 } 462 }
@@ -499,7 +497,7 @@ xfs_zero_last_block(
499 497
500int /* error (positive) */ 498int /* error (positive) */
501xfs_zero_eof( 499xfs_zero_eof(
502 vnode_t *vp, 500 bhv_vnode_t *vp,
503 xfs_iocore_t *io, 501 xfs_iocore_t *io,
504 xfs_off_t offset, /* starting I/O offset */ 502 xfs_off_t offset, /* starting I/O offset */
505 xfs_fsize_t isize, /* current inode size */ 503 xfs_fsize_t isize, /* current inode size */
@@ -510,7 +508,6 @@ xfs_zero_eof(
510 xfs_fileoff_t end_zero_fsb; 508 xfs_fileoff_t end_zero_fsb;
511 xfs_fileoff_t zero_count_fsb; 509 xfs_fileoff_t zero_count_fsb;
512 xfs_fileoff_t last_fsb; 510 xfs_fileoff_t last_fsb;
513 xfs_extlen_t buf_len_fsb;
514 xfs_mount_t *mp = io->io_mount; 511 xfs_mount_t *mp = io->io_mount;
515 int nimaps; 512 int nimaps;
516 int error = 0; 513 int error = 0;
@@ -556,7 +553,7 @@ xfs_zero_eof(
556 nimaps = 1; 553 nimaps = 1;
557 zero_count_fsb = end_zero_fsb - start_zero_fsb + 1; 554 zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
558 error = XFS_BMAPI(mp, NULL, io, start_zero_fsb, zero_count_fsb, 555 error = XFS_BMAPI(mp, NULL, io, start_zero_fsb, zero_count_fsb,
559 0, NULL, 0, &imap, &nimaps, NULL); 556 0, NULL, 0, &imap, &nimaps, NULL, NULL);
560 if (error) { 557 if (error) {
561 ASSERT(ismrlocked(io->io_lock, MR_UPDATE)); 558 ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
562 ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); 559 ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
@@ -579,16 +576,7 @@ xfs_zero_eof(
579 } 576 }
580 577
581 /* 578 /*
582 * There are blocks in the range requested. 579 * There are blocks we need to zero.
583 * Zero them a single write at a time. We actually
584 * don't zero the entire range returned if it is
585 * too big and simply loop around to get the rest.
586 * That is not the most efficient thing to do, but it
587 * is simple and this path should not be exercised often.
588 */
589 buf_len_fsb = XFS_FILBLKS_MIN(imap.br_blockcount,
590 mp->m_writeio_blocks << 8);
591 /*
592 * Drop the inode lock while we're doing the I/O. 580 * Drop the inode lock while we're doing the I/O.
593 * We'll still have the iolock to protect us. 581 * We'll still have the iolock to protect us.
594 */ 582 */
@@ -596,14 +584,13 @@ xfs_zero_eof(
596 584
597 error = xfs_iozero(ip, 585 error = xfs_iozero(ip,
598 XFS_FSB_TO_B(mp, start_zero_fsb), 586 XFS_FSB_TO_B(mp, start_zero_fsb),
599 XFS_FSB_TO_B(mp, buf_len_fsb), 587 XFS_FSB_TO_B(mp, imap.br_blockcount),
600 end_size); 588 end_size);
601
602 if (error) { 589 if (error) {
603 goto out_lock; 590 goto out_lock;
604 } 591 }
605 592
606 start_zero_fsb = imap.br_startoff + buf_len_fsb; 593 start_zero_fsb = imap.br_startoff + imap.br_blockcount;
607 ASSERT(start_zero_fsb <= (end_zero_fsb + 1)); 594 ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
608 595
609 XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); 596 XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
@@ -637,11 +624,11 @@ xfs_write(
637 ssize_t ret = 0, error = 0; 624 ssize_t ret = 0, error = 0;
638 xfs_fsize_t isize, new_size; 625 xfs_fsize_t isize, new_size;
639 xfs_iocore_t *io; 626 xfs_iocore_t *io;
640 vnode_t *vp; 627 bhv_vnode_t *vp;
641 unsigned long seg; 628 unsigned long seg;
642 int iolock; 629 int iolock;
643 int eventsent = 0; 630 int eventsent = 0;
644 vrwlock_t locktype; 631 bhv_vrwlock_t locktype;
645 size_t ocount = 0, count; 632 size_t ocount = 0, count;
646 loff_t pos; 633 loff_t pos;
647 int need_i_mutex = 1, need_flush = 0; 634 int need_i_mutex = 1, need_flush = 0;
@@ -679,11 +666,11 @@ xfs_write(
679 io = &xip->i_iocore; 666 io = &xip->i_iocore;
680 mp = io->io_mount; 667 mp = io->io_mount;
681 668
669 vfs_wait_for_freeze(vp->v_vfsp, SB_FREEZE_WRITE);
670
682 if (XFS_FORCED_SHUTDOWN(mp)) 671 if (XFS_FORCED_SHUTDOWN(mp))
683 return -EIO; 672 return -EIO;
684 673
685 fs_check_frozen(vp->v_vfsp, SB_FREEZE_WRITE);
686
687 if (ioflags & IO_ISDIRECT) { 674 if (ioflags & IO_ISDIRECT) {
688 xfs_buftarg_t *target = 675 xfs_buftarg_t *target =
689 (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? 676 (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
@@ -814,7 +801,7 @@ retry:
814 if (need_flush) { 801 if (need_flush) {
815 xfs_inval_cached_trace(io, pos, -1, 802 xfs_inval_cached_trace(io, pos, -1,
816 ctooff(offtoct(pos)), -1); 803 ctooff(offtoct(pos)), -1);
817 VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(pos)), 804 bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)),
818 -1, FI_REMAPF_LOCKED); 805 -1, FI_REMAPF_LOCKED);
819 } 806 }
820 807
@@ -903,79 +890,9 @@ retry:
903 890
904 /* Handle various SYNC-type writes */ 891 /* Handle various SYNC-type writes */
905 if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { 892 if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
906 /* 893 error = xfs_write_sync_logforce(mp, xip);
907 * If we're treating this as O_DSYNC and we have not updated the 894 if (error)
908 * size, force the log. 895 goto out_unlock_internal;
909 */
910 if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) &&
911 !(xip->i_update_size)) {
912 xfs_inode_log_item_t *iip = xip->i_itemp;
913
914 /*
915 * If an allocation transaction occurred
916 * without extending the size, then we have to force
917 * the log up the proper point to ensure that the
918 * allocation is permanent. We can't count on
919 * the fact that buffered writes lock out direct I/O
920 * writes - the direct I/O write could have extended
921 * the size nontransactionally, then finished before
922 * we started. xfs_write_file will think that the file
923 * didn't grow but the update isn't safe unless the
924 * size change is logged.
925 *
926 * Force the log if we've committed a transaction
927 * against the inode or if someone else has and
928 * the commit record hasn't gone to disk (e.g.
929 * the inode is pinned). This guarantees that
930 * all changes affecting the inode are permanent
931 * when we return.
932 */
933 if (iip && iip->ili_last_lsn) {
934 xfs_log_force(mp, iip->ili_last_lsn,
935 XFS_LOG_FORCE | XFS_LOG_SYNC);
936 } else if (xfs_ipincount(xip) > 0) {
937 xfs_log_force(mp, (xfs_lsn_t)0,
938 XFS_LOG_FORCE | XFS_LOG_SYNC);
939 }
940
941 } else {
942 xfs_trans_t *tp;
943
944 /*
945 * O_SYNC or O_DSYNC _with_ a size update are handled
946 * the same way.
947 *
948 * If the write was synchronous then we need to make
949 * sure that the inode modification time is permanent.
950 * We'll have updated the timestamp above, so here
951 * we use a synchronous transaction to log the inode.
952 * It's not fast, but it's necessary.
953 *
954 * If this a dsync write and the size got changed
955 * non-transactionally, then we need to ensure that
956 * the size change gets logged in a synchronous
957 * transaction.
958 */
959
960 tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC);
961 if ((error = xfs_trans_reserve(tp, 0,
962 XFS_SWRITE_LOG_RES(mp),
963 0, 0, 0))) {
964 /* Transaction reserve failed */
965 xfs_trans_cancel(tp, 0);
966 } else {
967 /* Transaction reserve successful */
968 xfs_ilock(xip, XFS_ILOCK_EXCL);
969 xfs_trans_ijoin(tp, xip, XFS_ILOCK_EXCL);
970 xfs_trans_ihold(tp, xip);
971 xfs_trans_log_inode(tp, xip, XFS_ILOG_CORE);
972 xfs_trans_set_sync(tp);
973 error = xfs_trans_commit(tp, 0, NULL);
974 xfs_iunlock(xip, XFS_ILOCK_EXCL);
975 }
976 if (error)
977 goto out_unlock_internal;
978 }
979 896
980 xfs_rwunlock(bdp, locktype); 897 xfs_rwunlock(bdp, locktype);
981 if (need_i_mutex) 898 if (need_i_mutex)
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index 8f4539952350..c77e62efb742 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -18,8 +18,8 @@
18#ifndef __XFS_LRW_H__ 18#ifndef __XFS_LRW_H__
19#define __XFS_LRW_H__ 19#define __XFS_LRW_H__
20 20
21struct vnode;
22struct bhv_desc; 21struct bhv_desc;
22struct bhv_vnode;
23struct xfs_mount; 23struct xfs_mount;
24struct xfs_iocore; 24struct xfs_iocore;
25struct xfs_inode; 25struct xfs_inode;
@@ -49,7 +49,7 @@ struct xfs_iomap;
49#define XFS_CTRUNC4 14 49#define XFS_CTRUNC4 14
50#define XFS_CTRUNC5 15 50#define XFS_CTRUNC5 15
51#define XFS_CTRUNC6 16 51#define XFS_CTRUNC6 16
52#define XFS_BUNMAPI 17 52#define XFS_BUNMAP 17
53#define XFS_INVAL_CACHED 18 53#define XFS_INVAL_CACHED 18
54#define XFS_DIORD_ENTER 19 54#define XFS_DIORD_ENTER 19
55#define XFS_DIOWR_ENTER 20 55#define XFS_DIOWR_ENTER 20
@@ -82,7 +82,7 @@ extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
82extern int xfs_bdstrat_cb(struct xfs_buf *); 82extern int xfs_bdstrat_cb(struct xfs_buf *);
83extern int xfs_dev_is_read_only(struct xfs_mount *, char *); 83extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
84 84
85extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t, 85extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t,
86 xfs_fsize_t, xfs_fsize_t); 86 xfs_fsize_t, xfs_fsize_t);
87extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *, 87extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
88 const struct iovec *, unsigned int, 88 const struct iovec *, unsigned int,
diff --git a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/linux-2.6/xfs_stats.c
index 1f0589a05eca..e480b6102051 100644
--- a/fs/xfs/linux-2.6/xfs_stats.c
+++ b/fs/xfs/linux-2.6/xfs_stats.c
@@ -62,7 +62,7 @@ xfs_read_xfsstats(
62 while (j < xstats[i].endpoint) { 62 while (j < xstats[i].endpoint) {
63 val = 0; 63 val = 0;
64 /* sum over all cpus */ 64 /* sum over all cpus */
65 for_each_cpu(c) 65 for_each_possible_cpu(c)
66 val += *(((__u32*)&per_cpu(xfsstats, c) + j)); 66 val += *(((__u32*)&per_cpu(xfsstats, c) + j));
67 len += sprintf(buffer + len, " %u", val); 67 len += sprintf(buffer + len, " %u", val);
68 j++; 68 j++;
@@ -70,7 +70,7 @@ xfs_read_xfsstats(
70 buffer[len++] = '\n'; 70 buffer[len++] = '\n';
71 } 71 }
72 /* extra precision counters */ 72 /* extra precision counters */
73 for_each_cpu(i) { 73 for_each_possible_cpu(i) {
74 xs_xstrat_bytes += per_cpu(xfsstats, i).xs_xstrat_bytes; 74 xs_xstrat_bytes += per_cpu(xfsstats, i).xs_xstrat_bytes;
75 xs_write_bytes += per_cpu(xfsstats, i).xs_write_bytes; 75 xs_write_bytes += per_cpu(xfsstats, i).xs_write_bytes;
76 xs_read_bytes += per_cpu(xfsstats, i).xs_read_bytes; 76 xs_read_bytes += per_cpu(xfsstats, i).xs_read_bytes;
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 68f4793e8a11..9bdef9d51900 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
@@ -151,7 +149,7 @@ xfs_set_inodeops(
151STATIC __inline__ void 149STATIC __inline__ void
152xfs_revalidate_inode( 150xfs_revalidate_inode(
153 xfs_mount_t *mp, 151 xfs_mount_t *mp,
154 vnode_t *vp, 152 bhv_vnode_t *vp,
155 xfs_inode_t *ip) 153 xfs_inode_t *ip)
156{ 154{
157 struct inode *inode = vn_to_inode(vp); 155 struct inode *inode = vn_to_inode(vp);
@@ -206,7 +204,7 @@ xfs_revalidate_inode(
206void 204void
207xfs_initialize_vnode( 205xfs_initialize_vnode(
208 bhv_desc_t *bdp, 206 bhv_desc_t *bdp,
209 vnode_t *vp, 207 bhv_vnode_t *vp,
210 bhv_desc_t *inode_bhv, 208 bhv_desc_t *inode_bhv,
211 int unlock) 209 int unlock)
212{ 210{
@@ -336,7 +334,7 @@ STATIC struct inode *
336xfs_fs_alloc_inode( 334xfs_fs_alloc_inode(
337 struct super_block *sb) 335 struct super_block *sb)
338{ 336{
339 vnode_t *vp; 337 bhv_vnode_t *vp;
340 338
341 vp = kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP); 339 vp = kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP);
342 if (unlikely(!vp)) 340 if (unlikely(!vp))
@@ -359,13 +357,13 @@ xfs_fs_inode_init_once(
359{ 357{
360 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == 358 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
361 SLAB_CTOR_CONSTRUCTOR) 359 SLAB_CTOR_CONSTRUCTOR)
362 inode_init_once(vn_to_inode((vnode_t *)vnode)); 360 inode_init_once(vn_to_inode((bhv_vnode_t *)vnode));
363} 361}
364 362
365STATIC int 363STATIC int
366xfs_init_zones(void) 364xfs_init_zones(void)
367{ 365{
368 xfs_vnode_zone = kmem_zone_init_flags(sizeof(vnode_t), "xfs_vnode_t", 366 xfs_vnode_zone = kmem_zone_init_flags(sizeof(bhv_vnode_t), "xfs_vnode",
369 KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | 367 KM_ZONE_HWALIGN | KM_ZONE_RECLAIM |
370 KM_ZONE_SPREAD, 368 KM_ZONE_SPREAD,
371 xfs_fs_inode_init_once); 369 xfs_fs_inode_init_once);
@@ -409,22 +407,17 @@ xfs_fs_write_inode(
409 struct inode *inode, 407 struct inode *inode,
410 int sync) 408 int sync)
411{ 409{
412 vnode_t *vp = vn_from_inode(inode); 410 bhv_vnode_t *vp = vn_from_inode(inode);
413 int error = 0, flags = FLUSH_INODE; 411 int error = 0, flags = FLUSH_INODE;
414 412
415 if (vp) { 413 if (vp) {
416 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); 414 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
417 if (sync) 415 if (sync)
418 flags |= FLUSH_SYNC; 416 flags |= FLUSH_SYNC;
419 VOP_IFLUSH(vp, flags, error); 417 error = bhv_vop_iflush(vp, flags);
420 if (error == EAGAIN) { 418 if (error == EAGAIN)
421 if (sync) 419 error = sync? bhv_vop_iflush(vp, flags | FLUSH_LOG) : 0;
422 VOP_IFLUSH(vp, flags | FLUSH_LOG, error);
423 else
424 error = 0;
425 }
426 } 420 }
427
428 return -error; 421 return -error;
429} 422}
430 423
@@ -432,8 +425,7 @@ STATIC void
432xfs_fs_clear_inode( 425xfs_fs_clear_inode(
433 struct inode *inode) 426 struct inode *inode)
434{ 427{
435 vnode_t *vp = vn_from_inode(inode); 428 bhv_vnode_t *vp = vn_from_inode(inode);
436 int error, cache;
437 429
438 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); 430 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
439 431
@@ -446,20 +438,18 @@ xfs_fs_clear_inode(
446 * This can happen because xfs_iget_core calls xfs_idestroy if we 438 * This can happen because xfs_iget_core calls xfs_idestroy if we
447 * find an inode with di_mode == 0 but without IGET_CREATE set. 439 * find an inode with di_mode == 0 but without IGET_CREATE set.
448 */ 440 */
449 if (vp->v_fbhv) 441 if (VNHEAD(vp))
450 VOP_INACTIVE(vp, NULL, cache); 442 bhv_vop_inactive(vp, NULL);
451 443
452 VN_LOCK(vp); 444 VN_LOCK(vp);
453 vp->v_flag &= ~VMODIFIED; 445 vp->v_flag &= ~VMODIFIED;
454 VN_UNLOCK(vp, 0); 446 VN_UNLOCK(vp, 0);
455 447
456 if (vp->v_fbhv) { 448 if (VNHEAD(vp))
457 VOP_RECLAIM(vp, error); 449 if (bhv_vop_reclaim(vp))
458 if (error) 450 panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, vp);
459 panic("vn_purge: cannot reclaim");
460 }
461 451
462 ASSERT(vp->v_fbhv == NULL); 452 ASSERT(VNHEAD(vp) == NULL);
463 453
464#ifdef XFS_VNODE_TRACE 454#ifdef XFS_VNODE_TRACE
465 ktrace_free(vp->v_trace); 455 ktrace_free(vp->v_trace);
@@ -475,13 +465,13 @@ xfs_fs_clear_inode(
475 */ 465 */
476STATIC void 466STATIC void
477xfs_syncd_queue_work( 467xfs_syncd_queue_work(
478 struct vfs *vfs, 468 struct bhv_vfs *vfs,
479 void *data, 469 void *data,
480 void (*syncer)(vfs_t *, void *)) 470 void (*syncer)(bhv_vfs_t *, void *))
481{ 471{
482 vfs_sync_work_t *work; 472 struct bhv_vfs_sync_work *work;
483 473
484 work = kmem_alloc(sizeof(struct vfs_sync_work), KM_SLEEP); 474 work = kmem_alloc(sizeof(struct bhv_vfs_sync_work), KM_SLEEP);
485 INIT_LIST_HEAD(&work->w_list); 475 INIT_LIST_HEAD(&work->w_list);
486 work->w_syncer = syncer; 476 work->w_syncer = syncer;
487 work->w_data = data; 477 work->w_data = data;
@@ -500,7 +490,7 @@ xfs_syncd_queue_work(
500 */ 490 */
501STATIC void 491STATIC void
502xfs_flush_inode_work( 492xfs_flush_inode_work(
503 vfs_t *vfs, 493 bhv_vfs_t *vfs,
504 void *inode) 494 void *inode)
505{ 495{
506 filemap_flush(((struct inode *)inode)->i_mapping); 496 filemap_flush(((struct inode *)inode)->i_mapping);
@@ -512,7 +502,7 @@ xfs_flush_inode(
512 xfs_inode_t *ip) 502 xfs_inode_t *ip)
513{ 503{
514 struct inode *inode = vn_to_inode(XFS_ITOV(ip)); 504 struct inode *inode = vn_to_inode(XFS_ITOV(ip));
515 struct vfs *vfs = XFS_MTOVFS(ip->i_mount); 505 struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount);
516 506
517 igrab(inode); 507 igrab(inode);
518 xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work); 508 xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work);
@@ -525,7 +515,7 @@ xfs_flush_inode(
525 */ 515 */
526STATIC void 516STATIC void
527xfs_flush_device_work( 517xfs_flush_device_work(
528 vfs_t *vfs, 518 bhv_vfs_t *vfs,
529 void *inode) 519 void *inode)
530{ 520{
531 sync_blockdev(vfs->vfs_super->s_bdev); 521 sync_blockdev(vfs->vfs_super->s_bdev);
@@ -537,7 +527,7 @@ xfs_flush_device(
537 xfs_inode_t *ip) 527 xfs_inode_t *ip)
538{ 528{
539 struct inode *inode = vn_to_inode(XFS_ITOV(ip)); 529 struct inode *inode = vn_to_inode(XFS_ITOV(ip));
540 struct vfs *vfs = XFS_MTOVFS(ip->i_mount); 530 struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount);
541 531
542 igrab(inode); 532 igrab(inode);
543 xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work); 533 xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work);
@@ -545,16 +535,16 @@ xfs_flush_device(
545 xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); 535 xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
546} 536}
547 537
548#define SYNCD_FLAGS (SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR|SYNC_REFCACHE)
549STATIC void 538STATIC void
550vfs_sync_worker( 539vfs_sync_worker(
551 vfs_t *vfsp, 540 bhv_vfs_t *vfsp,
552 void *unused) 541 void *unused)
553{ 542{
554 int error; 543 int error;
555 544
556 if (!(vfsp->vfs_flag & VFS_RDONLY)) 545 if (!(vfsp->vfs_flag & VFS_RDONLY))
557 VFS_SYNC(vfsp, SYNCD_FLAGS, NULL, error); 546 error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \
547 SYNC_ATTR | SYNC_REFCACHE, NULL);
558 vfsp->vfs_sync_seq++; 548 vfsp->vfs_sync_seq++;
559 wmb(); 549 wmb();
560 wake_up(&vfsp->vfs_wait_single_sync_task); 550 wake_up(&vfsp->vfs_wait_single_sync_task);
@@ -565,8 +555,8 @@ xfssyncd(
565 void *arg) 555 void *arg)
566{ 556{
567 long timeleft; 557 long timeleft;
568 vfs_t *vfsp = (vfs_t *) arg; 558 bhv_vfs_t *vfsp = (bhv_vfs_t *) arg;
569 struct vfs_sync_work *work, *n; 559 bhv_vfs_sync_work_t *work, *n;
570 LIST_HEAD (tmp); 560 LIST_HEAD (tmp);
571 561
572 timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10); 562 timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
@@ -600,7 +590,7 @@ xfssyncd(
600 list_del(&work->w_list); 590 list_del(&work->w_list);
601 if (work == &vfsp->vfs_sync_work) 591 if (work == &vfsp->vfs_sync_work)
602 continue; 592 continue;
603 kmem_free(work, sizeof(struct vfs_sync_work)); 593 kmem_free(work, sizeof(struct bhv_vfs_sync_work));
604 } 594 }
605 } 595 }
606 596
@@ -609,7 +599,7 @@ xfssyncd(
609 599
610STATIC int 600STATIC int
611xfs_fs_start_syncd( 601xfs_fs_start_syncd(
612 vfs_t *vfsp) 602 bhv_vfs_t *vfsp)
613{ 603{
614 vfsp->vfs_sync_work.w_syncer = vfs_sync_worker; 604 vfsp->vfs_sync_work.w_syncer = vfs_sync_worker;
615 vfsp->vfs_sync_work.w_vfs = vfsp; 605 vfsp->vfs_sync_work.w_vfs = vfsp;
@@ -621,7 +611,7 @@ xfs_fs_start_syncd(
621 611
622STATIC void 612STATIC void
623xfs_fs_stop_syncd( 613xfs_fs_stop_syncd(
624 vfs_t *vfsp) 614 bhv_vfs_t *vfsp)
625{ 615{
626 kthread_stop(vfsp->vfs_sync_task); 616 kthread_stop(vfsp->vfs_sync_task);
627} 617}
@@ -630,35 +620,26 @@ STATIC void
630xfs_fs_put_super( 620xfs_fs_put_super(
631 struct super_block *sb) 621 struct super_block *sb)
632{ 622{
633 vfs_t *vfsp = vfs_from_sb(sb); 623 bhv_vfs_t *vfsp = vfs_from_sb(sb);
634 int error; 624 int error;
635 625
636 xfs_fs_stop_syncd(vfsp); 626 xfs_fs_stop_syncd(vfsp);
637 VFS_SYNC(vfsp, SYNC_ATTR|SYNC_DELWRI, NULL, error); 627 bhv_vfs_sync(vfsp, SYNC_ATTR | SYNC_DELWRI, NULL);
638 if (!error) 628 error = bhv_vfs_unmount(vfsp, 0, NULL);
639 VFS_UNMOUNT(vfsp, 0, NULL, error);
640 if (error) { 629 if (error) {
641 printk("XFS unmount got error %d\n", error); 630 printk("XFS: unmount got error=%d\n", error);
642 printk("%s: vfsp/0x%p left dangling!\n", __FUNCTION__, vfsp); 631 printk("%s: vfs=0x%p left dangling!\n", __FUNCTION__, vfsp);
643 return; 632 } else {
633 vfs_deallocate(vfsp);
644 } 634 }
645
646 vfs_deallocate(vfsp);
647} 635}
648 636
649STATIC void 637STATIC void
650xfs_fs_write_super( 638xfs_fs_write_super(
651 struct super_block *sb) 639 struct super_block *sb)
652{ 640{
653 vfs_t *vfsp = vfs_from_sb(sb); 641 if (!(sb->s_flags & MS_RDONLY))
654 int error; 642 bhv_vfs_sync(vfs_from_sb(sb), SYNC_FSDATA, NULL);
655
656 if (sb->s_flags & MS_RDONLY) {
657 sb->s_dirt = 0; /* paranoia */
658 return;
659 }
660 /* Push the log and superblock a little */
661 VFS_SYNC(vfsp, SYNC_FSDATA, NULL, error);
662 sb->s_dirt = 0; 643 sb->s_dirt = 0;
663} 644}
664 645
@@ -667,16 +648,16 @@ xfs_fs_sync_super(
667 struct super_block *sb, 648 struct super_block *sb,
668 int wait) 649 int wait)
669{ 650{
670 vfs_t *vfsp = vfs_from_sb(sb); 651 bhv_vfs_t *vfsp = vfs_from_sb(sb);
671 int error; 652 int error;
672 int flags = SYNC_FSDATA; 653 int flags;
673 654
674 if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) 655 if (unlikely(sb->s_frozen == SB_FREEZE_WRITE))
675 flags = SYNC_QUIESCE; 656 flags = SYNC_QUIESCE;
676 else 657 else
677 flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0); 658 flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
678 659
679 VFS_SYNC(vfsp, flags, NULL, error); 660 error = bhv_vfs_sync(vfsp, flags, NULL);
680 sb->s_dirt = 0; 661 sb->s_dirt = 0;
681 662
682 if (unlikely(laptop_mode)) { 663 if (unlikely(laptop_mode)) {
@@ -703,14 +684,11 @@ xfs_fs_sync_super(
703 684
704STATIC int 685STATIC int
705xfs_fs_statfs( 686xfs_fs_statfs(
706 struct super_block *sb, 687 struct dentry *dentry,
707 struct kstatfs *statp) 688 struct kstatfs *statp)
708{ 689{
709 vfs_t *vfsp = vfs_from_sb(sb); 690 return -bhv_vfs_statvfs(vfs_from_sb(dentry->d_sb), statp,
710 int error; 691 vn_from_inode(dentry->d_inode));
711
712 VFS_STATVFS(vfsp, statp, NULL, error);
713 return -error;
714} 692}
715 693
716STATIC int 694STATIC int
@@ -719,13 +697,13 @@ xfs_fs_remount(
719 int *flags, 697 int *flags,
720 char *options) 698 char *options)
721{ 699{
722 vfs_t *vfsp = vfs_from_sb(sb); 700 bhv_vfs_t *vfsp = vfs_from_sb(sb);
723 struct xfs_mount_args *args = xfs_args_allocate(sb, 0); 701 struct xfs_mount_args *args = xfs_args_allocate(sb, 0);
724 int error; 702 int error;
725 703
726 VFS_PARSEARGS(vfsp, options, args, 1, error); 704 error = bhv_vfs_parseargs(vfsp, options, args, 1);
727 if (!error) 705 if (!error)
728 VFS_MNTUPDATE(vfsp, flags, args, error); 706 error = bhv_vfs_mntupdate(vfsp, flags, args);
729 kmem_free(args, sizeof(*args)); 707 kmem_free(args, sizeof(*args));
730 return -error; 708 return -error;
731} 709}
@@ -734,7 +712,7 @@ STATIC void
734xfs_fs_lockfs( 712xfs_fs_lockfs(
735 struct super_block *sb) 713 struct super_block *sb)
736{ 714{
737 VFS_FREEZE(vfs_from_sb(sb)); 715 bhv_vfs_freeze(vfs_from_sb(sb));
738} 716}
739 717
740STATIC int 718STATIC int
@@ -742,11 +720,7 @@ xfs_fs_show_options(
742 struct seq_file *m, 720 struct seq_file *m,
743 struct vfsmount *mnt) 721 struct vfsmount *mnt)
744{ 722{
745 struct vfs *vfsp = vfs_from_sb(mnt->mnt_sb); 723 return -bhv_vfs_showargs(vfs_from_sb(mnt->mnt_sb), m);
746 int error;
747
748 VFS_SHOWARGS(vfsp, m, error);
749 return error;
750} 724}
751 725
752STATIC int 726STATIC int
@@ -754,11 +728,7 @@ xfs_fs_quotasync(
754 struct super_block *sb, 728 struct super_block *sb,
755 int type) 729 int type)
756{ 730{
757 struct vfs *vfsp = vfs_from_sb(sb); 731 return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XQUOTASYNC, 0, NULL);
758 int error;
759
760 VFS_QUOTACTL(vfsp, Q_XQUOTASYNC, 0, (caddr_t)NULL, error);
761 return -error;
762} 732}
763 733
764STATIC int 734STATIC int
@@ -766,11 +736,7 @@ xfs_fs_getxstate(
766 struct super_block *sb, 736 struct super_block *sb,
767 struct fs_quota_stat *fqs) 737 struct fs_quota_stat *fqs)
768{ 738{
769 struct vfs *vfsp = vfs_from_sb(sb); 739 return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XGETQSTAT, 0, (caddr_t)fqs);
770 int error;
771
772 VFS_QUOTACTL(vfsp, Q_XGETQSTAT, 0, (caddr_t)fqs, error);
773 return -error;
774} 740}
775 741
776STATIC int 742STATIC int
@@ -779,11 +745,7 @@ xfs_fs_setxstate(
779 unsigned int flags, 745 unsigned int flags,
780 int op) 746 int op)
781{ 747{
782 struct vfs *vfsp = vfs_from_sb(sb); 748 return -bhv_vfs_quotactl(vfs_from_sb(sb), op, 0, (caddr_t)&flags);
783 int error;
784
785 VFS_QUOTACTL(vfsp, op, 0, (caddr_t)&flags, error);
786 return -error;
787} 749}
788 750
789STATIC int 751STATIC int
@@ -793,13 +755,10 @@ xfs_fs_getxquota(
793 qid_t id, 755 qid_t id,
794 struct fs_disk_quota *fdq) 756 struct fs_disk_quota *fdq)
795{ 757{
796 struct vfs *vfsp = vfs_from_sb(sb); 758 return -bhv_vfs_quotactl(vfs_from_sb(sb),
797 int error, getmode; 759 (type == USRQUOTA) ? Q_XGETQUOTA :
798 760 ((type == GRPQUOTA) ? Q_XGETGQUOTA :
799 getmode = (type == USRQUOTA) ? Q_XGETQUOTA : 761 Q_XGETPQUOTA), id, (caddr_t)fdq);
800 ((type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETPQUOTA);
801 VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error);
802 return -error;
803} 762}
804 763
805STATIC int 764STATIC int
@@ -809,13 +768,10 @@ xfs_fs_setxquota(
809 qid_t id, 768 qid_t id,
810 struct fs_disk_quota *fdq) 769 struct fs_disk_quota *fdq)
811{ 770{
812 struct vfs *vfsp = vfs_from_sb(sb); 771 return -bhv_vfs_quotactl(vfs_from_sb(sb),
813 int error, setmode; 772 (type == USRQUOTA) ? Q_XSETQLIM :
814 773 ((type == GRPQUOTA) ? Q_XSETGQLIM :
815 setmode = (type == USRQUOTA) ? Q_XSETQLIM : 774 Q_XSETPQLIM), id, (caddr_t)fdq);
816 ((type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETPQLIM);
817 VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error);
818 return -error;
819} 775}
820 776
821STATIC int 777STATIC int
@@ -824,34 +780,32 @@ xfs_fs_fill_super(
824 void *data, 780 void *data,
825 int silent) 781 int silent)
826{ 782{
827 vnode_t *rootvp; 783 struct bhv_vnode *rootvp;
828 struct vfs *vfsp = vfs_allocate(sb); 784 struct bhv_vfs *vfsp = vfs_allocate(sb);
829 struct xfs_mount_args *args = xfs_args_allocate(sb, silent); 785 struct xfs_mount_args *args = xfs_args_allocate(sb, silent);
830 struct kstatfs statvfs; 786 struct kstatfs statvfs;
831 int error, error2; 787 int error;
832 788
833 bhv_insert_all_vfsops(vfsp); 789 bhv_insert_all_vfsops(vfsp);
834 790
835 VFS_PARSEARGS(vfsp, (char *)data, args, 0, error); 791 error = bhv_vfs_parseargs(vfsp, (char *)data, args, 0);
836 if (error) { 792 if (error) {
837 bhv_remove_all_vfsops(vfsp, 1); 793 bhv_remove_all_vfsops(vfsp, 1);
838 goto fail_vfsop; 794 goto fail_vfsop;
839 } 795 }
840 796
841 sb_min_blocksize(sb, BBSIZE); 797 sb_min_blocksize(sb, BBSIZE);
842#ifdef CONFIG_XFS_EXPORT
843 sb->s_export_op = &xfs_export_operations; 798 sb->s_export_op = &xfs_export_operations;
844#endif
845 sb->s_qcop = &xfs_quotactl_operations; 799 sb->s_qcop = &xfs_quotactl_operations;
846 sb->s_op = &xfs_super_operations; 800 sb->s_op = &xfs_super_operations;
847 801
848 VFS_MOUNT(vfsp, args, NULL, error); 802 error = bhv_vfs_mount(vfsp, args, NULL);
849 if (error) { 803 if (error) {
850 bhv_remove_all_vfsops(vfsp, 1); 804 bhv_remove_all_vfsops(vfsp, 1);
851 goto fail_vfsop; 805 goto fail_vfsop;
852 } 806 }
853 807
854 VFS_STATVFS(vfsp, &statvfs, NULL, error); 808 error = bhv_vfs_statvfs(vfsp, &statvfs, NULL);
855 if (error) 809 if (error)
856 goto fail_unmount; 810 goto fail_unmount;
857 811
@@ -863,7 +817,7 @@ xfs_fs_fill_super(
863 sb->s_time_gran = 1; 817 sb->s_time_gran = 1;
864 set_posix_acl_flag(sb); 818 set_posix_acl_flag(sb);
865 819
866 VFS_ROOT(vfsp, &rootvp, error); 820 error = bhv_vfs_root(vfsp, &rootvp);
867 if (error) 821 if (error)
868 goto fail_unmount; 822 goto fail_unmount;
869 823
@@ -892,7 +846,7 @@ fail_vnrele:
892 } 846 }
893 847
894fail_unmount: 848fail_unmount:
895 VFS_UNMOUNT(vfsp, 0, NULL, error2); 849 bhv_vfs_unmount(vfsp, 0, NULL);
896 850
897fail_vfsop: 851fail_vfsop:
898 vfs_deallocate(vfsp); 852 vfs_deallocate(vfsp);
@@ -900,14 +854,16 @@ fail_vfsop:
900 return -error; 854 return -error;
901} 855}
902 856
903STATIC struct super_block * 857STATIC int
904xfs_fs_get_sb( 858xfs_fs_get_sb(
905 struct file_system_type *fs_type, 859 struct file_system_type *fs_type,
906 int flags, 860 int flags,
907 const char *dev_name, 861 const char *dev_name,
908 void *data) 862 void *data,
863 struct vfsmount *mnt)
909{ 864{
910 return get_sb_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super); 865 return get_sb_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super,
866 mnt);
911} 867}
912 868
913STATIC struct super_operations xfs_super_operations = { 869STATIC struct super_operations xfs_super_operations = {
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
index 376b96cb513a..33dd1ca13245 100644
--- a/fs/xfs/linux-2.6/xfs_super.h
+++ b/fs/xfs/linux-2.6/xfs_super.h
@@ -105,7 +105,7 @@ struct block_device;
105 105
106extern __uint64_t xfs_max_file_offset(unsigned int); 106extern __uint64_t xfs_max_file_offset(unsigned int);
107 107
108extern void xfs_initialize_vnode(bhv_desc_t *, vnode_t *, bhv_desc_t *, int); 108extern void xfs_initialize_vnode(bhv_desc_t *, bhv_vnode_t *, bhv_desc_t *, int);
109 109
110extern void xfs_flush_inode(struct xfs_inode *); 110extern void xfs_flush_inode(struct xfs_inode *);
111extern void xfs_flush_device(struct xfs_inode *); 111extern void xfs_flush_device(struct xfs_inode *);
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c
index 7079cc837210..af246532fbfb 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.c
+++ b/fs/xfs/linux-2.6/xfs_sysctl.c
@@ -38,7 +38,7 @@ xfs_stats_clear_proc_handler(
38 38
39 if (!ret && write && *valp) { 39 if (!ret && write && *valp) {
40 printk("XFS Clearing xfsstats\n"); 40 printk("XFS Clearing xfsstats\n");
41 for_each_cpu(c) { 41 for_each_possible_cpu(c) {
42 preempt_disable(); 42 preempt_disable();
43 /* save vn_active, it's a universal truth! */ 43 /* save vn_active, it's a universal truth! */
44 vn_active = per_cpu(xfsstats, c).vn_active; 44 vn_active = per_cpu(xfsstats, c).vn_active;
@@ -120,6 +120,11 @@ STATIC ctl_table xfs_table[] = {
120 &sysctl_intvec, NULL, 120 &sysctl_intvec, NULL,
121 &xfs_params.rotorstep.min, &xfs_params.rotorstep.max}, 121 &xfs_params.rotorstep.min, &xfs_params.rotorstep.max},
122 122
123 {XFS_INHERIT_NODFRG, "inherit_nodefrag", &xfs_params.inherit_nodfrg.val,
124 sizeof(int), 0644, NULL, &proc_dointvec_minmax,
125 &sysctl_intvec, NULL,
126 &xfs_params.inherit_nodfrg.min, &xfs_params.inherit_nodfrg.max},
127
123 /* please keep this the last entry */ 128 /* please keep this the last entry */
124#ifdef CONFIG_PROC_FS 129#ifdef CONFIG_PROC_FS
125 {XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val, 130 {XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val,
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.h b/fs/xfs/linux-2.6/xfs_sysctl.h
index bc8c11f13722..a631fb8cc5ac 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.h
+++ b/fs/xfs/linux-2.6/xfs_sysctl.h
@@ -46,6 +46,7 @@ typedef struct xfs_param {
46 xfs_sysctl_val_t xfs_buf_age; /* Metadata buffer age before flush. */ 46 xfs_sysctl_val_t xfs_buf_age; /* Metadata buffer age before flush. */
47 xfs_sysctl_val_t inherit_nosym; /* Inherit the "nosymlinks" flag. */ 47 xfs_sysctl_val_t inherit_nosym; /* Inherit the "nosymlinks" flag. */
48 xfs_sysctl_val_t rotorstep; /* inode32 AG rotoring control knob */ 48 xfs_sysctl_val_t rotorstep; /* inode32 AG rotoring control knob */
49 xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */
49} xfs_param_t; 50} xfs_param_t;
50 51
51/* 52/*
@@ -84,6 +85,7 @@ enum {
84 /* XFS_IO_BYPASS = 18 */ 85 /* XFS_IO_BYPASS = 18 */
85 XFS_INHERIT_NOSYM = 19, 86 XFS_INHERIT_NOSYM = 19,
86 XFS_ROTORSTEP = 20, 87 XFS_ROTORSTEP = 20,
88 XFS_INHERIT_NODFRG = 21,
87}; 89};
88 90
89extern xfs_param_t xfs_params; 91extern xfs_param_t xfs_params;
diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c
index 6f7c9f7a8624..6145e8bd0be2 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.c
+++ b/fs/xfs/linux-2.6/xfs_vfs.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_imap.h" 27#include "xfs_imap.h"
29#include "xfs_alloc.h" 28#include "xfs_alloc.h"
@@ -104,7 +103,7 @@ vfs_mntupdate(
104int 103int
105vfs_root( 104vfs_root(
106 struct bhv_desc *bdp, 105 struct bhv_desc *bdp,
107 struct vnode **vpp) 106 struct bhv_vnode **vpp)
108{ 107{
109 struct bhv_desc *next = bdp; 108 struct bhv_desc *next = bdp;
110 109
@@ -117,15 +116,15 @@ vfs_root(
117int 116int
118vfs_statvfs( 117vfs_statvfs(
119 struct bhv_desc *bdp, 118 struct bhv_desc *bdp,
120 xfs_statfs_t *sp, 119 bhv_statvfs_t *statp,
121 struct vnode *vp) 120 struct bhv_vnode *vp)
122{ 121{
123 struct bhv_desc *next = bdp; 122 struct bhv_desc *next = bdp;
124 123
125 ASSERT(next); 124 ASSERT(next);
126 while (! (bhvtovfsops(next))->vfs_statvfs) 125 while (! (bhvtovfsops(next))->vfs_statvfs)
127 next = BHV_NEXT(next); 126 next = BHV_NEXT(next);
128 return ((*bhvtovfsops(next)->vfs_statvfs)(next, sp, vp)); 127 return ((*bhvtovfsops(next)->vfs_statvfs)(next, statp, vp));
129} 128}
130 129
131int 130int
@@ -145,7 +144,7 @@ vfs_sync(
145int 144int
146vfs_vget( 145vfs_vget(
147 struct bhv_desc *bdp, 146 struct bhv_desc *bdp,
148 struct vnode **vpp, 147 struct bhv_vnode **vpp,
149 struct fid *fidp) 148 struct fid *fidp)
150{ 149{
151 struct bhv_desc *next = bdp; 150 struct bhv_desc *next = bdp;
@@ -187,7 +186,7 @@ vfs_quotactl(
187void 186void
188vfs_init_vnode( 187vfs_init_vnode(
189 struct bhv_desc *bdp, 188 struct bhv_desc *bdp,
190 struct vnode *vp, 189 struct bhv_vnode *vp,
191 struct bhv_desc *bp, 190 struct bhv_desc *bp,
192 int unlock) 191 int unlock)
193{ 192{
@@ -226,13 +225,13 @@ vfs_freeze(
226 ((*bhvtovfsops(next)->vfs_freeze)(next)); 225 ((*bhvtovfsops(next)->vfs_freeze)(next));
227} 226}
228 227
229vfs_t * 228bhv_vfs_t *
230vfs_allocate( 229vfs_allocate(
231 struct super_block *sb) 230 struct super_block *sb)
232{ 231{
233 struct vfs *vfsp; 232 struct bhv_vfs *vfsp;
234 233
235 vfsp = kmem_zalloc(sizeof(vfs_t), KM_SLEEP); 234 vfsp = kmem_zalloc(sizeof(bhv_vfs_t), KM_SLEEP);
236 bhv_head_init(VFS_BHVHEAD(vfsp), "vfs"); 235 bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
237 INIT_LIST_HEAD(&vfsp->vfs_sync_list); 236 INIT_LIST_HEAD(&vfsp->vfs_sync_list);
238 spin_lock_init(&vfsp->vfs_sync_lock); 237 spin_lock_init(&vfsp->vfs_sync_lock);
@@ -247,25 +246,25 @@ vfs_allocate(
247 return vfsp; 246 return vfsp;
248} 247}
249 248
250vfs_t * 249bhv_vfs_t *
251vfs_from_sb( 250vfs_from_sb(
252 struct super_block *sb) 251 struct super_block *sb)
253{ 252{
254 return (vfs_t *)sb->s_fs_info; 253 return (bhv_vfs_t *)sb->s_fs_info;
255} 254}
256 255
257void 256void
258vfs_deallocate( 257vfs_deallocate(
259 struct vfs *vfsp) 258 struct bhv_vfs *vfsp)
260{ 259{
261 bhv_head_destroy(VFS_BHVHEAD(vfsp)); 260 bhv_head_destroy(VFS_BHVHEAD(vfsp));
262 kmem_free(vfsp, sizeof(vfs_t)); 261 kmem_free(vfsp, sizeof(bhv_vfs_t));
263} 262}
264 263
265void 264void
266vfs_insertops( 265vfs_insertops(
267 struct vfs *vfsp, 266 struct bhv_vfs *vfsp,
268 struct bhv_vfsops *vfsops) 267 struct bhv_module_vfsops *vfsops)
269{ 268{
270 struct bhv_desc *bdp; 269 struct bhv_desc *bdp;
271 270
@@ -276,9 +275,9 @@ vfs_insertops(
276 275
277void 276void
278vfs_insertbhv( 277vfs_insertbhv(
279 struct vfs *vfsp, 278 struct bhv_vfs *vfsp,
280 struct bhv_desc *bdp, 279 struct bhv_desc *bdp,
281 struct vfsops *vfsops, 280 struct bhv_vfsops *vfsops,
282 void *mount) 281 void *mount)
283{ 282{
284 bhv_desc_init(bdp, mount, vfsp, vfsops); 283 bhv_desc_init(bdp, mount, vfsp, vfsops);
@@ -287,7 +286,7 @@ vfs_insertbhv(
287 286
288void 287void
289bhv_remove_vfsops( 288bhv_remove_vfsops(
290 struct vfs *vfsp, 289 struct bhv_vfs *vfsp,
291 int pos) 290 int pos)
292{ 291{
293 struct bhv_desc *bhv; 292 struct bhv_desc *bhv;
@@ -301,7 +300,7 @@ bhv_remove_vfsops(
301 300
302void 301void
303bhv_remove_all_vfsops( 302bhv_remove_all_vfsops(
304 struct vfs *vfsp, 303 struct bhv_vfs *vfsp,
305 int freebase) 304 int freebase)
306{ 305{
307 struct xfs_mount *mp; 306 struct xfs_mount *mp;
@@ -317,7 +316,7 @@ bhv_remove_all_vfsops(
317 316
318void 317void
319bhv_insert_all_vfsops( 318bhv_insert_all_vfsops(
320 struct vfs *vfsp) 319 struct bhv_vfs *vfsp)
321{ 320{
322 struct xfs_mount *mp; 321 struct xfs_mount *mp;
323 322
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index 841200c03092..91fc2c4b3353 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -21,42 +21,40 @@
21#include <linux/vfs.h> 21#include <linux/vfs.h>
22#include "xfs_fs.h" 22#include "xfs_fs.h"
23 23
24struct bhv_vfs;
25struct bhv_vnode;
26
24struct fid; 27struct fid;
25struct vfs;
26struct cred; 28struct cred;
27struct vnode;
28struct kstatfs;
29struct seq_file; 29struct seq_file;
30struct super_block; 30struct super_block;
31struct xfs_mount_args; 31struct xfs_mount_args;
32 32
33typedef struct kstatfs xfs_statfs_t; 33typedef struct kstatfs bhv_statvfs_t;
34 34
35typedef struct vfs_sync_work { 35typedef struct bhv_vfs_sync_work {
36 struct list_head w_list; 36 struct list_head w_list;
37 struct vfs *w_vfs; 37 struct bhv_vfs *w_vfs;
38 void *w_data; /* syncer routine argument */ 38 void *w_data; /* syncer routine argument */
39 void (*w_syncer)(struct vfs *, void *); 39 void (*w_syncer)(struct bhv_vfs *, void *);
40} vfs_sync_work_t; 40} bhv_vfs_sync_work_t;
41 41
42typedef struct vfs { 42typedef struct bhv_vfs {
43 u_int vfs_flag; /* flags */ 43 u_int vfs_flag; /* flags */
44 xfs_fsid_t vfs_fsid; /* file system ID */ 44 xfs_fsid_t vfs_fsid; /* file system ID */
45 xfs_fsid_t *vfs_altfsid; /* An ID fixed for life of FS */ 45 xfs_fsid_t *vfs_altfsid; /* An ID fixed for life of FS */
46 bhv_head_t vfs_bh; /* head of vfs behavior chain */ 46 bhv_head_t vfs_bh; /* head of vfs behavior chain */
47 struct super_block *vfs_super; /* generic superblock pointer */ 47 struct super_block *vfs_super; /* generic superblock pointer */
48 struct task_struct *vfs_sync_task; /* generalised sync thread */ 48 struct task_struct *vfs_sync_task; /* generalised sync thread */
49 vfs_sync_work_t vfs_sync_work; /* work item for VFS_SYNC */ 49 bhv_vfs_sync_work_t vfs_sync_work; /* work item for VFS_SYNC */
50 struct list_head vfs_sync_list; /* sync thread work item list */ 50 struct list_head vfs_sync_list; /* sync thread work item list */
51 spinlock_t vfs_sync_lock; /* work item list lock */ 51 spinlock_t vfs_sync_lock; /* work item list lock */
52 int vfs_sync_seq; /* sync thread generation no. */ 52 int vfs_sync_seq; /* sync thread generation no. */
53 wait_queue_head_t vfs_wait_single_sync_task; 53 wait_queue_head_t vfs_wait_single_sync_task;
54} vfs_t; 54} bhv_vfs_t;
55
56#define vfs_fbhv vfs_bh.bh_first /* 1st on vfs behavior chain */
57 55
58#define bhvtovfs(bdp) ( (struct vfs *)BHV_VOBJ(bdp) ) 56#define bhvtovfs(bdp) ( (struct bhv_vfs *)BHV_VOBJ(bdp) )
59#define bhvtovfsops(bdp) ( (struct vfsops *)BHV_OPS(bdp) ) 57#define bhvtovfsops(bdp) ( (struct bhv_vfsops *)BHV_OPS(bdp) )
60#define VFS_BHVHEAD(vfs) ( &(vfs)->vfs_bh ) 58#define VFS_BHVHEAD(vfs) ( &(vfs)->vfs_bh )
61#define VFS_REMOVEBHV(vfs, bdp) ( bhv_remove(VFS_BHVHEAD(vfs), bdp) ) 59#define VFS_REMOVEBHV(vfs, bdp) ( bhv_remove(VFS_BHVHEAD(vfs), bdp) )
62 60
@@ -71,7 +69,7 @@ typedef enum {
71 VFS_BHV_QM, /* quota manager */ 69 VFS_BHV_QM, /* quota manager */
72 VFS_BHV_IO, /* IO path */ 70 VFS_BHV_IO, /* IO path */
73 VFS_BHV_END /* housekeeping end-of-range */ 71 VFS_BHV_END /* housekeeping end-of-range */
74} vfs_bhv_t; 72} bhv_vfs_type_t;
75 73
76#define VFS_POSITION_XFS (BHV_POSITION_BASE) 74#define VFS_POSITION_XFS (BHV_POSITION_BASE)
77#define VFS_POSITION_DM (VFS_POSITION_BASE+10) 75#define VFS_POSITION_DM (VFS_POSITION_BASE+10)
@@ -81,8 +79,9 @@ typedef enum {
81#define VFS_RDONLY 0x0001 /* read-only vfs */ 79#define VFS_RDONLY 0x0001 /* read-only vfs */
82#define VFS_GRPID 0x0002 /* group-ID assigned from directory */ 80#define VFS_GRPID 0x0002 /* group-ID assigned from directory */
83#define VFS_DMI 0x0004 /* filesystem has the DMI enabled */ 81#define VFS_DMI 0x0004 /* filesystem has the DMI enabled */
84#define VFS_32BITINODES 0x0008 /* do not use inums above 32 bits */ 82#define VFS_UMOUNT 0x0008 /* unmount in progress */
85#define VFS_END 0x0008 /* max flag */ 83#define VFS_32BITINODES 0x0010 /* do not use inums above 32 bits */
84#define VFS_END 0x0010 /* max flag */
86 85
87#define SYNC_ATTR 0x0001 /* sync attributes */ 86#define SYNC_ATTR 0x0001 /* sync attributes */
88#define SYNC_CLOSE 0x0002 /* close file system down */ 87#define SYNC_CLOSE 0x0002 /* close file system down */
@@ -92,7 +91,14 @@ typedef enum {
92#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */ 91#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */
93#define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */ 92#define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */
94#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */ 93#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
95#define SYNC_QUIESCE 0x0100 /* quiesce filesystem for a snapshot */ 94#define SYNC_QUIESCE 0x0100 /* quiesce fileystem for a snapshot */
95
96#define SHUTDOWN_META_IO_ERROR 0x0001 /* write attempt to metadata failed */
97#define SHUTDOWN_LOG_IO_ERROR 0x0002 /* write attempt to the log failed */
98#define SHUTDOWN_FORCE_UMOUNT 0x0004 /* shutdown from a forced unmount */
99#define SHUTDOWN_CORRUPT_INCORE 0x0008 /* corrupt in-memory data structures */
100#define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */
101#define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */
96 102
97typedef int (*vfs_mount_t)(bhv_desc_t *, 103typedef int (*vfs_mount_t)(bhv_desc_t *,
98 struct xfs_mount_args *, struct cred *); 104 struct xfs_mount_args *, struct cred *);
@@ -102,18 +108,19 @@ typedef int (*vfs_showargs_t)(bhv_desc_t *, struct seq_file *);
102typedef int (*vfs_unmount_t)(bhv_desc_t *, int, struct cred *); 108typedef int (*vfs_unmount_t)(bhv_desc_t *, int, struct cred *);
103typedef int (*vfs_mntupdate_t)(bhv_desc_t *, int *, 109typedef int (*vfs_mntupdate_t)(bhv_desc_t *, int *,
104 struct xfs_mount_args *); 110 struct xfs_mount_args *);
105typedef int (*vfs_root_t)(bhv_desc_t *, struct vnode **); 111typedef int (*vfs_root_t)(bhv_desc_t *, struct bhv_vnode **);
106typedef int (*vfs_statvfs_t)(bhv_desc_t *, xfs_statfs_t *, struct vnode *); 112typedef int (*vfs_statvfs_t)(bhv_desc_t *, bhv_statvfs_t *,
113 struct bhv_vnode *);
107typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *); 114typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *);
108typedef int (*vfs_vget_t)(bhv_desc_t *, struct vnode **, struct fid *); 115typedef int (*vfs_vget_t)(bhv_desc_t *, struct bhv_vnode **, struct fid *);
109typedef int (*vfs_dmapiops_t)(bhv_desc_t *, caddr_t); 116typedef int (*vfs_dmapiops_t)(bhv_desc_t *, caddr_t);
110typedef int (*vfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t); 117typedef int (*vfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t);
111typedef void (*vfs_init_vnode_t)(bhv_desc_t *, 118typedef void (*vfs_init_vnode_t)(bhv_desc_t *,
112 struct vnode *, bhv_desc_t *, int); 119 struct bhv_vnode *, bhv_desc_t *, int);
113typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int); 120typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int);
114typedef void (*vfs_freeze_t)(bhv_desc_t *); 121typedef void (*vfs_freeze_t)(bhv_desc_t *);
115 122
116typedef struct vfsops { 123typedef struct bhv_vfsops {
117 bhv_position_t vf_position; /* behavior chain position */ 124 bhv_position_t vf_position; /* behavior chain position */
118 vfs_mount_t vfs_mount; /* mount file system */ 125 vfs_mount_t vfs_mount; /* mount file system */
119 vfs_parseargs_t vfs_parseargs; /* parse mount options */ 126 vfs_parseargs_t vfs_parseargs; /* parse mount options */
@@ -129,82 +136,82 @@ typedef struct vfsops {
129 vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */ 136 vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */
130 vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */ 137 vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */
131 vfs_freeze_t vfs_freeze; /* freeze fs for snapshot */ 138 vfs_freeze_t vfs_freeze; /* freeze fs for snapshot */
132} vfsops_t; 139} bhv_vfsops_t;
133 140
134/* 141/*
135 * VFS's. Operates on vfs structure pointers (starts at bhv head). 142 * Virtual filesystem operations, operating from head bhv.
136 */ 143 */
137#define VHEAD(v) ((v)->vfs_fbhv) 144#define VFSHEAD(v) ((v)->vfs_bh.bh_first)
138#define VFS_MOUNT(v, ma,cr, rv) ((rv) = vfs_mount(VHEAD(v), ma,cr)) 145#define bhv_vfs_mount(v, ma,cr) vfs_mount(VFSHEAD(v), ma,cr)
139#define VFS_PARSEARGS(v, o,ma,f, rv) ((rv) = vfs_parseargs(VHEAD(v), o,ma,f)) 146#define bhv_vfs_parseargs(v, o,ma,f) vfs_parseargs(VFSHEAD(v), o,ma,f)
140#define VFS_SHOWARGS(v, m, rv) ((rv) = vfs_showargs(VHEAD(v), m)) 147#define bhv_vfs_showargs(v, m) vfs_showargs(VFSHEAD(v), m)
141#define VFS_UNMOUNT(v, f, cr, rv) ((rv) = vfs_unmount(VHEAD(v), f,cr)) 148#define bhv_vfs_unmount(v, f,cr) vfs_unmount(VFSHEAD(v), f,cr)
142#define VFS_MNTUPDATE(v, fl, args, rv) ((rv) = vfs_mntupdate(VHEAD(v), fl, args)) 149#define bhv_vfs_mntupdate(v, fl,args) vfs_mntupdate(VFSHEAD(v), fl,args)
143#define VFS_ROOT(v, vpp, rv) ((rv) = vfs_root(VHEAD(v), vpp)) 150#define bhv_vfs_root(v, vpp) vfs_root(VFSHEAD(v), vpp)
144#define VFS_STATVFS(v, sp,vp, rv) ((rv) = vfs_statvfs(VHEAD(v), sp,vp)) 151#define bhv_vfs_statvfs(v, sp,vp) vfs_statvfs(VFSHEAD(v), sp,vp)
145#define VFS_SYNC(v, flag,cr, rv) ((rv) = vfs_sync(VHEAD(v), flag,cr)) 152#define bhv_vfs_sync(v, flag,cr) vfs_sync(VFSHEAD(v), flag,cr)
146#define VFS_VGET(v, vpp,fidp, rv) ((rv) = vfs_vget(VHEAD(v), vpp,fidp)) 153#define bhv_vfs_vget(v, vpp,fidp) vfs_vget(VFSHEAD(v), vpp,fidp)
147#define VFS_DMAPIOPS(v, p, rv) ((rv) = vfs_dmapiops(VHEAD(v), p)) 154#define bhv_vfs_dmapiops(v, p) vfs_dmapiops(VFSHEAD(v), p)
148#define VFS_QUOTACTL(v, c,id,p, rv) ((rv) = vfs_quotactl(VHEAD(v), c,id,p)) 155#define bhv_vfs_quotactl(v, c,id,p) vfs_quotactl(VFSHEAD(v), c,id,p)
149#define VFS_INIT_VNODE(v, vp,b,ul) ( vfs_init_vnode(VHEAD(v), vp,b,ul) ) 156#define bhv_vfs_init_vnode(v, vp,b,ul) vfs_init_vnode(VFSHEAD(v), vp,b,ul)
150#define VFS_FORCE_SHUTDOWN(v, fl,f,l) ( vfs_force_shutdown(VHEAD(v), fl,f,l) ) 157#define bhv_vfs_force_shutdown(v,u,f,l) vfs_force_shutdown(VFSHEAD(v), u,f,l)
151#define VFS_FREEZE(v) ( vfs_freeze(VHEAD(v)) ) 158#define bhv_vfs_freeze(v) vfs_freeze(VFSHEAD(v))
152 159
153/* 160/*
154 * PVFS's. Operates on behavior descriptor pointers. 161 * Virtual filesystem operations, operating from next bhv.
155 */ 162 */
156#define PVFS_MOUNT(b, ma,cr, rv) ((rv) = vfs_mount(b, ma,cr)) 163#define bhv_next_vfs_mount(b, ma,cr) vfs_mount(b, ma,cr)
157#define PVFS_PARSEARGS(b, o,ma,f, rv) ((rv) = vfs_parseargs(b, o,ma,f)) 164#define bhv_next_vfs_parseargs(b, o,ma,f) vfs_parseargs(b, o,ma,f)
158#define PVFS_SHOWARGS(b, m, rv) ((rv) = vfs_showargs(b, m)) 165#define bhv_next_vfs_showargs(b, m) vfs_showargs(b, m)
159#define PVFS_UNMOUNT(b, f,cr, rv) ((rv) = vfs_unmount(b, f,cr)) 166#define bhv_next_vfs_unmount(b, f,cr) vfs_unmount(b, f,cr)
160#define PVFS_MNTUPDATE(b, fl, args, rv) ((rv) = vfs_mntupdate(b, fl, args)) 167#define bhv_next_vfs_mntupdate(b, fl,args) vfs_mntupdate(b, fl, args)
161#define PVFS_ROOT(b, vpp, rv) ((rv) = vfs_root(b, vpp)) 168#define bhv_next_vfs_root(b, vpp) vfs_root(b, vpp)
162#define PVFS_STATVFS(b, sp,vp, rv) ((rv) = vfs_statvfs(b, sp,vp)) 169#define bhv_next_vfs_statvfs(b, sp,vp) vfs_statvfs(b, sp,vp)
163#define PVFS_SYNC(b, flag,cr, rv) ((rv) = vfs_sync(b, flag,cr)) 170#define bhv_next_vfs_sync(b, flag,cr) vfs_sync(b, flag,cr)
164#define PVFS_VGET(b, vpp,fidp, rv) ((rv) = vfs_vget(b, vpp,fidp)) 171#define bhv_next_vfs_vget(b, vpp,fidp) vfs_vget(b, vpp,fidp)
165#define PVFS_DMAPIOPS(b, p, rv) ((rv) = vfs_dmapiops(b, p)) 172#define bhv_next_vfs_dmapiops(b, p) vfs_dmapiops(b, p)
166#define PVFS_QUOTACTL(b, c,id,p, rv) ((rv) = vfs_quotactl(b, c,id,p)) 173#define bhv_next_vfs_quotactl(b, c,id,p) vfs_quotactl(b, c,id,p)
167#define PVFS_INIT_VNODE(b, vp,b2,ul) ( vfs_init_vnode(b, vp,b2,ul) ) 174#define bhv_next_vfs_init_vnode(b, vp,b2,ul) vfs_init_vnode(b, vp,b2,ul)
168#define PVFS_FORCE_SHUTDOWN(b, fl,f,l) ( vfs_force_shutdown(b, fl,f,l) ) 175#define bhv_next_force_shutdown(b, fl,f,l) vfs_force_shutdown(b, fl,f,l)
169#define PVFS_FREEZE(b) ( vfs_freeze(b) ) 176#define bhv_next_vfs_freeze(b) vfs_freeze(b)
170 177
171extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *); 178extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *);
172extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int); 179extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int);
173extern int vfs_showargs(bhv_desc_t *, struct seq_file *); 180extern int vfs_showargs(bhv_desc_t *, struct seq_file *);
174extern int vfs_unmount(bhv_desc_t *, int, struct cred *); 181extern int vfs_unmount(bhv_desc_t *, int, struct cred *);
175extern int vfs_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *); 182extern int vfs_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *);
176extern int vfs_root(bhv_desc_t *, struct vnode **); 183extern int vfs_root(bhv_desc_t *, struct bhv_vnode **);
177extern int vfs_statvfs(bhv_desc_t *, xfs_statfs_t *, struct vnode *); 184extern int vfs_statvfs(bhv_desc_t *, bhv_statvfs_t *, struct bhv_vnode *);
178extern int vfs_sync(bhv_desc_t *, int, struct cred *); 185extern int vfs_sync(bhv_desc_t *, int, struct cred *);
179extern int vfs_vget(bhv_desc_t *, struct vnode **, struct fid *); 186extern int vfs_vget(bhv_desc_t *, struct bhv_vnode **, struct fid *);
180extern int vfs_dmapiops(bhv_desc_t *, caddr_t); 187extern int vfs_dmapiops(bhv_desc_t *, caddr_t);
181extern int vfs_quotactl(bhv_desc_t *, int, int, caddr_t); 188extern int vfs_quotactl(bhv_desc_t *, int, int, caddr_t);
182extern void vfs_init_vnode(bhv_desc_t *, struct vnode *, bhv_desc_t *, int); 189extern void vfs_init_vnode(bhv_desc_t *, struct bhv_vnode *, bhv_desc_t *, int);
183extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int); 190extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int);
184extern void vfs_freeze(bhv_desc_t *); 191extern void vfs_freeze(bhv_desc_t *);
185 192
186typedef struct bhv_vfsops { 193#define vfs_test_for_freeze(vfs) ((vfs)->vfs_super->s_frozen)
187 struct vfsops bhv_common; 194#define vfs_wait_for_freeze(vfs,l) vfs_check_frozen((vfs)->vfs_super, (l))
195
196typedef struct bhv_module_vfsops {
197 struct bhv_vfsops bhv_common;
188 void * bhv_custom; 198 void * bhv_custom;
189} bhv_vfsops_t; 199} bhv_module_vfsops_t;
190 200
191#define vfs_bhv_lookup(v, id) ( bhv_lookup_range(&(v)->vfs_bh, (id), (id)) ) 201#define vfs_bhv_lookup(v, id) (bhv_lookup_range(&(v)->vfs_bh, (id), (id)))
192#define vfs_bhv_custom(b) ( ((bhv_vfsops_t *)BHV_OPS(b))->bhv_custom ) 202#define vfs_bhv_custom(b) (((bhv_module_vfsops_t*)BHV_OPS(b))->bhv_custom)
193#define vfs_bhv_set_custom(b,o) ( (b)->bhv_custom = (void *)(o)) 203#define vfs_bhv_set_custom(b,o) ((b)->bhv_custom = (void *)(o))
194#define vfs_bhv_clr_custom(b) ( (b)->bhv_custom = NULL ) 204#define vfs_bhv_clr_custom(b) ((b)->bhv_custom = NULL)
195 205
196extern vfs_t *vfs_allocate(struct super_block *); 206extern bhv_vfs_t *vfs_allocate(struct super_block *);
197extern vfs_t *vfs_from_sb(struct super_block *); 207extern bhv_vfs_t *vfs_from_sb(struct super_block *);
198extern void vfs_deallocate(vfs_t *); 208extern void vfs_deallocate(bhv_vfs_t *);
199extern void vfs_insertops(vfs_t *, bhv_vfsops_t *); 209extern void vfs_insertbhv(bhv_vfs_t *, bhv_desc_t *, bhv_vfsops_t *, void *);
200extern void vfs_insertbhv(vfs_t *, bhv_desc_t *, vfsops_t *, void *);
201 210
202extern void bhv_insert_all_vfsops(struct vfs *); 211extern void vfs_insertops(bhv_vfs_t *, bhv_module_vfsops_t *);
203extern void bhv_remove_all_vfsops(struct vfs *, int);
204extern void bhv_remove_vfsops(struct vfs *, int);
205 212
206#define fs_frozen(vfsp) ((vfsp)->vfs_super->s_frozen) 213extern void bhv_insert_all_vfsops(struct bhv_vfs *);
207#define fs_check_frozen(vfsp, level) \ 214extern void bhv_remove_all_vfsops(struct bhv_vfs *, int);
208 vfs_check_frozen(vfsp->vfs_super, level); 215extern void bhv_remove_vfsops(struct bhv_vfs *, int);
209 216
210#endif /* __XFS_VFS_H__ */ 217#endif /* __XFS_VFS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index d27c25b27ccd..6628d96b6fd6 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -39,7 +39,7 @@ vn_init(void)
39 39
40void 40void
41vn_iowait( 41vn_iowait(
42 struct vnode *vp) 42 bhv_vnode_t *vp)
43{ 43{
44 wait_queue_head_t *wq = vptosync(vp); 44 wait_queue_head_t *wq = vptosync(vp);
45 45
@@ -48,17 +48,33 @@ vn_iowait(
48 48
49void 49void
50vn_iowake( 50vn_iowake(
51 struct vnode *vp) 51 bhv_vnode_t *vp)
52{ 52{
53 if (atomic_dec_and_test(&vp->v_iocount)) 53 if (atomic_dec_and_test(&vp->v_iocount))
54 wake_up(vptosync(vp)); 54 wake_up(vptosync(vp));
55} 55}
56 56
57struct vnode * 57/*
58 * Volume managers supporting multiple paths can send back ENODEV when the
59 * final path disappears. In this case continuing to fill the page cache
60 * with dirty data which cannot be written out is evil, so prevent that.
61 */
62void
63vn_ioerror(
64 bhv_vnode_t *vp,
65 int error,
66 char *f,
67 int l)
68{
69 if (unlikely(error == -ENODEV))
70 bhv_vfs_force_shutdown(vp->v_vfsp, SHUTDOWN_DEVICE_REQ, f, l);
71}
72
73bhv_vnode_t *
58vn_initialize( 74vn_initialize(
59 struct inode *inode) 75 struct inode *inode)
60{ 76{
61 struct vnode *vp = vn_from_inode(inode); 77 bhv_vnode_t *vp = vn_from_inode(inode);
62 78
63 XFS_STATS_INC(vn_active); 79 XFS_STATS_INC(vn_active);
64 XFS_STATS_INC(vn_alloc); 80 XFS_STATS_INC(vn_alloc);
@@ -94,8 +110,8 @@ vn_initialize(
94 */ 110 */
95void 111void
96vn_revalidate_core( 112vn_revalidate_core(
97 struct vnode *vp, 113 bhv_vnode_t *vp,
98 vattr_t *vap) 114 bhv_vattr_t *vap)
99{ 115{
100 struct inode *inode = vn_to_inode(vp); 116 struct inode *inode = vn_to_inode(vp);
101 117
@@ -130,14 +146,14 @@ vn_revalidate_core(
130 */ 146 */
131int 147int
132__vn_revalidate( 148__vn_revalidate(
133 struct vnode *vp, 149 bhv_vnode_t *vp,
134 struct vattr *vattr) 150 bhv_vattr_t *vattr)
135{ 151{
136 int error; 152 int error;
137 153
138 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); 154 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
139 vattr->va_mask = XFS_AT_STAT | XFS_AT_XFLAGS; 155 vattr->va_mask = XFS_AT_STAT | XFS_AT_XFLAGS;
140 VOP_GETATTR(vp, vattr, 0, NULL, error); 156 error = bhv_vop_getattr(vp, vattr, 0, NULL);
141 if (likely(!error)) { 157 if (likely(!error)) {
142 vn_revalidate_core(vp, vattr); 158 vn_revalidate_core(vp, vattr);
143 VUNMODIFY(vp); 159 VUNMODIFY(vp);
@@ -147,9 +163,9 @@ __vn_revalidate(
147 163
148int 164int
149vn_revalidate( 165vn_revalidate(
150 struct vnode *vp) 166 bhv_vnode_t *vp)
151{ 167{
152 vattr_t vattr; 168 bhv_vattr_t vattr;
153 169
154 return __vn_revalidate(vp, &vattr); 170 return __vn_revalidate(vp, &vattr);
155} 171}
@@ -157,9 +173,9 @@ vn_revalidate(
157/* 173/*
158 * Add a reference to a referenced vnode. 174 * Add a reference to a referenced vnode.
159 */ 175 */
160struct vnode * 176bhv_vnode_t *
161vn_hold( 177vn_hold(
162 struct vnode *vp) 178 bhv_vnode_t *vp)
163{ 179{
164 struct inode *inode; 180 struct inode *inode;
165 181
@@ -192,31 +208,31 @@ vn_hold(
192 * Vnode tracing code. 208 * Vnode tracing code.
193 */ 209 */
194void 210void
195vn_trace_entry(vnode_t *vp, const char *func, inst_t *ra) 211vn_trace_entry(bhv_vnode_t *vp, const char *func, inst_t *ra)
196{ 212{
197 KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra); 213 KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra);
198} 214}
199 215
200void 216void
201vn_trace_exit(vnode_t *vp, const char *func, inst_t *ra) 217vn_trace_exit(bhv_vnode_t *vp, const char *func, inst_t *ra)
202{ 218{
203 KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra); 219 KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra);
204} 220}
205 221
206void 222void
207vn_trace_hold(vnode_t *vp, char *file, int line, inst_t *ra) 223vn_trace_hold(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
208{ 224{
209 KTRACE_ENTER(vp, VNODE_KTRACE_HOLD, file, line, ra); 225 KTRACE_ENTER(vp, VNODE_KTRACE_HOLD, file, line, ra);
210} 226}
211 227
212void 228void
213vn_trace_ref(vnode_t *vp, char *file, int line, inst_t *ra) 229vn_trace_ref(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
214{ 230{
215 KTRACE_ENTER(vp, VNODE_KTRACE_REF, file, line, ra); 231 KTRACE_ENTER(vp, VNODE_KTRACE_REF, file, line, ra);
216} 232}
217 233
218void 234void
219vn_trace_rele(vnode_t *vp, char *file, int line, inst_t *ra) 235vn_trace_rele(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
220{ 236{
221 KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra); 237 KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra);
222} 238}
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 2a8e16c22353..35c6a01963a7 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -14,57 +14,35 @@
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation, 15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 * Portions Copyright (c) 1989, 1993
19 * The Regents of the University of California. All rights reserved.
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
23 * are met:
24 * 1. Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
29 * 3. Neither the name of the University nor the names of its contributors
30 * may be used to endorse or promote products derived from this software
31 * without specific prior written permission.
32 *
33 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
34 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
37 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */ 17 */
45#ifndef __XFS_VNODE_H__ 18#ifndef __XFS_VNODE_H__
46#define __XFS_VNODE_H__ 19#define __XFS_VNODE_H__
47 20
48struct uio; 21struct uio;
49struct file; 22struct file;
50struct vattr; 23struct bhv_vfs;
24struct bhv_vattr;
51struct xfs_iomap; 25struct xfs_iomap;
52struct attrlist_cursor_kern; 26struct attrlist_cursor_kern;
53 27
28typedef struct dentry bhv_vname_t;
29typedef __u64 bhv_vnumber_t;
54 30
55typedef xfs_ino_t vnumber_t; 31typedef enum bhv_vflags {
56typedef struct dentry vname_t; 32 VMODIFIED = 0x08, /* XFS inode state possibly differs */
57typedef bhv_head_t vn_bhv_head_t; 33 /* to the Linux inode state. */
34 VTRUNCATED = 0x40, /* truncated down so flush-on-close */
35} bhv_vflags_t;
58 36
59/* 37/*
60 * MP locking protocols: 38 * MP locking protocols:
61 * v_flag, v_vfsp VN_LOCK/VN_UNLOCK 39 * v_flag, v_vfsp VN_LOCK/VN_UNLOCK
62 */ 40 */
63typedef struct vnode { 41typedef struct bhv_vnode {
64 __u32 v_flag; /* vnode flags (see below) */ 42 bhv_vflags_t v_flag; /* vnode flags (see above) */
65 struct vfs *v_vfsp; /* ptr to containing VFS */ 43 bhv_vfs_t *v_vfsp; /* ptr to containing VFS */
66 vnumber_t v_number; /* in-core vnode number */ 44 bhv_vnumber_t v_number; /* in-core vnode number */
67 vn_bhv_head_t v_bh; /* behavior head */ 45 bhv_head_t v_bh; /* behavior head */
68 spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */ 46 spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */
69 atomic_t v_iocount; /* outstanding I/O count */ 47 atomic_t v_iocount; /* outstanding I/O count */
70#ifdef XFS_VNODE_TRACE 48#ifdef XFS_VNODE_TRACE
@@ -72,7 +50,7 @@ typedef struct vnode {
72#endif 50#endif
73 struct inode v_inode; /* Linux inode */ 51 struct inode v_inode; /* Linux inode */
74 /* inode MUST be last */ 52 /* inode MUST be last */
75} vnode_t; 53} bhv_vnode_t;
76 54
77#define VN_ISLNK(vp) S_ISLNK((vp)->v_inode.i_mode) 55#define VN_ISLNK(vp) S_ISLNK((vp)->v_inode.i_mode)
78#define VN_ISREG(vp) S_ISREG((vp)->v_inode.i_mode) 56#define VN_ISREG(vp) S_ISREG((vp)->v_inode.i_mode)
@@ -80,9 +58,6 @@ typedef struct vnode {
80#define VN_ISCHR(vp) S_ISCHR((vp)->v_inode.i_mode) 58#define VN_ISCHR(vp) S_ISCHR((vp)->v_inode.i_mode)
81#define VN_ISBLK(vp) S_ISBLK((vp)->v_inode.i_mode) 59#define VN_ISBLK(vp) S_ISBLK((vp)->v_inode.i_mode)
82 60
83#define v_fbhv v_bh.bh_first /* first behavior */
84#define v_fops v_bh.bh_first->bd_ops /* first behavior ops */
85
86#define VNODE_POSITION_BASE BHV_POSITION_BASE /* chain bottom */ 61#define VNODE_POSITION_BASE BHV_POSITION_BASE /* chain bottom */
87#define VNODE_POSITION_TOP BHV_POSITION_TOP /* chain top */ 62#define VNODE_POSITION_TOP BHV_POSITION_TOP /* chain top */
88#define VNODE_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */ 63#define VNODE_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */
@@ -104,8 +79,8 @@ typedef enum {
104/* 79/*
105 * Macros for dealing with the behavior descriptor inside of the vnode. 80 * Macros for dealing with the behavior descriptor inside of the vnode.
106 */ 81 */
107#define BHV_TO_VNODE(bdp) ((vnode_t *)BHV_VOBJ(bdp)) 82#define BHV_TO_VNODE(bdp) ((bhv_vnode_t *)BHV_VOBJ(bdp))
108#define BHV_TO_VNODE_NULL(bdp) ((vnode_t *)BHV_VOBJNULL(bdp)) 83#define BHV_TO_VNODE_NULL(bdp) ((bhv_vnode_t *)BHV_VOBJNULL(bdp))
109 84
110#define VN_BHV_HEAD(vp) ((bhv_head_t *)(&((vp)->v_bh))) 85#define VN_BHV_HEAD(vp) ((bhv_head_t *)(&((vp)->v_bh)))
111#define vn_bhv_head_init(bhp,name) bhv_head_init(bhp,name) 86#define vn_bhv_head_init(bhp,name) bhv_head_init(bhp,name)
@@ -116,35 +91,29 @@ typedef enum {
116/* 91/*
117 * Vnode to Linux inode mapping. 92 * Vnode to Linux inode mapping.
118 */ 93 */
119static inline struct vnode *vn_from_inode(struct inode *inode) 94static inline struct bhv_vnode *vn_from_inode(struct inode *inode)
120{ 95{
121 return (vnode_t *)list_entry(inode, vnode_t, v_inode); 96 return (bhv_vnode_t *)list_entry(inode, bhv_vnode_t, v_inode);
122} 97}
123static inline struct inode *vn_to_inode(struct vnode *vnode) 98static inline struct inode *vn_to_inode(struct bhv_vnode *vnode)
124{ 99{
125 return &vnode->v_inode; 100 return &vnode->v_inode;
126} 101}
127 102
128/* 103/*
129 * Vnode flags. 104 * Values for the vop_rwlock/rwunlock flags parameter.
130 */
131#define VMODIFIED 0x8 /* XFS inode state possibly differs */
132 /* to the Linux inode state. */
133
134/*
135 * Values for the VOP_RWLOCK and VOP_RWUNLOCK flags parameter.
136 */ 105 */
137typedef enum vrwlock { 106typedef enum bhv_vrwlock {
138 VRWLOCK_NONE, 107 VRWLOCK_NONE,
139 VRWLOCK_READ, 108 VRWLOCK_READ,
140 VRWLOCK_WRITE, 109 VRWLOCK_WRITE,
141 VRWLOCK_WRITE_DIRECT, 110 VRWLOCK_WRITE_DIRECT,
142 VRWLOCK_TRY_READ, 111 VRWLOCK_TRY_READ,
143 VRWLOCK_TRY_WRITE 112 VRWLOCK_TRY_WRITE
144} vrwlock_t; 113} bhv_vrwlock_t;
145 114
146/* 115/*
147 * Return values for VOP_INACTIVE. A return value of 116 * Return values for bhv_vop_inactive. A return value of
148 * VN_INACTIVE_NOCACHE implies that the file system behavior 117 * VN_INACTIVE_NOCACHE implies that the file system behavior
149 * has disassociated its state and bhv_desc_t from the vnode. 118 * has disassociated its state and bhv_desc_t from the vnode.
150 */ 119 */
@@ -152,18 +121,20 @@ typedef enum vrwlock {
152#define VN_INACTIVE_NOCACHE 1 121#define VN_INACTIVE_NOCACHE 1
153 122
154/* 123/*
155 * Values for the cmd code given to VOP_VNODE_CHANGE. 124 * Values for the cmd code given to vop_vnode_change.
156 */ 125 */
157typedef enum vchange { 126typedef enum bhv_vchange {
158 VCHANGE_FLAGS_FRLOCKS = 0, 127 VCHANGE_FLAGS_FRLOCKS = 0,
159 VCHANGE_FLAGS_ENF_LOCKING = 1, 128 VCHANGE_FLAGS_ENF_LOCKING = 1,
160 VCHANGE_FLAGS_TRUNCATED = 2, 129 VCHANGE_FLAGS_TRUNCATED = 2,
161 VCHANGE_FLAGS_PAGE_DIRTY = 3, 130 VCHANGE_FLAGS_PAGE_DIRTY = 3,
162 VCHANGE_FLAGS_IOEXCL_COUNT = 4 131 VCHANGE_FLAGS_IOEXCL_COUNT = 4
163} vchange_t; 132} bhv_vchange_t;
164 133
134typedef enum { L_FALSE, L_TRUE } lastclose_t;
165 135
166typedef int (*vop_open_t)(bhv_desc_t *, struct cred *); 136typedef int (*vop_open_t)(bhv_desc_t *, struct cred *);
137typedef int (*vop_close_t)(bhv_desc_t *, int, lastclose_t, struct cred *);
167typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *, 138typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *,
168 const struct iovec *, unsigned int, 139 const struct iovec *, unsigned int,
169 loff_t *, int, struct cred *); 140 loff_t *, int, struct cred *);
@@ -181,27 +152,27 @@ typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct pipe_inode_info *,
181 struct cred *); 152 struct cred *);
182typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *, 153typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
183 int, unsigned int, void __user *); 154 int, unsigned int, void __user *);
184typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int, 155typedef int (*vop_getattr_t)(bhv_desc_t *, struct bhv_vattr *, int,
185 struct cred *); 156 struct cred *);
186typedef int (*vop_setattr_t)(bhv_desc_t *, struct vattr *, int, 157typedef int (*vop_setattr_t)(bhv_desc_t *, struct bhv_vattr *, int,
187 struct cred *); 158 struct cred *);
188typedef int (*vop_access_t)(bhv_desc_t *, int, struct cred *); 159typedef int (*vop_access_t)(bhv_desc_t *, int, struct cred *);
189typedef int (*vop_lookup_t)(bhv_desc_t *, vname_t *, vnode_t **, 160typedef int (*vop_lookup_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t **,
190 int, vnode_t *, struct cred *); 161 int, bhv_vnode_t *, struct cred *);
191typedef int (*vop_create_t)(bhv_desc_t *, vname_t *, struct vattr *, 162typedef int (*vop_create_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *,
192 vnode_t **, struct cred *); 163 bhv_vnode_t **, struct cred *);
193typedef int (*vop_remove_t)(bhv_desc_t *, vname_t *, struct cred *); 164typedef int (*vop_remove_t)(bhv_desc_t *, bhv_vname_t *, struct cred *);
194typedef int (*vop_link_t)(bhv_desc_t *, vnode_t *, vname_t *, 165typedef int (*vop_link_t)(bhv_desc_t *, bhv_vnode_t *, bhv_vname_t *,
195 struct cred *);
196typedef int (*vop_rename_t)(bhv_desc_t *, vname_t *, vnode_t *, vname_t *,
197 struct cred *); 166 struct cred *);
198typedef int (*vop_mkdir_t)(bhv_desc_t *, vname_t *, struct vattr *, 167typedef int (*vop_rename_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *,
199 vnode_t **, struct cred *); 168 bhv_vname_t *, struct cred *);
200typedef int (*vop_rmdir_t)(bhv_desc_t *, vname_t *, struct cred *); 169typedef int (*vop_mkdir_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *,
170 bhv_vnode_t **, struct cred *);
171typedef int (*vop_rmdir_t)(bhv_desc_t *, bhv_vname_t *, struct cred *);
201typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *, 172typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *,
202 int *); 173 int *);
203typedef int (*vop_symlink_t)(bhv_desc_t *, vname_t *, struct vattr *, 174typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*,
204 char *, vnode_t **, struct cred *); 175 char *, bhv_vnode_t **, struct cred *);
205typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int, 176typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int,
206 struct cred *); 177 struct cred *);
207typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *, 178typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *,
@@ -209,8 +180,8 @@ typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *,
209typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *); 180typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *);
210typedef int (*vop_fid2_t)(bhv_desc_t *, struct fid *); 181typedef int (*vop_fid2_t)(bhv_desc_t *, struct fid *);
211typedef int (*vop_release_t)(bhv_desc_t *); 182typedef int (*vop_release_t)(bhv_desc_t *);
212typedef int (*vop_rwlock_t)(bhv_desc_t *, vrwlock_t); 183typedef int (*vop_rwlock_t)(bhv_desc_t *, bhv_vrwlock_t);
213typedef void (*vop_rwunlock_t)(bhv_desc_t *, vrwlock_t); 184typedef void (*vop_rwunlock_t)(bhv_desc_t *, bhv_vrwlock_t);
214typedef int (*vop_bmap_t)(bhv_desc_t *, xfs_off_t, ssize_t, int, 185typedef int (*vop_bmap_t)(bhv_desc_t *, xfs_off_t, ssize_t, int,
215 struct xfs_iomap *, int *); 186 struct xfs_iomap *, int *);
216typedef int (*vop_reclaim_t)(bhv_desc_t *); 187typedef int (*vop_reclaim_t)(bhv_desc_t *);
@@ -222,8 +193,8 @@ typedef int (*vop_attr_remove_t)(bhv_desc_t *, const char *,
222 int, struct cred *); 193 int, struct cred *);
223typedef int (*vop_attr_list_t)(bhv_desc_t *, char *, int, int, 194typedef int (*vop_attr_list_t)(bhv_desc_t *, char *, int, int,
224 struct attrlist_cursor_kern *, struct cred *); 195 struct attrlist_cursor_kern *, struct cred *);
225typedef void (*vop_link_removed_t)(bhv_desc_t *, vnode_t *, int); 196typedef void (*vop_link_removed_t)(bhv_desc_t *, bhv_vnode_t *, int);
226typedef void (*vop_vnode_change_t)(bhv_desc_t *, vchange_t, __psint_t); 197typedef void (*vop_vnode_change_t)(bhv_desc_t *, bhv_vchange_t, __psint_t);
227typedef void (*vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int); 198typedef void (*vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
228typedef void (*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int); 199typedef void (*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
229typedef int (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, 200typedef int (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t,
@@ -231,9 +202,10 @@ typedef int (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t,
231typedef int (*vop_iflush_t)(bhv_desc_t *, int); 202typedef int (*vop_iflush_t)(bhv_desc_t *, int);
232 203
233 204
234typedef struct vnodeops { 205typedef struct bhv_vnodeops {
235 bhv_position_t vn_position; /* position within behavior chain */ 206 bhv_position_t vn_position; /* position within behavior chain */
236 vop_open_t vop_open; 207 vop_open_t vop_open;
208 vop_close_t vop_close;
237 vop_read_t vop_read; 209 vop_read_t vop_read;
238 vop_write_t vop_write; 210 vop_write_t vop_write;
239 vop_sendfile_t vop_sendfile; 211 vop_sendfile_t vop_sendfile;
@@ -271,103 +243,80 @@ typedef struct vnodeops {
271 vop_pflushvp_t vop_flush_pages; 243 vop_pflushvp_t vop_flush_pages;
272 vop_release_t vop_release; 244 vop_release_t vop_release;
273 vop_iflush_t vop_iflush; 245 vop_iflush_t vop_iflush;
274} vnodeops_t; 246} bhv_vnodeops_t;
275 247
276/* 248/*
277 * VOP's. 249 * Virtual node operations, operating from head bhv.
278 */
279#define _VOP_(op, vp) (*((vnodeops_t *)(vp)->v_fops)->op)
280
281#define VOP_READ(vp,file,iov,segs,offset,ioflags,cr,rv) \
282 rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr)
283#define VOP_WRITE(vp,file,iov,segs,offset,ioflags,cr,rv) \
284 rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr)
285#define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv) \
286 rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr)
287#define VOP_SPLICE_READ(vp,f,o,pipe,cnt,fl,iofl,cr,rv) \
288 rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr)
289#define VOP_SPLICE_WRITE(vp,f,o,pipe,cnt,fl,iofl,cr,rv) \
290 rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr)
291#define VOP_BMAP(vp,of,sz,rw,b,n,rv) \
292 rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n)
293#define VOP_OPEN(vp, cr, rv) \
294 rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr)
295#define VOP_GETATTR(vp, vap, f, cr, rv) \
296 rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr)
297#define VOP_SETATTR(vp, vap, f, cr, rv) \
298 rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr)
299#define VOP_ACCESS(vp, mode, cr, rv) \
300 rv = _VOP_(vop_access, vp)((vp)->v_fbhv, mode, cr)
301#define VOP_LOOKUP(vp,d,vpp,f,rdir,cr,rv) \
302 rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,d,vpp,f,rdir,cr)
303#define VOP_CREATE(dvp,d,vap,vpp,cr,rv) \
304 rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,d,vap,vpp,cr)
305#define VOP_REMOVE(dvp,d,cr,rv) \
306 rv = _VOP_(vop_remove, dvp)((dvp)->v_fbhv,d,cr)
307#define VOP_LINK(tdvp,fvp,d,cr,rv) \
308 rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,d,cr)
309#define VOP_RENAME(fvp,fnm,tdvp,tnm,cr,rv) \
310 rv = _VOP_(vop_rename, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,cr)
311#define VOP_MKDIR(dp,d,vap,vpp,cr,rv) \
312 rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,d,vap,vpp,cr)
313#define VOP_RMDIR(dp,d,cr,rv) \
314 rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,d,cr)
315#define VOP_READDIR(vp,uiop,cr,eofp,rv) \
316 rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp)
317#define VOP_SYMLINK(dvp,d,vap,tnm,vpp,cr,rv) \
318 rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr)
319#define VOP_READLINK(vp,uiop,fl,cr,rv) \
320 rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,fl,cr)
321#define VOP_FSYNC(vp,f,cr,b,e,rv) \
322 rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e)
323#define VOP_INACTIVE(vp, cr, rv) \
324 rv = _VOP_(vop_inactive, vp)((vp)->v_fbhv, cr)
325#define VOP_RELEASE(vp, rv) \
326 rv = _VOP_(vop_release, vp)((vp)->v_fbhv)
327#define VOP_FID2(vp, fidp, rv) \
328 rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp)
329#define VOP_RWLOCK(vp,i) \
330 (void)_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i)
331#define VOP_RWLOCK_TRY(vp,i) \
332 _VOP_(vop_rwlock, vp)((vp)->v_fbhv, i)
333#define VOP_RWUNLOCK(vp,i) \
334 (void)_VOP_(vop_rwunlock, vp)((vp)->v_fbhv, i)
335#define VOP_FRLOCK(vp,c,fl,flags,offset,fr,rv) \
336 rv = _VOP_(vop_frlock, vp)((vp)->v_fbhv,c,fl,flags,offset,fr)
337#define VOP_RECLAIM(vp, rv) \
338 rv = _VOP_(vop_reclaim, vp)((vp)->v_fbhv)
339#define VOP_ATTR_GET(vp, name, val, vallenp, fl, cred, rv) \
340 rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred)
341#define VOP_ATTR_SET(vp, name, val, vallen, fl, cred, rv) \
342 rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred)
343#define VOP_ATTR_REMOVE(vp, name, flags, cred, rv) \
344 rv = _VOP_(vop_attr_remove, vp)((vp)->v_fbhv,name,flags,cred)
345#define VOP_ATTR_LIST(vp, buf, buflen, fl, cursor, cred, rv) \
346 rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred)
347#define VOP_LINK_REMOVED(vp, dvp, linkzero) \
348 (void)_VOP_(vop_link_removed, vp)((vp)->v_fbhv, dvp, linkzero)
349#define VOP_VNODE_CHANGE(vp, cmd, val) \
350 (void)_VOP_(vop_vnode_change, vp)((vp)->v_fbhv,cmd,val)
351/*
352 * These are page cache functions that now go thru VOPs.
353 * 'last' parameter is unused and left in for IRIX compatibility
354 */ 250 */
355#define VOP_TOSS_PAGES(vp, first, last, fiopt) \ 251#define VNHEAD(vp) ((vp)->v_bh.bh_first)
356 _VOP_(vop_tosspages, vp)((vp)->v_fbhv,first, last, fiopt) 252#define VOP(op, vp) (*((bhv_vnodeops_t *)VNHEAD(vp)->bd_ops)->op)
357/* 253#define bhv_vop_open(vp, cr) VOP(vop_open, vp)(VNHEAD(vp),cr)
358 * 'last' parameter is unused and left in for IRIX compatibility 254#define bhv_vop_close(vp, f,last,cr) VOP(vop_close, vp)(VNHEAD(vp),f,last,cr)
359 */ 255#define bhv_vop_read(vp,file,iov,segs,offset,ioflags,cr) \
360#define VOP_FLUSHINVAL_PAGES(vp, first, last, fiopt) \ 256 VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
361 _VOP_(vop_flushinval_pages, vp)((vp)->v_fbhv,first,last,fiopt) 257#define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr) \
362/* 258 VOP(vop_write, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
363 * 'last' parameter is unused and left in for IRIX compatibility 259#define bhv_vop_sendfile(vp,f,off,ioflags,cnt,act,targ,cr) \
364 */ 260 VOP(vop_sendfile, vp)(VNHEAD(vp),f,off,ioflags,cnt,act,targ,cr)
365#define VOP_FLUSH_PAGES(vp, first, last, flags, fiopt, rv) \ 261#define bhv_vop_splice_read(vp,f,o,pipe,cnt,fl,iofl,cr) \
366 rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt) 262 VOP(vop_splice_read, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
367#define VOP_IOCTL(vp, inode, filp, fl, cmd, arg, rv) \ 263#define bhv_vop_splice_write(vp,f,o,pipe,cnt,fl,iofl,cr) \
368 rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,fl,cmd,arg) 264 VOP(vop_splice_write, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
369#define VOP_IFLUSH(vp, flags, rv) \ 265#define bhv_vop_bmap(vp,of,sz,rw,b,n) \
370 rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags) 266 VOP(vop_bmap, vp)(VNHEAD(vp),of,sz,rw,b,n)
267#define bhv_vop_getattr(vp, vap,f,cr) \
268 VOP(vop_getattr, vp)(VNHEAD(vp), vap,f,cr)
269#define bhv_vop_setattr(vp, vap,f,cr) \
270 VOP(vop_setattr, vp)(VNHEAD(vp), vap,f,cr)
271#define bhv_vop_access(vp, mode,cr) VOP(vop_access, vp)(VNHEAD(vp), mode,cr)
272#define bhv_vop_lookup(vp,d,vpp,f,rdir,cr) \
273 VOP(vop_lookup, vp)(VNHEAD(vp),d,vpp,f,rdir,cr)
274#define bhv_vop_create(dvp,d,vap,vpp,cr) \
275 VOP(vop_create, dvp)(VNHEAD(dvp),d,vap,vpp,cr)
276#define bhv_vop_remove(dvp,d,cr) VOP(vop_remove, dvp)(VNHEAD(dvp),d,cr)
277#define bhv_vop_link(dvp,fvp,d,cr) VOP(vop_link, dvp)(VNHEAD(dvp),fvp,d,cr)
278#define bhv_vop_rename(fvp,fnm,tdvp,tnm,cr) \
279 VOP(vop_rename, fvp)(VNHEAD(fvp),fnm,tdvp,tnm,cr)
280#define bhv_vop_mkdir(dp,d,vap,vpp,cr) \
281 VOP(vop_mkdir, dp)(VNHEAD(dp),d,vap,vpp,cr)
282#define bhv_vop_rmdir(dp,d,cr) VOP(vop_rmdir, dp)(VNHEAD(dp),d,cr)
283#define bhv_vop_readdir(vp,uiop,cr,eofp) \
284 VOP(vop_readdir, vp)(VNHEAD(vp),uiop,cr,eofp)
285#define bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr) \
286 VOP(vop_symlink, dvp)(VNHEAD(dvp),d,vap,tnm,vpp,cr)
287#define bhv_vop_readlink(vp,uiop,fl,cr) \
288 VOP(vop_readlink, vp)(VNHEAD(vp),uiop,fl,cr)
289#define bhv_vop_fsync(vp,f,cr,b,e) VOP(vop_fsync, vp)(VNHEAD(vp),f,cr,b,e)
290#define bhv_vop_inactive(vp,cr) VOP(vop_inactive, vp)(VNHEAD(vp),cr)
291#define bhv_vop_release(vp) VOP(vop_release, vp)(VNHEAD(vp))
292#define bhv_vop_fid2(vp,fidp) VOP(vop_fid2, vp)(VNHEAD(vp),fidp)
293#define bhv_vop_rwlock(vp,i) VOP(vop_rwlock, vp)(VNHEAD(vp),i)
294#define bhv_vop_rwlock_try(vp,i) VOP(vop_rwlock, vp)(VNHEAD(vp),i)
295#define bhv_vop_rwunlock(vp,i) VOP(vop_rwunlock, vp)(VNHEAD(vp),i)
296#define bhv_vop_frlock(vp,c,fl,flags,offset,fr) \
297 VOP(vop_frlock, vp)(VNHEAD(vp),c,fl,flags,offset,fr)
298#define bhv_vop_reclaim(vp) VOP(vop_reclaim, vp)(VNHEAD(vp))
299#define bhv_vop_attr_get(vp, name, val, vallenp, fl, cred) \
300 VOP(vop_attr_get, vp)(VNHEAD(vp),name,val,vallenp,fl,cred)
301#define bhv_vop_attr_set(vp, name, val, vallen, fl, cred) \
302 VOP(vop_attr_set, vp)(VNHEAD(vp),name,val,vallen,fl,cred)
303#define bhv_vop_attr_remove(vp, name, flags, cred) \
304 VOP(vop_attr_remove, vp)(VNHEAD(vp),name,flags,cred)
305#define bhv_vop_attr_list(vp, buf, buflen, fl, cursor, cred) \
306 VOP(vop_attr_list, vp)(VNHEAD(vp),buf,buflen,fl,cursor,cred)
307#define bhv_vop_link_removed(vp, dvp, linkzero) \
308 VOP(vop_link_removed, vp)(VNHEAD(vp), dvp, linkzero)
309#define bhv_vop_vnode_change(vp, cmd, val) \
310 VOP(vop_vnode_change, vp)(VNHEAD(vp), cmd, val)
311#define bhv_vop_toss_pages(vp, first, last, fiopt) \
312 VOP(vop_tosspages, vp)(VNHEAD(vp), first, last, fiopt)
313#define bhv_vop_flushinval_pages(vp, first, last, fiopt) \
314 VOP(vop_flushinval_pages, vp)(VNHEAD(vp),first,last,fiopt)
315#define bhv_vop_flush_pages(vp, first, last, flags, fiopt) \
316 VOP(vop_flush_pages, vp)(VNHEAD(vp),first,last,flags,fiopt)
317#define bhv_vop_ioctl(vp, inode, filp, fl, cmd, arg) \
318 VOP(vop_ioctl, vp)(VNHEAD(vp),inode,filp,fl,cmd,arg)
319#define bhv_vop_iflush(vp, flags) VOP(vop_iflush, vp)(VNHEAD(vp), flags)
371 320
372/* 321/*
373 * Flags for read/write calls - same values as IRIX 322 * Flags for read/write calls - same values as IRIX
@@ -377,7 +326,7 @@ typedef struct vnodeops {
377#define IO_INVIS 0x00020 /* don't update inode timestamps */ 326#define IO_INVIS 0x00020 /* don't update inode timestamps */
378 327
379/* 328/*
380 * Flags for VOP_IFLUSH call 329 * Flags for vop_iflush call
381 */ 330 */
382#define FLUSH_SYNC 1 /* wait for flush to complete */ 331#define FLUSH_SYNC 1 /* wait for flush to complete */
383#define FLUSH_INODE 2 /* flush the inode itself */ 332#define FLUSH_INODE 2 /* flush the inode itself */
@@ -385,8 +334,7 @@ typedef struct vnodeops {
385 * this inode out to disk */ 334 * this inode out to disk */
386 335
387/* 336/*
388 * Flush/Invalidate options for VOP_TOSS_PAGES, VOP_FLUSHINVAL_PAGES and 337 * Flush/Invalidate options for vop_toss/flush/flushinval_pages.
389 * VOP_FLUSH_PAGES.
390 */ 338 */
391#define FI_NONE 0 /* none */ 339#define FI_NONE 0 /* none */
392#define FI_REMAPF 1 /* Do a remapf prior to the operation */ 340#define FI_REMAPF 1 /* Do a remapf prior to the operation */
@@ -398,7 +346,7 @@ typedef struct vnodeops {
398 * Vnode attributes. va_mask indicates those attributes the caller 346 * Vnode attributes. va_mask indicates those attributes the caller
399 * wants to set or extract. 347 * wants to set or extract.
400 */ 348 */
401typedef struct vattr { 349typedef struct bhv_vattr {
402 int va_mask; /* bit-mask of attributes present */ 350 int va_mask; /* bit-mask of attributes present */
403 mode_t va_mode; /* file access mode and type */ 351 mode_t va_mode; /* file access mode and type */
404 xfs_nlink_t va_nlink; /* number of references to file */ 352 xfs_nlink_t va_nlink; /* number of references to file */
@@ -418,7 +366,7 @@ typedef struct vattr {
418 u_long va_nextents; /* number of extents in file */ 366 u_long va_nextents; /* number of extents in file */
419 u_long va_anextents; /* number of attr extents in file */ 367 u_long va_anextents; /* number of attr extents in file */
420 prid_t va_projid; /* project id */ 368 prid_t va_projid; /* project id */
421} vattr_t; 369} bhv_vattr_t;
422 370
423/* 371/*
424 * setattr or getattr attributes 372 * setattr or getattr attributes
@@ -492,29 +440,17 @@ typedef struct vattr {
492 (VN_ISREG(vp) && ((mode) & (VSGID|(VEXEC>>3))) == VSGID) 440 (VN_ISREG(vp) && ((mode) & (VSGID|(VEXEC>>3))) == VSGID)
493 441
494extern void vn_init(void); 442extern void vn_init(void);
495extern vnode_t *vn_initialize(struct inode *); 443extern bhv_vnode_t *vn_initialize(struct inode *);
496 444extern int vn_revalidate(struct bhv_vnode *);
497/* 445extern int __vn_revalidate(struct bhv_vnode *, bhv_vattr_t *);
498 * vnode_map structures _must_ match vn_epoch and vnode structure sizes. 446extern void vn_revalidate_core(struct bhv_vnode *, bhv_vattr_t *);
499 */
500typedef struct vnode_map {
501 vfs_t *v_vfsp;
502 vnumber_t v_number; /* in-core vnode number */
503 xfs_ino_t v_ino; /* inode # */
504} vmap_t;
505
506#define VMAP(vp, vmap) {(vmap).v_vfsp = (vp)->v_vfsp, \
507 (vmap).v_number = (vp)->v_number, \
508 (vmap).v_ino = (vp)->v_inode.i_ino; }
509 447
510extern int vn_revalidate(struct vnode *); 448extern void vn_iowait(struct bhv_vnode *vp);
511extern int __vn_revalidate(struct vnode *, vattr_t *); 449extern void vn_iowake(struct bhv_vnode *vp);
512extern void vn_revalidate_core(struct vnode *, vattr_t *);
513 450
514extern void vn_iowait(struct vnode *vp); 451extern void vn_ioerror(struct bhv_vnode *vp, int error, char *f, int l);
515extern void vn_iowake(struct vnode *vp);
516 452
517static inline int vn_count(struct vnode *vp) 453static inline int vn_count(struct bhv_vnode *vp)
518{ 454{
519 return atomic_read(&vn_to_inode(vp)->i_count); 455 return atomic_read(&vn_to_inode(vp)->i_count);
520} 456}
@@ -522,7 +458,7 @@ static inline int vn_count(struct vnode *vp)
522/* 458/*
523 * Vnode reference counting functions (and macros for compatibility). 459 * Vnode reference counting functions (and macros for compatibility).
524 */ 460 */
525extern vnode_t *vn_hold(struct vnode *); 461extern bhv_vnode_t *vn_hold(struct bhv_vnode *);
526 462
527#if defined(XFS_VNODE_TRACE) 463#if defined(XFS_VNODE_TRACE)
528#define VN_HOLD(vp) \ 464#define VN_HOLD(vp) \
@@ -536,7 +472,7 @@ extern vnode_t *vn_hold(struct vnode *);
536#define VN_RELE(vp) (iput(vn_to_inode(vp))) 472#define VN_RELE(vp) (iput(vn_to_inode(vp)))
537#endif 473#endif
538 474
539static inline struct vnode *vn_grab(struct vnode *vp) 475static inline struct bhv_vnode *vn_grab(struct bhv_vnode *vp)
540{ 476{
541 struct inode *inode = igrab(vn_to_inode(vp)); 477 struct inode *inode = igrab(vn_to_inode(vp));
542 return inode ? vn_from_inode(inode) : NULL; 478 return inode ? vn_from_inode(inode) : NULL;
@@ -554,32 +490,39 @@ static inline struct vnode *vn_grab(struct vnode *vp)
554 */ 490 */
555#define VN_LOCK(vp) mutex_spinlock(&(vp)->v_lock) 491#define VN_LOCK(vp) mutex_spinlock(&(vp)->v_lock)
556#define VN_UNLOCK(vp, s) mutex_spinunlock(&(vp)->v_lock, s) 492#define VN_UNLOCK(vp, s) mutex_spinunlock(&(vp)->v_lock, s)
557#define VN_FLAGSET(vp,b) vn_flagset(vp,b)
558#define VN_FLAGCLR(vp,b) vn_flagclr(vp,b)
559 493
560static __inline__ void vn_flagset(struct vnode *vp, uint flag) 494static __inline__ void vn_flagset(struct bhv_vnode *vp, uint flag)
561{ 495{
562 spin_lock(&vp->v_lock); 496 spin_lock(&vp->v_lock);
563 vp->v_flag |= flag; 497 vp->v_flag |= flag;
564 spin_unlock(&vp->v_lock); 498 spin_unlock(&vp->v_lock);
565} 499}
566 500
567static __inline__ void vn_flagclr(struct vnode *vp, uint flag) 501static __inline__ uint vn_flagclr(struct bhv_vnode *vp, uint flag)
568{ 502{
503 uint cleared;
504
569 spin_lock(&vp->v_lock); 505 spin_lock(&vp->v_lock);
506 cleared = (vp->v_flag & flag);
570 vp->v_flag &= ~flag; 507 vp->v_flag &= ~flag;
571 spin_unlock(&vp->v_lock); 508 spin_unlock(&vp->v_lock);
509 return cleared;
572} 510}
573 511
512#define VMODIFY(vp) vn_flagset(vp, VMODIFIED)
513#define VUNMODIFY(vp) vn_flagclr(vp, VMODIFIED)
514#define VTRUNCATE(vp) vn_flagset(vp, VTRUNCATED)
515#define VUNTRUNCATE(vp) vn_flagclr(vp, VTRUNCATED)
516
574/* 517/*
575 * Dealing with bad inodes 518 * Dealing with bad inodes
576 */ 519 */
577static inline void vn_mark_bad(struct vnode *vp) 520static inline void vn_mark_bad(struct bhv_vnode *vp)
578{ 521{
579 make_bad_inode(vn_to_inode(vp)); 522 make_bad_inode(vn_to_inode(vp));
580} 523}
581 524
582static inline int VN_BAD(struct vnode *vp) 525static inline int VN_BAD(struct bhv_vnode *vp)
583{ 526{
584 return is_bad_inode(vn_to_inode(vp)); 527 return is_bad_inode(vn_to_inode(vp));
585} 528}
@@ -587,18 +530,18 @@ static inline int VN_BAD(struct vnode *vp)
587/* 530/*
588 * Extracting atime values in various formats 531 * Extracting atime values in various formats
589 */ 532 */
590static inline void vn_atime_to_bstime(struct vnode *vp, xfs_bstime_t *bs_atime) 533static inline void vn_atime_to_bstime(bhv_vnode_t *vp, xfs_bstime_t *bs_atime)
591{ 534{
592 bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec; 535 bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec;
593 bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec; 536 bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec;
594} 537}
595 538
596static inline void vn_atime_to_timespec(struct vnode *vp, struct timespec *ts) 539static inline void vn_atime_to_timespec(bhv_vnode_t *vp, struct timespec *ts)
597{ 540{
598 *ts = vp->v_inode.i_atime; 541 *ts = vp->v_inode.i_atime;
599} 542}
600 543
601static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt) 544static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt)
602{ 545{
603 *tt = vp->v_inode.i_atime.tv_sec; 546 *tt = vp->v_inode.i_atime.tv_sec;
604} 547}
@@ -610,11 +553,10 @@ static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt)
610#define VN_CACHED(vp) (vn_to_inode(vp)->i_mapping->nrpages) 553#define VN_CACHED(vp) (vn_to_inode(vp)->i_mapping->nrpages)
611#define VN_DIRTY(vp) mapping_tagged(vn_to_inode(vp)->i_mapping, \ 554#define VN_DIRTY(vp) mapping_tagged(vn_to_inode(vp)->i_mapping, \
612 PAGECACHE_TAG_DIRTY) 555 PAGECACHE_TAG_DIRTY)
613#define VMODIFY(vp) VN_FLAGSET(vp, VMODIFIED) 556#define VN_TRUNC(vp) ((vp)->v_flag & VTRUNCATED)
614#define VUNMODIFY(vp) VN_FLAGCLR(vp, VMODIFIED)
615 557
616/* 558/*
617 * Flags to VOP_SETATTR/VOP_GETATTR. 559 * Flags to vop_setattr/getattr.
618 */ 560 */
619#define ATTR_UTIME 0x01 /* non-default utime(2) request */ 561#define ATTR_UTIME 0x01 /* non-default utime(2) request */
620#define ATTR_DMI 0x08 /* invocation from a DMI function */ 562#define ATTR_DMI 0x08 /* invocation from a DMI function */
@@ -624,7 +566,7 @@ static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt)
624#define ATTR_NOSIZETOK 0x400 /* Don't get the SIZE token */ 566#define ATTR_NOSIZETOK 0x400 /* Don't get the SIZE token */
625 567
626/* 568/*
627 * Flags to VOP_FSYNC and VOP_RECLAIM. 569 * Flags to vop_fsync/reclaim.
628 */ 570 */
629#define FSYNC_NOWAIT 0 /* asynchronous flush */ 571#define FSYNC_NOWAIT 0 /* asynchronous flush */
630#define FSYNC_WAIT 0x1 /* synchronous fsync or forced reclaim */ 572#define FSYNC_WAIT 0x1 /* synchronous fsync or forced reclaim */
@@ -643,11 +585,11 @@ static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt)
643#define VNODE_KTRACE_REF 4 585#define VNODE_KTRACE_REF 4
644#define VNODE_KTRACE_RELE 5 586#define VNODE_KTRACE_RELE 5
645 587
646extern void vn_trace_entry(struct vnode *, const char *, inst_t *); 588extern void vn_trace_entry(struct bhv_vnode *, const char *, inst_t *);
647extern void vn_trace_exit(struct vnode *, const char *, inst_t *); 589extern void vn_trace_exit(struct bhv_vnode *, const char *, inst_t *);
648extern void vn_trace_hold(struct vnode *, char *, int, inst_t *); 590extern void vn_trace_hold(struct bhv_vnode *, char *, int, inst_t *);
649extern void vn_trace_ref(struct vnode *, char *, int, inst_t *); 591extern void vn_trace_ref(struct bhv_vnode *, char *, int, inst_t *);
650extern void vn_trace_rele(struct vnode *, char *, int, inst_t *); 592extern void vn_trace_rele(struct bhv_vnode *, char *, int, inst_t *);
651 593
652#define VN_TRACE(vp) \ 594#define VN_TRACE(vp) \
653 vn_trace_ref(vp, __FILE__, __LINE__, (inst_t *)__return_address) 595 vn_trace_ref(vp, __FILE__, __LINE__, (inst_t *)__return_address)
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 772ac48329ea..3aa771531856 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
@@ -444,7 +442,7 @@ xfs_qm_dqalloc(
444 XFS_BMAPI_METADATA | XFS_BMAPI_WRITE, 442 XFS_BMAPI_METADATA | XFS_BMAPI_WRITE,
445 &firstblock, 443 &firstblock,
446 XFS_QM_DQALLOC_SPACE_RES(mp), 444 XFS_QM_DQALLOC_SPACE_RES(mp),
447 &map, &nmaps, &flist))) { 445 &map, &nmaps, &flist, NULL))) {
448 goto error0; 446 goto error0;
449 } 447 }
450 ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB); 448 ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB);
@@ -559,7 +557,7 @@ xfs_qm_dqtobp(
559 error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset, 557 error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset,
560 XFS_DQUOT_CLUSTER_SIZE_FSB, 558 XFS_DQUOT_CLUSTER_SIZE_FSB,
561 XFS_BMAPI_METADATA, 559 XFS_BMAPI_METADATA,
562 NULL, 0, &map, &nmaps, NULL); 560 NULL, 0, &map, &nmaps, NULL, NULL);
563 561
564 xfs_iunlock(quotip, XFS_ILOCK_SHARED); 562 xfs_iunlock(quotip, XFS_ILOCK_SHARED);
565 if (error) 563 if (error)
@@ -1261,7 +1259,7 @@ xfs_qm_dqflush(
1261 1259
1262 if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id), 1260 if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id),
1263 0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) { 1261 0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
1264 xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE); 1262 xfs_force_shutdown(dqp->q_mount, SHUTDOWN_CORRUPT_INCORE);
1265 return XFS_ERROR(EIO); 1263 return XFS_ERROR(EIO);
1266 } 1264 }
1267 1265
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index c0c629663a5c..78d3ab95c5fd 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -119,7 +119,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
119 */ 119 */
120#define xfs_dqflock(dqp) { psema(&((dqp)->q_flock), PINOD | PRECALC);\ 120#define xfs_dqflock(dqp) { psema(&((dqp)->q_flock), PINOD | PRECALC);\
121 (dqp)->dq_flags |= XFS_DQ_FLOCKED; } 121 (dqp)->dq_flags |= XFS_DQ_FLOCKED; }
122#define xfs_dqfunlock(dqp) { ASSERT(valusema(&((dqp)->q_flock)) <= 0); \ 122#define xfs_dqfunlock(dqp) { ASSERT(issemalocked(&((dqp)->q_flock))); \
123 vsema(&((dqp)->q_flock)); \ 123 vsema(&((dqp)->q_flock)); \
124 (dqp)->dq_flags &= ~(XFS_DQ_FLOCKED); } 124 (dqp)->dq_flags &= ~(XFS_DQ_FLOCKED); }
125 125
@@ -128,7 +128,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
128#define XFS_DQ_PINUNLOCK(dqp, s) mutex_spinunlock( \ 128#define XFS_DQ_PINUNLOCK(dqp, s) mutex_spinunlock( \
129 &(XFS_DQ_TO_QINF(dqp)->qi_pinlock), s) 129 &(XFS_DQ_TO_QINF(dqp)->qi_pinlock), s)
130 130
131#define XFS_DQ_IS_FLUSH_LOCKED(dqp) (valusema(&((dqp)->q_flock)) <= 0) 131#define XFS_DQ_IS_FLUSH_LOCKED(dqp) (issemalocked(&((dqp)->q_flock)))
132#define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) 132#define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp))
133#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) 133#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY)
134#define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) 134#define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER)
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index 546f48af882a..5b2dcc58b244 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
@@ -248,7 +246,7 @@ xfs_qm_dquot_logitem_pushbuf(
248 * inode flush completed and the inode was taken off the AIL. 246 * inode flush completed and the inode was taken off the AIL.
249 * So, just get out. 247 * So, just get out.
250 */ 248 */
251 if ((valusema(&(dqp->q_flock)) > 0) || 249 if (!issemalocked(&(dqp->q_flock)) ||
252 ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) { 250 ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) {
253 qip->qli_pushbuf_flag = 0; 251 qip->qli_pushbuf_flag = 0;
254 xfs_dqunlock(dqp); 252 xfs_dqunlock(dqp);
@@ -261,7 +259,7 @@ xfs_qm_dquot_logitem_pushbuf(
261 if (bp != NULL) { 259 if (bp != NULL) {
262 if (XFS_BUF_ISDELAYWRITE(bp)) { 260 if (XFS_BUF_ISDELAYWRITE(bp)) {
263 dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) && 261 dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) &&
264 (valusema(&(dqp->q_flock)) <= 0)); 262 issemalocked(&(dqp->q_flock)));
265 qip->qli_pushbuf_flag = 0; 263 qip->qli_pushbuf_flag = 0;
266 xfs_dqunlock(dqp); 264 xfs_dqunlock(dqp);
267 265
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 7fb5eca9bd50..e23e45535c48 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -24,7 +24,6 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_alloc.h" 28#include "xfs_alloc.h"
30#include "xfs_dmapi.h" 29#include "xfs_dmapi.h"
@@ -33,7 +32,6 @@
33#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
34#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
35#include "xfs_ialloc_btree.h" 34#include "xfs_ialloc_btree.h"
36#include "xfs_dir_sf.h"
37#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
38#include "xfs_attr_sf.h" 36#include "xfs_attr_sf.h"
39#include "xfs_dinode.h" 37#include "xfs_dinode.h"
@@ -1603,7 +1601,7 @@ xfs_qm_dqiterate(
1603 maxlblkcnt - lblkno, 1601 maxlblkcnt - lblkno,
1604 XFS_BMAPI_METADATA, 1602 XFS_BMAPI_METADATA,
1605 NULL, 1603 NULL,
1606 0, map, &nmaps, NULL); 1604 0, map, &nmaps, NULL, NULL);
1607 xfs_iunlock(qip, XFS_ILOCK_SHARED); 1605 xfs_iunlock(qip, XFS_ILOCK_SHARED);
1608 if (error) 1606 if (error)
1609 break; 1607 break;
@@ -1905,9 +1903,7 @@ xfs_qm_quotacheck(
1905 */ 1903 */
1906 if ((error = xfs_bulkstat(mp, &lastino, &count, 1904 if ((error = xfs_bulkstat(mp, &lastino, &count,
1907 xfs_qm_dqusage_adjust, NULL, 1905 xfs_qm_dqusage_adjust, NULL,
1908 structsz, NULL, 1906 structsz, NULL, BULKSTAT_FG_IGET, &done)))
1909 BULKSTAT_FG_IGET|BULKSTAT_FG_VFSLOCKED,
1910 &done)))
1911 break; 1907 break;
1912 1908
1913 } while (! done); 1909 } while (! done);
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index 6838b36d95a9..e95e99f7168f 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -24,7 +24,6 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_alloc.h" 28#include "xfs_alloc.h"
30#include "xfs_dmapi.h" 29#include "xfs_dmapi.h"
@@ -33,7 +32,6 @@
33#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
34#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
35#include "xfs_ialloc_btree.h" 34#include "xfs_ialloc_btree.h"
36#include "xfs_dir_sf.h"
37#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
38#include "xfs_attr_sf.h" 36#include "xfs_attr_sf.h"
39#include "xfs_dinode.h" 37#include "xfs_dinode.h"
@@ -129,7 +127,7 @@ xfs_qm_parseargs(
129 return XFS_ERROR(EINVAL); 127 return XFS_ERROR(EINVAL);
130 } 128 }
131 129
132 PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error); 130 error = bhv_next_vfs_parseargs(BHV_NEXT(bhv), options, args, update);
133 if (!error && !referenced) 131 if (!error && !referenced)
134 bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM); 132 bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM);
135 return error; 133 return error;
@@ -140,9 +138,8 @@ xfs_qm_showargs(
140 struct bhv_desc *bhv, 138 struct bhv_desc *bhv,
141 struct seq_file *m) 139 struct seq_file *m)
142{ 140{
143 struct vfs *vfsp = bhvtovfs(bhv); 141 struct bhv_vfs *vfsp = bhvtovfs(bhv);
144 struct xfs_mount *mp = XFS_VFSTOM(vfsp); 142 struct xfs_mount *mp = XFS_VFSTOM(vfsp);
145 int error;
146 143
147 if (mp->m_qflags & XFS_UQUOTA_ACCT) { 144 if (mp->m_qflags & XFS_UQUOTA_ACCT) {
148 (mp->m_qflags & XFS_UQUOTA_ENFD) ? 145 (mp->m_qflags & XFS_UQUOTA_ENFD) ?
@@ -165,8 +162,7 @@ xfs_qm_showargs(
165 if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT)) 162 if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
166 seq_puts(m, "," MNTOPT_NOQUOTA); 163 seq_puts(m, "," MNTOPT_NOQUOTA);
167 164
168 PVFS_SHOWARGS(BHV_NEXT(bhv), m, error); 165 return bhv_next_vfs_showargs(BHV_NEXT(bhv), m);
169 return error;
170} 166}
171 167
172STATIC int 168STATIC int
@@ -175,14 +171,67 @@ xfs_qm_mount(
175 struct xfs_mount_args *args, 171 struct xfs_mount_args *args,
176 struct cred *cr) 172 struct cred *cr)
177{ 173{
178 struct vfs *vfsp = bhvtovfs(bhv); 174 struct bhv_vfs *vfsp = bhvtovfs(bhv);
179 struct xfs_mount *mp = XFS_VFSTOM(vfsp); 175 struct xfs_mount *mp = XFS_VFSTOM(vfsp);
180 int error;
181 176
182 if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA)) 177 if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA))
183 xfs_qm_mount_quotainit(mp, args->flags); 178 xfs_qm_mount_quotainit(mp, args->flags);
184 PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error); 179 return bhv_next_vfs_mount(BHV_NEXT(bhv), args, cr);
185 return error; 180}
181
182/*
183 * Directory tree accounting is implemented using project quotas, where
184 * the project identifier is inherited from parent directories.
185 * A statvfs (df, etc.) of a directory that is using project quota should
186 * return a statvfs of the project, not the entire filesystem.
187 * This makes such trees appear as if they are filesystems in themselves.
188 */
189STATIC int
190xfs_qm_statvfs(
191 struct bhv_desc *bhv,
192 bhv_statvfs_t *statp,
193 struct bhv_vnode *vnode)
194{
195 xfs_mount_t *mp;
196 xfs_inode_t *ip;
197 xfs_dquot_t *dqp;
198 xfs_disk_dquot_t *dp;
199 __uint64_t limit;
200 int error;
201
202 error = bhv_next_vfs_statvfs(BHV_NEXT(bhv), statp, vnode);
203 if (error || !vnode)
204 return error;
205
206 mp = XFS_BHVTOM(bhv);
207 ip = xfs_vtoi(vnode);
208
209 if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT))
210 return 0;
211 if (!(mp->m_qflags & XFS_PQUOTA_ACCT))
212 return 0;
213 if (!(mp->m_qflags & XFS_OQUOTA_ENFD))
214 return 0;
215
216 if (xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp))
217 return 0;
218 dp = &dqp->q_core;
219
220 limit = dp->d_blk_softlimit ? dp->d_blk_softlimit : dp->d_blk_hardlimit;
221 if (limit && statp->f_blocks > limit) {
222 statp->f_blocks = limit;
223 statp->f_bfree = (statp->f_blocks > dp->d_bcount) ?
224 (statp->f_blocks - dp->d_bcount) : 0;
225 }
226 limit = dp->d_ino_softlimit ? dp->d_ino_softlimit : dp->d_ino_hardlimit;
227 if (limit && statp->f_files > limit) {
228 statp->f_files = limit;
229 statp->f_ffree = (statp->f_files > dp->d_icount) ?
230 (statp->f_ffree - dp->d_icount) : 0;
231 }
232
233 xfs_qm_dqput(dqp);
234 return 0;
186} 235}
187 236
188STATIC int 237STATIC int
@@ -191,7 +240,7 @@ xfs_qm_syncall(
191 int flags, 240 int flags,
192 cred_t *credp) 241 cred_t *credp)
193{ 242{
194 struct vfs *vfsp = bhvtovfs(bhv); 243 struct bhv_vfs *vfsp = bhvtovfs(bhv);
195 struct xfs_mount *mp = XFS_VFSTOM(vfsp); 244 struct xfs_mount *mp = XFS_VFSTOM(vfsp);
196 int error; 245 int error;
197 246
@@ -210,8 +259,7 @@ xfs_qm_syncall(
210 } 259 }
211 } 260 }
212 } 261 }
213 PVFS_SYNC(BHV_NEXT(bhv), flags, credp, error); 262 return bhv_next_vfs_sync(BHV_NEXT(bhv), flags, credp);
214 return error;
215} 263}
216 264
217STATIC int 265STATIC int
@@ -346,11 +394,12 @@ STATIC struct xfs_qmops xfs_qmcore_xfs = {
346 .xfs_dqtrxops = &xfs_trans_dquot_ops, 394 .xfs_dqtrxops = &xfs_trans_dquot_ops,
347}; 395};
348 396
349struct bhv_vfsops xfs_qmops = { { 397struct bhv_module_vfsops xfs_qmops = { {
350 BHV_IDENTITY_INIT(VFS_BHV_QM, VFS_POSITION_QM), 398 BHV_IDENTITY_INIT(VFS_BHV_QM, VFS_POSITION_QM),
351 .vfs_parseargs = xfs_qm_parseargs, 399 .vfs_parseargs = xfs_qm_parseargs,
352 .vfs_showargs = xfs_qm_showargs, 400 .vfs_showargs = xfs_qm_showargs,
353 .vfs_mount = xfs_qm_mount, 401 .vfs_mount = xfs_qm_mount,
402 .vfs_statvfs = xfs_qm_statvfs,
354 .vfs_sync = xfs_qm_syncall, 403 .vfs_sync = xfs_qm_syncall,
355 .vfs_quotactl = xfs_qm_quotactl, }, 404 .vfs_quotactl = xfs_qm_quotactl, },
356}; 405};
diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c
index 0570f7733550..6f858fb81a36 100644
--- a/fs/xfs/quota/xfs_qm_stats.c
+++ b/fs/xfs/quota/xfs_qm_stats.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index c55db463bbf2..ed620c4d1594 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -26,7 +26,6 @@
26#include "xfs_trans.h" 26#include "xfs_trans.h"
27#include "xfs_sb.h" 27#include "xfs_sb.h"
28#include "xfs_ag.h" 28#include "xfs_ag.h"
29#include "xfs_dir.h"
30#include "xfs_dir2.h" 29#include "xfs_dir2.h"
31#include "xfs_alloc.h" 30#include "xfs_alloc.h"
32#include "xfs_dmapi.h" 31#include "xfs_dmapi.h"
@@ -35,7 +34,6 @@
35#include "xfs_bmap_btree.h" 34#include "xfs_bmap_btree.h"
36#include "xfs_alloc_btree.h" 35#include "xfs_alloc_btree.h"
37#include "xfs_ialloc_btree.h" 36#include "xfs_ialloc_btree.h"
38#include "xfs_dir_sf.h"
39#include "xfs_dir2_sf.h" 37#include "xfs_dir2_sf.h"
40#include "xfs_attr_sf.h" 38#include "xfs_attr_sf.h"
41#include "xfs_dinode.h" 39#include "xfs_dinode.h"
@@ -91,8 +89,8 @@ xfs_qm_quotactl(
91 xfs_caddr_t addr) 89 xfs_caddr_t addr)
92{ 90{
93 xfs_mount_t *mp; 91 xfs_mount_t *mp;
92 bhv_vfs_t *vfsp;
94 int error; 93 int error;
95 struct vfs *vfsp;
96 94
97 vfsp = bhvtovfs(bdp); 95 vfsp = bhvtovfs(bdp);
98 mp = XFS_VFSTOM(vfsp); 96 mp = XFS_VFSTOM(vfsp);
@@ -1035,7 +1033,7 @@ xfs_qm_dqrele_all_inodes(
1035{ 1033{
1036 xfs_inode_t *ip, *topino; 1034 xfs_inode_t *ip, *topino;
1037 uint ireclaims; 1035 uint ireclaims;
1038 vnode_t *vp; 1036 bhv_vnode_t *vp;
1039 boolean_t vnode_refd; 1037 boolean_t vnode_refd;
1040 1038
1041 ASSERT(mp->m_quotainfo); 1039 ASSERT(mp->m_quotainfo);
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 9168918db252..0242e9666e8e 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -33,7 +32,6 @@
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
36#include "xfs_dir_sf.h"
37#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
39#include "xfs_inode.h" 37#include "xfs_inode.h"
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
index b08b3d9345b7..36fbeccdc722 100644
--- a/fs/xfs/support/debug.c
+++ b/fs/xfs/support/debug.c
@@ -47,7 +47,7 @@ cmn_err(register int level, char *fmt, ...)
47 va_start(ap, fmt); 47 va_start(ap, fmt);
48 if (*fmt == '!') fp++; 48 if (*fmt == '!') fp++;
49 len = vsprintf(message, fp, ap); 49 len = vsprintf(message, fp, ap);
50 if (message[len-1] != '\n') 50 if (level != CE_DEBUG && message[len-1] != '\n')
51 strcat(message, "\n"); 51 strcat(message, "\n");
52 printk("%s%s", err_level[level], message); 52 printk("%s%s", err_level[level], message);
53 va_end(ap); 53 va_end(ap);
@@ -68,7 +68,7 @@ icmn_err(register int level, char *fmt, va_list ap)
68 level = XFS_MAX_ERR_LEVEL; 68 level = XFS_MAX_ERR_LEVEL;
69 spin_lock_irqsave(&xfs_err_lock,flags); 69 spin_lock_irqsave(&xfs_err_lock,flags);
70 len = vsprintf(message, fmt, ap); 70 len = vsprintf(message, fmt, ap);
71 if (message[len-1] != '\n') 71 if (level != CE_DEBUG && message[len-1] != '\n')
72 strcat(message, "\n"); 72 strcat(message, "\n");
73 spin_unlock_irqrestore(&xfs_err_lock,flags); 73 spin_unlock_irqrestore(&xfs_err_lock,flags);
74 printk("%s%s", err_level[level], message); 74 printk("%s%s", err_level[level], message);
diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h
index e3bf58112e7e..4f54dca662a8 100644
--- a/fs/xfs/support/debug.h
+++ b/fs/xfs/support/debug.h
@@ -33,9 +33,6 @@ extern void cmn_err(int, char *, ...)
33 __attribute__ ((format (printf, 2, 3))); 33 __attribute__ ((format (printf, 2, 3)));
34extern void assfail(char *expr, char *f, int l); 34extern void assfail(char *expr, char *f, int l);
35 35
36#define prdev(fmt,targ,args...) \
37 printk("Device %s - " fmt "\n", XFS_BUFTARG_NAME(targ), ## args)
38
39#define ASSERT_ALWAYS(expr) \ 36#define ASSERT_ALWAYS(expr) \
40 (unlikely((expr) != 0) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) 37 (unlikely((expr) != 0) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
41 38
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 2539af34eb63..4b0cb474be4c 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -21,12 +21,10 @@
21#include "xfs_bit.h" 21#include "xfs_bit.h"
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_ag.h" 23#include "xfs_ag.h"
24#include "xfs_dir.h"
25#include "xfs_dir2.h" 24#include "xfs_dir2.h"
26#include "xfs_bmap_btree.h" 25#include "xfs_bmap_btree.h"
27#include "xfs_alloc_btree.h" 26#include "xfs_alloc_btree.h"
28#include "xfs_ialloc_btree.h" 27#include "xfs_ialloc_btree.h"
29#include "xfs_dir_sf.h"
30#include "xfs_dir2_sf.h" 28#include "xfs_dir2_sf.h"
31#include "xfs_attr_sf.h" 29#include "xfs_attr_sf.h"
32#include "xfs_dinode.h" 30#include "xfs_dinode.h"
@@ -39,15 +37,15 @@
39#include <linux/capability.h> 37#include <linux/capability.h>
40#include <linux/posix_acl_xattr.h> 38#include <linux/posix_acl_xattr.h>
41 39
42STATIC int xfs_acl_setmode(vnode_t *, xfs_acl_t *, int *); 40STATIC int xfs_acl_setmode(bhv_vnode_t *, xfs_acl_t *, int *);
43STATIC void xfs_acl_filter_mode(mode_t, xfs_acl_t *); 41STATIC void xfs_acl_filter_mode(mode_t, xfs_acl_t *);
44STATIC void xfs_acl_get_endian(xfs_acl_t *); 42STATIC void xfs_acl_get_endian(xfs_acl_t *);
45STATIC int xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *); 43STATIC int xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *);
46STATIC int xfs_acl_invalid(xfs_acl_t *); 44STATIC int xfs_acl_invalid(xfs_acl_t *);
47STATIC void xfs_acl_sync_mode(mode_t, xfs_acl_t *); 45STATIC void xfs_acl_sync_mode(mode_t, xfs_acl_t *);
48STATIC void xfs_acl_get_attr(vnode_t *, xfs_acl_t *, int, int, int *); 46STATIC void xfs_acl_get_attr(bhv_vnode_t *, xfs_acl_t *, int, int, int *);
49STATIC void xfs_acl_set_attr(vnode_t *, xfs_acl_t *, int, int *); 47STATIC void xfs_acl_set_attr(bhv_vnode_t *, xfs_acl_t *, int, int *);
50STATIC int xfs_acl_allow_set(vnode_t *, int); 48STATIC int xfs_acl_allow_set(bhv_vnode_t *, int);
51 49
52kmem_zone_t *xfs_acl_zone; 50kmem_zone_t *xfs_acl_zone;
53 51
@@ -57,7 +55,7 @@ kmem_zone_t *xfs_acl_zone;
57 */ 55 */
58int 56int
59xfs_acl_vhasacl_access( 57xfs_acl_vhasacl_access(
60 vnode_t *vp) 58 bhv_vnode_t *vp)
61{ 59{
62 int error; 60 int error;
63 61
@@ -70,7 +68,7 @@ xfs_acl_vhasacl_access(
70 */ 68 */
71int 69int
72xfs_acl_vhasacl_default( 70xfs_acl_vhasacl_default(
73 vnode_t *vp) 71 bhv_vnode_t *vp)
74{ 72{
75 int error; 73 int error;
76 74
@@ -209,7 +207,7 @@ posix_acl_xfs_to_xattr(
209 207
210int 208int
211xfs_acl_vget( 209xfs_acl_vget(
212 vnode_t *vp, 210 bhv_vnode_t *vp,
213 void *acl, 211 void *acl,
214 size_t size, 212 size_t size,
215 int kind) 213 int kind)
@@ -241,10 +239,10 @@ xfs_acl_vget(
241 goto out; 239 goto out;
242 } 240 }
243 if (kind == _ACL_TYPE_ACCESS) { 241 if (kind == _ACL_TYPE_ACCESS) {
244 vattr_t va; 242 bhv_vattr_t va;
245 243
246 va.va_mask = XFS_AT_MODE; 244 va.va_mask = XFS_AT_MODE;
247 VOP_GETATTR(vp, &va, 0, sys_cred, error); 245 error = bhv_vop_getattr(vp, &va, 0, sys_cred);
248 if (error) 246 if (error)
249 goto out; 247 goto out;
250 xfs_acl_sync_mode(va.va_mode, xfs_acl); 248 xfs_acl_sync_mode(va.va_mode, xfs_acl);
@@ -260,7 +258,7 @@ out:
260 258
261int 259int
262xfs_acl_vremove( 260xfs_acl_vremove(
263 vnode_t *vp, 261 bhv_vnode_t *vp,
264 int kind) 262 int kind)
265{ 263{
266 int error; 264 int error;
@@ -268,9 +266,9 @@ xfs_acl_vremove(
268 VN_HOLD(vp); 266 VN_HOLD(vp);
269 error = xfs_acl_allow_set(vp, kind); 267 error = xfs_acl_allow_set(vp, kind);
270 if (!error) { 268 if (!error) {
271 VOP_ATTR_REMOVE(vp, kind == _ACL_TYPE_DEFAULT? 269 error = bhv_vop_attr_remove(vp, kind == _ACL_TYPE_DEFAULT?
272 SGI_ACL_DEFAULT: SGI_ACL_FILE, 270 SGI_ACL_DEFAULT: SGI_ACL_FILE,
273 ATTR_ROOT, sys_cred, error); 271 ATTR_ROOT, sys_cred);
274 if (error == ENOATTR) 272 if (error == ENOATTR)
275 error = 0; /* 'scool */ 273 error = 0; /* 'scool */
276 } 274 }
@@ -280,7 +278,7 @@ xfs_acl_vremove(
280 278
281int 279int
282xfs_acl_vset( 280xfs_acl_vset(
283 vnode_t *vp, 281 bhv_vnode_t *vp,
284 void *acl, 282 void *acl,
285 size_t size, 283 size_t size,
286 int kind) 284 int kind)
@@ -370,10 +368,10 @@ xfs_acl_iaccess(
370 368
371STATIC int 369STATIC int
372xfs_acl_allow_set( 370xfs_acl_allow_set(
373 vnode_t *vp, 371 bhv_vnode_t *vp,
374 int kind) 372 int kind)
375{ 373{
376 vattr_t va; 374 bhv_vattr_t va;
377 int error; 375 int error;
378 376
379 if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND)) 377 if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
@@ -383,7 +381,7 @@ xfs_acl_allow_set(
383 if (vp->v_vfsp->vfs_flag & VFS_RDONLY) 381 if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
384 return EROFS; 382 return EROFS;
385 va.va_mask = XFS_AT_UID; 383 va.va_mask = XFS_AT_UID;
386 VOP_GETATTR(vp, &va, 0, NULL, error); 384 error = bhv_vop_getattr(vp, &va, 0, NULL);
387 if (error) 385 if (error)
388 return error; 386 return error;
389 if (va.va_uid != current->fsuid && !capable(CAP_FOWNER)) 387 if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
@@ -606,7 +604,7 @@ xfs_acl_get_endian(
606 */ 604 */
607STATIC void 605STATIC void
608xfs_acl_get_attr( 606xfs_acl_get_attr(
609 vnode_t *vp, 607 bhv_vnode_t *vp,
610 xfs_acl_t *aclp, 608 xfs_acl_t *aclp,
611 int kind, 609 int kind,
612 int flags, 610 int flags,
@@ -616,9 +614,9 @@ xfs_acl_get_attr(
616 614
617 ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1); 615 ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1);
618 flags |= ATTR_ROOT; 616 flags |= ATTR_ROOT;
619 VOP_ATTR_GET(vp, 617 *error = bhv_vop_attr_get(vp, kind == _ACL_TYPE_ACCESS ?
620 kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE : SGI_ACL_DEFAULT, 618 SGI_ACL_FILE : SGI_ACL_DEFAULT,
621 (char *)aclp, &len, flags, sys_cred, *error); 619 (char *)aclp, &len, flags, sys_cred);
622 if (*error || (flags & ATTR_KERNOVAL)) 620 if (*error || (flags & ATTR_KERNOVAL))
623 return; 621 return;
624 xfs_acl_get_endian(aclp); 622 xfs_acl_get_endian(aclp);
@@ -629,7 +627,7 @@ xfs_acl_get_attr(
629 */ 627 */
630STATIC void 628STATIC void
631xfs_acl_set_attr( 629xfs_acl_set_attr(
632 vnode_t *vp, 630 bhv_vnode_t *vp,
633 xfs_acl_t *aclp, 631 xfs_acl_t *aclp,
634 int kind, 632 int kind,
635 int *error) 633 int *error)
@@ -654,19 +652,19 @@ xfs_acl_set_attr(
654 INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm); 652 INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm);
655 } 653 }
656 INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt); 654 INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
657 VOP_ATTR_SET(vp, 655 *error = bhv_vop_attr_set(vp, kind == _ACL_TYPE_ACCESS ?
658 kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE: SGI_ACL_DEFAULT, 656 SGI_ACL_FILE: SGI_ACL_DEFAULT,
659 (char *)newacl, len, ATTR_ROOT, sys_cred, *error); 657 (char *)newacl, len, ATTR_ROOT, sys_cred);
660 _ACL_FREE(newacl); 658 _ACL_FREE(newacl);
661} 659}
662 660
663int 661int
664xfs_acl_vtoacl( 662xfs_acl_vtoacl(
665 vnode_t *vp, 663 bhv_vnode_t *vp,
666 xfs_acl_t *access_acl, 664 xfs_acl_t *access_acl,
667 xfs_acl_t *default_acl) 665 xfs_acl_t *default_acl)
668{ 666{
669 vattr_t va; 667 bhv_vattr_t va;
670 int error = 0; 668 int error = 0;
671 669
672 if (access_acl) { 670 if (access_acl) {
@@ -678,7 +676,7 @@ xfs_acl_vtoacl(
678 if (!error) { 676 if (!error) {
679 /* Got the ACL, need the mode... */ 677 /* Got the ACL, need the mode... */
680 va.va_mask = XFS_AT_MODE; 678 va.va_mask = XFS_AT_MODE;
681 VOP_GETATTR(vp, &va, 0, sys_cred, error); 679 error = bhv_vop_getattr(vp, &va, 0, sys_cred);
682 } 680 }
683 681
684 if (error) 682 if (error)
@@ -701,8 +699,8 @@ xfs_acl_vtoacl(
701 */ 699 */
702int 700int
703xfs_acl_inherit( 701xfs_acl_inherit(
704 vnode_t *vp, 702 bhv_vnode_t *vp,
705 vattr_t *vap, 703 bhv_vattr_t *vap,
706 xfs_acl_t *pdaclp) 704 xfs_acl_t *pdaclp)
707{ 705{
708 xfs_acl_t *cacl; 706 xfs_acl_t *cacl;
@@ -757,11 +755,11 @@ xfs_acl_inherit(
757 */ 755 */
758STATIC int 756STATIC int
759xfs_acl_setmode( 757xfs_acl_setmode(
760 vnode_t *vp, 758 bhv_vnode_t *vp,
761 xfs_acl_t *acl, 759 xfs_acl_t *acl,
762 int *basicperms) 760 int *basicperms)
763{ 761{
764 vattr_t va; 762 bhv_vattr_t va;
765 xfs_acl_entry_t *ap; 763 xfs_acl_entry_t *ap;
766 xfs_acl_entry_t *gap = NULL; 764 xfs_acl_entry_t *gap = NULL;
767 int i, error, nomask = 1; 765 int i, error, nomask = 1;
@@ -776,7 +774,7 @@ xfs_acl_setmode(
776 * mode. The m:: bits take precedence over the g:: bits. 774 * mode. The m:: bits take precedence over the g:: bits.
777 */ 775 */
778 va.va_mask = XFS_AT_MODE; 776 va.va_mask = XFS_AT_MODE;
779 VOP_GETATTR(vp, &va, 0, sys_cred, error); 777 error = bhv_vop_getattr(vp, &va, 0, sys_cred);
780 if (error) 778 if (error)
781 return error; 779 return error;
782 780
@@ -810,8 +808,7 @@ xfs_acl_setmode(
810 if (gap && nomask) 808 if (gap && nomask)
811 va.va_mode |= gap->ae_perm << 3; 809 va.va_mode |= gap->ae_perm << 3;
812 810
813 VOP_SETATTR(vp, &va, 0, sys_cred, error); 811 return bhv_vop_setattr(vp, &va, 0, sys_cred);
814 return error;
815} 812}
816 813
817/* 814/*
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 538d0d65b04c..f853cf1a6270 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -50,7 +50,7 @@ typedef struct xfs_acl {
50#ifdef CONFIG_XFS_POSIX_ACL 50#ifdef CONFIG_XFS_POSIX_ACL
51 51
52struct vattr; 52struct vattr;
53struct vnode; 53struct bhv_vnode;
54struct xfs_inode; 54struct xfs_inode;
55 55
56extern struct kmem_zone *xfs_acl_zone; 56extern struct kmem_zone *xfs_acl_zone;
@@ -58,14 +58,14 @@ extern struct kmem_zone *xfs_acl_zone;
58 (zone) = kmem_zone_init(sizeof(xfs_acl_t), (name)) 58 (zone) = kmem_zone_init(sizeof(xfs_acl_t), (name))
59#define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone) 59#define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone)
60 60
61extern int xfs_acl_inherit(struct vnode *, struct vattr *, xfs_acl_t *); 61extern int xfs_acl_inherit(struct bhv_vnode *, struct bhv_vattr *, xfs_acl_t *);
62extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *); 62extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *);
63extern int xfs_acl_vtoacl(struct vnode *, xfs_acl_t *, xfs_acl_t *); 63extern int xfs_acl_vtoacl(struct bhv_vnode *, xfs_acl_t *, xfs_acl_t *);
64extern int xfs_acl_vhasacl_access(struct vnode *); 64extern int xfs_acl_vhasacl_access(struct bhv_vnode *);
65extern int xfs_acl_vhasacl_default(struct vnode *); 65extern int xfs_acl_vhasacl_default(struct bhv_vnode *);
66extern int xfs_acl_vset(struct vnode *, void *, size_t, int); 66extern int xfs_acl_vset(struct bhv_vnode *, void *, size_t, int);
67extern int xfs_acl_vget(struct vnode *, void *, size_t, int); 67extern int xfs_acl_vget(struct bhv_vnode *, void *, size_t, int);
68extern int xfs_acl_vremove(struct vnode *vp, int); 68extern int xfs_acl_vremove(struct bhv_vnode *, int);
69 69
70#define _ACL_TYPE_ACCESS 1 70#define _ACL_TYPE_ACCESS 1
71#define _ACL_TYPE_DEFAULT 2 71#define _ACL_TYPE_DEFAULT 2
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 8558226281c4..eef6763f3a67 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
@@ -1862,7 +1860,7 @@ xfs_alloc_fix_freelist(
1862 (pag->pagf_longest - delta) : 1860 (pag->pagf_longest - delta) :
1863 (pag->pagf_flcount > 0 || pag->pagf_longest > 0); 1861 (pag->pagf_flcount > 0 || pag->pagf_longest > 0);
1864 if (args->minlen + args->alignment + args->minalignslop - 1 > longest || 1862 if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
1865 (args->minleft && 1863 (!(flags & XFS_ALLOC_FLAG_FREEING) &&
1866 (int)(pag->pagf_freeblks + pag->pagf_flcount - 1864 (int)(pag->pagf_freeblks + pag->pagf_flcount -
1867 need - args->total) < 1865 need - args->total) <
1868 (int)args->minleft)) { 1866 (int)args->minleft)) {
@@ -1898,7 +1896,7 @@ xfs_alloc_fix_freelist(
1898 longest = (longest > delta) ? (longest - delta) : 1896 longest = (longest > delta) ? (longest - delta) :
1899 (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0); 1897 (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0);
1900 if (args->minlen + args->alignment + args->minalignslop - 1 > longest || 1898 if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
1901 (args->minleft && 1899 (!(flags & XFS_ALLOC_FLAG_FREEING) &&
1902 (int)(be32_to_cpu(agf->agf_freeblks) + 1900 (int)(be32_to_cpu(agf->agf_freeblks) +
1903 be32_to_cpu(agf->agf_flcount) - need - args->total) < 1901 be32_to_cpu(agf->agf_flcount) - need - args->total) <
1904 (int)args->minleft)) { 1902 (int)args->minleft)) {
@@ -1951,8 +1949,14 @@ xfs_alloc_fix_freelist(
1951 * the restrictions correctly. Can happen for free calls 1949 * the restrictions correctly. Can happen for free calls
1952 * on a completely full ag. 1950 * on a completely full ag.
1953 */ 1951 */
1954 if (targs.agbno == NULLAGBLOCK) 1952 if (targs.agbno == NULLAGBLOCK) {
1953 if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
1954 xfs_trans_brelse(tp, agflbp);
1955 args->agbp = NULL;
1956 return 0;
1957 }
1955 break; 1958 break;
1959 }
1956 /* 1960 /*
1957 * Put each allocated block on the list. 1961 * Put each allocated block on the list.
1958 */ 1962 */
@@ -2360,8 +2364,19 @@ xfs_alloc_vextent(
2360 if (args->agno == sagno && 2364 if (args->agno == sagno &&
2361 type == XFS_ALLOCTYPE_START_BNO) 2365 type == XFS_ALLOCTYPE_START_BNO)
2362 args->type = XFS_ALLOCTYPE_THIS_AG; 2366 args->type = XFS_ALLOCTYPE_THIS_AG;
2363 if (++(args->agno) == mp->m_sb.sb_agcount) 2367 /*
2364 args->agno = 0; 2368 * For the first allocation, we can try any AG to get
2369 * space. However, if we already have allocated a
2370 * block, we don't want to try AGs whose number is below
2371 * sagno. Otherwise, we may end up with out-of-order
2372 * locking of AGF, which might cause deadlock.
2373 */
2374 if (++(args->agno) == mp->m_sb.sb_agcount) {
2375 if (args->firstblock != NULLFSBLOCK)
2376 args->agno = sagno;
2377 else
2378 args->agno = 0;
2379 }
2365 /* 2380 /*
2366 * Reached the starting a.g., must either be done 2381 * Reached the starting a.g., must either be done
2367 * or switch to non-trylock mode. 2382 * or switch to non-trylock mode.
@@ -2443,7 +2458,7 @@ xfs_free_extent(
2443 args.minlen = args.minleft = args.minalignslop = 0; 2458 args.minlen = args.minleft = args.minalignslop = 0;
2444 down_read(&args.mp->m_peraglock); 2459 down_read(&args.mp->m_peraglock);
2445 args.pag = &args.mp->m_perag[args.agno]; 2460 args.pag = &args.mp->m_perag[args.agno];
2446 if ((error = xfs_alloc_fix_freelist(&args, 0))) 2461 if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING)))
2447 goto error0; 2462 goto error0;
2448#ifdef DEBUG 2463#ifdef DEBUG
2449 ASSERT(args.agbp != NULL); 2464 ASSERT(args.agbp != NULL);
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h
index 2d1f8928b267..650591f999ae 100644
--- a/fs/xfs/xfs_alloc.h
+++ b/fs/xfs/xfs_alloc.h
@@ -41,6 +41,7 @@ typedef enum xfs_alloctype
41 * Flags for xfs_alloc_fix_freelist. 41 * Flags for xfs_alloc_fix_freelist.
42 */ 42 */
43#define XFS_ALLOC_FLAG_TRYLOCK 0x00000001 /* use trylock for buffer locking */ 43#define XFS_ALLOC_FLAG_TRYLOCK 0x00000001 /* use trylock for buffer locking */
44#define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/
44 45
45/* 46/*
46 * Argument structure for xfs_alloc routines. 47 * Argument structure for xfs_alloc routines.
@@ -70,6 +71,7 @@ typedef struct xfs_alloc_arg {
70 char wasfromfl; /* set if allocation is from freelist */ 71 char wasfromfl; /* set if allocation is from freelist */
71 char isfl; /* set if is freelist blocks - !acctg */ 72 char isfl; /* set if is freelist blocks - !acctg */
72 char userdata; /* set if this is user data */ 73 char userdata; /* set if this is user data */
74 xfs_fsblock_t firstblock; /* io first block allocated */
73} xfs_alloc_arg_t; 75} xfs_alloc_arg_t;
74 76
75/* 77/*
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index a1d92da86ccd..7446556e8021 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index b6e1e02bbb28..1a2101043275 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -27,7 +27,6 @@
27#include "xfs_trans.h" 27#include "xfs_trans.h"
28#include "xfs_sb.h" 28#include "xfs_sb.h"
29#include "xfs_ag.h" 29#include "xfs_ag.h"
30#include "xfs_dir.h"
31#include "xfs_dir2.h" 30#include "xfs_dir2.h"
32#include "xfs_dmapi.h" 31#include "xfs_dmapi.h"
33#include "xfs_mount.h" 32#include "xfs_mount.h"
@@ -35,7 +34,6 @@
35#include "xfs_bmap_btree.h" 34#include "xfs_bmap_btree.h"
36#include "xfs_alloc_btree.h" 35#include "xfs_alloc_btree.h"
37#include "xfs_ialloc_btree.h" 36#include "xfs_ialloc_btree.h"
38#include "xfs_dir_sf.h"
39#include "xfs_dir2_sf.h" 37#include "xfs_dir2_sf.h"
40#include "xfs_attr_sf.h" 38#include "xfs_attr_sf.h"
41#include "xfs_dinode.h" 39#include "xfs_dinode.h"
@@ -1910,7 +1908,7 @@ xfs_attr_rmtval_get(xfs_da_args_t *args)
1910 error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno, 1908 error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno,
1911 args->rmtblkcnt, 1909 args->rmtblkcnt,
1912 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, 1910 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
1913 NULL, 0, map, &nmap, NULL); 1911 NULL, 0, map, &nmap, NULL, NULL);
1914 if (error) 1912 if (error)
1915 return(error); 1913 return(error);
1916 ASSERT(nmap >= 1); 1914 ASSERT(nmap >= 1);
@@ -1988,7 +1986,7 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
1988 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA | 1986 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA |
1989 XFS_BMAPI_WRITE, 1987 XFS_BMAPI_WRITE,
1990 args->firstblock, args->total, &map, &nmap, 1988 args->firstblock, args->total, &map, &nmap,
1991 args->flist); 1989 args->flist, NULL);
1992 if (!error) { 1990 if (!error) {
1993 error = xfs_bmap_finish(&args->trans, args->flist, 1991 error = xfs_bmap_finish(&args->trans, args->flist,
1994 *args->firstblock, &committed); 1992 *args->firstblock, &committed);
@@ -2039,7 +2037,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
2039 error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno, 2037 error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno,
2040 args->rmtblkcnt, 2038 args->rmtblkcnt,
2041 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, 2039 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
2042 args->firstblock, 0, &map, &nmap, NULL); 2040 args->firstblock, 0, &map, &nmap,
2041 NULL, NULL);
2043 if (error) { 2042 if (error) {
2044 return(error); 2043 return(error);
2045 } 2044 }
@@ -2104,7 +2103,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
2104 args->rmtblkcnt, 2103 args->rmtblkcnt,
2105 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, 2104 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
2106 args->firstblock, 0, &map, &nmap, 2105 args->firstblock, 0, &map, &nmap,
2107 args->flist); 2106 args->flist, NULL);
2108 if (error) { 2107 if (error) {
2109 return(error); 2108 return(error);
2110 } 2109 }
@@ -2142,7 +2141,8 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
2142 XFS_BMAP_INIT(args->flist, args->firstblock); 2141 XFS_BMAP_INIT(args->flist, args->firstblock);
2143 error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, 2142 error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,
2144 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, 2143 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
2145 1, args->firstblock, args->flist, &done); 2144 1, args->firstblock, args->flist,
2145 NULL, &done);
2146 if (!error) { 2146 if (!error) {
2147 error = xfs_bmap_finish(&args->trans, args->flist, 2147 error = xfs_bmap_finish(&args->trans, args->flist,
2148 *args->firstblock, &committed); 2148 *args->firstblock, &committed);
@@ -2322,56 +2322,56 @@ xfs_attr_trace_enter(int type, char *where,
2322 2322
2323STATIC int 2323STATIC int
2324posix_acl_access_set( 2324posix_acl_access_set(
2325 vnode_t *vp, char *name, void *data, size_t size, int xflags) 2325 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2326{ 2326{
2327 return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS); 2327 return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS);
2328} 2328}
2329 2329
2330STATIC int 2330STATIC int
2331posix_acl_access_remove( 2331posix_acl_access_remove(
2332 struct vnode *vp, char *name, int xflags) 2332 bhv_vnode_t *vp, char *name, int xflags)
2333{ 2333{
2334 return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS); 2334 return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
2335} 2335}
2336 2336
2337STATIC int 2337STATIC int
2338posix_acl_access_get( 2338posix_acl_access_get(
2339 vnode_t *vp, char *name, void *data, size_t size, int xflags) 2339 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2340{ 2340{
2341 return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS); 2341 return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS);
2342} 2342}
2343 2343
2344STATIC int 2344STATIC int
2345posix_acl_access_exists( 2345posix_acl_access_exists(
2346 vnode_t *vp) 2346 bhv_vnode_t *vp)
2347{ 2347{
2348 return xfs_acl_vhasacl_access(vp); 2348 return xfs_acl_vhasacl_access(vp);
2349} 2349}
2350 2350
2351STATIC int 2351STATIC int
2352posix_acl_default_set( 2352posix_acl_default_set(
2353 vnode_t *vp, char *name, void *data, size_t size, int xflags) 2353 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2354{ 2354{
2355 return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT); 2355 return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT);
2356} 2356}
2357 2357
2358STATIC int 2358STATIC int
2359posix_acl_default_get( 2359posix_acl_default_get(
2360 vnode_t *vp, char *name, void *data, size_t size, int xflags) 2360 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2361{ 2361{
2362 return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT); 2362 return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT);
2363} 2363}
2364 2364
2365STATIC int 2365STATIC int
2366posix_acl_default_remove( 2366posix_acl_default_remove(
2367 struct vnode *vp, char *name, int xflags) 2367 bhv_vnode_t *vp, char *name, int xflags)
2368{ 2368{
2369 return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT); 2369 return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT);
2370} 2370}
2371 2371
2372STATIC int 2372STATIC int
2373posix_acl_default_exists( 2373posix_acl_default_exists(
2374 vnode_t *vp) 2374 bhv_vnode_t *vp)
2375{ 2375{
2376 return xfs_acl_vhasacl_default(vp); 2376 return xfs_acl_vhasacl_default(vp);
2377} 2377}
@@ -2404,21 +2404,18 @@ STATIC struct attrnames *attr_system_names[] =
2404 2404
2405STATIC int 2405STATIC int
2406attr_generic_set( 2406attr_generic_set(
2407 struct vnode *vp, char *name, void *data, size_t size, int xflags) 2407 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2408{ 2408{
2409 int error; 2409 return -bhv_vop_attr_set(vp, name, data, size, xflags, NULL);
2410
2411 VOP_ATTR_SET(vp, name, data, size, xflags, NULL, error);
2412 return -error;
2413} 2410}
2414 2411
2415STATIC int 2412STATIC int
2416attr_generic_get( 2413attr_generic_get(
2417 struct vnode *vp, char *name, void *data, size_t size, int xflags) 2414 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2418{ 2415{
2419 int error, asize = size; 2416 int error, asize = size;
2420 2417
2421 VOP_ATTR_GET(vp, name, data, &asize, xflags, NULL, error); 2418 error = bhv_vop_attr_get(vp, name, data, &asize, xflags, NULL);
2422 if (!error) 2419 if (!error)
2423 return asize; 2420 return asize;
2424 return -error; 2421 return -error;
@@ -2426,12 +2423,9 @@ attr_generic_get(
2426 2423
2427STATIC int 2424STATIC int
2428attr_generic_remove( 2425attr_generic_remove(
2429 struct vnode *vp, char *name, int xflags) 2426 bhv_vnode_t *vp, char *name, int xflags)
2430{ 2427{
2431 int error; 2428 return -bhv_vop_attr_remove(vp, name, xflags, NULL);
2432
2433 VOP_ATTR_REMOVE(vp, name, xflags, NULL, error);
2434 return -error;
2435} 2429}
2436 2430
2437STATIC int 2431STATIC int
@@ -2459,7 +2453,7 @@ attr_generic_listadd(
2459 2453
2460STATIC int 2454STATIC int
2461attr_system_list( 2455attr_system_list(
2462 struct vnode *vp, 2456 bhv_vnode_t *vp,
2463 void *data, 2457 void *data,
2464 size_t size, 2458 size_t size,
2465 ssize_t *result) 2459 ssize_t *result)
@@ -2481,12 +2475,12 @@ attr_system_list(
2481 2475
2482int 2476int
2483attr_generic_list( 2477attr_generic_list(
2484 struct vnode *vp, void *data, size_t size, int xflags, ssize_t *result) 2478 bhv_vnode_t *vp, void *data, size_t size, int xflags, ssize_t *result)
2485{ 2479{
2486 attrlist_cursor_kern_t cursor = { 0 }; 2480 attrlist_cursor_kern_t cursor = { 0 };
2487 int error; 2481 int error;
2488 2482
2489 VOP_ATTR_LIST(vp, data, size, xflags, &cursor, NULL, error); 2483 error = bhv_vop_attr_list(vp, data, size, xflags, &cursor, NULL);
2490 if (error > 0) 2484 if (error > 0)
2491 return -error; 2485 return -error;
2492 *result = -error; 2486 *result = -error;
@@ -2514,7 +2508,7 @@ attr_lookup_namespace(
2514 */ 2508 */
2515STATIC int 2509STATIC int
2516attr_user_capable( 2510attr_user_capable(
2517 struct vnode *vp, 2511 bhv_vnode_t *vp,
2518 cred_t *cred) 2512 cred_t *cred)
2519{ 2513{
2520 struct inode *inode = vn_to_inode(vp); 2514 struct inode *inode = vn_to_inode(vp);
@@ -2532,7 +2526,7 @@ attr_user_capable(
2532 2526
2533STATIC int 2527STATIC int
2534attr_trusted_capable( 2528attr_trusted_capable(
2535 struct vnode *vp, 2529 bhv_vnode_t *vp,
2536 cred_t *cred) 2530 cred_t *cred)
2537{ 2531{
2538 struct inode *inode = vn_to_inode(vp); 2532 struct inode *inode = vn_to_inode(vp);
@@ -2546,7 +2540,7 @@ attr_trusted_capable(
2546 2540
2547STATIC int 2541STATIC int
2548attr_secure_capable( 2542attr_secure_capable(
2549 struct vnode *vp, 2543 bhv_vnode_t *vp,
2550 cred_t *cred) 2544 cred_t *cred)
2551{ 2545{
2552 return -ENOSECURITY; 2546 return -ENOSECURITY;
@@ -2554,7 +2548,7 @@ attr_secure_capable(
2554 2548
2555STATIC int 2549STATIC int
2556attr_system_set( 2550attr_system_set(
2557 struct vnode *vp, char *name, void *data, size_t size, int xflags) 2551 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2558{ 2552{
2559 attrnames_t *namesp; 2553 attrnames_t *namesp;
2560 int error; 2554 int error;
@@ -2573,7 +2567,7 @@ attr_system_set(
2573 2567
2574STATIC int 2568STATIC int
2575attr_system_get( 2569attr_system_get(
2576 struct vnode *vp, char *name, void *data, size_t size, int xflags) 2570 bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
2577{ 2571{
2578 attrnames_t *namesp; 2572 attrnames_t *namesp;
2579 2573
@@ -2585,7 +2579,7 @@ attr_system_get(
2585 2579
2586STATIC int 2580STATIC int
2587attr_system_remove( 2581attr_system_remove(
2588 struct vnode *vp, char *name, int xflags) 2582 bhv_vnode_t *vp, char *name, int xflags)
2589{ 2583{
2590 attrnames_t *namesp; 2584 attrnames_t *namesp;
2591 2585
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
index b2c7b9fcded3..981633f6c077 100644
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -36,13 +36,13 @@
36 *========================================================================*/ 36 *========================================================================*/
37 37
38struct cred; 38struct cred;
39struct vnode; 39struct bhv_vnode;
40 40
41typedef int (*attrset_t)(struct vnode *, char *, void *, size_t, int); 41typedef int (*attrset_t)(struct bhv_vnode *, char *, void *, size_t, int);
42typedef int (*attrget_t)(struct vnode *, char *, void *, size_t, int); 42typedef int (*attrget_t)(struct bhv_vnode *, char *, void *, size_t, int);
43typedef int (*attrremove_t)(struct vnode *, char *, int); 43typedef int (*attrremove_t)(struct bhv_vnode *, char *, int);
44typedef int (*attrexists_t)(struct vnode *); 44typedef int (*attrexists_t)(struct bhv_vnode *);
45typedef int (*attrcapable_t)(struct vnode *, struct cred *); 45typedef int (*attrcapable_t)(struct bhv_vnode *, struct cred *);
46 46
47typedef struct attrnames { 47typedef struct attrnames {
48 char * attr_name; 48 char * attr_name;
@@ -63,7 +63,7 @@ extern struct attrnames attr_trusted;
63extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT]; 63extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
64 64
65extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int); 65extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
66extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *); 66extern int attr_generic_list(struct bhv_vnode *, void *, size_t, int, ssize_t *);
67 67
68#define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */ 68#define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */
69#define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */ 69#define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 9462be86aa14..9455051f0120 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -24,7 +24,6 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
@@ -34,7 +33,6 @@
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_alloc.h" 34#include "xfs_alloc.h"
36#include "xfs_btree.h" 35#include "xfs_btree.h"
37#include "xfs_dir_sf.h"
38#include "xfs_dir2_sf.h" 36#include "xfs_dir2_sf.h"
39#include "xfs_attr_sf.h" 37#include "xfs_attr_sf.h"
40#include "xfs_dinode.h" 38#include "xfs_dinode.h"
@@ -2990,7 +2988,7 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
2990 nmap = 1; 2988 nmap = 1;
2991 error = xfs_bmapi(*trans, dp, (xfs_fileoff_t)tblkno, tblkcnt, 2989 error = xfs_bmapi(*trans, dp, (xfs_fileoff_t)tblkno, tblkcnt,
2992 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, 2990 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
2993 NULL, 0, &map, &nmap, NULL); 2991 NULL, 0, &map, &nmap, NULL, NULL);
2994 if (error) { 2992 if (error) {
2995 return(error); 2993 return(error);
2996 } 2994 }
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 26939d364bc4..3a6137539064 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -24,13 +24,11 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_da_btree.h" 28#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h" 29#include "xfs_bmap_btree.h"
31#include "xfs_alloc_btree.h" 30#include "xfs_alloc_btree.h"
32#include "xfs_ialloc_btree.h" 31#include "xfs_ialloc_btree.h"
33#include "xfs_dir_sf.h"
34#include "xfs_dir2_sf.h" 32#include "xfs_dir2_sf.h"
35#include "xfs_attr_sf.h" 33#include "xfs_attr_sf.h"
36#include "xfs_dinode.h" 34#include "xfs_dinode.h"
@@ -40,13 +38,15 @@
40#include "xfs_mount.h" 38#include "xfs_mount.h"
41#include "xfs_ialloc.h" 39#include "xfs_ialloc.h"
42#include "xfs_itable.h" 40#include "xfs_itable.h"
41#include "xfs_dir2_data.h"
42#include "xfs_dir2_leaf.h"
43#include "xfs_dir2_block.h"
43#include "xfs_inode_item.h" 44#include "xfs_inode_item.h"
44#include "xfs_extfree_item.h" 45#include "xfs_extfree_item.h"
45#include "xfs_alloc.h" 46#include "xfs_alloc.h"
46#include "xfs_bmap.h" 47#include "xfs_bmap.h"
47#include "xfs_rtalloc.h" 48#include "xfs_rtalloc.h"
48#include "xfs_error.h" 49#include "xfs_error.h"
49#include "xfs_dir_leaf.h"
50#include "xfs_attr_leaf.h" 50#include "xfs_attr_leaf.h"
51#include "xfs_rw.h" 51#include "xfs_rw.h"
52#include "xfs_quota.h" 52#include "xfs_quota.h"
@@ -101,6 +101,7 @@ xfs_bmap_add_extent(
101 xfs_fsblock_t *first, /* pointer to firstblock variable */ 101 xfs_fsblock_t *first, /* pointer to firstblock variable */
102 xfs_bmap_free_t *flist, /* list of extents to be freed */ 102 xfs_bmap_free_t *flist, /* list of extents to be freed */
103 int *logflagsp, /* inode logging flags */ 103 int *logflagsp, /* inode logging flags */
104 xfs_extdelta_t *delta, /* Change made to incore extents */
104 int whichfork, /* data or attr fork */ 105 int whichfork, /* data or attr fork */
105 int rsvd); /* OK to allocate reserved blocks */ 106 int rsvd); /* OK to allocate reserved blocks */
106 107
@@ -118,6 +119,7 @@ xfs_bmap_add_extent_delay_real(
118 xfs_fsblock_t *first, /* pointer to firstblock variable */ 119 xfs_fsblock_t *first, /* pointer to firstblock variable */
119 xfs_bmap_free_t *flist, /* list of extents to be freed */ 120 xfs_bmap_free_t *flist, /* list of extents to be freed */
120 int *logflagsp, /* inode logging flags */ 121 int *logflagsp, /* inode logging flags */
122 xfs_extdelta_t *delta, /* Change made to incore extents */
121 int rsvd); /* OK to allocate reserved blocks */ 123 int rsvd); /* OK to allocate reserved blocks */
122 124
123/* 125/*
@@ -131,6 +133,7 @@ xfs_bmap_add_extent_hole_delay(
131 xfs_btree_cur_t *cur, /* if null, not a btree */ 133 xfs_btree_cur_t *cur, /* if null, not a btree */
132 xfs_bmbt_irec_t *new, /* new data to add to file extents */ 134 xfs_bmbt_irec_t *new, /* new data to add to file extents */
133 int *logflagsp,/* inode logging flags */ 135 int *logflagsp,/* inode logging flags */
136 xfs_extdelta_t *delta, /* Change made to incore extents */
134 int rsvd); /* OK to allocate reserved blocks */ 137 int rsvd); /* OK to allocate reserved blocks */
135 138
136/* 139/*
@@ -144,6 +147,7 @@ xfs_bmap_add_extent_hole_real(
144 xfs_btree_cur_t *cur, /* if null, not a btree */ 147 xfs_btree_cur_t *cur, /* if null, not a btree */
145 xfs_bmbt_irec_t *new, /* new data to add to file extents */ 148 xfs_bmbt_irec_t *new, /* new data to add to file extents */
146 int *logflagsp, /* inode logging flags */ 149 int *logflagsp, /* inode logging flags */
150 xfs_extdelta_t *delta, /* Change made to incore extents */
147 int whichfork); /* data or attr fork */ 151 int whichfork); /* data or attr fork */
148 152
149/* 153/*
@@ -156,7 +160,8 @@ xfs_bmap_add_extent_unwritten_real(
156 xfs_extnum_t idx, /* extent number to update/insert */ 160 xfs_extnum_t idx, /* extent number to update/insert */
157 xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ 161 xfs_btree_cur_t **curp, /* if *curp is null, not a btree */
158 xfs_bmbt_irec_t *new, /* new data to add to file extents */ 162 xfs_bmbt_irec_t *new, /* new data to add to file extents */
159 int *logflagsp); /* inode logging flags */ 163 int *logflagsp, /* inode logging flags */
164 xfs_extdelta_t *delta); /* Change made to incore extents */
160 165
161/* 166/*
162 * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. 167 * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
@@ -203,6 +208,7 @@ xfs_bmap_del_extent(
203 xfs_btree_cur_t *cur, /* if null, not a btree */ 208 xfs_btree_cur_t *cur, /* if null, not a btree */
204 xfs_bmbt_irec_t *new, /* new data to add to file extents */ 209 xfs_bmbt_irec_t *new, /* new data to add to file extents */
205 int *logflagsp,/* inode logging flags */ 210 int *logflagsp,/* inode logging flags */
211 xfs_extdelta_t *delta, /* Change made to incore extents */
206 int whichfork, /* data or attr fork */ 212 int whichfork, /* data or attr fork */
207 int rsvd); /* OK to allocate reserved blocks */ 213 int rsvd); /* OK to allocate reserved blocks */
208 214
@@ -510,7 +516,7 @@ xfs_bmap_add_attrfork_local(
510 dargs.total = mp->m_dirblkfsbs; 516 dargs.total = mp->m_dirblkfsbs;
511 dargs.whichfork = XFS_DATA_FORK; 517 dargs.whichfork = XFS_DATA_FORK;
512 dargs.trans = tp; 518 dargs.trans = tp;
513 error = XFS_DIR_SHORTFORM_TO_SINGLE(mp, &dargs); 519 error = xfs_dir2_sf_to_block(&dargs);
514 } else 520 } else
515 error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags, 521 error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags,
516 XFS_DATA_FORK); 522 XFS_DATA_FORK);
@@ -530,6 +536,7 @@ xfs_bmap_add_extent(
530 xfs_fsblock_t *first, /* pointer to firstblock variable */ 536 xfs_fsblock_t *first, /* pointer to firstblock variable */
531 xfs_bmap_free_t *flist, /* list of extents to be freed */ 537 xfs_bmap_free_t *flist, /* list of extents to be freed */
532 int *logflagsp, /* inode logging flags */ 538 int *logflagsp, /* inode logging flags */
539 xfs_extdelta_t *delta, /* Change made to incore extents */
533 int whichfork, /* data or attr fork */ 540 int whichfork, /* data or attr fork */
534 int rsvd) /* OK to use reserved data blocks */ 541 int rsvd) /* OK to use reserved data blocks */
535{ 542{
@@ -567,6 +574,15 @@ xfs_bmap_add_extent(
567 logflags = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); 574 logflags = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
568 } else 575 } else
569 logflags = 0; 576 logflags = 0;
577 /* DELTA: single new extent */
578 if (delta) {
579 if (delta->xed_startoff > new->br_startoff)
580 delta->xed_startoff = new->br_startoff;
581 if (delta->xed_blockcount <
582 new->br_startoff + new->br_blockcount)
583 delta->xed_blockcount = new->br_startoff +
584 new->br_blockcount;
585 }
570 } 586 }
571 /* 587 /*
572 * Any kind of new delayed allocation goes here. 588 * Any kind of new delayed allocation goes here.
@@ -576,7 +592,7 @@ xfs_bmap_add_extent(
576 ASSERT((cur->bc_private.b.flags & 592 ASSERT((cur->bc_private.b.flags &
577 XFS_BTCUR_BPRV_WASDEL) == 0); 593 XFS_BTCUR_BPRV_WASDEL) == 0);
578 if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, cur, new, 594 if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, cur, new,
579 &logflags, rsvd))) 595 &logflags, delta, rsvd)))
580 goto done; 596 goto done;
581 } 597 }
582 /* 598 /*
@@ -587,7 +603,7 @@ xfs_bmap_add_extent(
587 ASSERT((cur->bc_private.b.flags & 603 ASSERT((cur->bc_private.b.flags &
588 XFS_BTCUR_BPRV_WASDEL) == 0); 604 XFS_BTCUR_BPRV_WASDEL) == 0);
589 if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new, 605 if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new,
590 &logflags, whichfork))) 606 &logflags, delta, whichfork)))
591 goto done; 607 goto done;
592 } else { 608 } else {
593 xfs_bmbt_irec_t prev; /* old extent at offset idx */ 609 xfs_bmbt_irec_t prev; /* old extent at offset idx */
@@ -612,17 +628,17 @@ xfs_bmap_add_extent(
612 XFS_BTCUR_BPRV_WASDEL); 628 XFS_BTCUR_BPRV_WASDEL);
613 if ((error = xfs_bmap_add_extent_delay_real(ip, 629 if ((error = xfs_bmap_add_extent_delay_real(ip,
614 idx, &cur, new, &da_new, first, flist, 630 idx, &cur, new, &da_new, first, flist,
615 &logflags, rsvd))) 631 &logflags, delta, rsvd)))
616 goto done; 632 goto done;
617 } else if (new->br_state == XFS_EXT_NORM) { 633 } else if (new->br_state == XFS_EXT_NORM) {
618 ASSERT(new->br_state == XFS_EXT_NORM); 634 ASSERT(new->br_state == XFS_EXT_NORM);
619 if ((error = xfs_bmap_add_extent_unwritten_real( 635 if ((error = xfs_bmap_add_extent_unwritten_real(
620 ip, idx, &cur, new, &logflags))) 636 ip, idx, &cur, new, &logflags, delta)))
621 goto done; 637 goto done;
622 } else { 638 } else {
623 ASSERT(new->br_state == XFS_EXT_UNWRITTEN); 639 ASSERT(new->br_state == XFS_EXT_UNWRITTEN);
624 if ((error = xfs_bmap_add_extent_unwritten_real( 640 if ((error = xfs_bmap_add_extent_unwritten_real(
625 ip, idx, &cur, new, &logflags))) 641 ip, idx, &cur, new, &logflags, delta)))
626 goto done; 642 goto done;
627 } 643 }
628 ASSERT(*curp == cur || *curp == NULL); 644 ASSERT(*curp == cur || *curp == NULL);
@@ -635,7 +651,7 @@ xfs_bmap_add_extent(
635 ASSERT((cur->bc_private.b.flags & 651 ASSERT((cur->bc_private.b.flags &
636 XFS_BTCUR_BPRV_WASDEL) == 0); 652 XFS_BTCUR_BPRV_WASDEL) == 0);
637 if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, 653 if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur,
638 new, &logflags, whichfork))) 654 new, &logflags, delta, whichfork)))
639 goto done; 655 goto done;
640 } 656 }
641 } 657 }
@@ -700,6 +716,7 @@ xfs_bmap_add_extent_delay_real(
700 xfs_fsblock_t *first, /* pointer to firstblock variable */ 716 xfs_fsblock_t *first, /* pointer to firstblock variable */
701 xfs_bmap_free_t *flist, /* list of extents to be freed */ 717 xfs_bmap_free_t *flist, /* list of extents to be freed */
702 int *logflagsp, /* inode logging flags */ 718 int *logflagsp, /* inode logging flags */
719 xfs_extdelta_t *delta, /* Change made to incore extents */
703 int rsvd) /* OK to use reserved data block allocation */ 720 int rsvd) /* OK to use reserved data block allocation */
704{ 721{
705 xfs_btree_cur_t *cur; /* btree cursor */ 722 xfs_btree_cur_t *cur; /* btree cursor */
@@ -716,8 +733,8 @@ xfs_bmap_add_extent_delay_real(
716 /* left is 0, right is 1, prev is 2 */ 733 /* left is 0, right is 1, prev is 2 */
717 int rval=0; /* return value (logging flags) */ 734 int rval=0; /* return value (logging flags) */
718 int state = 0;/* state bits, accessed thru macros */ 735 int state = 0;/* state bits, accessed thru macros */
719 xfs_filblks_t temp; /* value for dnew calculations */ 736 xfs_filblks_t temp=0; /* value for dnew calculations */
720 xfs_filblks_t temp2; /* value for dnew calculations */ 737 xfs_filblks_t temp2=0;/* value for dnew calculations */
721 int tmp_rval; /* partial logging flags */ 738 int tmp_rval; /* partial logging flags */
722 enum { /* bit number definitions for state */ 739 enum { /* bit number definitions for state */
723 LEFT_CONTIG, RIGHT_CONTIG, 740 LEFT_CONTIG, RIGHT_CONTIG,
@@ -839,6 +856,11 @@ xfs_bmap_add_extent_delay_real(
839 goto done; 856 goto done;
840 } 857 }
841 *dnew = 0; 858 *dnew = 0;
859 /* DELTA: Three in-core extents are replaced by one. */
860 temp = LEFT.br_startoff;
861 temp2 = LEFT.br_blockcount +
862 PREV.br_blockcount +
863 RIGHT.br_blockcount;
842 break; 864 break;
843 865
844 case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG): 866 case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
@@ -872,6 +894,10 @@ xfs_bmap_add_extent_delay_real(
872 goto done; 894 goto done;
873 } 895 }
874 *dnew = 0; 896 *dnew = 0;
897 /* DELTA: Two in-core extents are replaced by one. */
898 temp = LEFT.br_startoff;
899 temp2 = LEFT.br_blockcount +
900 PREV.br_blockcount;
875 break; 901 break;
876 902
877 case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG): 903 case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
@@ -906,6 +932,10 @@ xfs_bmap_add_extent_delay_real(
906 goto done; 932 goto done;
907 } 933 }
908 *dnew = 0; 934 *dnew = 0;
935 /* DELTA: Two in-core extents are replaced by one. */
936 temp = PREV.br_startoff;
937 temp2 = PREV.br_blockcount +
938 RIGHT.br_blockcount;
909 break; 939 break;
910 940
911 case MASK2(LEFT_FILLING, RIGHT_FILLING): 941 case MASK2(LEFT_FILLING, RIGHT_FILLING):
@@ -936,6 +966,9 @@ xfs_bmap_add_extent_delay_real(
936 ASSERT(i == 1); 966 ASSERT(i == 1);
937 } 967 }
938 *dnew = 0; 968 *dnew = 0;
969 /* DELTA: The in-core extent described by new changed type. */
970 temp = new->br_startoff;
971 temp2 = new->br_blockcount;
939 break; 972 break;
940 973
941 case MASK2(LEFT_FILLING, LEFT_CONTIG): 974 case MASK2(LEFT_FILLING, LEFT_CONTIG):
@@ -978,6 +1011,10 @@ xfs_bmap_add_extent_delay_real(
978 xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx, 1011 xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx,
979 XFS_DATA_FORK); 1012 XFS_DATA_FORK);
980 *dnew = temp; 1013 *dnew = temp;
1014 /* DELTA: The boundary between two in-core extents moved. */
1015 temp = LEFT.br_startoff;
1016 temp2 = LEFT.br_blockcount +
1017 PREV.br_blockcount;
981 break; 1018 break;
982 1019
983 case MASK(LEFT_FILLING): 1020 case MASK(LEFT_FILLING):
@@ -1025,6 +1062,9 @@ xfs_bmap_add_extent_delay_real(
1025 xfs_bmap_trace_post_update(fname, "LF", ip, idx + 1, 1062 xfs_bmap_trace_post_update(fname, "LF", ip, idx + 1,
1026 XFS_DATA_FORK); 1063 XFS_DATA_FORK);
1027 *dnew = temp; 1064 *dnew = temp;
1065 /* DELTA: One in-core extent is split in two. */
1066 temp = PREV.br_startoff;
1067 temp2 = PREV.br_blockcount;
1028 break; 1068 break;
1029 1069
1030 case MASK2(RIGHT_FILLING, RIGHT_CONTIG): 1070 case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
@@ -1067,6 +1107,10 @@ xfs_bmap_add_extent_delay_real(
1067 xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx, 1107 xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx,
1068 XFS_DATA_FORK); 1108 XFS_DATA_FORK);
1069 *dnew = temp; 1109 *dnew = temp;
1110 /* DELTA: The boundary between two in-core extents moved. */
1111 temp = PREV.br_startoff;
1112 temp2 = PREV.br_blockcount +
1113 RIGHT.br_blockcount;
1070 break; 1114 break;
1071 1115
1072 case MASK(RIGHT_FILLING): 1116 case MASK(RIGHT_FILLING):
@@ -1112,6 +1156,9 @@ xfs_bmap_add_extent_delay_real(
1112 xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp)); 1156 xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
1113 xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK); 1157 xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK);
1114 *dnew = temp; 1158 *dnew = temp;
1159 /* DELTA: One in-core extent is split in two. */
1160 temp = PREV.br_startoff;
1161 temp2 = PREV.br_blockcount;
1115 break; 1162 break;
1116 1163
1117 case 0: 1164 case 0:
@@ -1194,6 +1241,9 @@ xfs_bmap_add_extent_delay_real(
1194 xfs_bmap_trace_post_update(fname, "0", ip, idx + 2, 1241 xfs_bmap_trace_post_update(fname, "0", ip, idx + 2,
1195 XFS_DATA_FORK); 1242 XFS_DATA_FORK);
1196 *dnew = temp + temp2; 1243 *dnew = temp + temp2;
1244 /* DELTA: One in-core extent is split in three. */
1245 temp = PREV.br_startoff;
1246 temp2 = PREV.br_blockcount;
1197 break; 1247 break;
1198 1248
1199 case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG): 1249 case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
@@ -1209,6 +1259,13 @@ xfs_bmap_add_extent_delay_real(
1209 ASSERT(0); 1259 ASSERT(0);
1210 } 1260 }
1211 *curp = cur; 1261 *curp = cur;
1262 if (delta) {
1263 temp2 += temp;
1264 if (delta->xed_startoff > temp)
1265 delta->xed_startoff = temp;
1266 if (delta->xed_blockcount < temp2)
1267 delta->xed_blockcount = temp2;
1268 }
1212done: 1269done:
1213 *logflagsp = rval; 1270 *logflagsp = rval;
1214 return error; 1271 return error;
@@ -1235,7 +1292,8 @@ xfs_bmap_add_extent_unwritten_real(
1235 xfs_extnum_t idx, /* extent number to update/insert */ 1292 xfs_extnum_t idx, /* extent number to update/insert */
1236 xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ 1293 xfs_btree_cur_t **curp, /* if *curp is null, not a btree */
1237 xfs_bmbt_irec_t *new, /* new data to add to file extents */ 1294 xfs_bmbt_irec_t *new, /* new data to add to file extents */
1238 int *logflagsp) /* inode logging flags */ 1295 int *logflagsp, /* inode logging flags */
1296 xfs_extdelta_t *delta) /* Change made to incore extents */
1239{ 1297{
1240 xfs_btree_cur_t *cur; /* btree cursor */ 1298 xfs_btree_cur_t *cur; /* btree cursor */
1241 xfs_bmbt_rec_t *ep; /* extent entry for idx */ 1299 xfs_bmbt_rec_t *ep; /* extent entry for idx */
@@ -1252,6 +1310,8 @@ xfs_bmap_add_extent_unwritten_real(
1252 /* left is 0, right is 1, prev is 2 */ 1310 /* left is 0, right is 1, prev is 2 */
1253 int rval=0; /* return value (logging flags) */ 1311 int rval=0; /* return value (logging flags) */
1254 int state = 0;/* state bits, accessed thru macros */ 1312 int state = 0;/* state bits, accessed thru macros */
1313 xfs_filblks_t temp=0;
1314 xfs_filblks_t temp2=0;
1255 enum { /* bit number definitions for state */ 1315 enum { /* bit number definitions for state */
1256 LEFT_CONTIG, RIGHT_CONTIG, 1316 LEFT_CONTIG, RIGHT_CONTIG,
1257 LEFT_FILLING, RIGHT_FILLING, 1317 LEFT_FILLING, RIGHT_FILLING,
@@ -1380,6 +1440,11 @@ xfs_bmap_add_extent_unwritten_real(
1380 RIGHT.br_blockcount, LEFT.br_state))) 1440 RIGHT.br_blockcount, LEFT.br_state)))
1381 goto done; 1441 goto done;
1382 } 1442 }
1443 /* DELTA: Three in-core extents are replaced by one. */
1444 temp = LEFT.br_startoff;
1445 temp2 = LEFT.br_blockcount +
1446 PREV.br_blockcount +
1447 RIGHT.br_blockcount;
1383 break; 1448 break;
1384 1449
1385 case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG): 1450 case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
@@ -1419,6 +1484,10 @@ xfs_bmap_add_extent_unwritten_real(
1419 LEFT.br_state))) 1484 LEFT.br_state)))
1420 goto done; 1485 goto done;
1421 } 1486 }
1487 /* DELTA: Two in-core extents are replaced by one. */
1488 temp = LEFT.br_startoff;
1489 temp2 = LEFT.br_blockcount +
1490 PREV.br_blockcount;
1422 break; 1491 break;
1423 1492
1424 case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG): 1493 case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
@@ -1459,6 +1528,10 @@ xfs_bmap_add_extent_unwritten_real(
1459 newext))) 1528 newext)))
1460 goto done; 1529 goto done;
1461 } 1530 }
1531 /* DELTA: Two in-core extents are replaced by one. */
1532 temp = PREV.br_startoff;
1533 temp2 = PREV.br_blockcount +
1534 RIGHT.br_blockcount;
1462 break; 1535 break;
1463 1536
1464 case MASK2(LEFT_FILLING, RIGHT_FILLING): 1537 case MASK2(LEFT_FILLING, RIGHT_FILLING):
@@ -1487,6 +1560,9 @@ xfs_bmap_add_extent_unwritten_real(
1487 newext))) 1560 newext)))
1488 goto done; 1561 goto done;
1489 } 1562 }
1563 /* DELTA: The in-core extent described by new changed type. */
1564 temp = new->br_startoff;
1565 temp2 = new->br_blockcount;
1490 break; 1566 break;
1491 1567
1492 case MASK2(LEFT_FILLING, LEFT_CONTIG): 1568 case MASK2(LEFT_FILLING, LEFT_CONTIG):
@@ -1534,6 +1610,10 @@ xfs_bmap_add_extent_unwritten_real(
1534 LEFT.br_state)) 1610 LEFT.br_state))
1535 goto done; 1611 goto done;
1536 } 1612 }
1613 /* DELTA: The boundary between two in-core extents moved. */
1614 temp = LEFT.br_startoff;
1615 temp2 = LEFT.br_blockcount +
1616 PREV.br_blockcount;
1537 break; 1617 break;
1538 1618
1539 case MASK(LEFT_FILLING): 1619 case MASK(LEFT_FILLING):
@@ -1574,6 +1654,9 @@ xfs_bmap_add_extent_unwritten_real(
1574 goto done; 1654 goto done;
1575 ASSERT(i == 1); 1655 ASSERT(i == 1);
1576 } 1656 }
1657 /* DELTA: One in-core extent is split in two. */
1658 temp = PREV.br_startoff;
1659 temp2 = PREV.br_blockcount;
1577 break; 1660 break;
1578 1661
1579 case MASK2(RIGHT_FILLING, RIGHT_CONTIG): 1662 case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
@@ -1617,6 +1700,10 @@ xfs_bmap_add_extent_unwritten_real(
1617 newext))) 1700 newext)))
1618 goto done; 1701 goto done;
1619 } 1702 }
1703 /* DELTA: The boundary between two in-core extents moved. */
1704 temp = PREV.br_startoff;
1705 temp2 = PREV.br_blockcount +
1706 RIGHT.br_blockcount;
1620 break; 1707 break;
1621 1708
1622 case MASK(RIGHT_FILLING): 1709 case MASK(RIGHT_FILLING):
@@ -1657,6 +1744,9 @@ xfs_bmap_add_extent_unwritten_real(
1657 goto done; 1744 goto done;
1658 ASSERT(i == 1); 1745 ASSERT(i == 1);
1659 } 1746 }
1747 /* DELTA: One in-core extent is split in two. */
1748 temp = PREV.br_startoff;
1749 temp2 = PREV.br_blockcount;
1660 break; 1750 break;
1661 1751
1662 case 0: 1752 case 0:
@@ -1710,6 +1800,9 @@ xfs_bmap_add_extent_unwritten_real(
1710 goto done; 1800 goto done;
1711 ASSERT(i == 1); 1801 ASSERT(i == 1);
1712 } 1802 }
1803 /* DELTA: One in-core extent is split in three. */
1804 temp = PREV.br_startoff;
1805 temp2 = PREV.br_blockcount;
1713 break; 1806 break;
1714 1807
1715 case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG): 1808 case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
@@ -1725,6 +1818,13 @@ xfs_bmap_add_extent_unwritten_real(
1725 ASSERT(0); 1818 ASSERT(0);
1726 } 1819 }
1727 *curp = cur; 1820 *curp = cur;
1821 if (delta) {
1822 temp2 += temp;
1823 if (delta->xed_startoff > temp)
1824 delta->xed_startoff = temp;
1825 if (delta->xed_blockcount < temp2)
1826 delta->xed_blockcount = temp2;
1827 }
1728done: 1828done:
1729 *logflagsp = rval; 1829 *logflagsp = rval;
1730 return error; 1830 return error;
@@ -1753,6 +1853,7 @@ xfs_bmap_add_extent_hole_delay(
1753 xfs_btree_cur_t *cur, /* if null, not a btree */ 1853 xfs_btree_cur_t *cur, /* if null, not a btree */
1754 xfs_bmbt_irec_t *new, /* new data to add to file extents */ 1854 xfs_bmbt_irec_t *new, /* new data to add to file extents */
1755 int *logflagsp, /* inode logging flags */ 1855 int *logflagsp, /* inode logging flags */
1856 xfs_extdelta_t *delta, /* Change made to incore extents */
1756 int rsvd) /* OK to allocate reserved blocks */ 1857 int rsvd) /* OK to allocate reserved blocks */
1757{ 1858{
1758 xfs_bmbt_rec_t *ep; /* extent record for idx */ 1859 xfs_bmbt_rec_t *ep; /* extent record for idx */
@@ -1765,7 +1866,8 @@ xfs_bmap_add_extent_hole_delay(
1765 xfs_filblks_t oldlen=0; /* old indirect size */ 1866 xfs_filblks_t oldlen=0; /* old indirect size */
1766 xfs_bmbt_irec_t right; /* right neighbor extent entry */ 1867 xfs_bmbt_irec_t right; /* right neighbor extent entry */
1767 int state; /* state bits, accessed thru macros */ 1868 int state; /* state bits, accessed thru macros */
1768 xfs_filblks_t temp; /* temp for indirect calculations */ 1869 xfs_filblks_t temp=0; /* temp for indirect calculations */
1870 xfs_filblks_t temp2=0;
1769 enum { /* bit number definitions for state */ 1871 enum { /* bit number definitions for state */
1770 LEFT_CONTIG, RIGHT_CONTIG, 1872 LEFT_CONTIG, RIGHT_CONTIG,
1771 LEFT_DELAY, RIGHT_DELAY, 1873 LEFT_DELAY, RIGHT_DELAY,
@@ -1844,6 +1946,9 @@ xfs_bmap_add_extent_hole_delay(
1844 XFS_DATA_FORK); 1946 XFS_DATA_FORK);
1845 xfs_iext_remove(ifp, idx, 1); 1947 xfs_iext_remove(ifp, idx, 1);
1846 ip->i_df.if_lastex = idx - 1; 1948 ip->i_df.if_lastex = idx - 1;
1949 /* DELTA: Two in-core extents were replaced by one. */
1950 temp2 = temp;
1951 temp = left.br_startoff;
1847 break; 1952 break;
1848 1953
1849 case MASK(LEFT_CONTIG): 1954 case MASK(LEFT_CONTIG):
@@ -1864,6 +1969,9 @@ xfs_bmap_add_extent_hole_delay(
1864 xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, 1969 xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1,
1865 XFS_DATA_FORK); 1970 XFS_DATA_FORK);
1866 ip->i_df.if_lastex = idx - 1; 1971 ip->i_df.if_lastex = idx - 1;
1972 /* DELTA: One in-core extent grew into a hole. */
1973 temp2 = temp;
1974 temp = left.br_startoff;
1867 break; 1975 break;
1868 1976
1869 case MASK(RIGHT_CONTIG): 1977 case MASK(RIGHT_CONTIG):
@@ -1881,6 +1989,9 @@ xfs_bmap_add_extent_hole_delay(
1881 NULLSTARTBLOCK((int)newlen), temp, right.br_state); 1989 NULLSTARTBLOCK((int)newlen), temp, right.br_state);
1882 xfs_bmap_trace_post_update(fname, "RC", ip, idx, XFS_DATA_FORK); 1990 xfs_bmap_trace_post_update(fname, "RC", ip, idx, XFS_DATA_FORK);
1883 ip->i_df.if_lastex = idx; 1991 ip->i_df.if_lastex = idx;
1992 /* DELTA: One in-core extent grew into a hole. */
1993 temp2 = temp;
1994 temp = new->br_startoff;
1884 break; 1995 break;
1885 1996
1886 case 0: 1997 case 0:
@@ -1894,6 +2005,9 @@ xfs_bmap_add_extent_hole_delay(
1894 XFS_DATA_FORK); 2005 XFS_DATA_FORK);
1895 xfs_iext_insert(ifp, idx, 1, new); 2006 xfs_iext_insert(ifp, idx, 1, new);
1896 ip->i_df.if_lastex = idx; 2007 ip->i_df.if_lastex = idx;
2008 /* DELTA: A new in-core extent was added in a hole. */
2009 temp2 = new->br_blockcount;
2010 temp = new->br_startoff;
1897 break; 2011 break;
1898 } 2012 }
1899 if (oldlen != newlen) { 2013 if (oldlen != newlen) {
@@ -1904,6 +2018,13 @@ xfs_bmap_add_extent_hole_delay(
1904 * Nothing to do for disk quota accounting here. 2018 * Nothing to do for disk quota accounting here.
1905 */ 2019 */
1906 } 2020 }
2021 if (delta) {
2022 temp2 += temp;
2023 if (delta->xed_startoff > temp)
2024 delta->xed_startoff = temp;
2025 if (delta->xed_blockcount < temp2)
2026 delta->xed_blockcount = temp2;
2027 }
1907 *logflagsp = 0; 2028 *logflagsp = 0;
1908 return 0; 2029 return 0;
1909#undef MASK 2030#undef MASK
@@ -1925,6 +2046,7 @@ xfs_bmap_add_extent_hole_real(
1925 xfs_btree_cur_t *cur, /* if null, not a btree */ 2046 xfs_btree_cur_t *cur, /* if null, not a btree */
1926 xfs_bmbt_irec_t *new, /* new data to add to file extents */ 2047 xfs_bmbt_irec_t *new, /* new data to add to file extents */
1927 int *logflagsp, /* inode logging flags */ 2048 int *logflagsp, /* inode logging flags */
2049 xfs_extdelta_t *delta, /* Change made to incore extents */
1928 int whichfork) /* data or attr fork */ 2050 int whichfork) /* data or attr fork */
1929{ 2051{
1930 xfs_bmbt_rec_t *ep; /* pointer to extent entry ins. point */ 2052 xfs_bmbt_rec_t *ep; /* pointer to extent entry ins. point */
@@ -1936,7 +2058,10 @@ xfs_bmap_add_extent_hole_real(
1936 xfs_ifork_t *ifp; /* inode fork pointer */ 2058 xfs_ifork_t *ifp; /* inode fork pointer */
1937 xfs_bmbt_irec_t left; /* left neighbor extent entry */ 2059 xfs_bmbt_irec_t left; /* left neighbor extent entry */
1938 xfs_bmbt_irec_t right; /* right neighbor extent entry */ 2060 xfs_bmbt_irec_t right; /* right neighbor extent entry */
2061 int rval=0; /* return value (logging flags) */
1939 int state; /* state bits, accessed thru macros */ 2062 int state; /* state bits, accessed thru macros */
2063 xfs_filblks_t temp=0;
2064 xfs_filblks_t temp2=0;
1940 enum { /* bit number definitions for state */ 2065 enum { /* bit number definitions for state */
1941 LEFT_CONTIG, RIGHT_CONTIG, 2066 LEFT_CONTIG, RIGHT_CONTIG,
1942 LEFT_DELAY, RIGHT_DELAY, 2067 LEFT_DELAY, RIGHT_DELAY,
@@ -1993,6 +2118,7 @@ xfs_bmap_add_extent_hole_real(
1993 left.br_blockcount + new->br_blockcount + 2118 left.br_blockcount + new->br_blockcount +
1994 right.br_blockcount <= MAXEXTLEN)); 2119 right.br_blockcount <= MAXEXTLEN));
1995 2120
2121 error = 0;
1996 /* 2122 /*
1997 * Select which case we're in here, and implement it. 2123 * Select which case we're in here, and implement it.
1998 */ 2124 */
@@ -2018,25 +2144,35 @@ xfs_bmap_add_extent_hole_real(
2018 XFS_IFORK_NEXT_SET(ip, whichfork, 2144 XFS_IFORK_NEXT_SET(ip, whichfork,
2019 XFS_IFORK_NEXTENTS(ip, whichfork) - 1); 2145 XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
2020 if (cur == NULL) { 2146 if (cur == NULL) {
2021 *logflagsp = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); 2147 rval = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
2022 return 0; 2148 } else {
2149 rval = XFS_ILOG_CORE;
2150 if ((error = xfs_bmbt_lookup_eq(cur,
2151 right.br_startoff,
2152 right.br_startblock,
2153 right.br_blockcount, &i)))
2154 goto done;
2155 ASSERT(i == 1);
2156 if ((error = xfs_bmbt_delete(cur, &i)))
2157 goto done;
2158 ASSERT(i == 1);
2159 if ((error = xfs_bmbt_decrement(cur, 0, &i)))
2160 goto done;
2161 ASSERT(i == 1);
2162 if ((error = xfs_bmbt_update(cur, left.br_startoff,
2163 left.br_startblock,
2164 left.br_blockcount +
2165 new->br_blockcount +
2166 right.br_blockcount,
2167 left.br_state)))
2168 goto done;
2023 } 2169 }
2024 *logflagsp = XFS_ILOG_CORE; 2170 /* DELTA: Two in-core extents were replaced by one. */
2025 if ((error = xfs_bmbt_lookup_eq(cur, right.br_startoff, 2171 temp = left.br_startoff;
2026 right.br_startblock, right.br_blockcount, &i))) 2172 temp2 = left.br_blockcount +
2027 return error; 2173 new->br_blockcount +
2028 ASSERT(i == 1); 2174 right.br_blockcount;
2029 if ((error = xfs_bmbt_delete(cur, &i))) 2175 break;
2030 return error;
2031 ASSERT(i == 1);
2032 if ((error = xfs_bmbt_decrement(cur, 0, &i)))
2033 return error;
2034 ASSERT(i == 1);
2035 error = xfs_bmbt_update(cur, left.br_startoff,
2036 left.br_startblock,
2037 left.br_blockcount + new->br_blockcount +
2038 right.br_blockcount, left.br_state);
2039 return error;
2040 2176
2041 case MASK(LEFT_CONTIG): 2177 case MASK(LEFT_CONTIG):
2042 /* 2178 /*
@@ -2050,19 +2186,27 @@ xfs_bmap_add_extent_hole_real(
2050 xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, whichfork); 2186 xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, whichfork);
2051 ifp->if_lastex = idx - 1; 2187 ifp->if_lastex = idx - 1;
2052 if (cur == NULL) { 2188 if (cur == NULL) {
2053 *logflagsp = XFS_ILOG_FEXT(whichfork); 2189 rval = XFS_ILOG_FEXT(whichfork);
2054 return 0; 2190 } else {
2191 rval = 0;
2192 if ((error = xfs_bmbt_lookup_eq(cur,
2193 left.br_startoff,
2194 left.br_startblock,
2195 left.br_blockcount, &i)))
2196 goto done;
2197 ASSERT(i == 1);
2198 if ((error = xfs_bmbt_update(cur, left.br_startoff,
2199 left.br_startblock,
2200 left.br_blockcount +
2201 new->br_blockcount,
2202 left.br_state)))
2203 goto done;
2055 } 2204 }
2056 *logflagsp = 0; 2205 /* DELTA: One in-core extent grew. */
2057 if ((error = xfs_bmbt_lookup_eq(cur, left.br_startoff, 2206 temp = left.br_startoff;
2058 left.br_startblock, left.br_blockcount, &i))) 2207 temp2 = left.br_blockcount +
2059 return error; 2208 new->br_blockcount;
2060 ASSERT(i == 1); 2209 break;
2061 error = xfs_bmbt_update(cur, left.br_startoff,
2062 left.br_startblock,
2063 left.br_blockcount + new->br_blockcount,
2064 left.br_state);
2065 return error;
2066 2210
2067 case MASK(RIGHT_CONTIG): 2211 case MASK(RIGHT_CONTIG):
2068 /* 2212 /*
@@ -2077,19 +2221,27 @@ xfs_bmap_add_extent_hole_real(
2077 xfs_bmap_trace_post_update(fname, "RC", ip, idx, whichfork); 2221 xfs_bmap_trace_post_update(fname, "RC", ip, idx, whichfork);
2078 ifp->if_lastex = idx; 2222 ifp->if_lastex = idx;
2079 if (cur == NULL) { 2223 if (cur == NULL) {
2080 *logflagsp = XFS_ILOG_FEXT(whichfork); 2224 rval = XFS_ILOG_FEXT(whichfork);
2081 return 0; 2225 } else {
2226 rval = 0;
2227 if ((error = xfs_bmbt_lookup_eq(cur,
2228 right.br_startoff,
2229 right.br_startblock,
2230 right.br_blockcount, &i)))
2231 goto done;
2232 ASSERT(i == 1);
2233 if ((error = xfs_bmbt_update(cur, new->br_startoff,
2234 new->br_startblock,
2235 new->br_blockcount +
2236 right.br_blockcount,
2237 right.br_state)))
2238 goto done;
2082 } 2239 }
2083 *logflagsp = 0; 2240 /* DELTA: One in-core extent grew. */
2084 if ((error = xfs_bmbt_lookup_eq(cur, right.br_startoff, 2241 temp = new->br_startoff;
2085 right.br_startblock, right.br_blockcount, &i))) 2242 temp2 = new->br_blockcount +
2086 return error; 2243 right.br_blockcount;
2087 ASSERT(i == 1); 2244 break;
2088 error = xfs_bmbt_update(cur, new->br_startoff,
2089 new->br_startblock,
2090 new->br_blockcount + right.br_blockcount,
2091 right.br_state);
2092 return error;
2093 2245
2094 case 0: 2246 case 0:
2095 /* 2247 /*
@@ -2104,29 +2256,41 @@ xfs_bmap_add_extent_hole_real(
2104 XFS_IFORK_NEXT_SET(ip, whichfork, 2256 XFS_IFORK_NEXT_SET(ip, whichfork,
2105 XFS_IFORK_NEXTENTS(ip, whichfork) + 1); 2257 XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
2106 if (cur == NULL) { 2258 if (cur == NULL) {
2107 *logflagsp = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); 2259 rval = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
2108 return 0; 2260 } else {
2261 rval = XFS_ILOG_CORE;
2262 if ((error = xfs_bmbt_lookup_eq(cur,
2263 new->br_startoff,
2264 new->br_startblock,
2265 new->br_blockcount, &i)))
2266 goto done;
2267 ASSERT(i == 0);
2268 cur->bc_rec.b.br_state = new->br_state;
2269 if ((error = xfs_bmbt_insert(cur, &i)))
2270 goto done;
2271 ASSERT(i == 1);
2109 } 2272 }
2110 *logflagsp = XFS_ILOG_CORE; 2273 /* DELTA: A new extent was added in a hole. */
2111 if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, 2274 temp = new->br_startoff;
2112 new->br_startblock, new->br_blockcount, &i))) 2275 temp2 = new->br_blockcount;
2113 return error; 2276 break;
2114 ASSERT(i == 0); 2277 }
2115 cur->bc_rec.b.br_state = new->br_state; 2278 if (delta) {
2116 if ((error = xfs_bmbt_insert(cur, &i))) 2279 temp2 += temp;
2117 return error; 2280 if (delta->xed_startoff > temp)
2118 ASSERT(i == 1); 2281 delta->xed_startoff = temp;
2119 return 0; 2282 if (delta->xed_blockcount < temp2)
2283 delta->xed_blockcount = temp2;
2120 } 2284 }
2285done:
2286 *logflagsp = rval;
2287 return error;
2121#undef MASK 2288#undef MASK
2122#undef MASK2 2289#undef MASK2
2123#undef STATE_SET 2290#undef STATE_SET
2124#undef STATE_TEST 2291#undef STATE_TEST
2125#undef STATE_SET_TEST 2292#undef STATE_SET_TEST
2126#undef SWITCH_STATE 2293#undef SWITCH_STATE
2127 /* NOTREACHED */
2128 ASSERT(0);
2129 return 0; /* keep gcc quite */
2130} 2294}
2131 2295
2132/* 2296/*
@@ -2598,6 +2762,7 @@ xfs_bmap_btalloc(
2598 args.mp = mp; 2762 args.mp = mp;
2599 args.fsbno = ap->rval; 2763 args.fsbno = ap->rval;
2600 args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks); 2764 args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks);
2765 args.firstblock = ap->firstblock;
2601 blen = 0; 2766 blen = 0;
2602 if (nullfb) { 2767 if (nullfb) {
2603 args.type = XFS_ALLOCTYPE_START_BNO; 2768 args.type = XFS_ALLOCTYPE_START_BNO;
@@ -2657,7 +2822,7 @@ xfs_bmap_btalloc(
2657 else 2822 else
2658 args.minlen = ap->alen; 2823 args.minlen = ap->alen;
2659 } else if (ap->low) { 2824 } else if (ap->low) {
2660 args.type = XFS_ALLOCTYPE_FIRST_AG; 2825 args.type = XFS_ALLOCTYPE_START_BNO;
2661 args.total = args.minlen = ap->minlen; 2826 args.total = args.minlen = ap->minlen;
2662 } else { 2827 } else {
2663 args.type = XFS_ALLOCTYPE_NEAR_BNO; 2828 args.type = XFS_ALLOCTYPE_NEAR_BNO;
@@ -2669,7 +2834,7 @@ xfs_bmap_btalloc(
2669 args.prod = ap->ip->i_d.di_extsize; 2834 args.prod = ap->ip->i_d.di_extsize;
2670 if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod))) 2835 if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
2671 args.mod = (xfs_extlen_t)(args.prod - args.mod); 2836 args.mod = (xfs_extlen_t)(args.prod - args.mod);
2672 } else if (unlikely(mp->m_sb.sb_blocksize >= NBPP)) { 2837 } else if (mp->m_sb.sb_blocksize >= NBPP) {
2673 args.prod = 1; 2838 args.prod = 1;
2674 args.mod = 0; 2839 args.mod = 0;
2675 } else { 2840 } else {
@@ -2885,6 +3050,7 @@ xfs_bmap_del_extent(
2885 xfs_btree_cur_t *cur, /* if null, not a btree */ 3050 xfs_btree_cur_t *cur, /* if null, not a btree */
2886 xfs_bmbt_irec_t *del, /* data to remove from extents */ 3051 xfs_bmbt_irec_t *del, /* data to remove from extents */
2887 int *logflagsp, /* inode logging flags */ 3052 int *logflagsp, /* inode logging flags */
3053 xfs_extdelta_t *delta, /* Change made to incore extents */
2888 int whichfork, /* data or attr fork */ 3054 int whichfork, /* data or attr fork */
2889 int rsvd) /* OK to allocate reserved blocks */ 3055 int rsvd) /* OK to allocate reserved blocks */
2890{ 3056{
@@ -3193,6 +3359,14 @@ xfs_bmap_del_extent(
3193 if (da_old > da_new) 3359 if (da_old > da_new)
3194 xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int)(da_old - da_new), 3360 xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int)(da_old - da_new),
3195 rsvd); 3361 rsvd);
3362 if (delta) {
3363 /* DELTA: report the original extent. */
3364 if (delta->xed_startoff > got.br_startoff)
3365 delta->xed_startoff = got.br_startoff;
3366 if (delta->xed_blockcount < got.br_startoff+got.br_blockcount)
3367 delta->xed_blockcount = got.br_startoff +
3368 got.br_blockcount;
3369 }
3196done: 3370done:
3197 *logflagsp = flags; 3371 *logflagsp = flags;
3198 return error; 3372 return error;
@@ -3279,6 +3453,7 @@ xfs_bmap_extents_to_btree(
3279 XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE); 3453 XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
3280 args.tp = tp; 3454 args.tp = tp;
3281 args.mp = mp; 3455 args.mp = mp;
3456 args.firstblock = *firstblock;
3282 if (*firstblock == NULLFSBLOCK) { 3457 if (*firstblock == NULLFSBLOCK) {
3283 args.type = XFS_ALLOCTYPE_START_BNO; 3458 args.type = XFS_ALLOCTYPE_START_BNO;
3284 args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); 3459 args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
@@ -3414,6 +3589,7 @@ xfs_bmap_local_to_extents(
3414 3589
3415 args.tp = tp; 3590 args.tp = tp;
3416 args.mp = ip->i_mount; 3591 args.mp = ip->i_mount;
3592 args.firstblock = *firstblock;
3417 ASSERT((ifp->if_flags & 3593 ASSERT((ifp->if_flags &
3418 (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE); 3594 (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE);
3419 /* 3595 /*
@@ -3753,7 +3929,7 @@ xfs_bunmap_trace(
3753 if (ip->i_rwtrace == NULL) 3929 if (ip->i_rwtrace == NULL)
3754 return; 3930 return;
3755 ktrace_enter(ip->i_rwtrace, 3931 ktrace_enter(ip->i_rwtrace,
3756 (void *)(__psint_t)XFS_BUNMAPI, 3932 (void *)(__psint_t)XFS_BUNMAP,
3757 (void *)ip, 3933 (void *)ip,
3758 (void *)(__psint_t)((ip->i_d.di_size >> 32) & 0xffffffff), 3934 (void *)(__psint_t)((ip->i_d.di_size >> 32) & 0xffffffff),
3759 (void *)(__psint_t)(ip->i_d.di_size & 0xffffffff), 3935 (void *)(__psint_t)(ip->i_d.di_size & 0xffffffff),
@@ -4087,8 +4263,8 @@ xfs_bmap_finish(
4087 if (!XFS_FORCED_SHUTDOWN(mp)) 4263 if (!XFS_FORCED_SHUTDOWN(mp))
4088 xfs_force_shutdown(mp, 4264 xfs_force_shutdown(mp,
4089 (error == EFSCORRUPTED) ? 4265 (error == EFSCORRUPTED) ?
4090 XFS_CORRUPT_INCORE : 4266 SHUTDOWN_CORRUPT_INCORE :
4091 XFS_METADATA_IO_ERROR); 4267 SHUTDOWN_META_IO_ERROR);
4092 return error; 4268 return error;
4093 } 4269 }
4094 xfs_trans_log_efd_extent(ntp, efd, free->xbfi_startblock, 4270 xfs_trans_log_efd_extent(ntp, efd, free->xbfi_startblock,
@@ -4538,7 +4714,8 @@ xfs_bmapi(
4538 xfs_extlen_t total, /* total blocks needed */ 4714 xfs_extlen_t total, /* total blocks needed */
4539 xfs_bmbt_irec_t *mval, /* output: map values */ 4715 xfs_bmbt_irec_t *mval, /* output: map values */
4540 int *nmap, /* i/o: mval size/count */ 4716 int *nmap, /* i/o: mval size/count */
4541 xfs_bmap_free_t *flist) /* i/o: list extents to free */ 4717 xfs_bmap_free_t *flist, /* i/o: list extents to free */
4718 xfs_extdelta_t *delta) /* o: change made to incore extents */
4542{ 4719{
4543 xfs_fsblock_t abno; /* allocated block number */ 4720 xfs_fsblock_t abno; /* allocated block number */
4544 xfs_extlen_t alen; /* allocated extent length */ 4721 xfs_extlen_t alen; /* allocated extent length */
@@ -4650,6 +4827,10 @@ xfs_bmapi(
4650 end = bno + len; 4827 end = bno + len;
4651 obno = bno; 4828 obno = bno;
4652 bma.ip = NULL; 4829 bma.ip = NULL;
4830 if (delta) {
4831 delta->xed_startoff = NULLFILEOFF;
4832 delta->xed_blockcount = 0;
4833 }
4653 while (bno < end && n < *nmap) { 4834 while (bno < end && n < *nmap) {
4654 /* 4835 /*
4655 * Reading past eof, act as though there's a hole 4836 * Reading past eof, act as though there's a hole
@@ -4886,8 +5067,8 @@ xfs_bmapi(
4886 got.br_state = XFS_EXT_UNWRITTEN; 5067 got.br_state = XFS_EXT_UNWRITTEN;
4887 } 5068 }
4888 error = xfs_bmap_add_extent(ip, lastx, &cur, &got, 5069 error = xfs_bmap_add_extent(ip, lastx, &cur, &got,
4889 firstblock, flist, &tmp_logflags, whichfork, 5070 firstblock, flist, &tmp_logflags, delta,
4890 (flags & XFS_BMAPI_RSVBLOCKS)); 5071 whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
4891 logflags |= tmp_logflags; 5072 logflags |= tmp_logflags;
4892 if (error) 5073 if (error)
4893 goto error0; 5074 goto error0;
@@ -4983,8 +5164,8 @@ xfs_bmapi(
4983 } 5164 }
4984 mval->br_state = XFS_EXT_NORM; 5165 mval->br_state = XFS_EXT_NORM;
4985 error = xfs_bmap_add_extent(ip, lastx, &cur, mval, 5166 error = xfs_bmap_add_extent(ip, lastx, &cur, mval,
4986 firstblock, flist, &tmp_logflags, whichfork, 5167 firstblock, flist, &tmp_logflags, delta,
4987 (flags & XFS_BMAPI_RSVBLOCKS)); 5168 whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
4988 logflags |= tmp_logflags; 5169 logflags |= tmp_logflags;
4989 if (error) 5170 if (error)
4990 goto error0; 5171 goto error0;
@@ -5073,7 +5254,14 @@ xfs_bmapi(
5073 ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE || 5254 ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
5074 XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max); 5255 XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max);
5075 error = 0; 5256 error = 0;
5076 5257 if (delta && delta->xed_startoff != NULLFILEOFF) {
5258 /* A change was actually made.
5259 * Note that delta->xed_blockount is an offset at this
5260 * point and needs to be converted to a block count.
5261 */
5262 ASSERT(delta->xed_blockcount > delta->xed_startoff);
5263 delta->xed_blockcount -= delta->xed_startoff;
5264 }
5077error0: 5265error0:
5078 /* 5266 /*
5079 * Log everything. Do this after conversion, there's no point in 5267 * Log everything. Do this after conversion, there's no point in
@@ -5185,6 +5373,8 @@ xfs_bunmapi(
5185 xfs_fsblock_t *firstblock, /* first allocated block 5373 xfs_fsblock_t *firstblock, /* first allocated block
5186 controls a.g. for allocs */ 5374 controls a.g. for allocs */
5187 xfs_bmap_free_t *flist, /* i/o: list extents to free */ 5375 xfs_bmap_free_t *flist, /* i/o: list extents to free */
5376 xfs_extdelta_t *delta, /* o: change made to incore
5377 extents */
5188 int *done) /* set if not done yet */ 5378 int *done) /* set if not done yet */
5189{ 5379{
5190 xfs_btree_cur_t *cur; /* bmap btree cursor */ 5380 xfs_btree_cur_t *cur; /* bmap btree cursor */
@@ -5242,6 +5432,10 @@ xfs_bunmapi(
5242 bno = start + len - 1; 5432 bno = start + len - 1;
5243 ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, 5433 ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
5244 &prev); 5434 &prev);
5435 if (delta) {
5436 delta->xed_startoff = NULLFILEOFF;
5437 delta->xed_blockcount = 0;
5438 }
5245 /* 5439 /*
5246 * Check to see if the given block number is past the end of the 5440 * Check to see if the given block number is past the end of the
5247 * file, back up to the last block if so... 5441 * file, back up to the last block if so...
@@ -5340,7 +5534,8 @@ xfs_bunmapi(
5340 } 5534 }
5341 del.br_state = XFS_EXT_UNWRITTEN; 5535 del.br_state = XFS_EXT_UNWRITTEN;
5342 error = xfs_bmap_add_extent(ip, lastx, &cur, &del, 5536 error = xfs_bmap_add_extent(ip, lastx, &cur, &del,
5343 firstblock, flist, &logflags, XFS_DATA_FORK, 0); 5537 firstblock, flist, &logflags, delta,
5538 XFS_DATA_FORK, 0);
5344 if (error) 5539 if (error)
5345 goto error0; 5540 goto error0;
5346 goto nodelete; 5541 goto nodelete;
@@ -5394,7 +5589,7 @@ xfs_bunmapi(
5394 prev.br_state = XFS_EXT_UNWRITTEN; 5589 prev.br_state = XFS_EXT_UNWRITTEN;
5395 error = xfs_bmap_add_extent(ip, lastx - 1, &cur, 5590 error = xfs_bmap_add_extent(ip, lastx - 1, &cur,
5396 &prev, firstblock, flist, &logflags, 5591 &prev, firstblock, flist, &logflags,
5397 XFS_DATA_FORK, 0); 5592 delta, XFS_DATA_FORK, 0);
5398 if (error) 5593 if (error)
5399 goto error0; 5594 goto error0;
5400 goto nodelete; 5595 goto nodelete;
@@ -5403,7 +5598,7 @@ xfs_bunmapi(
5403 del.br_state = XFS_EXT_UNWRITTEN; 5598 del.br_state = XFS_EXT_UNWRITTEN;
5404 error = xfs_bmap_add_extent(ip, lastx, &cur, 5599 error = xfs_bmap_add_extent(ip, lastx, &cur,
5405 &del, firstblock, flist, &logflags, 5600 &del, firstblock, flist, &logflags,
5406 XFS_DATA_FORK, 0); 5601 delta, XFS_DATA_FORK, 0);
5407 if (error) 5602 if (error)
5408 goto error0; 5603 goto error0;
5409 goto nodelete; 5604 goto nodelete;
@@ -5456,7 +5651,7 @@ xfs_bunmapi(
5456 goto error0; 5651 goto error0;
5457 } 5652 }
5458 error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del, 5653 error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del,
5459 &tmp_logflags, whichfork, rsvd); 5654 &tmp_logflags, delta, whichfork, rsvd);
5460 logflags |= tmp_logflags; 5655 logflags |= tmp_logflags;
5461 if (error) 5656 if (error)
5462 goto error0; 5657 goto error0;
@@ -5513,6 +5708,14 @@ nodelete:
5513 ASSERT(ifp->if_ext_max == 5708 ASSERT(ifp->if_ext_max ==
5514 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); 5709 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
5515 error = 0; 5710 error = 0;
5711 if (delta && delta->xed_startoff != NULLFILEOFF) {
5712 /* A change was actually made.
5713 * Note that delta->xed_blockount is an offset at this
5714 * point and needs to be converted to a block count.
5715 */
5716 ASSERT(delta->xed_blockcount > delta->xed_startoff);
5717 delta->xed_blockcount -= delta->xed_startoff;
5718 }
5516error0: 5719error0:
5517 /* 5720 /*
5518 * Log everything. Do this after conversion, there's no point in 5721 * Log everything. Do this after conversion, there's no point in
@@ -5556,7 +5759,7 @@ xfs_getbmap(
5556 __int64_t fixlen; /* length for -1 case */ 5759 __int64_t fixlen; /* length for -1 case */
5557 int i; /* extent number */ 5760 int i; /* extent number */
5558 xfs_inode_t *ip; /* xfs incore inode pointer */ 5761 xfs_inode_t *ip; /* xfs incore inode pointer */
5559 vnode_t *vp; /* corresponding vnode */ 5762 bhv_vnode_t *vp; /* corresponding vnode */
5560 int lock; /* lock state */ 5763 int lock; /* lock state */
5561 xfs_bmbt_irec_t *map; /* buffer for user's data */ 5764 xfs_bmbt_irec_t *map; /* buffer for user's data */
5562 xfs_mount_t *mp; /* file system mount point */ 5765 xfs_mount_t *mp; /* file system mount point */
@@ -5653,7 +5856,7 @@ xfs_getbmap(
5653 5856
5654 if (whichfork == XFS_DATA_FORK && ip->i_delayed_blks) { 5857 if (whichfork == XFS_DATA_FORK && ip->i_delayed_blks) {
5655 /* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */ 5858 /* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */
5656 VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error); 5859 error = bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF);
5657 } 5860 }
5658 5861
5659 ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0); 5862 ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0);
@@ -5689,7 +5892,8 @@ xfs_getbmap(
5689 nmap = (nexleft > subnex) ? subnex : nexleft; 5892 nmap = (nexleft > subnex) ? subnex : nexleft;
5690 error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), 5893 error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
5691 XFS_BB_TO_FSB(mp, bmv->bmv_length), 5894 XFS_BB_TO_FSB(mp, bmv->bmv_length),
5692 bmapi_flags, NULL, 0, map, &nmap, NULL); 5895 bmapi_flags, NULL, 0, map, &nmap,
5896 NULL, NULL);
5693 if (error) 5897 if (error)
5694 goto unlock_and_return; 5898 goto unlock_and_return;
5695 ASSERT(nmap <= subnex); 5899 ASSERT(nmap <= subnex);
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 8e0d73d9ccc4..80e93409b78d 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -26,6 +26,20 @@ struct xfs_mount;
26struct xfs_trans; 26struct xfs_trans;
27 27
28/* 28/*
29 * DELTA: describe a change to the in-core extent list.
30 *
31 * Internally the use of xed_blockount is somewhat funky.
32 * xed_blockcount contains an offset much of the time because this
33 * makes merging changes easier. (xfs_fileoff_t and xfs_filblks_t are
34 * the same underlying type).
35 */
36typedef struct xfs_extdelta
37{
38 xfs_fileoff_t xed_startoff; /* offset of range */
39 xfs_filblks_t xed_blockcount; /* blocks in range */
40} xfs_extdelta_t;
41
42/*
29 * List of extents to be free "later". 43 * List of extents to be free "later".
30 * The list is kept sorted on xbf_startblock. 44 * The list is kept sorted on xbf_startblock.
31 */ 45 */
@@ -275,7 +289,9 @@ xfs_bmapi(
275 xfs_extlen_t total, /* total blocks needed */ 289 xfs_extlen_t total, /* total blocks needed */
276 struct xfs_bmbt_irec *mval, /* output: map values */ 290 struct xfs_bmbt_irec *mval, /* output: map values */
277 int *nmap, /* i/o: mval size/count */ 291 int *nmap, /* i/o: mval size/count */
278 xfs_bmap_free_t *flist); /* i/o: list extents to free */ 292 xfs_bmap_free_t *flist, /* i/o: list extents to free */
293 xfs_extdelta_t *delta); /* o: change made to incore
294 extents */
279 295
280/* 296/*
281 * Map file blocks to filesystem blocks, simple version. 297 * Map file blocks to filesystem blocks, simple version.
@@ -309,6 +325,8 @@ xfs_bunmapi(
309 xfs_fsblock_t *firstblock, /* first allocated block 325 xfs_fsblock_t *firstblock, /* first allocated block
310 controls a.g. for allocs */ 326 controls a.g. for allocs */
311 xfs_bmap_free_t *flist, /* i/o: list extents to free */ 327 xfs_bmap_free_t *flist, /* i/o: list extents to free */
328 xfs_extdelta_t *delta, /* o: change made to incore
329 extents */
312 int *done); /* set if not done yet */ 330 int *done); /* set if not done yet */
313 331
314/* 332/*
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index bea44709afbe..18fb7385d719 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
@@ -1569,12 +1567,11 @@ xfs_bmbt_split(
1569 lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp)); 1567 lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp));
1570 left = XFS_BUF_TO_BMBT_BLOCK(lbp); 1568 left = XFS_BUF_TO_BMBT_BLOCK(lbp);
1571 args.fsbno = cur->bc_private.b.firstblock; 1569 args.fsbno = cur->bc_private.b.firstblock;
1570 args.firstblock = args.fsbno;
1572 if (args.fsbno == NULLFSBLOCK) { 1571 if (args.fsbno == NULLFSBLOCK) {
1573 args.fsbno = lbno; 1572 args.fsbno = lbno;
1574 args.type = XFS_ALLOCTYPE_START_BNO; 1573 args.type = XFS_ALLOCTYPE_START_BNO;
1575 } else if (cur->bc_private.b.flist->xbf_low) 1574 } else
1576 args.type = XFS_ALLOCTYPE_FIRST_AG;
1577 else
1578 args.type = XFS_ALLOCTYPE_NEAR_BNO; 1575 args.type = XFS_ALLOCTYPE_NEAR_BNO;
1579 args.mod = args.minleft = args.alignment = args.total = args.isfl = 1576 args.mod = args.minleft = args.alignment = args.total = args.isfl =
1580 args.userdata = args.minalignslop = 0; 1577 args.userdata = args.minalignslop = 0;
@@ -2356,6 +2353,7 @@ xfs_bmbt_newroot(
2356 args.userdata = args.minalignslop = 0; 2353 args.userdata = args.minalignslop = 0;
2357 args.minlen = args.maxlen = args.prod = 1; 2354 args.minlen = args.maxlen = args.prod = 1;
2358 args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; 2355 args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
2356 args.firstblock = args.fsbno;
2359 if (args.fsbno == NULLFSBLOCK) { 2357 if (args.fsbno == NULLFSBLOCK) {
2360#ifdef DEBUG 2358#ifdef DEBUG
2361 if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) { 2359 if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
@@ -2365,9 +2363,7 @@ xfs_bmbt_newroot(
2365#endif 2363#endif
2366 args.fsbno = INT_GET(*pp, ARCH_CONVERT); 2364 args.fsbno = INT_GET(*pp, ARCH_CONVERT);
2367 args.type = XFS_ALLOCTYPE_START_BNO; 2365 args.type = XFS_ALLOCTYPE_START_BNO;
2368 } else if (args.wasdel) 2366 } else
2369 args.type = XFS_ALLOCTYPE_FIRST_AG;
2370 else
2371 args.type = XFS_ALLOCTYPE_NEAR_BNO; 2367 args.type = XFS_ALLOCTYPE_NEAR_BNO;
2372 if ((error = xfs_alloc_vextent(&args))) { 2368 if ((error = xfs_alloc_vextent(&args))) {
2373 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2369 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 52d5d095fc35..ee2255bd6562 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 5fed15682dda..a4aa53974f76 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -23,7 +23,6 @@
23#include "xfs_inum.h" 23#include "xfs_inum.h"
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_dir.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_buf_item.h" 28#include "xfs_buf_item.h"
@@ -1030,9 +1029,9 @@ xfs_buf_iodone_callbacks(
1030 if ((XFS_BUF_TARGET(bp) != lasttarg) || 1029 if ((XFS_BUF_TARGET(bp) != lasttarg) ||
1031 (time_after(jiffies, (lasttime + 5*HZ)))) { 1030 (time_after(jiffies, (lasttime + 5*HZ)))) {
1032 lasttime = jiffies; 1031 lasttime = jiffies;
1033 prdev("XFS write error in file system meta-data " 1032 cmn_err(CE_ALERT, "Device %s, XFS metadata write error"
1034 "block 0x%llx in %s", 1033 " block 0x%llx in %s",
1035 XFS_BUF_TARGET(bp), 1034 XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),
1036 (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname); 1035 (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname);
1037 } 1036 }
1038 lasttarg = XFS_BUF_TARGET(bp); 1037 lasttarg = XFS_BUF_TARGET(bp);
@@ -1108,7 +1107,7 @@ xfs_buf_error_relse(
1108 XFS_BUF_ERROR(bp,0); 1107 XFS_BUF_ERROR(bp,0);
1109 xfs_buftrace("BUF_ERROR_RELSE", bp); 1108 xfs_buftrace("BUF_ERROR_RELSE", bp);
1110 if (! XFS_FORCED_SHUTDOWN(mp)) 1109 if (! XFS_FORCED_SHUTDOWN(mp))
1111 xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); 1110 xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
1112 /* 1111 /*
1113 * We have to unpin the pinned buffers so do the 1112 * We have to unpin the pinned buffers so do the
1114 * callbacks. 1113 * callbacks.
diff --git a/fs/xfs/xfs_cap.h b/fs/xfs/xfs_cap.h
index d0035c6e9514..7a0e482dd436 100644
--- a/fs/xfs/xfs_cap.h
+++ b/fs/xfs/xfs_cap.h
@@ -49,12 +49,12 @@ typedef struct xfs_cap_set {
49 49
50#include <linux/posix_cap_xattr.h> 50#include <linux/posix_cap_xattr.h>
51 51
52struct vnode; 52struct bhv_vnode;
53 53
54extern int xfs_cap_vhascap(struct vnode *); 54extern int xfs_cap_vhascap(struct bhv_vnode *);
55extern int xfs_cap_vset(struct vnode *, void *, size_t); 55extern int xfs_cap_vset(struct bhv_vnode *, void *, size_t);
56extern int xfs_cap_vget(struct vnode *, void *, size_t); 56extern int xfs_cap_vget(struct bhv_vnode *, void *, size_t);
57extern int xfs_cap_vremove(struct vnode *vp); 57extern int xfs_cap_vremove(struct bhv_vnode *);
58 58
59#define _CAP_EXISTS xfs_cap_vhascap 59#define _CAP_EXISTS xfs_cap_vhascap
60 60
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 8988b9051175..32ab61d17ace 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -24,7 +24,6 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
@@ -43,7 +41,6 @@
43#include "xfs_bmap.h" 41#include "xfs_bmap.h"
44#include "xfs_attr.h" 42#include "xfs_attr.h"
45#include "xfs_attr_leaf.h" 43#include "xfs_attr_leaf.h"
46#include "xfs_dir_leaf.h"
47#include "xfs_dir2_data.h" 44#include "xfs_dir2_data.h"
48#include "xfs_dir2_leaf.h" 45#include "xfs_dir2_leaf.h"
49#include "xfs_dir2_block.h" 46#include "xfs_dir2_block.h"
@@ -159,7 +156,7 @@ xfs_da_split(xfs_da_state_t *state)
159 max = state->path.active - 1; 156 max = state->path.active - 1;
160 ASSERT((max >= 0) && (max < XFS_DA_NODE_MAXDEPTH)); 157 ASSERT((max >= 0) && (max < XFS_DA_NODE_MAXDEPTH));
161 ASSERT(state->path.blk[max].magic == XFS_ATTR_LEAF_MAGIC || 158 ASSERT(state->path.blk[max].magic == XFS_ATTR_LEAF_MAGIC ||
162 state->path.blk[max].magic == XFS_DIRX_LEAF_MAGIC(state->mp)); 159 state->path.blk[max].magic == XFS_DIR2_LEAFN_MAGIC);
163 160
164 addblk = &state->path.blk[max]; /* initial dummy value */ 161 addblk = &state->path.blk[max]; /* initial dummy value */
165 for (i = max; (i >= 0) && addblk; state->path.active--, i--) { 162 for (i = max; (i >= 0) && addblk; state->path.active--, i--) {
@@ -199,38 +196,7 @@ xfs_da_split(xfs_da_state_t *state)
199 return(error); /* GROT: attr inconsistent */ 196 return(error); /* GROT: attr inconsistent */
200 addblk = newblk; 197 addblk = newblk;
201 break; 198 break;
202 case XFS_DIR_LEAF_MAGIC:
203 ASSERT(XFS_DIR_IS_V1(state->mp));
204 error = xfs_dir_leaf_split(state, oldblk, newblk);
205 if ((error != 0) && (error != ENOSPC)) {
206 return(error); /* GROT: dir is inconsistent */
207 }
208 if (!error) {
209 addblk = newblk;
210 break;
211 }
212 /*
213 * Entry wouldn't fit, split the leaf again.
214 */
215 state->extravalid = 1;
216 if (state->inleaf) {
217 state->extraafter = 0; /* before newblk */
218 error = xfs_dir_leaf_split(state, oldblk,
219 &state->extrablk);
220 if (error)
221 return(error); /* GROT: dir incon. */
222 addblk = newblk;
223 } else {
224 state->extraafter = 1; /* after newblk */
225 error = xfs_dir_leaf_split(state, newblk,
226 &state->extrablk);
227 if (error)
228 return(error); /* GROT: dir incon. */
229 addblk = newblk;
230 }
231 break;
232 case XFS_DIR2_LEAFN_MAGIC: 199 case XFS_DIR2_LEAFN_MAGIC:
233 ASSERT(XFS_DIR_IS_V2(state->mp));
234 error = xfs_dir2_leafn_split(state, oldblk, newblk); 200 error = xfs_dir2_leafn_split(state, oldblk, newblk);
235 if (error) 201 if (error)
236 return error; 202 return error;
@@ -363,7 +329,6 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
363 size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] - 329 size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] -
364 (char *)oldroot); 330 (char *)oldroot);
365 } else { 331 } else {
366 ASSERT(XFS_DIR_IS_V2(mp));
367 ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); 332 ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
368 leaf = (xfs_dir2_leaf_t *)oldroot; 333 leaf = (xfs_dir2_leaf_t *)oldroot;
369 size = (int)((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] - 334 size = (int)((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] -
@@ -379,8 +344,7 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
379 * Set up the new root node. 344 * Set up the new root node.
380 */ 345 */
381 error = xfs_da_node_create(args, 346 error = xfs_da_node_create(args,
382 args->whichfork == XFS_DATA_FORK && 347 (args->whichfork == XFS_DATA_FORK) ? mp->m_dirleafblk : 0,
383 XFS_DIR_IS_V2(mp) ? mp->m_dirleafblk : 0,
384 be16_to_cpu(node->hdr.level) + 1, &bp, args->whichfork); 348 be16_to_cpu(node->hdr.level) + 1, &bp, args->whichfork);
385 if (error) 349 if (error)
386 return(error); 350 return(error);
@@ -427,10 +391,9 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
427 ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); 391 ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
428 392
429 /* 393 /*
430 * With V2 the extra block is data or freespace. 394 * With V2 dirs the extra block is data or freespace.
431 */ 395 */
432 useextra = state->extravalid && (XFS_DIR_IS_V1(state->mp) || 396 useextra = state->extravalid && state->args->whichfork == XFS_ATTR_FORK;
433 state->args->whichfork == XFS_ATTR_FORK);
434 newcount = 1 + useextra; 397 newcount = 1 + useextra;
435 /* 398 /*
436 * Do we have to split the node? 399 * Do we have to split the node?
@@ -624,7 +587,7 @@ xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
624 ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); 587 ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
625 ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count))); 588 ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count)));
626 ASSERT(newblk->blkno != 0); 589 ASSERT(newblk->blkno != 0);
627 if (state->args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) 590 if (state->args->whichfork == XFS_DATA_FORK)
628 ASSERT(newblk->blkno >= mp->m_dirleafblk && 591 ASSERT(newblk->blkno >= mp->m_dirleafblk &&
629 newblk->blkno < mp->m_dirfreeblk); 592 newblk->blkno < mp->m_dirfreeblk);
630 593
@@ -670,7 +633,7 @@ xfs_da_join(xfs_da_state_t *state)
670 save_blk = &state->altpath.blk[ state->path.active-1 ]; 633 save_blk = &state->altpath.blk[ state->path.active-1 ];
671 ASSERT(state->path.blk[0].magic == XFS_DA_NODE_MAGIC); 634 ASSERT(state->path.blk[0].magic == XFS_DA_NODE_MAGIC);
672 ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC || 635 ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC ||
673 drop_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp)); 636 drop_blk->magic == XFS_DIR2_LEAFN_MAGIC);
674 637
675 /* 638 /*
676 * Walk back up the tree joining/deallocating as necessary. 639 * Walk back up the tree joining/deallocating as necessary.
@@ -693,17 +656,7 @@ xfs_da_join(xfs_da_state_t *state)
693 return(0); 656 return(0);
694 xfs_attr_leaf_unbalance(state, drop_blk, save_blk); 657 xfs_attr_leaf_unbalance(state, drop_blk, save_blk);
695 break; 658 break;
696 case XFS_DIR_LEAF_MAGIC:
697 ASSERT(XFS_DIR_IS_V1(state->mp));
698 error = xfs_dir_leaf_toosmall(state, &action);
699 if (error)
700 return(error);
701 if (action == 0)
702 return(0);
703 xfs_dir_leaf_unbalance(state, drop_blk, save_blk);
704 break;
705 case XFS_DIR2_LEAFN_MAGIC: 659 case XFS_DIR2_LEAFN_MAGIC:
706 ASSERT(XFS_DIR_IS_V2(state->mp));
707 error = xfs_dir2_leafn_toosmall(state, &action); 660 error = xfs_dir2_leafn_toosmall(state, &action);
708 if (error) 661 if (error)
709 return error; 662 return error;
@@ -790,7 +743,7 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
790 ASSERT(bp != NULL); 743 ASSERT(bp != NULL);
791 blkinfo = bp->data; 744 blkinfo = bp->data;
792 if (be16_to_cpu(oldroot->hdr.level) == 1) { 745 if (be16_to_cpu(oldroot->hdr.level) == 1) {
793 ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || 746 ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DIR2_LEAFN_MAGIC ||
794 be16_to_cpu(blkinfo->magic) == XFS_ATTR_LEAF_MAGIC); 747 be16_to_cpu(blkinfo->magic) == XFS_ATTR_LEAF_MAGIC);
795 } else { 748 } else {
796 ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DA_NODE_MAGIC); 749 ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DA_NODE_MAGIC);
@@ -951,14 +904,7 @@ xfs_da_fixhashpath(xfs_da_state_t *state, xfs_da_state_path_t *path)
951 if (count == 0) 904 if (count == 0)
952 return; 905 return;
953 break; 906 break;
954 case XFS_DIR_LEAF_MAGIC:
955 ASSERT(XFS_DIR_IS_V1(state->mp));
956 lasthash = xfs_dir_leaf_lasthash(blk->bp, &count);
957 if (count == 0)
958 return;
959 break;
960 case XFS_DIR2_LEAFN_MAGIC: 907 case XFS_DIR2_LEAFN_MAGIC:
961 ASSERT(XFS_DIR_IS_V2(state->mp));
962 lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count); 908 lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count);
963 if (count == 0) 909 if (count == 0)
964 return; 910 return;
@@ -1117,10 +1063,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1117 * Descend thru the B-tree searching each level for the right 1063 * Descend thru the B-tree searching each level for the right
1118 * node to use, until the right hashval is found. 1064 * node to use, until the right hashval is found.
1119 */ 1065 */
1120 if (args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(state->mp)) 1066 blkno = (args->whichfork == XFS_DATA_FORK)? state->mp->m_dirleafblk : 0;
1121 blkno = state->mp->m_dirleafblk;
1122 else
1123 blkno = 0;
1124 for (blk = &state->path.blk[0], state->path.active = 1; 1067 for (blk = &state->path.blk[0], state->path.active = 1;
1125 state->path.active <= XFS_DA_NODE_MAXDEPTH; 1068 state->path.active <= XFS_DA_NODE_MAXDEPTH;
1126 blk++, state->path.active++) { 1069 blk++, state->path.active++) {
@@ -1137,7 +1080,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1137 } 1080 }
1138 curr = blk->bp->data; 1081 curr = blk->bp->data;
1139 ASSERT(be16_to_cpu(curr->magic) == XFS_DA_NODE_MAGIC || 1082 ASSERT(be16_to_cpu(curr->magic) == XFS_DA_NODE_MAGIC ||
1140 be16_to_cpu(curr->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || 1083 be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC ||
1141 be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC); 1084 be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC);
1142 1085
1143 /* 1086 /*
@@ -1190,16 +1133,10 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1190 blk->index = probe; 1133 blk->index = probe;
1191 blkno = be32_to_cpu(btree->before); 1134 blkno = be32_to_cpu(btree->before);
1192 } 1135 }
1193 } 1136 } else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) {
1194 else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) {
1195 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL); 1137 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
1196 break; 1138 break;
1197 } 1139 } else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) {
1198 else if (be16_to_cpu(curr->magic) == XFS_DIR_LEAF_MAGIC) {
1199 blk->hashval = xfs_dir_leaf_lasthash(blk->bp, NULL);
1200 break;
1201 }
1202 else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) {
1203 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL); 1140 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL);
1204 break; 1141 break;
1205 } 1142 }
@@ -1212,12 +1149,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1212 * next leaf and keep searching. 1149 * next leaf and keep searching.
1213 */ 1150 */
1214 for (;;) { 1151 for (;;) {
1215 if (blk->magic == XFS_DIR_LEAF_MAGIC) { 1152 if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
1216 ASSERT(XFS_DIR_IS_V1(state->mp));
1217 retval = xfs_dir_leaf_lookup_int(blk->bp, args,
1218 &blk->index);
1219 } else if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
1220 ASSERT(XFS_DIR_IS_V2(state->mp));
1221 retval = xfs_dir2_leafn_lookup_int(blk->bp, args, 1153 retval = xfs_dir2_leafn_lookup_int(blk->bp, args,
1222 &blk->index, state); 1154 &blk->index, state);
1223 } 1155 }
@@ -1270,7 +1202,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
1270 old_info = old_blk->bp->data; 1202 old_info = old_blk->bp->data;
1271 new_info = new_blk->bp->data; 1203 new_info = new_blk->bp->data;
1272 ASSERT(old_blk->magic == XFS_DA_NODE_MAGIC || 1204 ASSERT(old_blk->magic == XFS_DA_NODE_MAGIC ||
1273 old_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) || 1205 old_blk->magic == XFS_DIR2_LEAFN_MAGIC ||
1274 old_blk->magic == XFS_ATTR_LEAF_MAGIC); 1206 old_blk->magic == XFS_ATTR_LEAF_MAGIC);
1275 ASSERT(old_blk->magic == be16_to_cpu(old_info->magic)); 1207 ASSERT(old_blk->magic == be16_to_cpu(old_info->magic));
1276 ASSERT(new_blk->magic == be16_to_cpu(new_info->magic)); 1208 ASSERT(new_blk->magic == be16_to_cpu(new_info->magic));
@@ -1280,12 +1212,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
1280 case XFS_ATTR_LEAF_MAGIC: 1212 case XFS_ATTR_LEAF_MAGIC:
1281 before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp); 1213 before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp);
1282 break; 1214 break;
1283 case XFS_DIR_LEAF_MAGIC:
1284 ASSERT(XFS_DIR_IS_V1(state->mp));
1285 before = xfs_dir_leaf_order(old_blk->bp, new_blk->bp);
1286 break;
1287 case XFS_DIR2_LEAFN_MAGIC: 1215 case XFS_DIR2_LEAFN_MAGIC:
1288 ASSERT(XFS_DIR_IS_V2(state->mp));
1289 before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp); 1216 before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp);
1290 break; 1217 break;
1291 case XFS_DA_NODE_MAGIC: 1218 case XFS_DA_NODE_MAGIC:
@@ -1404,7 +1331,7 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
1404 save_info = save_blk->bp->data; 1331 save_info = save_blk->bp->data;
1405 drop_info = drop_blk->bp->data; 1332 drop_info = drop_blk->bp->data;
1406 ASSERT(save_blk->magic == XFS_DA_NODE_MAGIC || 1333 ASSERT(save_blk->magic == XFS_DA_NODE_MAGIC ||
1407 save_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) || 1334 save_blk->magic == XFS_DIR2_LEAFN_MAGIC ||
1408 save_blk->magic == XFS_ATTR_LEAF_MAGIC); 1335 save_blk->magic == XFS_ATTR_LEAF_MAGIC);
1409 ASSERT(save_blk->magic == be16_to_cpu(save_info->magic)); 1336 ASSERT(save_blk->magic == be16_to_cpu(save_info->magic));
1410 ASSERT(drop_blk->magic == be16_to_cpu(drop_info->magic)); 1337 ASSERT(drop_blk->magic == be16_to_cpu(drop_info->magic));
@@ -1529,7 +1456,7 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
1529 ASSERT(blk->bp != NULL); 1456 ASSERT(blk->bp != NULL);
1530 info = blk->bp->data; 1457 info = blk->bp->data;
1531 ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC || 1458 ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC ||
1532 be16_to_cpu(info->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || 1459 be16_to_cpu(info->magic) == XFS_DIR2_LEAFN_MAGIC ||
1533 be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC); 1460 be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC);
1534 blk->magic = be16_to_cpu(info->magic); 1461 blk->magic = be16_to_cpu(info->magic);
1535 if (blk->magic == XFS_DA_NODE_MAGIC) { 1462 if (blk->magic == XFS_DA_NODE_MAGIC) {
@@ -1548,20 +1475,13 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
1548 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, 1475 blk->hashval = xfs_attr_leaf_lasthash(blk->bp,
1549 NULL); 1476 NULL);
1550 break; 1477 break;
1551 case XFS_DIR_LEAF_MAGIC:
1552 ASSERT(XFS_DIR_IS_V1(state->mp));
1553 blk->hashval = xfs_dir_leaf_lasthash(blk->bp,
1554 NULL);
1555 break;
1556 case XFS_DIR2_LEAFN_MAGIC: 1478 case XFS_DIR2_LEAFN_MAGIC:
1557 ASSERT(XFS_DIR_IS_V2(state->mp));
1558 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, 1479 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp,
1559 NULL); 1480 NULL);
1560 break; 1481 break;
1561 default: 1482 default:
1562 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC || 1483 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC ||
1563 blk->magic == 1484 blk->magic == XFS_DIR2_LEAFN_MAGIC);
1564 XFS_DIRX_LEAF_MAGIC(state->mp));
1565 break; 1485 break;
1566 } 1486 }
1567 } 1487 }
@@ -1620,7 +1540,6 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
1620 xfs_bmbt_irec_t *mapp; 1540 xfs_bmbt_irec_t *mapp;
1621 xfs_inode_t *dp; 1541 xfs_inode_t *dp;
1622 int nmap, error, w, count, c, got, i, mapi; 1542 int nmap, error, w, count, c, got, i, mapi;
1623 xfs_fsize_t size;
1624 xfs_trans_t *tp; 1543 xfs_trans_t *tp;
1625 xfs_mount_t *mp; 1544 xfs_mount_t *mp;
1626 1545
@@ -1631,7 +1550,7 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
1631 /* 1550 /*
1632 * For new directories adjust the file offset and block count. 1551 * For new directories adjust the file offset and block count.
1633 */ 1552 */
1634 if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) { 1553 if (w == XFS_DATA_FORK) {
1635 bno = mp->m_dirleafblk; 1554 bno = mp->m_dirleafblk;
1636 count = mp->m_dirblkfsbs; 1555 count = mp->m_dirblkfsbs;
1637 } else { 1556 } else {
@@ -1641,10 +1560,9 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
1641 /* 1560 /*
1642 * Find a spot in the file space to put the new block. 1561 * Find a spot in the file space to put the new block.
1643 */ 1562 */
1644 if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w))) { 1563 if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w)))
1645 return error; 1564 return error;
1646 } 1565 if (w == XFS_DATA_FORK)
1647 if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
1648 ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk); 1566 ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk);
1649 /* 1567 /*
1650 * Try mapping it in one filesystem block. 1568 * Try mapping it in one filesystem block.
@@ -1655,7 +1573,7 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
1655 XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA| 1573 XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|
1656 XFS_BMAPI_CONTIG, 1574 XFS_BMAPI_CONTIG,
1657 args->firstblock, args->total, &map, &nmap, 1575 args->firstblock, args->total, &map, &nmap,
1658 args->flist))) { 1576 args->flist, NULL))) {
1659 return error; 1577 return error;
1660 } 1578 }
1661 ASSERT(nmap <= 1); 1579 ASSERT(nmap <= 1);
@@ -1676,7 +1594,8 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
1676 XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE| 1594 XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE|
1677 XFS_BMAPI_METADATA, 1595 XFS_BMAPI_METADATA,
1678 args->firstblock, args->total, 1596 args->firstblock, args->total,
1679 &mapp[mapi], &nmap, args->flist))) { 1597 &mapp[mapi], &nmap, args->flist,
1598 NULL))) {
1680 kmem_free(mapp, sizeof(*mapp) * count); 1599 kmem_free(mapp, sizeof(*mapp) * count);
1681 return error; 1600 return error;
1682 } 1601 }
@@ -1705,19 +1624,6 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
1705 if (mapp != &map) 1624 if (mapp != &map)
1706 kmem_free(mapp, sizeof(*mapp) * count); 1625 kmem_free(mapp, sizeof(*mapp) * count);
1707 *new_blkno = (xfs_dablk_t)bno; 1626 *new_blkno = (xfs_dablk_t)bno;
1708 /*
1709 * For version 1 directories, adjust the file size if it changed.
1710 */
1711 if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) {
1712 ASSERT(mapi == 1);
1713 if ((error = xfs_bmap_last_offset(tp, dp, &bno, w)))
1714 return error;
1715 size = XFS_FSB_TO_B(mp, bno);
1716 if (size != dp->i_d.di_size) {
1717 dp->i_d.di_size = size;
1718 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
1719 }
1720 }
1721 return 0; 1627 return 0;
1722} 1628}
1723 1629
@@ -1742,7 +1648,6 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
1742 int error, w, entno, level, dead_level; 1648 int error, w, entno, level, dead_level;
1743 xfs_da_blkinfo_t *dead_info, *sib_info; 1649 xfs_da_blkinfo_t *dead_info, *sib_info;
1744 xfs_da_intnode_t *par_node, *dead_node; 1650 xfs_da_intnode_t *par_node, *dead_node;
1745 xfs_dir_leafblock_t *dead_leaf;
1746 xfs_dir2_leaf_t *dead_leaf2; 1651 xfs_dir2_leaf_t *dead_leaf2;
1747 xfs_dahash_t dead_hash; 1652 xfs_dahash_t dead_hash;
1748 1653
@@ -1753,11 +1658,8 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
1753 w = args->whichfork; 1658 w = args->whichfork;
1754 ASSERT(w == XFS_DATA_FORK); 1659 ASSERT(w == XFS_DATA_FORK);
1755 mp = ip->i_mount; 1660 mp = ip->i_mount;
1756 if (XFS_DIR_IS_V2(mp)) { 1661 lastoff = mp->m_dirfreeblk;
1757 lastoff = mp->m_dirfreeblk; 1662 error = xfs_bmap_last_before(tp, ip, &lastoff, w);
1758 error = xfs_bmap_last_before(tp, ip, &lastoff, w);
1759 } else
1760 error = xfs_bmap_last_offset(tp, ip, &lastoff, w);
1761 if (error) 1663 if (error)
1762 return error; 1664 return error;
1763 if (unlikely(lastoff == 0)) { 1665 if (unlikely(lastoff == 0)) {
@@ -1780,14 +1682,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
1780 /* 1682 /*
1781 * Get values from the moved block. 1683 * Get values from the moved block.
1782 */ 1684 */
1783 if (be16_to_cpu(dead_info->magic) == XFS_DIR_LEAF_MAGIC) { 1685 if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) {
1784 ASSERT(XFS_DIR_IS_V1(mp));
1785 dead_leaf = (xfs_dir_leafblock_t *)dead_info;
1786 dead_level = 0;
1787 dead_hash =
1788 INT_GET(dead_leaf->entries[INT_GET(dead_leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT);
1789 } else if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) {
1790 ASSERT(XFS_DIR_IS_V2(mp));
1791 dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; 1686 dead_leaf2 = (xfs_dir2_leaf_t *)dead_info;
1792 dead_level = 0; 1687 dead_level = 0;
1793 dead_hash = be32_to_cpu(dead_leaf2->ents[be16_to_cpu(dead_leaf2->hdr.count) - 1].hashval); 1688 dead_hash = be32_to_cpu(dead_leaf2->ents[be16_to_cpu(dead_leaf2->hdr.count) - 1].hashval);
@@ -1842,7 +1737,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
1842 xfs_da_buf_done(sib_buf); 1737 xfs_da_buf_done(sib_buf);
1843 sib_buf = NULL; 1738 sib_buf = NULL;
1844 } 1739 }
1845 par_blkno = XFS_DIR_IS_V1(mp) ? 0 : mp->m_dirleafblk; 1740 par_blkno = mp->m_dirleafblk;
1846 level = -1; 1741 level = -1;
1847 /* 1742 /*
1848 * Walk down the tree looking for the parent of the moved block. 1743 * Walk down the tree looking for the parent of the moved block.
@@ -1941,8 +1836,6 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
1941{ 1836{
1942 xfs_inode_t *dp; 1837 xfs_inode_t *dp;
1943 int done, error, w, count; 1838 int done, error, w, count;
1944 xfs_fileoff_t bno;
1945 xfs_fsize_t size;
1946 xfs_trans_t *tp; 1839 xfs_trans_t *tp;
1947 xfs_mount_t *mp; 1840 xfs_mount_t *mp;
1948 1841
@@ -1950,7 +1843,7 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
1950 w = args->whichfork; 1843 w = args->whichfork;
1951 tp = args->trans; 1844 tp = args->trans;
1952 mp = dp->i_mount; 1845 mp = dp->i_mount;
1953 if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) 1846 if (w == XFS_DATA_FORK)
1954 count = mp->m_dirblkfsbs; 1847 count = mp->m_dirblkfsbs;
1955 else 1848 else
1956 count = 1; 1849 count = 1;
@@ -1961,34 +1854,17 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
1961 */ 1854 */
1962 if ((error = xfs_bunmapi(tp, dp, dead_blkno, count, 1855 if ((error = xfs_bunmapi(tp, dp, dead_blkno, count,
1963 XFS_BMAPI_AFLAG(w)|XFS_BMAPI_METADATA, 1856 XFS_BMAPI_AFLAG(w)|XFS_BMAPI_METADATA,
1964 0, args->firstblock, args->flist, 1857 0, args->firstblock, args->flist, NULL,
1965 &done)) == ENOSPC) { 1858 &done)) == ENOSPC) {
1966 if (w != XFS_DATA_FORK) 1859 if (w != XFS_DATA_FORK)
1967 goto done; 1860 break;
1968 if ((error = xfs_da_swap_lastblock(args, &dead_blkno, 1861 if ((error = xfs_da_swap_lastblock(args, &dead_blkno,
1969 &dead_buf))) 1862 &dead_buf)))
1970 goto done; 1863 break;
1971 } else if (error) 1864 } else {
1972 goto done;
1973 else
1974 break; 1865 break;
1975 }
1976 ASSERT(done);
1977 xfs_da_binval(tp, dead_buf);
1978 /*
1979 * Adjust the directory size for version 1.
1980 */
1981 if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) {
1982 if ((error = xfs_bmap_last_offset(tp, dp, &bno, w)))
1983 return error;
1984 size = XFS_FSB_TO_B(dp->i_mount, bno);
1985 if (size != dp->i_d.di_size) {
1986 dp->i_d.di_size = size;
1987 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
1988 } 1866 }
1989 } 1867 }
1990 return 0;
1991done:
1992 xfs_da_binval(tp, dead_buf); 1868 xfs_da_binval(tp, dead_buf);
1993 return error; 1869 return error;
1994} 1870}
@@ -2049,10 +1925,7 @@ xfs_da_do_buf(
2049 xfs_dabuf_t *rbp; 1925 xfs_dabuf_t *rbp;
2050 1926
2051 mp = dp->i_mount; 1927 mp = dp->i_mount;
2052 if (whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) 1928 nfsb = (whichfork == XFS_DATA_FORK) ? mp->m_dirblkfsbs : 1;
2053 nfsb = mp->m_dirblkfsbs;
2054 else
2055 nfsb = 1;
2056 mappedbno = *mappedbnop; 1929 mappedbno = *mappedbnop;
2057 /* 1930 /*
2058 * Caller doesn't have a mapping. -2 means don't complain 1931 * Caller doesn't have a mapping. -2 means don't complain
@@ -2086,7 +1959,7 @@ xfs_da_do_buf(
2086 nfsb, 1959 nfsb,
2087 XFS_BMAPI_METADATA | 1960 XFS_BMAPI_METADATA |
2088 XFS_BMAPI_AFLAG(whichfork), 1961 XFS_BMAPI_AFLAG(whichfork),
2089 NULL, 0, mapp, &nmap, NULL))) 1962 NULL, 0, mapp, &nmap, NULL, NULL)))
2090 goto exit0; 1963 goto exit0;
2091 } 1964 }
2092 } else { 1965 } else {
@@ -2198,7 +2071,6 @@ xfs_da_do_buf(
2198 magic1 = be32_to_cpu(data->hdr.magic); 2071 magic1 = be32_to_cpu(data->hdr.magic);
2199 if (unlikely( 2072 if (unlikely(
2200 XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && 2073 XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) &&
2201 (magic != XFS_DIR_LEAF_MAGIC) &&
2202 (magic != XFS_ATTR_LEAF_MAGIC) && 2074 (magic != XFS_ATTR_LEAF_MAGIC) &&
2203 (magic != XFS_DIR2_LEAF1_MAGIC) && 2075 (magic != XFS_DIR2_LEAF1_MAGIC) &&
2204 (magic != XFS_DIR2_LEAFN_MAGIC) && 2076 (magic != XFS_DIR2_LEAFN_MAGIC) &&
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 243a730d5ec8..4ab865ec8b82 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -36,14 +36,10 @@ struct zone;
36 * level in the Btree, and to identify which type of block this is. 36 * level in the Btree, and to identify which type of block this is.
37 */ 37 */
38#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */ 38#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */
39#define XFS_DIR_LEAF_MAGIC 0xfeeb /* magic number: directory leaf blks */
40#define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */ 39#define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */
41#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */ 40#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
42#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */ 41#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
43 42
44#define XFS_DIRX_LEAF_MAGIC(mp) \
45 (XFS_DIR_IS_V1(mp) ? XFS_DIR_LEAF_MAGIC : XFS_DIR2_LEAFN_MAGIC)
46
47typedef struct xfs_da_blkinfo { 43typedef struct xfs_da_blkinfo {
48 __be32 forw; /* previous block in list */ 44 __be32 forw; /* previous block in list */
49 __be32 back; /* following block in list */ 45 __be32 back; /* following block in list */
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 4968a6358e61..80562b60fb95 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
@@ -54,24 +52,14 @@ xfs_swapext(
54 xfs_swapext_t __user *sxu) 52 xfs_swapext_t __user *sxu)
55{ 53{
56 xfs_swapext_t *sxp; 54 xfs_swapext_t *sxp;
57 xfs_inode_t *ip=NULL, *tip=NULL, *ips[2]; 55 xfs_inode_t *ip=NULL, *tip=NULL;
58 xfs_trans_t *tp;
59 xfs_mount_t *mp; 56 xfs_mount_t *mp;
60 xfs_bstat_t *sbp;
61 struct file *fp = NULL, *tfp = NULL; 57 struct file *fp = NULL, *tfp = NULL;
62 vnode_t *vp, *tvp; 58 bhv_vnode_t *vp, *tvp;
63 static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL;
64 int ilf_fields, tilf_fields;
65 int error = 0; 59 int error = 0;
66 xfs_ifork_t *tempifp, *ifp, *tifp;
67 __uint64_t tmp;
68 int aforkblks = 0;
69 int taforkblks = 0;
70 char locked = 0;
71 60
72 sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL); 61 sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL);
73 tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); 62 if (!sxp) {
74 if (!sxp || !tempifp) {
75 error = XFS_ERROR(ENOMEM); 63 error = XFS_ERROR(ENOMEM);
76 goto error0; 64 goto error0;
77 } 65 }
@@ -118,14 +106,56 @@ xfs_swapext(
118 106
119 mp = ip->i_mount; 107 mp = ip->i_mount;
120 108
121 sbp = &sxp->sx_stat;
122
123 if (XFS_FORCED_SHUTDOWN(mp)) { 109 if (XFS_FORCED_SHUTDOWN(mp)) {
124 error = XFS_ERROR(EIO); 110 error = XFS_ERROR(EIO);
125 goto error0; 111 goto error0;
126 } 112 }
127 113
128 locked = 1; 114 error = XFS_SWAP_EXTENTS(mp, &ip->i_iocore, &tip->i_iocore, sxp);
115
116 error0:
117 if (fp != NULL)
118 fput(fp);
119 if (tfp != NULL)
120 fput(tfp);
121
122 if (sxp != NULL)
123 kmem_free(sxp, sizeof(xfs_swapext_t));
124
125 return error;
126}
127
128int
129xfs_swap_extents(
130 xfs_inode_t *ip,
131 xfs_inode_t *tip,
132 xfs_swapext_t *sxp)
133{
134 xfs_mount_t *mp;
135 xfs_inode_t *ips[2];
136 xfs_trans_t *tp;
137 xfs_bstat_t *sbp = &sxp->sx_stat;
138 bhv_vnode_t *vp, *tvp;
139 xfs_ifork_t *tempifp, *ifp, *tifp;
140 int ilf_fields, tilf_fields;
141 static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL;
142 int error = 0;
143 int aforkblks = 0;
144 int taforkblks = 0;
145 __uint64_t tmp;
146 char locked = 0;
147
148 mp = ip->i_mount;
149
150 tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL);
151 if (!tempifp) {
152 error = XFS_ERROR(ENOMEM);
153 goto error0;
154 }
155
156 sbp = &sxp->sx_stat;
157 vp = XFS_ITOV(ip);
158 tvp = XFS_ITOV(tip);
129 159
130 /* Lock in i_ino order */ 160 /* Lock in i_ino order */
131 if (ip->i_ino < tip->i_ino) { 161 if (ip->i_ino < tip->i_ino) {
@@ -137,6 +167,7 @@ xfs_swapext(
137 } 167 }
138 168
139 xfs_lock_inodes(ips, 2, 0, lock_flags); 169 xfs_lock_inodes(ips, 2, 0, lock_flags);
170 locked = 1;
140 171
141 /* Check permissions */ 172 /* Check permissions */
142 error = xfs_iaccess(ip, S_IWUSR, NULL); 173 error = xfs_iaccess(ip, S_IWUSR, NULL);
@@ -169,7 +200,7 @@ xfs_swapext(
169 200
170 if (VN_CACHED(tvp) != 0) { 201 if (VN_CACHED(tvp) != 0) {
171 xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1); 202 xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1);
172 VOP_FLUSHINVAL_PAGES(tvp, 0, -1, FI_REMAPF_LOCKED); 203 bhv_vop_flushinval_pages(tvp, 0, -1, FI_REMAPF_LOCKED);
173 } 204 }
174 205
175 /* Verify O_DIRECT for ftmp */ 206 /* Verify O_DIRECT for ftmp */
@@ -214,7 +245,7 @@ xfs_swapext(
214 /* We need to fail if the file is memory mapped. Once we have tossed 245 /* We need to fail if the file is memory mapped. Once we have tossed
215 * all existing pages, the page fault will have no option 246 * all existing pages, the page fault will have no option
216 * but to go to the filesystem for pages. By making the page fault call 247 * but to go to the filesystem for pages. By making the page fault call
217 * VOP_READ (or write in the case of autogrow) they block on the iolock 248 * vop_read (or write in the case of autogrow) they block on the iolock
218 * until we have switched the extents. 249 * until we have switched the extents.
219 */ 250 */
220 if (VN_MAPPED(vp)) { 251 if (VN_MAPPED(vp)) {
@@ -233,7 +264,7 @@ xfs_swapext(
233 * fields change. 264 * fields change.
234 */ 265 */
235 266
236 VOP_TOSS_PAGES(vp, 0, -1, FI_REMAPF); 267 bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
237 268
238 tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT); 269 tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT);
239 if ((error = xfs_trans_reserve(tp, 0, 270 if ((error = xfs_trans_reserve(tp, 0,
@@ -360,16 +391,7 @@ xfs_swapext(
360 xfs_iunlock(ip, lock_flags); 391 xfs_iunlock(ip, lock_flags);
361 xfs_iunlock(tip, lock_flags); 392 xfs_iunlock(tip, lock_flags);
362 } 393 }
363
364 if (fp != NULL)
365 fput(fp);
366 if (tfp != NULL)
367 fput(tfp);
368
369 if (sxp != NULL)
370 kmem_free(sxp, sizeof(xfs_swapext_t));
371 if (tempifp != NULL) 394 if (tempifp != NULL)
372 kmem_free(tempifp, sizeof(xfs_ifork_t)); 395 kmem_free(tempifp, sizeof(xfs_ifork_t));
373
374 return error; 396 return error;
375} 397}
diff --git a/fs/xfs/xfs_dfrag.h b/fs/xfs/xfs_dfrag.h
index f678559abc45..da178205be68 100644
--- a/fs/xfs/xfs_dfrag.h
+++ b/fs/xfs/xfs_dfrag.h
@@ -48,6 +48,9 @@ typedef struct xfs_swapext
48 */ 48 */
49int xfs_swapext(struct xfs_swapext __user *sx); 49int xfs_swapext(struct xfs_swapext __user *sx);
50 50
51int xfs_swap_extents(struct xfs_inode *ip, struct xfs_inode *tip,
52 struct xfs_swapext *sxp);
53
51#endif /* __KERNEL__ */ 54#endif /* __KERNEL__ */
52 55
53#endif /* __XFS_DFRAG_H__ */ 56#endif /* __XFS_DFRAG_H__ */
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index 79d0d9e1fbab..b33826961c45 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -85,7 +85,6 @@ typedef struct xfs_dinode
85 union { 85 union {
86 xfs_bmdr_block_t di_bmbt; /* btree root block */ 86 xfs_bmdr_block_t di_bmbt; /* btree root block */
87 xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */ 87 xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */
88 xfs_dir_shortform_t di_dirsf; /* shortform directory */
89 xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */ 88 xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */
90 char di_c[1]; /* local contents */ 89 char di_c[1]; /* local contents */
91 xfs_dev_t di_dev; /* device for S_IFCHR/S_IFBLK */ 90 xfs_dev_t di_dev; /* device for S_IFCHR/S_IFBLK */
@@ -257,6 +256,7 @@ typedef enum xfs_dinode_fmt
257#define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */ 256#define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */
258#define XFS_DIFLAG_EXTSIZE_BIT 11 /* inode extent size allocator hint */ 257#define XFS_DIFLAG_EXTSIZE_BIT 11 /* inode extent size allocator hint */
259#define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */ 258#define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */
259#define XFS_DIFLAG_NODEFRAG_BIT 13 /* do not reorganize/defragment */
260#define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT) 260#define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT)
261#define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT) 261#define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT)
262#define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT) 262#define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT)
@@ -270,12 +270,13 @@ typedef enum xfs_dinode_fmt
270#define XFS_DIFLAG_NOSYMLINKS (1 << XFS_DIFLAG_NOSYMLINKS_BIT) 270#define XFS_DIFLAG_NOSYMLINKS (1 << XFS_DIFLAG_NOSYMLINKS_BIT)
271#define XFS_DIFLAG_EXTSIZE (1 << XFS_DIFLAG_EXTSIZE_BIT) 271#define XFS_DIFLAG_EXTSIZE (1 << XFS_DIFLAG_EXTSIZE_BIT)
272#define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT) 272#define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT)
273#define XFS_DIFLAG_NODEFRAG (1 << XFS_DIFLAG_NODEFRAG_BIT)
273 274
274#define XFS_DIFLAG_ANY \ 275#define XFS_DIFLAG_ANY \
275 (XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \ 276 (XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \
276 XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \ 277 XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \
277 XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \ 278 XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \
278 XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \ 279 XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \
279 XFS_DIFLAG_EXTSZINHERIT) 280 XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG)
280 281
281#endif /* __XFS_DINODE_H__ */ 282#endif /* __XFS_DINODE_H__ */
diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c
deleted file mode 100644
index 9cc702a839a3..000000000000
--- a/fs/xfs/xfs_dir.c
+++ /dev/null
@@ -1,1217 +0,0 @@
1/*
2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_types.h"
21#include "xfs_log.h"
22#include "xfs_inum.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h"
27#include "xfs_dmapi.h"
28#include "xfs_mount.h"
29#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_alloc_btree.h"
32#include "xfs_ialloc_btree.h"
33#include "xfs_alloc.h"
34#include "xfs_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h"
38#include "xfs_dinode.h"
39#include "xfs_inode.h"
40#include "xfs_bmap.h"
41#include "xfs_dir_leaf.h"
42#include "xfs_error.h"
43
44/*
45 * xfs_dir.c
46 *
47 * Provide the external interfaces to manage directories.
48 */
49
50/*========================================================================
51 * Function prototypes for the kernel.
52 *========================================================================*/
53
54/*
55 * Functions for the dirops interfaces.
56 */
57static void xfs_dir_mount(struct xfs_mount *mp);
58
59static int xfs_dir_isempty(struct xfs_inode *dp);
60
61static int xfs_dir_init(struct xfs_trans *trans,
62 struct xfs_inode *dir,
63 struct xfs_inode *parent_dir);
64
65static int xfs_dir_createname(struct xfs_trans *trans,
66 struct xfs_inode *dp,
67 char *name_string,
68 int name_len,
69 xfs_ino_t inode_number,
70 xfs_fsblock_t *firstblock,
71 xfs_bmap_free_t *flist,
72 xfs_extlen_t total);
73
74static int xfs_dir_lookup(struct xfs_trans *tp,
75 struct xfs_inode *dp,
76 char *name_string,
77 int name_length,
78 xfs_ino_t *inode_number);
79
80static int xfs_dir_removename(struct xfs_trans *trans,
81 struct xfs_inode *dp,
82 char *name_string,
83 int name_length,
84 xfs_ino_t ino,
85 xfs_fsblock_t *firstblock,
86 xfs_bmap_free_t *flist,
87 xfs_extlen_t total);
88
89static int xfs_dir_getdents(struct xfs_trans *tp,
90 struct xfs_inode *dp,
91 struct uio *uiop,
92 int *eofp);
93
94static int xfs_dir_replace(struct xfs_trans *tp,
95 struct xfs_inode *dp,
96 char *name_string,
97 int name_length,
98 xfs_ino_t inode_number,
99 xfs_fsblock_t *firstblock,
100 xfs_bmap_free_t *flist,
101 xfs_extlen_t total);
102
103static int xfs_dir_canenter(struct xfs_trans *tp,
104 struct xfs_inode *dp,
105 char *name_string,
106 int name_length);
107
108static int xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp,
109 xfs_dinode_t *dip);
110
111xfs_dirops_t xfsv1_dirops = {
112 .xd_mount = xfs_dir_mount,
113 .xd_isempty = xfs_dir_isempty,
114 .xd_init = xfs_dir_init,
115 .xd_createname = xfs_dir_createname,
116 .xd_lookup = xfs_dir_lookup,
117 .xd_removename = xfs_dir_removename,
118 .xd_getdents = xfs_dir_getdents,
119 .xd_replace = xfs_dir_replace,
120 .xd_canenter = xfs_dir_canenter,
121 .xd_shortform_validate_ondisk = xfs_dir_shortform_validate_ondisk,
122 .xd_shortform_to_single = xfs_dir_shortform_to_leaf,
123};
124
125/*
126 * Internal routines when dirsize == XFS_LBSIZE(mp).
127 */
128STATIC int xfs_dir_leaf_lookup(xfs_da_args_t *args);
129STATIC int xfs_dir_leaf_removename(xfs_da_args_t *args, int *number_entries,
130 int *total_namebytes);
131STATIC int xfs_dir_leaf_getdents(xfs_trans_t *trans, xfs_inode_t *dp,
132 uio_t *uio, int *eofp,
133 xfs_dirent_t *dbp,
134 xfs_dir_put_t put);
135STATIC int xfs_dir_leaf_replace(xfs_da_args_t *args);
136
137/*
138 * Internal routines when dirsize > XFS_LBSIZE(mp).
139 */
140STATIC int xfs_dir_node_addname(xfs_da_args_t *args);
141STATIC int xfs_dir_node_lookup(xfs_da_args_t *args);
142STATIC int xfs_dir_node_removename(xfs_da_args_t *args);
143STATIC int xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp,
144 uio_t *uio, int *eofp,
145 xfs_dirent_t *dbp,
146 xfs_dir_put_t put);
147STATIC int xfs_dir_node_replace(xfs_da_args_t *args);
148
149#if defined(XFS_DIR_TRACE)
150ktrace_t *xfs_dir_trace_buf;
151#endif
152
153
154/*========================================================================
155 * Overall external interface routines.
156 *========================================================================*/
157
158xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot;
159
160/*
161 * One-time startup routine called from xfs_init().
162 */
163void
164xfs_dir_startup(void)
165{
166 xfs_dir_hash_dot = xfs_da_hashname(".", 1);
167 xfs_dir_hash_dotdot = xfs_da_hashname("..", 2);
168}
169
170/*
171 * Initialize directory-related fields in the mount structure.
172 */
173static void
174xfs_dir_mount(xfs_mount_t *mp)
175{
176 uint shortcount, leafcount, count;
177
178 mp->m_dirversion = 1;
179 if (!(mp->m_flags & XFS_MOUNT_ATTR2)) {
180 shortcount = (mp->m_attroffset -
181 (uint)sizeof(xfs_dir_sf_hdr_t)) /
182 (uint)sizeof(xfs_dir_sf_entry_t);
183 leafcount = (XFS_LBSIZE(mp) -
184 (uint)sizeof(xfs_dir_leaf_hdr_t)) /
185 ((uint)sizeof(xfs_dir_leaf_entry_t) +
186 (uint)sizeof(xfs_dir_leaf_name_t));
187 } else {
188 shortcount = (XFS_BMDR_SPACE_CALC(MINABTPTRS) -
189 (uint)sizeof(xfs_dir_sf_hdr_t)) /
190 (uint)sizeof(xfs_dir_sf_entry_t);
191 leafcount = (XFS_LBSIZE(mp) -
192 (uint)sizeof(xfs_dir_leaf_hdr_t)) /
193 ((uint)sizeof(xfs_dir_leaf_entry_t) +
194 (uint)sizeof(xfs_dir_leaf_name_t));
195 }
196 count = shortcount > leafcount ? shortcount : leafcount;
197 mp->m_dircook_elog = xfs_da_log2_roundup(count + 1);
198 ASSERT(mp->m_dircook_elog <= mp->m_sb.sb_blocklog);
199 mp->m_dir_node_ents = mp->m_attr_node_ents =
200 (XFS_LBSIZE(mp) - (uint)sizeof(xfs_da_node_hdr_t)) /
201 (uint)sizeof(xfs_da_node_entry_t);
202 mp->m_dir_magicpct = (XFS_LBSIZE(mp) * 37) / 100;
203 mp->m_dirblksize = mp->m_sb.sb_blocksize;
204 mp->m_dirblkfsbs = 1;
205}
206
207/*
208 * Return 1 if directory contains only "." and "..".
209 */
210static int
211xfs_dir_isempty(xfs_inode_t *dp)
212{
213 xfs_dir_sf_hdr_t *hdr;
214
215 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
216 if (dp->i_d.di_size == 0)
217 return(1);
218 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
219 return(0);
220 hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data;
221 return(hdr->count == 0);
222}
223
224/*
225 * Initialize a directory with its "." and ".." entries.
226 */
227static int
228xfs_dir_init(xfs_trans_t *trans, xfs_inode_t *dir, xfs_inode_t *parent_dir)
229{
230 xfs_da_args_t args;
231 int error;
232
233 memset((char *)&args, 0, sizeof(args));
234 args.dp = dir;
235 args.trans = trans;
236
237 ASSERT((dir->i_d.di_mode & S_IFMT) == S_IFDIR);
238 if ((error = xfs_dir_ino_validate(trans->t_mountp, parent_dir->i_ino)))
239 return error;
240
241 return(xfs_dir_shortform_create(&args, parent_dir->i_ino));
242}
243
244/*
245 * Generic handler routine to add a name to a directory.
246 * Transitions directory from shortform to Btree as necessary.
247 */
248static int /* error */
249xfs_dir_createname(xfs_trans_t *trans, xfs_inode_t *dp, char *name,
250 int namelen, xfs_ino_t inum, xfs_fsblock_t *firstblock,
251 xfs_bmap_free_t *flist, xfs_extlen_t total)
252{
253 xfs_da_args_t args;
254 int retval, newsize, done;
255
256 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
257
258 if ((retval = xfs_dir_ino_validate(trans->t_mountp, inum)))
259 return (retval);
260
261 XFS_STATS_INC(xs_dir_create);
262 /*
263 * Fill in the arg structure for this request.
264 */
265 args.name = name;
266 args.namelen = namelen;
267 args.hashval = xfs_da_hashname(name, namelen);
268 args.inumber = inum;
269 args.dp = dp;
270 args.firstblock = firstblock;
271 args.flist = flist;
272 args.total = total;
273 args.whichfork = XFS_DATA_FORK;
274 args.trans = trans;
275 args.justcheck = 0;
276 args.addname = args.oknoent = 1;
277
278 /*
279 * Decide on what work routines to call based on the inode size.
280 */
281 done = 0;
282 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
283 newsize = XFS_DIR_SF_ENTSIZE_BYNAME(args.namelen);
284 if ((dp->i_d.di_size + newsize) <= XFS_IFORK_DSIZE(dp)) {
285 retval = xfs_dir_shortform_addname(&args);
286 done = 1;
287 } else {
288 if (total == 0)
289 return XFS_ERROR(ENOSPC);
290 retval = xfs_dir_shortform_to_leaf(&args);
291 done = retval != 0;
292 }
293 }
294 if (!done && xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
295 retval = xfs_dir_leaf_addname(&args);
296 done = retval != ENOSPC;
297 if (!done) {
298 if (total == 0)
299 return XFS_ERROR(ENOSPC);
300 retval = xfs_dir_leaf_to_node(&args);
301 done = retval != 0;
302 }
303 }
304 if (!done) {
305 retval = xfs_dir_node_addname(&args);
306 }
307 return(retval);
308}
309
310/*
311 * Generic handler routine to check if a name can be added to a directory,
312 * without adding any blocks to the directory.
313 */
314static int /* error */
315xfs_dir_canenter(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen)
316{
317 xfs_da_args_t args;
318 int retval, newsize;
319
320 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
321 /*
322 * Fill in the arg structure for this request.
323 */
324 args.name = name;
325 args.namelen = namelen;
326 args.hashval = xfs_da_hashname(name, namelen);
327 args.inumber = 0;
328 args.dp = dp;
329 args.firstblock = NULL;
330 args.flist = NULL;
331 args.total = 0;
332 args.whichfork = XFS_DATA_FORK;
333 args.trans = trans;
334 args.justcheck = args.addname = args.oknoent = 1;
335
336 /*
337 * Decide on what work routines to call based on the inode size.
338 */
339 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
340 newsize = XFS_DIR_SF_ENTSIZE_BYNAME(args.namelen);
341 if ((dp->i_d.di_size + newsize) <= XFS_IFORK_DSIZE(dp))
342 retval = 0;
343 else
344 retval = XFS_ERROR(ENOSPC);
345 } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
346 retval = xfs_dir_leaf_addname(&args);
347 } else {
348 retval = xfs_dir_node_addname(&args);
349 }
350 return(retval);
351}
352
353/*
354 * Generic handler routine to remove a name from a directory.
355 * Transitions directory from Btree to shortform as necessary.
356 */
357static int /* error */
358xfs_dir_removename(xfs_trans_t *trans, xfs_inode_t *dp, char *name,
359 int namelen, xfs_ino_t ino, xfs_fsblock_t *firstblock,
360 xfs_bmap_free_t *flist, xfs_extlen_t total)
361{
362 xfs_da_args_t args;
363 int count, totallen, newsize, retval;
364
365 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
366 XFS_STATS_INC(xs_dir_remove);
367 /*
368 * Fill in the arg structure for this request.
369 */
370 args.name = name;
371 args.namelen = namelen;
372 args.hashval = xfs_da_hashname(name, namelen);
373 args.inumber = ino;
374 args.dp = dp;
375 args.firstblock = firstblock;
376 args.flist = flist;
377 args.total = total;
378 args.whichfork = XFS_DATA_FORK;
379 args.trans = trans;
380 args.justcheck = args.addname = args.oknoent = 0;
381
382 /*
383 * Decide on what work routines to call based on the inode size.
384 */
385 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
386 retval = xfs_dir_shortform_removename(&args);
387 } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
388 retval = xfs_dir_leaf_removename(&args, &count, &totallen);
389 if (retval == 0) {
390 newsize = XFS_DIR_SF_ALLFIT(count, totallen);
391 if (newsize <= XFS_IFORK_DSIZE(dp)) {
392 retval = xfs_dir_leaf_to_shortform(&args);
393 }
394 }
395 } else {
396 retval = xfs_dir_node_removename(&args);
397 }
398 return(retval);
399}
400
401static int /* error */
402xfs_dir_lookup(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen,
403 xfs_ino_t *inum)
404{
405 xfs_da_args_t args;
406 int retval;
407
408 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
409
410 XFS_STATS_INC(xs_dir_lookup);
411 /*
412 * Fill in the arg structure for this request.
413 */
414 args.name = name;
415 args.namelen = namelen;
416 args.hashval = xfs_da_hashname(name, namelen);
417 args.inumber = 0;
418 args.dp = dp;
419 args.firstblock = NULL;
420 args.flist = NULL;
421 args.total = 0;
422 args.whichfork = XFS_DATA_FORK;
423 args.trans = trans;
424 args.justcheck = args.addname = 0;
425 args.oknoent = 1;
426
427 /*
428 * Decide on what work routines to call based on the inode size.
429 */
430 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
431 retval = xfs_dir_shortform_lookup(&args);
432 } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
433 retval = xfs_dir_leaf_lookup(&args);
434 } else {
435 retval = xfs_dir_node_lookup(&args);
436 }
437 if (retval == EEXIST)
438 retval = 0;
439 *inum = args.inumber;
440 return(retval);
441}
442
443/*
444 * Implement readdir.
445 */
446static int /* error */
447xfs_dir_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, int *eofp)
448{
449 xfs_dirent_t *dbp;
450 int alignment, retval;
451 xfs_dir_put_t put;
452
453 XFS_STATS_INC(xs_dir_getdents);
454 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
455
456 /*
457 * If our caller has given us a single contiguous memory buffer,
458 * just work directly within that buffer. If it's in user memory,
459 * lock it down first.
460 */
461 alignment = sizeof(xfs_off_t) - 1;
462 if ((uio->uio_iovcnt == 1) &&
463 (((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) &&
464 ((uio->uio_iov[0].iov_len & alignment) == 0)) {
465 dbp = NULL;
466 put = xfs_dir_put_dirent64_direct;
467 } else {
468 dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP);
469 put = xfs_dir_put_dirent64_uio;
470 }
471
472 /*
473 * Decide on what work routines to call based on the inode size.
474 */
475 *eofp = 0;
476
477 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
478 retval = xfs_dir_shortform_getdents(dp, uio, eofp, dbp, put);
479 } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
480 retval = xfs_dir_leaf_getdents(trans, dp, uio, eofp, dbp, put);
481 } else {
482 retval = xfs_dir_node_getdents(trans, dp, uio, eofp, dbp, put);
483 }
484 if (dbp != NULL)
485 kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN);
486
487 return(retval);
488}
489
490static int /* error */
491xfs_dir_replace(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen,
492 xfs_ino_t inum, xfs_fsblock_t *firstblock,
493 xfs_bmap_free_t *flist, xfs_extlen_t total)
494{
495 xfs_da_args_t args;
496 int retval;
497
498 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
499
500 if ((retval = xfs_dir_ino_validate(trans->t_mountp, inum)))
501 return retval;
502
503 /*
504 * Fill in the arg structure for this request.
505 */
506 args.name = name;
507 args.namelen = namelen;
508 args.hashval = xfs_da_hashname(name, namelen);
509 args.inumber = inum;
510 args.dp = dp;
511 args.firstblock = firstblock;
512 args.flist = flist;
513 args.total = total;
514 args.whichfork = XFS_DATA_FORK;
515 args.trans = trans;
516 args.justcheck = args.addname = args.oknoent = 0;
517
518 /*
519 * Decide on what work routines to call based on the inode size.
520 */
521 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
522 retval = xfs_dir_shortform_replace(&args);
523 } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
524 retval = xfs_dir_leaf_replace(&args);
525 } else {
526 retval = xfs_dir_node_replace(&args);
527 }
528
529 return(retval);
530}
531
532static int
533xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp, xfs_dinode_t *dp)
534{
535 xfs_ino_t ino;
536 int namelen_sum;
537 int count;
538 xfs_dir_shortform_t *sf;
539 xfs_dir_sf_entry_t *sfe;
540 int i;
541
542
543
544 if ((INT_GET(dp->di_core.di_mode, ARCH_CONVERT) & S_IFMT) != S_IFDIR) {
545 return 0;
546 }
547 if (INT_GET(dp->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_LOCAL) {
548 return 0;
549 }
550 if (INT_GET(dp->di_core.di_size, ARCH_CONVERT) < sizeof(sf->hdr)) {
551 xfs_fs_cmn_err(CE_WARN, mp, "Invalid shortform size: dp 0x%p",
552 dp);
553 return 1;
554 }
555 sf = (xfs_dir_shortform_t *)(&dp->di_u.di_dirsf);
556 ino = XFS_GET_DIR_INO8(sf->hdr.parent);
557 if (xfs_dir_ino_validate(mp, ino))
558 return 1;
559
560 count = sf->hdr.count;
561 if ((count < 0) || ((count * 10) > XFS_LITINO(mp))) {
562 xfs_fs_cmn_err(CE_WARN, mp,
563 "Invalid shortform count: dp 0x%p", dp);
564 return(1);
565 }
566
567 if (count == 0) {
568 return 0;
569 }
570
571 namelen_sum = 0;
572 sfe = &sf->list[0];
573 for (i = sf->hdr.count - 1; i >= 0; i--) {
574 ino = XFS_GET_DIR_INO8(sfe->inumber);
575 xfs_dir_ino_validate(mp, ino);
576 if (sfe->namelen >= XFS_LITINO(mp)) {
577 xfs_fs_cmn_err(CE_WARN, mp,
578 "Invalid shortform namelen: dp 0x%p", dp);
579 return 1;
580 }
581 namelen_sum += sfe->namelen;
582 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
583 }
584 if (namelen_sum >= XFS_LITINO(mp)) {
585 xfs_fs_cmn_err(CE_WARN, mp,
586 "Invalid shortform namelen: dp 0x%p", dp);
587 return 1;
588 }
589
590 return 0;
591}
592
593/*========================================================================
594 * External routines when dirsize == XFS_LBSIZE(dp->i_mount).
595 *========================================================================*/
596
597/*
598 * Add a name to the leaf directory structure
599 * This is the external routine.
600 */
601int
602xfs_dir_leaf_addname(xfs_da_args_t *args)
603{
604 int index, retval;
605 xfs_dabuf_t *bp;
606
607 retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
608 XFS_DATA_FORK);
609 if (retval)
610 return(retval);
611 ASSERT(bp != NULL);
612
613 retval = xfs_dir_leaf_lookup_int(bp, args, &index);
614 if (retval == ENOENT)
615 retval = xfs_dir_leaf_add(bp, args, index);
616 xfs_da_buf_done(bp);
617 return(retval);
618}
619
620/*
621 * Remove a name from the leaf directory structure
622 * This is the external routine.
623 */
624STATIC int
625xfs_dir_leaf_removename(xfs_da_args_t *args, int *count, int *totallen)
626{
627 xfs_dir_leafblock_t *leaf;
628 int index, retval;
629 xfs_dabuf_t *bp;
630
631 retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
632 XFS_DATA_FORK);
633 if (retval)
634 return(retval);
635 ASSERT(bp != NULL);
636 leaf = bp->data;
637 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
638 retval = xfs_dir_leaf_lookup_int(bp, args, &index);
639 if (retval == EEXIST) {
640 (void)xfs_dir_leaf_remove(args->trans, bp, index);
641 *count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
642 *totallen = INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
643 retval = 0;
644 }
645 xfs_da_buf_done(bp);
646 return(retval);
647}
648
649/*
650 * Look up a name in a leaf directory structure.
651 * This is the external routine.
652 */
653STATIC int
654xfs_dir_leaf_lookup(xfs_da_args_t *args)
655{
656 int index, retval;
657 xfs_dabuf_t *bp;
658
659 retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
660 XFS_DATA_FORK);
661 if (retval)
662 return(retval);
663 ASSERT(bp != NULL);
664 retval = xfs_dir_leaf_lookup_int(bp, args, &index);
665 xfs_da_brelse(args->trans, bp);
666 return(retval);
667}
668
669/*
670 * Copy out directory entries for getdents(), for leaf directories.
671 */
672STATIC int
673xfs_dir_leaf_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio,
674 int *eofp, xfs_dirent_t *dbp, xfs_dir_put_t put)
675{
676 xfs_dabuf_t *bp;
677 int retval, eob;
678
679 retval = xfs_da_read_buf(dp->i_transp, dp, 0, -1, &bp, XFS_DATA_FORK);
680 if (retval)
681 return(retval);
682 ASSERT(bp != NULL);
683 retval = xfs_dir_leaf_getdents_int(bp, dp, 0, uio, &eob, dbp, put, -1);
684 xfs_da_brelse(trans, bp);
685 *eofp = (eob == 0);
686 return(retval);
687}
688
689/*
690 * Look up a name in a leaf directory structure, replace the inode number.
691 * This is the external routine.
692 */
693STATIC int
694xfs_dir_leaf_replace(xfs_da_args_t *args)
695{
696 int index, retval;
697 xfs_dabuf_t *bp;
698 xfs_ino_t inum;
699 xfs_dir_leafblock_t *leaf;
700 xfs_dir_leaf_entry_t *entry;
701 xfs_dir_leaf_name_t *namest;
702
703 inum = args->inumber;
704 retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
705 XFS_DATA_FORK);
706 if (retval)
707 return(retval);
708 ASSERT(bp != NULL);
709 retval = xfs_dir_leaf_lookup_int(bp, args, &index);
710 if (retval == EEXIST) {
711 leaf = bp->data;
712 entry = &leaf->entries[index];
713 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
714 /* XXX - replace assert? */
715 XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber);
716 xfs_da_log_buf(args->trans, bp,
717 XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber)));
718 xfs_da_buf_done(bp);
719 retval = 0;
720 } else
721 xfs_da_brelse(args->trans, bp);
722 return(retval);
723}
724
725
726/*========================================================================
727 * External routines when dirsize > XFS_LBSIZE(mp).
728 *========================================================================*/
729
730/*
731 * Add a name to a Btree-format directory.
732 *
733 * This will involve walking down the Btree, and may involve splitting
734 * leaf nodes and even splitting intermediate nodes up to and including
735 * the root node (a special case of an intermediate node).
736 */
737STATIC int
738xfs_dir_node_addname(xfs_da_args_t *args)
739{
740 xfs_da_state_t *state;
741 xfs_da_state_blk_t *blk;
742 int retval, error;
743
744 /*
745 * Fill in bucket of arguments/results/context to carry around.
746 */
747 state = xfs_da_state_alloc();
748 state->args = args;
749 state->mp = args->dp->i_mount;
750 state->blocksize = state->mp->m_sb.sb_blocksize;
751 state->node_ents = state->mp->m_dir_node_ents;
752
753 /*
754 * Search to see if name already exists, and get back a pointer
755 * to where it should go.
756 */
757 error = xfs_da_node_lookup_int(state, &retval);
758 if (error)
759 retval = error;
760 if (retval != ENOENT)
761 goto error;
762 blk = &state->path.blk[ state->path.active-1 ];
763 ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC);
764 retval = xfs_dir_leaf_add(blk->bp, args, blk->index);
765 if (retval == 0) {
766 /*
767 * Addition succeeded, update Btree hashvals.
768 */
769 if (!args->justcheck)
770 xfs_da_fixhashpath(state, &state->path);
771 } else {
772 /*
773 * Addition failed, split as many Btree elements as required.
774 */
775 if (args->total == 0) {
776 ASSERT(retval == ENOSPC);
777 goto error;
778 }
779 retval = xfs_da_split(state);
780 }
781error:
782 xfs_da_state_free(state);
783
784 return(retval);
785}
786
787/*
788 * Remove a name from a B-tree directory.
789 *
790 * This will involve walking down the Btree, and may involve joining
791 * leaf nodes and even joining intermediate nodes up to and including
792 * the root node (a special case of an intermediate node).
793 */
794STATIC int
795xfs_dir_node_removename(xfs_da_args_t *args)
796{
797 xfs_da_state_t *state;
798 xfs_da_state_blk_t *blk;
799 int retval, error;
800
801 state = xfs_da_state_alloc();
802 state->args = args;
803 state->mp = args->dp->i_mount;
804 state->blocksize = state->mp->m_sb.sb_blocksize;
805 state->node_ents = state->mp->m_dir_node_ents;
806
807 /*
808 * Search to see if name exists, and get back a pointer to it.
809 */
810 error = xfs_da_node_lookup_int(state, &retval);
811 if (error)
812 retval = error;
813 if (retval != EEXIST) {
814 xfs_da_state_free(state);
815 return(retval);
816 }
817
818 /*
819 * Remove the name and update the hashvals in the tree.
820 */
821 blk = &state->path.blk[ state->path.active-1 ];
822 ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC);
823 retval = xfs_dir_leaf_remove(args->trans, blk->bp, blk->index);
824 xfs_da_fixhashpath(state, &state->path);
825
826 /*
827 * Check to see if the tree needs to be collapsed.
828 */
829 error = 0;
830 if (retval) {
831 error = xfs_da_join(state);
832 }
833
834 xfs_da_state_free(state);
835 if (error)
836 return(error);
837 return(0);
838}
839
840/*
841 * Look up a filename in a int directory.
842 * Use an internal routine to actually do all the work.
843 */
844STATIC int
845xfs_dir_node_lookup(xfs_da_args_t *args)
846{
847 xfs_da_state_t *state;
848 int retval, error, i;
849
850 state = xfs_da_state_alloc();
851 state->args = args;
852 state->mp = args->dp->i_mount;
853 state->blocksize = state->mp->m_sb.sb_blocksize;
854 state->node_ents = state->mp->m_dir_node_ents;
855
856 /*
857 * Search to see if name exists,
858 * and get back a pointer to it.
859 */
860 error = xfs_da_node_lookup_int(state, &retval);
861 if (error) {
862 retval = error;
863 }
864
865 /*
866 * If not in a transaction, we have to release all the buffers.
867 */
868 for (i = 0; i < state->path.active; i++) {
869 xfs_da_brelse(args->trans, state->path.blk[i].bp);
870 state->path.blk[i].bp = NULL;
871 }
872
873 xfs_da_state_free(state);
874 return(retval);
875}
876
877STATIC int
878xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio,
879 int *eofp, xfs_dirent_t *dbp, xfs_dir_put_t put)
880{
881 xfs_da_intnode_t *node;
882 xfs_da_node_entry_t *btree;
883 xfs_dir_leafblock_t *leaf = NULL;
884 xfs_dablk_t bno, nextbno;
885 xfs_dahash_t cookhash;
886 xfs_mount_t *mp;
887 int error, eob, i;
888 xfs_dabuf_t *bp;
889 xfs_daddr_t nextda;
890
891 /*
892 * Pick up our context.
893 */
894 mp = dp->i_mount;
895 bp = NULL;
896 bno = XFS_DA_COOKIE_BNO(mp, uio->uio_offset);
897 cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset);
898
899 xfs_dir_trace_g_du("node: start", dp, uio);
900
901 /*
902 * Re-find our place, even if we're confused about what our place is.
903 *
904 * First we check the block number from the magic cookie, it is a
905 * cache of where we ended last time. If we find a leaf block, and
906 * the starting hashval in that block is less than our desired
907 * hashval, then we run with it.
908 */
909 if (bno > 0) {
910 error = xfs_da_read_buf(trans, dp, bno, -2, &bp, XFS_DATA_FORK);
911 if ((error != 0) && (error != EFSCORRUPTED))
912 return(error);
913 if (bp)
914 leaf = bp->data;
915 if (bp && be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) {
916 xfs_dir_trace_g_dub("node: block not a leaf",
917 dp, uio, bno);
918 xfs_da_brelse(trans, bp);
919 bp = NULL;
920 }
921 if (bp && INT_GET(leaf->entries[0].hashval, ARCH_CONVERT) > cookhash) {
922 xfs_dir_trace_g_dub("node: leaf hash too large",
923 dp, uio, bno);
924 xfs_da_brelse(trans, bp);
925 bp = NULL;
926 }
927 if (bp &&
928 cookhash > INT_GET(leaf->entries[INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT)) {
929 xfs_dir_trace_g_dub("node: leaf hash too small",
930 dp, uio, bno);
931 xfs_da_brelse(trans, bp);
932 bp = NULL;
933 }
934 }
935
936 /*
937 * If we did not find a leaf block from the blockno in the cookie,
938 * or we there was no blockno in the cookie (eg: first time thru),
939 * the we start at the top of the Btree and re-find our hashval.
940 */
941 if (bp == NULL) {
942 xfs_dir_trace_g_du("node: start at root" , dp, uio);
943 bno = 0;
944 for (;;) {
945 error = xfs_da_read_buf(trans, dp, bno, -1, &bp,
946 XFS_DATA_FORK);
947 if (error)
948 return(error);
949 if (bp == NULL)
950 return(XFS_ERROR(EFSCORRUPTED));
951 node = bp->data;
952 if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC)
953 break;
954 btree = &node->btree[0];
955 xfs_dir_trace_g_dun("node: node detail", dp, uio, node);
956 for (i = 0; i < be16_to_cpu(node->hdr.count); btree++, i++) {
957 if (be32_to_cpu(btree->hashval) >= cookhash) {
958 bno = be32_to_cpu(btree->before);
959 break;
960 }
961 }
962 if (i == be16_to_cpu(node->hdr.count)) {
963 xfs_da_brelse(trans, bp);
964 xfs_dir_trace_g_du("node: hash beyond EOF",
965 dp, uio);
966 uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0,
967 XFS_DA_MAXHASH);
968 *eofp = 1;
969 return(0);
970 }
971 xfs_dir_trace_g_dub("node: going to block",
972 dp, uio, bno);
973 xfs_da_brelse(trans, bp);
974 }
975 }
976 ASSERT(cookhash != XFS_DA_MAXHASH);
977
978 /*
979 * We've dropped down to the (first) leaf block that contains the
980 * hashval we are interested in. Continue rolling upward thru the
981 * leaf blocks until we fill up our buffer.
982 */
983 for (;;) {
984 leaf = bp->data;
985 if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC)) {
986 xfs_dir_trace_g_dul("node: not a leaf", dp, uio, leaf);
987 xfs_da_brelse(trans, bp);
988 XFS_CORRUPTION_ERROR("xfs_dir_node_getdents(1)",
989 XFS_ERRLEVEL_LOW, mp, leaf);
990 return XFS_ERROR(EFSCORRUPTED);
991 }
992 xfs_dir_trace_g_dul("node: leaf detail", dp, uio, leaf);
993 if ((nextbno = be32_to_cpu(leaf->hdr.info.forw))) {
994 nextda = xfs_da_reada_buf(trans, dp, nextbno,
995 XFS_DATA_FORK);
996 } else
997 nextda = -1;
998 error = xfs_dir_leaf_getdents_int(bp, dp, bno, uio, &eob, dbp,
999 put, nextda);
1000 xfs_da_brelse(trans, bp);
1001 bno = nextbno;
1002 if (eob) {
1003 xfs_dir_trace_g_dub("node: E-O-B", dp, uio, bno);
1004 *eofp = 0;
1005 return(error);
1006 }
1007 if (bno == 0)
1008 break;
1009 error = xfs_da_read_buf(trans, dp, bno, nextda, &bp,
1010 XFS_DATA_FORK);
1011 if (error)
1012 return(error);
1013 if (unlikely(bp == NULL)) {
1014 XFS_ERROR_REPORT("xfs_dir_node_getdents(2)",
1015 XFS_ERRLEVEL_LOW, mp);
1016 return(XFS_ERROR(EFSCORRUPTED));
1017 }
1018 }
1019 *eofp = 1;
1020 xfs_dir_trace_g_du("node: E-O-F", dp, uio);
1021 return(0);
1022}
1023
1024/*
1025 * Look up a filename in an int directory, replace the inode number.
1026 * Use an internal routine to actually do the lookup.
1027 */
1028STATIC int
1029xfs_dir_node_replace(xfs_da_args_t *args)
1030{
1031 xfs_da_state_t *state;
1032 xfs_da_state_blk_t *blk;
1033 xfs_dir_leafblock_t *leaf;
1034 xfs_dir_leaf_entry_t *entry;
1035 xfs_dir_leaf_name_t *namest;
1036 xfs_ino_t inum;
1037 int retval, error, i;
1038 xfs_dabuf_t *bp;
1039
1040 state = xfs_da_state_alloc();
1041 state->args = args;
1042 state->mp = args->dp->i_mount;
1043 state->blocksize = state->mp->m_sb.sb_blocksize;
1044 state->node_ents = state->mp->m_dir_node_ents;
1045 inum = args->inumber;
1046
1047 /*
1048 * Search to see if name exists,
1049 * and get back a pointer to it.
1050 */
1051 error = xfs_da_node_lookup_int(state, &retval);
1052 if (error) {
1053 retval = error;
1054 }
1055
1056 if (retval == EEXIST) {
1057 blk = &state->path.blk[state->path.active - 1];
1058 ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC);
1059 bp = blk->bp;
1060 leaf = bp->data;
1061 entry = &leaf->entries[blk->index];
1062 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
1063 /* XXX - replace assert ? */
1064 XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber);
1065 xfs_da_log_buf(args->trans, bp,
1066 XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber)));
1067 xfs_da_buf_done(bp);
1068 blk->bp = NULL;
1069 retval = 0;
1070 } else {
1071 i = state->path.active - 1;
1072 xfs_da_brelse(args->trans, state->path.blk[i].bp);
1073 state->path.blk[i].bp = NULL;
1074 }
1075 for (i = 0; i < state->path.active - 1; i++) {
1076 xfs_da_brelse(args->trans, state->path.blk[i].bp);
1077 state->path.blk[i].bp = NULL;
1078 }
1079
1080 xfs_da_state_free(state);
1081 return(retval);
1082}
1083
1084#if defined(XFS_DIR_TRACE)
1085/*
1086 * Add a trace buffer entry for an inode and a uio.
1087 */
1088void
1089xfs_dir_trace_g_du(char *where, xfs_inode_t *dp, uio_t *uio)
1090{
1091 xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DU, where,
1092 (void *)dp, (void *)dp->i_mount,
1093 (void *)((unsigned long)(uio->uio_offset >> 32)),
1094 (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
1095 (void *)(unsigned long)uio->uio_resid,
1096 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1097}
1098
1099/*
1100 * Add a trace buffer entry for an inode and a uio.
1101 */
1102void
1103xfs_dir_trace_g_dub(char *where, xfs_inode_t *dp, uio_t *uio, xfs_dablk_t bno)
1104{
1105 xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUB, where,
1106 (void *)dp, (void *)dp->i_mount,
1107 (void *)((unsigned long)(uio->uio_offset >> 32)),
1108 (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
1109 (void *)(unsigned long)uio->uio_resid,
1110 (void *)(unsigned long)bno,
1111 NULL, NULL, NULL, NULL, NULL, NULL);
1112}
1113
1114/*
1115 * Add a trace buffer entry for an inode and a uio.
1116 */
1117void
1118xfs_dir_trace_g_dun(char *where, xfs_inode_t *dp, uio_t *uio,
1119 xfs_da_intnode_t *node)
1120{
1121 int last = be16_to_cpu(node->hdr.count) - 1;
1122
1123 xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUN, where,
1124 (void *)dp, (void *)dp->i_mount,
1125 (void *)((unsigned long)(uio->uio_offset >> 32)),
1126 (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
1127 (void *)(unsigned long)uio->uio_resid,
1128 (void *)(unsigned long)be32_to_cpu(node->hdr.info.forw),
1129 (void *)(unsigned long)
1130 be16_to_cpu(node->hdr.count),
1131 (void *)(unsigned long)
1132 be32_to_cpu(node->btree[0].hashval),
1133 (void *)(unsigned long)
1134 be32_to_cpu(node->btree[last].hashval),
1135 NULL, NULL, NULL);
1136}
1137
1138/*
1139 * Add a trace buffer entry for an inode and a uio.
1140 */
1141void
1142xfs_dir_trace_g_dul(char *where, xfs_inode_t *dp, uio_t *uio,
1143 xfs_dir_leafblock_t *leaf)
1144{
1145 int last = INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1;
1146
1147 xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUL, where,
1148 (void *)dp, (void *)dp->i_mount,
1149 (void *)((unsigned long)(uio->uio_offset >> 32)),
1150 (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
1151 (void *)(unsigned long)uio->uio_resid,
1152 (void *)(unsigned long)be32_to_cpu(leaf->hdr.info.forw),
1153 (void *)(unsigned long)
1154 INT_GET(leaf->hdr.count, ARCH_CONVERT),
1155 (void *)(unsigned long)
1156 INT_GET(leaf->entries[0].hashval, ARCH_CONVERT),
1157 (void *)(unsigned long)
1158 INT_GET(leaf->entries[last].hashval, ARCH_CONVERT),
1159 NULL, NULL, NULL);
1160}
1161
1162/*
1163 * Add a trace buffer entry for an inode and a uio.
1164 */
1165void
1166xfs_dir_trace_g_due(char *where, xfs_inode_t *dp, uio_t *uio,
1167 xfs_dir_leaf_entry_t *entry)
1168{
1169 xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUE, where,
1170 (void *)dp, (void *)dp->i_mount,
1171 (void *)((unsigned long)(uio->uio_offset >> 32)),
1172 (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
1173 (void *)(unsigned long)uio->uio_resid,
1174 (void *)(unsigned long)
1175 INT_GET(entry->hashval, ARCH_CONVERT),
1176 NULL, NULL, NULL, NULL, NULL, NULL);
1177}
1178
1179/*
1180 * Add a trace buffer entry for an inode and a uio.
1181 */
1182void
1183xfs_dir_trace_g_duc(char *where, xfs_inode_t *dp, uio_t *uio, xfs_off_t cookie)
1184{
1185 xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUC, where,
1186 (void *)dp, (void *)dp->i_mount,
1187 (void *)((unsigned long)(uio->uio_offset >> 32)),
1188 (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
1189 (void *)(unsigned long)uio->uio_resid,
1190 (void *)((unsigned long)(cookie >> 32)),
1191 (void *)((unsigned long)(cookie & 0xFFFFFFFF)),
1192 NULL, NULL, NULL, NULL, NULL);
1193}
1194
1195/*
1196 * Add a trace buffer entry for the arguments given to the routine,
1197 * generic form.
1198 */
1199void
1200xfs_dir_trace_enter(int type, char *where,
1201 void * a0, void * a1,
1202 void * a2, void * a3,
1203 void * a4, void * a5,
1204 void * a6, void * a7,
1205 void * a8, void * a9,
1206 void * a10, void * a11)
1207{
1208 ASSERT(xfs_dir_trace_buf);
1209 ktrace_enter(xfs_dir_trace_buf, (void *)(unsigned long)type,
1210 (void *)where,
1211 (void *)a0, (void *)a1, (void *)a2,
1212 (void *)a3, (void *)a4, (void *)a5,
1213 (void *)a6, (void *)a7, (void *)a8,
1214 (void *)a9, (void *)a10, (void *)a11,
1215 NULL, NULL);
1216}
1217#endif /* XFS_DIR_TRACE */
diff --git a/fs/xfs/xfs_dir.h b/fs/xfs/xfs_dir.h
deleted file mode 100644
index 8cc8afb9f6c0..000000000000
--- a/fs/xfs/xfs_dir.h
+++ /dev/null
@@ -1,142 +0,0 @@
1/*
2 * Copyright (c) 2000,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#ifndef __XFS_DIR_H__
19#define __XFS_DIR_H__
20
21/*
22 * Large directories are structured around Btrees where all the data
23 * elements are in the leaf nodes. Filenames are hashed into an int,
24 * then that int is used as the index into the Btree. Since the hashval
25 * of a filename may not be unique, we may have duplicate keys. The
26 * internal links in the Btree are logical block offsets into the file.
27 *
28 * Small directories use a different format and are packed as tightly
29 * as possible so as to fit into the literal area of the inode.
30 */
31
32/*========================================================================
33 * Function prototypes for the kernel.
34 *========================================================================*/
35
36struct uio;
37struct xfs_bmap_free;
38struct xfs_da_args;
39struct xfs_dinode;
40struct xfs_inode;
41struct xfs_mount;
42struct xfs_trans;
43
44/*
45 * Directory function types.
46 * Put in structures (xfs_dirops_t) for v1 and v2 directories.
47 */
48typedef void (*xfs_dir_mount_t)(struct xfs_mount *mp);
49typedef int (*xfs_dir_isempty_t)(struct xfs_inode *dp);
50typedef int (*xfs_dir_init_t)(struct xfs_trans *tp,
51 struct xfs_inode *dp,
52 struct xfs_inode *pdp);
53typedef int (*xfs_dir_createname_t)(struct xfs_trans *tp,
54 struct xfs_inode *dp,
55 char *name,
56 int namelen,
57 xfs_ino_t inum,
58 xfs_fsblock_t *first,
59 struct xfs_bmap_free *flist,
60 xfs_extlen_t total);
61typedef int (*xfs_dir_lookup_t)(struct xfs_trans *tp,
62 struct xfs_inode *dp,
63 char *name,
64 int namelen,
65 xfs_ino_t *inum);
66typedef int (*xfs_dir_removename_t)(struct xfs_trans *tp,
67 struct xfs_inode *dp,
68 char *name,
69 int namelen,
70 xfs_ino_t ino,
71 xfs_fsblock_t *first,
72 struct xfs_bmap_free *flist,
73 xfs_extlen_t total);
74typedef int (*xfs_dir_getdents_t)(struct xfs_trans *tp,
75 struct xfs_inode *dp,
76 struct uio *uio,
77 int *eofp);
78typedef int (*xfs_dir_replace_t)(struct xfs_trans *tp,
79 struct xfs_inode *dp,
80 char *name,
81 int namelen,
82 xfs_ino_t inum,
83 xfs_fsblock_t *first,
84 struct xfs_bmap_free *flist,
85 xfs_extlen_t total);
86typedef int (*xfs_dir_canenter_t)(struct xfs_trans *tp,
87 struct xfs_inode *dp,
88 char *name,
89 int namelen);
90typedef int (*xfs_dir_shortform_validate_ondisk_t)(struct xfs_mount *mp,
91 struct xfs_dinode *dip);
92typedef int (*xfs_dir_shortform_to_single_t)(struct xfs_da_args *args);
93
94typedef struct xfs_dirops {
95 xfs_dir_mount_t xd_mount;
96 xfs_dir_isempty_t xd_isempty;
97 xfs_dir_init_t xd_init;
98 xfs_dir_createname_t xd_createname;
99 xfs_dir_lookup_t xd_lookup;
100 xfs_dir_removename_t xd_removename;
101 xfs_dir_getdents_t xd_getdents;
102 xfs_dir_replace_t xd_replace;
103 xfs_dir_canenter_t xd_canenter;
104 xfs_dir_shortform_validate_ondisk_t xd_shortform_validate_ondisk;
105 xfs_dir_shortform_to_single_t xd_shortform_to_single;
106} xfs_dirops_t;
107
108/*
109 * Overall external interface routines.
110 */
111void xfs_dir_startup(void); /* called exactly once */
112
113#define XFS_DIR_MOUNT(mp) \
114 ((mp)->m_dirops.xd_mount(mp))
115#define XFS_DIR_ISEMPTY(mp,dp) \
116 ((mp)->m_dirops.xd_isempty(dp))
117#define XFS_DIR_INIT(mp,tp,dp,pdp) \
118 ((mp)->m_dirops.xd_init(tp,dp,pdp))
119#define XFS_DIR_CREATENAME(mp,tp,dp,name,namelen,inum,first,flist,total) \
120 ((mp)->m_dirops.xd_createname(tp,dp,name,namelen,inum,first,flist,\
121 total))
122#define XFS_DIR_LOOKUP(mp,tp,dp,name,namelen,inum) \
123 ((mp)->m_dirops.xd_lookup(tp,dp,name,namelen,inum))
124#define XFS_DIR_REMOVENAME(mp,tp,dp,name,namelen,ino,first,flist,total) \
125 ((mp)->m_dirops.xd_removename(tp,dp,name,namelen,ino,first,flist,total))
126#define XFS_DIR_GETDENTS(mp,tp,dp,uio,eofp) \
127 ((mp)->m_dirops.xd_getdents(tp,dp,uio,eofp))
128#define XFS_DIR_REPLACE(mp,tp,dp,name,namelen,inum,first,flist,total) \
129 ((mp)->m_dirops.xd_replace(tp,dp,name,namelen,inum,first,flist,total))
130#define XFS_DIR_CANENTER(mp,tp,dp,name,namelen) \
131 ((mp)->m_dirops.xd_canenter(tp,dp,name,namelen))
132#define XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp,dip) \
133 ((mp)->m_dirops.xd_shortform_validate_ondisk(mp,dip))
134#define XFS_DIR_SHORTFORM_TO_SINGLE(mp,args) \
135 ((mp)->m_dirops.xd_shortform_to_single(args))
136
137#define XFS_DIR_IS_V1(mp) ((mp)->m_dirversion == 1)
138#define XFS_DIR_IS_V2(mp) ((mp)->m_dirversion == 2)
139extern xfs_dirops_t xfsv1_dirops;
140extern xfs_dirops_t xfsv2_dirops;
141
142#endif /* __XFS_DIR_H__ */
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index 022c8398ab62..8edbe1adb95b 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -24,21 +24,18 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_da_btree.h" 30#include "xfs_da_btree.h"
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
38#include "xfs_inode.h" 36#include "xfs_inode.h"
39#include "xfs_inode_item.h" 37#include "xfs_inode_item.h"
40#include "xfs_bmap.h" 38#include "xfs_bmap.h"
41#include "xfs_dir_leaf.h"
42#include "xfs_dir2_data.h" 39#include "xfs_dir2_data.h"
43#include "xfs_dir2_leaf.h" 40#include "xfs_dir2_leaf.h"
44#include "xfs_dir2_block.h" 41#include "xfs_dir2_block.h"
@@ -46,69 +43,14 @@
46#include "xfs_dir2_trace.h" 43#include "xfs_dir2_trace.h"
47#include "xfs_error.h" 44#include "xfs_error.h"
48 45
49/*
50 * Declarations for interface routines.
51 */
52static void xfs_dir2_mount(xfs_mount_t *mp);
53static int xfs_dir2_isempty(xfs_inode_t *dp);
54static int xfs_dir2_init(xfs_trans_t *tp, xfs_inode_t *dp,
55 xfs_inode_t *pdp);
56static int xfs_dir2_createname(xfs_trans_t *tp, xfs_inode_t *dp,
57 char *name, int namelen, xfs_ino_t inum,
58 xfs_fsblock_t *first,
59 xfs_bmap_free_t *flist, xfs_extlen_t total);
60static int xfs_dir2_lookup(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
61 int namelen, xfs_ino_t *inum);
62static int xfs_dir2_removename(xfs_trans_t *tp, xfs_inode_t *dp,
63 char *name, int namelen, xfs_ino_t ino,
64 xfs_fsblock_t *first,
65 xfs_bmap_free_t *flist, xfs_extlen_t total);
66static int xfs_dir2_getdents(xfs_trans_t *tp, xfs_inode_t *dp, uio_t *uio,
67 int *eofp);
68static int xfs_dir2_replace(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
69 int namelen, xfs_ino_t inum,
70 xfs_fsblock_t *first, xfs_bmap_free_t *flist,
71 xfs_extlen_t total);
72static int xfs_dir2_canenter(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
73 int namelen);
74static int xfs_dir2_shortform_validate_ondisk(xfs_mount_t *mp,
75 xfs_dinode_t *dip);
76
77/*
78 * Utility routine declarations.
79 */
80static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa); 46static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa);
81static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa); 47static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa);
82 48
83/* 49void
84 * Directory operations vector. 50xfs_dir_mount(
85 */ 51 xfs_mount_t *mp)
86xfs_dirops_t xfsv2_dirops = {
87 .xd_mount = xfs_dir2_mount,
88 .xd_isempty = xfs_dir2_isempty,
89 .xd_init = xfs_dir2_init,
90 .xd_createname = xfs_dir2_createname,
91 .xd_lookup = xfs_dir2_lookup,
92 .xd_removename = xfs_dir2_removename,
93 .xd_getdents = xfs_dir2_getdents,
94 .xd_replace = xfs_dir2_replace,
95 .xd_canenter = xfs_dir2_canenter,
96 .xd_shortform_validate_ondisk = xfs_dir2_shortform_validate_ondisk,
97 .xd_shortform_to_single = xfs_dir2_sf_to_block,
98};
99
100/*
101 * Interface routines.
102 */
103
104/*
105 * Initialize directory-related fields in the mount structure.
106 */
107static void
108xfs_dir2_mount(
109 xfs_mount_t *mp) /* filesystem mount point */
110{ 52{
111 mp->m_dirversion = 2; 53 ASSERT(XFS_SB_VERSION_HASDIRV2(&mp->m_sb));
112 ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= 54 ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <=
113 XFS_MAX_BLOCKSIZE); 55 XFS_MAX_BLOCKSIZE);
114 mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog); 56 mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
@@ -128,19 +70,15 @@ xfs_dir2_mount(
128/* 70/*
129 * Return 1 if directory contains only "." and "..". 71 * Return 1 if directory contains only "." and "..".
130 */ 72 */
131static int /* return code */ 73int
132xfs_dir2_isempty( 74xfs_dir_isempty(
133 xfs_inode_t *dp) /* incore inode structure */ 75 xfs_inode_t *dp)
134{ 76{
135 xfs_dir2_sf_t *sfp; /* shortform directory structure */ 77 xfs_dir2_sf_t *sfp;
136 78
137 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 79 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
138 /* 80 if (dp->i_d.di_size == 0) /* might happen during shutdown. */
139 * Might happen during shutdown.
140 */
141 if (dp->i_d.di_size == 0) {
142 return 1; 81 return 1;
143 }
144 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) 82 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
145 return 0; 83 return 0;
146 sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data; 84 sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
@@ -148,53 +86,83 @@ xfs_dir2_isempty(
148} 86}
149 87
150/* 88/*
89 * Validate a given inode number.
90 */
91int
92xfs_dir_ino_validate(
93 xfs_mount_t *mp,
94 xfs_ino_t ino)
95{
96 xfs_agblock_t agblkno;
97 xfs_agino_t agino;
98 xfs_agnumber_t agno;
99 int ino_ok;
100 int ioff;
101
102 agno = XFS_INO_TO_AGNO(mp, ino);
103 agblkno = XFS_INO_TO_AGBNO(mp, ino);
104 ioff = XFS_INO_TO_OFFSET(mp, ino);
105 agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff);
106 ino_ok =
107 agno < mp->m_sb.sb_agcount &&
108 agblkno < mp->m_sb.sb_agblocks &&
109 agblkno != 0 &&
110 ioff < (1 << mp->m_sb.sb_inopblog) &&
111 XFS_AGINO_TO_INO(mp, agno, agino) == ino;
112 if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
113 XFS_RANDOM_DIR_INO_VALIDATE))) {
114 xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx",
115 (unsigned long long) ino);
116 XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
117 return XFS_ERROR(EFSCORRUPTED);
118 }
119 return 0;
120}
121
122/*
151 * Initialize a directory with its "." and ".." entries. 123 * Initialize a directory with its "." and ".." entries.
152 */ 124 */
153static int /* error */ 125int
154xfs_dir2_init( 126xfs_dir_init(
155 xfs_trans_t *tp, /* transaction pointer */ 127 xfs_trans_t *tp,
156 xfs_inode_t *dp, /* incore directory inode */ 128 xfs_inode_t *dp,
157 xfs_inode_t *pdp) /* incore parent directory inode */ 129 xfs_inode_t *pdp)
158{ 130{
159 xfs_da_args_t args; /* operation arguments */ 131 xfs_da_args_t args;
160 int error; /* error return value */ 132 int error;
161 133
162 memset((char *)&args, 0, sizeof(args)); 134 memset((char *)&args, 0, sizeof(args));
163 args.dp = dp; 135 args.dp = dp;
164 args.trans = tp; 136 args.trans = tp;
165 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 137 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
166 if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) { 138 if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino)))
167 return error; 139 return error;
168 }
169 return xfs_dir2_sf_create(&args, pdp->i_ino); 140 return xfs_dir2_sf_create(&args, pdp->i_ino);
170} 141}
171 142
172/* 143/*
173 Enter a name in a directory. 144 Enter a name in a directory.
174 */ 145 */
175static int /* error */ 146int
176xfs_dir2_createname( 147xfs_dir_createname(
177 xfs_trans_t *tp, /* transaction pointer */ 148 xfs_trans_t *tp,
178 xfs_inode_t *dp, /* incore directory inode */ 149 xfs_inode_t *dp,
179 char *name, /* new entry name */ 150 char *name,
180 int namelen, /* new entry name length */ 151 int namelen,
181 xfs_ino_t inum, /* new entry inode number */ 152 xfs_ino_t inum, /* new entry inode number */
182 xfs_fsblock_t *first, /* bmap's firstblock */ 153 xfs_fsblock_t *first, /* bmap's firstblock */
183 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 154 xfs_bmap_free_t *flist, /* bmap's freeblock list */
184 xfs_extlen_t total) /* bmap's total block count */ 155 xfs_extlen_t total) /* bmap's total block count */
185{ 156{
186 xfs_da_args_t args; /* operation arguments */ 157 xfs_da_args_t args;
187 int rval; /* return value */ 158 int rval;
188 int v; /* type-checking value */ 159 int v; /* type-checking value */
189 160
190 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 161 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
191 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) { 162 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
192 return rval; 163 return rval;
193 }
194 XFS_STATS_INC(xs_dir_create); 164 XFS_STATS_INC(xs_dir_create);
195 /* 165
196 * Fill in the arg structure for this request.
197 */
198 args.name = name; 166 args.name = name;
199 args.namelen = namelen; 167 args.namelen = namelen;
200 args.hashval = xfs_da_hashname(name, namelen); 168 args.hashval = xfs_da_hashname(name, namelen);
@@ -207,18 +175,16 @@ xfs_dir2_createname(
207 args.trans = tp; 175 args.trans = tp;
208 args.justcheck = 0; 176 args.justcheck = 0;
209 args.addname = args.oknoent = 1; 177 args.addname = args.oknoent = 1;
210 /* 178
211 * Decide on what work routines to call based on the inode size.
212 */
213 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 179 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
214 rval = xfs_dir2_sf_addname(&args); 180 rval = xfs_dir2_sf_addname(&args);
215 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 181 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
216 return rval; 182 return rval;
217 } else if (v) 183 else if (v)
218 rval = xfs_dir2_block_addname(&args); 184 rval = xfs_dir2_block_addname(&args);
219 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 185 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
220 return rval; 186 return rval;
221 } else if (v) 187 else if (v)
222 rval = xfs_dir2_leaf_addname(&args); 188 rval = xfs_dir2_leaf_addname(&args);
223 else 189 else
224 rval = xfs_dir2_node_addname(&args); 190 rval = xfs_dir2_node_addname(&args);
@@ -228,24 +194,21 @@ xfs_dir2_createname(
228/* 194/*
229 * Lookup a name in a directory, give back the inode number. 195 * Lookup a name in a directory, give back the inode number.
230 */ 196 */
231static int /* error */ 197int
232xfs_dir2_lookup( 198xfs_dir_lookup(
233 xfs_trans_t *tp, /* transaction pointer */ 199 xfs_trans_t *tp,
234 xfs_inode_t *dp, /* incore directory inode */ 200 xfs_inode_t *dp,
235 char *name, /* lookup name */ 201 char *name,
236 int namelen, /* lookup name length */ 202 int namelen,
237 xfs_ino_t *inum) /* out: inode number */ 203 xfs_ino_t *inum) /* out: inode number */
238{ 204{
239 xfs_da_args_t args; /* operation arguments */ 205 xfs_da_args_t args;
240 int rval; /* return value */ 206 int rval;
241 int v; /* type-checking value */ 207 int v; /* type-checking value */
242 208
243 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 209 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
244 XFS_STATS_INC(xs_dir_lookup); 210 XFS_STATS_INC(xs_dir_lookup);
245 211
246 /*
247 * Fill in the arg structure for this request.
248 */
249 args.name = name; 212 args.name = name;
250 args.namelen = namelen; 213 args.namelen = namelen;
251 args.hashval = xfs_da_hashname(name, namelen); 214 args.hashval = xfs_da_hashname(name, namelen);
@@ -258,18 +221,16 @@ xfs_dir2_lookup(
258 args.trans = tp; 221 args.trans = tp;
259 args.justcheck = args.addname = 0; 222 args.justcheck = args.addname = 0;
260 args.oknoent = 1; 223 args.oknoent = 1;
261 /* 224
262 * Decide on what work routines to call based on the inode size.
263 */
264 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 225 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
265 rval = xfs_dir2_sf_lookup(&args); 226 rval = xfs_dir2_sf_lookup(&args);
266 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 227 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
267 return rval; 228 return rval;
268 } else if (v) 229 else if (v)
269 rval = xfs_dir2_block_lookup(&args); 230 rval = xfs_dir2_block_lookup(&args);
270 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 231 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
271 return rval; 232 return rval;
272 } else if (v) 233 else if (v)
273 rval = xfs_dir2_leaf_lookup(&args); 234 rval = xfs_dir2_leaf_lookup(&args);
274 else 235 else
275 rval = xfs_dir2_node_lookup(&args); 236 rval = xfs_dir2_node_lookup(&args);
@@ -283,26 +244,24 @@ xfs_dir2_lookup(
283/* 244/*
284 * Remove an entry from a directory. 245 * Remove an entry from a directory.
285 */ 246 */
286static int /* error */ 247int
287xfs_dir2_removename( 248xfs_dir_removename(
288 xfs_trans_t *tp, /* transaction pointer */ 249 xfs_trans_t *tp,
289 xfs_inode_t *dp, /* incore directory inode */ 250 xfs_inode_t *dp,
290 char *name, /* name of entry to remove */ 251 char *name,
291 int namelen, /* name length of entry to remove */ 252 int namelen,
292 xfs_ino_t ino, /* inode number of entry to remove */ 253 xfs_ino_t ino,
293 xfs_fsblock_t *first, /* bmap's firstblock */ 254 xfs_fsblock_t *first, /* bmap's firstblock */
294 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 255 xfs_bmap_free_t *flist, /* bmap's freeblock list */
295 xfs_extlen_t total) /* bmap's total block count */ 256 xfs_extlen_t total) /* bmap's total block count */
296{ 257{
297 xfs_da_args_t args; /* operation arguments */ 258 xfs_da_args_t args;
298 int rval; /* return value */ 259 int rval;
299 int v; /* type-checking value */ 260 int v; /* type-checking value */
300 261
301 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 262 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
302 XFS_STATS_INC(xs_dir_remove); 263 XFS_STATS_INC(xs_dir_remove);
303 /* 264
304 * Fill in the arg structure for this request.
305 */
306 args.name = name; 265 args.name = name;
307 args.namelen = namelen; 266 args.namelen = namelen;
308 args.hashval = xfs_da_hashname(name, namelen); 267 args.hashval = xfs_da_hashname(name, namelen);
@@ -314,18 +273,16 @@ xfs_dir2_removename(
314 args.whichfork = XFS_DATA_FORK; 273 args.whichfork = XFS_DATA_FORK;
315 args.trans = tp; 274 args.trans = tp;
316 args.justcheck = args.addname = args.oknoent = 0; 275 args.justcheck = args.addname = args.oknoent = 0;
317 /* 276
318 * Decide on what work routines to call based on the inode size.
319 */
320 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 277 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
321 rval = xfs_dir2_sf_removename(&args); 278 rval = xfs_dir2_sf_removename(&args);
322 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 279 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
323 return rval; 280 return rval;
324 } else if (v) 281 else if (v)
325 rval = xfs_dir2_block_removename(&args); 282 rval = xfs_dir2_block_removename(&args);
326 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 283 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
327 return rval; 284 return rval;
328 } else if (v) 285 else if (v)
329 rval = xfs_dir2_leaf_removename(&args); 286 rval = xfs_dir2_leaf_removename(&args);
330 else 287 else
331 rval = xfs_dir2_node_removename(&args); 288 rval = xfs_dir2_node_removename(&args);
@@ -335,10 +292,10 @@ xfs_dir2_removename(
335/* 292/*
336 * Read a directory. 293 * Read a directory.
337 */ 294 */
338static int /* error */ 295int
339xfs_dir2_getdents( 296xfs_dir_getdents(
340 xfs_trans_t *tp, /* transaction pointer */ 297 xfs_trans_t *tp,
341 xfs_inode_t *dp, /* incore directory inode */ 298 xfs_inode_t *dp,
342 uio_t *uio, /* caller's buffer control */ 299 uio_t *uio, /* caller's buffer control */
343 int *eofp) /* out: eof reached */ 300 int *eofp) /* out: eof reached */
344{ 301{
@@ -367,14 +324,11 @@ xfs_dir2_getdents(
367 } 324 }
368 325
369 *eofp = 0; 326 *eofp = 0;
370 /*
371 * Decide on what work routines to call based on the inode size.
372 */
373 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 327 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
374 rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put); 328 rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put);
375 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 329 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
376 ; 330 ;
377 } else if (v) 331 else if (v)
378 rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put); 332 rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put);
379 else 333 else
380 rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put); 334 rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put);
@@ -386,29 +340,26 @@ xfs_dir2_getdents(
386/* 340/*
387 * Replace the inode number of a directory entry. 341 * Replace the inode number of a directory entry.
388 */ 342 */
389static int /* error */ 343int
390xfs_dir2_replace( 344xfs_dir_replace(
391 xfs_trans_t *tp, /* transaction pointer */ 345 xfs_trans_t *tp,
392 xfs_inode_t *dp, /* incore directory inode */ 346 xfs_inode_t *dp,
393 char *name, /* name of entry to replace */ 347 char *name, /* name of entry to replace */
394 int namelen, /* name length of entry to replace */ 348 int namelen,
395 xfs_ino_t inum, /* new inode number */ 349 xfs_ino_t inum, /* new inode number */
396 xfs_fsblock_t *first, /* bmap's firstblock */ 350 xfs_fsblock_t *first, /* bmap's firstblock */
397 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 351 xfs_bmap_free_t *flist, /* bmap's freeblock list */
398 xfs_extlen_t total) /* bmap's total block count */ 352 xfs_extlen_t total) /* bmap's total block count */
399{ 353{
400 xfs_da_args_t args; /* operation arguments */ 354 xfs_da_args_t args;
401 int rval; /* return value */ 355 int rval;
402 int v; /* type-checking value */ 356 int v; /* type-checking value */
403 357
404 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 358 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
405 359
406 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) { 360 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
407 return rval; 361 return rval;
408 } 362
409 /*
410 * Fill in the arg structure for this request.
411 */
412 args.name = name; 363 args.name = name;
413 args.namelen = namelen; 364 args.namelen = namelen;
414 args.hashval = xfs_da_hashname(name, namelen); 365 args.hashval = xfs_da_hashname(name, namelen);
@@ -420,18 +371,16 @@ xfs_dir2_replace(
420 args.whichfork = XFS_DATA_FORK; 371 args.whichfork = XFS_DATA_FORK;
421 args.trans = tp; 372 args.trans = tp;
422 args.justcheck = args.addname = args.oknoent = 0; 373 args.justcheck = args.addname = args.oknoent = 0;
423 /* 374
424 * Decide on what work routines to call based on the inode size.
425 */
426 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 375 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
427 rval = xfs_dir2_sf_replace(&args); 376 rval = xfs_dir2_sf_replace(&args);
428 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 377 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
429 return rval; 378 return rval;
430 } else if (v) 379 else if (v)
431 rval = xfs_dir2_block_replace(&args); 380 rval = xfs_dir2_block_replace(&args);
432 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 381 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
433 return rval; 382 return rval;
434 } else if (v) 383 else if (v)
435 rval = xfs_dir2_leaf_replace(&args); 384 rval = xfs_dir2_leaf_replace(&args);
436 else 385 else
437 rval = xfs_dir2_node_replace(&args); 386 rval = xfs_dir2_node_replace(&args);
@@ -441,21 +390,19 @@ xfs_dir2_replace(
441/* 390/*
442 * See if this entry can be added to the directory without allocating space. 391 * See if this entry can be added to the directory without allocating space.
443 */ 392 */
444static int /* error */ 393int
445xfs_dir2_canenter( 394xfs_dir_canenter(
446 xfs_trans_t *tp, /* transaction pointer */ 395 xfs_trans_t *tp,
447 xfs_inode_t *dp, /* incore directory inode */ 396 xfs_inode_t *dp,
448 char *name, /* name of entry to add */ 397 char *name, /* name of entry to add */
449 int namelen) /* name length of entry to add */ 398 int namelen)
450{ 399{
451 xfs_da_args_t args; /* operation arguments */ 400 xfs_da_args_t args;
452 int rval; /* return value */ 401 int rval;
453 int v; /* type-checking value */ 402 int v; /* type-checking value */
454 403
455 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 404 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
456 /* 405
457 * Fill in the arg structure for this request.
458 */
459 args.name = name; 406 args.name = name;
460 args.namelen = namelen; 407 args.namelen = namelen;
461 args.hashval = xfs_da_hashname(name, namelen); 408 args.hashval = xfs_da_hashname(name, namelen);
@@ -467,18 +414,16 @@ xfs_dir2_canenter(
467 args.whichfork = XFS_DATA_FORK; 414 args.whichfork = XFS_DATA_FORK;
468 args.trans = tp; 415 args.trans = tp;
469 args.justcheck = args.addname = args.oknoent = 1; 416 args.justcheck = args.addname = args.oknoent = 1;
470 /* 417
471 * Decide on what work routines to call based on the inode size.
472 */
473 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 418 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
474 rval = xfs_dir2_sf_addname(&args); 419 rval = xfs_dir2_sf_addname(&args);
475 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 420 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
476 return rval; 421 return rval;
477 } else if (v) 422 else if (v)
478 rval = xfs_dir2_block_addname(&args); 423 rval = xfs_dir2_block_addname(&args);
479 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 424 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
480 return rval; 425 return rval;
481 } else if (v) 426 else if (v)
482 rval = xfs_dir2_leaf_addname(&args); 427 rval = xfs_dir2_leaf_addname(&args);
483 else 428 else
484 rval = xfs_dir2_node_addname(&args); 429 rval = xfs_dir2_node_addname(&args);
@@ -486,19 +431,6 @@ xfs_dir2_canenter(
486} 431}
487 432
488/* 433/*
489 * Dummy routine for shortform inode validation.
490 * Can't really do this.
491 */
492/* ARGSUSED */
493static int /* error */
494xfs_dir2_shortform_validate_ondisk(
495 xfs_mount_t *mp, /* filesystem mount point */
496 xfs_dinode_t *dip) /* ondisk inode */
497{
498 return 0;
499}
500
501/*
502 * Utility routines. 434 * Utility routines.
503 */ 435 */
504 436
@@ -507,24 +439,24 @@ xfs_dir2_shortform_validate_ondisk(
507 * This routine is for data and free blocks, not leaf/node blocks 439 * This routine is for data and free blocks, not leaf/node blocks
508 * which are handled by xfs_da_grow_inode. 440 * which are handled by xfs_da_grow_inode.
509 */ 441 */
510int /* error */ 442int
511xfs_dir2_grow_inode( 443xfs_dir2_grow_inode(
512 xfs_da_args_t *args, /* operation arguments */ 444 xfs_da_args_t *args,
513 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ 445 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */
514 xfs_dir2_db_t *dbp) /* out: block number added */ 446 xfs_dir2_db_t *dbp) /* out: block number added */
515{ 447{
516 xfs_fileoff_t bno; /* directory offset of new block */ 448 xfs_fileoff_t bno; /* directory offset of new block */
517 int count; /* count of filesystem blocks */ 449 int count; /* count of filesystem blocks */
518 xfs_inode_t *dp; /* incore directory inode */ 450 xfs_inode_t *dp; /* incore directory inode */
519 int error; /* error return value */ 451 int error;
520 int got; /* blocks actually mapped */ 452 int got; /* blocks actually mapped */
521 int i; /* temp mapping index */ 453 int i;
522 xfs_bmbt_irec_t map; /* single structure for bmap */ 454 xfs_bmbt_irec_t map; /* single structure for bmap */
523 int mapi; /* mapping index */ 455 int mapi; /* mapping index */
524 xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */ 456 xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */
525 xfs_mount_t *mp; /* filesystem mount point */ 457 xfs_mount_t *mp;
526 int nmap; /* number of bmap entries */ 458 int nmap; /* number of bmap entries */
527 xfs_trans_t *tp; /* transaction pointer */ 459 xfs_trans_t *tp;
528 460
529 xfs_dir2_trace_args_s("grow_inode", args, space); 461 xfs_dir2_trace_args_s("grow_inode", args, space);
530 dp = args->dp; 462 dp = args->dp;
@@ -538,9 +470,8 @@ xfs_dir2_grow_inode(
538 /* 470 /*
539 * Find the first hole for our block. 471 * Find the first hole for our block.
540 */ 472 */
541 if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK))) { 473 if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK)))
542 return error; 474 return error;
543 }
544 nmap = 1; 475 nmap = 1;
545 ASSERT(args->firstblock != NULL); 476 ASSERT(args->firstblock != NULL);
546 /* 477 /*
@@ -549,13 +480,9 @@ xfs_dir2_grow_inode(
549 if ((error = xfs_bmapi(tp, dp, bno, count, 480 if ((error = xfs_bmapi(tp, dp, bno, count,
550 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, 481 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
551 args->firstblock, args->total, &map, &nmap, 482 args->firstblock, args->total, &map, &nmap,
552 args->flist))) { 483 args->flist, NULL)))
553 return error; 484 return error;
554 }
555 ASSERT(nmap <= 1); 485 ASSERT(nmap <= 1);
556 /*
557 * Got it in 1.
558 */
559 if (nmap == 1) { 486 if (nmap == 1) {
560 mapp = &map; 487 mapp = &map;
561 mapi = 1; 488 mapi = 1;
@@ -585,7 +512,8 @@ xfs_dir2_grow_inode(
585 if ((error = xfs_bmapi(tp, dp, b, c, 512 if ((error = xfs_bmapi(tp, dp, b, c,
586 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA, 513 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA,
587 args->firstblock, args->total, 514 args->firstblock, args->total,
588 &mapp[mapi], &nmap, args->flist))) { 515 &mapp[mapi], &nmap, args->flist,
516 NULL))) {
589 kmem_free(mapp, sizeof(*mapp) * count); 517 kmem_free(mapp, sizeof(*mapp) * count);
590 return error; 518 return error;
591 } 519 }
@@ -645,20 +573,19 @@ xfs_dir2_grow_inode(
645/* 573/*
646 * See if the directory is a single-block form directory. 574 * See if the directory is a single-block form directory.
647 */ 575 */
648int /* error */ 576int
649xfs_dir2_isblock( 577xfs_dir2_isblock(
650 xfs_trans_t *tp, /* transaction pointer */ 578 xfs_trans_t *tp,
651 xfs_inode_t *dp, /* incore directory inode */ 579 xfs_inode_t *dp,
652 int *vp) /* out: 1 is block, 0 is not block */ 580 int *vp) /* out: 1 is block, 0 is not block */
653{ 581{
654 xfs_fileoff_t last; /* last file offset */ 582 xfs_fileoff_t last; /* last file offset */
655 xfs_mount_t *mp; /* filesystem mount point */ 583 xfs_mount_t *mp;
656 int rval; /* return value */ 584 int rval;
657 585
658 mp = dp->i_mount; 586 mp = dp->i_mount;
659 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) { 587 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))
660 return rval; 588 return rval;
661 }
662 rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize; 589 rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize;
663 ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize); 590 ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize);
664 *vp = rval; 591 *vp = rval;
@@ -668,20 +595,19 @@ xfs_dir2_isblock(
668/* 595/*
669 * See if the directory is a single-leaf form directory. 596 * See if the directory is a single-leaf form directory.
670 */ 597 */
671int /* error */ 598int
672xfs_dir2_isleaf( 599xfs_dir2_isleaf(
673 xfs_trans_t *tp, /* transaction pointer */ 600 xfs_trans_t *tp,
674 xfs_inode_t *dp, /* incore directory inode */ 601 xfs_inode_t *dp,
675 int *vp) /* out: 1 is leaf, 0 is not leaf */ 602 int *vp) /* out: 1 is leaf, 0 is not leaf */
676{ 603{
677 xfs_fileoff_t last; /* last file offset */ 604 xfs_fileoff_t last; /* last file offset */
678 xfs_mount_t *mp; /* filesystem mount point */ 605 xfs_mount_t *mp;
679 int rval; /* return value */ 606 int rval;
680 607
681 mp = dp->i_mount; 608 mp = dp->i_mount;
682 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) { 609 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))
683 return rval; 610 return rval;
684 }
685 *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog); 611 *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog);
686 return 0; 612 return 0;
687} 613}
@@ -689,9 +615,9 @@ xfs_dir2_isleaf(
689/* 615/*
690 * Getdents put routine for 64-bit ABI, direct form. 616 * Getdents put routine for 64-bit ABI, direct form.
691 */ 617 */
692static int /* error */ 618static int
693xfs_dir2_put_dirent64_direct( 619xfs_dir2_put_dirent64_direct(
694 xfs_dir2_put_args_t *pa) /* argument bundle */ 620 xfs_dir2_put_args_t *pa)
695{ 621{
696 xfs_dirent_t *idbp; /* dirent pointer */ 622 xfs_dirent_t *idbp; /* dirent pointer */
697 iovec_t *iovp; /* io vector */ 623 iovec_t *iovp; /* io vector */
@@ -726,9 +652,9 @@ xfs_dir2_put_dirent64_direct(
726/* 652/*
727 * Getdents put routine for 64-bit ABI, uio form. 653 * Getdents put routine for 64-bit ABI, uio form.
728 */ 654 */
729static int /* error */ 655static int
730xfs_dir2_put_dirent64_uio( 656xfs_dir2_put_dirent64_uio(
731 xfs_dir2_put_args_t *pa) /* argument bundle */ 657 xfs_dir2_put_args_t *pa)
732{ 658{
733 xfs_dirent_t *idbp; /* dirent pointer */ 659 xfs_dirent_t *idbp; /* dirent pointer */
734 int namelen; /* entry name length */ 660 int namelen; /* entry name length */
@@ -764,17 +690,17 @@ xfs_dir2_put_dirent64_uio(
764 */ 690 */
765int 691int
766xfs_dir2_shrink_inode( 692xfs_dir2_shrink_inode(
767 xfs_da_args_t *args, /* operation arguments */ 693 xfs_da_args_t *args,
768 xfs_dir2_db_t db, /* directory block number */ 694 xfs_dir2_db_t db,
769 xfs_dabuf_t *bp) /* block's buffer */ 695 xfs_dabuf_t *bp)
770{ 696{
771 xfs_fileoff_t bno; /* directory file offset */ 697 xfs_fileoff_t bno; /* directory file offset */
772 xfs_dablk_t da; /* directory file offset */ 698 xfs_dablk_t da; /* directory file offset */
773 int done; /* bunmap is finished */ 699 int done; /* bunmap is finished */
774 xfs_inode_t *dp; /* incore directory inode */ 700 xfs_inode_t *dp;
775 int error; /* error return value */ 701 int error;
776 xfs_mount_t *mp; /* filesystem mount point */ 702 xfs_mount_t *mp;
777 xfs_trans_t *tp; /* transaction pointer */ 703 xfs_trans_t *tp;
778 704
779 xfs_dir2_trace_args_db("shrink_inode", args, db, bp); 705 xfs_dir2_trace_args_db("shrink_inode", args, db, bp);
780 dp = args->dp; 706 dp = args->dp;
@@ -786,7 +712,7 @@ xfs_dir2_shrink_inode(
786 */ 712 */
787 if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs, 713 if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs,
788 XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, 714 XFS_BMAPI_METADATA, 0, args->firstblock, args->flist,
789 &done))) { 715 NULL, &done))) {
790 /* 716 /*
791 * ENOSPC actually can happen if we're in a removename with 717 * ENOSPC actually can happen if we're in a removename with
792 * no space reservation, and the resulting block removal 718 * no space reservation, and the resulting block removal
diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h
index 7dd364b1e038..86560b6f794c 100644
--- a/fs/xfs/xfs_dir2.h
+++ b/fs/xfs/xfs_dir2.h
@@ -22,7 +22,9 @@ struct uio;
22struct xfs_dabuf; 22struct xfs_dabuf;
23struct xfs_da_args; 23struct xfs_da_args;
24struct xfs_dir2_put_args; 24struct xfs_dir2_put_args;
25struct xfs_bmap_free;
25struct xfs_inode; 26struct xfs_inode;
27struct xfs_mount;
26struct xfs_trans; 28struct xfs_trans;
27 29
28/* 30/*
@@ -73,7 +75,35 @@ typedef struct xfs_dir2_put_args {
73} xfs_dir2_put_args_t; 75} xfs_dir2_put_args_t;
74 76
75/* 77/*
76 * Other interfaces used by the rest of the dir v2 code. 78 * Generic directory interface routines
79 */
80extern void xfs_dir_startup(void);
81extern void xfs_dir_mount(struct xfs_mount *mp);
82extern int xfs_dir_isempty(struct xfs_inode *dp);
83extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp,
84 struct xfs_inode *pdp);
85extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp,
86 char *name, int namelen, xfs_ino_t inum,
87 xfs_fsblock_t *first,
88 struct xfs_bmap_free *flist, xfs_extlen_t tot);
89extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp,
90 char *name, int namelen, xfs_ino_t *inum);
91extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
92 char *name, int namelen, xfs_ino_t ino,
93 xfs_fsblock_t *first,
94 struct xfs_bmap_free *flist, xfs_extlen_t tot);
95extern int xfs_dir_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
96 uio_t *uio, int *eofp);
97extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
98 char *name, int namelen, xfs_ino_t inum,
99 xfs_fsblock_t *first,
100 struct xfs_bmap_free *flist, xfs_extlen_t tot);
101extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
102 char *name, int namelen);
103extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
104
105/*
106 * Utility routines for v2 directories.
77 */ 107 */
78extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, 108extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
79 xfs_dir2_db_t *dbp); 109 xfs_dir2_db_t *dbp);
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 972ded595476..9d7438bba30d 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -22,19 +22,16 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h" 25#include "xfs_dir2.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_da_btree.h" 28#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h" 29#include "xfs_bmap_btree.h"
31#include "xfs_dir_sf.h"
32#include "xfs_dir2_sf.h" 30#include "xfs_dir2_sf.h"
33#include "xfs_attr_sf.h" 31#include "xfs_attr_sf.h"
34#include "xfs_dinode.h" 32#include "xfs_dinode.h"
35#include "xfs_inode.h" 33#include "xfs_inode.h"
36#include "xfs_inode_item.h" 34#include "xfs_inode_item.h"
37#include "xfs_dir_leaf.h"
38#include "xfs_dir2_data.h" 35#include "xfs_dir2_data.h"
39#include "xfs_dir2_leaf.h" 36#include "xfs_dir2_leaf.h"
40#include "xfs_dir2_block.h" 37#include "xfs_dir2_block.h"
@@ -51,6 +48,18 @@ static int xfs_dir2_block_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **bpp,
51 int *entno); 48 int *entno);
52static int xfs_dir2_block_sort(const void *a, const void *b); 49static int xfs_dir2_block_sort(const void *a, const void *b);
53 50
51static xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot;
52
53/*
54 * One-time startup routine called from xfs_init().
55 */
56void
57xfs_dir_startup(void)
58{
59 xfs_dir_hash_dot = xfs_da_hashname(".", 1);
60 xfs_dir_hash_dotdot = xfs_da_hashname("..", 2);
61}
62
54/* 63/*
55 * Add an entry to a block directory. 64 * Add an entry to a block directory.
56 */ 65 */
@@ -400,7 +409,7 @@ xfs_dir2_block_addname(
400 /* 409 /*
401 * Create the new data entry. 410 * Create the new data entry.
402 */ 411 */
403 INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); 412 dep->inumber = cpu_to_be64(args->inumber);
404 dep->namelen = args->namelen; 413 dep->namelen = args->namelen;
405 memcpy(dep->name, args->name, args->namelen); 414 memcpy(dep->name, args->name, args->namelen);
406 tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); 415 tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
@@ -508,7 +517,7 @@ xfs_dir2_block_getdents(
508 517
509 p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, 518 p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
510 ptr - (char *)block); 519 ptr - (char *)block);
511 p.ino = INT_GET(dep->inumber, ARCH_CONVERT); 520 p.ino = be64_to_cpu(dep->inumber);
512#if XFS_BIG_INUMS 521#if XFS_BIG_INUMS
513 p.ino += mp->m_inoadd; 522 p.ino += mp->m_inoadd;
514#endif 523#endif
@@ -626,7 +635,7 @@ xfs_dir2_block_lookup(
626 /* 635 /*
627 * Fill in inode number, release the block. 636 * Fill in inode number, release the block.
628 */ 637 */
629 args->inumber = INT_GET(dep->inumber, ARCH_CONVERT); 638 args->inumber = be64_to_cpu(dep->inumber);
630 xfs_da_brelse(args->trans, bp); 639 xfs_da_brelse(args->trans, bp);
631 return XFS_ERROR(EEXIST); 640 return XFS_ERROR(EEXIST);
632} 641}
@@ -844,11 +853,11 @@ xfs_dir2_block_replace(
844 */ 853 */
845 dep = (xfs_dir2_data_entry_t *) 854 dep = (xfs_dir2_data_entry_t *)
846 ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address))); 855 ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
847 ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) != args->inumber); 856 ASSERT(be64_to_cpu(dep->inumber) != args->inumber);
848 /* 857 /*
849 * Change the inode number to the new value. 858 * Change the inode number to the new value.
850 */ 859 */
851 INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); 860 dep->inumber = cpu_to_be64(args->inumber);
852 xfs_dir2_data_log_entry(args->trans, bp, dep); 861 xfs_dir2_data_log_entry(args->trans, bp, dep);
853 xfs_dir2_data_check(dp, bp); 862 xfs_dir2_data_check(dp, bp);
854 xfs_da_buf_done(bp); 863 xfs_da_buf_done(bp);
@@ -1130,7 +1139,7 @@ xfs_dir2_sf_to_block(
1130 */ 1139 */
1131 dep = (xfs_dir2_data_entry_t *) 1140 dep = (xfs_dir2_data_entry_t *)
1132 ((char *)block + XFS_DIR2_DATA_DOT_OFFSET); 1141 ((char *)block + XFS_DIR2_DATA_DOT_OFFSET);
1133 INT_SET(dep->inumber, ARCH_CONVERT, dp->i_ino); 1142 dep->inumber = cpu_to_be64(dp->i_ino);
1134 dep->namelen = 1; 1143 dep->namelen = 1;
1135 dep->name[0] = '.'; 1144 dep->name[0] = '.';
1136 tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); 1145 tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
@@ -1144,7 +1153,7 @@ xfs_dir2_sf_to_block(
1144 */ 1153 */
1145 dep = (xfs_dir2_data_entry_t *) 1154 dep = (xfs_dir2_data_entry_t *)
1146 ((char *)block + XFS_DIR2_DATA_DOTDOT_OFFSET); 1155 ((char *)block + XFS_DIR2_DATA_DOTDOT_OFFSET);
1147 INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent)); 1156 dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
1148 dep->namelen = 2; 1157 dep->namelen = 2;
1149 dep->name[0] = dep->name[1] = '.'; 1158 dep->name[0] = dep->name[1] = '.';
1150 tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); 1159 tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
@@ -1193,7 +1202,7 @@ xfs_dir2_sf_to_block(
1193 * Copy a real entry. 1202 * Copy a real entry.
1194 */ 1203 */
1195 dep = (xfs_dir2_data_entry_t *)((char *)block + newoffset); 1204 dep = (xfs_dir2_data_entry_t *)((char *)block + newoffset);
1196 INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER(sfp, 1205 dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp,
1197 XFS_DIR2_SF_INUMBERP(sfep))); 1206 XFS_DIR2_SF_INUMBERP(sfep)));
1198 dep->namelen = sfep->namelen; 1207 dep->namelen = sfep->namelen;
1199 memcpy(dep->name, sfep->name, dep->namelen); 1208 memcpy(dep->name, sfep->name, dep->namelen);
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index bb3d03ff002b..f7c799217072 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -22,18 +22,15 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h" 25#include "xfs_dir2.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_da_btree.h" 28#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h" 29#include "xfs_bmap_btree.h"
31#include "xfs_dir_sf.h"
32#include "xfs_dir2_sf.h" 30#include "xfs_dir2_sf.h"
33#include "xfs_attr_sf.h" 31#include "xfs_attr_sf.h"
34#include "xfs_dinode.h" 32#include "xfs_dinode.h"
35#include "xfs_inode.h" 33#include "xfs_inode.h"
36#include "xfs_dir_leaf.h"
37#include "xfs_dir2_data.h" 34#include "xfs_dir2_data.h"
38#include "xfs_dir2_leaf.h" 35#include "xfs_dir2_leaf.h"
39#include "xfs_dir2_block.h" 36#include "xfs_dir2_block.h"
@@ -133,7 +130,7 @@ xfs_dir2_data_check(
133 */ 130 */
134 dep = (xfs_dir2_data_entry_t *)p; 131 dep = (xfs_dir2_data_entry_t *)p;
135 ASSERT(dep->namelen != 0); 132 ASSERT(dep->namelen != 0);
136 ASSERT(xfs_dir_ino_validate(mp, INT_GET(dep->inumber, ARCH_CONVERT)) == 0); 133 ASSERT(xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)) == 0);
137 ASSERT(be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)) == 134 ASSERT(be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)) ==
138 (char *)dep - (char *)d); 135 (char *)dep - (char *)d);
139 count++; 136 count++;
diff --git a/fs/xfs/xfs_dir2_data.h b/fs/xfs/xfs_dir2_data.h
index 0847cbb53e17..a6ae2d21c40a 100644
--- a/fs/xfs/xfs_dir2_data.h
+++ b/fs/xfs/xfs_dir2_data.h
@@ -85,11 +85,11 @@ typedef struct xfs_dir2_data_hdr {
85 * Tag appears as the last 2 bytes. 85 * Tag appears as the last 2 bytes.
86 */ 86 */
87typedef struct xfs_dir2_data_entry { 87typedef struct xfs_dir2_data_entry {
88 xfs_ino_t inumber; /* inode number */ 88 __be64 inumber; /* inode number */
89 __uint8_t namelen; /* name length */ 89 __u8 namelen; /* name length */
90 __uint8_t name[1]; /* name bytes, no null */ 90 __u8 name[1]; /* name bytes, no null */
91 /* variable offset */ 91 /* variable offset */
92 xfs_dir2_data_off_t tag; /* starting offset of us */ 92 __be16 tag; /* starting offset of us */
93} xfs_dir2_data_entry_t; 93} xfs_dir2_data_entry_t;
94 94
95/* 95/*
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 0f5e2f2ce6ec..b1cf1fbf423d 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_da_btree.h" 30#include "xfs_da_btree.h"
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_attr_sf.h" 32#include "xfs_attr_sf.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_dinode.h" 34#include "xfs_dinode.h"
37#include "xfs_inode.h" 35#include "xfs_inode.h"
@@ -407,7 +405,7 @@ xfs_dir2_leaf_addname(
407 * Initialize our new entry (at last). 405 * Initialize our new entry (at last).
408 */ 406 */
409 dep = (xfs_dir2_data_entry_t *)dup; 407 dep = (xfs_dir2_data_entry_t *)dup;
410 INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); 408 dep->inumber = cpu_to_be64(args->inumber);
411 dep->namelen = args->namelen; 409 dep->namelen = args->namelen;
412 memcpy(dep->name, args->name, dep->namelen); 410 memcpy(dep->name, args->name, dep->namelen);
413 tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); 411 tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
@@ -884,7 +882,7 @@ xfs_dir2_leaf_getdents(
884 XFS_DIR2_BYTE_TO_DA(mp, 882 XFS_DIR2_BYTE_TO_DA(mp,
885 XFS_DIR2_LEAF_OFFSET) - map_off, 883 XFS_DIR2_LEAF_OFFSET) - map_off,
886 XFS_BMAPI_METADATA, NULL, 0, 884 XFS_BMAPI_METADATA, NULL, 0,
887 &map[map_valid], &nmap, NULL); 885 &map[map_valid], &nmap, NULL, NULL);
888 /* 886 /*
889 * Don't know if we should ignore this or 887 * Don't know if we should ignore this or
890 * try to return an error. 888 * try to return an error.
@@ -1098,7 +1096,7 @@ xfs_dir2_leaf_getdents(
1098 1096
1099 p->cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length); 1097 p->cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length);
1100 1098
1101 p->ino = INT_GET(dep->inumber, ARCH_CONVERT); 1099 p->ino = be64_to_cpu(dep->inumber);
1102#if XFS_BIG_INUMS 1100#if XFS_BIG_INUMS
1103 p->ino += mp->m_inoadd; 1101 p->ino += mp->m_inoadd;
1104#endif 1102#endif
@@ -1319,7 +1317,7 @@ xfs_dir2_leaf_lookup(
1319 /* 1317 /*
1320 * Return the found inode number. 1318 * Return the found inode number.
1321 */ 1319 */
1322 args->inumber = INT_GET(dep->inumber, ARCH_CONVERT); 1320 args->inumber = be64_to_cpu(dep->inumber);
1323 xfs_da_brelse(tp, dbp); 1321 xfs_da_brelse(tp, dbp);
1324 xfs_da_brelse(tp, lbp); 1322 xfs_da_brelse(tp, lbp);
1325 return XFS_ERROR(EEXIST); 1323 return XFS_ERROR(EEXIST);
@@ -1606,11 +1604,11 @@ xfs_dir2_leaf_replace(
1606 dep = (xfs_dir2_data_entry_t *) 1604 dep = (xfs_dir2_data_entry_t *)
1607 ((char *)dbp->data + 1605 ((char *)dbp->data +
1608 XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address))); 1606 XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address)));
1609 ASSERT(args->inumber != INT_GET(dep->inumber, ARCH_CONVERT)); 1607 ASSERT(args->inumber != be64_to_cpu(dep->inumber));
1610 /* 1608 /*
1611 * Put the new inode number in, log it. 1609 * Put the new inode number in, log it.
1612 */ 1610 */
1613 INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); 1611 dep->inumber = cpu_to_be64(args->inumber);
1614 tp = args->trans; 1612 tp = args->trans;
1615 xfs_dir2_data_log_entry(tp, dbp, dep); 1613 xfs_dir2_data_log_entry(tp, dbp, dep);
1616 xfs_da_buf_done(dbp); 1614 xfs_da_buf_done(dbp);
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index ac511ab9c52d..9ca71719b683 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -22,13 +22,11 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h" 25#include "xfs_dir2.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_da_btree.h" 28#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h" 29#include "xfs_bmap_btree.h"
31#include "xfs_dir_sf.h"
32#include "xfs_dir2_sf.h" 30#include "xfs_dir2_sf.h"
33#include "xfs_attr_sf.h" 31#include "xfs_attr_sf.h"
34#include "xfs_dinode.h" 32#include "xfs_dinode.h"
@@ -505,7 +503,6 @@ xfs_dir2_leafn_lookup_int(
505 XFS_DATA_FORK))) { 503 XFS_DATA_FORK))) {
506 return error; 504 return error;
507 } 505 }
508 curfdb = newfdb;
509 free = curbp->data; 506 free = curbp->data;
510 ASSERT(be32_to_cpu(free->hdr.magic) == 507 ASSERT(be32_to_cpu(free->hdr.magic) ==
511 XFS_DIR2_FREE_MAGIC); 508 XFS_DIR2_FREE_MAGIC);
@@ -527,8 +524,11 @@ xfs_dir2_leafn_lookup_int(
527 if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) { 524 if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) {
528 XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", 525 XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
529 XFS_ERRLEVEL_LOW, mp); 526 XFS_ERRLEVEL_LOW, mp);
527 if (curfdb != newfdb)
528 xfs_da_brelse(tp, curbp);
530 return XFS_ERROR(EFSCORRUPTED); 529 return XFS_ERROR(EFSCORRUPTED);
531 } 530 }
531 curfdb = newfdb;
532 if (be16_to_cpu(free->bests[fi]) >= length) { 532 if (be16_to_cpu(free->bests[fi]) >= length) {
533 *indexp = index; 533 *indexp = index;
534 state->extravalid = 1; 534 state->extravalid = 1;
@@ -580,7 +580,7 @@ xfs_dir2_leafn_lookup_int(
580 if (dep->namelen == args->namelen && 580 if (dep->namelen == args->namelen &&
581 dep->name[0] == args->name[0] && 581 dep->name[0] == args->name[0] &&
582 memcmp(dep->name, args->name, args->namelen) == 0) { 582 memcmp(dep->name, args->name, args->namelen) == 0) {
583 args->inumber = INT_GET(dep->inumber, ARCH_CONVERT); 583 args->inumber = be64_to_cpu(dep->inumber);
584 *indexp = index; 584 *indexp = index;
585 state->extravalid = 1; 585 state->extravalid = 1;
586 state->extrablk.bp = curbp; 586 state->extrablk.bp = curbp;
@@ -970,7 +970,7 @@ xfs_dir2_leafn_remove(
970 /* 970 /*
971 * One less used entry in the free table. 971 * One less used entry in the free table.
972 */ 972 */
973 free->hdr.nused = cpu_to_be32(-1); 973 be32_add(&free->hdr.nused, -1);
974 xfs_dir2_free_log_header(tp, fbp); 974 xfs_dir2_free_log_header(tp, fbp);
975 /* 975 /*
976 * If this was the last entry in the table, we can 976 * If this was the last entry in the table, we can
@@ -1695,7 +1695,7 @@ xfs_dir2_node_addname_int(
1695 * Fill in the new entry and log it. 1695 * Fill in the new entry and log it.
1696 */ 1696 */
1697 dep = (xfs_dir2_data_entry_t *)dup; 1697 dep = (xfs_dir2_data_entry_t *)dup;
1698 INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); 1698 dep->inumber = cpu_to_be64(args->inumber);
1699 dep->namelen = args->namelen; 1699 dep->namelen = args->namelen;
1700 memcpy(dep->name, args->name, dep->namelen); 1700 memcpy(dep->name, args->name, dep->namelen);
1701 tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); 1701 tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
@@ -1905,11 +1905,11 @@ xfs_dir2_node_replace(
1905 dep = (xfs_dir2_data_entry_t *) 1905 dep = (xfs_dir2_data_entry_t *)
1906 ((char *)data + 1906 ((char *)data +
1907 XFS_DIR2_DATAPTR_TO_OFF(state->mp, be32_to_cpu(lep->address))); 1907 XFS_DIR2_DATAPTR_TO_OFF(state->mp, be32_to_cpu(lep->address)));
1908 ASSERT(inum != INT_GET(dep->inumber, ARCH_CONVERT)); 1908 ASSERT(inum != be64_to_cpu(dep->inumber));
1909 /* 1909 /*
1910 * Fill in the new inode number and log the entry. 1910 * Fill in the new inode number and log the entry.
1911 */ 1911 */
1912 INT_SET(dep->inumber, ARCH_CONVERT, inum); 1912 dep->inumber = cpu_to_be64(inum);
1913 xfs_dir2_data_log_entry(args->trans, state->extrablk.bp, dep); 1913 xfs_dir2_data_log_entry(args->trans, state->extrablk.bp, dep);
1914 rval = 0; 1914 rval = 0;
1915 } 1915 }
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index d98a41d1fe63..0cd77b17bf92 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -22,19 +22,16 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h" 25#include "xfs_dir2.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_da_btree.h" 28#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h" 29#include "xfs_bmap_btree.h"
31#include "xfs_dir_sf.h"
32#include "xfs_dir2_sf.h" 30#include "xfs_dir2_sf.h"
33#include "xfs_attr_sf.h" 31#include "xfs_attr_sf.h"
34#include "xfs_dinode.h" 32#include "xfs_dinode.h"
35#include "xfs_inode.h" 33#include "xfs_inode.h"
36#include "xfs_inode_item.h" 34#include "xfs_inode_item.h"
37#include "xfs_dir_leaf.h"
38#include "xfs_error.h" 35#include "xfs_error.h"
39#include "xfs_dir2_data.h" 36#include "xfs_dir2_data.h"
40#include "xfs_dir2_leaf.h" 37#include "xfs_dir2_leaf.h"
@@ -117,13 +114,13 @@ xfs_dir2_block_sfsize(
117 dep->name[0] == '.' && dep->name[1] == '.'; 114 dep->name[0] == '.' && dep->name[1] == '.';
118#if XFS_BIG_INUMS 115#if XFS_BIG_INUMS
119 if (!isdot) 116 if (!isdot)
120 i8count += INT_GET(dep->inumber, ARCH_CONVERT) > XFS_DIR2_MAX_SHORT_INUM; 117 i8count += be64_to_cpu(dep->inumber) > XFS_DIR2_MAX_SHORT_INUM;
121#endif 118#endif
122 if (!isdot && !isdotdot) { 119 if (!isdot && !isdotdot) {
123 count++; 120 count++;
124 namelen += dep->namelen; 121 namelen += dep->namelen;
125 } else if (isdotdot) 122 } else if (isdotdot)
126 parent = INT_GET(dep->inumber, ARCH_CONVERT); 123 parent = be64_to_cpu(dep->inumber);
127 /* 124 /*
128 * Calculate the new size, see if we should give up yet. 125 * Calculate the new size, see if we should give up yet.
129 */ 126 */
@@ -229,13 +226,13 @@ xfs_dir2_block_to_sf(
229 * Skip . 226 * Skip .
230 */ 227 */
231 if (dep->namelen == 1 && dep->name[0] == '.') 228 if (dep->namelen == 1 && dep->name[0] == '.')
232 ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) == dp->i_ino); 229 ASSERT(be64_to_cpu(dep->inumber) == dp->i_ino);
233 /* 230 /*
234 * Skip .., but make sure the inode number is right. 231 * Skip .., but make sure the inode number is right.
235 */ 232 */
236 else if (dep->namelen == 2 && 233 else if (dep->namelen == 2 &&
237 dep->name[0] == '.' && dep->name[1] == '.') 234 dep->name[0] == '.' && dep->name[1] == '.')
238 ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) == 235 ASSERT(be64_to_cpu(dep->inumber) ==
239 XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent)); 236 XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
240 /* 237 /*
241 * Normal entry, copy it into shortform. 238 * Normal entry, copy it into shortform.
@@ -246,7 +243,7 @@ xfs_dir2_block_to_sf(
246 (xfs_dir2_data_aoff_t) 243 (xfs_dir2_data_aoff_t)
247 ((char *)dep - (char *)block)); 244 ((char *)dep - (char *)block));
248 memcpy(sfep->name, dep->name, dep->namelen); 245 memcpy(sfep->name, dep->name, dep->namelen);
249 temp=INT_GET(dep->inumber, ARCH_CONVERT); 246 temp = be64_to_cpu(dep->inumber);
250 XFS_DIR2_SF_PUT_INUMBER(sfp, &temp, 247 XFS_DIR2_SF_PUT_INUMBER(sfp, &temp,
251 XFS_DIR2_SF_INUMBERP(sfep)); 248 XFS_DIR2_SF_INUMBERP(sfep));
252 sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep); 249 sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
diff --git a/fs/xfs/xfs_dir2_trace.c b/fs/xfs/xfs_dir2_trace.c
index c626943b4112..f3fb2ffd6f5c 100644
--- a/fs/xfs/xfs_dir2_trace.c
+++ b/fs/xfs/xfs_dir2_trace.c
@@ -19,11 +19,9 @@
19#include "xfs_fs.h" 19#include "xfs_fs.h"
20#include "xfs_types.h" 20#include "xfs_types.h"
21#include "xfs_inum.h" 21#include "xfs_inum.h"
22#include "xfs_dir.h"
23#include "xfs_dir2.h" 22#include "xfs_dir2.h"
24#include "xfs_da_btree.h" 23#include "xfs_da_btree.h"
25#include "xfs_bmap_btree.h" 24#include "xfs_bmap_btree.h"
26#include "xfs_dir_sf.h"
27#include "xfs_dir2_sf.h" 25#include "xfs_dir2_sf.h"
28#include "xfs_attr_sf.h" 26#include "xfs_attr_sf.h"
29#include "xfs_dinode.h" 27#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c
deleted file mode 100644
index 6d711869262f..000000000000
--- a/fs/xfs/xfs_dir_leaf.c
+++ /dev/null
@@ -1,2213 +0,0 @@
1/*
2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_types.h"
21#include "xfs_log.h"
22#include "xfs_inum.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h"
27#include "xfs_dmapi.h"
28#include "xfs_mount.h"
29#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_alloc_btree.h"
32#include "xfs_ialloc_btree.h"
33#include "xfs_dir_sf.h"
34#include "xfs_dir2_sf.h"
35#include "xfs_attr_sf.h"
36#include "xfs_dinode.h"
37#include "xfs_inode.h"
38#include "xfs_inode_item.h"
39#include "xfs_alloc.h"
40#include "xfs_btree.h"
41#include "xfs_bmap.h"
42#include "xfs_dir_leaf.h"
43#include "xfs_error.h"
44
45/*
46 * xfs_dir_leaf.c
47 *
48 * Routines to implement leaf blocks of directories as Btrees of hashed names.
49 */
50
51/*========================================================================
52 * Function prototypes for the kernel.
53 *========================================================================*/
54
55/*
56 * Routines used for growing the Btree.
57 */
58STATIC void xfs_dir_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args,
59 int insertion_index,
60 int freemap_index);
61STATIC int xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer,
62 int musthave, int justcheck);
63STATIC void xfs_dir_leaf_rebalance(xfs_da_state_t *state,
64 xfs_da_state_blk_t *blk1,
65 xfs_da_state_blk_t *blk2);
66STATIC int xfs_dir_leaf_figure_balance(xfs_da_state_t *state,
67 xfs_da_state_blk_t *leaf_blk_1,
68 xfs_da_state_blk_t *leaf_blk_2,
69 int *number_entries_in_blk1,
70 int *number_namebytes_in_blk1);
71
72STATIC int xfs_dir_leaf_create(struct xfs_da_args *args,
73 xfs_dablk_t which_block,
74 struct xfs_dabuf **bpp);
75
76/*
77 * Utility routines.
78 */
79STATIC void xfs_dir_leaf_moveents(xfs_dir_leafblock_t *src_leaf,
80 int src_start,
81 xfs_dir_leafblock_t *dst_leaf,
82 int dst_start, int move_count,
83 xfs_mount_t *mp);
84
85
86/*========================================================================
87 * External routines when dirsize < XFS_IFORK_DSIZE(dp).
88 *========================================================================*/
89
90
91/*
92 * Validate a given inode number.
93 */
94int
95xfs_dir_ino_validate(xfs_mount_t *mp, xfs_ino_t ino)
96{
97 xfs_agblock_t agblkno;
98 xfs_agino_t agino;
99 xfs_agnumber_t agno;
100 int ino_ok;
101 int ioff;
102
103 agno = XFS_INO_TO_AGNO(mp, ino);
104 agblkno = XFS_INO_TO_AGBNO(mp, ino);
105 ioff = XFS_INO_TO_OFFSET(mp, ino);
106 agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff);
107 ino_ok =
108 agno < mp->m_sb.sb_agcount &&
109 agblkno < mp->m_sb.sb_agblocks &&
110 agblkno != 0 &&
111 ioff < (1 << mp->m_sb.sb_inopblog) &&
112 XFS_AGINO_TO_INO(mp, agno, agino) == ino;
113 if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
114 XFS_RANDOM_DIR_INO_VALIDATE))) {
115 xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx",
116 (unsigned long long) ino);
117 XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
118 return XFS_ERROR(EFSCORRUPTED);
119 }
120 return 0;
121}
122
123/*
124 * Create the initial contents of a shortform directory.
125 */
126int
127xfs_dir_shortform_create(xfs_da_args_t *args, xfs_ino_t parent)
128{
129 xfs_dir_sf_hdr_t *hdr;
130 xfs_inode_t *dp;
131
132 dp = args->dp;
133 ASSERT(dp != NULL);
134 ASSERT(dp->i_d.di_size == 0);
135 if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) {
136 dp->i_df.if_flags &= ~XFS_IFEXTENTS; /* just in case */
137 dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
138 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
139 dp->i_df.if_flags |= XFS_IFINLINE;
140 }
141 ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
142 ASSERT(dp->i_df.if_bytes == 0);
143 xfs_idata_realloc(dp, sizeof(*hdr), XFS_DATA_FORK);
144 hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data;
145 XFS_DIR_SF_PUT_DIRINO(&parent, &hdr->parent);
146
147 hdr->count = 0;
148 dp->i_d.di_size = sizeof(*hdr);
149 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
150 return 0;
151}
152
153/*
154 * Add a name to the shortform directory structure.
155 * Overflow from the inode has already been checked for.
156 */
157int
158xfs_dir_shortform_addname(xfs_da_args_t *args)
159{
160 xfs_dir_shortform_t *sf;
161 xfs_dir_sf_entry_t *sfe;
162 int i, offset, size;
163 xfs_inode_t *dp;
164
165 dp = args->dp;
166 ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
167 /*
168 * Catch the case where the conversion from shortform to leaf
169 * failed part way through.
170 */
171 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
172 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
173 return XFS_ERROR(EIO);
174 }
175 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
176 ASSERT(dp->i_df.if_u1.if_data != NULL);
177 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
178 sfe = &sf->list[0];
179 for (i = sf->hdr.count-1; i >= 0; i--) {
180 if (sfe->namelen == args->namelen &&
181 args->name[0] == sfe->name[0] &&
182 memcmp(args->name, sfe->name, args->namelen) == 0)
183 return XFS_ERROR(EEXIST);
184 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
185 }
186
187 offset = (int)((char *)sfe - (char *)sf);
188 size = XFS_DIR_SF_ENTSIZE_BYNAME(args->namelen);
189 xfs_idata_realloc(dp, size, XFS_DATA_FORK);
190 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
191 sfe = (xfs_dir_sf_entry_t *)((char *)sf + offset);
192
193 XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber);
194 sfe->namelen = args->namelen;
195 memcpy(sfe->name, args->name, sfe->namelen);
196 sf->hdr.count++;
197
198 dp->i_d.di_size += size;
199 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
200
201 return 0;
202}
203
204/*
205 * Remove a name from the shortform directory structure.
206 */
207int
208xfs_dir_shortform_removename(xfs_da_args_t *args)
209{
210 xfs_dir_shortform_t *sf;
211 xfs_dir_sf_entry_t *sfe;
212 int base, size = 0, i;
213 xfs_inode_t *dp;
214
215 dp = args->dp;
216 ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
217 /*
218 * Catch the case where the conversion from shortform to leaf
219 * failed part way through.
220 */
221 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
222 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
223 return XFS_ERROR(EIO);
224 }
225 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
226 ASSERT(dp->i_df.if_u1.if_data != NULL);
227 base = sizeof(xfs_dir_sf_hdr_t);
228 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
229 sfe = &sf->list[0];
230 for (i = sf->hdr.count-1; i >= 0; i--) {
231 size = XFS_DIR_SF_ENTSIZE_BYENTRY(sfe);
232 if (sfe->namelen == args->namelen &&
233 sfe->name[0] == args->name[0] &&
234 memcmp(sfe->name, args->name, args->namelen) == 0)
235 break;
236 base += size;
237 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
238 }
239 if (i < 0) {
240 ASSERT(args->oknoent);
241 return XFS_ERROR(ENOENT);
242 }
243
244 if ((base + size) != dp->i_d.di_size) {
245 memmove(&((char *)sf)[base], &((char *)sf)[base+size],
246 dp->i_d.di_size - (base+size));
247 }
248 sf->hdr.count--;
249
250 xfs_idata_realloc(dp, -size, XFS_DATA_FORK);
251 dp->i_d.di_size -= size;
252 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
253
254 return 0;
255}
256
257/*
258 * Look up a name in a shortform directory structure.
259 */
260int
261xfs_dir_shortform_lookup(xfs_da_args_t *args)
262{
263 xfs_dir_shortform_t *sf;
264 xfs_dir_sf_entry_t *sfe;
265 int i;
266 xfs_inode_t *dp;
267
268 dp = args->dp;
269 ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
270 /*
271 * Catch the case where the conversion from shortform to leaf
272 * failed part way through.
273 */
274 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
275 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
276 return XFS_ERROR(EIO);
277 }
278 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
279 ASSERT(dp->i_df.if_u1.if_data != NULL);
280 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
281 if (args->namelen == 2 &&
282 args->name[0] == '.' && args->name[1] == '.') {
283 XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &args->inumber);
284 return(XFS_ERROR(EEXIST));
285 }
286 if (args->namelen == 1 && args->name[0] == '.') {
287 args->inumber = dp->i_ino;
288 return(XFS_ERROR(EEXIST));
289 }
290 sfe = &sf->list[0];
291 for (i = sf->hdr.count-1; i >= 0; i--) {
292 if (sfe->namelen == args->namelen &&
293 sfe->name[0] == args->name[0] &&
294 memcmp(args->name, sfe->name, args->namelen) == 0) {
295 XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args->inumber);
296 return(XFS_ERROR(EEXIST));
297 }
298 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
299 }
300 ASSERT(args->oknoent);
301 return(XFS_ERROR(ENOENT));
302}
303
304/*
305 * Convert from using the shortform to the leaf.
306 */
307int
308xfs_dir_shortform_to_leaf(xfs_da_args_t *iargs)
309{
310 xfs_inode_t *dp;
311 xfs_dir_shortform_t *sf;
312 xfs_dir_sf_entry_t *sfe;
313 xfs_da_args_t args;
314 xfs_ino_t inumber;
315 char *tmpbuffer;
316 int retval, i, size;
317 xfs_dablk_t blkno;
318 xfs_dabuf_t *bp;
319
320 dp = iargs->dp;
321 /*
322 * Catch the case where the conversion from shortform to leaf
323 * failed part way through.
324 */
325 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
326 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
327 return XFS_ERROR(EIO);
328 }
329 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
330 ASSERT(dp->i_df.if_u1.if_data != NULL);
331 size = dp->i_df.if_bytes;
332 tmpbuffer = kmem_alloc(size, KM_SLEEP);
333 ASSERT(tmpbuffer != NULL);
334
335 memcpy(tmpbuffer, dp->i_df.if_u1.if_data, size);
336
337 sf = (xfs_dir_shortform_t *)tmpbuffer;
338 XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &inumber);
339
340 xfs_idata_realloc(dp, -size, XFS_DATA_FORK);
341 dp->i_d.di_size = 0;
342 xfs_trans_log_inode(iargs->trans, dp, XFS_ILOG_CORE);
343 retval = xfs_da_grow_inode(iargs, &blkno);
344 if (retval)
345 goto out;
346
347 ASSERT(blkno == 0);
348 retval = xfs_dir_leaf_create(iargs, blkno, &bp);
349 if (retval)
350 goto out;
351 xfs_da_buf_done(bp);
352
353 args.name = ".";
354 args.namelen = 1;
355 args.hashval = xfs_dir_hash_dot;
356 args.inumber = dp->i_ino;
357 args.dp = dp;
358 args.firstblock = iargs->firstblock;
359 args.flist = iargs->flist;
360 args.total = iargs->total;
361 args.whichfork = XFS_DATA_FORK;
362 args.trans = iargs->trans;
363 args.justcheck = 0;
364 args.addname = args.oknoent = 1;
365 retval = xfs_dir_leaf_addname(&args);
366 if (retval)
367 goto out;
368
369 args.name = "..";
370 args.namelen = 2;
371 args.hashval = xfs_dir_hash_dotdot;
372 args.inumber = inumber;
373 retval = xfs_dir_leaf_addname(&args);
374 if (retval)
375 goto out;
376
377 sfe = &sf->list[0];
378 for (i = 0; i < sf->hdr.count; i++) {
379 args.name = (char *)(sfe->name);
380 args.namelen = sfe->namelen;
381 args.hashval = xfs_da_hashname((char *)(sfe->name),
382 sfe->namelen);
383 XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args.inumber);
384 retval = xfs_dir_leaf_addname(&args);
385 if (retval)
386 goto out;
387 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
388 }
389 retval = 0;
390
391out:
392 kmem_free(tmpbuffer, size);
393 return retval;
394}
395
396STATIC int
397xfs_dir_shortform_compare(const void *a, const void *b)
398{
399 xfs_dir_sf_sort_t *sa, *sb;
400
401 sa = (xfs_dir_sf_sort_t *)a;
402 sb = (xfs_dir_sf_sort_t *)b;
403 if (sa->hash < sb->hash)
404 return -1;
405 else if (sa->hash > sb->hash)
406 return 1;
407 else
408 return sa->entno - sb->entno;
409}
410
411/*
412 * Copy out directory entries for getdents(), for shortform directories.
413 */
414/*ARGSUSED*/
415int
416xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp,
417 xfs_dirent_t *dbp, xfs_dir_put_t put)
418{
419 xfs_dir_shortform_t *sf;
420 xfs_dir_sf_entry_t *sfe;
421 int retval, i, sbsize, nsbuf, lastresid=0, want_entno;
422 xfs_mount_t *mp;
423 xfs_dahash_t cookhash, hash;
424 xfs_dir_put_args_t p;
425 xfs_dir_sf_sort_t *sbuf, *sbp;
426
427 mp = dp->i_mount;
428 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
429 cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset);
430 want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset);
431 nsbuf = sf->hdr.count + 2;
432 sbsize = (nsbuf + 1) * sizeof(*sbuf);
433 sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP);
434
435 xfs_dir_trace_g_du("sf: start", dp, uio);
436
437 /*
438 * Collect all the entries into the buffer.
439 * Entry 0 is .
440 */
441 sbp->entno = 0;
442 sbp->seqno = 0;
443 sbp->hash = xfs_dir_hash_dot;
444 sbp->ino = dp->i_ino;
445 sbp->name = ".";
446 sbp->namelen = 1;
447 sbp++;
448
449 /*
450 * Entry 1 is ..
451 */
452 sbp->entno = 1;
453 sbp->seqno = 0;
454 sbp->hash = xfs_dir_hash_dotdot;
455 sbp->ino = XFS_GET_DIR_INO8(sf->hdr.parent);
456 sbp->name = "..";
457 sbp->namelen = 2;
458 sbp++;
459
460 /*
461 * Scan the directory data for the rest of the entries.
462 */
463 for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
464
465 if (unlikely(
466 ((char *)sfe < (char *)sf) ||
467 ((char *)sfe >= ((char *)sf + dp->i_df.if_bytes)))) {
468 xfs_dir_trace_g_du("sf: corrupted", dp, uio);
469 XFS_CORRUPTION_ERROR("xfs_dir_shortform_getdents",
470 XFS_ERRLEVEL_LOW, mp, sfe);
471 kmem_free(sbuf, sbsize);
472 return XFS_ERROR(EFSCORRUPTED);
473 }
474
475 sbp->entno = i + 2;
476 sbp->seqno = 0;
477 sbp->hash = xfs_da_hashname((char *)sfe->name, sfe->namelen);
478 sbp->ino = XFS_GET_DIR_INO8(sfe->inumber);
479 sbp->name = (char *)sfe->name;
480 sbp->namelen = sfe->namelen;
481 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
482 sbp++;
483 }
484
485 /*
486 * Sort the entries on hash then entno.
487 */
488 xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_dir_shortform_compare);
489 /*
490 * Stuff in last entry.
491 */
492 sbp->entno = nsbuf;
493 sbp->hash = XFS_DA_MAXHASH;
494 sbp->seqno = 0;
495 /*
496 * Figure out the sequence numbers in case there's a hash duplicate.
497 */
498 for (hash = sbuf->hash, sbp = sbuf + 1;
499 sbp < &sbuf[nsbuf + 1]; sbp++) {
500 if (sbp->hash == hash)
501 sbp->seqno = sbp[-1].seqno + 1;
502 else
503 hash = sbp->hash;
504 }
505
506 /*
507 * Set up put routine.
508 */
509 p.dbp = dbp;
510 p.put = put;
511 p.uio = uio;
512
513 /*
514 * Find our place.
515 */
516 for (sbp = sbuf; sbp < &sbuf[nsbuf + 1]; sbp++) {
517 if (sbp->hash > cookhash ||
518 (sbp->hash == cookhash && sbp->seqno >= want_entno))
519 break;
520 }
521
522 /*
523 * Did we fail to find anything? We stop at the last entry,
524 * the one we put maxhash into.
525 */
526 if (sbp == &sbuf[nsbuf]) {
527 kmem_free(sbuf, sbsize);
528 xfs_dir_trace_g_du("sf: hash beyond end", dp, uio);
529 uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH);
530 *eofp = 1;
531 return 0;
532 }
533
534 /*
535 * Loop putting entries into the user buffer.
536 */
537 while (sbp < &sbuf[nsbuf]) {
538 /*
539 * Save the first resid in a run of equal-hashval entries
540 * so that we can back them out if they don't all fit.
541 */
542 if (sbp->seqno == 0 || sbp == sbuf)
543 lastresid = uio->uio_resid;
544 XFS_PUT_COOKIE(p.cook, mp, 0, sbp[1].seqno, sbp[1].hash);
545 p.ino = sbp->ino;
546#if XFS_BIG_INUMS
547 p.ino += mp->m_inoadd;
548#endif
549 p.name = sbp->name;
550 p.namelen = sbp->namelen;
551 retval = p.put(&p);
552 if (!p.done) {
553 uio->uio_offset =
554 XFS_DA_MAKE_COOKIE(mp, 0, 0, sbp->hash);
555 kmem_free(sbuf, sbsize);
556 uio->uio_resid = lastresid;
557 xfs_dir_trace_g_du("sf: E-O-B", dp, uio);
558 return retval;
559 }
560 sbp++;
561 }
562 kmem_free(sbuf, sbsize);
563 uio->uio_offset = p.cook.o;
564 *eofp = 1;
565 xfs_dir_trace_g_du("sf: E-O-F", dp, uio);
566 return 0;
567}
568
569/*
570 * Look up a name in a shortform directory structure, replace the inode number.
571 */
572int
573xfs_dir_shortform_replace(xfs_da_args_t *args)
574{
575 xfs_dir_shortform_t *sf;
576 xfs_dir_sf_entry_t *sfe;
577 xfs_inode_t *dp;
578 int i;
579
580 dp = args->dp;
581 ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
582 /*
583 * Catch the case where the conversion from shortform to leaf
584 * failed part way through.
585 */
586 if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
587 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
588 return XFS_ERROR(EIO);
589 }
590 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
591 ASSERT(dp->i_df.if_u1.if_data != NULL);
592 sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
593 if (args->namelen == 2 &&
594 args->name[0] == '.' && args->name[1] == '.') {
595 /* XXX - replace assert? */
596 XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sf->hdr.parent);
597 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
598 return 0;
599 }
600 ASSERT(args->namelen != 1 || args->name[0] != '.');
601 sfe = &sf->list[0];
602 for (i = sf->hdr.count-1; i >= 0; i--) {
603 if (sfe->namelen == args->namelen &&
604 sfe->name[0] == args->name[0] &&
605 memcmp(args->name, sfe->name, args->namelen) == 0) {
606 ASSERT(memcmp((char *)&args->inumber,
607 (char *)&sfe->inumber, sizeof(xfs_ino_t)));
608 XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber);
609 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
610 return 0;
611 }
612 sfe = XFS_DIR_SF_NEXTENTRY(sfe);
613 }
614 ASSERT(args->oknoent);
615 return XFS_ERROR(ENOENT);
616}
617
618/*
619 * Convert a leaf directory to shortform structure
620 */
621int
622xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs)
623{
624 xfs_dir_leafblock_t *leaf;
625 xfs_dir_leaf_hdr_t *hdr;
626 xfs_dir_leaf_entry_t *entry;
627 xfs_dir_leaf_name_t *namest;
628 xfs_da_args_t args;
629 xfs_inode_t *dp;
630 xfs_ino_t parent = 0;
631 char *tmpbuffer;
632 int retval, i;
633 xfs_dabuf_t *bp;
634
635 dp = iargs->dp;
636 tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP);
637 ASSERT(tmpbuffer != NULL);
638
639 retval = xfs_da_read_buf(iargs->trans, iargs->dp, 0, -1, &bp,
640 XFS_DATA_FORK);
641 if (retval)
642 goto out;
643 ASSERT(bp != NULL);
644 memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount));
645 leaf = (xfs_dir_leafblock_t *)tmpbuffer;
646 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
647 memset(bp->data, 0, XFS_LBSIZE(dp->i_mount));
648
649 /*
650 * Find and special case the parent inode number
651 */
652 hdr = &leaf->hdr;
653 entry = &leaf->entries[0];
654 for (i = INT_GET(hdr->count, ARCH_CONVERT)-1; i >= 0; entry++, i--) {
655 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
656 if ((entry->namelen == 2) &&
657 (namest->name[0] == '.') &&
658 (namest->name[1] == '.')) {
659 XFS_DIR_SF_GET_DIRINO(&namest->inumber, &parent);
660 entry->nameidx = 0;
661 } else if ((entry->namelen == 1) && (namest->name[0] == '.')) {
662 entry->nameidx = 0;
663 }
664 }
665 retval = xfs_da_shrink_inode(iargs, 0, bp);
666 if (retval)
667 goto out;
668 retval = xfs_dir_shortform_create(iargs, parent);
669 if (retval)
670 goto out;
671
672 /*
673 * Copy the rest of the filenames
674 */
675 entry = &leaf->entries[0];
676 args.dp = dp;
677 args.firstblock = iargs->firstblock;
678 args.flist = iargs->flist;
679 args.total = iargs->total;
680 args.whichfork = XFS_DATA_FORK;
681 args.trans = iargs->trans;
682 args.justcheck = 0;
683 args.addname = args.oknoent = 1;
684 for (i = 0; i < INT_GET(hdr->count, ARCH_CONVERT); entry++, i++) {
685 if (!entry->nameidx)
686 continue;
687 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
688 args.name = (char *)(namest->name);
689 args.namelen = entry->namelen;
690 args.hashval = INT_GET(entry->hashval, ARCH_CONVERT);
691 XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args.inumber);
692 xfs_dir_shortform_addname(&args);
693 }
694
695out:
696 kmem_free(tmpbuffer, XFS_LBSIZE(dp->i_mount));
697 return retval;
698}
699
700/*
701 * Convert from using a single leaf to a root node and a leaf.
702 */
703int
704xfs_dir_leaf_to_node(xfs_da_args_t *args)
705{
706 xfs_dir_leafblock_t *leaf;
707 xfs_da_intnode_t *node;
708 xfs_inode_t *dp;
709 xfs_dabuf_t *bp1, *bp2;
710 xfs_dablk_t blkno;
711 int retval;
712
713 dp = args->dp;
714 retval = xfs_da_grow_inode(args, &blkno);
715 ASSERT(blkno == 1);
716 if (retval)
717 return retval;
718 retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp1,
719 XFS_DATA_FORK);
720 if (retval)
721 return retval;
722 ASSERT(bp1 != NULL);
723 retval = xfs_da_get_buf(args->trans, args->dp, 1, -1, &bp2,
724 XFS_DATA_FORK);
725 if (retval) {
726 xfs_da_buf_done(bp1);
727 return retval;
728 }
729 ASSERT(bp2 != NULL);
730 memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount));
731 xfs_da_buf_done(bp1);
732 xfs_da_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1);
733
734 /*
735 * Set up the new root node.
736 */
737 retval = xfs_da_node_create(args, 0, 1, &bp1, XFS_DATA_FORK);
738 if (retval) {
739 xfs_da_buf_done(bp2);
740 return retval;
741 }
742 node = bp1->data;
743 leaf = bp2->data;
744 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
745 node->btree[0].hashval = cpu_to_be32(
746 INT_GET(leaf->entries[
747 INT_GET(leaf->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT));
748 xfs_da_buf_done(bp2);
749 node->btree[0].before = cpu_to_be32(blkno);
750 node->hdr.count = cpu_to_be16(1);
751 xfs_da_log_buf(args->trans, bp1,
752 XFS_DA_LOGRANGE(node, &node->btree[0], sizeof(node->btree[0])));
753 xfs_da_buf_done(bp1);
754
755 return retval;
756}
757
758
759/*========================================================================
760 * Routines used for growing the Btree.
761 *========================================================================*/
762
763/*
764 * Create the initial contents of a leaf directory
765 * or a leaf in a node directory.
766 */
767STATIC int
768xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
769{
770 xfs_dir_leafblock_t *leaf;
771 xfs_dir_leaf_hdr_t *hdr;
772 xfs_inode_t *dp;
773 xfs_dabuf_t *bp;
774 int retval;
775
776 dp = args->dp;
777 ASSERT(dp != NULL);
778 retval = xfs_da_get_buf(args->trans, dp, blkno, -1, &bp, XFS_DATA_FORK);
779 if (retval)
780 return retval;
781 ASSERT(bp != NULL);
782 leaf = bp->data;
783 memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount));
784 hdr = &leaf->hdr;
785 hdr->info.magic = cpu_to_be16(XFS_DIR_LEAF_MAGIC);
786 INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount));
787 if (!hdr->firstused)
788 INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount) - 1);
789 INT_SET(hdr->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t));
790 INT_SET(hdr->freemap[0].size, ARCH_CONVERT, INT_GET(hdr->firstused, ARCH_CONVERT) - INT_GET(hdr->freemap[0].base, ARCH_CONVERT));
791
792 xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1);
793
794 *bpp = bp;
795 return 0;
796}
797
798/*
799 * Split the leaf node, rebalance, then add the new entry.
800 */
801int
802xfs_dir_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
803 xfs_da_state_blk_t *newblk)
804{
805 xfs_dablk_t blkno;
806 xfs_da_args_t *args;
807 int error;
808
809 /*
810 * Allocate space for a new leaf node.
811 */
812 args = state->args;
813 ASSERT(args != NULL);
814 ASSERT(oldblk->magic == XFS_DIR_LEAF_MAGIC);
815 error = xfs_da_grow_inode(args, &blkno);
816 if (error)
817 return error;
818 error = xfs_dir_leaf_create(args, blkno, &newblk->bp);
819 if (error)
820 return error;
821 newblk->blkno = blkno;
822 newblk->magic = XFS_DIR_LEAF_MAGIC;
823
824 /*
825 * Rebalance the entries across the two leaves.
826 */
827 xfs_dir_leaf_rebalance(state, oldblk, newblk);
828 error = xfs_da_blk_link(state, oldblk, newblk);
829 if (error)
830 return error;
831
832 /*
833 * Insert the new entry in the correct block.
834 */
835 if (state->inleaf) {
836 error = xfs_dir_leaf_add(oldblk->bp, args, oldblk->index);
837 } else {
838 error = xfs_dir_leaf_add(newblk->bp, args, newblk->index);
839 }
840
841 /*
842 * Update last hashval in each block since we added the name.
843 */
844 oldblk->hashval = xfs_dir_leaf_lasthash(oldblk->bp, NULL);
845 newblk->hashval = xfs_dir_leaf_lasthash(newblk->bp, NULL);
846 return error;
847}
848
849/*
850 * Add a name to the leaf directory structure.
851 *
852 * Must take into account fragmented leaves and leaves where spacemap has
853 * lost some freespace information (ie: holes).
854 */
855int
856xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index)
857{
858 xfs_dir_leafblock_t *leaf;
859 xfs_dir_leaf_hdr_t *hdr;
860 xfs_dir_leaf_map_t *map;
861 int tablesize, entsize, sum, i, tmp, error;
862
863 leaf = bp->data;
864 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
865 ASSERT((index >= 0) && (index <= INT_GET(leaf->hdr.count, ARCH_CONVERT)));
866 hdr = &leaf->hdr;
867 entsize = XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen);
868
869 /*
870 * Search through freemap for first-fit on new name length.
871 * (may need to figure in size of entry struct too)
872 */
873 tablesize = (INT_GET(hdr->count, ARCH_CONVERT) + 1) * (uint)sizeof(xfs_dir_leaf_entry_t)
874 + (uint)sizeof(xfs_dir_leaf_hdr_t);
875 map = &hdr->freemap[XFS_DIR_LEAF_MAPSIZE-1];
876 for (sum = 0, i = XFS_DIR_LEAF_MAPSIZE-1; i >= 0; map--, i--) {
877 if (tablesize > INT_GET(hdr->firstused, ARCH_CONVERT)) {
878 sum += INT_GET(map->size, ARCH_CONVERT);
879 continue;
880 }
881 if (!map->size)
882 continue; /* no space in this map */
883 tmp = entsize;
884 if (INT_GET(map->base, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT))
885 tmp += (uint)sizeof(xfs_dir_leaf_entry_t);
886 if (INT_GET(map->size, ARCH_CONVERT) >= tmp) {
887 if (!args->justcheck)
888 xfs_dir_leaf_add_work(bp, args, index, i);
889 return 0;
890 }
891 sum += INT_GET(map->size, ARCH_CONVERT);
892 }
893
894 /*
895 * If there are no holes in the address space of the block,
896 * and we don't have enough freespace, then compaction will do us
897 * no good and we should just give up.
898 */
899 if (!hdr->holes && (sum < entsize))
900 return XFS_ERROR(ENOSPC);
901
902 /*
903 * Compact the entries to coalesce free space.
904 * Pass the justcheck flag so the checking pass can return
905 * an error, without changing anything, if it won't fit.
906 */
907 error = xfs_dir_leaf_compact(args->trans, bp,
908 args->total == 0 ?
909 entsize +
910 (uint)sizeof(xfs_dir_leaf_entry_t) : 0,
911 args->justcheck);
912 if (error)
913 return error;
914 /*
915 * After compaction, the block is guaranteed to have only one
916 * free region, in freemap[0]. If it is not big enough, give up.
917 */
918 if (INT_GET(hdr->freemap[0].size, ARCH_CONVERT) <
919 (entsize + (uint)sizeof(xfs_dir_leaf_entry_t)))
920 return XFS_ERROR(ENOSPC);
921
922 if (!args->justcheck)
923 xfs_dir_leaf_add_work(bp, args, index, 0);
924 return 0;
925}
926
927/*
928 * Add a name to a leaf directory structure.
929 */
930STATIC void
931xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index,
932 int mapindex)
933{
934 xfs_dir_leafblock_t *leaf;
935 xfs_dir_leaf_hdr_t *hdr;
936 xfs_dir_leaf_entry_t *entry;
937 xfs_dir_leaf_name_t *namest;
938 xfs_dir_leaf_map_t *map;
939 /* REFERENCED */
940 xfs_mount_t *mp;
941 int tmp, i;
942
943 leaf = bp->data;
944 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
945 hdr = &leaf->hdr;
946 ASSERT((mapindex >= 0) && (mapindex < XFS_DIR_LEAF_MAPSIZE));
947 ASSERT((index >= 0) && (index <= INT_GET(hdr->count, ARCH_CONVERT)));
948
949 /*
950 * Force open some space in the entry array and fill it in.
951 */
952 entry = &leaf->entries[index];
953 if (index < INT_GET(hdr->count, ARCH_CONVERT)) {
954 tmp = INT_GET(hdr->count, ARCH_CONVERT) - index;
955 tmp *= (uint)sizeof(xfs_dir_leaf_entry_t);
956 memmove(entry + 1, entry, tmp);
957 xfs_da_log_buf(args->trans, bp,
958 XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry)));
959 }
960 INT_MOD(hdr->count, ARCH_CONVERT, +1);
961
962 /*
963 * Allocate space for the new string (at the end of the run).
964 */
965 map = &hdr->freemap[mapindex];
966 mp = args->trans->t_mountp;
967 ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp));
968 ASSERT(INT_GET(map->size, ARCH_CONVERT) >= XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen));
969 ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp));
970 INT_MOD(map->size, ARCH_CONVERT, -(XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen)));
971 INT_SET(entry->nameidx, ARCH_CONVERT, INT_GET(map->base, ARCH_CONVERT) + INT_GET(map->size, ARCH_CONVERT));
972 INT_SET(entry->hashval, ARCH_CONVERT, args->hashval);
973 entry->namelen = args->namelen;
974 xfs_da_log_buf(args->trans, bp,
975 XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
976
977 /*
978 * Copy the string and inode number into the new space.
979 */
980 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
981 XFS_DIR_SF_PUT_DIRINO(&args->inumber, &namest->inumber);
982 memcpy(namest->name, args->name, args->namelen);
983 xfs_da_log_buf(args->trans, bp,
984 XFS_DA_LOGRANGE(leaf, namest, XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry)));
985
986 /*
987 * Update the control info for this leaf node
988 */
989 if (INT_GET(entry->nameidx, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT))
990 INT_COPY(hdr->firstused, entry->nameidx, ARCH_CONVERT);
991 ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) >= ((INT_GET(hdr->count, ARCH_CONVERT)*sizeof(*entry))+sizeof(*hdr)));
992 tmp = (INT_GET(hdr->count, ARCH_CONVERT)-1) * (uint)sizeof(xfs_dir_leaf_entry_t)
993 + (uint)sizeof(xfs_dir_leaf_hdr_t);
994 map = &hdr->freemap[0];
995 for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) {
996 if (INT_GET(map->base, ARCH_CONVERT) == tmp) {
997 INT_MOD(map->base, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_entry_t));
998 INT_MOD(map->size, ARCH_CONVERT, -((uint)sizeof(xfs_dir_leaf_entry_t)));
999 }
1000 }
1001 INT_MOD(hdr->namebytes, ARCH_CONVERT, args->namelen);
1002 xfs_da_log_buf(args->trans, bp,
1003 XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));
1004}
1005
1006/*
1007 * Garbage collect a leaf directory block by copying it to a new buffer.
1008 */
1009STATIC int
1010xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp, int musthave,
1011 int justcheck)
1012{
1013 xfs_dir_leafblock_t *leaf_s, *leaf_d;
1014 xfs_dir_leaf_hdr_t *hdr_s, *hdr_d;
1015 xfs_mount_t *mp;
1016 char *tmpbuffer;
1017 char *tmpbuffer2=NULL;
1018 int rval;
1019 int lbsize;
1020
1021 mp = trans->t_mountp;
1022 lbsize = XFS_LBSIZE(mp);
1023 tmpbuffer = kmem_alloc(lbsize, KM_SLEEP);
1024 ASSERT(tmpbuffer != NULL);
1025 memcpy(tmpbuffer, bp->data, lbsize);
1026
1027 /*
1028 * Make a second copy in case xfs_dir_leaf_moveents()
1029 * below destroys the original.
1030 */
1031 if (musthave || justcheck) {
1032 tmpbuffer2 = kmem_alloc(lbsize, KM_SLEEP);
1033 memcpy(tmpbuffer2, bp->data, lbsize);
1034 }
1035 memset(bp->data, 0, lbsize);
1036
1037 /*
1038 * Copy basic information
1039 */
1040 leaf_s = (xfs_dir_leafblock_t *)tmpbuffer;
1041 leaf_d = bp->data;
1042 hdr_s = &leaf_s->hdr;
1043 hdr_d = &leaf_d->hdr;
1044 hdr_d->info = hdr_s->info; /* struct copy */
1045 INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize);
1046 if (!hdr_d->firstused)
1047 INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize - 1);
1048 hdr_d->namebytes = 0;
1049 hdr_d->count = 0;
1050 hdr_d->holes = 0;
1051 INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t));
1052 INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, INT_GET(hdr_d->firstused, ARCH_CONVERT) - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT));
1053
1054 /*
1055 * Copy all entry's in the same (sorted) order,
1056 * but allocate filenames packed and in sequence.
1057 * This changes the source (leaf_s) as well.
1058 */
1059 xfs_dir_leaf_moveents(leaf_s, 0, leaf_d, 0, (int)INT_GET(hdr_s->count, ARCH_CONVERT), mp);
1060
1061 if (musthave && INT_GET(hdr_d->freemap[0].size, ARCH_CONVERT) < musthave)
1062 rval = XFS_ERROR(ENOSPC);
1063 else
1064 rval = 0;
1065
1066 if (justcheck || rval == ENOSPC) {
1067 ASSERT(tmpbuffer2);
1068 memcpy(bp->data, tmpbuffer2, lbsize);
1069 } else {
1070 xfs_da_log_buf(trans, bp, 0, lbsize - 1);
1071 }
1072
1073 kmem_free(tmpbuffer, lbsize);
1074 if (musthave || justcheck)
1075 kmem_free(tmpbuffer2, lbsize);
1076 return rval;
1077}
1078
1079/*
1080 * Redistribute the directory entries between two leaf nodes,
1081 * taking into account the size of the new entry.
1082 *
1083 * NOTE: if new block is empty, then it will get the upper half of old block.
1084 */
1085STATIC void
1086xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
1087 xfs_da_state_blk_t *blk2)
1088{
1089 xfs_da_state_blk_t *tmp_blk;
1090 xfs_dir_leafblock_t *leaf1, *leaf2;
1091 xfs_dir_leaf_hdr_t *hdr1, *hdr2;
1092 int count, totallen, max, space, swap;
1093
1094 /*
1095 * Set up environment.
1096 */
1097 ASSERT(blk1->magic == XFS_DIR_LEAF_MAGIC);
1098 ASSERT(blk2->magic == XFS_DIR_LEAF_MAGIC);
1099 leaf1 = blk1->bp->data;
1100 leaf2 = blk2->bp->data;
1101 ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1102 ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1103
1104 /*
1105 * Check ordering of blocks, reverse if it makes things simpler.
1106 */
1107 swap = 0;
1108 if (xfs_dir_leaf_order(blk1->bp, blk2->bp)) {
1109 tmp_blk = blk1;
1110 blk1 = blk2;
1111 blk2 = tmp_blk;
1112 leaf1 = blk1->bp->data;
1113 leaf2 = blk2->bp->data;
1114 swap = 1;
1115 }
1116 hdr1 = &leaf1->hdr;
1117 hdr2 = &leaf2->hdr;
1118
1119 /*
1120 * Examine entries until we reduce the absolute difference in
1121 * byte usage between the two blocks to a minimum. Then get
1122 * the direction to copy and the number of elements to move.
1123 */
1124 state->inleaf = xfs_dir_leaf_figure_balance(state, blk1, blk2,
1125 &count, &totallen);
1126 if (swap)
1127 state->inleaf = !state->inleaf;
1128
1129 /*
1130 * Move any entries required from leaf to leaf:
1131 */
1132 if (count < INT_GET(hdr1->count, ARCH_CONVERT)) {
1133 /*
1134 * Figure the total bytes to be added to the destination leaf.
1135 */
1136 count = INT_GET(hdr1->count, ARCH_CONVERT) - count; /* number entries being moved */
1137 space = INT_GET(hdr1->namebytes, ARCH_CONVERT) - totallen;
1138 space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1);
1139 space += count * (uint)sizeof(xfs_dir_leaf_entry_t);
1140
1141 /*
1142 * leaf2 is the destination, compact it if it looks tight.
1143 */
1144 max = INT_GET(hdr2->firstused, ARCH_CONVERT) - (uint)sizeof(xfs_dir_leaf_hdr_t);
1145 max -= INT_GET(hdr2->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t);
1146 if (space > max) {
1147 xfs_dir_leaf_compact(state->args->trans, blk2->bp,
1148 0, 0);
1149 }
1150
1151 /*
1152 * Move high entries from leaf1 to low end of leaf2.
1153 */
1154 xfs_dir_leaf_moveents(leaf1, INT_GET(hdr1->count, ARCH_CONVERT) - count,
1155 leaf2, 0, count, state->mp);
1156
1157 xfs_da_log_buf(state->args->trans, blk1->bp, 0,
1158 state->blocksize-1);
1159 xfs_da_log_buf(state->args->trans, blk2->bp, 0,
1160 state->blocksize-1);
1161
1162 } else if (count > INT_GET(hdr1->count, ARCH_CONVERT)) {
1163 /*
1164 * Figure the total bytes to be added to the destination leaf.
1165 */
1166 count -= INT_GET(hdr1->count, ARCH_CONVERT); /* number entries being moved */
1167 space = totallen - INT_GET(hdr1->namebytes, ARCH_CONVERT);
1168 space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1);
1169 space += count * (uint)sizeof(xfs_dir_leaf_entry_t);
1170
1171 /*
1172 * leaf1 is the destination, compact it if it looks tight.
1173 */
1174 max = INT_GET(hdr1->firstused, ARCH_CONVERT) - (uint)sizeof(xfs_dir_leaf_hdr_t);
1175 max -= INT_GET(hdr1->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t);
1176 if (space > max) {
1177 xfs_dir_leaf_compact(state->args->trans, blk1->bp,
1178 0, 0);
1179 }
1180
1181 /*
1182 * Move low entries from leaf2 to high end of leaf1.
1183 */
1184 xfs_dir_leaf_moveents(leaf2, 0, leaf1, (int)INT_GET(hdr1->count, ARCH_CONVERT),
1185 count, state->mp);
1186
1187 xfs_da_log_buf(state->args->trans, blk1->bp, 0,
1188 state->blocksize-1);
1189 xfs_da_log_buf(state->args->trans, blk2->bp, 0,
1190 state->blocksize-1);
1191 }
1192
1193 /*
1194 * Copy out last hashval in each block for B-tree code.
1195 */
1196 blk1->hashval = INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
1197 blk2->hashval = INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
1198
1199 /*
1200 * Adjust the expected index for insertion.
1201 * GROT: this doesn't work unless blk2 was originally empty.
1202 */
1203 if (!state->inleaf) {
1204 blk2->index = blk1->index - INT_GET(leaf1->hdr.count, ARCH_CONVERT);
1205 }
1206}
1207
1208/*
1209 * Examine entries until we reduce the absolute difference in
1210 * byte usage between the two blocks to a minimum.
1211 * GROT: Is this really necessary? With other than a 512 byte blocksize,
1212 * GROT: there will always be enough room in either block for a new entry.
1213 * GROT: Do a double-split for this case?
1214 */
1215STATIC int
1216xfs_dir_leaf_figure_balance(xfs_da_state_t *state,
1217 xfs_da_state_blk_t *blk1,
1218 xfs_da_state_blk_t *blk2,
1219 int *countarg, int *namebytesarg)
1220{
1221 xfs_dir_leafblock_t *leaf1, *leaf2;
1222 xfs_dir_leaf_hdr_t *hdr1, *hdr2;
1223 xfs_dir_leaf_entry_t *entry;
1224 int count, max, totallen, half;
1225 int lastdelta, foundit, tmp;
1226
1227 /*
1228 * Set up environment.
1229 */
1230 leaf1 = blk1->bp->data;
1231 leaf2 = blk2->bp->data;
1232 hdr1 = &leaf1->hdr;
1233 hdr2 = &leaf2->hdr;
1234 foundit = 0;
1235 totallen = 0;
1236
1237 /*
1238 * Examine entries until we reduce the absolute difference in
1239 * byte usage between the two blocks to a minimum.
1240 */
1241 max = INT_GET(hdr1->count, ARCH_CONVERT) + INT_GET(hdr2->count, ARCH_CONVERT);
1242 half = (max+1) * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1);
1243 half += INT_GET(hdr1->namebytes, ARCH_CONVERT) + INT_GET(hdr2->namebytes, ARCH_CONVERT) + state->args->namelen;
1244 half /= 2;
1245 lastdelta = state->blocksize;
1246 entry = &leaf1->entries[0];
1247 for (count = 0; count < max; entry++, count++) {
1248
1249#define XFS_DIR_ABS(A) (((A) < 0) ? -(A) : (A))
1250 /*
1251 * The new entry is in the first block, account for it.
1252 */
1253 if (count == blk1->index) {
1254 tmp = totallen + (uint)sizeof(*entry)
1255 + XFS_DIR_LEAF_ENTSIZE_BYNAME(state->args->namelen);
1256 if (XFS_DIR_ABS(half - tmp) > lastdelta)
1257 break;
1258 lastdelta = XFS_DIR_ABS(half - tmp);
1259 totallen = tmp;
1260 foundit = 1;
1261 }
1262
1263 /*
1264 * Wrap around into the second block if necessary.
1265 */
1266 if (count == INT_GET(hdr1->count, ARCH_CONVERT)) {
1267 leaf1 = leaf2;
1268 entry = &leaf1->entries[0];
1269 }
1270
1271 /*
1272 * Figure out if next leaf entry would be too much.
1273 */
1274 tmp = totallen + (uint)sizeof(*entry)
1275 + XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry);
1276 if (XFS_DIR_ABS(half - tmp) > lastdelta)
1277 break;
1278 lastdelta = XFS_DIR_ABS(half - tmp);
1279 totallen = tmp;
1280#undef XFS_DIR_ABS
1281 }
1282
1283 /*
1284 * Calculate the number of namebytes that will end up in lower block.
1285 * If new entry not in lower block, fix up the count.
1286 */
1287 totallen -=
1288 count * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1);
1289 if (foundit) {
1290 totallen -= (sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1) +
1291 state->args->namelen;
1292 }
1293
1294 *countarg = count;
1295 *namebytesarg = totallen;
1296 return foundit;
1297}
1298
1299/*========================================================================
1300 * Routines used for shrinking the Btree.
1301 *========================================================================*/
1302
1303/*
1304 * Check a leaf block and its neighbors to see if the block should be
1305 * collapsed into one or the other neighbor. Always keep the block
1306 * with the smaller block number.
1307 * If the current block is over 50% full, don't try to join it, return 0.
1308 * If the block is empty, fill in the state structure and return 2.
1309 * If it can be collapsed, fill in the state structure and return 1.
1310 * If nothing can be done, return 0.
1311 */
1312int
1313xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action)
1314{
1315 xfs_dir_leafblock_t *leaf;
1316 xfs_da_state_blk_t *blk;
1317 xfs_da_blkinfo_t *info;
1318 int count, bytes, forward, error, retval, i;
1319 xfs_dablk_t blkno;
1320 xfs_dabuf_t *bp;
1321
1322 /*
1323 * Check for the degenerate case of the block being over 50% full.
1324 * If so, it's not worth even looking to see if we might be able
1325 * to coalesce with a sibling.
1326 */
1327 blk = &state->path.blk[ state->path.active-1 ];
1328 info = blk->bp->data;
1329 ASSERT(be16_to_cpu(info->magic) == XFS_DIR_LEAF_MAGIC);
1330 leaf = (xfs_dir_leafblock_t *)info;
1331 count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
1332 bytes = (uint)sizeof(xfs_dir_leaf_hdr_t) +
1333 count * (uint)sizeof(xfs_dir_leaf_entry_t) +
1334 count * ((uint)sizeof(xfs_dir_leaf_name_t)-1) +
1335 INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
1336 if (bytes > (state->blocksize >> 1)) {
1337 *action = 0; /* blk over 50%, don't try to join */
1338 return 0;
1339 }
1340
1341 /*
1342 * Check for the degenerate case of the block being empty.
1343 * If the block is empty, we'll simply delete it, no need to
1344 * coalesce it with a sibling block. We choose (arbitrarily)
1345 * to merge with the forward block unless it is NULL.
1346 */
1347 if (count == 0) {
1348 /*
1349 * Make altpath point to the block we want to keep and
1350 * path point to the block we want to drop (this one).
1351 */
1352 forward = (info->forw != 0);
1353 memcpy(&state->altpath, &state->path, sizeof(state->path));
1354 error = xfs_da_path_shift(state, &state->altpath, forward,
1355 0, &retval);
1356 if (error)
1357 return error;
1358 if (retval) {
1359 *action = 0;
1360 } else {
1361 *action = 2;
1362 }
1363 return 0;
1364 }
1365
1366 /*
1367 * Examine each sibling block to see if we can coalesce with
1368 * at least 25% free space to spare. We need to figure out
1369 * whether to merge with the forward or the backward block.
1370 * We prefer coalescing with the lower numbered sibling so as
1371 * to shrink a directory over time.
1372 */
1373 forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back)); /* start with smaller blk num */
1374 for (i = 0; i < 2; forward = !forward, i++) {
1375 if (forward)
1376 blkno = be32_to_cpu(info->forw);
1377 else
1378 blkno = be32_to_cpu(info->back);
1379 if (blkno == 0)
1380 continue;
1381 error = xfs_da_read_buf(state->args->trans, state->args->dp,
1382 blkno, -1, &bp,
1383 XFS_DATA_FORK);
1384 if (error)
1385 return error;
1386 ASSERT(bp != NULL);
1387
1388 leaf = (xfs_dir_leafblock_t *)info;
1389 count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
1390 bytes = state->blocksize - (state->blocksize>>2);
1391 bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
1392 leaf = bp->data;
1393 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1394 count += INT_GET(leaf->hdr.count, ARCH_CONVERT);
1395 bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
1396 bytes -= count * ((uint)sizeof(xfs_dir_leaf_name_t) - 1);
1397 bytes -= count * (uint)sizeof(xfs_dir_leaf_entry_t);
1398 bytes -= (uint)sizeof(xfs_dir_leaf_hdr_t);
1399 if (bytes >= 0)
1400 break; /* fits with at least 25% to spare */
1401
1402 xfs_da_brelse(state->args->trans, bp);
1403 }
1404 if (i >= 2) {
1405 *action = 0;
1406 return 0;
1407 }
1408 xfs_da_buf_done(bp);
1409
1410 /*
1411 * Make altpath point to the block we want to keep (the lower
1412 * numbered block) and path point to the block we want to drop.
1413 */
1414 memcpy(&state->altpath, &state->path, sizeof(state->path));
1415 if (blkno < blk->blkno) {
1416 error = xfs_da_path_shift(state, &state->altpath, forward,
1417 0, &retval);
1418 } else {
1419 error = xfs_da_path_shift(state, &state->path, forward,
1420 0, &retval);
1421 }
1422 if (error)
1423 return error;
1424 if (retval) {
1425 *action = 0;
1426 } else {
1427 *action = 1;
1428 }
1429 return 0;
1430}
1431
1432/*
1433 * Remove a name from the leaf directory structure.
1434 *
1435 * Return 1 if leaf is less than 37% full, 0 if >= 37% full.
1436 * If two leaves are 37% full, when combined they will leave 25% free.
1437 */
1438int
1439xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index)
1440{
1441 xfs_dir_leafblock_t *leaf;
1442 xfs_dir_leaf_hdr_t *hdr;
1443 xfs_dir_leaf_map_t *map;
1444 xfs_dir_leaf_entry_t *entry;
1445 xfs_dir_leaf_name_t *namest;
1446 int before, after, smallest, entsize;
1447 int tablesize, tmp, i;
1448 xfs_mount_t *mp;
1449
1450 leaf = bp->data;
1451 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1452 hdr = &leaf->hdr;
1453 mp = trans->t_mountp;
1454 ASSERT((INT_GET(hdr->count, ARCH_CONVERT) > 0) && (INT_GET(hdr->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8)));
1455 ASSERT((index >= 0) && (index < INT_GET(hdr->count, ARCH_CONVERT)));
1456 ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) >= ((INT_GET(hdr->count, ARCH_CONVERT)*sizeof(*entry))+sizeof(*hdr)));
1457 entry = &leaf->entries[index];
1458 ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= INT_GET(hdr->firstused, ARCH_CONVERT));
1459 ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp));
1460
1461 /*
1462 * Scan through free region table:
1463 * check for adjacency of free'd entry with an existing one,
1464 * find smallest free region in case we need to replace it,
1465 * adjust any map that borders the entry table,
1466 */
1467 tablesize = INT_GET(hdr->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t)
1468 + (uint)sizeof(xfs_dir_leaf_hdr_t);
1469 map = &hdr->freemap[0];
1470 tmp = INT_GET(map->size, ARCH_CONVERT);
1471 before = after = -1;
1472 smallest = XFS_DIR_LEAF_MAPSIZE - 1;
1473 entsize = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry);
1474 for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) {
1475 ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp));
1476 ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp));
1477 if (INT_GET(map->base, ARCH_CONVERT) == tablesize) {
1478 INT_MOD(map->base, ARCH_CONVERT, -((uint)sizeof(xfs_dir_leaf_entry_t)));
1479 INT_MOD(map->size, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_entry_t));
1480 }
1481
1482 if ((INT_GET(map->base, ARCH_CONVERT) + INT_GET(map->size, ARCH_CONVERT)) == INT_GET(entry->nameidx, ARCH_CONVERT)) {
1483 before = i;
1484 } else if (INT_GET(map->base, ARCH_CONVERT) == (INT_GET(entry->nameidx, ARCH_CONVERT) + entsize)) {
1485 after = i;
1486 } else if (INT_GET(map->size, ARCH_CONVERT) < tmp) {
1487 tmp = INT_GET(map->size, ARCH_CONVERT);
1488 smallest = i;
1489 }
1490 }
1491
1492 /*
1493 * Coalesce adjacent freemap regions,
1494 * or replace the smallest region.
1495 */
1496 if ((before >= 0) || (after >= 0)) {
1497 if ((before >= 0) && (after >= 0)) {
1498 map = &hdr->freemap[before];
1499 INT_MOD(map->size, ARCH_CONVERT, entsize);
1500 INT_MOD(map->size, ARCH_CONVERT, INT_GET(hdr->freemap[after].size, ARCH_CONVERT));
1501 hdr->freemap[after].base = 0;
1502 hdr->freemap[after].size = 0;
1503 } else if (before >= 0) {
1504 map = &hdr->freemap[before];
1505 INT_MOD(map->size, ARCH_CONVERT, entsize);
1506 } else {
1507 map = &hdr->freemap[after];
1508 INT_COPY(map->base, entry->nameidx, ARCH_CONVERT);
1509 INT_MOD(map->size, ARCH_CONVERT, entsize);
1510 }
1511 } else {
1512 /*
1513 * Replace smallest region (if it is smaller than free'd entry)
1514 */
1515 map = &hdr->freemap[smallest];
1516 if (INT_GET(map->size, ARCH_CONVERT) < entsize) {
1517 INT_COPY(map->base, entry->nameidx, ARCH_CONVERT);
1518 INT_SET(map->size, ARCH_CONVERT, entsize);
1519 }
1520 }
1521
1522 /*
1523 * Did we remove the first entry?
1524 */
1525 if (INT_GET(entry->nameidx, ARCH_CONVERT) == INT_GET(hdr->firstused, ARCH_CONVERT))
1526 smallest = 1;
1527 else
1528 smallest = 0;
1529
1530 /*
1531 * Compress the remaining entries and zero out the removed stuff.
1532 */
1533 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
1534 memset((char *)namest, 0, entsize);
1535 xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, namest, entsize));
1536
1537 INT_MOD(hdr->namebytes, ARCH_CONVERT, -(entry->namelen));
1538 tmp = (INT_GET(hdr->count, ARCH_CONVERT) - index) * (uint)sizeof(xfs_dir_leaf_entry_t);
1539 memmove(entry, entry + 1, tmp);
1540 INT_MOD(hdr->count, ARCH_CONVERT, -1);
1541 xfs_da_log_buf(trans, bp,
1542 XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry)));
1543 entry = &leaf->entries[INT_GET(hdr->count, ARCH_CONVERT)];
1544 memset((char *)entry, 0, sizeof(xfs_dir_leaf_entry_t));
1545
1546 /*
1547 * If we removed the first entry, re-find the first used byte
1548 * in the name area. Note that if the entry was the "firstused",
1549 * then we don't have a "hole" in our block resulting from
1550 * removing the name.
1551 */
1552 if (smallest) {
1553 tmp = XFS_LBSIZE(mp);
1554 entry = &leaf->entries[0];
1555 for (i = INT_GET(hdr->count, ARCH_CONVERT)-1; i >= 0; entry++, i--) {
1556 ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= INT_GET(hdr->firstused, ARCH_CONVERT));
1557 ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp));
1558 if (INT_GET(entry->nameidx, ARCH_CONVERT) < tmp)
1559 tmp = INT_GET(entry->nameidx, ARCH_CONVERT);
1560 }
1561 INT_SET(hdr->firstused, ARCH_CONVERT, tmp);
1562 if (!hdr->firstused)
1563 INT_SET(hdr->firstused, ARCH_CONVERT, tmp - 1);
1564 } else {
1565 hdr->holes = 1; /* mark as needing compaction */
1566 }
1567
1568 xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));
1569
1570 /*
1571 * Check if leaf is less than 50% full, caller may want to
1572 * "join" the leaf with a sibling if so.
1573 */
1574 tmp = (uint)sizeof(xfs_dir_leaf_hdr_t);
1575 tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t);
1576 tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * ((uint)sizeof(xfs_dir_leaf_name_t) - 1);
1577 tmp += INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
1578 if (tmp < mp->m_dir_magicpct)
1579 return 1; /* leaf is < 37% full */
1580 return 0;
1581}
1582
1583/*
1584 * Move all the directory entries from drop_leaf into save_leaf.
1585 */
1586void
1587xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
1588 xfs_da_state_blk_t *save_blk)
1589{
1590 xfs_dir_leafblock_t *drop_leaf, *save_leaf, *tmp_leaf;
1591 xfs_dir_leaf_hdr_t *drop_hdr, *save_hdr, *tmp_hdr;
1592 xfs_mount_t *mp;
1593 char *tmpbuffer;
1594
1595 /*
1596 * Set up environment.
1597 */
1598 mp = state->mp;
1599 ASSERT(drop_blk->magic == XFS_DIR_LEAF_MAGIC);
1600 ASSERT(save_blk->magic == XFS_DIR_LEAF_MAGIC);
1601 drop_leaf = drop_blk->bp->data;
1602 save_leaf = save_blk->bp->data;
1603 ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1604 ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1605 drop_hdr = &drop_leaf->hdr;
1606 save_hdr = &save_leaf->hdr;
1607
1608 /*
1609 * Save last hashval from dying block for later Btree fixup.
1610 */
1611 drop_blk->hashval = INT_GET(drop_leaf->entries[ drop_leaf->hdr.count-1 ].hashval, ARCH_CONVERT);
1612
1613 /*
1614 * Check if we need a temp buffer, or can we do it in place.
1615 * Note that we don't check "leaf" for holes because we will
1616 * always be dropping it, toosmall() decided that for us already.
1617 */
1618 if (save_hdr->holes == 0) {
1619 /*
1620 * dest leaf has no holes, so we add there. May need
1621 * to make some room in the entry array.
1622 */
1623 if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) {
1624 xfs_dir_leaf_moveents(drop_leaf, 0, save_leaf, 0,
1625 (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp);
1626 } else {
1627 xfs_dir_leaf_moveents(drop_leaf, 0,
1628 save_leaf, INT_GET(save_hdr->count, ARCH_CONVERT),
1629 (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp);
1630 }
1631 } else {
1632 /*
1633 * Destination has holes, so we make a temporary copy
1634 * of the leaf and add them both to that.
1635 */
1636 tmpbuffer = kmem_alloc(state->blocksize, KM_SLEEP);
1637 ASSERT(tmpbuffer != NULL);
1638 memset(tmpbuffer, 0, state->blocksize);
1639 tmp_leaf = (xfs_dir_leafblock_t *)tmpbuffer;
1640 tmp_hdr = &tmp_leaf->hdr;
1641 tmp_hdr->info = save_hdr->info; /* struct copy */
1642 tmp_hdr->count = 0;
1643 INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize);
1644 if (!tmp_hdr->firstused)
1645 INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize - 1);
1646 tmp_hdr->namebytes = 0;
1647 if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) {
1648 xfs_dir_leaf_moveents(drop_leaf, 0, tmp_leaf, 0,
1649 (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp);
1650 xfs_dir_leaf_moveents(save_leaf, 0,
1651 tmp_leaf, INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT),
1652 (int)INT_GET(save_hdr->count, ARCH_CONVERT), mp);
1653 } else {
1654 xfs_dir_leaf_moveents(save_leaf, 0, tmp_leaf, 0,
1655 (int)INT_GET(save_hdr->count, ARCH_CONVERT), mp);
1656 xfs_dir_leaf_moveents(drop_leaf, 0,
1657 tmp_leaf, INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT),
1658 (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp);
1659 }
1660 memcpy(save_leaf, tmp_leaf, state->blocksize);
1661 kmem_free(tmpbuffer, state->blocksize);
1662 }
1663
1664 xfs_da_log_buf(state->args->trans, save_blk->bp, 0,
1665 state->blocksize - 1);
1666
1667 /*
1668 * Copy out last hashval in each block for B-tree code.
1669 */
1670 save_blk->hashval = INT_GET(save_leaf->entries[ INT_GET(save_leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
1671}
1672
1673/*========================================================================
1674 * Routines used for finding things in the Btree.
1675 *========================================================================*/
1676
1677/*
1678 * Look up a name in a leaf directory structure.
1679 * This is the internal routine, it uses the caller's buffer.
1680 *
1681 * Note that duplicate keys are allowed, but only check within the
1682 * current leaf node. The Btree code must check in adjacent leaf nodes.
1683 *
1684 * Return in *index the index into the entry[] array of either the found
1685 * entry, or where the entry should have been (insert before that entry).
1686 *
1687 * Don't change the args->inumber unless we find the filename.
1688 */
1689int
1690xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index)
1691{
1692 xfs_dir_leafblock_t *leaf;
1693 xfs_dir_leaf_entry_t *entry;
1694 xfs_dir_leaf_name_t *namest;
1695 int probe, span;
1696 xfs_dahash_t hashval;
1697
1698 leaf = bp->data;
1699 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1700 ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) < (XFS_LBSIZE(args->dp->i_mount)/8));
1701
1702 /*
1703 * Binary search. (note: small blocks will skip this loop)
1704 */
1705 hashval = args->hashval;
1706 probe = span = INT_GET(leaf->hdr.count, ARCH_CONVERT) / 2;
1707 for (entry = &leaf->entries[probe]; span > 4;
1708 entry = &leaf->entries[probe]) {
1709 span /= 2;
1710 if (INT_GET(entry->hashval, ARCH_CONVERT) < hashval)
1711 probe += span;
1712 else if (INT_GET(entry->hashval, ARCH_CONVERT) > hashval)
1713 probe -= span;
1714 else
1715 break;
1716 }
1717 ASSERT((probe >= 0) && \
1718 ((!leaf->hdr.count) || (probe < INT_GET(leaf->hdr.count, ARCH_CONVERT))));
1719 ASSERT((span <= 4) || (INT_GET(entry->hashval, ARCH_CONVERT) == hashval));
1720
1721 /*
1722 * Since we may have duplicate hashval's, find the first matching
1723 * hashval in the leaf.
1724 */
1725 while ((probe > 0) && (INT_GET(entry->hashval, ARCH_CONVERT) >= hashval)) {
1726 entry--;
1727 probe--;
1728 }
1729 while ((probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) && (INT_GET(entry->hashval, ARCH_CONVERT) < hashval)) {
1730 entry++;
1731 probe++;
1732 }
1733 if ((probe == INT_GET(leaf->hdr.count, ARCH_CONVERT)) || (INT_GET(entry->hashval, ARCH_CONVERT) != hashval)) {
1734 *index = probe;
1735 ASSERT(args->oknoent);
1736 return XFS_ERROR(ENOENT);
1737 }
1738
1739 /*
1740 * Duplicate keys may be present, so search all of them for a match.
1741 */
1742 while ((probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) && (INT_GET(entry->hashval, ARCH_CONVERT) == hashval)) {
1743 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
1744 if (entry->namelen == args->namelen &&
1745 namest->name[0] == args->name[0] &&
1746 memcmp(args->name, namest->name, args->namelen) == 0) {
1747 XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args->inumber);
1748 *index = probe;
1749 return XFS_ERROR(EEXIST);
1750 }
1751 entry++;
1752 probe++;
1753 }
1754 *index = probe;
1755 ASSERT(probe == INT_GET(leaf->hdr.count, ARCH_CONVERT) || args->oknoent);
1756 return XFS_ERROR(ENOENT);
1757}
1758
1759/*========================================================================
1760 * Utility routines.
1761 *========================================================================*/
1762
1763/*
1764 * Move the indicated entries from one leaf to another.
1765 * NOTE: this routine modifies both source and destination leaves.
1766 */
1767/* ARGSUSED */
1768STATIC void
1769xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s,
1770 xfs_dir_leafblock_t *leaf_d, int start_d,
1771 int count, xfs_mount_t *mp)
1772{
1773 xfs_dir_leaf_hdr_t *hdr_s, *hdr_d;
1774 xfs_dir_leaf_entry_t *entry_s, *entry_d;
1775 int tmp, i;
1776
1777 /*
1778 * Check for nothing to do.
1779 */
1780 if (count == 0)
1781 return;
1782
1783 /*
1784 * Set up environment.
1785 */
1786 ASSERT(be16_to_cpu(leaf_s->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1787 ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1788 hdr_s = &leaf_s->hdr;
1789 hdr_d = &leaf_d->hdr;
1790 ASSERT((INT_GET(hdr_s->count, ARCH_CONVERT) > 0) && (INT_GET(hdr_s->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8)));
1791 ASSERT(INT_GET(hdr_s->firstused, ARCH_CONVERT) >=
1792 ((INT_GET(hdr_s->count, ARCH_CONVERT)*sizeof(*entry_s))+sizeof(*hdr_s)));
1793 ASSERT(INT_GET(hdr_d->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8));
1794 ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >=
1795 ((INT_GET(hdr_d->count, ARCH_CONVERT)*sizeof(*entry_d))+sizeof(*hdr_d)));
1796
1797 ASSERT(start_s < INT_GET(hdr_s->count, ARCH_CONVERT));
1798 ASSERT(start_d <= INT_GET(hdr_d->count, ARCH_CONVERT));
1799 ASSERT(count <= INT_GET(hdr_s->count, ARCH_CONVERT));
1800
1801 /*
1802 * Move the entries in the destination leaf up to make a hole?
1803 */
1804 if (start_d < INT_GET(hdr_d->count, ARCH_CONVERT)) {
1805 tmp = INT_GET(hdr_d->count, ARCH_CONVERT) - start_d;
1806 tmp *= (uint)sizeof(xfs_dir_leaf_entry_t);
1807 entry_s = &leaf_d->entries[start_d];
1808 entry_d = &leaf_d->entries[start_d + count];
1809 memcpy(entry_d, entry_s, tmp);
1810 }
1811
1812 /*
1813 * Copy all entry's in the same (sorted) order,
1814 * but allocate filenames packed and in sequence.
1815 */
1816 entry_s = &leaf_s->entries[start_s];
1817 entry_d = &leaf_d->entries[start_d];
1818 for (i = 0; i < count; entry_s++, entry_d++, i++) {
1819 ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) >= INT_GET(hdr_s->firstused, ARCH_CONVERT));
1820 tmp = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry_s);
1821 INT_MOD(hdr_d->firstused, ARCH_CONVERT, -(tmp));
1822 entry_d->hashval = entry_s->hashval; /* INT_: direct copy */
1823 INT_COPY(entry_d->nameidx, hdr_d->firstused, ARCH_CONVERT);
1824 entry_d->namelen = entry_s->namelen;
1825 ASSERT(INT_GET(entry_d->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp));
1826 memcpy(XFS_DIR_LEAF_NAMESTRUCT(leaf_d, INT_GET(entry_d->nameidx, ARCH_CONVERT)),
1827 XFS_DIR_LEAF_NAMESTRUCT(leaf_s, INT_GET(entry_s->nameidx, ARCH_CONVERT)), tmp);
1828 ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp));
1829 memset((char *)XFS_DIR_LEAF_NAMESTRUCT(leaf_s, INT_GET(entry_s->nameidx, ARCH_CONVERT)),
1830 0, tmp);
1831 INT_MOD(hdr_s->namebytes, ARCH_CONVERT, -(entry_d->namelen));
1832 INT_MOD(hdr_d->namebytes, ARCH_CONVERT, entry_d->namelen);
1833 INT_MOD(hdr_s->count, ARCH_CONVERT, -1);
1834 INT_MOD(hdr_d->count, ARCH_CONVERT, +1);
1835 tmp = INT_GET(hdr_d->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t)
1836 + (uint)sizeof(xfs_dir_leaf_hdr_t);
1837 ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >= tmp);
1838
1839 }
1840
1841 /*
1842 * Zero out the entries we just copied.
1843 */
1844 if (start_s == INT_GET(hdr_s->count, ARCH_CONVERT)) {
1845 tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t);
1846 entry_s = &leaf_s->entries[start_s];
1847 ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp));
1848 memset((char *)entry_s, 0, tmp);
1849 } else {
1850 /*
1851 * Move the remaining entries down to fill the hole,
1852 * then zero the entries at the top.
1853 */
1854 tmp = INT_GET(hdr_s->count, ARCH_CONVERT) - count;
1855 tmp *= (uint)sizeof(xfs_dir_leaf_entry_t);
1856 entry_s = &leaf_s->entries[start_s + count];
1857 entry_d = &leaf_s->entries[start_s];
1858 memcpy(entry_d, entry_s, tmp);
1859
1860 tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t);
1861 entry_s = &leaf_s->entries[INT_GET(hdr_s->count, ARCH_CONVERT)];
1862 ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp));
1863 memset((char *)entry_s, 0, tmp);
1864 }
1865
1866 /*
1867 * Fill in the freemap information
1868 */
1869 INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_hdr_t));
1870 INT_MOD(hdr_d->freemap[0].base, ARCH_CONVERT, INT_GET(hdr_d->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t));
1871 INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, INT_GET(hdr_d->firstused, ARCH_CONVERT) - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT));
1872 INT_SET(hdr_d->freemap[1].base, ARCH_CONVERT, (hdr_d->freemap[2].base = 0));
1873 INT_SET(hdr_d->freemap[1].size, ARCH_CONVERT, (hdr_d->freemap[2].size = 0));
1874 hdr_s->holes = 1; /* leaf may not be compact */
1875}
1876
1877/*
1878 * Compare two leaf blocks "order".
1879 */
1880int
1881xfs_dir_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp)
1882{
1883 xfs_dir_leafblock_t *leaf1, *leaf2;
1884
1885 leaf1 = leaf1_bp->data;
1886 leaf2 = leaf2_bp->data;
1887 ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC) &&
1888 (be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC));
1889 if ((INT_GET(leaf1->hdr.count, ARCH_CONVERT) > 0) && (INT_GET(leaf2->hdr.count, ARCH_CONVERT) > 0) &&
1890 ((INT_GET(leaf2->entries[ 0 ].hashval, ARCH_CONVERT) <
1891 INT_GET(leaf1->entries[ 0 ].hashval, ARCH_CONVERT)) ||
1892 (INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) <
1893 INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)))) {
1894 return 1;
1895 }
1896 return 0;
1897}
1898
1899/*
1900 * Pick up the last hashvalue from a leaf block.
1901 */
1902xfs_dahash_t
1903xfs_dir_leaf_lasthash(xfs_dabuf_t *bp, int *count)
1904{
1905 xfs_dir_leafblock_t *leaf;
1906
1907 leaf = bp->data;
1908 ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
1909 if (count)
1910 *count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
1911 if (!leaf->hdr.count)
1912 return(0);
1913 return(INT_GET(leaf->entries[ INT_GET(leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT));
1914}
1915
1916/*
1917 * Copy out directory entries for getdents(), for leaf directories.
1918 */
1919int
1920xfs_dir_leaf_getdents_int(
1921 xfs_dabuf_t *bp,
1922 xfs_inode_t *dp,
1923 xfs_dablk_t bno,
1924 uio_t *uio,
1925 int *eobp,
1926 xfs_dirent_t *dbp,
1927 xfs_dir_put_t put,
1928 xfs_daddr_t nextda)
1929{
1930 xfs_dir_leafblock_t *leaf;
1931 xfs_dir_leaf_entry_t *entry;
1932 xfs_dir_leaf_name_t *namest;
1933 int entno, want_entno, i, nextentno;
1934 xfs_mount_t *mp;
1935 xfs_dahash_t cookhash;
1936 xfs_dahash_t nexthash = 0;
1937#if (BITS_PER_LONG == 32)
1938 xfs_dahash_t lasthash = XFS_DA_MAXHASH;
1939#endif
1940 xfs_dir_put_args_t p;
1941
1942 mp = dp->i_mount;
1943 leaf = bp->data;
1944 if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) {
1945 *eobp = 1;
1946 return XFS_ERROR(ENOENT); /* XXX wrong code */
1947 }
1948
1949 want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset);
1950
1951 cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset);
1952
1953 xfs_dir_trace_g_dul("leaf: start", dp, uio, leaf);
1954
1955 /*
1956 * Re-find our place.
1957 */
1958 for (i = entno = 0, entry = &leaf->entries[0];
1959 i < INT_GET(leaf->hdr.count, ARCH_CONVERT);
1960 entry++, i++) {
1961
1962 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
1963 INT_GET(entry->nameidx, ARCH_CONVERT));
1964
1965 if (unlikely(
1966 ((char *)namest < (char *)leaf) ||
1967 ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) {
1968 XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(1)",
1969 XFS_ERRLEVEL_LOW, mp, leaf);
1970 xfs_dir_trace_g_du("leaf: corrupted", dp, uio);
1971 return XFS_ERROR(EFSCORRUPTED);
1972 }
1973 if (INT_GET(entry->hashval, ARCH_CONVERT) >= cookhash) {
1974 if ( entno < want_entno
1975 && INT_GET(entry->hashval, ARCH_CONVERT)
1976 == cookhash) {
1977 /*
1978 * Trying to get to a particular offset in a
1979 * run of equal-hashval entries.
1980 */
1981 entno++;
1982 } else if ( want_entno > 0
1983 && entno == want_entno
1984 && INT_GET(entry->hashval, ARCH_CONVERT)
1985 == cookhash) {
1986 break;
1987 } else {
1988 entno = 0;
1989 break;
1990 }
1991 }
1992 }
1993
1994 if (i == INT_GET(leaf->hdr.count, ARCH_CONVERT)) {
1995 xfs_dir_trace_g_du("leaf: hash not found", dp, uio);
1996 if (!leaf->hdr.info.forw)
1997 uio->uio_offset =
1998 XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH);
1999 /*
2000 * Don't set uio_offset if there's another block:
2001 * the node code will be setting uio_offset anyway.
2002 */
2003 *eobp = 0;
2004 return 0;
2005 }
2006 xfs_dir_trace_g_due("leaf: hash found", dp, uio, entry);
2007
2008 p.dbp = dbp;
2009 p.put = put;
2010 p.uio = uio;
2011
2012 /*
2013 * We're synchronized, start copying entries out to the user.
2014 */
2015 for (; entno >= 0 && i < INT_GET(leaf->hdr.count, ARCH_CONVERT);
2016 entry++, i++, (entno = nextentno)) {
2017 int lastresid=0, retval;
2018 xfs_dircook_t lastoffset;
2019 xfs_dahash_t thishash;
2020
2021 /*
2022 * Check for a damaged directory leaf block and pick up
2023 * the inode number from this entry.
2024 */
2025 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
2026 INT_GET(entry->nameidx, ARCH_CONVERT));
2027
2028 if (unlikely(
2029 ((char *)namest < (char *)leaf) ||
2030 ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) {
2031 XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(2)",
2032 XFS_ERRLEVEL_LOW, mp, leaf);
2033 xfs_dir_trace_g_du("leaf: corrupted", dp, uio);
2034 return XFS_ERROR(EFSCORRUPTED);
2035 }
2036
2037 xfs_dir_trace_g_duc("leaf: middle cookie ",
2038 dp, uio, p.cook.o);
2039
2040 if (i < (INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1)) {
2041 nexthash = INT_GET(entry[1].hashval, ARCH_CONVERT);
2042
2043 if (nexthash == INT_GET(entry->hashval, ARCH_CONVERT))
2044 nextentno = entno + 1;
2045 else
2046 nextentno = 0;
2047 XFS_PUT_COOKIE(p.cook, mp, bno, nextentno, nexthash);
2048 xfs_dir_trace_g_duc("leaf: middle cookie ",
2049 dp, uio, p.cook.o);
2050
2051 } else if ((thishash = be32_to_cpu(leaf->hdr.info.forw))) {
2052 xfs_dabuf_t *bp2;
2053 xfs_dir_leafblock_t *leaf2;
2054
2055 ASSERT(nextda != -1);
2056
2057 retval = xfs_da_read_buf(dp->i_transp, dp, thishash,
2058 nextda, &bp2, XFS_DATA_FORK);
2059 if (retval)
2060 return retval;
2061
2062 ASSERT(bp2 != NULL);
2063
2064 leaf2 = bp2->data;
2065
2066 if (unlikely(
2067 (be16_to_cpu(leaf2->hdr.info.magic)
2068 != XFS_DIR_LEAF_MAGIC)
2069 || (be32_to_cpu(leaf2->hdr.info.back)
2070 != bno))) { /* GROT */
2071 XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(3)",
2072 XFS_ERRLEVEL_LOW, mp,
2073 leaf2);
2074 xfs_da_brelse(dp->i_transp, bp2);
2075
2076 return XFS_ERROR(EFSCORRUPTED);
2077 }
2078
2079 nexthash = INT_GET(leaf2->entries[0].hashval,
2080 ARCH_CONVERT);
2081 nextentno = -1;
2082 XFS_PUT_COOKIE(p.cook, mp, thishash, 0, nexthash);
2083 xfs_da_brelse(dp->i_transp, bp2);
2084 xfs_dir_trace_g_duc("leaf: next blk cookie",
2085 dp, uio, p.cook.o);
2086 } else {
2087 nextentno = -1;
2088 XFS_PUT_COOKIE(p.cook, mp, 0, 0, XFS_DA_MAXHASH);
2089 }
2090
2091 /*
2092 * Save off the cookie so we can fall back should the
2093 * 'put' into the outgoing buffer fails. To handle a run
2094 * of equal-hashvals, the off_t structure on 64bit
2095 * builds has entno built into the cookie to ID the
2096 * entry. On 32bit builds, we only have space for the
2097 * hashval so we can't ID specific entries within a group
2098 * of same hashval entries. For this, lastoffset is set
2099 * to the first in the run of equal hashvals so we don't
2100 * include any entries unless we can include all entries
2101 * that share the same hashval. Hopefully the buffer
2102 * provided is big enough to handle it (see pv763517).
2103 */
2104#if (BITS_PER_LONG == 32)
2105 if ((thishash = INT_GET(entry->hashval, ARCH_CONVERT))
2106 != lasthash) {
2107 XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash);
2108 lastresid = uio->uio_resid;
2109 lasthash = thishash;
2110 } else {
2111 xfs_dir_trace_g_duc("leaf: DUP COOKIES, skipped",
2112 dp, uio, p.cook.o);
2113 }
2114#else
2115 thishash = INT_GET(entry->hashval, ARCH_CONVERT);
2116 XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash);
2117 lastresid = uio->uio_resid;
2118#endif /* BITS_PER_LONG == 32 */
2119
2120 /*
2121 * Put the current entry into the outgoing buffer. If we fail
2122 * then restore the UIO to the first entry in the current
2123 * run of equal-hashval entries (probably one 1 entry long).
2124 */
2125 p.ino = XFS_GET_DIR_INO8(namest->inumber);
2126#if XFS_BIG_INUMS
2127 p.ino += mp->m_inoadd;
2128#endif
2129 p.name = (char *)namest->name;
2130 p.namelen = entry->namelen;
2131
2132 retval = p.put(&p);
2133
2134 if (!p.done) {
2135 uio->uio_offset = lastoffset.o;
2136 uio->uio_resid = lastresid;
2137
2138 *eobp = 1;
2139
2140 xfs_dir_trace_g_du("leaf: E-O-B", dp, uio);
2141
2142 return retval;
2143 }
2144 }
2145
2146 uio->uio_offset = p.cook.o;
2147
2148 *eobp = 0;
2149
2150 xfs_dir_trace_g_du("leaf: E-O-F", dp, uio);
2151
2152 return 0;
2153}
2154
2155/*
2156 * Format a dirent64 structure and copy it out the the user's buffer.
2157 */
2158int
2159xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa)
2160{
2161 iovec_t *iovp;
2162 int reclen, namelen;
2163 xfs_dirent_t *idbp;
2164 uio_t *uio;
2165
2166 namelen = pa->namelen;
2167 reclen = DIRENTSIZE(namelen);
2168 uio = pa->uio;
2169 if (reclen > uio->uio_resid) {
2170 pa->done = 0;
2171 return 0;
2172 }
2173 iovp = uio->uio_iov;
2174 idbp = (xfs_dirent_t *)iovp->iov_base;
2175 iovp->iov_base = (char *)idbp + reclen;
2176 iovp->iov_len -= reclen;
2177 uio->uio_resid -= reclen;
2178 idbp->d_reclen = reclen;
2179 idbp->d_ino = pa->ino;
2180 idbp->d_off = pa->cook.o;
2181 idbp->d_name[namelen] = '\0';
2182 pa->done = 1;
2183 memcpy(idbp->d_name, pa->name, namelen);
2184 return 0;
2185}
2186
2187/*
2188 * Format a dirent64 structure and copy it out the the user's buffer.
2189 */
2190int
2191xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa)
2192{
2193 int retval, reclen, namelen;
2194 xfs_dirent_t *idbp;
2195 uio_t *uio;
2196
2197 namelen = pa->namelen;
2198 reclen = DIRENTSIZE(namelen);
2199 uio = pa->uio;
2200 if (reclen > uio->uio_resid) {
2201 pa->done = 0;
2202 return 0;
2203 }
2204 idbp = pa->dbp;
2205 idbp->d_reclen = reclen;
2206 idbp->d_ino = pa->ino;
2207 idbp->d_off = pa->cook.o;
2208 idbp->d_name[namelen] = '\0';
2209 memcpy(idbp->d_name, pa->name, namelen);
2210 retval = uio_read((caddr_t)idbp, reclen, uio);
2211 pa->done = (retval == 0);
2212 return retval;
2213}
diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h
deleted file mode 100644
index eb8cd9a4667f..000000000000
--- a/fs/xfs/xfs_dir_leaf.h
+++ /dev/null
@@ -1,231 +0,0 @@
1/*
2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#ifndef __XFS_DIR_LEAF_H__
19#define __XFS_DIR_LEAF_H__
20
21/*
22 * Directory layout, internal structure, access macros, etc.
23 *
24 * Large directories are structured around Btrees where all the data
25 * elements are in the leaf nodes. Filenames are hashed into an int,
26 * then that int is used as the index into the Btree. Since the hashval
27 * of a filename may not be unique, we may have duplicate keys. The
28 * internal links in the Btree are logical block offsets into the file.
29 */
30
31struct uio;
32struct xfs_bmap_free;
33struct xfs_dabuf;
34struct xfs_da_args;
35struct xfs_da_state;
36struct xfs_da_state_blk;
37struct xfs_dir_put_args;
38struct xfs_inode;
39struct xfs_mount;
40struct xfs_trans;
41
42/*========================================================================
43 * Directory Structure when equal to XFS_LBSIZE(mp) bytes.
44 *========================================================================*/
45
46/*
47 * This is the structure of the leaf nodes in the Btree.
48 *
49 * Struct leaf_entry's are packed from the top. Names grow from the bottom
50 * but are not packed. The freemap contains run-length-encoded entries
51 * for the free bytes after the leaf_entry's, but only the N largest such,
52 * smaller runs are dropped. When the freemap doesn't show enough space
53 * for an allocation, we compact the namelist area and try again. If we
54 * still don't have enough space, then we have to split the block.
55 *
56 * Since we have duplicate hash keys, for each key that matches, compare
57 * the actual string. The root and intermediate node search always takes
58 * the first-in-the-block key match found, so we should only have to work
59 * "forw"ard. If none matches, continue with the "forw"ard leaf nodes
60 * until the hash key changes or the filename is found.
61 *
62 * The parent directory and the self-pointer are explicitly represented
63 * (ie: there are entries for "." and "..").
64 *
65 * Note that the count being a __uint16_t limits us to something like a
66 * blocksize of 1.3MB in the face of worst case (short) filenames.
67 */
68#define XFS_DIR_LEAF_MAPSIZE 3 /* how many freespace slots */
69
70typedef struct xfs_dir_leaf_map { /* RLE map of free bytes */
71 __uint16_t base; /* base of free region */
72 __uint16_t size; /* run length of free region */
73} xfs_dir_leaf_map_t;
74
75typedef struct xfs_dir_leaf_hdr { /* constant-structure header block */
76 xfs_da_blkinfo_t info; /* block type, links, etc. */
77 __uint16_t count; /* count of active leaf_entry's */
78 __uint16_t namebytes; /* num bytes of name strings stored */
79 __uint16_t firstused; /* first used byte in name area */
80 __uint8_t holes; /* != 0 if blk needs compaction */
81 __uint8_t pad1;
82 xfs_dir_leaf_map_t freemap[XFS_DIR_LEAF_MAPSIZE];
83} xfs_dir_leaf_hdr_t;
84
85typedef struct xfs_dir_leaf_entry { /* sorted on key, not name */
86 xfs_dahash_t hashval; /* hash value of name */
87 __uint16_t nameidx; /* index into buffer of name */
88 __uint8_t namelen; /* length of name string */
89 __uint8_t pad2;
90} xfs_dir_leaf_entry_t;
91
92typedef struct xfs_dir_leaf_name {
93 xfs_dir_ino_t inumber; /* inode number for this key */
94 __uint8_t name[1]; /* name string itself */
95} xfs_dir_leaf_name_t;
96
97typedef struct xfs_dir_leafblock {
98 xfs_dir_leaf_hdr_t hdr; /* constant-structure header block */
99 xfs_dir_leaf_entry_t entries[1]; /* var sized array */
100 xfs_dir_leaf_name_t namelist[1]; /* grows from bottom of buf */
101} xfs_dir_leafblock_t;
102
103/*
104 * Length of name for which a 512-byte block filesystem
105 * can get a double split.
106 */
107#define XFS_DIR_LEAF_CAN_DOUBLE_SPLIT_LEN \
108 (512 - (uint)sizeof(xfs_dir_leaf_hdr_t) - \
109 (uint)sizeof(xfs_dir_leaf_entry_t) * 2 - \
110 (uint)sizeof(xfs_dir_leaf_name_t) * 2 - (MAXNAMELEN - 2) + 1 + 1)
111
112typedef int (*xfs_dir_put_t)(struct xfs_dir_put_args *pa);
113
114typedef union {
115 xfs_off_t o; /* offset (cookie) */
116 /*
117 * Watch the order here (endian-ness dependent).
118 */
119 struct {
120#ifndef XFS_NATIVE_HOST
121 xfs_dahash_t h; /* hash value */
122 __uint32_t be; /* block and entry */
123#else
124 __uint32_t be; /* block and entry */
125 xfs_dahash_t h; /* hash value */
126#endif /* XFS_NATIVE_HOST */
127 } s;
128} xfs_dircook_t;
129
130#define XFS_PUT_COOKIE(c,mp,bno,entry,hash) \
131 ((c).s.be = XFS_DA_MAKE_BNOENTRY(mp, bno, entry), (c).s.h = (hash))
132
133typedef struct xfs_dir_put_args {
134 xfs_dircook_t cook; /* cookie of (next) entry */
135 xfs_intino_t ino; /* inode number */
136 struct xfs_dirent *dbp; /* buffer pointer */
137 char *name; /* directory entry name */
138 int namelen; /* length of name */
139 int done; /* output: set if value was stored */
140 xfs_dir_put_t put; /* put function ptr (i/o) */
141 struct uio *uio; /* uio control structure */
142} xfs_dir_put_args_t;
143
144#define XFS_DIR_LEAF_ENTSIZE_BYNAME(len) \
145 xfs_dir_leaf_entsize_byname(len)
146static inline int xfs_dir_leaf_entsize_byname(int len)
147{
148 return (uint)sizeof(xfs_dir_leaf_name_t)-1 + len;
149}
150
151#define XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry) \
152 xfs_dir_leaf_entsize_byentry(entry)
153static inline int xfs_dir_leaf_entsize_byentry(xfs_dir_leaf_entry_t *entry)
154{
155 return (uint)sizeof(xfs_dir_leaf_name_t)-1 + (entry)->namelen;
156}
157
158#define XFS_DIR_LEAF_NAMESTRUCT(leafp,offset) \
159 xfs_dir_leaf_namestruct(leafp,offset)
160static inline xfs_dir_leaf_name_t *
161xfs_dir_leaf_namestruct(xfs_dir_leafblock_t *leafp, int offset)
162{
163 return (xfs_dir_leaf_name_t *)&((char *)(leafp))[offset];
164}
165
166/*========================================================================
167 * Function prototypes for the kernel.
168 *========================================================================*/
169
170/*
171 * Internal routines when dirsize < XFS_LITINO(mp).
172 */
173int xfs_dir_shortform_create(struct xfs_da_args *args, xfs_ino_t parent);
174int xfs_dir_shortform_addname(struct xfs_da_args *args);
175int xfs_dir_shortform_lookup(struct xfs_da_args *args);
176int xfs_dir_shortform_to_leaf(struct xfs_da_args *args);
177int xfs_dir_shortform_removename(struct xfs_da_args *args);
178int xfs_dir_shortform_getdents(struct xfs_inode *dp, struct uio *uio, int *eofp,
179 struct xfs_dirent *dbp, xfs_dir_put_t put);
180int xfs_dir_shortform_replace(struct xfs_da_args *args);
181
182/*
183 * Internal routines when dirsize == XFS_LBSIZE(mp).
184 */
185int xfs_dir_leaf_to_node(struct xfs_da_args *args);
186int xfs_dir_leaf_to_shortform(struct xfs_da_args *args);
187
188/*
189 * Routines used for growing the Btree.
190 */
191int xfs_dir_leaf_split(struct xfs_da_state *state,
192 struct xfs_da_state_blk *oldblk,
193 struct xfs_da_state_blk *newblk);
194int xfs_dir_leaf_add(struct xfs_dabuf *leaf_buffer,
195 struct xfs_da_args *args, int insertion_index);
196int xfs_dir_leaf_addname(struct xfs_da_args *args);
197int xfs_dir_leaf_lookup_int(struct xfs_dabuf *leaf_buffer,
198 struct xfs_da_args *args,
199 int *index_found_at);
200int xfs_dir_leaf_remove(struct xfs_trans *trans,
201 struct xfs_dabuf *leaf_buffer,
202 int index_to_remove);
203int xfs_dir_leaf_getdents_int(struct xfs_dabuf *bp, struct xfs_inode *dp,
204 xfs_dablk_t bno, struct uio *uio,
205 int *eobp, struct xfs_dirent *dbp,
206 xfs_dir_put_t put, xfs_daddr_t nextda);
207
208/*
209 * Routines used for shrinking the Btree.
210 */
211int xfs_dir_leaf_toosmall(struct xfs_da_state *state, int *retval);
212void xfs_dir_leaf_unbalance(struct xfs_da_state *state,
213 struct xfs_da_state_blk *drop_blk,
214 struct xfs_da_state_blk *save_blk);
215
216/*
217 * Utility routines.
218 */
219uint xfs_dir_leaf_lasthash(struct xfs_dabuf *bp, int *count);
220int xfs_dir_leaf_order(struct xfs_dabuf *leaf1_bp,
221 struct xfs_dabuf *leaf2_bp);
222int xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa);
223int xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa);
224int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
225
226/*
227 * Global data.
228 */
229extern xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot;
230
231#endif /* __XFS_DIR_LEAF_H__ */
diff --git a/fs/xfs/xfs_dir_sf.h b/fs/xfs/xfs_dir_sf.h
deleted file mode 100644
index 5b20b4d3f57d..000000000000
--- a/fs/xfs/xfs_dir_sf.h
+++ /dev/null
@@ -1,155 +0,0 @@
1/*
2 * Copyright (c) 2000,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#ifndef __XFS_DIR_SF_H__
19#define __XFS_DIR_SF_H__
20
21/*
22 * Directory layout when stored internal to an inode.
23 *
24 * Small directories are packed as tightly as possible so as to
25 * fit into the literal area of the inode.
26 */
27
28typedef struct { __uint8_t i[sizeof(xfs_ino_t)]; } xfs_dir_ino_t;
29
30/*
31 * The parent directory has a dedicated field, and the self-pointer must
32 * be calculated on the fly.
33 *
34 * Entries are packed toward the top as tight as possible. The header
35 * and the elements much be memcpy'd out into a work area to get correct
36 * alignment for the inode number fields.
37 */
38typedef struct xfs_dir_sf_hdr { /* constant-structure header block */
39 xfs_dir_ino_t parent; /* parent dir inode number */
40 __uint8_t count; /* count of active entries */
41} xfs_dir_sf_hdr_t;
42
43typedef struct xfs_dir_sf_entry {
44 xfs_dir_ino_t inumber; /* referenced inode number */
45 __uint8_t namelen; /* actual length of name (no NULL) */
46 __uint8_t name[1]; /* name */
47} xfs_dir_sf_entry_t;
48
49typedef struct xfs_dir_shortform {
50 xfs_dir_sf_hdr_t hdr;
51 xfs_dir_sf_entry_t list[1]; /* variable sized array */
52} xfs_dir_shortform_t;
53
54/*
55 * We generate this then sort it, so that readdirs are returned in
56 * hash-order. Else seekdir won't work.
57 */
58typedef struct xfs_dir_sf_sort {
59 __uint8_t entno; /* .=0, ..=1, else entry# + 2 */
60 __uint8_t seqno; /* sequence # with same hash value */
61 __uint8_t namelen; /* length of name value (no null) */
62 xfs_dahash_t hash; /* this entry's hash value */
63 xfs_intino_t ino; /* this entry's inode number */
64 char *name; /* name value, pointer into buffer */
65} xfs_dir_sf_sort_t;
66
67#define XFS_DIR_SF_GET_DIRINO(from,to) xfs_dir_sf_get_dirino(from, to)
68static inline void xfs_dir_sf_get_dirino(xfs_dir_ino_t *from, xfs_ino_t *to)
69{
70 *(to) = XFS_GET_DIR_INO8(*from);
71}
72
73#define XFS_DIR_SF_PUT_DIRINO(from,to) xfs_dir_sf_put_dirino(from, to)
74static inline void xfs_dir_sf_put_dirino(xfs_ino_t *from, xfs_dir_ino_t *to)
75{
76 XFS_PUT_DIR_INO8(*(from), *(to));
77}
78
79#define XFS_DIR_SF_ENTSIZE_BYNAME(len) xfs_dir_sf_entsize_byname(len)
80static inline int xfs_dir_sf_entsize_byname(int len)
81{
82 return (uint)sizeof(xfs_dir_sf_entry_t)-1 + (len);
83}
84
85#define XFS_DIR_SF_ENTSIZE_BYENTRY(sfep) xfs_dir_sf_entsize_byentry(sfep)
86static inline int xfs_dir_sf_entsize_byentry(xfs_dir_sf_entry_t *sfep)
87{
88 return (uint)sizeof(xfs_dir_sf_entry_t)-1 + (sfep)->namelen;
89}
90
91#define XFS_DIR_SF_NEXTENTRY(sfep) xfs_dir_sf_nextentry(sfep)
92static inline xfs_dir_sf_entry_t *xfs_dir_sf_nextentry(xfs_dir_sf_entry_t *sfep)
93{
94 return (xfs_dir_sf_entry_t *) \
95 ((char *)(sfep) + XFS_DIR_SF_ENTSIZE_BYENTRY(sfep));
96}
97
98#define XFS_DIR_SF_ALLFIT(count,totallen) \
99 xfs_dir_sf_allfit(count,totallen)
100static inline int xfs_dir_sf_allfit(int count, int totallen)
101{
102 return ((uint)sizeof(xfs_dir_sf_hdr_t) + \
103 ((uint)sizeof(xfs_dir_sf_entry_t)-1)*(count) + (totallen));
104}
105
106#if defined(XFS_DIR_TRACE)
107
108/*
109 * Kernel tracing support for directories.
110 */
111struct uio;
112struct xfs_inode;
113struct xfs_da_intnode;
114struct xfs_dinode;
115struct xfs_dir_leafblock;
116struct xfs_dir_leaf_entry;
117
118#define XFS_DIR_TRACE_SIZE 4096 /* size of global trace buffer */
119extern ktrace_t *xfs_dir_trace_buf;
120
121/*
122 * Trace record types.
123 */
124#define XFS_DIR_KTRACE_G_DU 1 /* dp, uio */
125#define XFS_DIR_KTRACE_G_DUB 2 /* dp, uio, bno */
126#define XFS_DIR_KTRACE_G_DUN 3 /* dp, uio, node */
127#define XFS_DIR_KTRACE_G_DUL 4 /* dp, uio, leaf */
128#define XFS_DIR_KTRACE_G_DUE 5 /* dp, uio, leaf entry */
129#define XFS_DIR_KTRACE_G_DUC 6 /* dp, uio, cookie */
130
131void xfs_dir_trace_g_du(char *where, struct xfs_inode *dp, struct uio *uio);
132void xfs_dir_trace_g_dub(char *where, struct xfs_inode *dp, struct uio *uio,
133 xfs_dablk_t bno);
134void xfs_dir_trace_g_dun(char *where, struct xfs_inode *dp, struct uio *uio,
135 struct xfs_da_intnode *node);
136void xfs_dir_trace_g_dul(char *where, struct xfs_inode *dp, struct uio *uio,
137 struct xfs_dir_leafblock *leaf);
138void xfs_dir_trace_g_due(char *where, struct xfs_inode *dp, struct uio *uio,
139 struct xfs_dir_leaf_entry *entry);
140void xfs_dir_trace_g_duc(char *where, struct xfs_inode *dp, struct uio *uio,
141 xfs_off_t cookie);
142void xfs_dir_trace_enter(int type, char *where,
143 void *a0, void *a1, void *a2, void *a3,
144 void *a4, void *a5, void *a6, void *a7,
145 void *a8, void *a9, void *a10, void *a11);
146#else
147#define xfs_dir_trace_g_du(w,d,u)
148#define xfs_dir_trace_g_dub(w,d,u,b)
149#define xfs_dir_trace_g_dun(w,d,u,n)
150#define xfs_dir_trace_g_dul(w,d,u,l)
151#define xfs_dir_trace_g_due(w,d,u,e)
152#define xfs_dir_trace_g_duc(w,d,u,c)
153#endif /* DEBUG */
154
155#endif /* __XFS_DIR_SF_H__ */
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h
index 00b1540f8108..4e7865ad6f0e 100644
--- a/fs/xfs/xfs_dmapi.h
+++ b/fs/xfs/xfs_dmapi.h
@@ -189,6 +189,6 @@ typedef enum {
189#define AT_DELAY_FLAG(f) ((f&ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0) 189#define AT_DELAY_FLAG(f) ((f&ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0)
190 190
191 191
192extern struct bhv_vfsops xfs_dmops; 192extern struct bhv_module_vfsops xfs_dmops;
193 193
194#endif /* __XFS_DMAPI_H__ */ 194#endif /* __XFS_DMAPI_H__ */
diff --git a/fs/xfs/xfs_dmops.c b/fs/xfs/xfs_dmops.c
index 629795b3b3d5..1e4a35ddf7f9 100644
--- a/fs/xfs/xfs_dmops.c
+++ b/fs/xfs/xfs_dmops.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_dmapi.h" 27#include "xfs_dmapi.h"
29#include "xfs_mount.h" 28#include "xfs_mount.h"
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 2a21c5024017..b95681b03d81 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -22,12 +22,10 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h" 25#include "xfs_dir2.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_bmap_btree.h" 28#include "xfs_bmap_btree.h"
30#include "xfs_dir_sf.h"
31#include "xfs_dir2_sf.h" 29#include "xfs_dir2_sf.h"
32#include "xfs_attr_sf.h" 30#include "xfs_attr_sf.h"
33#include "xfs_dinode.h" 31#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index f19282ec8549..6cf6d8769b97 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_buf_item.h" 24#include "xfs_buf_item.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_dir.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_trans_priv.h" 28#include "xfs_trans_priv.h"
@@ -294,6 +293,62 @@ xfs_efi_init(xfs_mount_t *mp,
294} 293}
295 294
296/* 295/*
296 * Copy an EFI format buffer from the given buf, and into the destination
297 * EFI format structure.
298 * The given buffer can be in 32 bit or 64 bit form (which has different padding),
299 * one of which will be the native format for this kernel.
300 * It will handle the conversion of formats if necessary.
301 */
302int
303xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt)
304{
305 xfs_efi_log_format_t *src_efi_fmt = (xfs_efi_log_format_t *)buf->i_addr;
306 uint i;
307 uint len = sizeof(xfs_efi_log_format_t) +
308 (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t);
309 uint len32 = sizeof(xfs_efi_log_format_32_t) +
310 (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_32_t);
311 uint len64 = sizeof(xfs_efi_log_format_64_t) +
312 (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_64_t);
313
314 if (buf->i_len == len) {
315 memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len);
316 return 0;
317 } else if (buf->i_len == len32) {
318 xfs_efi_log_format_32_t *src_efi_fmt_32 =
319 (xfs_efi_log_format_32_t *)buf->i_addr;
320
321 dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type;
322 dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size;
323 dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents;
324 dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id;
325 for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
326 dst_efi_fmt->efi_extents[i].ext_start =
327 src_efi_fmt_32->efi_extents[i].ext_start;
328 dst_efi_fmt->efi_extents[i].ext_len =
329 src_efi_fmt_32->efi_extents[i].ext_len;
330 }
331 return 0;
332 } else if (buf->i_len == len64) {
333 xfs_efi_log_format_64_t *src_efi_fmt_64 =
334 (xfs_efi_log_format_64_t *)buf->i_addr;
335
336 dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type;
337 dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size;
338 dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents;
339 dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id;
340 for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
341 dst_efi_fmt->efi_extents[i].ext_start =
342 src_efi_fmt_64->efi_extents[i].ext_start;
343 dst_efi_fmt->efi_extents[i].ext_len =
344 src_efi_fmt_64->efi_extents[i].ext_len;
345 }
346 return 0;
347 }
348 return EFSCORRUPTED;
349}
350
351/*
297 * This is called by the efd item code below to release references to 352 * This is called by the efd item code below to release references to
298 * the given efi item. Each efd calls this with the number of 353 * the given efi item. Each efd calls this with the number of
299 * extents that it has logged, and when the sum of these reaches 354 * extents that it has logged, and when the sum of these reaches
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h
index 5bf681708fec..0ea45edaab03 100644
--- a/fs/xfs/xfs_extfree_item.h
+++ b/fs/xfs/xfs_extfree_item.h
@@ -27,6 +27,24 @@ typedef struct xfs_extent {
27} xfs_extent_t; 27} xfs_extent_t;
28 28
29/* 29/*
30 * Since an xfs_extent_t has types (start:64, len: 32)
31 * there are different alignments on 32 bit and 64 bit kernels.
32 * So we provide the different variants for use by a
33 * conversion routine.
34 */
35
36typedef struct xfs_extent_32 {
37 xfs_dfsbno_t ext_start;
38 xfs_extlen_t ext_len;
39} __attribute__((packed)) xfs_extent_32_t;
40
41typedef struct xfs_extent_64 {
42 xfs_dfsbno_t ext_start;
43 xfs_extlen_t ext_len;
44 __uint32_t ext_pad;
45} xfs_extent_64_t;
46
47/*
30 * This is the structure used to lay out an efi log item in the 48 * This is the structure used to lay out an efi log item in the
31 * log. The efi_extents field is a variable size array whose 49 * log. The efi_extents field is a variable size array whose
32 * size is given by efi_nextents. 50 * size is given by efi_nextents.
@@ -39,6 +57,22 @@ typedef struct xfs_efi_log_format {
39 xfs_extent_t efi_extents[1]; /* array of extents to free */ 57 xfs_extent_t efi_extents[1]; /* array of extents to free */
40} xfs_efi_log_format_t; 58} xfs_efi_log_format_t;
41 59
60typedef struct xfs_efi_log_format_32 {
61 unsigned short efi_type; /* efi log item type */
62 unsigned short efi_size; /* size of this item */
63 uint efi_nextents; /* # extents to free */
64 __uint64_t efi_id; /* efi identifier */
65 xfs_extent_32_t efi_extents[1]; /* array of extents to free */
66} __attribute__((packed)) xfs_efi_log_format_32_t;
67
68typedef struct xfs_efi_log_format_64 {
69 unsigned short efi_type; /* efi log item type */
70 unsigned short efi_size; /* size of this item */
71 uint efi_nextents; /* # extents to free */
72 __uint64_t efi_id; /* efi identifier */
73 xfs_extent_64_t efi_extents[1]; /* array of extents to free */
74} xfs_efi_log_format_64_t;
75
42/* 76/*
43 * This is the structure used to lay out an efd log item in the 77 * This is the structure used to lay out an efd log item in the
44 * log. The efd_extents array is a variable size array whose 78 * log. The efd_extents array is a variable size array whose
@@ -52,6 +86,22 @@ typedef struct xfs_efd_log_format {
52 xfs_extent_t efd_extents[1]; /* array of extents freed */ 86 xfs_extent_t efd_extents[1]; /* array of extents freed */
53} xfs_efd_log_format_t; 87} xfs_efd_log_format_t;
54 88
89typedef struct xfs_efd_log_format_32 {
90 unsigned short efd_type; /* efd log item type */
91 unsigned short efd_size; /* size of this item */
92 uint efd_nextents; /* # of extents freed */
93 __uint64_t efd_efi_id; /* id of corresponding efi */
94 xfs_extent_32_t efd_extents[1]; /* array of extents freed */
95} __attribute__((packed)) xfs_efd_log_format_32_t;
96
97typedef struct xfs_efd_log_format_64 {
98 unsigned short efd_type; /* efd log item type */
99 unsigned short efd_size; /* size of this item */
100 uint efd_nextents; /* # of extents freed */
101 __uint64_t efd_efi_id; /* id of corresponding efi */
102 xfs_extent_64_t efd_extents[1]; /* array of extents freed */
103} xfs_efd_log_format_64_t;
104
55 105
56#ifdef __KERNEL__ 106#ifdef __KERNEL__
57 107
@@ -103,7 +153,8 @@ extern struct kmem_zone *xfs_efd_zone;
103xfs_efi_log_item_t *xfs_efi_init(struct xfs_mount *, uint); 153xfs_efi_log_item_t *xfs_efi_init(struct xfs_mount *, uint);
104xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *, 154xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *,
105 uint); 155 uint);
106 156int xfs_efi_copy_format(xfs_log_iovec_t *buf,
157 xfs_efi_log_format_t *dst_efi_fmt);
107void xfs_efi_item_free(xfs_efi_log_item_t *); 158void xfs_efi_item_free(xfs_efi_log_item_t *);
108 159
109#endif /* __KERNEL__ */ 160#endif /* __KERNEL__ */
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 14010f1fa82f..0f0ad1535951 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -67,14 +67,15 @@ struct fsxattr {
67#define XFS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */ 67#define XFS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */
68#define XFS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */ 68#define XFS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */
69#define XFS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */ 69#define XFS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */
70#define XFS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */
70#define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ 71#define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */
71 72
72/* 73/*
73 * Structure for XFS_IOC_GETBMAP. 74 * Structure for XFS_IOC_GETBMAP.
74 * On input, fill in bmv_offset and bmv_length of the first structure 75 * On input, fill in bmv_offset and bmv_length of the first structure
75 * to indicate the area of interest in the file, and bmv_entry with the 76 * to indicate the area of interest in the file, and bmv_entries with
76 * number of array elements given. The first structure is updated on 77 * the number of array elements given back. The first structure is
77 * return to give the offset and length for the next call. 78 * updated on return to give the offset and length for the next call.
78 */ 79 */
79#ifndef HAVE_GETBMAP 80#ifndef HAVE_GETBMAP
80struct getbmap { 81struct getbmap {
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index dfa3527b20a7..077629bab532 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
@@ -542,14 +540,13 @@ xfs_reserve_blocks(
542} 540}
543 541
544void 542void
545xfs_fs_log_dummy(xfs_mount_t *mp) 543xfs_fs_log_dummy(
544 xfs_mount_t *mp)
546{ 545{
547 xfs_trans_t *tp; 546 xfs_trans_t *tp;
548 xfs_inode_t *ip; 547 xfs_inode_t *ip;
549
550 548
551 tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1); 549 tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
552 atomic_inc(&mp->m_active_trans);
553 if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) { 550 if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) {
554 xfs_trans_cancel(tp, 0); 551 xfs_trans_cancel(tp, 0);
555 return; 552 return;
@@ -574,21 +571,22 @@ xfs_fs_goingdown(
574{ 571{
575 switch (inflags) { 572 switch (inflags) {
576 case XFS_FSOP_GOING_FLAGS_DEFAULT: { 573 case XFS_FSOP_GOING_FLAGS_DEFAULT: {
577 struct vfs *vfsp = XFS_MTOVFS(mp); 574 struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
578 struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev); 575 struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev);
579 576
580 if (sb && !IS_ERR(sb)) { 577 if (sb && !IS_ERR(sb)) {
581 xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); 578 xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT);
582 thaw_bdev(sb->s_bdev, sb); 579 thaw_bdev(sb->s_bdev, sb);
583 } 580 }
584 581
585 break; 582 break;
586 } 583 }
587 case XFS_FSOP_GOING_FLAGS_LOGFLUSH: 584 case XFS_FSOP_GOING_FLAGS_LOGFLUSH:
588 xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); 585 xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT);
589 break; 586 break;
590 case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH: 587 case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH:
591 xfs_force_shutdown(mp, XFS_FORCE_UMOUNT|XFS_LOG_IO_ERROR); 588 xfs_force_shutdown(mp,
589 SHUTDOWN_FORCE_UMOUNT | SHUTDOWN_LOG_IO_ERROR);
592 break; 590 break;
593 default: 591 default:
594 return XFS_ERROR(EINVAL); 592 return XFS_ERROR(EINVAL);
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index deddbd03c166..33164a85aa9d 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
@@ -1174,6 +1172,9 @@ xfs_dilocate(
1174 if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks || 1172 if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
1175 ino != XFS_AGINO_TO_INO(mp, agno, agino)) { 1173 ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
1176#ifdef DEBUG 1174#ifdef DEBUG
1175 /* no diagnostics for bulkstat, ino comes from userspace */
1176 if (flags & XFS_IMAP_BULKSTAT)
1177 return XFS_ERROR(EINVAL);
1177 if (agno >= mp->m_sb.sb_agcount) { 1178 if (agno >= mp->m_sb.sb_agcount) {
1178 xfs_fs_cmn_err(CE_ALERT, mp, 1179 xfs_fs_cmn_err(CE_ALERT, mp,
1179 "xfs_dilocate: agno (%d) >= " 1180 "xfs_dilocate: agno (%d) >= "
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c
index 60c65683462d..616eeeb6953e 100644
--- a/fs/xfs/xfs_ialloc_btree.c
+++ b/fs/xfs/xfs_ialloc_btree.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index b53854325266..0724df7fabb7 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
@@ -186,7 +184,7 @@ xfs_ihash_promote(
186 */ 184 */
187STATIC int 185STATIC int
188xfs_iget_core( 186xfs_iget_core(
189 vnode_t *vp, 187 bhv_vnode_t *vp,
190 xfs_mount_t *mp, 188 xfs_mount_t *mp,
191 xfs_trans_t *tp, 189 xfs_trans_t *tp,
192 xfs_ino_t ino, 190 xfs_ino_t ino,
@@ -198,7 +196,7 @@ xfs_iget_core(
198 xfs_ihash_t *ih; 196 xfs_ihash_t *ih;
199 xfs_inode_t *ip; 197 xfs_inode_t *ip;
200 xfs_inode_t *iq; 198 xfs_inode_t *iq;
201 vnode_t *inode_vp; 199 bhv_vnode_t *inode_vp;
202 ulong version; 200 ulong version;
203 int error; 201 int error;
204 /* REFERENCED */ 202 /* REFERENCED */
@@ -468,7 +466,7 @@ finish_inode:
468 * If we have a real type for an on-disk inode, we can set ops(&unlock) 466 * If we have a real type for an on-disk inode, we can set ops(&unlock)
469 * now. If it's a new inode being created, xfs_ialloc will handle it. 467 * now. If it's a new inode being created, xfs_ialloc will handle it.
470 */ 468 */
471 VFS_INIT_VNODE(XFS_MTOVFS(mp), vp, XFS_ITOBHV(ip), 1); 469 bhv_vfs_init_vnode(XFS_MTOVFS(mp), vp, XFS_ITOBHV(ip), 1);
472 470
473 return 0; 471 return 0;
474} 472}
@@ -489,7 +487,7 @@ xfs_iget(
489 xfs_daddr_t bno) 487 xfs_daddr_t bno)
490{ 488{
491 struct inode *inode; 489 struct inode *inode;
492 vnode_t *vp = NULL; 490 bhv_vnode_t *vp = NULL;
493 int error; 491 int error;
494 492
495 XFS_STATS_INC(xs_ig_attempts); 493 XFS_STATS_INC(xs_ig_attempts);
@@ -543,7 +541,7 @@ retry:
543void 541void
544xfs_inode_lock_init( 542xfs_inode_lock_init(
545 xfs_inode_t *ip, 543 xfs_inode_t *ip,
546 vnode_t *vp) 544 bhv_vnode_t *vp)
547{ 545{
548 mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER, 546 mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
549 "xfsino", (long)vp->v_number); 547 "xfsino", (long)vp->v_number);
@@ -603,12 +601,10 @@ void
603xfs_iput(xfs_inode_t *ip, 601xfs_iput(xfs_inode_t *ip,
604 uint lock_flags) 602 uint lock_flags)
605{ 603{
606 vnode_t *vp = XFS_ITOV(ip); 604 bhv_vnode_t *vp = XFS_ITOV(ip);
607 605
608 vn_trace_entry(vp, "xfs_iput", (inst_t *)__return_address); 606 vn_trace_entry(vp, "xfs_iput", (inst_t *)__return_address);
609
610 xfs_iunlock(ip, lock_flags); 607 xfs_iunlock(ip, lock_flags);
611
612 VN_RELE(vp); 608 VN_RELE(vp);
613} 609}
614 610
@@ -619,7 +615,7 @@ void
619xfs_iput_new(xfs_inode_t *ip, 615xfs_iput_new(xfs_inode_t *ip,
620 uint lock_flags) 616 uint lock_flags)
621{ 617{
622 vnode_t *vp = XFS_ITOV(ip); 618 bhv_vnode_t *vp = XFS_ITOV(ip);
623 struct inode *inode = vn_to_inode(vp); 619 struct inode *inode = vn_to_inode(vp);
624 620
625 vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); 621 vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address);
@@ -645,7 +641,7 @@ xfs_iput_new(xfs_inode_t *ip,
645void 641void
646xfs_ireclaim(xfs_inode_t *ip) 642xfs_ireclaim(xfs_inode_t *ip)
647{ 643{
648 vnode_t *vp; 644 bhv_vnode_t *vp;
649 645
650 /* 646 /*
651 * Remove from old hash list and mount list. 647 * Remove from old hash list and mount list.
@@ -1033,6 +1029,6 @@ xfs_iflock_nowait(xfs_inode_t *ip)
1033void 1029void
1034xfs_ifunlock(xfs_inode_t *ip) 1030xfs_ifunlock(xfs_inode_t *ip)
1035{ 1031{
1036 ASSERT(valusema(&(ip->i_flock)) <= 0); 1032 ASSERT(issemalocked(&(ip->i_flock)));
1037 vsema(&(ip->i_flock)); 1033 vsema(&(ip->i_flock));
1038} 1034}
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 94b60dd03801..5fa0adb7e173 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -26,14 +26,12 @@
26#include "xfs_trans_priv.h" 26#include "xfs_trans_priv.h"
27#include "xfs_sb.h" 27#include "xfs_sb.h"
28#include "xfs_ag.h" 28#include "xfs_ag.h"
29#include "xfs_dir.h"
30#include "xfs_dir2.h" 29#include "xfs_dir2.h"
31#include "xfs_dmapi.h" 30#include "xfs_dmapi.h"
32#include "xfs_mount.h" 31#include "xfs_mount.h"
33#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
34#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
35#include "xfs_ialloc_btree.h" 34#include "xfs_ialloc_btree.h"
36#include "xfs_dir_sf.h"
37#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
38#include "xfs_attr_sf.h" 36#include "xfs_attr_sf.h"
39#include "xfs_dinode.h" 37#include "xfs_dinode.h"
@@ -256,13 +254,11 @@ xfs_itobp(
256 xfs_daddr_t bno, 254 xfs_daddr_t bno,
257 uint imap_flags) 255 uint imap_flags)
258{ 256{
257 xfs_imap_t imap;
259 xfs_buf_t *bp; 258 xfs_buf_t *bp;
260 int error; 259 int error;
261 xfs_imap_t imap;
262#ifdef __KERNEL__
263 int i; 260 int i;
264 int ni; 261 int ni;
265#endif
266 262
267 if (ip->i_blkno == (xfs_daddr_t)0) { 263 if (ip->i_blkno == (xfs_daddr_t)0) {
268 /* 264 /*
@@ -319,7 +315,6 @@ xfs_itobp(
319 */ 315 */
320 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap.im_blkno, 316 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap.im_blkno,
321 (int)imap.im_len, XFS_BUF_LOCK, &bp); 317 (int)imap.im_len, XFS_BUF_LOCK, &bp);
322
323 if (error) { 318 if (error) {
324#ifdef DEBUG 319#ifdef DEBUG
325 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_itobp: " 320 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_itobp: "
@@ -330,17 +325,21 @@ xfs_itobp(
330#endif /* DEBUG */ 325#endif /* DEBUG */
331 return error; 326 return error;
332 } 327 }
333#ifdef __KERNEL__ 328
334 /* 329 /*
335 * Validate the magic number and version of every inode in the buffer 330 * Validate the magic number and version of every inode in the buffer
336 * (if DEBUG kernel) or the first inode in the buffer, otherwise. 331 * (if DEBUG kernel) or the first inode in the buffer, otherwise.
332 * No validation is done here in userspace (xfs_repair).
337 */ 333 */
338#ifdef DEBUG 334#if !defined(__KERNEL__)
335 ni = 0;
336#elif defined(DEBUG)
339 ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 337 ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 :
340 (BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog); 338 (BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog);
341#else 339#else /* usual case */
342 ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1; 340 ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1;
343#endif 341#endif
342
344 for (i = 0; i < ni; i++) { 343 for (i = 0; i < ni; i++) {
345 int di_ok; 344 int di_ok;
346 xfs_dinode_t *dip; 345 xfs_dinode_t *dip;
@@ -352,8 +351,11 @@ xfs_itobp(
352 if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, 351 if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
353 XFS_RANDOM_ITOBP_INOTOBP))) { 352 XFS_RANDOM_ITOBP_INOTOBP))) {
354#ifdef DEBUG 353#ifdef DEBUG
355 prdev("bad inode magic/vsn daddr %lld #%d (magic=%x)", 354 if (!(imap_flags & XFS_IMAP_BULKSTAT))
356 mp->m_ddev_targp, 355 cmn_err(CE_ALERT,
356 "Device %s - bad inode magic/vsn "
357 "daddr %lld #%d (magic=%x)",
358 XFS_BUFTARG_NAME(mp->m_ddev_targp),
357 (unsigned long long)imap.im_blkno, i, 359 (unsigned long long)imap.im_blkno, i,
358 INT_GET(dip->di_core.di_magic, ARCH_CONVERT)); 360 INT_GET(dip->di_core.di_magic, ARCH_CONVERT));
359#endif 361#endif
@@ -363,7 +365,6 @@ xfs_itobp(
363 return XFS_ERROR(EFSCORRUPTED); 365 return XFS_ERROR(EFSCORRUPTED);
364 } 366 }
365 } 367 }
366#endif /* __KERNEL__ */
367 368
368 xfs_inobp_check(mp, bp); 369 xfs_inobp_check(mp, bp);
369 370
@@ -782,7 +783,6 @@ xfs_xlate_dinode_core(
782 783
783STATIC uint 784STATIC uint
784_xfs_dic2xflags( 785_xfs_dic2xflags(
785 xfs_dinode_core_t *dic,
786 __uint16_t di_flags) 786 __uint16_t di_flags)
787{ 787{
788 uint flags = 0; 788 uint flags = 0;
@@ -812,6 +812,8 @@ _xfs_dic2xflags(
812 flags |= XFS_XFLAG_EXTSIZE; 812 flags |= XFS_XFLAG_EXTSIZE;
813 if (di_flags & XFS_DIFLAG_EXTSZINHERIT) 813 if (di_flags & XFS_DIFLAG_EXTSZINHERIT)
814 flags |= XFS_XFLAG_EXTSZINHERIT; 814 flags |= XFS_XFLAG_EXTSZINHERIT;
815 if (di_flags & XFS_DIFLAG_NODEFRAG)
816 flags |= XFS_XFLAG_NODEFRAG;
815 } 817 }
816 818
817 return flags; 819 return flags;
@@ -823,16 +825,16 @@ xfs_ip2xflags(
823{ 825{
824 xfs_dinode_core_t *dic = &ip->i_d; 826 xfs_dinode_core_t *dic = &ip->i_d;
825 827
826 return _xfs_dic2xflags(dic, dic->di_flags) | 828 return _xfs_dic2xflags(dic->di_flags) |
827 (XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0); 829 (XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0);
828} 830}
829 831
830uint 832uint
831xfs_dic2xflags( 833xfs_dic2xflags(
832 xfs_dinode_core_t *dic) 834 xfs_dinode_core_t *dic)
833{ 835{
834 return _xfs_dic2xflags(dic, INT_GET(dic->di_flags, ARCH_CONVERT)) | 836 return _xfs_dic2xflags(INT_GET(dic->di_flags, ARCH_CONVERT)) |
835 (XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0); 837 (XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0);
836} 838}
837 839
838/* 840/*
@@ -1083,7 +1085,7 @@ xfs_ialloc(
1083{ 1085{
1084 xfs_ino_t ino; 1086 xfs_ino_t ino;
1085 xfs_inode_t *ip; 1087 xfs_inode_t *ip;
1086 vnode_t *vp; 1088 bhv_vnode_t *vp;
1087 uint flags; 1089 uint flags;
1088 int error; 1090 int error;
1089 1091
@@ -1221,6 +1223,9 @@ xfs_ialloc(
1221 di_flags |= XFS_DIFLAG_NOSYMLINKS; 1223 di_flags |= XFS_DIFLAG_NOSYMLINKS;
1222 if (pip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) 1224 if (pip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
1223 di_flags |= XFS_DIFLAG_PROJINHERIT; 1225 di_flags |= XFS_DIFLAG_PROJINHERIT;
1226 if ((pip->i_d.di_flags & XFS_DIFLAG_NODEFRAG) &&
1227 xfs_inherit_nodefrag)
1228 di_flags |= XFS_DIFLAG_NODEFRAG;
1224 ip->i_d.di_flags |= di_flags; 1229 ip->i_d.di_flags |= di_flags;
1225 } 1230 }
1226 /* FALLTHROUGH */ 1231 /* FALLTHROUGH */
@@ -1244,8 +1249,8 @@ xfs_ialloc(
1244 */ 1249 */
1245 xfs_trans_log_inode(tp, ip, flags); 1250 xfs_trans_log_inode(tp, ip, flags);
1246 1251
1247 /* now that we have an i_mode we can set Linux inode ops (& unlock) */ 1252 /* now that we have an i_mode we can setup inode ops and unlock */
1248 VFS_INIT_VNODE(XFS_MTOVFS(tp->t_mountp), vp, XFS_ITOBHV(ip), 1); 1253 bhv_vfs_init_vnode(XFS_MTOVFS(tp->t_mountp), vp, XFS_ITOBHV(ip), 1);
1249 1254
1250 *ipp = ip; 1255 *ipp = ip;
1251 return 0; 1256 return 0;
@@ -1285,7 +1290,7 @@ xfs_isize_check(
1285 (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) - 1290 (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) -
1286 map_first), 1291 map_first),
1287 XFS_BMAPI_ENTIRE, NULL, 0, imaps, &nimaps, 1292 XFS_BMAPI_ENTIRE, NULL, 0, imaps, &nimaps,
1288 NULL)) 1293 NULL, NULL))
1289 return; 1294 return;
1290 ASSERT(nimaps == 1); 1295 ASSERT(nimaps == 1);
1291 ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK); 1296 ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK);
@@ -1421,7 +1426,7 @@ xfs_itruncate_start(
1421 xfs_fsize_t last_byte; 1426 xfs_fsize_t last_byte;
1422 xfs_off_t toss_start; 1427 xfs_off_t toss_start;
1423 xfs_mount_t *mp; 1428 xfs_mount_t *mp;
1424 vnode_t *vp; 1429 bhv_vnode_t *vp;
1425 1430
1426 ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0); 1431 ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0);
1427 ASSERT((new_size == 0) || (new_size <= ip->i_d.di_size)); 1432 ASSERT((new_size == 0) || (new_size <= ip->i_d.di_size));
@@ -1434,9 +1439,9 @@ xfs_itruncate_start(
1434 vn_iowait(vp); /* wait for the completion of any pending DIOs */ 1439 vn_iowait(vp); /* wait for the completion of any pending DIOs */
1435 1440
1436 /* 1441 /*
1437 * Call VOP_TOSS_PAGES() or VOP_FLUSHINVAL_PAGES() to get rid of pages and buffers 1442 * Call toss_pages or flushinval_pages to get rid of pages
1438 * overlapping the region being removed. We have to use 1443 * overlapping the region being removed. We have to use
1439 * the less efficient VOP_FLUSHINVAL_PAGES() in the case that the 1444 * the less efficient flushinval_pages in the case that the
1440 * caller may not be able to finish the truncate without 1445 * caller may not be able to finish the truncate without
1441 * dropping the inode's I/O lock. Make sure 1446 * dropping the inode's I/O lock. Make sure
1442 * to catch any pages brought in by buffers overlapping 1447 * to catch any pages brought in by buffers overlapping
@@ -1445,10 +1450,10 @@ xfs_itruncate_start(
1445 * so that we don't toss things on the same block as 1450 * so that we don't toss things on the same block as
1446 * new_size but before it. 1451 * new_size but before it.
1447 * 1452 *
1448 * Before calling VOP_TOSS_PAGES() or VOP_FLUSHINVAL_PAGES(), make sure to 1453 * Before calling toss_page or flushinval_pages, make sure to
1449 * call remapf() over the same region if the file is mapped. 1454 * call remapf() over the same region if the file is mapped.
1450 * This frees up mapped file references to the pages in the 1455 * This frees up mapped file references to the pages in the
1451 * given range and for the VOP_FLUSHINVAL_PAGES() case it ensures 1456 * given range and for the flushinval_pages case it ensures
1452 * that we get the latest mapped changes flushed out. 1457 * that we get the latest mapped changes flushed out.
1453 */ 1458 */
1454 toss_start = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size); 1459 toss_start = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size);
@@ -1466,9 +1471,9 @@ xfs_itruncate_start(
1466 last_byte); 1471 last_byte);
1467 if (last_byte > toss_start) { 1472 if (last_byte > toss_start) {
1468 if (flags & XFS_ITRUNC_DEFINITE) { 1473 if (flags & XFS_ITRUNC_DEFINITE) {
1469 VOP_TOSS_PAGES(vp, toss_start, -1, FI_REMAPF_LOCKED); 1474 bhv_vop_toss_pages(vp, toss_start, -1, FI_REMAPF_LOCKED);
1470 } else { 1475 } else {
1471 VOP_FLUSHINVAL_PAGES(vp, toss_start, -1, FI_REMAPF_LOCKED); 1476 bhv_vop_flushinval_pages(vp, toss_start, -1, FI_REMAPF_LOCKED);
1472 } 1477 }
1473 } 1478 }
1474 1479
@@ -1666,12 +1671,13 @@ xfs_itruncate_finish(
1666 * runs. 1671 * runs.
1667 */ 1672 */
1668 XFS_BMAP_INIT(&free_list, &first_block); 1673 XFS_BMAP_INIT(&free_list, &first_block);
1669 error = xfs_bunmapi(ntp, ip, first_unmap_block, 1674 error = XFS_BUNMAPI(mp, ntp, &ip->i_iocore,
1670 unmap_len, 1675 first_unmap_block, unmap_len,
1671 XFS_BMAPI_AFLAG(fork) | 1676 XFS_BMAPI_AFLAG(fork) |
1672 (sync ? 0 : XFS_BMAPI_ASYNC), 1677 (sync ? 0 : XFS_BMAPI_ASYNC),
1673 XFS_ITRUNC_MAX_EXTENTS, 1678 XFS_ITRUNC_MAX_EXTENTS,
1674 &first_block, &free_list, &done); 1679 &first_block, &free_list,
1680 NULL, &done);
1675 if (error) { 1681 if (error) {
1676 /* 1682 /*
1677 * If the bunmapi call encounters an error, 1683 * If the bunmapi call encounters an error,
@@ -2745,13 +2751,14 @@ xfs_iunpin(
2745 * the inode to become unpinned. 2751 * the inode to become unpinned.
2746 */ 2752 */
2747 if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) { 2753 if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) {
2748 vnode_t *vp = XFS_ITOV_NULL(ip); 2754 bhv_vnode_t *vp = XFS_ITOV_NULL(ip);
2749 2755
2750 /* make sync come back and flush this inode */ 2756 /* make sync come back and flush this inode */
2751 if (vp) { 2757 if (vp) {
2752 struct inode *inode = vn_to_inode(vp); 2758 struct inode *inode = vn_to_inode(vp);
2753 2759
2754 if (!(inode->i_state & I_NEW)) 2760 if (!(inode->i_state &
2761 (I_NEW|I_FREEING|I_CLEAR)))
2755 mark_inode_dirty_sync(inode); 2762 mark_inode_dirty_sync(inode);
2756 } 2763 }
2757 } 2764 }
@@ -2916,13 +2923,6 @@ xfs_iflush_fork(
2916 ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork)); 2923 ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
2917 memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes); 2924 memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes);
2918 } 2925 }
2919 if (whichfork == XFS_DATA_FORK) {
2920 if (unlikely(XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp, dip))) {
2921 XFS_ERROR_REPORT("xfs_iflush_fork",
2922 XFS_ERRLEVEL_LOW, mp);
2923 return XFS_ERROR(EFSCORRUPTED);
2924 }
2925 }
2926 break; 2926 break;
2927 2927
2928 case XFS_DINODE_FMT_EXTENTS: 2928 case XFS_DINODE_FMT_EXTENTS:
@@ -3006,7 +3006,7 @@ xfs_iflush(
3006 XFS_STATS_INC(xs_iflush_count); 3006 XFS_STATS_INC(xs_iflush_count);
3007 3007
3008 ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS)); 3008 ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
3009 ASSERT(valusema(&ip->i_flock) <= 0); 3009 ASSERT(issemalocked(&(ip->i_flock)));
3010 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || 3010 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
3011 ip->i_d.di_nextents > ip->i_df.if_ext_max); 3011 ip->i_d.di_nextents > ip->i_df.if_ext_max);
3012 3012
@@ -3199,7 +3199,7 @@ xfs_iflush(
3199 3199
3200corrupt_out: 3200corrupt_out:
3201 xfs_buf_relse(bp); 3201 xfs_buf_relse(bp);
3202 xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); 3202 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
3203 xfs_iflush_abort(ip); 3203 xfs_iflush_abort(ip);
3204 /* 3204 /*
3205 * Unlocks the flush lock 3205 * Unlocks the flush lock
@@ -3221,7 +3221,7 @@ cluster_corrupt_out:
3221 xfs_buf_relse(bp); 3221 xfs_buf_relse(bp);
3222 } 3222 }
3223 3223
3224 xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); 3224 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
3225 3225
3226 if(!bufwasdelwri) { 3226 if(!bufwasdelwri) {
3227 /* 3227 /*
@@ -3264,7 +3264,7 @@ xfs_iflush_int(
3264 SPLDECL(s); 3264 SPLDECL(s);
3265 3265
3266 ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS)); 3266 ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
3267 ASSERT(valusema(&ip->i_flock) <= 0); 3267 ASSERT(issemalocked(&(ip->i_flock)));
3268 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || 3268 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
3269 ip->i_d.di_nextents > ip->i_df.if_ext_max); 3269 ip->i_d.di_nextents > ip->i_df.if_ext_max);
3270 3270
@@ -3504,7 +3504,7 @@ xfs_iflush_all(
3504 xfs_mount_t *mp) 3504 xfs_mount_t *mp)
3505{ 3505{
3506 xfs_inode_t *ip; 3506 xfs_inode_t *ip;
3507 vnode_t *vp; 3507 bhv_vnode_t *vp;
3508 3508
3509 again: 3509 again:
3510 XFS_MOUNT_ILOCK(mp); 3510 XFS_MOUNT_ILOCK(mp);
@@ -4180,7 +4180,7 @@ xfs_iext_direct_to_inline(
4180 */ 4180 */
4181 memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents, 4181 memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents,
4182 nextents * sizeof(xfs_bmbt_rec_t)); 4182 nextents * sizeof(xfs_bmbt_rec_t));
4183 kmem_free(ifp->if_u1.if_extents, KM_SLEEP); 4183 kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes);
4184 ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; 4184 ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
4185 ifp->if_real_bytes = 0; 4185 ifp->if_real_bytes = 0;
4186} 4186}
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 3b544db1790b..d10b76ed1e5b 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -102,9 +102,9 @@ typedef struct xfs_ifork {
102 102
103#ifdef __KERNEL__ 103#ifdef __KERNEL__
104struct bhv_desc; 104struct bhv_desc;
105struct bhv_vnode;
105struct cred; 106struct cred;
106struct ktrace; 107struct ktrace;
107struct vnode;
108struct xfs_buf; 108struct xfs_buf;
109struct xfs_bmap_free; 109struct xfs_bmap_free;
110struct xfs_bmbt_irec; 110struct xfs_bmbt_irec;
@@ -400,7 +400,7 @@ void xfs_chash_init(struct xfs_mount *);
400void xfs_chash_free(struct xfs_mount *); 400void xfs_chash_free(struct xfs_mount *);
401xfs_inode_t *xfs_inode_incore(struct xfs_mount *, xfs_ino_t, 401xfs_inode_t *xfs_inode_incore(struct xfs_mount *, xfs_ino_t,
402 struct xfs_trans *); 402 struct xfs_trans *);
403void xfs_inode_lock_init(xfs_inode_t *, struct vnode *); 403void xfs_inode_lock_init(xfs_inode_t *, struct bhv_vnode *);
404int xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, 404int xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
405 uint, uint, xfs_inode_t **, xfs_daddr_t); 405 uint, uint, xfs_inode_t **, xfs_daddr_t);
406void xfs_iput(xfs_inode_t *, uint); 406void xfs_iput(xfs_inode_t *, uint);
@@ -461,7 +461,7 @@ void xfs_ichgtime(xfs_inode_t *, int);
461xfs_fsize_t xfs_file_last_byte(xfs_inode_t *); 461xfs_fsize_t xfs_file_last_byte(xfs_inode_t *);
462void xfs_lock_inodes(xfs_inode_t **, int, int, uint); 462void xfs_lock_inodes(xfs_inode_t **, int, int, uint);
463 463
464xfs_inode_t *xfs_vtoi(struct vnode *vp); 464xfs_inode_t *xfs_vtoi(struct bhv_vnode *vp);
465 465
466void xfs_synchronize_atime(xfs_inode_t *); 466void xfs_synchronize_atime(xfs_inode_t *);
467 467
@@ -509,7 +509,6 @@ extern struct kmem_zone *xfs_chashlist_zone;
509extern struct kmem_zone *xfs_ifork_zone; 509extern struct kmem_zone *xfs_ifork_zone;
510extern struct kmem_zone *xfs_inode_zone; 510extern struct kmem_zone *xfs_inode_zone;
511extern struct kmem_zone *xfs_ili_zone; 511extern struct kmem_zone *xfs_ili_zone;
512extern struct vnodeops xfs_vnodeops;
513 512
514#endif /* __KERNEL__ */ 513#endif /* __KERNEL__ */
515 514
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 7497a481b2f5..f8e80d8e7237 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -25,7 +25,6 @@
25#include "xfs_buf_item.h" 25#include "xfs_buf_item.h"
26#include "xfs_sb.h" 26#include "xfs_sb.h"
27#include "xfs_ag.h" 27#include "xfs_ag.h"
28#include "xfs_dir.h"
29#include "xfs_dir2.h" 28#include "xfs_dir2.h"
30#include "xfs_dmapi.h" 29#include "xfs_dmapi.h"
31#include "xfs_mount.h" 30#include "xfs_mount.h"
@@ -33,7 +32,6 @@
33#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
34#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
35#include "xfs_ialloc_btree.h" 34#include "xfs_ialloc_btree.h"
36#include "xfs_dir_sf.h"
37#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
38#include "xfs_attr_sf.h" 36#include "xfs_attr_sf.h"
39#include "xfs_dinode.h" 37#include "xfs_dinode.h"
@@ -794,7 +792,7 @@ xfs_inode_item_pushbuf(
794 * inode flush completed and the inode was taken off the AIL. 792 * inode flush completed and the inode was taken off the AIL.
795 * So, just get out. 793 * So, just get out.
796 */ 794 */
797 if ((valusema(&(ip->i_flock)) > 0) || 795 if (!issemalocked(&(ip->i_flock)) ||
798 ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) { 796 ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) {
799 iip->ili_pushbuf_flag = 0; 797 iip->ili_pushbuf_flag = 0;
800 xfs_iunlock(ip, XFS_ILOCK_SHARED); 798 xfs_iunlock(ip, XFS_ILOCK_SHARED);
@@ -816,7 +814,7 @@ xfs_inode_item_pushbuf(
816 * If not, we can flush it async. 814 * If not, we can flush it async.
817 */ 815 */
818 dopush = ((iip->ili_item.li_flags & XFS_LI_IN_AIL) && 816 dopush = ((iip->ili_item.li_flags & XFS_LI_IN_AIL) &&
819 (valusema(&(ip->i_flock)) <= 0)); 817 issemalocked(&(ip->i_flock)));
820 iip->ili_pushbuf_flag = 0; 818 iip->ili_pushbuf_flag = 0;
821 xfs_iunlock(ip, XFS_ILOCK_SHARED); 819 xfs_iunlock(ip, XFS_ILOCK_SHARED);
822 xfs_buftrace("INODE ITEM PUSH", bp); 820 xfs_buftrace("INODE ITEM PUSH", bp);
@@ -864,7 +862,7 @@ xfs_inode_item_push(
864 ip = iip->ili_inode; 862 ip = iip->ili_inode;
865 863
866 ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS)); 864 ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS));
867 ASSERT(valusema(&(ip->i_flock)) <= 0); 865 ASSERT(issemalocked(&(ip->i_flock)));
868 /* 866 /*
869 * Since we were able to lock the inode's flush lock and 867 * Since we were able to lock the inode's flush lock and
870 * we found it on the AIL, the inode must be dirty. This 868 * we found it on the AIL, the inode must be dirty. This
@@ -1084,3 +1082,52 @@ xfs_istale_done(
1084{ 1082{
1085 xfs_iflush_abort(iip->ili_inode); 1083 xfs_iflush_abort(iip->ili_inode);
1086} 1084}
1085
1086/*
1087 * convert an xfs_inode_log_format struct from either 32 or 64 bit versions
1088 * (which can have different field alignments) to the native version
1089 */
1090int
1091xfs_inode_item_format_convert(
1092 xfs_log_iovec_t *buf,
1093 xfs_inode_log_format_t *in_f)
1094{
1095 if (buf->i_len == sizeof(xfs_inode_log_format_32_t)) {
1096 xfs_inode_log_format_32_t *in_f32;
1097
1098 in_f32 = (xfs_inode_log_format_32_t *)buf->i_addr;
1099 in_f->ilf_type = in_f32->ilf_type;
1100 in_f->ilf_size = in_f32->ilf_size;
1101 in_f->ilf_fields = in_f32->ilf_fields;
1102 in_f->ilf_asize = in_f32->ilf_asize;
1103 in_f->ilf_dsize = in_f32->ilf_dsize;
1104 in_f->ilf_ino = in_f32->ilf_ino;
1105 /* copy biggest field of ilf_u */
1106 memcpy(in_f->ilf_u.ilfu_uuid.__u_bits,
1107 in_f32->ilf_u.ilfu_uuid.__u_bits,
1108 sizeof(uuid_t));
1109 in_f->ilf_blkno = in_f32->ilf_blkno;
1110 in_f->ilf_len = in_f32->ilf_len;
1111 in_f->ilf_boffset = in_f32->ilf_boffset;
1112 return 0;
1113 } else if (buf->i_len == sizeof(xfs_inode_log_format_64_t)){
1114 xfs_inode_log_format_64_t *in_f64;
1115
1116 in_f64 = (xfs_inode_log_format_64_t *)buf->i_addr;
1117 in_f->ilf_type = in_f64->ilf_type;
1118 in_f->ilf_size = in_f64->ilf_size;
1119 in_f->ilf_fields = in_f64->ilf_fields;
1120 in_f->ilf_asize = in_f64->ilf_asize;
1121 in_f->ilf_dsize = in_f64->ilf_dsize;
1122 in_f->ilf_ino = in_f64->ilf_ino;
1123 /* copy biggest field of ilf_u */
1124 memcpy(in_f->ilf_u.ilfu_uuid.__u_bits,
1125 in_f64->ilf_u.ilfu_uuid.__u_bits,
1126 sizeof(uuid_t));
1127 in_f->ilf_blkno = in_f64->ilf_blkno;
1128 in_f->ilf_len = in_f64->ilf_len;
1129 in_f->ilf_boffset = in_f64->ilf_boffset;
1130 return 0;
1131 }
1132 return EFSCORRUPTED;
1133}
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h
index c5dbf93b6661..5db6cd1b4cf3 100644
--- a/fs/xfs/xfs_inode_item.h
+++ b/fs/xfs/xfs_inode_item.h
@@ -23,25 +23,6 @@
23 * log. The size of the inline data/extents/b-tree root to be logged 23 * log. The size of the inline data/extents/b-tree root to be logged
24 * (if any) is indicated in the ilf_dsize field. Changes to this structure 24 * (if any) is indicated in the ilf_dsize field. Changes to this structure
25 * must be added on to the end. 25 * must be added on to the end.
26 *
27 * Convention for naming inode log item versions : The current version
28 * is always named XFS_LI_INODE. When an inode log item gets superseded,
29 * add the latest version of IRIX that will generate logs with that item
30 * to the version name.
31 *
32 * -Version 1 of this structure (XFS_LI_5_3_INODE) included up to the first
33 * union (ilf_u) field. This was released with IRIX 5.3-XFS.
34 * -Version 2 of this structure (XFS_LI_6_1_INODE) is currently the entire
35 * structure. This was released with IRIX 6.0.1-XFS and IRIX 6.1.
36 * -Version 3 of this structure (XFS_LI_INODE) is the same as version 2
37 * so a new structure definition wasn't necessary. However, we had
38 * to add a new type because the inode cluster size changed from 4K
39 * to 8K and the version number had to be rev'ved to keep older kernels
40 * from trying to recover logs with the 8K buffers in them. The logging
41 * code can handle recovery on different-sized clusters now so hopefully
42 * this'll be the last time we need to change the inode log item just
43 * for a change in the inode cluster size. This new version was
44 * released with IRIX 6.2.
45 */ 26 */
46typedef struct xfs_inode_log_format { 27typedef struct xfs_inode_log_format {
47 unsigned short ilf_type; /* inode log item type */ 28 unsigned short ilf_type; /* inode log item type */
@@ -59,18 +40,38 @@ typedef struct xfs_inode_log_format {
59 int ilf_boffset; /* off of inode in buffer */ 40 int ilf_boffset; /* off of inode in buffer */
60} xfs_inode_log_format_t; 41} xfs_inode_log_format_t;
61 42
62/* Initial version shipped with IRIX 5.3-XFS */ 43typedef struct xfs_inode_log_format_32 {
63typedef struct xfs_inode_log_format_v1 { 44 unsigned short ilf_type; /* 16: inode log item type */
64 unsigned short ilf_type; /* inode log item type */ 45 unsigned short ilf_size; /* 16: size of this item */
65 unsigned short ilf_size; /* size of this item */ 46 uint ilf_fields; /* 32: flags for fields logged */
66 uint ilf_fields; /* flags for fields logged */ 47 ushort ilf_asize; /* 32: size of attr d/ext/root */
67 uint ilf_dsize; /* size of data/ext/root */ 48 ushort ilf_dsize; /* 32: size of data/ext/root */
68 xfs_ino_t ilf_ino; /* inode number */ 49 xfs_ino_t ilf_ino; /* 64: inode number */
69 union { 50 union {
70 xfs_dev_t ilfu_rdev; /* rdev value for dev inode*/ 51 xfs_dev_t ilfu_rdev; /* 32: rdev value for dev inode*/
71 uuid_t ilfu_uuid; /* mount point value */ 52 uuid_t ilfu_uuid; /* 128: mount point value */
53 } ilf_u;
54 __int64_t ilf_blkno; /* 64: blkno of inode buffer */
55 int ilf_len; /* 32: len of inode buffer */
56 int ilf_boffset; /* 32: off of inode in buffer */
57} __attribute__((packed)) xfs_inode_log_format_32_t;
58
59typedef struct xfs_inode_log_format_64 {
60 unsigned short ilf_type; /* 16: inode log item type */
61 unsigned short ilf_size; /* 16: size of this item */
62 uint ilf_fields; /* 32: flags for fields logged */
63 ushort ilf_asize; /* 32: size of attr d/ext/root */
64 ushort ilf_dsize; /* 32: size of data/ext/root */
65 __uint32_t ilf_pad; /* 32: pad for 64 bit boundary */
66 xfs_ino_t ilf_ino; /* 64: inode number */
67 union {
68 xfs_dev_t ilfu_rdev; /* 32: rdev value for dev inode*/
69 uuid_t ilfu_uuid; /* 128: mount point value */
72 } ilf_u; 70 } ilf_u;
73} xfs_inode_log_format_t_v1; 71 __int64_t ilf_blkno; /* 64: blkno of inode buffer */
72 int ilf_len; /* 32: len of inode buffer */
73 int ilf_boffset; /* 32: off of inode in buffer */
74} xfs_inode_log_format_64_t;
74 75
75/* 76/*
76 * Flags for xfs_trans_log_inode flags field. 77 * Flags for xfs_trans_log_inode flags field.
@@ -172,6 +173,8 @@ extern void xfs_inode_item_destroy(struct xfs_inode *);
172extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *); 173extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *);
173extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *); 174extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *);
174extern void xfs_iflush_abort(struct xfs_inode *); 175extern void xfs_iflush_abort(struct xfs_inode *);
176extern int xfs_inode_item_format_convert(xfs_log_iovec_t *,
177 xfs_inode_log_format_t *);
175 178
176#endif /* __KERNEL__ */ 179#endif /* __KERNEL__ */
177 180
diff --git a/fs/xfs/xfs_iocore.c b/fs/xfs/xfs_iocore.c
index a07815661a8c..06d710c9ce4b 100644
--- a/fs/xfs/xfs_iocore.c
+++ b/fs/xfs/xfs_iocore.c
@@ -24,14 +24,13 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
28#include "xfs_dfrag.h"
29#include "xfs_dmapi.h" 29#include "xfs_dmapi.h"
30#include "xfs_mount.h" 30#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 36#include "xfs_dinode.h"
@@ -58,7 +57,7 @@ xfs_size_fn(
58 57
59STATIC int 58STATIC int
60xfs_ioinit( 59xfs_ioinit(
61 struct vfs *vfsp, 60 struct bhv_vfs *vfsp,
62 struct xfs_mount_args *mntargs, 61 struct xfs_mount_args *mntargs,
63 int flags) 62 int flags)
64{ 63{
@@ -68,6 +67,7 @@ xfs_ioinit(
68xfs_ioops_t xfs_iocore_xfs = { 67xfs_ioops_t xfs_iocore_xfs = {
69 .xfs_ioinit = (xfs_ioinit_t) xfs_ioinit, 68 .xfs_ioinit = (xfs_ioinit_t) xfs_ioinit,
70 .xfs_bmapi_func = (xfs_bmapi_t) xfs_bmapi, 69 .xfs_bmapi_func = (xfs_bmapi_t) xfs_bmapi,
70 .xfs_bunmapi_func = (xfs_bunmapi_t) xfs_bunmapi,
71 .xfs_bmap_eof_func = (xfs_bmap_eof_t) xfs_bmap_eof, 71 .xfs_bmap_eof_func = (xfs_bmap_eof_t) xfs_bmap_eof,
72 .xfs_iomap_write_direct = 72 .xfs_iomap_write_direct =
73 (xfs_iomap_write_direct_t) xfs_iomap_write_direct, 73 (xfs_iomap_write_direct_t) xfs_iomap_write_direct,
@@ -84,6 +84,7 @@ xfs_ioops_t xfs_iocore_xfs = {
84 .xfs_unlock = (xfs_unlk_t) xfs_iunlock, 84 .xfs_unlock = (xfs_unlk_t) xfs_iunlock,
85 .xfs_size_func = (xfs_size_t) xfs_size_fn, 85 .xfs_size_func = (xfs_size_t) xfs_size_fn,
86 .xfs_iodone = (xfs_iodone_t) fs_noerr, 86 .xfs_iodone = (xfs_iodone_t) fs_noerr,
87 .xfs_swap_extents_func = (xfs_swap_extents_t) xfs_swap_extents,
87}; 88};
88 89
89void 90void
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index d5dfedcb8922..f1949c16df15 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_alloc.h" 27#include "xfs_alloc.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
@@ -252,7 +250,7 @@ xfs_iomap(
252 error = XFS_BMAPI(mp, NULL, io, offset_fsb, 250 error = XFS_BMAPI(mp, NULL, io, offset_fsb,
253 (xfs_filblks_t)(end_fsb - offset_fsb), 251 (xfs_filblks_t)(end_fsb - offset_fsb),
254 bmapi_flags, NULL, 0, &imap, 252 bmapi_flags, NULL, 0, &imap,
255 &nimaps, NULL); 253 &nimaps, NULL, NULL);
256 254
257 if (error) 255 if (error)
258 goto out; 256 goto out;
@@ -519,8 +517,8 @@ xfs_iomap_write_direct(
519 */ 517 */
520 XFS_BMAP_INIT(&free_list, &firstfsb); 518 XFS_BMAP_INIT(&free_list, &firstfsb);
521 nimaps = 1; 519 nimaps = 1;
522 error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, 520 error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb, bmapi_flag,
523 bmapi_flag, &firstfsb, 0, &imap, &nimaps, &free_list); 521 &firstfsb, 0, &imap, &nimaps, &free_list, NULL);
524 if (error) 522 if (error)
525 goto error0; 523 goto error0;
526 524
@@ -610,8 +608,8 @@ xfs_iomap_eof_want_preallocate(
610 while (count_fsb > 0) { 608 while (count_fsb > 0) {
611 imaps = nimaps; 609 imaps = nimaps;
612 firstblock = NULLFSBLOCK; 610 firstblock = NULLFSBLOCK;
613 error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, 611 error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, 0,
614 0, &firstblock, 0, imap, &imaps, NULL); 612 &firstblock, 0, imap, &imaps, NULL, NULL);
615 if (error) 613 if (error)
616 return error; 614 return error;
617 for (n = 0; n < imaps; n++) { 615 for (n = 0; n < imaps; n++) {
@@ -695,11 +693,11 @@ retry:
695 693
696 nimaps = XFS_WRITE_IMAPS; 694 nimaps = XFS_WRITE_IMAPS;
697 firstblock = NULLFSBLOCK; 695 firstblock = NULLFSBLOCK;
698 error = xfs_bmapi(NULL, ip, offset_fsb, 696 error = XFS_BMAPI(mp, NULL, io, offset_fsb,
699 (xfs_filblks_t)(last_fsb - offset_fsb), 697 (xfs_filblks_t)(last_fsb - offset_fsb),
700 XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | 698 XFS_BMAPI_DELAY | XFS_BMAPI_WRITE |
701 XFS_BMAPI_ENTIRE, &firstblock, 1, imap, 699 XFS_BMAPI_ENTIRE, &firstblock, 1, imap,
702 &nimaps, NULL); 700 &nimaps, NULL, NULL);
703 if (error && (error != ENOSPC)) 701 if (error && (error != ENOSPC))
704 return XFS_ERROR(error); 702 return XFS_ERROR(error);
705 703
@@ -832,9 +830,9 @@ xfs_iomap_write_allocate(
832 } 830 }
833 831
834 /* Go get the actual blocks */ 832 /* Go get the actual blocks */
835 error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb, 833 error = XFS_BMAPI(mp, tp, io, map_start_fsb, count_fsb,
836 XFS_BMAPI_WRITE, &first_block, 1, 834 XFS_BMAPI_WRITE, &first_block, 1,
837 imap, &nimaps, &free_list); 835 imap, &nimaps, &free_list, NULL);
838 if (error) 836 if (error)
839 goto trans_cancel; 837 goto trans_cancel;
840 838
@@ -955,9 +953,9 @@ xfs_iomap_write_unwritten(
955 */ 953 */
956 XFS_BMAP_INIT(&free_list, &firstfsb); 954 XFS_BMAP_INIT(&free_list, &firstfsb);
957 nimaps = 1; 955 nimaps = 1;
958 error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, 956 error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb,
959 XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb, 957 XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb,
960 1, &imap, &nimaps, &free_list); 958 1, &imap, &nimaps, &free_list, NULL);
961 if (error) 959 if (error)
962 goto error_on_bmapi_transaction; 960 goto error_on_bmapi_transaction;
963 961
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 94068d014f27..46249e4d1fea 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
@@ -41,11 +39,6 @@
41#include "xfs_error.h" 39#include "xfs_error.h"
42#include "xfs_btree.h" 40#include "xfs_btree.h"
43 41
44#ifndef HAVE_USERACC
45#define useracc(ubuffer, size, flags, foo) (0)
46#define unuseracc(ubuffer, size, flags)
47#endif
48
49STATIC int 42STATIC int
50xfs_bulkstat_one_iget( 43xfs_bulkstat_one_iget(
51 xfs_mount_t *mp, /* mount point for filesystem */ 44 xfs_mount_t *mp, /* mount point for filesystem */
@@ -56,7 +49,7 @@ xfs_bulkstat_one_iget(
56{ 49{
57 xfs_dinode_core_t *dic; /* dinode core info pointer */ 50 xfs_dinode_core_t *dic; /* dinode core info pointer */
58 xfs_inode_t *ip; /* incore inode pointer */ 51 xfs_inode_t *ip; /* incore inode pointer */
59 vnode_t *vp; 52 bhv_vnode_t *vp;
60 int error; 53 int error;
61 54
62 error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno); 55 error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno);
@@ -336,15 +329,6 @@ xfs_bulkstat(
336 nimask = ~(nicluster - 1); 329 nimask = ~(nicluster - 1);
337 nbcluster = nicluster >> mp->m_sb.sb_inopblog; 330 nbcluster = nicluster >> mp->m_sb.sb_inopblog;
338 /* 331 /*
339 * Lock down the user's buffer. If a buffer was not sent, as in the case
340 * disk quota code calls here, we skip this.
341 */
342 if (ubuffer &&
343 (error = useracc(ubuffer, ubcount * statstruct_size,
344 (B_READ|B_PHYS), NULL))) {
345 return error;
346 }
347 /*
348 * Allocate a page-sized buffer for inode btree records. 332 * Allocate a page-sized buffer for inode btree records.
349 * We could try allocating something smaller, but for normal 333 * We could try allocating something smaller, but for normal
350 * calls we'll always (potentially) need the whole page. 334 * calls we'll always (potentially) need the whole page.
@@ -650,8 +634,6 @@ xfs_bulkstat(
650 * Done, we're either out of filesystem or space to put the data. 634 * Done, we're either out of filesystem or space to put the data.
651 */ 635 */
652 kmem_free(irbuf, NBPC); 636 kmem_free(irbuf, NBPC);
653 if (ubuffer)
654 unuseracc(ubuffer, ubcount * statstruct_size, (B_READ|B_PHYS));
655 *ubcountp = ubelem; 637 *ubcountp = ubelem;
656 if (agno >= mp->m_sb.sb_agcount) { 638 if (agno >= mp->m_sb.sb_agcount) {
657 /* 639 /*
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index 11eb4e1b18c4..be5f12e07d22 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -45,7 +45,6 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount *mp,
45 */ 45 */
46#define BULKSTAT_FG_IGET 0x1 /* Go through the buffer cache */ 46#define BULKSTAT_FG_IGET 0x1 /* Go through the buffer cache */
47#define BULKSTAT_FG_QUICK 0x2 /* No iget, walk the dinode cluster */ 47#define BULKSTAT_FG_QUICK 0x2 /* No iget, walk the dinode cluster */
48#define BULKSTAT_FG_VFSLOCKED 0x4 /* Already have vfs lock */
49 48
50/* 49/*
51 * Return stat information in bulk (by-inode) for the filesystem. 50 * Return stat information in bulk (by-inode) for the filesystem.
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 32e841d2f26d..d8f5d4cbe8b7 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -24,7 +24,6 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
@@ -36,7 +35,6 @@
36#include "xfs_ialloc_btree.h" 35#include "xfs_ialloc_btree.h"
37#include "xfs_log_recover.h" 36#include "xfs_log_recover.h"
38#include "xfs_trans_priv.h" 37#include "xfs_trans_priv.h"
39#include "xfs_dir_sf.h"
40#include "xfs_dir2_sf.h" 38#include "xfs_dir2_sf.h"
41#include "xfs_attr_sf.h" 39#include "xfs_attr_sf.h"
42#include "xfs_dinode.h" 40#include "xfs_dinode.h"
@@ -402,7 +400,7 @@ xfs_log_release_iclog(xfs_mount_t *mp,
402 xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl; 400 xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl;
403 401
404 if (xlog_state_release_iclog(log, iclog)) { 402 if (xlog_state_release_iclog(log, iclog)) {
405 xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); 403 xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
406 return EIO; 404 return EIO;
407 } 405 }
408 406
@@ -498,9 +496,8 @@ xfs_log_mount(xfs_mount_t *mp,
498 * just worked. 496 * just worked.
499 */ 497 */
500 if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) { 498 if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {
501 int error; 499 bhv_vfs_t *vfsp = XFS_MTOVFS(mp);
502 vfs_t *vfsp = XFS_MTOVFS(mp); 500 int error, readonly = (vfsp->vfs_flag & VFS_RDONLY);
503 int readonly = (vfsp->vfs_flag & VFS_RDONLY);
504 501
505 if (readonly) 502 if (readonly)
506 vfsp->vfs_flag &= ~VFS_RDONLY; 503 vfsp->vfs_flag &= ~VFS_RDONLY;
@@ -726,7 +723,7 @@ xfs_log_write(xfs_mount_t * mp,
726 return XFS_ERROR(EIO); 723 return XFS_ERROR(EIO);
727 724
728 if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) { 725 if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) {
729 xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); 726 xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
730 } 727 }
731 return error; 728 return error;
732} /* xfs_log_write */ 729} /* xfs_log_write */
@@ -816,9 +813,9 @@ xfs_log_need_covered(xfs_mount_t *mp)
816 SPLDECL(s); 813 SPLDECL(s);
817 int needed = 0, gen; 814 int needed = 0, gen;
818 xlog_t *log = mp->m_log; 815 xlog_t *log = mp->m_log;
819 vfs_t *vfsp = XFS_MTOVFS(mp); 816 bhv_vfs_t *vfsp = XFS_MTOVFS(mp);
820 817
821 if (fs_frozen(vfsp) || XFS_FORCED_SHUTDOWN(mp) || 818 if (vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
822 (vfsp->vfs_flag & VFS_RDONLY)) 819 (vfsp->vfs_flag & VFS_RDONLY))
823 return 0; 820 return 0;
824 821
@@ -956,7 +953,7 @@ xlog_iodone(xfs_buf_t *bp)
956 XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) { 953 XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) {
957 xfs_ioerror_alert("xlog_iodone", l->l_mp, bp, XFS_BUF_ADDR(bp)); 954 xfs_ioerror_alert("xlog_iodone", l->l_mp, bp, XFS_BUF_ADDR(bp));
958 XFS_BUF_STALE(bp); 955 XFS_BUF_STALE(bp);
959 xfs_force_shutdown(l->l_mp, XFS_LOG_IO_ERROR); 956 xfs_force_shutdown(l->l_mp, SHUTDOWN_LOG_IO_ERROR);
960 /* 957 /*
961 * This flag will be propagated to the trans-committed 958 * This flag will be propagated to the trans-committed
962 * callback routines to let them know that the log-commit 959 * callback routines to let them know that the log-commit
@@ -1261,7 +1258,7 @@ xlog_commit_record(xfs_mount_t *mp,
1261 ASSERT_ALWAYS(iclog); 1258 ASSERT_ALWAYS(iclog);
1262 if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp, 1259 if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp,
1263 iclog, XLOG_COMMIT_TRANS))) { 1260 iclog, XLOG_COMMIT_TRANS))) {
1264 xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); 1261 xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
1265 } 1262 }
1266 return error; 1263 return error;
1267} /* xlog_commit_record */ 1264} /* xlog_commit_record */
@@ -1790,7 +1787,7 @@ xlog_write(xfs_mount_t * mp,
1790 xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp, 1787 xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp,
1791 "xfs_log_write: reservation ran out. Need to up reservation"); 1788 "xfs_log_write: reservation ran out. Need to up reservation");
1792 /* If we did not panic, shutdown the filesystem */ 1789 /* If we did not panic, shutdown the filesystem */
1793 xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); 1790 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
1794#endif 1791#endif
1795 } else 1792 } else
1796 ticket->t_curr_res -= len; 1793 ticket->t_curr_res -= len;
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 1f0016b0b4ec..55b4237c2153 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -24,7 +24,6 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_ialloc_btree.h" 33#include "xfs_ialloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
@@ -193,14 +191,14 @@ xlog_header_check_dump(
193{ 191{
194 int b; 192 int b;
195 193
196 printk("%s: SB : uuid = ", __FUNCTION__); 194 cmn_err(CE_DEBUG, "%s: SB : uuid = ", __FUNCTION__);
197 for (b = 0; b < 16; b++) 195 for (b = 0; b < 16; b++)
198 printk("%02x",((unsigned char *)&mp->m_sb.sb_uuid)[b]); 196 cmn_err(CE_DEBUG, "%02x", ((uchar_t *)&mp->m_sb.sb_uuid)[b]);
199 printk(", fmt = %d\n", XLOG_FMT); 197 cmn_err(CE_DEBUG, ", fmt = %d\n", XLOG_FMT);
200 printk(" log : uuid = "); 198 cmn_err(CE_DEBUG, " log : uuid = ");
201 for (b = 0; b < 16; b++) 199 for (b = 0; b < 16; b++)
202 printk("%02x",((unsigned char *)&head->h_fs_uuid)[b]); 200 cmn_err(CE_DEBUG, "%02x",((uchar_t *)&head->h_fs_uuid)[b]);
203 printk(", fmt = %d\n", INT_GET(head->h_fmt, ARCH_CONVERT)); 201 cmn_err(CE_DEBUG, ", fmt = %d\n", INT_GET(head->h_fmt, ARCH_CONVERT));
204} 202}
205#else 203#else
206#define xlog_header_check_dump(mp, head) 204#define xlog_header_check_dump(mp, head)
@@ -282,7 +280,7 @@ xlog_recover_iodone(
282 mp = XFS_BUF_FSPRIVATE(bp, xfs_mount_t *); 280 mp = XFS_BUF_FSPRIVATE(bp, xfs_mount_t *);
283 xfs_ioerror_alert("xlog_recover_iodone", 281 xfs_ioerror_alert("xlog_recover_iodone",
284 mp, bp, XFS_BUF_ADDR(bp)); 282 mp, bp, XFS_BUF_ADDR(bp));
285 xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); 283 xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
286 } 284 }
287 XFS_BUF_SET_FSPRIVATE(bp, NULL); 285 XFS_BUF_SET_FSPRIVATE(bp, NULL);
288 XFS_BUF_CLR_IODONE_FUNC(bp); 286 XFS_BUF_CLR_IODONE_FUNC(bp);
@@ -1889,7 +1887,7 @@ xlog_recover_do_inode_buffer(
1889 1887
1890 buffer_nextp = (xfs_agino_t *)xfs_buf_offset(bp, 1888 buffer_nextp = (xfs_agino_t *)xfs_buf_offset(bp,
1891 next_unlinked_offset); 1889 next_unlinked_offset);
1892 INT_SET(*buffer_nextp, ARCH_CONVERT, *logged_nextp); 1890 *buffer_nextp = *logged_nextp;
1893 } 1891 }
1894 1892
1895 return 0; 1893 return 0;
@@ -2292,12 +2290,22 @@ xlog_recover_do_inode_trans(
2292 int attr_index; 2290 int attr_index;
2293 uint fields; 2291 uint fields;
2294 xfs_dinode_core_t *dicp; 2292 xfs_dinode_core_t *dicp;
2293 int need_free = 0;
2295 2294
2296 if (pass == XLOG_RECOVER_PASS1) { 2295 if (pass == XLOG_RECOVER_PASS1) {
2297 return 0; 2296 return 0;
2298 } 2297 }
2299 2298
2300 in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr; 2299 if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) {
2300 in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr;
2301 } else {
2302 in_f = (xfs_inode_log_format_t *)kmem_alloc(
2303 sizeof(xfs_inode_log_format_t), KM_SLEEP);
2304 need_free = 1;
2305 error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f);
2306 if (error)
2307 goto error;
2308 }
2301 ino = in_f->ilf_ino; 2309 ino = in_f->ilf_ino;
2302 mp = log->l_mp; 2310 mp = log->l_mp;
2303 if (ITEM_TYPE(item) == XFS_LI_INODE) { 2311 if (ITEM_TYPE(item) == XFS_LI_INODE) {
@@ -2323,8 +2331,10 @@ xlog_recover_do_inode_trans(
2323 * Inode buffers can be freed, look out for it, 2331 * Inode buffers can be freed, look out for it,
2324 * and do not replay the inode. 2332 * and do not replay the inode.
2325 */ 2333 */
2326 if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) 2334 if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) {
2327 return 0; 2335 error = 0;
2336 goto error;
2337 }
2328 2338
2329 bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len, 2339 bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len,
2330 XFS_BUF_LOCK); 2340 XFS_BUF_LOCK);
@@ -2333,7 +2343,7 @@ xlog_recover_do_inode_trans(
2333 bp, imap.im_blkno); 2343 bp, imap.im_blkno);
2334 error = XFS_BUF_GETERROR(bp); 2344 error = XFS_BUF_GETERROR(bp);
2335 xfs_buf_relse(bp); 2345 xfs_buf_relse(bp);
2336 return error; 2346 goto error;
2337 } 2347 }
2338 error = 0; 2348 error = 0;
2339 ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); 2349 ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
@@ -2350,7 +2360,8 @@ xlog_recover_do_inode_trans(
2350 dip, bp, ino); 2360 dip, bp, ino);
2351 XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)", 2361 XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)",
2352 XFS_ERRLEVEL_LOW, mp); 2362 XFS_ERRLEVEL_LOW, mp);
2353 return XFS_ERROR(EFSCORRUPTED); 2363 error = EFSCORRUPTED;
2364 goto error;
2354 } 2365 }
2355 dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr); 2366 dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr);
2356 if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { 2367 if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) {
@@ -2360,7 +2371,8 @@ xlog_recover_do_inode_trans(
2360 item, ino); 2371 item, ino);
2361 XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)", 2372 XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)",
2362 XFS_ERRLEVEL_LOW, mp); 2373 XFS_ERRLEVEL_LOW, mp);
2363 return XFS_ERROR(EFSCORRUPTED); 2374 error = EFSCORRUPTED;
2375 goto error;
2364 } 2376 }
2365 2377
2366 /* Skip replay when the on disk inode is newer than the log one */ 2378 /* Skip replay when the on disk inode is newer than the log one */
@@ -2376,7 +2388,8 @@ xlog_recover_do_inode_trans(
2376 /* do nothing */ 2388 /* do nothing */
2377 } else { 2389 } else {
2378 xfs_buf_relse(bp); 2390 xfs_buf_relse(bp);
2379 return 0; 2391 error = 0;
2392 goto error;
2380 } 2393 }
2381 } 2394 }
2382 /* Take the opportunity to reset the flush iteration count */ 2395 /* Take the opportunity to reset the flush iteration count */
@@ -2391,7 +2404,8 @@ xlog_recover_do_inode_trans(
2391 xfs_fs_cmn_err(CE_ALERT, mp, 2404 xfs_fs_cmn_err(CE_ALERT, mp,
2392 "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", 2405 "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
2393 item, dip, bp, ino); 2406 item, dip, bp, ino);
2394 return XFS_ERROR(EFSCORRUPTED); 2407 error = EFSCORRUPTED;
2408 goto error;
2395 } 2409 }
2396 } else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) { 2410 } else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) {
2397 if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && 2411 if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
@@ -2403,7 +2417,8 @@ xlog_recover_do_inode_trans(
2403 xfs_fs_cmn_err(CE_ALERT, mp, 2417 xfs_fs_cmn_err(CE_ALERT, mp,
2404 "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", 2418 "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
2405 item, dip, bp, ino); 2419 item, dip, bp, ino);
2406 return XFS_ERROR(EFSCORRUPTED); 2420 error = EFSCORRUPTED;
2421 goto error;
2407 } 2422 }
2408 } 2423 }
2409 if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ 2424 if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){
@@ -2415,7 +2430,8 @@ xlog_recover_do_inode_trans(
2415 item, dip, bp, ino, 2430 item, dip, bp, ino,
2416 dicp->di_nextents + dicp->di_anextents, 2431 dicp->di_nextents + dicp->di_anextents,
2417 dicp->di_nblocks); 2432 dicp->di_nblocks);
2418 return XFS_ERROR(EFSCORRUPTED); 2433 error = EFSCORRUPTED;
2434 goto error;
2419 } 2435 }
2420 if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { 2436 if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) {
2421 XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)", 2437 XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)",
@@ -2424,7 +2440,8 @@ xlog_recover_do_inode_trans(
2424 xfs_fs_cmn_err(CE_ALERT, mp, 2440 xfs_fs_cmn_err(CE_ALERT, mp,
2425 "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", 2441 "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x",
2426 item, dip, bp, ino, dicp->di_forkoff); 2442 item, dip, bp, ino, dicp->di_forkoff);
2427 return XFS_ERROR(EFSCORRUPTED); 2443 error = EFSCORRUPTED;
2444 goto error;
2428 } 2445 }
2429 if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) { 2446 if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) {
2430 XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)", 2447 XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)",
@@ -2433,7 +2450,8 @@ xlog_recover_do_inode_trans(
2433 xfs_fs_cmn_err(CE_ALERT, mp, 2450 xfs_fs_cmn_err(CE_ALERT, mp,
2434 "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p", 2451 "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p",
2435 item->ri_buf[1].i_len, item); 2452 item->ri_buf[1].i_len, item);
2436 return XFS_ERROR(EFSCORRUPTED); 2453 error = EFSCORRUPTED;
2454 goto error;
2437 } 2455 }
2438 2456
2439 /* The core is in in-core format */ 2457 /* The core is in in-core format */
@@ -2521,7 +2539,8 @@ xlog_recover_do_inode_trans(
2521 xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag"); 2539 xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag");
2522 ASSERT(0); 2540 ASSERT(0);
2523 xfs_buf_relse(bp); 2541 xfs_buf_relse(bp);
2524 return XFS_ERROR(EIO); 2542 error = EIO;
2543 goto error;
2525 } 2544 }
2526 } 2545 }
2527 2546
@@ -2537,7 +2556,10 @@ write_inode_buffer:
2537 error = xfs_bwrite(mp, bp); 2556 error = xfs_bwrite(mp, bp);
2538 } 2557 }
2539 2558
2540 return (error); 2559error:
2560 if (need_free)
2561 kmem_free(in_f, sizeof(*in_f));
2562 return XFS_ERROR(error);
2541} 2563}
2542 2564
2543/* 2565/*
@@ -2674,32 +2696,32 @@ xlog_recover_do_dquot_trans(
2674 * structure into it, and adds the efi to the AIL with the given 2696 * structure into it, and adds the efi to the AIL with the given
2675 * LSN. 2697 * LSN.
2676 */ 2698 */
2677STATIC void 2699STATIC int
2678xlog_recover_do_efi_trans( 2700xlog_recover_do_efi_trans(
2679 xlog_t *log, 2701 xlog_t *log,
2680 xlog_recover_item_t *item, 2702 xlog_recover_item_t *item,
2681 xfs_lsn_t lsn, 2703 xfs_lsn_t lsn,
2682 int pass) 2704 int pass)
2683{ 2705{
2706 int error;
2684 xfs_mount_t *mp; 2707 xfs_mount_t *mp;
2685 xfs_efi_log_item_t *efip; 2708 xfs_efi_log_item_t *efip;
2686 xfs_efi_log_format_t *efi_formatp; 2709 xfs_efi_log_format_t *efi_formatp;
2687 SPLDECL(s); 2710 SPLDECL(s);
2688 2711
2689 if (pass == XLOG_RECOVER_PASS1) { 2712 if (pass == XLOG_RECOVER_PASS1) {
2690 return; 2713 return 0;
2691 } 2714 }
2692 2715
2693 efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr; 2716 efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr;
2694 ASSERT(item->ri_buf[0].i_len ==
2695 (sizeof(xfs_efi_log_format_t) +
2696 ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t))));
2697 2717
2698 mp = log->l_mp; 2718 mp = log->l_mp;
2699 efip = xfs_efi_init(mp, efi_formatp->efi_nextents); 2719 efip = xfs_efi_init(mp, efi_formatp->efi_nextents);
2700 memcpy((char *)&(efip->efi_format), (char *)efi_formatp, 2720 if ((error = xfs_efi_copy_format(&(item->ri_buf[0]),
2701 sizeof(xfs_efi_log_format_t) + 2721 &(efip->efi_format)))) {
2702 ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t))); 2722 xfs_efi_item_free(efip);
2723 return error;
2724 }
2703 efip->efi_next_extent = efi_formatp->efi_nextents; 2725 efip->efi_next_extent = efi_formatp->efi_nextents;
2704 efip->efi_flags |= XFS_EFI_COMMITTED; 2726 efip->efi_flags |= XFS_EFI_COMMITTED;
2705 2727
@@ -2708,6 +2730,7 @@ xlog_recover_do_efi_trans(
2708 * xfs_trans_update_ail() drops the AIL lock. 2730 * xfs_trans_update_ail() drops the AIL lock.
2709 */ 2731 */
2710 xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s); 2732 xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s);
2733 return 0;
2711} 2734}
2712 2735
2713 2736
@@ -2738,9 +2761,10 @@ xlog_recover_do_efd_trans(
2738 } 2761 }
2739 2762
2740 efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr; 2763 efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr;
2741 ASSERT(item->ri_buf[0].i_len == 2764 ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) +
2742 (sizeof(xfs_efd_log_format_t) + 2765 ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) ||
2743 ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_t)))); 2766 (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) +
2767 ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_64_t)))));
2744 efi_id = efd_formatp->efd_efi_id; 2768 efi_id = efd_formatp->efd_efi_id;
2745 2769
2746 /* 2770 /*
@@ -2810,15 +2834,14 @@ xlog_recover_do_trans(
2810 if ((error = xlog_recover_do_buffer_trans(log, item, 2834 if ((error = xlog_recover_do_buffer_trans(log, item,
2811 pass))) 2835 pass)))
2812 break; 2836 break;
2813 } else if ((ITEM_TYPE(item) == XFS_LI_INODE) || 2837 } else if ((ITEM_TYPE(item) == XFS_LI_INODE)) {
2814 (ITEM_TYPE(item) == XFS_LI_6_1_INODE) ||
2815 (ITEM_TYPE(item) == XFS_LI_5_3_INODE)) {
2816 if ((error = xlog_recover_do_inode_trans(log, item, 2838 if ((error = xlog_recover_do_inode_trans(log, item,
2817 pass))) 2839 pass)))
2818 break; 2840 break;
2819 } else if (ITEM_TYPE(item) == XFS_LI_EFI) { 2841 } else if (ITEM_TYPE(item) == XFS_LI_EFI) {
2820 xlog_recover_do_efi_trans(log, item, trans->r_lsn, 2842 if ((error = xlog_recover_do_efi_trans(log, item, trans->r_lsn,
2821 pass); 2843 pass)))
2844 break;
2822 } else if (ITEM_TYPE(item) == XFS_LI_EFD) { 2845 } else if (ITEM_TYPE(item) == XFS_LI_EFD) {
2823 xlog_recover_do_efd_trans(log, item, pass); 2846 xlog_recover_do_efd_trans(log, item, pass);
2824 } else if (ITEM_TYPE(item) == XFS_LI_DQUOT) { 2847 } else if (ITEM_TYPE(item) == XFS_LI_DQUOT) {
@@ -3419,13 +3442,13 @@ xlog_unpack_data_checksum(
3419 if (rhead->h_chksum || 3442 if (rhead->h_chksum ||
3420 ((log->l_flags & XLOG_CHKSUM_MISMATCH) == 0)) { 3443 ((log->l_flags & XLOG_CHKSUM_MISMATCH) == 0)) {
3421 cmn_err(CE_DEBUG, 3444 cmn_err(CE_DEBUG,
3422 "XFS: LogR chksum mismatch: was (0x%x) is (0x%x)", 3445 "XFS: LogR chksum mismatch: was (0x%x) is (0x%x)\n",
3423 INT_GET(rhead->h_chksum, ARCH_CONVERT), chksum); 3446 INT_GET(rhead->h_chksum, ARCH_CONVERT), chksum);
3424 cmn_err(CE_DEBUG, 3447 cmn_err(CE_DEBUG,
3425"XFS: Disregard message if filesystem was created with non-DEBUG kernel"); 3448"XFS: Disregard message if filesystem was created with non-DEBUG kernel");
3426 if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) { 3449 if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
3427 cmn_err(CE_DEBUG, 3450 cmn_err(CE_DEBUG,
3428 "XFS: LogR this is a LogV2 filesystem"); 3451 "XFS: LogR this is a LogV2 filesystem\n");
3429 } 3452 }
3430 log->l_flags |= XLOG_CHKSUM_MISMATCH; 3453 log->l_flags |= XLOG_CHKSUM_MISMATCH;
3431 } 3454 }
@@ -3798,7 +3821,7 @@ xlog_do_log_recovery(
3798 error = xlog_do_recovery_pass(log, head_blk, tail_blk, 3821 error = xlog_do_recovery_pass(log, head_blk, tail_blk,
3799 XLOG_RECOVER_PASS2); 3822 XLOG_RECOVER_PASS2);
3800#ifdef DEBUG 3823#ifdef DEBUG
3801 { 3824 if (!error) {
3802 int i; 3825 int i;
3803 3826
3804 for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) 3827 for (i = 0; i < XLOG_BC_TABLE_SIZE; i++)
@@ -3974,7 +3997,7 @@ xlog_recover_finish(
3974 log->l_flags &= ~XLOG_RECOVERY_NEEDED; 3997 log->l_flags &= ~XLOG_RECOVERY_NEEDED;
3975 } else { 3998 } else {
3976 cmn_err(CE_DEBUG, 3999 cmn_err(CE_DEBUG,
3977 "!Ending clean XFS mount for filesystem: %s", 4000 "!Ending clean XFS mount for filesystem: %s\n",
3978 log->l_mp->m_fsname); 4001 log->l_mp->m_fsname);
3979 } 4002 }
3980 return 0; 4003 return 0;
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index c0b1c2906880..10dbf203c62f 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
@@ -196,7 +194,7 @@ xfs_mount_free(
196 kmem_free(mp->m_logname, strlen(mp->m_logname) + 1); 194 kmem_free(mp->m_logname, strlen(mp->m_logname) + 1);
197 195
198 if (remove_bhv) { 196 if (remove_bhv) {
199 struct vfs *vfsp = XFS_MTOVFS(mp); 197 struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
200 198
201 bhv_remove_all_vfsops(vfsp, 0); 199 bhv_remove_all_vfsops(vfsp, 0);
202 VFS_REMOVEBHV(vfsp, &mp->m_bhv); 200 VFS_REMOVEBHV(vfsp, &mp->m_bhv);
@@ -337,7 +335,7 @@ xfs_mount_validate_sb(
337 335
338xfs_agnumber_t 336xfs_agnumber_t
339xfs_initialize_perag( 337xfs_initialize_perag(
340 struct vfs *vfs, 338 bhv_vfs_t *vfs,
341 xfs_mount_t *mp, 339 xfs_mount_t *mp,
342 xfs_agnumber_t agcount) 340 xfs_agnumber_t agcount)
343{ 341{
@@ -651,14 +649,14 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
651 */ 649 */
652int 650int
653xfs_mountfs( 651xfs_mountfs(
654 vfs_t *vfsp, 652 bhv_vfs_t *vfsp,
655 xfs_mount_t *mp, 653 xfs_mount_t *mp,
656 int mfsi_flags) 654 int mfsi_flags)
657{ 655{
658 xfs_buf_t *bp; 656 xfs_buf_t *bp;
659 xfs_sb_t *sbp = &(mp->m_sb); 657 xfs_sb_t *sbp = &(mp->m_sb);
660 xfs_inode_t *rip; 658 xfs_inode_t *rip;
661 vnode_t *rvp = NULL; 659 bhv_vnode_t *rvp = NULL;
662 int readio_log, writeio_log; 660 int readio_log, writeio_log;
663 xfs_daddr_t d; 661 xfs_daddr_t d;
664 __uint64_t ret64; 662 __uint64_t ret64;
@@ -934,18 +932,7 @@ xfs_mountfs(
934 vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid; 932 vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid;
935 mp->m_dmevmask = 0; /* not persistent; set after each mount */ 933 mp->m_dmevmask = 0; /* not persistent; set after each mount */
936 934
937 /* 935 xfs_dir_mount(mp);
938 * Select the right directory manager.
939 */
940 mp->m_dirops =
941 XFS_SB_VERSION_HASDIRV2(&mp->m_sb) ?
942 xfsv2_dirops :
943 xfsv1_dirops;
944
945 /*
946 * Initialize directory manager's entries.
947 */
948 XFS_DIR_MOUNT(mp);
949 936
950 /* 937 /*
951 * Initialize the attribute manager's entries. 938 * Initialize the attribute manager's entries.
@@ -1006,8 +993,9 @@ xfs_mountfs(
1006 993
1007 if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) { 994 if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
1008 cmn_err(CE_WARN, "XFS: corrupted root inode"); 995 cmn_err(CE_WARN, "XFS: corrupted root inode");
1009 prdev("Root inode %llu is not a directory", 996 cmn_err(CE_WARN, "Device %s - root %llu is not a directory",
1010 mp->m_ddev_targp, (unsigned long long)rip->i_ino); 997 XFS_BUFTARG_NAME(mp->m_ddev_targp),
998 (unsigned long long)rip->i_ino);
1011 xfs_iunlock(rip, XFS_ILOCK_EXCL); 999 xfs_iunlock(rip, XFS_ILOCK_EXCL);
1012 XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, 1000 XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW,
1013 mp); 1001 mp);
@@ -1094,7 +1082,7 @@ xfs_mountfs(
1094int 1082int
1095xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) 1083xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
1096{ 1084{
1097 struct vfs *vfsp = XFS_MTOVFS(mp); 1085 struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
1098#if defined(DEBUG) || defined(INDUCE_IO_ERROR) 1086#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
1099 int64_t fsid; 1087 int64_t fsid;
1100#endif 1088#endif
@@ -1254,6 +1242,26 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
1254 1242
1255 xfs_trans_log_buf(tp, bp, first, last); 1243 xfs_trans_log_buf(tp, bp, first, last);
1256} 1244}
1245
1246/*
1247 * In order to avoid ENOSPC-related deadlock caused by
1248 * out-of-order locking of AGF buffer (PV 947395), we place
1249 * constraints on the relationship among actual allocations for
1250 * data blocks, freelist blocks, and potential file data bmap
1251 * btree blocks. However, these restrictions may result in no
1252 * actual space allocated for a delayed extent, for example, a data
1253 * block in a certain AG is allocated but there is no additional
1254 * block for the additional bmap btree block due to a split of the
1255 * bmap btree of the file. The result of this may lead to an
1256 * infinite loop in xfssyncd when the file gets flushed to disk and
1257 * all delayed extents need to be actually allocated. To get around
1258 * this, we explicitly set aside a few blocks which will not be
1259 * reserved in delayed allocation. Considering the minimum number of
1260 * needed freelist blocks is 4 fsbs, a potential split of file's bmap
1261 * btree requires 1 fsb, so we set the number of set-aside blocks to 8.
1262*/
1263#define SET_ASIDE_BLOCKS 8
1264
1257/* 1265/*
1258 * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply 1266 * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply
1259 * a delta to a specified field in the in-core superblock. Simply 1267 * a delta to a specified field in the in-core superblock. Simply
@@ -1298,7 +1306,7 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field,
1298 return 0; 1306 return 0;
1299 case XFS_SBS_FDBLOCKS: 1307 case XFS_SBS_FDBLOCKS:
1300 1308
1301 lcounter = (long long)mp->m_sb.sb_fdblocks; 1309 lcounter = (long long)mp->m_sb.sb_fdblocks - SET_ASIDE_BLOCKS;
1302 res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); 1310 res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
1303 1311
1304 if (delta > 0) { /* Putting blocks back */ 1312 if (delta > 0) { /* Putting blocks back */
@@ -1332,7 +1340,7 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field,
1332 } 1340 }
1333 } 1341 }
1334 1342
1335 mp->m_sb.sb_fdblocks = lcounter; 1343 mp->m_sb.sb_fdblocks = lcounter + SET_ASIDE_BLOCKS;
1336 return 0; 1344 return 0;
1337 case XFS_SBS_FREXTENTS: 1345 case XFS_SBS_FREXTENTS:
1338 lcounter = (long long)mp->m_sb.sb_frextents; 1346 lcounter = (long long)mp->m_sb.sb_frextents;
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 668ad23fd37c..b2bd4be4200a 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -53,8 +53,8 @@ typedef struct xfs_trans_reservations {
53#else 53#else
54struct cred; 54struct cred;
55struct log; 55struct log;
56struct vfs; 56struct bhv_vfs;
57struct vnode; 57struct bhv_vnode;
58struct xfs_mount_args; 58struct xfs_mount_args;
59struct xfs_ihash; 59struct xfs_ihash;
60struct xfs_chash; 60struct xfs_chash;
@@ -63,9 +63,11 @@ struct xfs_perag;
63struct xfs_iocore; 63struct xfs_iocore;
64struct xfs_bmbt_irec; 64struct xfs_bmbt_irec;
65struct xfs_bmap_free; 65struct xfs_bmap_free;
66struct xfs_extdelta;
67struct xfs_swapext;
66 68
67extern struct vfsops xfs_vfsops; 69extern struct bhv_vfsops xfs_vfsops;
68extern struct vnodeops xfs_vnodeops; 70extern struct bhv_vnodeops xfs_vnodeops;
69 71
70#define AIL_LOCK_T lock_t 72#define AIL_LOCK_T lock_t
71#define AIL_LOCKINIT(x,y) spinlock_init(x,y) 73#define AIL_LOCKINIT(x,y) spinlock_init(x,y)
@@ -78,15 +80,15 @@ extern struct vnodeops xfs_vnodeops;
78 * Prototypes and functions for the Data Migration subsystem. 80 * Prototypes and functions for the Data Migration subsystem.
79 */ 81 */
80 82
81typedef int (*xfs_send_data_t)(int, struct vnode *, 83typedef int (*xfs_send_data_t)(int, struct bhv_vnode *,
82 xfs_off_t, size_t, int, vrwlock_t *); 84 xfs_off_t, size_t, int, bhv_vrwlock_t *);
83typedef int (*xfs_send_mmap_t)(struct vm_area_struct *, uint); 85typedef int (*xfs_send_mmap_t)(struct vm_area_struct *, uint);
84typedef int (*xfs_send_destroy_t)(struct vnode *, dm_right_t); 86typedef int (*xfs_send_destroy_t)(struct bhv_vnode *, dm_right_t);
85typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct vfs *, 87typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct bhv_vfs *,
86 struct vnode *, 88 struct bhv_vnode *,
87 dm_right_t, struct vnode *, dm_right_t, 89 dm_right_t, struct bhv_vnode *, dm_right_t,
88 char *, char *, mode_t, int, int); 90 char *, char *, mode_t, int, int);
89typedef void (*xfs_send_unmount_t)(struct vfs *, struct vnode *, 91typedef void (*xfs_send_unmount_t)(struct bhv_vfs *, struct bhv_vnode *,
90 dm_right_t, mode_t, int, int); 92 dm_right_t, mode_t, int, int);
91 93
92typedef struct xfs_dmops { 94typedef struct xfs_dmops {
@@ -188,13 +190,18 @@ typedef struct xfs_qmops {
188 * Prototypes and functions for I/O core modularization. 190 * Prototypes and functions for I/O core modularization.
189 */ 191 */
190 192
191typedef int (*xfs_ioinit_t)(struct vfs *, 193typedef int (*xfs_ioinit_t)(struct bhv_vfs *,
192 struct xfs_mount_args *, int); 194 struct xfs_mount_args *, int);
193typedef int (*xfs_bmapi_t)(struct xfs_trans *, void *, 195typedef int (*xfs_bmapi_t)(struct xfs_trans *, void *,
194 xfs_fileoff_t, xfs_filblks_t, int, 196 xfs_fileoff_t, xfs_filblks_t, int,
195 xfs_fsblock_t *, xfs_extlen_t, 197 xfs_fsblock_t *, xfs_extlen_t,
196 struct xfs_bmbt_irec *, int *, 198 struct xfs_bmbt_irec *, int *,
197 struct xfs_bmap_free *); 199 struct xfs_bmap_free *, struct xfs_extdelta *);
200typedef int (*xfs_bunmapi_t)(struct xfs_trans *,
201 void *, xfs_fileoff_t,
202 xfs_filblks_t, int, xfs_extnum_t,
203 xfs_fsblock_t *, struct xfs_bmap_free *,
204 struct xfs_extdelta *, int *);
198typedef int (*xfs_bmap_eof_t)(void *, xfs_fileoff_t, int, int *); 205typedef int (*xfs_bmap_eof_t)(void *, xfs_fileoff_t, int, int *);
199typedef int (*xfs_iomap_write_direct_t)( 206typedef int (*xfs_iomap_write_direct_t)(
200 void *, xfs_off_t, size_t, int, 207 void *, xfs_off_t, size_t, int,
@@ -213,11 +220,14 @@ typedef void (*xfs_lock_demote_t)(void *, uint);
213typedef int (*xfs_lock_nowait_t)(void *, uint); 220typedef int (*xfs_lock_nowait_t)(void *, uint);
214typedef void (*xfs_unlk_t)(void *, unsigned int); 221typedef void (*xfs_unlk_t)(void *, unsigned int);
215typedef xfs_fsize_t (*xfs_size_t)(void *); 222typedef xfs_fsize_t (*xfs_size_t)(void *);
216typedef xfs_fsize_t (*xfs_iodone_t)(struct vfs *); 223typedef xfs_fsize_t (*xfs_iodone_t)(struct bhv_vfs *);
224typedef int (*xfs_swap_extents_t)(void *, void *,
225 struct xfs_swapext*);
217 226
218typedef struct xfs_ioops { 227typedef struct xfs_ioops {
219 xfs_ioinit_t xfs_ioinit; 228 xfs_ioinit_t xfs_ioinit;
220 xfs_bmapi_t xfs_bmapi_func; 229 xfs_bmapi_t xfs_bmapi_func;
230 xfs_bunmapi_t xfs_bunmapi_func;
221 xfs_bmap_eof_t xfs_bmap_eof_func; 231 xfs_bmap_eof_t xfs_bmap_eof_func;
222 xfs_iomap_write_direct_t xfs_iomap_write_direct; 232 xfs_iomap_write_direct_t xfs_iomap_write_direct;
223 xfs_iomap_write_delay_t xfs_iomap_write_delay; 233 xfs_iomap_write_delay_t xfs_iomap_write_delay;
@@ -230,13 +240,17 @@ typedef struct xfs_ioops {
230 xfs_unlk_t xfs_unlock; 240 xfs_unlk_t xfs_unlock;
231 xfs_size_t xfs_size_func; 241 xfs_size_t xfs_size_func;
232 xfs_iodone_t xfs_iodone; 242 xfs_iodone_t xfs_iodone;
243 xfs_swap_extents_t xfs_swap_extents_func;
233} xfs_ioops_t; 244} xfs_ioops_t;
234 245
235#define XFS_IOINIT(vfsp, args, flags) \ 246#define XFS_IOINIT(vfsp, args, flags) \
236 (*(mp)->m_io_ops.xfs_ioinit)(vfsp, args, flags) 247 (*(mp)->m_io_ops.xfs_ioinit)(vfsp, args, flags)
237#define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist) \ 248#define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist,delta) \
238 (*(mp)->m_io_ops.xfs_bmapi_func) \ 249 (*(mp)->m_io_ops.xfs_bmapi_func) \
239 (trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist) 250 (trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist,delta)
251#define XFS_BUNMAPI(mp, trans,io,bno,len,f,nexts,first,flist,delta,done) \
252 (*(mp)->m_io_ops.xfs_bunmapi_func) \
253 (trans,(io)->io_obj,bno,len,f,nexts,first,flist,delta,done)
240#define XFS_BMAP_EOF(mp, io, endoff, whichfork, eof) \ 254#define XFS_BMAP_EOF(mp, io, endoff, whichfork, eof) \
241 (*(mp)->m_io_ops.xfs_bmap_eof_func) \ 255 (*(mp)->m_io_ops.xfs_bmap_eof_func) \
242 ((io)->io_obj, endoff, whichfork, eof) 256 ((io)->io_obj, endoff, whichfork, eof)
@@ -266,6 +280,9 @@ typedef struct xfs_ioops {
266 (*(mp)->m_io_ops.xfs_size_func)((io)->io_obj) 280 (*(mp)->m_io_ops.xfs_size_func)((io)->io_obj)
267#define XFS_IODONE(vfsp) \ 281#define XFS_IODONE(vfsp) \
268 (*(mp)->m_io_ops.xfs_iodone)(vfsp) 282 (*(mp)->m_io_ops.xfs_iodone)(vfsp)
283#define XFS_SWAP_EXTENTS(mp, io, tio, sxp) \
284 (*(mp)->m_io_ops.xfs_swap_extents_func) \
285 ((io)->io_obj, (tio)->io_obj, sxp)
269 286
270#ifdef HAVE_PERCPU_SB 287#ifdef HAVE_PERCPU_SB
271 288
@@ -386,8 +403,6 @@ typedef struct xfs_mount {
386 __uint8_t m_inode_quiesce;/* call quiesce on new inodes. 403 __uint8_t m_inode_quiesce;/* call quiesce on new inodes.
387 field governed by m_ilock */ 404 field governed by m_ilock */
388 __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ 405 __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */
389 __uint8_t m_dirversion; /* 1 or 2 */
390 xfs_dirops_t m_dirops; /* table of dir funcs */
391 int m_dirblksize; /* directory block sz--bytes */ 406 int m_dirblksize; /* directory block sz--bytes */
392 int m_dirblkfsbs; /* directory block sz--fsbs */ 407 int m_dirblkfsbs; /* directory block sz--fsbs */
393 xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */ 408 xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */
@@ -494,16 +509,7 @@ xfs_preferred_iosize(xfs_mount_t *mp)
494 509
495#define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN) 510#define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN)
496#define xfs_force_shutdown(m,f) \ 511#define xfs_force_shutdown(m,f) \
497 VFS_FORCE_SHUTDOWN((XFS_MTOVFS(m)), f, __FILE__, __LINE__) 512 bhv_vfs_force_shutdown((XFS_MTOVFS(m)), f, __FILE__, __LINE__)
498
499/*
500 * Flags sent to xfs_force_shutdown.
501 */
502#define XFS_METADATA_IO_ERROR 0x1
503#define XFS_LOG_IO_ERROR 0x2
504#define XFS_FORCE_UMOUNT 0x4
505#define XFS_CORRUPT_INCORE 0x8 /* Corrupt in-memory data structures */
506#define XFS_SHUTDOWN_REMOTE_REQ 0x10 /* Shutdown came from remote cell */
507 513
508/* 514/*
509 * Flags for xfs_mountfs 515 * Flags for xfs_mountfs
@@ -521,7 +527,7 @@ xfs_preferred_iosize(xfs_mount_t *mp)
521 * Macros for getting from mount to vfs and back. 527 * Macros for getting from mount to vfs and back.
522 */ 528 */
523#define XFS_MTOVFS(mp) xfs_mtovfs(mp) 529#define XFS_MTOVFS(mp) xfs_mtovfs(mp)
524static inline struct vfs *xfs_mtovfs(xfs_mount_t *mp) 530static inline struct bhv_vfs *xfs_mtovfs(xfs_mount_t *mp)
525{ 531{
526 return bhvtovfs(&mp->m_bhv); 532 return bhvtovfs(&mp->m_bhv);
527} 533}
@@ -533,7 +539,7 @@ static inline xfs_mount_t *xfs_bhvtom(bhv_desc_t *bdp)
533} 539}
534 540
535#define XFS_VFSTOM(vfs) xfs_vfstom(vfs) 541#define XFS_VFSTOM(vfs) xfs_vfstom(vfs)
536static inline xfs_mount_t *xfs_vfstom(vfs_t *vfs) 542static inline xfs_mount_t *xfs_vfstom(bhv_vfs_t *vfs)
537{ 543{
538 return XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfs), &xfs_vfsops)); 544 return XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfs), &xfs_vfsops));
539} 545}
@@ -571,7 +577,7 @@ typedef struct xfs_mod_sb {
571extern xfs_mount_t *xfs_mount_init(void); 577extern xfs_mount_t *xfs_mount_init(void);
572extern void xfs_mod_sb(xfs_trans_t *, __int64_t); 578extern void xfs_mod_sb(xfs_trans_t *, __int64_t);
573extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv); 579extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
574extern int xfs_mountfs(struct vfs *, xfs_mount_t *mp, int); 580extern int xfs_mountfs(struct bhv_vfs *, xfs_mount_t *mp, int);
575extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); 581extern void xfs_mountfs_check_barriers(xfs_mount_t *mp);
576 582
577extern int xfs_unmountfs(xfs_mount_t *, struct cred *); 583extern int xfs_unmountfs(xfs_mount_t *, struct cred *);
@@ -589,7 +595,7 @@ extern void xfs_freesb(xfs_mount_t *);
589extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int); 595extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
590extern int xfs_syncsub(xfs_mount_t *, int, int, int *); 596extern int xfs_syncsub(xfs_mount_t *, int, int, int *);
591extern int xfs_sync_inodes(xfs_mount_t *, int, int, int *); 597extern int xfs_sync_inodes(xfs_mount_t *, int, int, int *);
592extern xfs_agnumber_t xfs_initialize_perag(struct vfs *, xfs_mount_t *, 598extern xfs_agnumber_t xfs_initialize_perag(struct bhv_vfs *, xfs_mount_t *,
593 xfs_agnumber_t); 599 xfs_agnumber_t);
594extern void xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t); 600extern void xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t);
595 601
diff --git a/fs/xfs/xfs_qmops.c b/fs/xfs/xfs_qmops.c
index 1408a32eef88..320d63ff9ca2 100644
--- a/fs/xfs/xfs_qmops.c
+++ b/fs/xfs/xfs_qmops.c
@@ -23,7 +23,6 @@
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_ag.h" 25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h" 26#include "xfs_dir2.h"
28#include "xfs_dmapi.h" 27#include "xfs_dmapi.h"
29#include "xfs_mount.h" 28#include "xfs_mount.h"
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 7fbef974bce6..acb853b33ebb 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -365,7 +365,7 @@ typedef struct xfs_dqtrxops {
365extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *); 365extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *);
366extern int xfs_mount_reset_sbqflags(struct xfs_mount *); 366extern int xfs_mount_reset_sbqflags(struct xfs_mount *);
367 367
368extern struct bhv_vfsops xfs_qmops; 368extern struct bhv_module_vfsops xfs_qmops;
369 369
370#endif /* __KERNEL__ */ 370#endif /* __KERNEL__ */
371 371
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 1f148762eb28..d98171deaa1c 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -22,13 +22,11 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dir2.h" 25#include "xfs_dir2.h"
27#include "xfs_dmapi.h" 26#include "xfs_dmapi.h"
28#include "xfs_mount.h" 27#include "xfs_mount.h"
29#include "xfs_da_btree.h" 28#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h" 29#include "xfs_bmap_btree.h"
31#include "xfs_dir_sf.h"
32#include "xfs_dir2_sf.h" 30#include "xfs_dir2_sf.h"
33#include "xfs_attr_sf.h" 31#include "xfs_attr_sf.h"
34#include "xfs_dinode.h" 32#include "xfs_dinode.h"
@@ -40,7 +38,6 @@
40#include "xfs_refcache.h" 38#include "xfs_refcache.h"
41#include "xfs_utils.h" 39#include "xfs_utils.h"
42#include "xfs_trans_space.h" 40#include "xfs_trans_space.h"
43#include "xfs_dir_leaf.h"
44 41
45 42
46/* 43/*
@@ -87,8 +84,8 @@ STATIC int
87xfs_lock_for_rename( 84xfs_lock_for_rename(
88 xfs_inode_t *dp1, /* old (source) directory inode */ 85 xfs_inode_t *dp1, /* old (source) directory inode */
89 xfs_inode_t *dp2, /* new (target) directory inode */ 86 xfs_inode_t *dp2, /* new (target) directory inode */
90 vname_t *vname1,/* old entry name */ 87 bhv_vname_t *vname1,/* old entry name */
91 vname_t *vname2,/* new entry name */ 88 bhv_vname_t *vname2,/* new entry name */
92 xfs_inode_t **ipp1, /* inode of old entry */ 89 xfs_inode_t **ipp1, /* inode of old entry */
93 xfs_inode_t **ipp2, /* inode of new entry, if it 90 xfs_inode_t **ipp2, /* inode of new entry, if it
94 already exists, NULL otherwise. */ 91 already exists, NULL otherwise. */
@@ -225,9 +222,9 @@ xfs_lock_for_rename(
225int 222int
226xfs_rename( 223xfs_rename(
227 bhv_desc_t *src_dir_bdp, 224 bhv_desc_t *src_dir_bdp,
228 vname_t *src_vname, 225 bhv_vname_t *src_vname,
229 vnode_t *target_dir_vp, 226 bhv_vnode_t *target_dir_vp,
230 vname_t *target_vname, 227 bhv_vname_t *target_vname,
231 cred_t *credp) 228 cred_t *credp)
232{ 229{
233 xfs_trans_t *tp; 230 xfs_trans_t *tp;
@@ -242,7 +239,7 @@ xfs_rename(
242 int committed; 239 int committed;
243 xfs_inode_t *inodes[4]; 240 xfs_inode_t *inodes[4];
244 int target_ip_dropped = 0; /* dropped target_ip link? */ 241 int target_ip_dropped = 0; /* dropped target_ip link? */
245 vnode_t *src_dir_vp; 242 bhv_vnode_t *src_dir_vp;
246 int spaceres; 243 int spaceres;
247 int target_link_zero = 0; 244 int target_link_zero = 0;
248 int num_inodes; 245 int num_inodes;
@@ -398,34 +395,29 @@ xfs_rename(
398 * fit before actually inserting it. 395 * fit before actually inserting it.
399 */ 396 */
400 if (spaceres == 0 && 397 if (spaceres == 0 &&
401 (error = XFS_DIR_CANENTER(mp, tp, target_dp, target_name, 398 (error = xfs_dir_canenter(tp, target_dp, target_name,
402 target_namelen))) { 399 target_namelen)))
403 goto error_return; 400 goto error_return;
404 }
405 /* 401 /*
406 * If target does not exist and the rename crosses 402 * If target does not exist and the rename crosses
407 * directories, adjust the target directory link count 403 * directories, adjust the target directory link count
408 * to account for the ".." reference from the new entry. 404 * to account for the ".." reference from the new entry.
409 */ 405 */
410 error = XFS_DIR_CREATENAME(mp, tp, target_dp, target_name, 406 error = xfs_dir_createname(tp, target_dp, target_name,
411 target_namelen, src_ip->i_ino, 407 target_namelen, src_ip->i_ino,
412 &first_block, &free_list, spaceres); 408 &first_block, &free_list, spaceres);
413 if (error == ENOSPC) { 409 if (error == ENOSPC)
414 goto error_return; 410 goto error_return;
415 } 411 if (error)
416 if (error) {
417 goto abort_return; 412 goto abort_return;
418 }
419 xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 413 xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
420 414
421 if (new_parent && src_is_directory) { 415 if (new_parent && src_is_directory) {
422 error = xfs_bumplink(tp, target_dp); 416 error = xfs_bumplink(tp, target_dp);
423 if (error) { 417 if (error)
424 goto abort_return; 418 goto abort_return;
425 }
426 } 419 }
427 } else { /* target_ip != NULL */ 420 } else { /* target_ip != NULL */
428
429 /* 421 /*
430 * If target exists and it's a directory, check that both 422 * If target exists and it's a directory, check that both
431 * target and source are directories and that target can be 423 * target and source are directories and that target can be
@@ -435,7 +427,7 @@ xfs_rename(
435 /* 427 /*
436 * Make sure target dir is empty. 428 * Make sure target dir is empty.
437 */ 429 */
438 if (!(XFS_DIR_ISEMPTY(target_ip->i_mount, target_ip)) || 430 if (!(xfs_dir_isempty(target_ip)) ||
439 (target_ip->i_d.di_nlink > 2)) { 431 (target_ip->i_d.di_nlink > 2)) {
440 error = XFS_ERROR(EEXIST); 432 error = XFS_ERROR(EEXIST);
441 goto error_return; 433 goto error_return;
@@ -451,12 +443,11 @@ xfs_rename(
451 * In case there is already an entry with the same 443 * In case there is already an entry with the same
452 * name at the destination directory, remove it first. 444 * name at the destination directory, remove it first.
453 */ 445 */
454 error = XFS_DIR_REPLACE(mp, tp, target_dp, target_name, 446 error = xfs_dir_replace(tp, target_dp, target_name,
455 target_namelen, src_ip->i_ino, &first_block, 447 target_namelen, src_ip->i_ino,
456 &free_list, spaceres); 448 &first_block, &free_list, spaceres);
457 if (error) { 449 if (error)
458 goto abort_return; 450 goto abort_return;
459 }
460 xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 451 xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
461 452
462 /* 453 /*
@@ -464,9 +455,8 @@ xfs_rename(
464 * dir no longer points to it. 455 * dir no longer points to it.
465 */ 456 */
466 error = xfs_droplink(tp, target_ip); 457 error = xfs_droplink(tp, target_ip);
467 if (error) { 458 if (error)
468 goto abort_return; 459 goto abort_return;
469 }
470 target_ip_dropped = 1; 460 target_ip_dropped = 1;
471 461
472 if (src_is_directory) { 462 if (src_is_directory) {
@@ -474,9 +464,8 @@ xfs_rename(
474 * Drop the link from the old "." entry. 464 * Drop the link from the old "." entry.
475 */ 465 */
476 error = xfs_droplink(tp, target_ip); 466 error = xfs_droplink(tp, target_ip);
477 if (error) { 467 if (error)
478 goto abort_return; 468 goto abort_return;
479 }
480 } 469 }
481 470
482 /* Do this test while we still hold the locks */ 471 /* Do this test while we still hold the locks */
@@ -488,18 +477,15 @@ xfs_rename(
488 * Remove the source. 477 * Remove the source.
489 */ 478 */
490 if (new_parent && src_is_directory) { 479 if (new_parent && src_is_directory) {
491
492 /* 480 /*
493 * Rewrite the ".." entry to point to the new 481 * Rewrite the ".." entry to point to the new
494 * directory. 482 * directory.
495 */ 483 */
496 error = XFS_DIR_REPLACE(mp, tp, src_ip, "..", 2, 484 error = xfs_dir_replace(tp, src_ip, "..", 2, target_dp->i_ino,
497 target_dp->i_ino, &first_block, 485 &first_block, &free_list, spaceres);
498 &free_list, spaceres);
499 ASSERT(error != EEXIST); 486 ASSERT(error != EEXIST);
500 if (error) { 487 if (error)
501 goto abort_return; 488 goto abort_return;
502 }
503 xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 489 xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
504 490
505 } else { 491 } else {
@@ -527,16 +513,14 @@ xfs_rename(
527 * entry that's moved no longer points to it. 513 * entry that's moved no longer points to it.
528 */ 514 */
529 error = xfs_droplink(tp, src_dp); 515 error = xfs_droplink(tp, src_dp);
530 if (error) { 516 if (error)
531 goto abort_return; 517 goto abort_return;
532 }
533 } 518 }
534 519
535 error = XFS_DIR_REMOVENAME(mp, tp, src_dp, src_name, src_namelen, 520 error = xfs_dir_removename(tp, src_dp, src_name, src_namelen,
536 src_ip->i_ino, &first_block, &free_list, spaceres); 521 src_ip->i_ino, &first_block, &free_list, spaceres);
537 if (error) { 522 if (error)
538 goto abort_return; 523 goto abort_return;
539 }
540 xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 524 xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
541 525
542 /* 526 /*
@@ -609,7 +593,7 @@ xfs_rename(
609 * Let interposed file systems know about removed links. 593 * Let interposed file systems know about removed links.
610 */ 594 */
611 if (target_ip_dropped) { 595 if (target_ip_dropped) {
612 VOP_LINK_REMOVED(XFS_ITOV(target_ip), target_dir_vp, 596 bhv_vop_link_removed(XFS_ITOV(target_ip), target_dir_vp,
613 target_link_zero); 597 target_link_zero);
614 IRELE(target_ip); 598 IRELE(target_ip);
615 } 599 }
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 5b413946b1c5..0c1e42b037ef 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
@@ -141,7 +139,7 @@ xfs_growfs_rt_alloc(
141 cancelflags |= XFS_TRANS_ABORT; 139 cancelflags |= XFS_TRANS_ABORT;
142 error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks, 140 error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks,
143 XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock, 141 XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock,
144 resblks, &map, &nmap, &flist); 142 resblks, &map, &nmap, &flist, NULL);
145 if (!error && nmap < 1) 143 if (!error && nmap < 1)
146 error = XFS_ERROR(ENOSPC); 144 error = XFS_ERROR(ENOSPC);
147 if (error) 145 if (error)
@@ -2404,10 +2402,10 @@ xfs_rtprint_range(
2404{ 2402{
2405 xfs_extlen_t i; /* block number in the extent */ 2403 xfs_extlen_t i; /* block number in the extent */
2406 2404
2407 printk("%Ld: ", (long long)start); 2405 cmn_err(CE_DEBUG, "%Ld: ", (long long)start);
2408 for (i = 0; i < len; i++) 2406 for (i = 0; i < len; i++)
2409 printk("%d", xfs_rtcheck_bit(mp, tp, start + i, 1)); 2407 cmn_err(CE_DEBUG, "%d", xfs_rtcheck_bit(mp, tp, start + i, 1));
2410 printk("\n"); 2408 cmn_err(CE_DEBUG, "\n");
2411} 2409}
2412 2410
2413/* 2411/*
@@ -2431,17 +2429,17 @@ xfs_rtprint_summary(
2431 (void)xfs_rtget_summary(mp, tp, l, i, &sumbp, &sb, &c); 2429 (void)xfs_rtget_summary(mp, tp, l, i, &sumbp, &sb, &c);
2432 if (c) { 2430 if (c) {
2433 if (!p) { 2431 if (!p) {
2434 printk("%Ld-%Ld:", 1LL << l, 2432 cmn_err(CE_DEBUG, "%Ld-%Ld:", 1LL << l,
2435 XFS_RTMIN((1LL << l) + 2433 XFS_RTMIN((1LL << l) +
2436 ((1LL << l) - 1LL), 2434 ((1LL << l) - 1LL),
2437 mp->m_sb.sb_rextents)); 2435 mp->m_sb.sb_rextents));
2438 p = 1; 2436 p = 1;
2439 } 2437 }
2440 printk(" %Ld:%d", (long long)i, c); 2438 cmn_err(CE_DEBUG, " %Ld:%d", (long long)i, c);
2441 } 2439 }
2442 } 2440 }
2443 if (p) 2441 if (p)
2444 printk("\n"); 2442 cmn_err(CE_DEBUG, "\n");
2445 } 2443 }
2446 if (sumbp) 2444 if (sumbp)
2447 xfs_trans_brelse(tp, sumbp); 2445 xfs_trans_brelse(tp, sumbp);
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c
index a59c102cf214..defb2febaaf5 100644
--- a/fs/xfs/xfs_rw.c
+++ b/fs/xfs/xfs_rw.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
@@ -92,6 +90,90 @@ xfs_write_clear_setuid(
92} 90}
93 91
94/* 92/*
93 * Handle logging requirements of various synchronous types of write.
94 */
95int
96xfs_write_sync_logforce(
97 xfs_mount_t *mp,
98 xfs_inode_t *ip)
99{
100 int error = 0;
101
102 /*
103 * If we're treating this as O_DSYNC and we have not updated the
104 * size, force the log.
105 */
106 if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) &&
107 !(ip->i_update_size)) {
108 xfs_inode_log_item_t *iip = ip->i_itemp;
109
110 /*
111 * If an allocation transaction occurred
112 * without extending the size, then we have to force
113 * the log up the proper point to ensure that the
114 * allocation is permanent. We can't count on
115 * the fact that buffered writes lock out direct I/O
116 * writes - the direct I/O write could have extended
117 * the size nontransactionally, then finished before
118 * we started. xfs_write_file will think that the file
119 * didn't grow but the update isn't safe unless the
120 * size change is logged.
121 *
122 * Force the log if we've committed a transaction
123 * against the inode or if someone else has and
124 * the commit record hasn't gone to disk (e.g.
125 * the inode is pinned). This guarantees that
126 * all changes affecting the inode are permanent
127 * when we return.
128 */
129 if (iip && iip->ili_last_lsn) {
130 xfs_log_force(mp, iip->ili_last_lsn,
131 XFS_LOG_FORCE | XFS_LOG_SYNC);
132 } else if (xfs_ipincount(ip) > 0) {
133 xfs_log_force(mp, (xfs_lsn_t)0,
134 XFS_LOG_FORCE | XFS_LOG_SYNC);
135 }
136
137 } else {
138 xfs_trans_t *tp;
139
140 /*
141 * O_SYNC or O_DSYNC _with_ a size update are handled
142 * the same way.
143 *
144 * If the write was synchronous then we need to make
145 * sure that the inode modification time is permanent.
146 * We'll have updated the timestamp above, so here
147 * we use a synchronous transaction to log the inode.
148 * It's not fast, but it's necessary.
149 *
150 * If this a dsync write and the size got changed
151 * non-transactionally, then we need to ensure that
152 * the size change gets logged in a synchronous
153 * transaction.
154 */
155 tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC);
156 if ((error = xfs_trans_reserve(tp, 0,
157 XFS_SWRITE_LOG_RES(mp),
158 0, 0, 0))) {
159 /* Transaction reserve failed */
160 xfs_trans_cancel(tp, 0);
161 } else {
162 /* Transaction reserve successful */
163 xfs_ilock(ip, XFS_ILOCK_EXCL);
164 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
165 xfs_trans_ihold(tp, ip);
166 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
167 xfs_trans_set_sync(tp);
168 error = xfs_trans_commit(tp, 0, NULL);
169 xfs_iunlock(ip, XFS_ILOCK_EXCL);
170 }
171 }
172
173 return error;
174}
175
176/*
95 * Force a shutdown of the filesystem instantly while keeping 177 * Force a shutdown of the filesystem instantly while keeping
96 * the filesystem consistent. We don't do an unmount here; just shutdown 178 * the filesystem consistent. We don't do an unmount here; just shutdown
97 * the shop, make sure that absolutely nothing persistent happens to 179 * the shop, make sure that absolutely nothing persistent happens to
@@ -109,12 +191,12 @@ xfs_do_force_shutdown(
109 xfs_mount_t *mp; 191 xfs_mount_t *mp;
110 192
111 mp = XFS_BHVTOM(bdp); 193 mp = XFS_BHVTOM(bdp);
112 logerror = flags & XFS_LOG_IO_ERROR; 194 logerror = flags & SHUTDOWN_LOG_IO_ERROR;
113 195
114 if (!(flags & XFS_FORCE_UMOUNT)) { 196 if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
115 cmn_err(CE_NOTE, 197 cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from "
116 "xfs_force_shutdown(%s,0x%x) called from line %d of file %s. Return address = 0x%p", 198 "line %d of file %s. Return address = 0x%p",
117 mp->m_fsname,flags,lnnum,fname,__return_address); 199 mp->m_fsname, flags, lnnum, fname, __return_address);
118 } 200 }
119 /* 201 /*
120 * No need to duplicate efforts. 202 * No need to duplicate efforts.
@@ -125,33 +207,37 @@ xfs_do_force_shutdown(
125 /* 207 /*
126 * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't 208 * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't
127 * queue up anybody new on the log reservations, and wakes up 209 * queue up anybody new on the log reservations, and wakes up
128 * everybody who's sleeping on log reservations and tells 210 * everybody who's sleeping on log reservations to tell them
129 * them the bad news. 211 * the bad news.
130 */ 212 */
131 if (xfs_log_force_umount(mp, logerror)) 213 if (xfs_log_force_umount(mp, logerror))
132 return; 214 return;
133 215
134 if (flags & XFS_CORRUPT_INCORE) { 216 if (flags & SHUTDOWN_CORRUPT_INCORE) {
135 xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp, 217 xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp,
136 "Corruption of in-memory data detected. Shutting down filesystem: %s", 218 "Corruption of in-memory data detected. Shutting down filesystem: %s",
137 mp->m_fsname); 219 mp->m_fsname);
138 if (XFS_ERRLEVEL_HIGH <= xfs_error_level) { 220 if (XFS_ERRLEVEL_HIGH <= xfs_error_level) {
139 xfs_stack_trace(); 221 xfs_stack_trace();
140 } 222 }
141 } else if (!(flags & XFS_FORCE_UMOUNT)) { 223 } else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
142 if (logerror) { 224 if (logerror) {
143 xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp, 225 xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp,
144 "Log I/O Error Detected. Shutting down filesystem: %s", 226 "Log I/O Error Detected. Shutting down filesystem: %s",
227 mp->m_fsname);
228 } else if (flags & SHUTDOWN_DEVICE_REQ) {
229 xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp,
230 "All device paths lost. Shutting down filesystem: %s",
145 mp->m_fsname); 231 mp->m_fsname);
146 } else if (!(flags & XFS_SHUTDOWN_REMOTE_REQ)) { 232 } else if (!(flags & SHUTDOWN_REMOTE_REQ)) {
147 xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, 233 xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp,
148 "I/O Error Detected. Shutting down filesystem: %s", 234 "I/O Error Detected. Shutting down filesystem: %s",
149 mp->m_fsname); 235 mp->m_fsname);
150 } 236 }
151 } 237 }
152 if (!(flags & XFS_FORCE_UMOUNT)) { 238 if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
153 cmn_err(CE_ALERT, 239 cmn_err(CE_ALERT, "Please umount the filesystem, "
154 "Please umount the filesystem, and rectify the problem(s)"); 240 "and rectify the problem(s)");
155 } 241 }
156} 242}
157 243
@@ -335,7 +421,7 @@ xfs_bwrite(
335 * from bwrite and we could be tracing a buffer that has 421 * from bwrite and we could be tracing a buffer that has
336 * been reused. 422 * been reused.
337 */ 423 */
338 xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); 424 xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
339 } 425 }
340 return (error); 426 return (error);
341} 427}
diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h
index e63795644478..188b296ff50c 100644
--- a/fs/xfs/xfs_rw.h
+++ b/fs/xfs/xfs_rw.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -75,6 +75,7 @@ xfs_fsb_to_db_io(struct xfs_iocore *io, xfs_fsblock_t fsb)
75 * Prototypes for functions in xfs_rw.c. 75 * Prototypes for functions in xfs_rw.c.
76 */ 76 */
77extern int xfs_write_clear_setuid(struct xfs_inode *ip); 77extern int xfs_write_clear_setuid(struct xfs_inode *ip);
78extern int xfs_write_sync_logforce(struct xfs_mount *mp, struct xfs_inode *ip);
78extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp); 79extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp);
79extern int xfs_bioerror(struct xfs_buf *bp); 80extern int xfs_bioerror(struct xfs_buf *bp);
80extern int xfs_bioerror_relse(struct xfs_buf *bp); 81extern int xfs_bioerror_relse(struct xfs_buf *bp);
@@ -87,9 +88,10 @@ extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp,
87/* 88/*
88 * Prototypes for functions in xfs_vnodeops.c. 89 * Prototypes for functions in xfs_vnodeops.c.
89 */ 90 */
90extern int xfs_rwlock(bhv_desc_t *bdp, vrwlock_t write_lock); 91extern int xfs_rwlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
91extern void xfs_rwunlock(bhv_desc_t *bdp, vrwlock_t write_lock); 92extern void xfs_rwunlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
92extern int xfs_setattr(bhv_desc_t *bdp, vattr_t *vap, int flags, cred_t *credp); 93extern int xfs_setattr(bhv_desc_t *, bhv_vattr_t *vap, int flags,
94 cred_t *credp);
93extern int xfs_change_file_space(bhv_desc_t *bdp, int cmd, xfs_flock64_t *bf, 95extern int xfs_change_file_space(bhv_desc_t *bdp, int cmd, xfs_flock64_t *bf,
94 xfs_off_t offset, cred_t *credp, int flags); 96 xfs_off_t offset, cred_t *credp, int flags);
95extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state, 97extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state,
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 8d056cef5d1f..ee2721e0de4d 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -24,7 +24,6 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
@@ -33,7 +32,6 @@
33#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
34#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
35#include "xfs_ialloc_btree.h" 34#include "xfs_ialloc_btree.h"
36#include "xfs_dir_sf.h"
37#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
38#include "xfs_attr_sf.h" 36#include "xfs_attr_sf.h"
39#include "xfs_dinode.h" 37#include "xfs_dinode.h"
@@ -236,11 +234,8 @@ xfs_trans_alloc(
236 xfs_mount_t *mp, 234 xfs_mount_t *mp,
237 uint type) 235 uint type)
238{ 236{
239 fs_check_frozen(XFS_MTOVFS(mp), SB_FREEZE_TRANS); 237 vfs_wait_for_freeze(XFS_MTOVFS(mp), SB_FREEZE_TRANS);
240 atomic_inc(&mp->m_active_trans); 238 return _xfs_trans_alloc(mp, type);
241
242 return (_xfs_trans_alloc(mp, type));
243
244} 239}
245 240
246xfs_trans_t * 241xfs_trans_t *
@@ -250,12 +245,9 @@ _xfs_trans_alloc(
250{ 245{
251 xfs_trans_t *tp; 246 xfs_trans_t *tp;
252 247
253 ASSERT(xfs_trans_zone != NULL); 248 atomic_inc(&mp->m_active_trans);
254 tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);
255 249
256 /* 250 tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);
257 * Initialize the transaction structure.
258 */
259 tp->t_magic = XFS_TRANS_MAGIC; 251 tp->t_magic = XFS_TRANS_MAGIC;
260 tp->t_type = type; 252 tp->t_type = type;
261 tp->t_mountp = mp; 253 tp->t_mountp = mp;
@@ -263,8 +255,7 @@ _xfs_trans_alloc(
263 tp->t_busy_free = XFS_LBC_NUM_SLOTS; 255 tp->t_busy_free = XFS_LBC_NUM_SLOTS;
264 XFS_LIC_INIT(&(tp->t_items)); 256 XFS_LIC_INIT(&(tp->t_items));
265 XFS_LBC_INIT(&(tp->t_busy)); 257 XFS_LBC_INIT(&(tp->t_busy));
266 258 return tp;
267 return (tp);
268} 259}
269 260
270/* 261/*
@@ -303,7 +294,7 @@ xfs_trans_dup(
303 tp->t_blk_res = tp->t_blk_res_used; 294 tp->t_blk_res = tp->t_blk_res_used;
304 ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used; 295 ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used;
305 tp->t_rtx_res = tp->t_rtx_res_used; 296 tp->t_rtx_res = tp->t_rtx_res_used;
306 PFLAGS_DUP(&tp->t_pflags, &ntp->t_pflags); 297 ntp->t_pflags = tp->t_pflags;
307 298
308 XFS_TRANS_DUP_DQINFO(tp->t_mountp, tp, ntp); 299 XFS_TRANS_DUP_DQINFO(tp->t_mountp, tp, ntp);
309 300
@@ -335,14 +326,11 @@ xfs_trans_reserve(
335 uint logcount) 326 uint logcount)
336{ 327{
337 int log_flags; 328 int log_flags;
338 int error; 329 int error = 0;
339 int rsvd; 330 int rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
340
341 error = 0;
342 rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
343 331
344 /* Mark this thread as being in a transaction */ 332 /* Mark this thread as being in a transaction */
345 PFLAGS_SET_FSTRANS(&tp->t_pflags); 333 current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
346 334
347 /* 335 /*
348 * Attempt to reserve the needed disk blocks by decrementing 336 * Attempt to reserve the needed disk blocks by decrementing
@@ -353,7 +341,7 @@ xfs_trans_reserve(
353 error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS, 341 error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,
354 -blocks, rsvd); 342 -blocks, rsvd);
355 if (error != 0) { 343 if (error != 0) {
356 PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); 344 current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
357 return (XFS_ERROR(ENOSPC)); 345 return (XFS_ERROR(ENOSPC));
358 } 346 }
359 tp->t_blk_res += blocks; 347 tp->t_blk_res += blocks;
@@ -426,9 +414,9 @@ undo_blocks:
426 tp->t_blk_res = 0; 414 tp->t_blk_res = 0;
427 } 415 }
428 416
429 PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); 417 current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
430 418
431 return (error); 419 return error;
432} 420}
433 421
434 422
@@ -819,7 +807,7 @@ shut_us_down:
819 if (commit_lsn == -1 && !shutdown) 807 if (commit_lsn == -1 && !shutdown)
820 shutdown = XFS_ERROR(EIO); 808 shutdown = XFS_ERROR(EIO);
821 } 809 }
822 PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); 810 current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
823 xfs_trans_free_items(tp, shutdown? XFS_TRANS_ABORT : 0); 811 xfs_trans_free_items(tp, shutdown? XFS_TRANS_ABORT : 0);
824 xfs_trans_free_busy(tp); 812 xfs_trans_free_busy(tp);
825 xfs_trans_free(tp); 813 xfs_trans_free(tp);
@@ -846,7 +834,7 @@ shut_us_down:
846 */ 834 */
847 nvec = xfs_trans_count_vecs(tp); 835 nvec = xfs_trans_count_vecs(tp);
848 if (nvec == 0) { 836 if (nvec == 0) {
849 xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); 837 xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
850 goto shut_us_down; 838 goto shut_us_down;
851 } else if (nvec <= XFS_TRANS_LOGVEC_COUNT) { 839 } else if (nvec <= XFS_TRANS_LOGVEC_COUNT) {
852 log_vector = log_vector_fast; 840 log_vector = log_vector_fast;
@@ -884,7 +872,7 @@ shut_us_down:
884 * had pinned, clean up, free trans structure, and return error. 872 * had pinned, clean up, free trans structure, and return error.
885 */ 873 */
886 if (error || commit_lsn == -1) { 874 if (error || commit_lsn == -1) {
887 PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); 875 current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
888 xfs_trans_uncommit(tp, flags|XFS_TRANS_ABORT); 876 xfs_trans_uncommit(tp, flags|XFS_TRANS_ABORT);
889 return XFS_ERROR(EIO); 877 return XFS_ERROR(EIO);
890 } 878 }
@@ -926,7 +914,7 @@ shut_us_down:
926 /* 914 /*
927 * Mark this thread as no longer being in a transaction 915 * Mark this thread as no longer being in a transaction
928 */ 916 */
929 PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); 917 current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
930 918
931 /* 919 /*
932 * Once all the items of the transaction have been copied 920 * Once all the items of the transaction have been copied
@@ -1148,7 +1136,7 @@ xfs_trans_cancel(
1148 */ 1136 */
1149 if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) { 1137 if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) {
1150 XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp); 1138 XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp);
1151 xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); 1139 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
1152 } 1140 }
1153#ifdef DEBUG 1141#ifdef DEBUG
1154 if (!(flags & XFS_TRANS_ABORT)) { 1142 if (!(flags & XFS_TRANS_ABORT)) {
@@ -1182,7 +1170,7 @@ xfs_trans_cancel(
1182 } 1170 }
1183 1171
1184 /* mark this thread as no longer being in a transaction */ 1172 /* mark this thread as no longer being in a transaction */
1185 PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); 1173 current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
1186 1174
1187 xfs_trans_free_items(tp, flags); 1175 xfs_trans_free_items(tp, flags);
1188 xfs_trans_free_busy(tp); 1176 xfs_trans_free_busy(tp);
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 100d9a4b38ee..cb65c3a603f5 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -805,12 +805,9 @@ typedef struct xfs_trans {
805 ((mp)->m_sb.sb_inodesize + \ 805 ((mp)->m_sb.sb_inodesize + \
806 (mp)->m_sb.sb_sectsize * 2 + \ 806 (mp)->m_sb.sb_sectsize * 2 + \
807 (mp)->m_dirblksize + \ 807 (mp)->m_dirblksize + \
808 (XFS_DIR_IS_V1(mp) ? 0 : \ 808 XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1)) + \
809 XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1))) + \
810 XFS_ALLOCFREE_LOG_RES(mp, 1) + \ 809 XFS_ALLOCFREE_LOG_RES(mp, 1) + \
811 (128 * (4 + \ 810 (128 * (4 + (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \
812 (XFS_DIR_IS_V1(mp) ? 0 : \
813 XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \
814 XFS_ALLOCFREE_LOG_COUNT(mp, 1)))) 811 XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
815 812
816#define XFS_ADDAFORK_LOG_RES(mp) ((mp)->m_reservations.tr_addafork) 813#define XFS_ADDAFORK_LOG_RES(mp) ((mp)->m_reservations.tr_addafork)
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 19ab24af1c1c..558c87ff0c41 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -22,7 +22,6 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dmapi.h" 25#include "xfs_dmapi.h"
27#include "xfs_mount.h" 26#include "xfs_mount.h"
28#include "xfs_trans_priv.h" 27#include "xfs_trans_priv.h"
@@ -363,9 +362,10 @@ xfs_trans_delete_ail(
363 AIL_UNLOCK(mp, s); 362 AIL_UNLOCK(mp, s);
364 else { 363 else {
365 xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp, 364 xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp,
366 "xfs_trans_delete_ail: attempting to delete a log item that is not in the AIL"); 365 "%s: attempting to delete a log item that is not in the AIL",
366 __FUNCTION__);
367 AIL_UNLOCK(mp, s); 367 AIL_UNLOCK(mp, s);
368 xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); 368 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
369 } 369 }
370 } 370 }
371} 371}
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index c74c31ebc81c..60b6b898022b 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
@@ -320,7 +318,7 @@ xfs_trans_read_buf(
320 if (xfs_error_target == target) { 318 if (xfs_error_target == target) {
321 if (((xfs_req_num++) % xfs_error_mod) == 0) { 319 if (((xfs_req_num++) % xfs_error_mod) == 0) {
322 xfs_buf_relse(bp); 320 xfs_buf_relse(bp);
323 printk("Returning error!\n"); 321 cmn_err(CE_DEBUG, "Returning error!\n");
324 return XFS_ERROR(EIO); 322 return XFS_ERROR(EIO);
325 } 323 }
326 } 324 }
@@ -369,7 +367,7 @@ xfs_trans_read_buf(
369 */ 367 */
370 if (tp->t_flags & XFS_TRANS_DIRTY) 368 if (tp->t_flags & XFS_TRANS_DIRTY)
371 xfs_force_shutdown(tp->t_mountp, 369 xfs_force_shutdown(tp->t_mountp,
372 XFS_METADATA_IO_ERROR); 370 SHUTDOWN_META_IO_ERROR);
373 return error; 371 return error;
374 } 372 }
375 } 373 }
@@ -414,7 +412,7 @@ xfs_trans_read_buf(
414 xfs_ioerror_alert("xfs_trans_read_buf", mp, 412 xfs_ioerror_alert("xfs_trans_read_buf", mp,
415 bp, blkno); 413 bp, blkno);
416 if (tp->t_flags & XFS_TRANS_DIRTY) 414 if (tp->t_flags & XFS_TRANS_DIRTY)
417 xfs_force_shutdown(tp->t_mountp, XFS_METADATA_IO_ERROR); 415 xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR);
418 xfs_buf_relse(bp); 416 xfs_buf_relse(bp);
419 return error; 417 return error;
420 } 418 }
@@ -423,9 +421,9 @@ xfs_trans_read_buf(
423 if (xfs_error_target == target) { 421 if (xfs_error_target == target) {
424 if (((xfs_req_num++) % xfs_error_mod) == 0) { 422 if (((xfs_req_num++) % xfs_error_mod) == 0) {
425 xfs_force_shutdown(tp->t_mountp, 423 xfs_force_shutdown(tp->t_mountp,
426 XFS_METADATA_IO_ERROR); 424 SHUTDOWN_META_IO_ERROR);
427 xfs_buf_relse(bp); 425 xfs_buf_relse(bp);
428 printk("Returning error in trans!\n"); 426 cmn_err(CE_DEBUG, "Returning trans error!\n");
429 return XFS_ERROR(EIO); 427 return XFS_ERROR(EIO);
430 } 428 }
431 } 429 }
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c
index 7d7d627f25df..b290270dd4a6 100644
--- a/fs/xfs/xfs_trans_extfree.c
+++ b/fs/xfs/xfs_trans_extfree.c
@@ -22,7 +22,6 @@
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_trans.h" 23#include "xfs_trans.h"
24#include "xfs_sb.h" 24#include "xfs_sb.h"
25#include "xfs_dir.h"
26#include "xfs_dmapi.h" 25#include "xfs_dmapi.h"
27#include "xfs_mount.h" 26#include "xfs_mount.h"
28#include "xfs_trans_priv.h" 27#include "xfs_trans_priv.h"
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index 7c5894d59f81..b8db1d5cde5a 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -24,14 +24,12 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_alloc_btree.h" 31#include "xfs_alloc_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c
index 1117d600d741..2912aac07c7b 100644
--- a/fs/xfs/xfs_trans_item.c
+++ b/fs/xfs/xfs_trans_item.c
@@ -493,7 +493,7 @@ xfs_trans_add_busy(xfs_trans_t *tp, xfs_agnumber_t ag, xfs_extlen_t idx)
493 break; 493 break;
494 } else { 494 } else {
495 /* out-of-order vacancy */ 495 /* out-of-order vacancy */
496 printk("OOO vacancy lbcp 0x%p\n", lbcp); 496 cmn_err(CE_DEBUG, "OOO vacancy lbcp 0x%p\n", lbcp);
497 ASSERT(0); 497 ASSERT(0);
498 } 498 }
499 } 499 }
diff --git a/fs/xfs/xfs_trans_space.h b/fs/xfs/xfs_trans_space.h
index 7fe3792b18df..4ea2e5074bdd 100644
--- a/fs/xfs/xfs_trans_space.h
+++ b/fs/xfs/xfs_trans_space.h
@@ -30,8 +30,7 @@
30 XFS_EXTENTADD_SPACE_RES(mp,w)) 30 XFS_EXTENTADD_SPACE_RES(mp,w))
31#define XFS_DAENTER_1B(mp,w) ((w) == XFS_DATA_FORK ? (mp)->m_dirblkfsbs : 1) 31#define XFS_DAENTER_1B(mp,w) ((w) == XFS_DATA_FORK ? (mp)->m_dirblkfsbs : 1)
32#define XFS_DAENTER_DBS(mp,w) \ 32#define XFS_DAENTER_DBS(mp,w) \
33 (XFS_DA_NODE_MAXDEPTH + \ 33 (XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 0))
34 ((XFS_DIR_IS_V2(mp) && (w) == XFS_DATA_FORK) ? 2 : 0))
35#define XFS_DAENTER_BLOCKS(mp,w) \ 34#define XFS_DAENTER_BLOCKS(mp,w) \
36 (XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w)) 35 (XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w))
37#define XFS_DAENTER_BMAP1B(mp,w) \ 36#define XFS_DAENTER_BMAP1B(mp,w) \
@@ -41,10 +40,7 @@
41#define XFS_DAENTER_SPACE_RES(mp,w) \ 40#define XFS_DAENTER_SPACE_RES(mp,w) \
42 (XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w)) 41 (XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w))
43#define XFS_DAREMOVE_SPACE_RES(mp,w) XFS_DAENTER_BMAPS(mp,w) 42#define XFS_DAREMOVE_SPACE_RES(mp,w) XFS_DAENTER_BMAPS(mp,w)
44#define XFS_DIRENTER_MAX_SPLIT(mp,nl) \ 43#define XFS_DIRENTER_MAX_SPLIT(mp,nl) 1
45 (((mp)->m_sb.sb_blocksize == 512 && \
46 XFS_DIR_IS_V1(mp) && \
47 (nl) >= XFS_DIR_LEAF_CAN_DOUBLE_SPLIT_LEN) ? 2 : 1)
48#define XFS_DIRENTER_SPACE_RES(mp,nl) \ 44#define XFS_DIRENTER_SPACE_RES(mp,nl) \
49 (XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \ 45 (XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \
50 XFS_DIRENTER_MAX_SPLIT(mp,nl)) 46 XFS_DIRENTER_MAX_SPLIT(mp,nl))
@@ -57,8 +53,7 @@
57 * Space reservation values for various transactions. 53 * Space reservation values for various transactions.
58 */ 54 */
59#define XFS_ADDAFORK_SPACE_RES(mp) \ 55#define XFS_ADDAFORK_SPACE_RES(mp) \
60 ((mp)->m_dirblkfsbs + \ 56 ((mp)->m_dirblkfsbs + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK))
61 (XFS_DIR_IS_V1(mp) ? 0 : XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK)))
62#define XFS_ATTRRM_SPACE_RES(mp) \ 57#define XFS_ATTRRM_SPACE_RES(mp) \
63 XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK) 58 XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK)
64/* This macro is not used - see inline code in xfs_attr_set */ 59/* This macro is not used - see inline code in xfs_attr_set */
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index 34654ec6ae10..9014d7e44488 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -24,12 +24,10 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_bmap_btree.h" 30#include "xfs_bmap_btree.h"
32#include "xfs_dir_sf.h"
33#include "xfs_dir2_sf.h" 31#include "xfs_dir2_sf.h"
34#include "xfs_attr_sf.h" 32#include "xfs_attr_sf.h"
35#include "xfs_dinode.h" 33#include "xfs_dinode.h"
@@ -51,10 +49,10 @@
51 */ 49 */
52int 50int
53xfs_get_dir_entry( 51xfs_get_dir_entry(
54 vname_t *dentry, 52 bhv_vname_t *dentry,
55 xfs_inode_t **ipp) 53 xfs_inode_t **ipp)
56{ 54{
57 vnode_t *vp; 55 bhv_vnode_t *vp;
58 56
59 vp = VNAME_TO_VNODE(dentry); 57 vp = VNAME_TO_VNODE(dentry);
60 58
@@ -69,11 +67,11 @@ int
69xfs_dir_lookup_int( 67xfs_dir_lookup_int(
70 bhv_desc_t *dir_bdp, 68 bhv_desc_t *dir_bdp,
71 uint lock_mode, 69 uint lock_mode,
72 vname_t *dentry, 70 bhv_vname_t *dentry,
73 xfs_ino_t *inum, 71 xfs_ino_t *inum,
74 xfs_inode_t **ipp) 72 xfs_inode_t **ipp)
75{ 73{
76 vnode_t *dir_vp; 74 bhv_vnode_t *dir_vp;
77 xfs_inode_t *dp; 75 xfs_inode_t *dp;
78 int error; 76 int error;
79 77
@@ -82,8 +80,7 @@ xfs_dir_lookup_int(
82 80
83 dp = XFS_BHVTOI(dir_bdp); 81 dp = XFS_BHVTOI(dir_bdp);
84 82
85 error = XFS_DIR_LOOKUP(dp->i_mount, NULL, dp, 83 error = xfs_dir_lookup(NULL, dp, VNAME(dentry), VNAMELEN(dentry), inum);
86 VNAME(dentry), VNAMELEN(dentry), inum);
87 if (!error) { 84 if (!error) {
88 /* 85 /*
89 * Unlock the directory. We do this because we can't 86 * Unlock the directory. We do this because we can't
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
index 472661a3b6d8..fe953e98afa7 100644
--- a/fs/xfs/xfs_utils.h
+++ b/fs/xfs/xfs_utils.h
@@ -23,9 +23,10 @@
23#define ITRACE(ip) vn_trace_ref(XFS_ITOV(ip), __FILE__, __LINE__, \ 23#define ITRACE(ip) vn_trace_ref(XFS_ITOV(ip), __FILE__, __LINE__, \
24 (inst_t *)__return_address) 24 (inst_t *)__return_address)
25 25
26extern int xfs_rename (bhv_desc_t *, vname_t *, vnode_t *, vname_t *, cred_t *); 26extern int xfs_rename (bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *,
27extern int xfs_get_dir_entry (vname_t *, xfs_inode_t **); 27 bhv_vname_t *, cred_t *);
28extern int xfs_dir_lookup_int (bhv_desc_t *, uint, vname_t *, xfs_ino_t *, 28extern int xfs_get_dir_entry (bhv_vname_t *, xfs_inode_t **);
29extern int xfs_dir_lookup_int (bhv_desc_t *, uint, bhv_vname_t *, xfs_ino_t *,
29 xfs_inode_t **); 30 xfs_inode_t **);
30extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *); 31extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *);
31extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t, 32extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 36ea1b2094f2..6c96391f3f1a 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -24,7 +24,6 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
@@ -32,7 +31,6 @@
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_ialloc_btree.h" 32#include "xfs_ialloc_btree.h"
34#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h" 34#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h" 35#include "xfs_attr_sf.h"
38#include "xfs_dinode.h" 36#include "xfs_dinode.h"
@@ -131,9 +129,6 @@ xfs_init(void)
131#ifdef XFS_BMBT_TRACE 129#ifdef XFS_BMBT_TRACE
132 xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_SLEEP); 130 xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_SLEEP);
133#endif 131#endif
134#ifdef XFS_DIR_TRACE
135 xfs_dir_trace_buf = ktrace_alloc(XFS_DIR_TRACE_SIZE, KM_SLEEP);
136#endif
137#ifdef XFS_ATTR_TRACE 132#ifdef XFS_ATTR_TRACE
138 xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_SLEEP); 133 xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_SLEEP);
139#endif 134#endif
@@ -177,9 +172,6 @@ xfs_cleanup(void)
177#ifdef XFS_ATTR_TRACE 172#ifdef XFS_ATTR_TRACE
178 ktrace_free(xfs_attr_trace_buf); 173 ktrace_free(xfs_attr_trace_buf);
179#endif 174#endif
180#ifdef XFS_DIR_TRACE
181 ktrace_free(xfs_dir_trace_buf);
182#endif
183#ifdef XFS_BMBT_TRACE 175#ifdef XFS_BMBT_TRACE
184 ktrace_free(xfs_bmbt_trace_buf); 176 ktrace_free(xfs_bmbt_trace_buf);
185#endif 177#endif
@@ -212,7 +204,7 @@ xfs_cleanup(void)
212 */ 204 */
213STATIC int 205STATIC int
214xfs_start_flags( 206xfs_start_flags(
215 struct vfs *vfs, 207 struct bhv_vfs *vfs,
216 struct xfs_mount_args *ap, 208 struct xfs_mount_args *ap,
217 struct xfs_mount *mp) 209 struct xfs_mount *mp)
218{ 210{
@@ -337,7 +329,7 @@ xfs_start_flags(
337 */ 329 */
338STATIC int 330STATIC int
339xfs_finish_flags( 331xfs_finish_flags(
340 struct vfs *vfs, 332 struct bhv_vfs *vfs,
341 struct xfs_mount_args *ap, 333 struct xfs_mount_args *ap,
342 struct xfs_mount *mp) 334 struct xfs_mount *mp)
343{ 335{
@@ -423,7 +415,7 @@ xfs_mount(
423 struct xfs_mount_args *args, 415 struct xfs_mount_args *args,
424 cred_t *credp) 416 cred_t *credp)
425{ 417{
426 struct vfs *vfsp = bhvtovfs(bhvp); 418 struct bhv_vfs *vfsp = bhvtovfs(bhvp);
427 struct bhv_desc *p; 419 struct bhv_desc *p;
428 struct xfs_mount *mp = XFS_BHVTOM(bhvp); 420 struct xfs_mount *mp = XFS_BHVTOM(bhvp);
429 struct block_device *ddev, *logdev, *rtdev; 421 struct block_device *ddev, *logdev, *rtdev;
@@ -552,10 +544,10 @@ xfs_unmount(
552 int flags, 544 int flags,
553 cred_t *credp) 545 cred_t *credp)
554{ 546{
555 struct vfs *vfsp = bhvtovfs(bdp); 547 bhv_vfs_t *vfsp = bhvtovfs(bdp);
556 xfs_mount_t *mp = XFS_BHVTOM(bdp); 548 xfs_mount_t *mp = XFS_BHVTOM(bdp);
557 xfs_inode_t *rip; 549 xfs_inode_t *rip;
558 vnode_t *rvp; 550 bhv_vnode_t *rvp;
559 int unmount_event_wanted = 0; 551 int unmount_event_wanted = 0;
560 int unmount_event_flags = 0; 552 int unmount_event_flags = 0;
561 int xfs_unmountfs_needed = 0; 553 int xfs_unmountfs_needed = 0;
@@ -665,9 +657,8 @@ xfs_mntupdate(
665 int *flags, 657 int *flags,
666 struct xfs_mount_args *args) 658 struct xfs_mount_args *args)
667{ 659{
668 struct vfs *vfsp = bhvtovfs(bdp); 660 bhv_vfs_t *vfsp = bhvtovfs(bdp);
669 xfs_mount_t *mp = XFS_BHVTOM(bdp); 661 xfs_mount_t *mp = XFS_BHVTOM(bdp);
670 int error;
671 662
672 if (!(*flags & MS_RDONLY)) { /* rw/ro -> rw */ 663 if (!(*flags & MS_RDONLY)) { /* rw/ro -> rw */
673 if (vfsp->vfs_flag & VFS_RDONLY) 664 if (vfsp->vfs_flag & VFS_RDONLY)
@@ -679,7 +670,7 @@ xfs_mntupdate(
679 mp->m_flags &= ~XFS_MOUNT_BARRIER; 670 mp->m_flags &= ~XFS_MOUNT_BARRIER;
680 } 671 }
681 } else if (!(vfsp->vfs_flag & VFS_RDONLY)) { /* rw -> ro */ 672 } else if (!(vfsp->vfs_flag & VFS_RDONLY)) { /* rw -> ro */
682 VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error); 673 bhv_vfs_sync(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL);
683 xfs_quiesce_fs(mp); 674 xfs_quiesce_fs(mp);
684 xfs_log_unmount_write(mp); 675 xfs_log_unmount_write(mp);
685 xfs_unmountfs_writesb(mp); 676 xfs_unmountfs_writesb(mp);
@@ -702,7 +693,7 @@ xfs_unmount_flush(
702 xfs_inode_t *rip = mp->m_rootip; 693 xfs_inode_t *rip = mp->m_rootip;
703 xfs_inode_t *rbmip; 694 xfs_inode_t *rbmip;
704 xfs_inode_t *rsumip = NULL; 695 xfs_inode_t *rsumip = NULL;
705 vnode_t *rvp = XFS_ITOV(rip); 696 bhv_vnode_t *rvp = XFS_ITOV(rip);
706 int error; 697 int error;
707 698
708 xfs_ilock(rip, XFS_ILOCK_EXCL); 699 xfs_ilock(rip, XFS_ILOCK_EXCL);
@@ -781,9 +772,9 @@ fscorrupt_out2:
781STATIC int 772STATIC int
782xfs_root( 773xfs_root(
783 bhv_desc_t *bdp, 774 bhv_desc_t *bdp,
784 vnode_t **vpp) 775 bhv_vnode_t **vpp)
785{ 776{
786 vnode_t *vp; 777 bhv_vnode_t *vp;
787 778
788 vp = XFS_ITOV((XFS_BHVTOM(bdp))->m_rootip); 779 vp = XFS_ITOV((XFS_BHVTOM(bdp))->m_rootip);
789 VN_HOLD(vp); 780 VN_HOLD(vp);
@@ -801,8 +792,8 @@ xfs_root(
801STATIC int 792STATIC int
802xfs_statvfs( 793xfs_statvfs(
803 bhv_desc_t *bdp, 794 bhv_desc_t *bdp,
804 xfs_statfs_t *statp, 795 bhv_statvfs_t *statp,
805 vnode_t *vp) 796 bhv_vnode_t *vp)
806{ 797{
807 __uint64_t fakeinos; 798 __uint64_t fakeinos;
808 xfs_extlen_t lsize; 799 xfs_extlen_t lsize;
@@ -900,7 +891,7 @@ xfs_sync(
900/* 891/*
901 * xfs sync routine for internal use 892 * xfs sync routine for internal use
902 * 893 *
903 * This routine supports all of the flags defined for the generic VFS_SYNC 894 * This routine supports all of the flags defined for the generic vfs_sync
904 * interface as explained above under xfs_sync. In the interests of not 895 * interface as explained above under xfs_sync. In the interests of not
905 * changing interfaces within the 6.5 family, additional internally- 896 * changing interfaces within the 6.5 family, additional internally-
906 * required functions are specified within a separate xflags parameter, 897 * required functions are specified within a separate xflags parameter,
@@ -917,7 +908,7 @@ xfs_sync_inodes(
917 xfs_inode_t *ip = NULL; 908 xfs_inode_t *ip = NULL;
918 xfs_inode_t *ip_next; 909 xfs_inode_t *ip_next;
919 xfs_buf_t *bp; 910 xfs_buf_t *bp;
920 vnode_t *vp = NULL; 911 bhv_vnode_t *vp = NULL;
921 int error; 912 int error;
922 int last_error; 913 int last_error;
923 uint64_t fflag; 914 uint64_t fflag;
@@ -1156,9 +1147,9 @@ xfs_sync_inodes(
1156 xfs_iunlock(ip, XFS_ILOCK_SHARED); 1147 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1157 1148
1158 if (XFS_FORCED_SHUTDOWN(mp)) { 1149 if (XFS_FORCED_SHUTDOWN(mp)) {
1159 VOP_TOSS_PAGES(vp, 0, -1, FI_REMAPF); 1150 bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
1160 } else { 1151 } else {
1161 VOP_FLUSHINVAL_PAGES(vp, 0, -1, FI_REMAPF); 1152 bhv_vop_flushinval_pages(vp, 0, -1, FI_REMAPF);
1162 } 1153 }
1163 1154
1164 xfs_ilock(ip, XFS_ILOCK_SHARED); 1155 xfs_ilock(ip, XFS_ILOCK_SHARED);
@@ -1178,8 +1169,8 @@ xfs_sync_inodes(
1178 * across calls to the buffer cache. 1169 * across calls to the buffer cache.
1179 */ 1170 */
1180 xfs_iunlock(ip, XFS_ILOCK_SHARED); 1171 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1181 VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 1172 error = bhv_vop_flush_pages(vp, (xfs_off_t)0,
1182 fflag, FI_NONE, error); 1173 -1, fflag, FI_NONE);
1183 xfs_ilock(ip, XFS_ILOCK_SHARED); 1174 xfs_ilock(ip, XFS_ILOCK_SHARED);
1184 } 1175 }
1185 1176
@@ -1231,9 +1222,7 @@ xfs_sync_inodes(
1231 * marker and free it. 1222 * marker and free it.
1232 */ 1223 */
1233 XFS_MOUNT_ILOCK(mp); 1224 XFS_MOUNT_ILOCK(mp);
1234
1235 IPOINTER_REMOVE(ip, mp); 1225 IPOINTER_REMOVE(ip, mp);
1236
1237 XFS_MOUNT_IUNLOCK(mp); 1226 XFS_MOUNT_IUNLOCK(mp);
1238 1227
1239 ASSERT(!(lock_flags & 1228 ASSERT(!(lock_flags &
@@ -1421,7 +1410,7 @@ xfs_sync_inodes(
1421/* 1410/*
1422 * xfs sync routine for internal use 1411 * xfs sync routine for internal use
1423 * 1412 *
1424 * This routine supports all of the flags defined for the generic VFS_SYNC 1413 * This routine supports all of the flags defined for the generic vfs_sync
1425 * interface as explained above under xfs_sync. In the interests of not 1414 * interface as explained above under xfs_sync. In the interests of not
1426 * changing interfaces within the 6.5 family, additional internally- 1415 * changing interfaces within the 6.5 family, additional internally-
1427 * required functions are specified within a separate xflags parameter, 1416 * required functions are specified within a separate xflags parameter,
@@ -1574,7 +1563,7 @@ xfs_syncsub(
1574STATIC int 1563STATIC int
1575xfs_vget( 1564xfs_vget(
1576 bhv_desc_t *bdp, 1565 bhv_desc_t *bdp,
1577 vnode_t **vpp, 1566 bhv_vnode_t **vpp,
1578 fid_t *fidp) 1567 fid_t *fidp)
1579{ 1568{
1580 xfs_mount_t *mp = XFS_BHVTOM(bdp); 1569 xfs_mount_t *mp = XFS_BHVTOM(bdp);
@@ -1657,10 +1646,10 @@ xfs_vget(
1657#define MNTOPT_NOATTR2 "noattr2" /* do not use attr2 attribute format */ 1646#define MNTOPT_NOATTR2 "noattr2" /* do not use attr2 attribute format */
1658 1647
1659STATIC unsigned long 1648STATIC unsigned long
1660suffix_strtoul(const char *cp, char **endp, unsigned int base) 1649suffix_strtoul(char *s, char **endp, unsigned int base)
1661{ 1650{
1662 int last, shift_left_factor = 0; 1651 int last, shift_left_factor = 0;
1663 char *value = (char *)cp; 1652 char *value = s;
1664 1653
1665 last = strlen(value) - 1; 1654 last = strlen(value) - 1;
1666 if (value[last] == 'K' || value[last] == 'k') { 1655 if (value[last] == 'K' || value[last] == 'k') {
@@ -1676,7 +1665,7 @@ suffix_strtoul(const char *cp, char **endp, unsigned int base)
1676 value[last] = '\0'; 1665 value[last] = '\0';
1677 } 1666 }
1678 1667
1679 return simple_strtoul(cp, endp, base) << shift_left_factor; 1668 return simple_strtoul((const char *)s, endp, base) << shift_left_factor;
1680} 1669}
1681 1670
1682STATIC int 1671STATIC int
@@ -1686,7 +1675,7 @@ xfs_parseargs(
1686 struct xfs_mount_args *args, 1675 struct xfs_mount_args *args,
1687 int update) 1676 int update)
1688{ 1677{
1689 struct vfs *vfsp = bhvtovfs(bhv); 1678 bhv_vfs_t *vfsp = bhvtovfs(bhv);
1690 char *this_char, *value, *eov; 1679 char *this_char, *value, *eov;
1691 int dsunit, dswidth, vol_dsunit, vol_dswidth; 1680 int dsunit, dswidth, vol_dsunit, vol_dswidth;
1692 int iosize; 1681 int iosize;
@@ -1708,42 +1697,48 @@ xfs_parseargs(
1708 1697
1709 if (!strcmp(this_char, MNTOPT_LOGBUFS)) { 1698 if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
1710 if (!value || !*value) { 1699 if (!value || !*value) {
1711 printk("XFS: %s option requires an argument\n", 1700 cmn_err(CE_WARN,
1701 "XFS: %s option requires an argument",
1712 this_char); 1702 this_char);
1713 return EINVAL; 1703 return EINVAL;
1714 } 1704 }
1715 args->logbufs = simple_strtoul(value, &eov, 10); 1705 args->logbufs = simple_strtoul(value, &eov, 10);
1716 } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { 1706 } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
1717 if (!value || !*value) { 1707 if (!value || !*value) {
1718 printk("XFS: %s option requires an argument\n", 1708 cmn_err(CE_WARN,
1709 "XFS: %s option requires an argument",
1719 this_char); 1710 this_char);
1720 return EINVAL; 1711 return EINVAL;
1721 } 1712 }
1722 args->logbufsize = suffix_strtoul(value, &eov, 10); 1713 args->logbufsize = suffix_strtoul(value, &eov, 10);
1723 } else if (!strcmp(this_char, MNTOPT_LOGDEV)) { 1714 } else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
1724 if (!value || !*value) { 1715 if (!value || !*value) {
1725 printk("XFS: %s option requires an argument\n", 1716 cmn_err(CE_WARN,
1717 "XFS: %s option requires an argument",
1726 this_char); 1718 this_char);
1727 return EINVAL; 1719 return EINVAL;
1728 } 1720 }
1729 strncpy(args->logname, value, MAXNAMELEN); 1721 strncpy(args->logname, value, MAXNAMELEN);
1730 } else if (!strcmp(this_char, MNTOPT_MTPT)) { 1722 } else if (!strcmp(this_char, MNTOPT_MTPT)) {
1731 if (!value || !*value) { 1723 if (!value || !*value) {
1732 printk("XFS: %s option requires an argument\n", 1724 cmn_err(CE_WARN,
1725 "XFS: %s option requires an argument",
1733 this_char); 1726 this_char);
1734 return EINVAL; 1727 return EINVAL;
1735 } 1728 }
1736 strncpy(args->mtpt, value, MAXNAMELEN); 1729 strncpy(args->mtpt, value, MAXNAMELEN);
1737 } else if (!strcmp(this_char, MNTOPT_RTDEV)) { 1730 } else if (!strcmp(this_char, MNTOPT_RTDEV)) {
1738 if (!value || !*value) { 1731 if (!value || !*value) {
1739 printk("XFS: %s option requires an argument\n", 1732 cmn_err(CE_WARN,
1733 "XFS: %s option requires an argument",
1740 this_char); 1734 this_char);
1741 return EINVAL; 1735 return EINVAL;
1742 } 1736 }
1743 strncpy(args->rtname, value, MAXNAMELEN); 1737 strncpy(args->rtname, value, MAXNAMELEN);
1744 } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { 1738 } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
1745 if (!value || !*value) { 1739 if (!value || !*value) {
1746 printk("XFS: %s option requires an argument\n", 1740 cmn_err(CE_WARN,
1741 "XFS: %s option requires an argument",
1747 this_char); 1742 this_char);
1748 return EINVAL; 1743 return EINVAL;
1749 } 1744 }
@@ -1752,7 +1747,8 @@ xfs_parseargs(
1752 args->iosizelog = (uint8_t) iosize; 1747 args->iosizelog = (uint8_t) iosize;
1753 } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) { 1748 } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
1754 if (!value || !*value) { 1749 if (!value || !*value) {
1755 printk("XFS: %s option requires an argument\n", 1750 cmn_err(CE_WARN,
1751 "XFS: %s option requires an argument",
1756 this_char); 1752 this_char);
1757 return EINVAL; 1753 return EINVAL;
1758 } 1754 }
@@ -1761,7 +1757,8 @@ xfs_parseargs(
1761 args->iosizelog = ffs(iosize) - 1; 1757 args->iosizelog = ffs(iosize) - 1;
1762 } else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) { 1758 } else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) {
1763 if (!value || !*value) { 1759 if (!value || !*value) {
1764 printk("XFS: %s option requires an argument\n", 1760 cmn_err(CE_WARN,
1761 "XFS: %s option requires an argument",
1765 this_char); 1762 this_char);
1766 return EINVAL; 1763 return EINVAL;
1767 } 1764 }
@@ -1782,7 +1779,8 @@ xfs_parseargs(
1782 } else if (!strcmp(this_char, MNTOPT_INO64)) { 1779 } else if (!strcmp(this_char, MNTOPT_INO64)) {
1783 args->flags |= XFSMNT_INO64; 1780 args->flags |= XFSMNT_INO64;
1784#if !XFS_BIG_INUMS 1781#if !XFS_BIG_INUMS
1785 printk("XFS: %s option not allowed on this system\n", 1782 cmn_err(CE_WARN,
1783 "XFS: %s option not allowed on this system",
1786 this_char); 1784 this_char);
1787 return EINVAL; 1785 return EINVAL;
1788#endif 1786#endif
@@ -1792,14 +1790,16 @@ xfs_parseargs(
1792 args->flags |= XFSMNT_SWALLOC; 1790 args->flags |= XFSMNT_SWALLOC;
1793 } else if (!strcmp(this_char, MNTOPT_SUNIT)) { 1791 } else if (!strcmp(this_char, MNTOPT_SUNIT)) {
1794 if (!value || !*value) { 1792 if (!value || !*value) {
1795 printk("XFS: %s option requires an argument\n", 1793 cmn_err(CE_WARN,
1794 "XFS: %s option requires an argument",
1796 this_char); 1795 this_char);
1797 return EINVAL; 1796 return EINVAL;
1798 } 1797 }
1799 dsunit = simple_strtoul(value, &eov, 10); 1798 dsunit = simple_strtoul(value, &eov, 10);
1800 } else if (!strcmp(this_char, MNTOPT_SWIDTH)) { 1799 } else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
1801 if (!value || !*value) { 1800 if (!value || !*value) {
1802 printk("XFS: %s option requires an argument\n", 1801 cmn_err(CE_WARN,
1802 "XFS: %s option requires an argument",
1803 this_char); 1803 this_char);
1804 return EINVAL; 1804 return EINVAL;
1805 } 1805 }
@@ -1807,7 +1807,8 @@ xfs_parseargs(
1807 } else if (!strcmp(this_char, MNTOPT_64BITINODE)) { 1807 } else if (!strcmp(this_char, MNTOPT_64BITINODE)) {
1808 args->flags &= ~XFSMNT_32BITINODES; 1808 args->flags &= ~XFSMNT_32BITINODES;
1809#if !XFS_BIG_INUMS 1809#if !XFS_BIG_INUMS
1810 printk("XFS: %s option not allowed on this system\n", 1810 cmn_err(CE_WARN,
1811 "XFS: %s option not allowed on this system",
1811 this_char); 1812 this_char);
1812 return EINVAL; 1813 return EINVAL;
1813#endif 1814#endif
@@ -1831,36 +1832,41 @@ xfs_parseargs(
1831 args->flags &= ~XFSMNT_ATTR2; 1832 args->flags &= ~XFSMNT_ATTR2;
1832 } else if (!strcmp(this_char, "osyncisdsync")) { 1833 } else if (!strcmp(this_char, "osyncisdsync")) {
1833 /* no-op, this is now the default */ 1834 /* no-op, this is now the default */
1834printk("XFS: osyncisdsync is now the default, option is deprecated.\n"); 1835 cmn_err(CE_WARN,
1836 "XFS: osyncisdsync is now the default, option is deprecated.");
1835 } else if (!strcmp(this_char, "irixsgid")) { 1837 } else if (!strcmp(this_char, "irixsgid")) {
1836printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n"); 1838 cmn_err(CE_WARN,
1839 "XFS: irixsgid is now a sysctl(2) variable, option is deprecated.");
1837 } else { 1840 } else {
1838 printk("XFS: unknown mount option [%s].\n", this_char); 1841 cmn_err(CE_WARN,
1842 "XFS: unknown mount option [%s].", this_char);
1839 return EINVAL; 1843 return EINVAL;
1840 } 1844 }
1841 } 1845 }
1842 1846
1843 if (args->flags & XFSMNT_NORECOVERY) { 1847 if (args->flags & XFSMNT_NORECOVERY) {
1844 if ((vfsp->vfs_flag & VFS_RDONLY) == 0) { 1848 if ((vfsp->vfs_flag & VFS_RDONLY) == 0) {
1845 printk("XFS: no-recovery mounts must be read-only.\n"); 1849 cmn_err(CE_WARN,
1850 "XFS: no-recovery mounts must be read-only.");
1846 return EINVAL; 1851 return EINVAL;
1847 } 1852 }
1848 } 1853 }
1849 1854
1850 if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) { 1855 if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) {
1851 printk( 1856 cmn_err(CE_WARN,
1852 "XFS: sunit and swidth options incompatible with the noalign option\n"); 1857 "XFS: sunit and swidth options incompatible with the noalign option");
1853 return EINVAL; 1858 return EINVAL;
1854 } 1859 }
1855 1860
1856 if ((dsunit && !dswidth) || (!dsunit && dswidth)) { 1861 if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
1857 printk("XFS: sunit and swidth must be specified together\n"); 1862 cmn_err(CE_WARN,
1863 "XFS: sunit and swidth must be specified together");
1858 return EINVAL; 1864 return EINVAL;
1859 } 1865 }
1860 1866
1861 if (dsunit && (dswidth % dsunit != 0)) { 1867 if (dsunit && (dswidth % dsunit != 0)) {
1862 printk( 1868 cmn_err(CE_WARN,
1863 "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)\n", 1869 "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)",
1864 dswidth, dsunit); 1870 dswidth, dsunit);
1865 return EINVAL; 1871 return EINVAL;
1866 } 1872 }
@@ -1907,7 +1913,7 @@ xfs_showargs(
1907 }; 1913 };
1908 struct proc_xfs_info *xfs_infop; 1914 struct proc_xfs_info *xfs_infop;
1909 struct xfs_mount *mp = XFS_BHVTOM(bhv); 1915 struct xfs_mount *mp = XFS_BHVTOM(bhv);
1910 struct vfs *vfsp = XFS_MTOVFS(mp); 1916 struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
1911 1917
1912 for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) { 1918 for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) {
1913 if (mp->m_flags & xfs_infop->flag) 1919 if (mp->m_flags & xfs_infop->flag)
@@ -1967,7 +1973,7 @@ xfs_freeze(
1967} 1973}
1968 1974
1969 1975
1970vfsops_t xfs_vfsops = { 1976bhv_vfsops_t xfs_vfsops = {
1971 BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS), 1977 BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS),
1972 .vfs_parseargs = xfs_parseargs, 1978 .vfs_parseargs = xfs_parseargs,
1973 .vfs_showargs = xfs_showargs, 1979 .vfs_showargs = xfs_showargs,
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 7027ae68ee38..00a6b7dc24a0 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -16,8 +16,6 @@
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */ 17 */
18 18
19#include <linux/capability.h>
20
21#include "xfs.h" 19#include "xfs.h"
22#include "xfs_fs.h" 20#include "xfs_fs.h"
23#include "xfs_types.h" 21#include "xfs_types.h"
@@ -27,7 +25,6 @@
27#include "xfs_trans.h" 25#include "xfs_trans.h"
28#include "xfs_sb.h" 26#include "xfs_sb.h"
29#include "xfs_ag.h" 27#include "xfs_ag.h"
30#include "xfs_dir.h"
31#include "xfs_dir2.h" 28#include "xfs_dir2.h"
32#include "xfs_dmapi.h" 29#include "xfs_dmapi.h"
33#include "xfs_mount.h" 30#include "xfs_mount.h"
@@ -35,13 +32,11 @@
35#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
36#include "xfs_alloc_btree.h" 33#include "xfs_alloc_btree.h"
37#include "xfs_ialloc_btree.h" 34#include "xfs_ialloc_btree.h"
38#include "xfs_dir_sf.h"
39#include "xfs_dir2_sf.h" 35#include "xfs_dir2_sf.h"
40#include "xfs_attr_sf.h" 36#include "xfs_attr_sf.h"
41#include "xfs_dinode.h" 37#include "xfs_dinode.h"
42#include "xfs_inode.h" 38#include "xfs_inode.h"
43#include "xfs_inode_item.h" 39#include "xfs_inode_item.h"
44#include "xfs_dir_leaf.h"
45#include "xfs_itable.h" 40#include "xfs_itable.h"
46#include "xfs_btree.h" 41#include "xfs_btree.h"
47#include "xfs_ialloc.h" 42#include "xfs_ialloc.h"
@@ -58,32 +53,14 @@
58#include "xfs_log_priv.h" 53#include "xfs_log_priv.h"
59#include "xfs_mac.h" 54#include "xfs_mac.h"
60 55
61
62/*
63 * The maximum pathlen is 1024 bytes. Since the minimum file system
64 * blocksize is 512 bytes, we can get a max of 2 extents back from
65 * bmapi.
66 */
67#define SYMLINK_MAPS 2
68
69/*
70 * For xfs, we check that the file isn't too big to be opened by this kernel.
71 * No other open action is required for regular files. Devices are handled
72 * through the specfs file system, pipes through fifofs. Device and
73 * fifo vnodes are "wrapped" by specfs and fifofs vnodes, respectively,
74 * when a new vnode is first looked up or created.
75 */
76STATIC int 56STATIC int
77xfs_open( 57xfs_open(
78 bhv_desc_t *bdp, 58 bhv_desc_t *bdp,
79 cred_t *credp) 59 cred_t *credp)
80{ 60{
81 int mode; 61 int mode;
82 vnode_t *vp; 62 bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
83 xfs_inode_t *ip; 63 xfs_inode_t *ip = XFS_BHVTOI(bdp);
84
85 vp = BHV_TO_VNODE(bdp);
86 ip = XFS_BHVTOI(bdp);
87 64
88 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) 65 if (XFS_FORCED_SHUTDOWN(ip->i_mount))
89 return XFS_ERROR(EIO); 66 return XFS_ERROR(EIO);
@@ -101,6 +78,35 @@ xfs_open(
101 return 0; 78 return 0;
102} 79}
103 80
81STATIC int
82xfs_close(
83 bhv_desc_t *bdp,
84 int flags,
85 lastclose_t lastclose,
86 cred_t *credp)
87{
88 bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
89 xfs_inode_t *ip = XFS_BHVTOI(bdp);
90
91 if (XFS_FORCED_SHUTDOWN(ip->i_mount))
92 return XFS_ERROR(EIO);
93
94 if (lastclose != L_TRUE || !VN_ISREG(vp))
95 return 0;
96
97 /*
98 * If we previously truncated this file and removed old data in
99 * the process, we want to initiate "early" writeout on the last
100 * close. This is an attempt to combat the notorious NULL files
101 * problem which is particularly noticable from a truncate down,
102 * buffered (re-)write (delalloc), followed by a crash. What we
103 * are effectively doing here is significantly reducing the time
104 * window where we'd otherwise be exposed to that problem.
105 */
106 if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0)
107 return bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE);
108 return 0;
109}
104 110
105/* 111/*
106 * xfs_getattr 112 * xfs_getattr
@@ -108,13 +114,13 @@ xfs_open(
108STATIC int 114STATIC int
109xfs_getattr( 115xfs_getattr(
110 bhv_desc_t *bdp, 116 bhv_desc_t *bdp,
111 vattr_t *vap, 117 bhv_vattr_t *vap,
112 int flags, 118 int flags,
113 cred_t *credp) 119 cred_t *credp)
114{ 120{
115 xfs_inode_t *ip; 121 xfs_inode_t *ip;
116 xfs_mount_t *mp; 122 xfs_mount_t *mp;
117 vnode_t *vp; 123 bhv_vnode_t *vp;
118 124
119 vp = BHV_TO_VNODE(bdp); 125 vp = BHV_TO_VNODE(bdp);
120 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); 126 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -241,7 +247,7 @@ xfs_getattr(
241int 247int
242xfs_setattr( 248xfs_setattr(
243 bhv_desc_t *bdp, 249 bhv_desc_t *bdp,
244 vattr_t *vap, 250 bhv_vattr_t *vap,
245 int flags, 251 int flags,
246 cred_t *credp) 252 cred_t *credp)
247{ 253{
@@ -255,7 +261,7 @@ xfs_setattr(
255 uid_t uid=0, iuid=0; 261 uid_t uid=0, iuid=0;
256 gid_t gid=0, igid=0; 262 gid_t gid=0, igid=0;
257 int timeflags = 0; 263 int timeflags = 0;
258 vnode_t *vp; 264 bhv_vnode_t *vp;
259 xfs_prid_t projid=0, iprojid=0; 265 xfs_prid_t projid=0, iprojid=0;
260 int mandlock_before, mandlock_after; 266 int mandlock_before, mandlock_after;
261 struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; 267 struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2;
@@ -347,7 +353,6 @@ xfs_setattr(
347 */ 353 */
348 tp = NULL; 354 tp = NULL;
349 lock_flags = XFS_ILOCK_EXCL; 355 lock_flags = XFS_ILOCK_EXCL;
350 ASSERT(flags & ATTR_NOLOCK ? flags & ATTR_DMI : 1);
351 if (flags & ATTR_NOLOCK) 356 if (flags & ATTR_NOLOCK)
352 need_iolock = 0; 357 need_iolock = 0;
353 if (!(mask & XFS_AT_SIZE)) { 358 if (!(mask & XFS_AT_SIZE)) {
@@ -666,9 +671,17 @@ xfs_setattr(
666 ((ip->i_d.di_nlink != 0 || 671 ((ip->i_d.di_nlink != 0 ||
667 !(mp->m_flags & XFS_MOUNT_WSYNC)) 672 !(mp->m_flags & XFS_MOUNT_WSYNC))
668 ? 1 : 0)); 673 ? 1 : 0));
669 if (code) { 674 if (code)
670 goto abort_return; 675 goto abort_return;
671 } 676 /*
677 * Truncated "down", so we're removing references
678 * to old data here - if we now delay flushing for
679 * a long time, we expose ourselves unduly to the
680 * notorious NULL files problem. So, we mark this
681 * vnode and flush it when the file is closed, and
682 * do not wait the usual (long) time for writeout.
683 */
684 VTRUNCATE(vp);
672 } 685 }
673 /* 686 /*
674 * Have to do this even if the file's size doesn't change. 687 * Have to do this even if the file's size doesn't change.
@@ -800,6 +813,8 @@ xfs_setattr(
800 di_flags |= XFS_DIFLAG_NODUMP; 813 di_flags |= XFS_DIFLAG_NODUMP;
801 if (vap->va_xflags & XFS_XFLAG_PROJINHERIT) 814 if (vap->va_xflags & XFS_XFLAG_PROJINHERIT)
802 di_flags |= XFS_DIFLAG_PROJINHERIT; 815 di_flags |= XFS_DIFLAG_PROJINHERIT;
816 if (vap->va_xflags & XFS_XFLAG_NODEFRAG)
817 di_flags |= XFS_DIFLAG_NODEFRAG;
803 if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { 818 if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
804 if (vap->va_xflags & XFS_XFLAG_RTINHERIT) 819 if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
805 di_flags |= XFS_DIFLAG_RTINHERIT; 820 di_flags |= XFS_DIFLAG_RTINHERIT;
@@ -869,7 +884,7 @@ xfs_setattr(
869 */ 884 */
870 mandlock_after = MANDLOCK(vp, ip->i_d.di_mode); 885 mandlock_after = MANDLOCK(vp, ip->i_d.di_mode);
871 if (mandlock_before != mandlock_after) { 886 if (mandlock_before != mandlock_after) {
872 VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_ENF_LOCKING, 887 bhv_vop_vnode_change(vp, VCHANGE_FLAGS_ENF_LOCKING,
873 mandlock_after); 888 mandlock_after);
874 } 889 }
875 890
@@ -936,6 +951,13 @@ xfs_access(
936 951
937 952
938/* 953/*
954 * The maximum pathlen is 1024 bytes. Since the minimum file system
955 * blocksize is 512 bytes, we can get a max of 2 extents back from
956 * bmapi.
957 */
958#define SYMLINK_MAPS 2
959
960/*
939 * xfs_readlink 961 * xfs_readlink
940 * 962 *
941 */ 963 */
@@ -950,7 +972,7 @@ xfs_readlink(
950 int count; 972 int count;
951 xfs_off_t offset; 973 xfs_off_t offset;
952 int pathlen; 974 int pathlen;
953 vnode_t *vp; 975 bhv_vnode_t *vp;
954 int error = 0; 976 int error = 0;
955 xfs_mount_t *mp; 977 xfs_mount_t *mp;
956 int nmaps; 978 int nmaps;
@@ -1000,7 +1022,7 @@ xfs_readlink(
1000 nmaps = SYMLINK_MAPS; 1022 nmaps = SYMLINK_MAPS;
1001 1023
1002 error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), 1024 error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen),
1003 0, NULL, 0, mval, &nmaps, NULL); 1025 0, NULL, 0, mval, &nmaps, NULL, NULL);
1004 1026
1005 if (error) { 1027 if (error) {
1006 goto error_return; 1028 goto error_return;
@@ -1208,8 +1230,8 @@ xfs_inactive_free_eofblocks(
1208 1230
1209 nimaps = 1; 1231 nimaps = 1;
1210 xfs_ilock(ip, XFS_ILOCK_SHARED); 1232 xfs_ilock(ip, XFS_ILOCK_SHARED);
1211 error = xfs_bmapi(NULL, ip, end_fsb, map_len, 0, 1233 error = XFS_BMAPI(mp, NULL, &ip->i_iocore, end_fsb, map_len, 0,
1212 NULL, 0, &imap, &nimaps, NULL); 1234 NULL, 0, &imap, &nimaps, NULL, NULL);
1213 xfs_iunlock(ip, XFS_ILOCK_SHARED); 1235 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1214 1236
1215 if (!error && (nimaps != 0) && 1237 if (!error && (nimaps != 0) &&
@@ -1338,7 +1360,7 @@ xfs_inactive_symlink_rmt(
1338 nmaps = ARRAY_SIZE(mval); 1360 nmaps = ARRAY_SIZE(mval);
1339 if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size), 1361 if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size),
1340 XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps, 1362 XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps,
1341 &free_list))) 1363 &free_list, NULL)))
1342 goto error0; 1364 goto error0;
1343 /* 1365 /*
1344 * Invalidate the block(s). 1366 * Invalidate the block(s).
@@ -1353,7 +1375,7 @@ xfs_inactive_symlink_rmt(
1353 * Unmap the dead block(s) to the free_list. 1375 * Unmap the dead block(s) to the free_list.
1354 */ 1376 */
1355 if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, 1377 if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps,
1356 &first_block, &free_list, &done))) 1378 &first_block, &free_list, NULL, &done)))
1357 goto error1; 1379 goto error1;
1358 ASSERT(done); 1380 ASSERT(done);
1359 /* 1381 /*
@@ -1469,9 +1491,6 @@ xfs_inactive_symlink_local(
1469 return 0; 1491 return 0;
1470} 1492}
1471 1493
1472/*
1473 *
1474 */
1475STATIC int 1494STATIC int
1476xfs_inactive_attrs( 1495xfs_inactive_attrs(
1477 xfs_inode_t *ip, 1496 xfs_inode_t *ip,
@@ -1524,16 +1543,16 @@ xfs_release(
1524 bhv_desc_t *bdp) 1543 bhv_desc_t *bdp)
1525{ 1544{
1526 xfs_inode_t *ip; 1545 xfs_inode_t *ip;
1527 vnode_t *vp; 1546 bhv_vnode_t *vp;
1528 xfs_mount_t *mp; 1547 xfs_mount_t *mp;
1529 int error; 1548 int error;
1530 1549
1531 vp = BHV_TO_VNODE(bdp); 1550 vp = BHV_TO_VNODE(bdp);
1532 ip = XFS_BHVTOI(bdp); 1551 ip = XFS_BHVTOI(bdp);
1552 mp = ip->i_mount;
1533 1553
1534 if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0)) { 1554 if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0))
1535 return 0; 1555 return 0;
1536 }
1537 1556
1538 /* If this is a read-only mount, don't do this (would generate I/O) */ 1557 /* If this is a read-only mount, don't do this (would generate I/O) */
1539 if (vp->v_vfsp->vfs_flag & VFS_RDONLY) 1558 if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
@@ -1545,8 +1564,6 @@ xfs_release(
1545 return 0; 1564 return 0;
1546#endif 1565#endif
1547 1566
1548 mp = ip->i_mount;
1549
1550 if (ip->i_d.di_nlink != 0) { 1567 if (ip->i_d.di_nlink != 0) {
1551 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && 1568 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
1552 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 || 1569 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
@@ -1579,8 +1596,8 @@ xfs_inactive(
1579 cred_t *credp) 1596 cred_t *credp)
1580{ 1597{
1581 xfs_inode_t *ip; 1598 xfs_inode_t *ip;
1582 vnode_t *vp; 1599 bhv_vnode_t *vp;
1583 xfs_bmap_free_t free_list; 1600 xfs_bmap_free_t free_list;
1584 xfs_fsblock_t first_block; 1601 xfs_fsblock_t first_block;
1585 int committed; 1602 int committed;
1586 xfs_trans_t *tp; 1603 xfs_trans_t *tp;
@@ -1760,7 +1777,7 @@ xfs_inactive(
1760 cmn_err(CE_NOTE, 1777 cmn_err(CE_NOTE,
1761 "xfs_inactive: xfs_ifree() returned an error = %d on %s", 1778 "xfs_inactive: xfs_ifree() returned an error = %d on %s",
1762 error, mp->m_fsname); 1779 error, mp->m_fsname);
1763 xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); 1780 xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
1764 } 1781 }
1765 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); 1782 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
1766 } else { 1783 } else {
@@ -1795,17 +1812,17 @@ xfs_inactive(
1795STATIC int 1812STATIC int
1796xfs_lookup( 1813xfs_lookup(
1797 bhv_desc_t *dir_bdp, 1814 bhv_desc_t *dir_bdp,
1798 vname_t *dentry, 1815 bhv_vname_t *dentry,
1799 vnode_t **vpp, 1816 bhv_vnode_t **vpp,
1800 int flags, 1817 int flags,
1801 vnode_t *rdir, 1818 bhv_vnode_t *rdir,
1802 cred_t *credp) 1819 cred_t *credp)
1803{ 1820{
1804 xfs_inode_t *dp, *ip; 1821 xfs_inode_t *dp, *ip;
1805 xfs_ino_t e_inum; 1822 xfs_ino_t e_inum;
1806 int error; 1823 int error;
1807 uint lock_mode; 1824 uint lock_mode;
1808 vnode_t *dir_vp; 1825 bhv_vnode_t *dir_vp;
1809 1826
1810 dir_vp = BHV_TO_VNODE(dir_bdp); 1827 dir_vp = BHV_TO_VNODE(dir_bdp);
1811 vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address); 1828 vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
@@ -1832,15 +1849,15 @@ xfs_lookup(
1832STATIC int 1849STATIC int
1833xfs_create( 1850xfs_create(
1834 bhv_desc_t *dir_bdp, 1851 bhv_desc_t *dir_bdp,
1835 vname_t *dentry, 1852 bhv_vname_t *dentry,
1836 vattr_t *vap, 1853 bhv_vattr_t *vap,
1837 vnode_t **vpp, 1854 bhv_vnode_t **vpp,
1838 cred_t *credp) 1855 cred_t *credp)
1839{ 1856{
1840 char *name = VNAME(dentry); 1857 char *name = VNAME(dentry);
1841 vnode_t *dir_vp; 1858 bhv_vnode_t *dir_vp;
1842 xfs_inode_t *dp, *ip; 1859 xfs_inode_t *dp, *ip;
1843 vnode_t *vp=NULL; 1860 bhv_vnode_t *vp = NULL;
1844 xfs_trans_t *tp; 1861 xfs_trans_t *tp;
1845 xfs_mount_t *mp; 1862 xfs_mount_t *mp;
1846 xfs_dev_t rdev; 1863 xfs_dev_t rdev;
@@ -1938,8 +1955,7 @@ xfs_create(
1938 if (error) 1955 if (error)
1939 goto error_return; 1956 goto error_return;
1940 1957
1941 if (resblks == 0 && 1958 if (resblks == 0 && (error = xfs_dir_canenter(tp, dp, name, namelen)))
1942 (error = XFS_DIR_CANENTER(mp, tp, dp, name, namelen)))
1943 goto error_return; 1959 goto error_return;
1944 rdev = (vap->va_mask & XFS_AT_RDEV) ? vap->va_rdev : 0; 1960 rdev = (vap->va_mask & XFS_AT_RDEV) ? vap->va_rdev : 0;
1945 error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 1, 1961 error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 1,
@@ -1970,9 +1986,9 @@ xfs_create(
1970 xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); 1986 xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
1971 dp_joined_to_trans = B_TRUE; 1987 dp_joined_to_trans = B_TRUE;
1972 1988
1973 error = XFS_DIR_CREATENAME(mp, tp, dp, name, namelen, ip->i_ino, 1989 error = xfs_dir_createname(tp, dp, name, namelen, ip->i_ino,
1974 &first_block, &free_list, 1990 &first_block, &free_list, resblks ?
1975 resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0); 1991 resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
1976 if (error) { 1992 if (error) {
1977 ASSERT(error != ENOSPC); 1993 ASSERT(error != ENOSPC);
1978 goto abort_return; 1994 goto abort_return;
@@ -2026,7 +2042,7 @@ xfs_create(
2026 * Propagate the fact that the vnode changed after the 2042 * Propagate the fact that the vnode changed after the
2027 * xfs_inode locks have been released. 2043 * xfs_inode locks have been released.
2028 */ 2044 */
2029 VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_TRUNCATED, 3); 2045 bhv_vop_vnode_change(vp, VCHANGE_FLAGS_TRUNCATED, 3);
2030 2046
2031 *vpp = vp; 2047 *vpp = vp;
2032 2048
@@ -2107,7 +2123,7 @@ int xfs_rm_attempts;
2107STATIC int 2123STATIC int
2108xfs_lock_dir_and_entry( 2124xfs_lock_dir_and_entry(
2109 xfs_inode_t *dp, 2125 xfs_inode_t *dp,
2110 vname_t *dentry, 2126 bhv_vname_t *dentry,
2111 xfs_inode_t *ip) /* inode of entry 'name' */ 2127 xfs_inode_t *ip) /* inode of entry 'name' */
2112{ 2128{
2113 int attempts; 2129 int attempts;
@@ -2321,10 +2337,10 @@ int remove_which_error_return = 0;
2321STATIC int 2337STATIC int
2322xfs_remove( 2338xfs_remove(
2323 bhv_desc_t *dir_bdp, 2339 bhv_desc_t *dir_bdp,
2324 vname_t *dentry, 2340 bhv_vname_t *dentry,
2325 cred_t *credp) 2341 cred_t *credp)
2326{ 2342{
2327 vnode_t *dir_vp; 2343 bhv_vnode_t *dir_vp;
2328 char *name = VNAME(dentry); 2344 char *name = VNAME(dentry);
2329 xfs_inode_t *dp, *ip; 2345 xfs_inode_t *dp, *ip;
2330 xfs_trans_t *tp = NULL; 2346 xfs_trans_t *tp = NULL;
@@ -2448,8 +2464,8 @@ xfs_remove(
2448 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry. 2464 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
2449 */ 2465 */
2450 XFS_BMAP_INIT(&free_list, &first_block); 2466 XFS_BMAP_INIT(&free_list, &first_block);
2451 error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, ip->i_ino, 2467 error = xfs_dir_removename(tp, dp, name, namelen, ip->i_ino,
2452 &first_block, &free_list, 0); 2468 &first_block, &free_list, 0);
2453 if (error) { 2469 if (error) {
2454 ASSERT(error != ENOENT); 2470 ASSERT(error != ENOENT);
2455 REMOVE_DEBUG_TRACE(__LINE__); 2471 REMOVE_DEBUG_TRACE(__LINE__);
@@ -2511,7 +2527,7 @@ xfs_remove(
2511 /* 2527 /*
2512 * Let interposed file systems know about removed links. 2528 * Let interposed file systems know about removed links.
2513 */ 2529 */
2514 VOP_LINK_REMOVED(XFS_ITOV(ip), dir_vp, link_zero); 2530 bhv_vop_link_removed(XFS_ITOV(ip), dir_vp, link_zero);
2515 2531
2516 IRELE(ip); 2532 IRELE(ip);
2517 2533
@@ -2564,8 +2580,8 @@ xfs_remove(
2564STATIC int 2580STATIC int
2565xfs_link( 2581xfs_link(
2566 bhv_desc_t *target_dir_bdp, 2582 bhv_desc_t *target_dir_bdp,
2567 vnode_t *src_vp, 2583 bhv_vnode_t *src_vp,
2568 vname_t *dentry, 2584 bhv_vname_t *dentry,
2569 cred_t *credp) 2585 cred_t *credp)
2570{ 2586{
2571 xfs_inode_t *tdp, *sip; 2587 xfs_inode_t *tdp, *sip;
@@ -2577,7 +2593,7 @@ xfs_link(
2577 xfs_fsblock_t first_block; 2593 xfs_fsblock_t first_block;
2578 int cancel_flags; 2594 int cancel_flags;
2579 int committed; 2595 int committed;
2580 vnode_t *target_dir_vp; 2596 bhv_vnode_t *target_dir_vp;
2581 int resblks; 2597 int resblks;
2582 char *target_name = VNAME(dentry); 2598 char *target_name = VNAME(dentry);
2583 int target_namelen; 2599 int target_namelen;
@@ -2668,13 +2684,12 @@ xfs_link(
2668 } 2684 }
2669 2685
2670 if (resblks == 0 && 2686 if (resblks == 0 &&
2671 (error = XFS_DIR_CANENTER(mp, tp, tdp, target_name, 2687 (error = xfs_dir_canenter(tp, tdp, target_name, target_namelen)))
2672 target_namelen)))
2673 goto error_return; 2688 goto error_return;
2674 2689
2675 XFS_BMAP_INIT(&free_list, &first_block); 2690 XFS_BMAP_INIT(&free_list, &first_block);
2676 2691
2677 error = XFS_DIR_CREATENAME(mp, tp, tdp, target_name, target_namelen, 2692 error = xfs_dir_createname(tp, tdp, target_name, target_namelen,
2678 sip->i_ino, &first_block, &free_list, 2693 sip->i_ino, &first_block, &free_list,
2679 resblks); 2694 resblks);
2680 if (error) 2695 if (error)
@@ -2734,15 +2749,15 @@ std_return:
2734STATIC int 2749STATIC int
2735xfs_mkdir( 2750xfs_mkdir(
2736 bhv_desc_t *dir_bdp, 2751 bhv_desc_t *dir_bdp,
2737 vname_t *dentry, 2752 bhv_vname_t *dentry,
2738 vattr_t *vap, 2753 bhv_vattr_t *vap,
2739 vnode_t **vpp, 2754 bhv_vnode_t **vpp,
2740 cred_t *credp) 2755 cred_t *credp)
2741{ 2756{
2742 char *dir_name = VNAME(dentry); 2757 char *dir_name = VNAME(dentry);
2743 xfs_inode_t *dp; 2758 xfs_inode_t *dp;
2744 xfs_inode_t *cdp; /* inode of created dir */ 2759 xfs_inode_t *cdp; /* inode of created dir */
2745 vnode_t *cvp; /* vnode of created dir */ 2760 bhv_vnode_t *cvp; /* vnode of created dir */
2746 xfs_trans_t *tp; 2761 xfs_trans_t *tp;
2747 xfs_mount_t *mp; 2762 xfs_mount_t *mp;
2748 int cancel_flags; 2763 int cancel_flags;
@@ -2750,7 +2765,7 @@ xfs_mkdir(
2750 int committed; 2765 int committed;
2751 xfs_bmap_free_t free_list; 2766 xfs_bmap_free_t free_list;
2752 xfs_fsblock_t first_block; 2767 xfs_fsblock_t first_block;
2753 vnode_t *dir_vp; 2768 bhv_vnode_t *dir_vp;
2754 boolean_t dp_joined_to_trans; 2769 boolean_t dp_joined_to_trans;
2755 boolean_t created = B_FALSE; 2770 boolean_t created = B_FALSE;
2756 int dm_event_sent = 0; 2771 int dm_event_sent = 0;
@@ -2840,7 +2855,7 @@ xfs_mkdir(
2840 goto error_return; 2855 goto error_return;
2841 2856
2842 if (resblks == 0 && 2857 if (resblks == 0 &&
2843 (error = XFS_DIR_CANENTER(mp, tp, dp, dir_name, dir_namelen))) 2858 (error = xfs_dir_canenter(tp, dp, dir_name, dir_namelen)))
2844 goto error_return; 2859 goto error_return;
2845 /* 2860 /*
2846 * create the directory inode. 2861 * create the directory inode.
@@ -2867,9 +2882,9 @@ xfs_mkdir(
2867 2882
2868 XFS_BMAP_INIT(&free_list, &first_block); 2883 XFS_BMAP_INIT(&free_list, &first_block);
2869 2884
2870 error = XFS_DIR_CREATENAME(mp, tp, dp, dir_name, dir_namelen, 2885 error = xfs_dir_createname(tp, dp, dir_name, dir_namelen, cdp->i_ino,
2871 cdp->i_ino, &first_block, &free_list, 2886 &first_block, &free_list, resblks ?
2872 resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0); 2887 resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
2873 if (error) { 2888 if (error) {
2874 ASSERT(error != ENOSPC); 2889 ASSERT(error != ENOSPC);
2875 goto error1; 2890 goto error1;
@@ -2883,16 +2898,14 @@ xfs_mkdir(
2883 */ 2898 */
2884 dp->i_gen++; 2899 dp->i_gen++;
2885 2900
2886 error = XFS_DIR_INIT(mp, tp, cdp, dp); 2901 error = xfs_dir_init(tp, cdp, dp);
2887 if (error) { 2902 if (error)
2888 goto error2; 2903 goto error2;
2889 }
2890 2904
2891 cdp->i_gen = 1; 2905 cdp->i_gen = 1;
2892 error = xfs_bumplink(tp, dp); 2906 error = xfs_bumplink(tp, dp);
2893 if (error) { 2907 if (error)
2894 goto error2; 2908 goto error2;
2895 }
2896 2909
2897 cvp = XFS_ITOV(cdp); 2910 cvp = XFS_ITOV(cdp);
2898 2911
@@ -2969,7 +2982,7 @@ std_return:
2969STATIC int 2982STATIC int
2970xfs_rmdir( 2983xfs_rmdir(
2971 bhv_desc_t *dir_bdp, 2984 bhv_desc_t *dir_bdp,
2972 vname_t *dentry, 2985 bhv_vname_t *dentry,
2973 cred_t *credp) 2986 cred_t *credp)
2974{ 2987{
2975 char *name = VNAME(dentry); 2988 char *name = VNAME(dentry);
@@ -2982,7 +2995,7 @@ xfs_rmdir(
2982 xfs_fsblock_t first_block; 2995 xfs_fsblock_t first_block;
2983 int cancel_flags; 2996 int cancel_flags;
2984 int committed; 2997 int committed;
2985 vnode_t *dir_vp; 2998 bhv_vnode_t *dir_vp;
2986 int dm_di_mode = 0; 2999 int dm_di_mode = 0;
2987 int last_cdp_link; 3000 int last_cdp_link;
2988 int namelen; 3001 int namelen;
@@ -3101,16 +3114,15 @@ xfs_rmdir(
3101 error = XFS_ERROR(ENOTEMPTY); 3114 error = XFS_ERROR(ENOTEMPTY);
3102 goto error_return; 3115 goto error_return;
3103 } 3116 }
3104 if (!XFS_DIR_ISEMPTY(mp, cdp)) { 3117 if (!xfs_dir_isempty(cdp)) {
3105 error = XFS_ERROR(ENOTEMPTY); 3118 error = XFS_ERROR(ENOTEMPTY);
3106 goto error_return; 3119 goto error_return;
3107 } 3120 }
3108 3121
3109 error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, cdp->i_ino, 3122 error = xfs_dir_removename(tp, dp, name, namelen, cdp->i_ino,
3110 &first_block, &free_list, resblks); 3123 &first_block, &free_list, resblks);
3111 if (error) { 3124 if (error)
3112 goto error1; 3125 goto error1;
3113 }
3114 3126
3115 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 3127 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
3116 3128
@@ -3181,7 +3193,7 @@ xfs_rmdir(
3181 /* 3193 /*
3182 * Let interposed file systems know about removed links. 3194 * Let interposed file systems know about removed links.
3183 */ 3195 */
3184 VOP_LINK_REMOVED(XFS_ITOV(cdp), dir_vp, last_cdp_link); 3196 bhv_vop_link_removed(XFS_ITOV(cdp), dir_vp, last_cdp_link);
3185 3197
3186 IRELE(cdp); 3198 IRELE(cdp);
3187 3199
@@ -3209,8 +3221,6 @@ xfs_rmdir(
3209 3221
3210 3222
3211/* 3223/*
3212 * xfs_readdir
3213 *
3214 * Read dp's entries starting at uiop->uio_offset and translate them into 3224 * Read dp's entries starting at uiop->uio_offset and translate them into
3215 * bufsize bytes worth of struct dirents starting at bufbase. 3225 * bufsize bytes worth of struct dirents starting at bufbase.
3216 */ 3226 */
@@ -3230,28 +3240,23 @@ xfs_readdir(
3230 (inst_t *)__return_address); 3240 (inst_t *)__return_address);
3231 dp = XFS_BHVTOI(dir_bdp); 3241 dp = XFS_BHVTOI(dir_bdp);
3232 3242
3233 if (XFS_FORCED_SHUTDOWN(dp->i_mount)) { 3243 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
3234 return XFS_ERROR(EIO); 3244 return XFS_ERROR(EIO);
3235 }
3236 3245
3237 lock_mode = xfs_ilock_map_shared(dp); 3246 lock_mode = xfs_ilock_map_shared(dp);
3238 error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp); 3247 error = xfs_dir_getdents(tp, dp, uiop, eofp);
3239 xfs_iunlock_map_shared(dp, lock_mode); 3248 xfs_iunlock_map_shared(dp, lock_mode);
3240 return error; 3249 return error;
3241} 3250}
3242 3251
3243 3252
3244/*
3245 * xfs_symlink
3246 *
3247 */
3248STATIC int 3253STATIC int
3249xfs_symlink( 3254xfs_symlink(
3250 bhv_desc_t *dir_bdp, 3255 bhv_desc_t *dir_bdp,
3251 vname_t *dentry, 3256 bhv_vname_t *dentry,
3252 vattr_t *vap, 3257 bhv_vattr_t *vap,
3253 char *target_path, 3258 char *target_path,
3254 vnode_t **vpp, 3259 bhv_vnode_t **vpp,
3255 cred_t *credp) 3260 cred_t *credp)
3256{ 3261{
3257 xfs_trans_t *tp; 3262 xfs_trans_t *tp;
@@ -3263,7 +3268,7 @@ xfs_symlink(
3263 xfs_bmap_free_t free_list; 3268 xfs_bmap_free_t free_list;
3264 xfs_fsblock_t first_block; 3269 xfs_fsblock_t first_block;
3265 boolean_t dp_joined_to_trans; 3270 boolean_t dp_joined_to_trans;
3266 vnode_t *dir_vp; 3271 bhv_vnode_t *dir_vp;
3267 uint cancel_flags; 3272 uint cancel_flags;
3268 int committed; 3273 int committed;
3269 xfs_fileoff_t first_fsb; 3274 xfs_fileoff_t first_fsb;
@@ -3308,7 +3313,7 @@ xfs_symlink(
3308 int len, total; 3313 int len, total;
3309 char *path; 3314 char *path;
3310 3315
3311 for(total = 0, path = target_path; total < pathlen;) { 3316 for (total = 0, path = target_path; total < pathlen;) {
3312 /* 3317 /*
3313 * Skip any slashes. 3318 * Skip any slashes.
3314 */ 3319 */
@@ -3402,7 +3407,7 @@ xfs_symlink(
3402 * Check for ability to enter directory entry, if no space reserved. 3407 * Check for ability to enter directory entry, if no space reserved.
3403 */ 3408 */
3404 if (resblks == 0 && 3409 if (resblks == 0 &&
3405 (error = XFS_DIR_CANENTER(mp, tp, dp, link_name, link_namelen))) 3410 (error = xfs_dir_canenter(tp, dp, link_name, link_namelen)))
3406 goto error_return; 3411 goto error_return;
3407 /* 3412 /*
3408 * Initialize the bmap freelist prior to calling either 3413 * Initialize the bmap freelist prior to calling either
@@ -3457,7 +3462,7 @@ xfs_symlink(
3457 error = xfs_bmapi(tp, ip, first_fsb, fs_blocks, 3462 error = xfs_bmapi(tp, ip, first_fsb, fs_blocks,
3458 XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, 3463 XFS_BMAPI_WRITE | XFS_BMAPI_METADATA,
3459 &first_block, resblks, mval, &nmaps, 3464 &first_block, resblks, mval, &nmaps,
3460 &free_list); 3465 &free_list, NULL);
3461 if (error) { 3466 if (error) {
3462 goto error1; 3467 goto error1;
3463 } 3468 }
@@ -3489,11 +3494,10 @@ xfs_symlink(
3489 /* 3494 /*
3490 * Create the directory entry for the symlink. 3495 * Create the directory entry for the symlink.
3491 */ 3496 */
3492 error = XFS_DIR_CREATENAME(mp, tp, dp, link_name, link_namelen, 3497 error = xfs_dir_createname(tp, dp, link_name, link_namelen, ip->i_ino,
3493 ip->i_ino, &first_block, &free_list, resblks); 3498 &first_block, &free_list, resblks);
3494 if (error) { 3499 if (error)
3495 goto error1; 3500 goto error1;
3496 }
3497 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 3501 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
3498 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 3502 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
3499 3503
@@ -3541,7 +3545,7 @@ std_return:
3541 } 3545 }
3542 3546
3543 if (!error) { 3547 if (!error) {
3544 vnode_t *vp; 3548 bhv_vnode_t *vp;
3545 3549
3546 ASSERT(ip); 3550 ASSERT(ip);
3547 vp = XFS_ITOV(ip); 3551 vp = XFS_ITOV(ip);
@@ -3606,10 +3610,10 @@ xfs_fid2(
3606int 3610int
3607xfs_rwlock( 3611xfs_rwlock(
3608 bhv_desc_t *bdp, 3612 bhv_desc_t *bdp,
3609 vrwlock_t locktype) 3613 bhv_vrwlock_t locktype)
3610{ 3614{
3611 xfs_inode_t *ip; 3615 xfs_inode_t *ip;
3612 vnode_t *vp; 3616 bhv_vnode_t *vp;
3613 3617
3614 vp = BHV_TO_VNODE(bdp); 3618 vp = BHV_TO_VNODE(bdp);
3615 if (VN_ISDIR(vp)) 3619 if (VN_ISDIR(vp))
@@ -3637,10 +3641,10 @@ xfs_rwlock(
3637void 3641void
3638xfs_rwunlock( 3642xfs_rwunlock(
3639 bhv_desc_t *bdp, 3643 bhv_desc_t *bdp,
3640 vrwlock_t locktype) 3644 bhv_vrwlock_t locktype)
3641{ 3645{
3642 xfs_inode_t *ip; 3646 xfs_inode_t *ip;
3643 vnode_t *vp; 3647 bhv_vnode_t *vp;
3644 3648
3645 vp = BHV_TO_VNODE(bdp); 3649 vp = BHV_TO_VNODE(bdp);
3646 if (VN_ISDIR(vp)) 3650 if (VN_ISDIR(vp))
@@ -3744,7 +3748,6 @@ xfs_inode_flush(
3744 return error; 3748 return error;
3745} 3749}
3746 3750
3747
3748int 3751int
3749xfs_set_dmattrs ( 3752xfs_set_dmattrs (
3750 bhv_desc_t *bdp, 3753 bhv_desc_t *bdp,
@@ -3785,16 +3788,12 @@ xfs_set_dmattrs (
3785 return error; 3788 return error;
3786} 3789}
3787 3790
3788
3789/*
3790 * xfs_reclaim
3791 */
3792STATIC int 3791STATIC int
3793xfs_reclaim( 3792xfs_reclaim(
3794 bhv_desc_t *bdp) 3793 bhv_desc_t *bdp)
3795{ 3794{
3796 xfs_inode_t *ip; 3795 xfs_inode_t *ip;
3797 vnode_t *vp; 3796 bhv_vnode_t *vp;
3798 3797
3799 vp = BHV_TO_VNODE(bdp); 3798 vp = BHV_TO_VNODE(bdp);
3800 ip = XFS_BHVTOI(bdp); 3799 ip = XFS_BHVTOI(bdp);
@@ -3849,7 +3848,7 @@ xfs_finish_reclaim(
3849 int sync_mode) 3848 int sync_mode)
3850{ 3849{
3851 xfs_ihash_t *ih = ip->i_hash; 3850 xfs_ihash_t *ih = ip->i_hash;
3852 vnode_t *vp = XFS_ITOV_NULL(ip); 3851 bhv_vnode_t *vp = XFS_ITOV_NULL(ip);
3853 int error; 3852 int error;
3854 3853
3855 if (vp && VN_BAD(vp)) 3854 if (vp && VN_BAD(vp))
@@ -4116,10 +4115,10 @@ retry:
4116 * Issue the xfs_bmapi() call to allocate the blocks 4115 * Issue the xfs_bmapi() call to allocate the blocks
4117 */ 4116 */
4118 XFS_BMAP_INIT(&free_list, &firstfsb); 4117 XFS_BMAP_INIT(&free_list, &firstfsb);
4119 error = xfs_bmapi(tp, ip, startoffset_fsb, 4118 error = XFS_BMAPI(mp, tp, &ip->i_iocore, startoffset_fsb,
4120 allocatesize_fsb, bmapi_flag, 4119 allocatesize_fsb, bmapi_flag,
4121 &firstfsb, 0, imapp, &nimaps, 4120 &firstfsb, 0, imapp, &nimaps,
4122 &free_list); 4121 &free_list, NULL);
4123 if (error) { 4122 if (error) {
4124 goto error0; 4123 goto error0;
4125 } 4124 }
@@ -4199,8 +4198,8 @@ xfs_zero_remaining_bytes(
4199 for (offset = startoff; offset <= endoff; offset = lastoffset + 1) { 4198 for (offset = startoff; offset <= endoff; offset = lastoffset + 1) {
4200 offset_fsb = XFS_B_TO_FSBT(mp, offset); 4199 offset_fsb = XFS_B_TO_FSBT(mp, offset);
4201 nimap = 1; 4200 nimap = 1;
4202 error = xfs_bmapi(NULL, ip, offset_fsb, 1, 0, NULL, 0, &imap, 4201 error = XFS_BMAPI(mp, NULL, &ip->i_iocore, offset_fsb, 1, 0,
4203 &nimap, NULL); 4202 NULL, 0, &imap, &nimap, NULL, NULL);
4204 if (error || nimap < 1) 4203 if (error || nimap < 1)
4205 break; 4204 break;
4206 ASSERT(imap.br_blockcount >= 1); 4205 ASSERT(imap.br_blockcount >= 1);
@@ -4259,7 +4258,7 @@ xfs_free_file_space(
4259 xfs_off_t len, 4258 xfs_off_t len,
4260 int attr_flags) 4259 int attr_flags)
4261{ 4260{
4262 vnode_t *vp; 4261 bhv_vnode_t *vp;
4263 int committed; 4262 int committed;
4264 int done; 4263 int done;
4265 xfs_off_t end_dmi_offset; 4264 xfs_off_t end_dmi_offset;
@@ -4308,7 +4307,6 @@ xfs_free_file_space(
4308 return error; 4307 return error;
4309 } 4308 }
4310 4309
4311 ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1);
4312 if (attr_flags & ATTR_NOLOCK) 4310 if (attr_flags & ATTR_NOLOCK)
4313 need_iolock = 0; 4311 need_iolock = 0;
4314 if (need_iolock) { 4312 if (need_iolock) {
@@ -4326,7 +4324,7 @@ xfs_free_file_space(
4326 if (VN_CACHED(vp) != 0) { 4324 if (VN_CACHED(vp) != 0) {
4327 xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1, 4325 xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1,
4328 ctooff(offtoct(ioffset)), -1); 4326 ctooff(offtoct(ioffset)), -1);
4329 VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(ioffset)), 4327 bhv_vop_flushinval_pages(vp, ctooff(offtoct(ioffset)),
4330 -1, FI_REMAPF_LOCKED); 4328 -1, FI_REMAPF_LOCKED);
4331 } 4329 }
4332 4330
@@ -4338,8 +4336,8 @@ xfs_free_file_space(
4338 */ 4336 */
4339 if (rt && !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) { 4337 if (rt && !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
4340 nimap = 1; 4338 nimap = 1;
4341 error = xfs_bmapi(NULL, ip, startoffset_fsb, 1, 0, NULL, 0, 4339 error = XFS_BMAPI(mp, NULL, &ip->i_iocore, startoffset_fsb,
4342 &imap, &nimap, NULL); 4340 1, 0, NULL, 0, &imap, &nimap, NULL, NULL);
4343 if (error) 4341 if (error)
4344 goto out_unlock_iolock; 4342 goto out_unlock_iolock;
4345 ASSERT(nimap == 0 || nimap == 1); 4343 ASSERT(nimap == 0 || nimap == 1);
@@ -4353,8 +4351,8 @@ xfs_free_file_space(
4353 startoffset_fsb += mp->m_sb.sb_rextsize - mod; 4351 startoffset_fsb += mp->m_sb.sb_rextsize - mod;
4354 } 4352 }
4355 nimap = 1; 4353 nimap = 1;
4356 error = xfs_bmapi(NULL, ip, endoffset_fsb - 1, 1, 0, NULL, 0, 4354 error = XFS_BMAPI(mp, NULL, &ip->i_iocore, endoffset_fsb - 1,
4357 &imap, &nimap, NULL); 4355 1, 0, NULL, 0, &imap, &nimap, NULL, NULL);
4358 if (error) 4356 if (error)
4359 goto out_unlock_iolock; 4357 goto out_unlock_iolock;
4360 ASSERT(nimap == 0 || nimap == 1); 4358 ASSERT(nimap == 0 || nimap == 1);
@@ -4426,9 +4424,9 @@ xfs_free_file_space(
4426 * issue the bunmapi() call to free the blocks 4424 * issue the bunmapi() call to free the blocks
4427 */ 4425 */
4428 XFS_BMAP_INIT(&free_list, &firstfsb); 4426 XFS_BMAP_INIT(&free_list, &firstfsb);
4429 error = xfs_bunmapi(tp, ip, startoffset_fsb, 4427 error = XFS_BUNMAPI(mp, tp, &ip->i_iocore, startoffset_fsb,
4430 endoffset_fsb - startoffset_fsb, 4428 endoffset_fsb - startoffset_fsb,
4431 0, 2, &firstfsb, &free_list, &done); 4429 0, 2, &firstfsb, &free_list, NULL, &done);
4432 if (error) { 4430 if (error) {
4433 goto error0; 4431 goto error0;
4434 } 4432 }
@@ -4488,8 +4486,8 @@ xfs_change_file_space(
4488 xfs_off_t startoffset; 4486 xfs_off_t startoffset;
4489 xfs_off_t llen; 4487 xfs_off_t llen;
4490 xfs_trans_t *tp; 4488 xfs_trans_t *tp;
4491 vattr_t va; 4489 bhv_vattr_t va;
4492 vnode_t *vp; 4490 bhv_vnode_t *vp;
4493 4491
4494 vp = BHV_TO_VNODE(bdp); 4492 vp = BHV_TO_VNODE(bdp);
4495 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); 4493 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -4642,9 +4640,10 @@ xfs_change_file_space(
4642 return error; 4640 return error;
4643} 4641}
4644 4642
4645vnodeops_t xfs_vnodeops = { 4643bhv_vnodeops_t xfs_vnodeops = {
4646 BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS), 4644 BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS),
4647 .vop_open = xfs_open, 4645 .vop_open = xfs_open,
4646 .vop_close = xfs_close,
4648 .vop_read = xfs_read, 4647 .vop_read = xfs_read,
4649#ifdef HAVE_SENDFILE 4648#ifdef HAVE_SENDFILE
4650 .vop_sendfile = xfs_sendfile, 4649 .vop_sendfile = xfs_sendfile,