aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/mux.c2
-rw-r--r--fs/9p/v9fs_vfs.h2
-rw-r--r--fs/9p/vfs_addr.c2
-rw-r--r--fs/9p/vfs_inode.c2
-rw-r--r--fs/Kconfig42
-rw-r--r--fs/Makefile1
-rw-r--r--fs/adfs/inode.c2
-rw-r--r--fs/affs/affs.h6
-rw-r--r--fs/affs/file.c4
-rw-r--r--fs/affs/symlink.c2
-rw-r--r--fs/afs/file.c2
-rw-r--r--fs/afs/internal.h2
-rw-r--r--fs/befs/linuxvfs.c2
-rw-r--r--fs/bfs/bfs.h2
-rw-r--r--fs/bfs/file.c2
-rw-r--r--fs/block_dev.c3
-rw-r--r--fs/buffer.c5
-rw-r--r--fs/char_dev.c1
-rw-r--r--fs/cifs/CHANGES17
-rw-r--r--fs/cifs/Makefile2
-rw-r--r--fs/cifs/README39
-rw-r--r--fs/cifs/asn1.c10
-rw-r--r--fs/cifs/cifs_debug.c134
-rw-r--r--fs/cifs/cifs_debug.h4
-rw-r--r--fs/cifs/cifs_unicode.c1
-rw-r--r--fs/cifs/cifsencrypt.c140
-rw-r--r--fs/cifs/cifsfs.c6
-rw-r--r--fs/cifs/cifsfs.h5
-rw-r--r--fs/cifs/cifsglob.h71
-rw-r--r--fs/cifs/cifspdu.h98
-rw-r--r--fs/cifs/cifsproto.h14
-rw-r--r--fs/cifs/cifssmb.c287
-rw-r--r--fs/cifs/connect.c498
-rw-r--r--fs/cifs/dir.c15
-rw-r--r--fs/cifs/fcntl.c4
-rw-r--r--fs/cifs/file.c54
-rw-r--r--fs/cifs/inode.c39
-rw-r--r--fs/cifs/link.c7
-rw-r--r--fs/cifs/misc.c10
-rw-r--r--fs/cifs/netmisc.c4
-rw-r--r--fs/cifs/ntlmssp.c143
-rw-r--r--fs/cifs/readdir.c184
-rw-r--r--fs/cifs/sess.c538
-rw-r--r--fs/cifs/smbencrypt.c1
-rw-r--r--fs/cifs/transport.c3
-rw-r--r--fs/coda/psdev.c23
-rw-r--r--fs/coda/symlink.c2
-rw-r--r--fs/compat_ioctl.c1
-rw-r--r--fs/configfs/inode.c2
-rw-r--r--fs/cramfs/inode.c4
-rw-r--r--fs/devfs/Makefile8
-rw-r--r--fs/devfs/base.c2836
-rw-r--r--fs/devfs/util.c97
-rw-r--r--fs/efs/inode.c2
-rw-r--r--fs/efs/symlink.c2
-rw-r--r--fs/ext2/ext2.h6
-rw-r--r--fs/ext2/inode.c6
-rw-r--r--fs/ext3/inode.c6
-rw-r--r--fs/fat/inode.c2
-rw-r--r--fs/freevxfs/vxfs_immed.c2
-rw-r--r--fs/freevxfs/vxfs_inode.c6
-rw-r--r--fs/freevxfs/vxfs_subr.c2
-rw-r--r--fs/fuse/file.c2
-rw-r--r--fs/hfs/hfs_fs.h4
-rw-r--r--fs/hfs/inode.c4
-rw-r--r--fs/hfsplus/hfsplus_fs.h4
-rw-r--r--fs/hfsplus/inode.c4
-rw-r--r--fs/hostfs/hostfs_kern.c6
-rw-r--r--fs/hpfs/file.c2
-rw-r--r--fs/hpfs/hpfs_fn.h4
-rw-r--r--fs/hpfs/namei.c2
-rw-r--r--fs/hugetlbfs/inode.c4
-rw-r--r--fs/inode.c2
-rw-r--r--fs/isofs/compress.c2
-rw-r--r--fs/isofs/inode.c2
-rw-r--r--fs/isofs/isofs.h2
-rw-r--r--fs/isofs/rock.c2
-rw-r--r--fs/isofs/zisofs.h2
-rw-r--r--fs/jbd/journal.c3
-rw-r--r--fs/jffs/inode-v23.c4
-rw-r--r--fs/jffs2/acl.c2
-rw-r--r--fs/jffs2/erase.c19
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jffs2/fs.c2
-rw-r--r--fs/jffs2/gc.c6
-rw-r--r--fs/jffs2/jffs2_fs_sb.h3
-rw-r--r--fs/jffs2/malloc.c2
-rw-r--r--fs/jffs2/nodelist.c3
-rw-r--r--fs/jffs2/nodemgmt.c21
-rw-r--r--fs/jffs2/os-linux.h2
-rw-r--r--fs/jffs2/readinode.c1
-rw-r--r--fs/jffs2/scan.c55
-rw-r--r--fs/jffs2/summary.c41
-rw-r--r--fs/jffs2/xattr.c632
-rw-r--r--fs/jffs2/xattr.h21
-rw-r--r--fs/jfs/inode.c2
-rw-r--r--fs/jfs/jfs_inode.h2
-rw-r--r--fs/jfs/jfs_metapage.c2
-rw-r--r--fs/jfs/jfs_metapage.h2
-rw-r--r--fs/minix/inode.c2
-rw-r--r--fs/ncpfs/inode.c2
-rw-r--r--fs/ncpfs/symlink.c2
-rw-r--r--fs/nfs/direct.c2
-rw-r--r--fs/nfs/file.c2
-rw-r--r--fs/nfs/inode.c2
-rw-r--r--fs/nfs/internal.h8
-rw-r--r--fs/nfs/pagelist.c2
-rw-r--r--fs/nfs/read.c2
-rw-r--r--fs/nfs/write.c2
-rw-r--r--fs/nfsd/nfs4state.c2
-rw-r--r--fs/ntfs/aops.c4
-rw-r--r--fs/ntfs/ntfs.h4
-rw-r--r--fs/ocfs2/aops.c2
-rw-r--r--fs/ocfs2/cluster/heartbeat.c2
-rw-r--r--fs/ocfs2/cluster/tcp.c2
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c2
-rw-r--r--fs/ocfs2/dlm/dlmlock.c2
-rw-r--r--fs/ocfs2/dlm/dlmrecovery.c4
-rw-r--r--fs/ocfs2/dlmglue.c2
-rw-r--r--fs/ocfs2/inode.h2
-rw-r--r--fs/ocfs2/journal.c2
-rw-r--r--fs/ocfs2/vote.c8
-rw-r--r--fs/partitions/Makefile1
-rw-r--r--fs/partitions/check.c32
-rw-r--r--fs/partitions/devfs.c130
-rw-r--r--fs/partitions/devfs.h10
-rw-r--r--fs/proc/task_mmu.c30
-rw-r--r--fs/qnx4/inode.c2
-rw-r--r--fs/ramfs/file-mmu.c2
-rw-r--r--fs/ramfs/file-nommu.c2
-rw-r--r--fs/ramfs/internal.h2
-rw-r--r--fs/reiserfs/inode.c2
-rw-r--r--fs/romfs/inode.c2
-rw-r--r--fs/smbfs/file.c2
-rw-r--r--fs/smbfs/proto.h2
-rw-r--r--fs/sysfs/inode.c2
-rw-r--r--fs/sysv/itree.c2
-rw-r--r--fs/sysv/sysv.h2
-rw-r--r--fs/udf/file.c2
-rw-r--r--fs/udf/inode.c2
-rw-r--r--fs/udf/symlink.c2
-rw-r--r--fs/udf/udfdecl.h6
-rw-r--r--fs/ufs/inode.c119
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c9
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h2
-rw-r--r--fs/xfs/xfs_behavior.h3
-rw-r--r--fs/xfs/xfs_inode.c4
-rw-r--r--fs/xfs/xfs_log.c4
-rw-r--r--fs/xfs/xfs_log_recover.c2
-rw-r--r--fs/xfs/xfs_mount.c21
-rw-r--r--fs/xfs/xfs_rtalloc.c2
-rw-r--r--fs/xfs/xfs_trans.h4
-rw-r--r--fs/xfs/xfs_vnodeops.c11
157 files changed, 2254 insertions, 4530 deletions
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
index 12e1baa4508d..8d45ed668837 100644
--- a/fs/9p/mux.c
+++ b/fs/9p/mux.c
@@ -932,6 +932,8 @@ v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
932 r.rcall || r.err); 932 r.rcall || r.err);
933 } while (!r.rcall && !r.err && err==-ERESTARTSYS && 933 } while (!r.rcall && !r.err && err==-ERESTARTSYS &&
934 m->trans->status==Connected && !m->err); 934 m->trans->status==Connected && !m->err);
935
936 err = -ERESTARTSYS;
935 } 937 }
936 sigpending = 1; 938 sigpending = 1;
937 } 939 }
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index f867b8d3e973..450b0c1b385e 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -38,7 +38,7 @@
38 */ 38 */
39 39
40extern struct file_system_type v9fs_fs_type; 40extern struct file_system_type v9fs_fs_type;
41extern struct address_space_operations v9fs_addr_operations; 41extern const struct address_space_operations v9fs_addr_operations;
42extern const struct file_operations v9fs_file_operations; 42extern const struct file_operations v9fs_file_operations;
43extern const struct file_operations v9fs_dir_operations; 43extern const struct file_operations v9fs_dir_operations;
44extern struct dentry_operations v9fs_dentry_operations; 44extern struct dentry_operations v9fs_dentry_operations;
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index efda46fb64d9..d4f0aa3c87f2 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -103,6 +103,6 @@ UnmapAndUnlock:
103 return retval; 103 return retval;
104} 104}
105 105
106struct address_space_operations v9fs_addr_operations = { 106const struct address_space_operations v9fs_addr_operations = {
107 .readpage = v9fs_vfs_readpage, 107 .readpage = v9fs_vfs_readpage,
108}; 108};
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 5c6bdf82146c..2f580a197b8d 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -300,7 +300,7 @@ clunk_fid:
300 fid = V9FS_NOFID; 300 fid = V9FS_NOFID;
301 301
302put_fid: 302put_fid:
303 if (fid >= 0) 303 if (fid != V9FS_NOFID)
304 v9fs_put_idpool(fid, &v9ses->fidpool); 304 v9fs_put_idpool(fid, &v9ses->fidpool);
305 305
306 kfree(fcall); 306 kfree(fcall);
diff --git a/fs/Kconfig b/fs/Kconfig
index 6c5051802bd2..6dc8cfd6d80c 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1116,7 +1116,7 @@ config JFFS2_SUMMARY
1116 1116
1117config JFFS2_FS_XATTR 1117config JFFS2_FS_XATTR
1118 bool "JFFS2 XATTR support (EXPERIMENTAL)" 1118 bool "JFFS2 XATTR support (EXPERIMENTAL)"
1119 depends on JFFS2_FS && EXPERIMENTAL && !JFFS2_FS_WRITEBUFFER 1119 depends on JFFS2_FS && EXPERIMENTAL
1120 default n 1120 default n
1121 help 1121 help
1122 Extended attributes are name:value pairs associated with inodes by 1122 Extended attributes are name:value pairs associated with inodes by
@@ -1722,7 +1722,7 @@ config CIFS_STATS
1722 mounted by the cifs client to be displayed in /proc/fs/cifs/Stats 1722 mounted by the cifs client to be displayed in /proc/fs/cifs/Stats
1723 1723
1724config CIFS_STATS2 1724config CIFS_STATS2
1725 bool "CIFS extended statistics" 1725 bool "Extended statistics"
1726 depends on CIFS_STATS 1726 depends on CIFS_STATS
1727 help 1727 help
1728 Enabling this option will allow more detailed statistics on SMB 1728 Enabling this option will allow more detailed statistics on SMB
@@ -1735,6 +1735,32 @@ config CIFS_STATS2
1735 Unless you are a developer or are doing network performance analysis 1735 Unless you are a developer or are doing network performance analysis
1736 or tuning, say N. 1736 or tuning, say N.
1737 1737
1738config CIFS_WEAK_PW_HASH
1739 bool "Support legacy servers which use weaker LANMAN security"
1740 depends on CIFS
1741 help
1742 Modern CIFS servers including Samba and most Windows versions
1743 (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos)
1744 security mechanisms. These hash the password more securely
1745 than the mechanisms used in the older LANMAN version of the
1746 SMB protocol needed to establish sessions with old SMB servers.
1747
1748 Enabling this option allows the cifs module to mount to older
1749 LANMAN based servers such as OS/2 and Windows 95, but such
1750 mounts may be less secure than mounts using NTLM or more recent
1751 security mechanisms if you are on a public network. Unless you
1752 have a need to access old SMB servers (and are on a private
1753 network) you probably want to say N. Even if this support
1754 is enabled in the kernel build, they will not be used
1755 automatically. At runtime LANMAN mounts are disabled but
1756 can be set to required (or optional) either in
1757 /proc/fs/cifs (see fs/cifs/README for more detail) or via an
1758 option on the mount command. This support is disabled by
1759 default in order to reduce the possibility of a downgrade
1760 attack.
1761
1762 If unsure, say N.
1763
1738config CIFS_XATTR 1764config CIFS_XATTR
1739 bool "CIFS extended attributes" 1765 bool "CIFS extended attributes"
1740 depends on CIFS 1766 depends on CIFS
@@ -1763,6 +1789,16 @@ config CIFS_POSIX
1763 (such as Samba 3.10 and later) which can negotiate 1789 (such as Samba 3.10 and later) which can negotiate
1764 CIFS POSIX ACL support. If unsure, say N. 1790 CIFS POSIX ACL support. If unsure, say N.
1765 1791
1792config CIFS_DEBUG2
1793 bool "Enable additional CIFS debugging routines"
1794 help
1795 Enabling this option adds a few more debugging routines
1796 to the cifs code which slightly increases the size of
1797 the cifs module and can cause additional logging of debug
1798 messages in some error paths, slowing performance. This
1799 option can be turned off unless you are debugging
1800 cifs problems. If unsure, say N.
1801
1766config CIFS_EXPERIMENTAL 1802config CIFS_EXPERIMENTAL
1767 bool "CIFS Experimental Features (EXPERIMENTAL)" 1803 bool "CIFS Experimental Features (EXPERIMENTAL)"
1768 depends on CIFS && EXPERIMENTAL 1804 depends on CIFS && EXPERIMENTAL
@@ -1778,7 +1814,7 @@ config CIFS_EXPERIMENTAL
1778 If unsure, say N. 1814 If unsure, say N.
1779 1815
1780config CIFS_UPCALL 1816config CIFS_UPCALL
1781 bool "CIFS Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" 1817 bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
1782 depends on CIFS_EXPERIMENTAL 1818 depends on CIFS_EXPERIMENTAL
1783 select CONNECTOR 1819 select CONNECTOR
1784 help 1820 help
diff --git a/fs/Makefile b/fs/Makefile
index d0ea6bfccf29..89135428a539 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -66,7 +66,6 @@ obj-$(CONFIG_MSDOS_FS) += msdos/
66obj-$(CONFIG_VFAT_FS) += vfat/ 66obj-$(CONFIG_VFAT_FS) += vfat/
67obj-$(CONFIG_BFS_FS) += bfs/ 67obj-$(CONFIG_BFS_FS) += bfs/
68obj-$(CONFIG_ISO9660_FS) += isofs/ 68obj-$(CONFIG_ISO9660_FS) += isofs/
69obj-$(CONFIG_DEVFS_FS) += devfs/
70obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+ 69obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+
71obj-$(CONFIG_HFS_FS) += hfs/ 70obj-$(CONFIG_HFS_FS) += hfs/
72obj-$(CONFIG_VXFS_FS) += freevxfs/ 71obj-$(CONFIG_VXFS_FS) += freevxfs/
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index a02802a30798..534f3eecc985 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -72,7 +72,7 @@ static sector_t _adfs_bmap(struct address_space *mapping, sector_t block)
72 return generic_block_bmap(mapping, block, adfs_get_block); 72 return generic_block_bmap(mapping, block, adfs_get_block);
73} 73}
74 74
75static struct address_space_operations adfs_aops = { 75static const struct address_space_operations adfs_aops = {
76 .readpage = adfs_readpage, 76 .readpage = adfs_readpage,
77 .writepage = adfs_writepage, 77 .writepage = adfs_writepage,
78 .sync_page = block_sync_page, 78 .sync_page = block_sync_page,
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index a43a876742b8..0ddd4cc0d1a0 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -195,9 +195,9 @@ extern struct inode_operations affs_symlink_inode_operations;
195extern const struct file_operations affs_file_operations; 195extern const struct file_operations affs_file_operations;
196extern const struct file_operations affs_file_operations_ofs; 196extern const struct file_operations affs_file_operations_ofs;
197extern const struct file_operations affs_dir_operations; 197extern const struct file_operations affs_dir_operations;
198extern struct address_space_operations affs_symlink_aops; 198extern const struct address_space_operations affs_symlink_aops;
199extern struct address_space_operations affs_aops; 199extern const struct address_space_operations affs_aops;
200extern struct address_space_operations affs_aops_ofs; 200extern const struct address_space_operations affs_aops_ofs;
201 201
202extern struct dentry_operations affs_dentry_operations; 202extern struct dentry_operations affs_dentry_operations;
203extern struct dentry_operations affs_dentry_operations_intl; 203extern struct dentry_operations affs_dentry_operations_intl;
diff --git a/fs/affs/file.c b/fs/affs/file.c
index 7076262af39b..3de8590e4f6a 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -406,7 +406,7 @@ static sector_t _affs_bmap(struct address_space *mapping, sector_t block)
406{ 406{
407 return generic_block_bmap(mapping,block,affs_get_block); 407 return generic_block_bmap(mapping,block,affs_get_block);
408} 408}
409struct address_space_operations affs_aops = { 409const struct address_space_operations affs_aops = {
410 .readpage = affs_readpage, 410 .readpage = affs_readpage,
411 .writepage = affs_writepage, 411 .writepage = affs_writepage,
412 .sync_page = block_sync_page, 412 .sync_page = block_sync_page,
@@ -759,7 +759,7 @@ out:
759 goto done; 759 goto done;
760} 760}
761 761
762struct address_space_operations affs_aops_ofs = { 762const struct address_space_operations affs_aops_ofs = {
763 .readpage = affs_readpage_ofs, 763 .readpage = affs_readpage_ofs,
764 //.writepage = affs_writepage_ofs, 764 //.writepage = affs_writepage_ofs,
765 //.sync_page = affs_sync_page_ofs, 765 //.sync_page = affs_sync_page_ofs,
diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c
index 426f0f094f23..f802256a5933 100644
--- a/fs/affs/symlink.c
+++ b/fs/affs/symlink.c
@@ -66,7 +66,7 @@ fail:
66 return err; 66 return err;
67} 67}
68 68
69struct address_space_operations affs_symlink_aops = { 69const struct address_space_operations affs_symlink_aops = {
70 .readpage = affs_symlink_readpage, 70 .readpage = affs_symlink_readpage,
71}; 71};
72 72
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 7bb716887e29..67d6634101fd 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -35,7 +35,7 @@ struct inode_operations afs_file_inode_operations = {
35 .getattr = afs_inode_getattr, 35 .getattr = afs_inode_getattr,
36}; 36};
37 37
38struct address_space_operations afs_fs_aops = { 38const struct address_space_operations afs_fs_aops = {
39 .readpage = afs_file_readpage, 39 .readpage = afs_file_readpage,
40 .sync_page = block_sync_page, 40 .sync_page = block_sync_page,
41 .set_page_dirty = __set_page_dirty_nobuffers, 41 .set_page_dirty = __set_page_dirty_nobuffers,
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 72febdf9a35a..e88b3b65ae49 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -69,7 +69,7 @@ extern const struct file_operations afs_dir_file_operations;
69/* 69/*
70 * file.c 70 * file.c
71 */ 71 */
72extern struct address_space_operations afs_fs_aops; 72extern const struct address_space_operations afs_fs_aops;
73extern struct inode_operations afs_file_inode_operations; 73extern struct inode_operations afs_file_inode_operations;
74 74
75#ifdef AFS_CACHING_SUPPORT 75#ifdef AFS_CACHING_SUPPORT
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 08201fab26cd..a83e889a97cd 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -73,7 +73,7 @@ static struct inode_operations befs_dir_inode_operations = {
73 .lookup = befs_lookup, 73 .lookup = befs_lookup,
74}; 74};
75 75
76static struct address_space_operations befs_aops = { 76static const struct address_space_operations befs_aops = {
77 .readpage = befs_readpage, 77 .readpage = befs_readpage,
78 .sync_page = block_sync_page, 78 .sync_page = block_sync_page,
79 .bmap = befs_bmap, 79 .bmap = befs_bmap,
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h
index 9d791004b21c..31973bbbf057 100644
--- a/fs/bfs/bfs.h
+++ b/fs/bfs/bfs.h
@@ -50,7 +50,7 @@ static inline struct bfs_inode_info *BFS_I(struct inode *inode)
50/* file.c */ 50/* file.c */
51extern struct inode_operations bfs_file_inops; 51extern struct inode_operations bfs_file_inops;
52extern const struct file_operations bfs_file_operations; 52extern const struct file_operations bfs_file_operations;
53extern struct address_space_operations bfs_aops; 53extern const struct address_space_operations bfs_aops;
54 54
55/* dir.c */ 55/* dir.c */
56extern struct inode_operations bfs_dir_inops; 56extern struct inode_operations bfs_dir_inops;
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index d83cd74a2e4e..3d5aca28a0a0 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -153,7 +153,7 @@ static sector_t bfs_bmap(struct address_space *mapping, sector_t block)
153 return generic_block_bmap(mapping, block, bfs_get_block); 153 return generic_block_bmap(mapping, block, bfs_get_block);
154} 154}
155 155
156struct address_space_operations bfs_aops = { 156const struct address_space_operations bfs_aops = {
157 .readpage = bfs_readpage, 157 .readpage = bfs_readpage,
158 .writepage = bfs_writepage, 158 .writepage = bfs_writepage,
159 .sync_page = block_sync_page, 159 .sync_page = block_sync_page,
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 028d9fb9c2d5..909cb0595b4e 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -12,7 +12,6 @@
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/kmod.h> 13#include <linux/kmod.h>
14#include <linux/major.h> 14#include <linux/major.h>
15#include <linux/devfs_fs_kernel.h>
16#include <linux/smp_lock.h> 15#include <linux/smp_lock.h>
17#include <linux/highmem.h> 16#include <linux/highmem.h>
18#include <linux/blkdev.h> 17#include <linux/blkdev.h>
@@ -1095,7 +1094,7 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
1095 return blkdev_ioctl(file->f_mapping->host, file, cmd, arg); 1094 return blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
1096} 1095}
1097 1096
1098struct address_space_operations def_blk_aops = { 1097const struct address_space_operations def_blk_aops = {
1099 .readpage = blkdev_readpage, 1098 .readpage = blkdev_readpage,
1100 .writepage = blkdev_writepage, 1099 .writepage = blkdev_writepage,
1101 .sync_page = block_sync_page, 1100 .sync_page = block_sync_page,
diff --git a/fs/buffer.c b/fs/buffer.c
index 373bb6292bdc..e9994722f4a3 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -564,7 +564,7 @@ still_busy:
564 * Completion handler for block_write_full_page() - pages which are unlocked 564 * Completion handler for block_write_full_page() - pages which are unlocked
565 * during I/O, and which have PageWriteback cleared upon I/O completion. 565 * during I/O, and which have PageWriteback cleared upon I/O completion.
566 */ 566 */
567void end_buffer_async_write(struct buffer_head *bh, int uptodate) 567static void end_buffer_async_write(struct buffer_head *bh, int uptodate)
568{ 568{
569 char b[BDEVNAME_SIZE]; 569 char b[BDEVNAME_SIZE];
570 unsigned long flags; 570 unsigned long flags;
@@ -2598,7 +2598,7 @@ int nobh_truncate_page(struct address_space *mapping, loff_t from)
2598 unsigned offset = from & (PAGE_CACHE_SIZE-1); 2598 unsigned offset = from & (PAGE_CACHE_SIZE-1);
2599 unsigned to; 2599 unsigned to;
2600 struct page *page; 2600 struct page *page;
2601 struct address_space_operations *a_ops = mapping->a_ops; 2601 const struct address_space_operations *a_ops = mapping->a_ops;
2602 char *kaddr; 2602 char *kaddr;
2603 int ret = 0; 2603 int ret = 0;
2604 2604
@@ -3166,7 +3166,6 @@ EXPORT_SYMBOL(block_sync_page);
3166EXPORT_SYMBOL(block_truncate_page); 3166EXPORT_SYMBOL(block_truncate_page);
3167EXPORT_SYMBOL(block_write_full_page); 3167EXPORT_SYMBOL(block_write_full_page);
3168EXPORT_SYMBOL(cont_prepare_write); 3168EXPORT_SYMBOL(cont_prepare_write);
3169EXPORT_SYMBOL(end_buffer_async_write);
3170EXPORT_SYMBOL(end_buffer_read_sync); 3169EXPORT_SYMBOL(end_buffer_read_sync);
3171EXPORT_SYMBOL(end_buffer_write_sync); 3170EXPORT_SYMBOL(end_buffer_write_sync);
3172EXPORT_SYMBOL(file_fsync); 3171EXPORT_SYMBOL(file_fsync);
diff --git a/fs/char_dev.c b/fs/char_dev.c
index f3418f7a6e9d..97986635b641 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -14,7 +14,6 @@
14#include <linux/errno.h> 14#include <linux/errno.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/smp_lock.h> 16#include <linux/smp_lock.h>
17#include <linux/devfs_fs_kernel.h>
18#include <linux/seq_file.h> 17#include <linux/seq_file.h>
19 18
20#include <linux/kobject.h> 19#include <linux/kobject.h>
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 7271bb0257f6..a61d17ed1827 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,9 +1,24 @@
1Version 1.44
2------------
3Rewritten sessionsetup support, including support for legacy SMB
4session setup needed for OS/2 and older servers such as Windows 95 and 98.
5Fix oops on ls to OS/2 servers. Add support for level 1 FindFirst
6so we can do search (ls etc.) to OS/2. Do not send NTCreateX
7or recent levels of FindFirst unless server says it supports NT SMBs
8(instead use legacy equivalents from LANMAN dialect). Fix to allow
9NTLMv2 authentication support (now can use stronger password hashing
10on mount if corresponding /proc/fs/cifs/SecurityFlags is set (0x4004).
11Allow override of global cifs security flags on mount via "sec=" option(s).
12
1Version 1.43 13Version 1.43
2------------ 14------------
3POSIX locking to servers which support CIFS POSIX Extensions 15POSIX locking to servers which support CIFS POSIX Extensions
4(disabled by default controlled by proc/fs/cifs/Experimental). 16(disabled by default controlled by proc/fs/cifs/Experimental).
5Handle conversion of long share names (especially Asian languages) 17Handle conversion of long share names (especially Asian languages)
6to Unicode during mount. 18to Unicode during mount. Fix memory leak in sess struct on reconnect.
19Fix rare oops after acpi suspend. Fix O_TRUNC opens to overwrite on
20cifs open which helps rare case when setpathinfo fails or server does
21not support it.
7 22
8Version 1.42 23Version 1.42
9------------ 24------------
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 58c77254a23b..a26f26ed5a17 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -3,4 +3,4 @@
3# 3#
4obj-$(CONFIG_CIFS) += cifs.o 4obj-$(CONFIG_CIFS) += cifs.o
5 5
6cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o ntlmssp.o 6cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o
diff --git a/fs/cifs/README b/fs/cifs/README
index 0355003f4f0a..7986d0d97ace 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -443,7 +443,10 @@ A partial list of the supported mount options follows:
443 SFU does). In the future the bottom 9 bits of the mode 443 SFU does). In the future the bottom 9 bits of the mode
444 mode also will be emulated using queries of the security 444 mode also will be emulated using queries of the security
445 descriptor (ACL). 445 descriptor (ACL).
446sec Security mode. Allowed values are: 446 sign Must use packet signing (helps avoid unwanted data modification
447 by intermediate systems in the route). Note that signing
448 does not work with lanman or plaintext authentication.
449 sec Security mode. Allowed values are:
447 none attempt to connection as a null user (no name) 450 none attempt to connection as a null user (no name)
448 krb5 Use Kerberos version 5 authentication 451 krb5 Use Kerberos version 5 authentication
449 krb5i Use Kerberos authentication and packet signing 452 krb5i Use Kerberos authentication and packet signing
@@ -453,6 +456,8 @@ sec Security mode. Allowed values are:
453 server requires signing also can be the default) 456 server requires signing also can be the default)
454 ntlmv2 Use NTLMv2 password hashing 457 ntlmv2 Use NTLMv2 password hashing
455 ntlmv2i Use NTLMv2 password hashing with packet signing 458 ntlmv2i Use NTLMv2 password hashing with packet signing
459 lanman (if configured in kernel config) use older
460 lanman hash
456 461
457The mount.cifs mount helper also accepts a few mount options before -o 462The mount.cifs mount helper also accepts a few mount options before -o
458including: 463including:
@@ -485,14 +490,34 @@ PacketSigningEnabled If set to one, cifs packet signing is enabled
485 it. If set to two, cifs packet signing is 490 it. If set to two, cifs packet signing is
486 required even if the server considers packet 491 required even if the server considers packet
487 signing optional. (default 1) 492 signing optional. (default 1)
493SecurityFlags Flags which control security negotiation and
494 also packet signing. Authentication (may/must)
495 flags (e.g. for NTLM and/or NTLMv2) may be combined with
496 the signing flags. Specifying two different password
497 hashing mechanisms (as "must use") on the other hand
498 does not make much sense. Default flags are
499 0x07007
500 (NTLM, NTLMv2 and packet signing allowed). Maximum
501 allowable flags if you want to allow mounts to servers
502 using weaker password hashes is 0x37037 (lanman,
503 plaintext, ntlm, ntlmv2, signing allowed):
504
505 may use packet signing 0x00001
506 must use packet signing 0x01001
507 may use NTLM (most common password hash) 0x00002
508 must use NTLM 0x02002
509 may use NTLMv2 0x00004
510 must use NTLMv2 0x04004
511 may use Kerberos security (not implemented yet) 0x00008
512 must use Kerberos (not implemented yet) 0x08008
513 may use lanman (weak) password hash 0x00010
514 must use lanman password hash 0x10010
515 may use plaintext passwords 0x00020
516 must use plaintext passwords 0x20020
517 (reserved for future packet encryption) 0x00040
518
488cifsFYI If set to one, additional debug information is 519cifsFYI If set to one, additional debug information is
489 logged to the system error log. (default 0) 520 logged to the system error log. (default 0)
490ExtendedSecurity If set to one, SPNEGO session establishment
491 is allowed which enables more advanced
492 secure CIFS session establishment (default 0)
493NTLMV2Enabled If set to one, more secure password hashes
494 are used when the server supports them and
495 when kerberos is not negotiated (default 0)
496traceSMB If set to one, debug information is logged to the 521traceSMB If set to one, debug information is logged to the
497 system error log with the start of smb requests 522 system error log with the start of smb requests
498 and responses (default 0) 523 and responses (default 0)
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index 086ae8f4a207..031cdf293256 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -467,7 +467,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
467 asn1_open(&ctx, security_blob, length); 467 asn1_open(&ctx, security_blob, length);
468 468
469 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 469 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
470 cFYI(1, ("Error decoding negTokenInit header ")); 470 cFYI(1, ("Error decoding negTokenInit header"));
471 return 0; 471 return 0;
472 } else if ((cls != ASN1_APL) || (con != ASN1_CON) 472 } else if ((cls != ASN1_APL) || (con != ASN1_CON)
473 || (tag != ASN1_EOC)) { 473 || (tag != ASN1_EOC)) {
@@ -495,7 +495,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
495 } 495 }
496 496
497 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 497 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
498 cFYI(1, ("Error decoding negTokenInit ")); 498 cFYI(1, ("Error decoding negTokenInit"));
499 return 0; 499 return 0;
500 } else if ((cls != ASN1_CTX) || (con != ASN1_CON) 500 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
501 || (tag != ASN1_EOC)) { 501 || (tag != ASN1_EOC)) {
@@ -505,7 +505,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
505 } 505 }
506 506
507 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 507 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
508 cFYI(1, ("Error decoding negTokenInit ")); 508 cFYI(1, ("Error decoding negTokenInit"));
509 return 0; 509 return 0;
510 } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 510 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
511 || (tag != ASN1_SEQ)) { 511 || (tag != ASN1_SEQ)) {
@@ -515,7 +515,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
515 } 515 }
516 516
517 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 517 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
518 cFYI(1, ("Error decoding 2nd part of negTokenInit ")); 518 cFYI(1, ("Error decoding 2nd part of negTokenInit"));
519 return 0; 519 return 0;
520 } else if ((cls != ASN1_CTX) || (con != ASN1_CON) 520 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
521 || (tag != ASN1_EOC)) { 521 || (tag != ASN1_EOC)) {
@@ -527,7 +527,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
527 527
528 if (asn1_header_decode 528 if (asn1_header_decode
529 (&ctx, &sequence_end, &cls, &con, &tag) == 0) { 529 (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
530 cFYI(1, ("Error decoding 2nd part of negTokenInit ")); 530 cFYI(1, ("Error decoding 2nd part of negTokenInit"));
531 return 0; 531 return 0;
532 } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 532 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
533 || (tag != ASN1_SEQ)) { 533 || (tag != ASN1_SEQ)) {
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index f4124a32bef8..96abeb738978 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -39,7 +39,7 @@ cifs_dump_mem(char *label, void *data, int length)
39 char *charptr = data; 39 char *charptr = data;
40 char buf[10], line[80]; 40 char buf[10], line[80];
41 41
42 printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n", 42 printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
43 label, length, data); 43 label, length, data);
44 for (i = 0; i < length; i += 16) { 44 for (i = 0; i < length; i += 16) {
45 line[0] = 0; 45 line[0] = 0;
@@ -57,6 +57,57 @@ cifs_dump_mem(char *label, void *data, int length)
57 } 57 }
58} 58}
59 59
60#ifdef CONFIG_CIFS_DEBUG2
61void cifs_dump_detail(struct smb_hdr * smb)
62{
63 cERROR(1,("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
64 smb->Command, smb->Status.CifsError,
65 smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
66 cERROR(1,("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
67}
68
69
70void cifs_dump_mids(struct TCP_Server_Info * server)
71{
72 struct list_head *tmp;
73 struct mid_q_entry * mid_entry;
74
75 if(server == NULL)
76 return;
77
78 cERROR(1,("Dump pending requests:"));
79 spin_lock(&GlobalMid_Lock);
80 list_for_each(tmp, &server->pending_mid_q) {
81 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
82 if(mid_entry) {
83 cERROR(1,("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
84 mid_entry->midState,
85 (int)mid_entry->command,
86 mid_entry->pid,
87 mid_entry->tsk,
88 mid_entry->mid));
89#ifdef CONFIG_CIFS_STATS2
90 cERROR(1,("IsLarge: %d buf: %p time rcv: %ld now: %ld",
91 mid_entry->largeBuf,
92 mid_entry->resp_buf,
93 mid_entry->when_received,
94 jiffies));
95#endif /* STATS2 */
96 cERROR(1,("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
97 mid_entry->multiEnd));
98 if(mid_entry->resp_buf) {
99 cifs_dump_detail(mid_entry->resp_buf);
100 cifs_dump_mem("existing buf: ",
101 mid_entry->resp_buf,
102 62 /* fixme */);
103 }
104
105 }
106 }
107 spin_unlock(&GlobalMid_Lock);
108}
109#endif /* CONFIG_CIFS_DEBUG2 */
110
60#ifdef CONFIG_PROC_FS 111#ifdef CONFIG_PROC_FS
61static int 112static int
62cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, 113cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
@@ -73,7 +124,6 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
73 124
74 *beginBuffer = buf + offset; 125 *beginBuffer = buf + offset;
75 126
76
77 length = 127 length =
78 sprintf(buf, 128 sprintf(buf,
79 "Display Internal CIFS Data Structures for Debugging\n" 129 "Display Internal CIFS Data Structures for Debugging\n"
@@ -395,12 +445,12 @@ static read_proc_t traceSMB_read;
395static write_proc_t traceSMB_write; 445static write_proc_t traceSMB_write;
396static read_proc_t multiuser_mount_read; 446static read_proc_t multiuser_mount_read;
397static write_proc_t multiuser_mount_write; 447static write_proc_t multiuser_mount_write;
398static read_proc_t extended_security_read; 448static read_proc_t security_flags_read;
399static write_proc_t extended_security_write; 449static write_proc_t security_flags_write;
400static read_proc_t ntlmv2_enabled_read; 450/* static read_proc_t ntlmv2_enabled_read;
401static write_proc_t ntlmv2_enabled_write; 451static write_proc_t ntlmv2_enabled_write;
402static read_proc_t packet_signing_enabled_read; 452static read_proc_t packet_signing_enabled_read;
403static write_proc_t packet_signing_enabled_write; 453static write_proc_t packet_signing_enabled_write;*/
404static read_proc_t experimEnabled_read; 454static read_proc_t experimEnabled_read;
405static write_proc_t experimEnabled_write; 455static write_proc_t experimEnabled_write;
406static read_proc_t linuxExtensionsEnabled_read; 456static read_proc_t linuxExtensionsEnabled_read;
@@ -458,10 +508,10 @@ cifs_proc_init(void)
458 pde->write_proc = multiuser_mount_write; 508 pde->write_proc = multiuser_mount_write;
459 509
460 pde = 510 pde =
461 create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs, 511 create_proc_read_entry("SecurityFlags", 0, proc_fs_cifs,
462 extended_security_read, NULL); 512 security_flags_read, NULL);
463 if (pde) 513 if (pde)
464 pde->write_proc = extended_security_write; 514 pde->write_proc = security_flags_write;
465 515
466 pde = 516 pde =
467 create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs, 517 create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
@@ -469,7 +519,7 @@ cifs_proc_init(void)
469 if (pde) 519 if (pde)
470 pde->write_proc = lookupFlag_write; 520 pde->write_proc = lookupFlag_write;
471 521
472 pde = 522/* pde =
473 create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs, 523 create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
474 ntlmv2_enabled_read, NULL); 524 ntlmv2_enabled_read, NULL);
475 if (pde) 525 if (pde)
@@ -479,7 +529,7 @@ cifs_proc_init(void)
479 create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs, 529 create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
480 packet_signing_enabled_read, NULL); 530 packet_signing_enabled_read, NULL);
481 if (pde) 531 if (pde)
482 pde->write_proc = packet_signing_enabled_write; 532 pde->write_proc = packet_signing_enabled_write;*/
483} 533}
484 534
485void 535void
@@ -496,9 +546,9 @@ cifs_proc_clean(void)
496#endif 546#endif
497 remove_proc_entry("MultiuserMount", proc_fs_cifs); 547 remove_proc_entry("MultiuserMount", proc_fs_cifs);
498 remove_proc_entry("OplockEnabled", proc_fs_cifs); 548 remove_proc_entry("OplockEnabled", proc_fs_cifs);
499 remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); 549/* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
500 remove_proc_entry("ExtendedSecurity",proc_fs_cifs); 550 remove_proc_entry("SecurityFlags",proc_fs_cifs);
501 remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); 551/* remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */
502 remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs); 552 remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
503 remove_proc_entry("Experimental",proc_fs_cifs); 553 remove_proc_entry("Experimental",proc_fs_cifs);
504 remove_proc_entry("LookupCacheEnabled",proc_fs_cifs); 554 remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
@@ -782,12 +832,12 @@ multiuser_mount_write(struct file *file, const char __user *buffer,
782} 832}
783 833
784static int 834static int
785extended_security_read(char *page, char **start, off_t off, 835security_flags_read(char *page, char **start, off_t off,
786 int count, int *eof, void *data) 836 int count, int *eof, void *data)
787{ 837{
788 int len; 838 int len;
789 839
790 len = sprintf(page, "%d\n", extended_security); 840 len = sprintf(page, "0x%x\n", extended_security);
791 841
792 len -= off; 842 len -= off;
793 *start = page + off; 843 *start = page + off;
@@ -803,24 +853,52 @@ extended_security_read(char *page, char **start, off_t off,
803 return len; 853 return len;
804} 854}
805static int 855static int
806extended_security_write(struct file *file, const char __user *buffer, 856security_flags_write(struct file *file, const char __user *buffer,
807 unsigned long count, void *data) 857 unsigned long count, void *data)
808{ 858{
859 unsigned int flags;
860 char flags_string[12];
809 char c; 861 char c;
810 int rc;
811 862
812 rc = get_user(c, buffer); 863 if((count < 1) || (count > 11))
813 if (rc) 864 return -EINVAL;
814 return rc; 865
815 if (c == '0' || c == 'n' || c == 'N') 866 memset(flags_string, 0, 12);
816 extended_security = 0; 867
817 else if (c == '1' || c == 'y' || c == 'Y') 868 if(copy_from_user(flags_string, buffer, count))
818 extended_security = 1; 869 return -EFAULT;
870
871 if(count < 3) {
872 /* single char or single char followed by null */
873 c = flags_string[0];
874 if (c == '0' || c == 'n' || c == 'N')
875 extended_security = CIFSSEC_DEF; /* default */
876 else if (c == '1' || c == 'y' || c == 'Y')
877 extended_security = CIFSSEC_MAX;
878 return count;
879 }
880 /* else we have a number */
881
882 flags = simple_strtoul(flags_string, NULL, 0);
883
884 cFYI(1,("sec flags 0x%x", flags));
885
886 if(flags <= 0) {
887 cERROR(1,("invalid security flags %s",flags_string));
888 return -EINVAL;
889 }
819 890
891 if(flags & ~CIFSSEC_MASK) {
892 cERROR(1,("attempt to set unsupported security flags 0x%x",
893 flags & ~CIFSSEC_MASK));
894 return -EINVAL;
895 }
896 /* flags look ok - update the global security flags for cifs module */
897 extended_security = flags;
820 return count; 898 return count;
821} 899}
822 900
823static int 901/* static int
824ntlmv2_enabled_read(char *page, char **start, off_t off, 902ntlmv2_enabled_read(char *page, char **start, off_t off,
825 int count, int *eof, void *data) 903 int count, int *eof, void *data)
826{ 904{
@@ -855,6 +933,8 @@ ntlmv2_enabled_write(struct file *file, const char __user *buffer,
855 ntlmv2_support = 0; 933 ntlmv2_support = 0;
856 else if (c == '1' || c == 'y' || c == 'Y') 934 else if (c == '1' || c == 'y' || c == 'Y')
857 ntlmv2_support = 1; 935 ntlmv2_support = 1;
936 else if (c == '2')
937 ntlmv2_support = 2;
858 938
859 return count; 939 return count;
860} 940}
@@ -898,7 +978,7 @@ packet_signing_enabled_write(struct file *file, const char __user *buffer,
898 sign_CIFS_PDUs = 2; 978 sign_CIFS_PDUs = 2;
899 979
900 return count; 980 return count;
901} 981} */
902 982
903 983
904#endif 984#endif
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
index 4304d9dcfb6c..c26cd0d2c6d5 100644
--- a/fs/cifs/cifs_debug.h
+++ b/fs/cifs/cifs_debug.h
@@ -24,6 +24,10 @@
24#define _H_CIFS_DEBUG 24#define _H_CIFS_DEBUG
25 25
26void cifs_dump_mem(char *label, void *data, int length); 26void cifs_dump_mem(char *label, void *data, int length);
27#ifdef CONFIG_CIFS_DEBUG2
28void cifs_dump_detail(struct smb_hdr *);
29void cifs_dump_mids(struct TCP_Server_Info *);
30#endif
27extern int traceSMB; /* flag which enables the function below */ 31extern int traceSMB; /* flag which enables the function below */
28void dump_smb(struct smb_hdr *, int); 32void dump_smb(struct smb_hdr *, int);
29#define CIFS_INFO 0x01 33#define CIFS_INFO 0x01
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index d2b128255944..d2a8b2941fc2 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -22,6 +22,7 @@
22#include "cifs_unicode.h" 22#include "cifs_unicode.h"
23#include "cifs_uniupr.h" 23#include "cifs_uniupr.h"
24#include "cifspdu.h" 24#include "cifspdu.h"
25#include "cifsglob.h"
25#include "cifs_debug.h" 26#include "cifs_debug.h"
26 27
27/* 28/*
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index e7d63737e651..a89efaf78a26 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -26,6 +26,8 @@
26#include "md5.h" 26#include "md5.h"
27#include "cifs_unicode.h" 27#include "cifs_unicode.h"
28#include "cifsproto.h" 28#include "cifsproto.h"
29#include <linux/ctype.h>
30#include <linux/random.h>
29 31
30/* Calculate and return the CIFS signature based on the mac key and the smb pdu */ 32/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
31/* the 16 byte signature must be allocated by the caller */ 33/* the 16 byte signature must be allocated by the caller */
@@ -35,6 +37,8 @@
35 37
36extern void mdfour(unsigned char *out, unsigned char *in, int n); 38extern void mdfour(unsigned char *out, unsigned char *in, int n);
37extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); 39extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
40extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
41 unsigned char *p24);
38 42
39static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, 43static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu,
40 const char * key, char * signature) 44 const char * key, char * signature)
@@ -45,7 +49,7 @@ static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu,
45 return -EINVAL; 49 return -EINVAL;
46 50
47 MD5Init(&context); 51 MD5Init(&context);
48 MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16); 52 MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
49 MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); 53 MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
50 MD5Final(signature,&context); 54 MD5Final(signature,&context);
51 return 0; 55 return 0;
@@ -90,7 +94,7 @@ static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
90 return -EINVAL; 94 return -EINVAL;
91 95
92 MD5Init(&context); 96 MD5Init(&context);
93 MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16); 97 MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
94 for(i=0;i<n_vec;i++) { 98 for(i=0;i<n_vec;i++) {
95 if(iov[i].iov_base == NULL) { 99 if(iov[i].iov_base == NULL) {
96 cERROR(1,("null iovec entry")); 100 cERROR(1,("null iovec entry"));
@@ -204,11 +208,12 @@ int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
204 208
205 E_md4hash(password, temp_key); 209 E_md4hash(password, temp_key);
206 mdfour(key,temp_key,16); 210 mdfour(key,temp_key,16);
207 memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE); 211 memcpy(key+16,rn, CIFS_SESS_KEY_SIZE);
208 return 0; 212 return 0;
209} 213}
210 214
211int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info) 215int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses,
216 const struct nls_table * nls_info)
212{ 217{
213 char temp_hash[16]; 218 char temp_hash[16];
214 struct HMACMD5Context ctx; 219 struct HMACMD5Context ctx;
@@ -225,6 +230,8 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
225 user_name_len = strlen(ses->userName); 230 user_name_len = strlen(ses->userName);
226 if(user_name_len > MAX_USERNAME_SIZE) 231 if(user_name_len > MAX_USERNAME_SIZE)
227 return -EINVAL; 232 return -EINVAL;
233 if(ses->domainName == NULL)
234 return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
228 dom_name_len = strlen(ses->domainName); 235 dom_name_len = strlen(ses->domainName);
229 if(dom_name_len > MAX_USERNAME_SIZE) 236 if(dom_name_len > MAX_USERNAME_SIZE)
230 return -EINVAL; 237 return -EINVAL;
@@ -259,16 +266,131 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
259 kfree(unicode_buf); 266 kfree(unicode_buf);
260 return 0; 267 return 0;
261} 268}
262void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response) 269
270#ifdef CONFIG_CIFS_WEAK_PW_HASH
271void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
272{
273 int i;
274 char password_with_pad[CIFS_ENCPWD_SIZE];
275
276 if(ses->server == NULL)
277 return;
278
279 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
280 strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
281
282 if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
283 if(extended_security & CIFSSEC_MAY_PLNTXT) {
284 memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE);
285 return;
286 }
287
288 /* calculate old style session key */
289 /* calling toupper is less broken than repeatedly
290 calling nls_toupper would be since that will never
291 work for UTF8, but neither handles multibyte code pages
292 but the only alternative would be converting to UCS-16 (Unicode)
293 (using a routine something like UniStrupr) then
294 uppercasing and then converting back from Unicode - which
295 would only worth doing it if we knew it were utf8. Basically
296 utf8 and other multibyte codepages each need their own strupper
297 function since a byte at a time will ont work. */
298
299 for(i = 0; i < CIFS_ENCPWD_SIZE; i++) {
300 password_with_pad[i] = toupper(password_with_pad[i]);
301 }
302
303 SMBencrypt(password_with_pad, ses->server->cryptKey, lnm_session_key);
304 /* clear password before we return/free memory */
305 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
306}
307#endif /* CIFS_WEAK_PW_HASH */
308
309static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
310 const struct nls_table * nls_cp)
311{
312 int rc = 0;
313 int len;
314 char nt_hash[16];
315 struct HMACMD5Context * pctxt;
316 wchar_t * user;
317 wchar_t * domain;
318
319 pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
320
321 if(pctxt == NULL)
322 return -ENOMEM;
323
324 /* calculate md4 hash of password */
325 E_md4hash(ses->password, nt_hash);
326
327 /* convert Domainname to unicode and uppercase */
328 hmac_md5_init_limK_to_64(nt_hash, 16, pctxt);
329
330 /* convert ses->userName to unicode and uppercase */
331 len = strlen(ses->userName);
332 user = kmalloc(2 + (len * 2), GFP_KERNEL);
333 if(user == NULL)
334 goto calc_exit_2;
335 len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
336 UniStrupr(user);
337 hmac_md5_update((char *)user, 2*len, pctxt);
338
339 /* convert ses->domainName to unicode and uppercase */
340 if(ses->domainName) {
341 len = strlen(ses->domainName);
342
343 domain = kmalloc(2 + (len * 2), GFP_KERNEL);
344 if(domain == NULL)
345 goto calc_exit_1;
346 len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
347 UniStrupr(domain);
348
349 hmac_md5_update((char *)domain, 2*len, pctxt);
350
351 kfree(domain);
352 }
353calc_exit_1:
354 kfree(user);
355calc_exit_2:
356 /* BB FIXME what about bytes 24 through 40 of the signing key?
357 compare with the NTLM example */
358 hmac_md5_final(ses->server->mac_signing_key, pctxt);
359
360 return rc;
361}
362
363void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
364 const struct nls_table * nls_cp)
365{
366 int rc;
367 struct ntlmv2_resp * buf = (struct ntlmv2_resp *)resp_buf;
368
369 buf->blob_signature = cpu_to_le32(0x00000101);
370 buf->reserved = 0;
371 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
372 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
373 buf->reserved2 = 0;
374 buf->names[0].type = 0;
375 buf->names[0].length = 0;
376
377 /* calculate buf->ntlmv2_hash */
378 rc = calc_ntlmv2_hash(ses, nls_cp);
379 if(rc)
380 cERROR(1,("could not get v2 hash rc %d",rc));
381 CalcNTLMv2_response(ses, resp_buf);
382}
383
384void CalcNTLMv2_response(const struct cifsSesInfo * ses, char * v2_session_response)
263{ 385{
264 struct HMACMD5Context context; 386 struct HMACMD5Context context;
387 /* rest of v2 struct already generated */
265 memcpy(v2_session_response + 8, ses->server->cryptKey,8); 388 memcpy(v2_session_response + 8, ses->server->cryptKey,8);
266 /* gen_blob(v2_session_response + 16); */
267 hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context); 389 hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context);
268 390
269 hmac_md5_update(ses->server->cryptKey,8,&context); 391 hmac_md5_update(v2_session_response+8,
270/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ 392 sizeof(struct ntlmv2_resp) - 8, &context);
271 393
272 hmac_md5_final(v2_session_response,&context); 394 hmac_md5_final(v2_session_response,&context);
273 cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); /* BB removeme BB */ 395/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
274} 396}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 8b4de6eaabd0..c28ede599946 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -56,8 +56,8 @@ unsigned int experimEnabled = 0;
56unsigned int linuxExtEnabled = 1; 56unsigned int linuxExtEnabled = 1;
57unsigned int lookupCacheEnabled = 1; 57unsigned int lookupCacheEnabled = 1;
58unsigned int multiuser_mount = 0; 58unsigned int multiuser_mount = 0;
59unsigned int extended_security = 0; 59unsigned int extended_security = CIFSSEC_DEF;
60unsigned int ntlmv2_support = 0; 60/* unsigned int ntlmv2_support = 0; */
61unsigned int sign_CIFS_PDUs = 1; 61unsigned int sign_CIFS_PDUs = 1;
62extern struct task_struct * oplockThread; /* remove sparse warning */ 62extern struct task_struct * oplockThread; /* remove sparse warning */
63struct task_struct * oplockThread = NULL; 63struct task_struct * oplockThread = NULL;
@@ -908,7 +908,7 @@ static int cifs_dnotify_thread(void * dummyarg)
908 struct cifsSesInfo *ses; 908 struct cifsSesInfo *ses;
909 909
910 do { 910 do {
911 if(try_to_freeze()) 911 if (try_to_freeze())
912 continue; 912 continue;
913 set_current_state(TASK_INTERRUPTIBLE); 913 set_current_state(TASK_INTERRUPTIBLE);
914 schedule_timeout(15*HZ); 914 schedule_timeout(15*HZ);
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index d56c0577c710..8f75c6f24701 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -32,7 +32,8 @@
32#define TRUE 1 32#define TRUE 1
33#endif 33#endif
34 34
35extern struct address_space_operations cifs_addr_ops; 35extern const struct address_space_operations cifs_addr_ops;
36extern const struct address_space_operations cifs_addr_ops_smallbuf;
36 37
37/* Functions related to super block operations */ 38/* Functions related to super block operations */
38extern struct super_operations cifs_super_ops; 39extern struct super_operations cifs_super_ops;
@@ -99,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
99extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 100extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
100extern int cifs_ioctl (struct inode * inode, struct file * filep, 101extern int cifs_ioctl (struct inode * inode, struct file * filep,
101 unsigned int command, unsigned long arg); 102 unsigned int command, unsigned long arg);
102#define CIFS_VERSION "1.43" 103#define CIFS_VERSION "1.44"
103#endif /* _CIFSFS_H */ 104#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 006eb33bff5f..6d7cf5f3bc0b 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -88,7 +88,8 @@ enum statusEnum {
88}; 88};
89 89
90enum securityEnum { 90enum securityEnum {
91 NTLM = 0, /* Legacy NTLM012 auth with NTLM hash */ 91 LANMAN = 0, /* Legacy LANMAN auth */
92 NTLM, /* Legacy NTLM012 auth with NTLM hash */
92 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ 93 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
93 RawNTLMSSP, /* NTLMSSP without SPNEGO */ 94 RawNTLMSSP, /* NTLMSSP without SPNEGO */
94 NTLMSSP, /* NTLMSSP via SPNEGO */ 95 NTLMSSP, /* NTLMSSP via SPNEGO */
@@ -157,7 +158,7 @@ struct TCP_Server_Info {
157 /* 16th byte of RFC1001 workstation name is always null */ 158 /* 16th byte of RFC1001 workstation name is always null */
158 char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; 159 char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
159 __u32 sequence_number; /* needed for CIFS PDU signature */ 160 __u32 sequence_number; /* needed for CIFS PDU signature */
160 char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; 161 char mac_signing_key[CIFS_SESS_KEY_SIZE + 16];
161}; 162};
162 163
163/* 164/*
@@ -179,10 +180,13 @@ struct cifsUidInfo {
179struct cifsSesInfo { 180struct cifsSesInfo {
180 struct list_head cifsSessionList; 181 struct list_head cifsSessionList;
181 struct semaphore sesSem; 182 struct semaphore sesSem;
183#if 0
182 struct cifsUidInfo *uidInfo; /* pointer to user info */ 184 struct cifsUidInfo *uidInfo; /* pointer to user info */
185#endif
183 struct TCP_Server_Info *server; /* pointer to server info */ 186 struct TCP_Server_Info *server; /* pointer to server info */
184 atomic_t inUse; /* # of mounts (tree connections) on this ses */ 187 atomic_t inUse; /* # of mounts (tree connections) on this ses */
185 enum statusEnum status; 188 enum statusEnum status;
189 unsigned overrideSecFlg; /* if non-zero override global sec flags */
186 __u16 ipc_tid; /* special tid for connection to IPC share */ 190 __u16 ipc_tid; /* special tid for connection to IPC share */
187 __u16 flags; 191 __u16 flags;
188 char *serverOS; /* name of operating system underlying server */ 192 char *serverOS; /* name of operating system underlying server */
@@ -194,7 +198,7 @@ struct cifsSesInfo {
194 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for 198 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
195 TCP names - will ipv6 and sctp addresses fit? */ 199 TCP names - will ipv6 and sctp addresses fit? */
196 char userName[MAX_USERNAME_SIZE + 1]; 200 char userName[MAX_USERNAME_SIZE + 1];
197 char domainName[MAX_USERNAME_SIZE + 1]; 201 char * domainName;
198 char * password; 202 char * password;
199}; 203};
200/* session flags */ 204/* session flags */
@@ -209,12 +213,12 @@ struct cifsTconInfo {
209 struct list_head openFileList; 213 struct list_head openFileList;
210 struct semaphore tconSem; 214 struct semaphore tconSem;
211 struct cifsSesInfo *ses; /* pointer to session associated with */ 215 struct cifsSesInfo *ses; /* pointer to session associated with */
212 char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */ 216 char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
213 char *nativeFileSystem; 217 char *nativeFileSystem;
214 __u16 tid; /* The 2 byte tree id */ 218 __u16 tid; /* The 2 byte tree id */
215 __u16 Flags; /* optional support bits */ 219 __u16 Flags; /* optional support bits */
216 enum statusEnum tidStatus; 220 enum statusEnum tidStatus;
217 atomic_t useCount; /* how many mounts (explicit or implicit) to this share */ 221 atomic_t useCount; /* how many explicit/implicit mounts to share */
218#ifdef CONFIG_CIFS_STATS 222#ifdef CONFIG_CIFS_STATS
219 atomic_t num_smbs_sent; 223 atomic_t num_smbs_sent;
220 atomic_t num_writes; 224 atomic_t num_writes;
@@ -254,7 +258,7 @@ struct cifsTconInfo {
254 spinlock_t stat_lock; 258 spinlock_t stat_lock;
255#endif /* CONFIG_CIFS_STATS */ 259#endif /* CONFIG_CIFS_STATS */
256 FILE_SYSTEM_DEVICE_INFO fsDevInfo; 260 FILE_SYSTEM_DEVICE_INFO fsDevInfo;
257 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */ 261 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
258 FILE_SYSTEM_UNIX_INFO fsUnixInfo; 262 FILE_SYSTEM_UNIX_INFO fsUnixInfo;
259 unsigned retry:1; 263 unsigned retry:1;
260 unsigned nocase:1; 264 unsigned nocase:1;
@@ -305,7 +309,6 @@ struct cifsFileInfo {
305 atomic_t wrtPending; /* handle in use - defer close */ 309 atomic_t wrtPending; /* handle in use - defer close */
306 struct semaphore fh_sem; /* prevents reopen race after dead ses*/ 310 struct semaphore fh_sem; /* prevents reopen race after dead ses*/
307 char * search_resume_name; /* BB removeme BB */ 311 char * search_resume_name; /* BB removeme BB */
308 unsigned int resume_name_length; /* BB removeme - field renamed and moved BB */
309 struct cifs_search_info srch_inf; 312 struct cifs_search_info srch_inf;
310}; 313};
311 314
@@ -391,9 +394,9 @@ struct mid_q_entry {
391 struct smb_hdr *resp_buf; /* response buffer */ 394 struct smb_hdr *resp_buf; /* response buffer */
392 int midState; /* wish this were enum but can not pass to wait_event */ 395 int midState; /* wish this were enum but can not pass to wait_event */
393 __u8 command; /* smb command code */ 396 __u8 command; /* smb command code */
394 unsigned multiPart:1; /* multiple responses to one SMB request */
395 unsigned largeBuf:1; /* if valid response, is pointer to large buf */ 397 unsigned largeBuf:1; /* if valid response, is pointer to large buf */
396 unsigned multiResp:1; /* multiple trans2 responses for one request */ 398 unsigned multiRsp:1; /* multiple trans2 responses for one request */
399 unsigned multiEnd:1; /* both received */
397}; 400};
398 401
399struct oplock_q_entry { 402struct oplock_q_entry {
@@ -430,15 +433,35 @@ struct dir_notify_req {
430#define CIFS_LARGE_BUFFER 2 433#define CIFS_LARGE_BUFFER 2
431#define CIFS_IOVEC 4 /* array of response buffers */ 434#define CIFS_IOVEC 4 /* array of response buffers */
432 435
433/* Type of session setup needed */ 436/* Security Flags: indicate type of session setup needed */
434#define CIFS_PLAINTEXT 0 437#define CIFSSEC_MAY_SIGN 0x00001
435#define CIFS_LANMAN 1 438#define CIFSSEC_MAY_NTLM 0x00002
436#define CIFS_NTLM 2 439#define CIFSSEC_MAY_NTLMV2 0x00004
437#define CIFS_NTLMSSP_NEG 3 440#define CIFSSEC_MAY_KRB5 0x00008
438#define CIFS_NTLMSSP_AUTH 4 441#ifdef CONFIG_CIFS_WEAK_PW_HASH
439#define CIFS_SPNEGO_INIT 5 442#define CIFSSEC_MAY_LANMAN 0x00010
440#define CIFS_SPNEGO_TARG 6 443#define CIFSSEC_MAY_PLNTXT 0x00020
441 444#endif /* weak passwords */
445#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
446
447#define CIFSSEC_MUST_SIGN 0x01001
448/* note that only one of the following can be set so the
449result of setting MUST flags more than once will be to
450require use of the stronger protocol */
451#define CIFSSEC_MUST_NTLM 0x02002
452#define CIFSSEC_MUST_NTLMV2 0x04004
453#define CIFSSEC_MUST_KRB5 0x08008
454#ifdef CONFIG_CIFS_WEAK_PW_HASH
455#define CIFSSEC_MUST_LANMAN 0x10010
456#define CIFSSEC_MUST_PLNTXT 0x20020
457#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
458#else
459#define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */
460#endif /* WEAK_PW_HASH */
461#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
462
463#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
464#define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2
442/* 465/*
443 ***************************************************************** 466 *****************************************************************
444 * All constants go here 467 * All constants go here
@@ -500,16 +523,16 @@ GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
500GLOBAL_EXTERN struct list_head GlobalOplock_Q; 523GLOBAL_EXTERN struct list_head GlobalOplock_Q;
501 524
502GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */ 525GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */
503GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q; /* Dir notify response queue */ 526GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q;/* DirNotify response queue */
504 527
505/* 528/*
506 * Global transaction id (XID) information 529 * Global transaction id (XID) information
507 */ 530 */
508GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */ 531GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
509GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */ 532GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
510GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */ 533GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
511GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above and list operations */ 534GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above & list operations */
512 /* on midQ entries */ 535 /* on midQ entries */
513GLOBAL_EXTERN char Local_System_Name[15]; 536GLOBAL_EXTERN char Local_System_Name[15];
514 537
515/* 538/*
@@ -531,7 +554,7 @@ GLOBAL_EXTERN atomic_t smBufAllocCount;
531GLOBAL_EXTERN atomic_t midCount; 554GLOBAL_EXTERN atomic_t midCount;
532 555
533/* Misc globals */ 556/* Misc globals */
534GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions 557GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
535 to be established on existing mount if we 558 to be established on existing mount if we
536 have the uid/password or Kerberos credential 559 have the uid/password or Kerberos credential
537 or equivalent for current user */ 560 or equivalent for current user */
@@ -540,8 +563,8 @@ GLOBAL_EXTERN unsigned int experimEnabled;
540GLOBAL_EXTERN unsigned int lookupCacheEnabled; 563GLOBAL_EXTERN unsigned int lookupCacheEnabled;
541GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent 564GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
542 with more secure ntlmssp2 challenge/resp */ 565 with more secure ntlmssp2 challenge/resp */
543GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */
544GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ 566GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
567GLOBAL_EXTERN unsigned int secFlags;
545GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ 568GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
546GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */ 569GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */
547GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ 570GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index b2233ac05bd2..86239023545b 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -16,7 +16,7 @@
16 * 16 *
17 * You should have received a copy of the GNU Lesser General Public License 17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software 18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 21
22#ifndef _CIFSPDU_H 22#ifndef _CIFSPDU_H
@@ -24,8 +24,14 @@
24 24
25#include <net/sock.h> 25#include <net/sock.h>
26 26
27#ifdef CONFIG_CIFS_WEAK_PW_HASH
28#define LANMAN_PROT 0
29#define CIFS_PROT 1
30#else
27#define CIFS_PROT 0 31#define CIFS_PROT 0
28#define BAD_PROT CIFS_PROT+1 32#endif
33#define POSIX_PROT CIFS_PROT+1
34#define BAD_PROT 0xFFFF
29 35
30/* SMB command codes */ 36/* SMB command codes */
31/* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses 37/* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
@@ -110,7 +116,7 @@
110/* 116/*
111 * Size of the session key (crypto key encrypted with the password 117 * Size of the session key (crypto key encrypted with the password
112 */ 118 */
113#define CIFS_SESSION_KEY_SIZE (24) 119#define CIFS_SESS_KEY_SIZE (24)
114 120
115/* 121/*
116 * Maximum user name length 122 * Maximum user name length
@@ -400,6 +406,29 @@ typedef struct negotiate_req {
400 unsigned char DialectsArray[1]; 406 unsigned char DialectsArray[1];
401} __attribute__((packed)) NEGOTIATE_REQ; 407} __attribute__((packed)) NEGOTIATE_REQ;
402 408
409/* Dialect index is 13 for LANMAN */
410
411typedef struct lanman_neg_rsp {
412 struct smb_hdr hdr; /* wct = 13 */
413 __le16 DialectIndex;
414 __le16 SecurityMode;
415 __le16 MaxBufSize;
416 __le16 MaxMpxCount;
417 __le16 MaxNumberVcs;
418 __le16 RawMode;
419 __le32 SessionKey;
420 __le32 ServerTime;
421 __le16 ServerTimeZone;
422 __le16 EncryptionKeyLength;
423 __le16 Reserved;
424 __u16 ByteCount;
425 unsigned char EncryptionKey[1];
426} __attribute__((packed)) LANMAN_NEG_RSP;
427
428#define READ_RAW_ENABLE 1
429#define WRITE_RAW_ENABLE 2
430#define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE)
431
403typedef struct negotiate_rsp { 432typedef struct negotiate_rsp {
404 struct smb_hdr hdr; /* wct = 17 */ 433 struct smb_hdr hdr; /* wct = 17 */
405 __le16 DialectIndex; 434 __le16 DialectIndex;
@@ -509,7 +538,7 @@ typedef union smb_com_session_setup_andx {
509/* unsigned char * NativeOS; */ 538/* unsigned char * NativeOS; */
510/* unsigned char * NativeLanMan; */ 539/* unsigned char * NativeLanMan; */
511/* unsigned char * PrimaryDomain; */ 540/* unsigned char * PrimaryDomain; */
512 } __attribute__((packed)) resp; /* NTLM response format (with or without extended security */ 541 } __attribute__((packed)) resp; /* NTLM response with or without extended sec*/
513 542
514 struct { /* request format */ 543 struct { /* request format */
515 struct smb_hdr hdr; /* wct = 10 */ 544 struct smb_hdr hdr; /* wct = 10 */
@@ -520,8 +549,8 @@ typedef union smb_com_session_setup_andx {
520 __le16 MaxMpxCount; 549 __le16 MaxMpxCount;
521 __le16 VcNumber; 550 __le16 VcNumber;
522 __u32 SessionKey; 551 __u32 SessionKey;
523 __le16 PassswordLength; 552 __le16 PasswordLength;
524 __u32 Reserved; 553 __u32 Reserved; /* encrypt key len and offset */
525 __le16 ByteCount; 554 __le16 ByteCount;
526 unsigned char AccountPassword[1]; /* followed by */ 555 unsigned char AccountPassword[1]; /* followed by */
527 /* STRING AccountName */ 556 /* STRING AccountName */
@@ -543,6 +572,26 @@ typedef union smb_com_session_setup_andx {
543 } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */ 572 } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */
544} __attribute__((packed)) SESSION_SETUP_ANDX; 573} __attribute__((packed)) SESSION_SETUP_ANDX;
545 574
575/* format of NLTMv2 Response ie "case sensitive password" hash when NTLMv2 */
576
577struct ntlmssp2_name {
578 __le16 type;
579 __le16 length;
580/* char name[length]; */
581} __attribute__((packed));
582
583struct ntlmv2_resp {
584 char ntlmv2_hash[CIFS_ENCPWD_SIZE];
585 __le32 blob_signature;
586 __u32 reserved;
587 __le64 time;
588 __u64 client_chal; /* random */
589 __u32 reserved2;
590 struct ntlmssp2_name names[1];
591 /* array of name entries could follow ending in minimum 4 byte struct */
592} __attribute__((packed));
593
594
546#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux" 595#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
547 596
548/* Capabilities bits (for NTLM SessSetup request) */ 597/* Capabilities bits (for NTLM SessSetup request) */
@@ -573,7 +622,9 @@ typedef struct smb_com_tconx_req {
573} __attribute__((packed)) TCONX_REQ; 622} __attribute__((packed)) TCONX_REQ;
574 623
575typedef struct smb_com_tconx_rsp { 624typedef struct smb_com_tconx_rsp {
576 struct smb_hdr hdr; /* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */ 625 struct smb_hdr hdr; /* wct = 3 note that Win2000 has sent wct = 7
626 in some cases on responses. Four unspecified
627 words followed OptionalSupport */
577 __u8 AndXCommand; 628 __u8 AndXCommand;
578 __u8 AndXReserved; 629 __u8 AndXReserved;
579 __le16 AndXOffset; 630 __le16 AndXOffset;
@@ -1323,6 +1374,9 @@ struct smb_t2_rsp {
1323#define SMB_FILE_MAXIMUM_INFO 0x40d 1374#define SMB_FILE_MAXIMUM_INFO 0x40d
1324 1375
1325/* Find File infolevels */ 1376/* Find File infolevels */
1377#define SMB_FIND_FILE_INFO_STANDARD 0x001
1378#define SMB_FIND_FILE_QUERY_EA_SIZE 0x002
1379#define SMB_FIND_FILE_QUERY_EAS_FROM_LIST 0x003
1326#define SMB_FIND_FILE_DIRECTORY_INFO 0x101 1380#define SMB_FIND_FILE_DIRECTORY_INFO 0x101
1327#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102 1381#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
1328#define SMB_FIND_FILE_NAMES_INFO 0x103 1382#define SMB_FIND_FILE_NAMES_INFO 0x103
@@ -1844,13 +1898,13 @@ typedef struct {
1844typedef struct { 1898typedef struct {
1845 __le32 DeviceType; 1899 __le32 DeviceType;
1846 __le32 DeviceCharacteristics; 1900 __le32 DeviceCharacteristics;
1847} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */ 1901} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info level 0x104 */
1848 1902
1849typedef struct { 1903typedef struct {
1850 __le32 Attributes; 1904 __le32 Attributes;
1851 __le32 MaxPathNameComponentLength; 1905 __le32 MaxPathNameComponentLength;
1852 __le32 FileSystemNameLen; 1906 __le32 FileSystemNameLen;
1853 char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */ 1907 char FileSystemName[52]; /* do not have to save this - get subset? */
1854} __attribute__((packed)) FILE_SYSTEM_ATTRIBUTE_INFO; 1908} __attribute__((packed)) FILE_SYSTEM_ATTRIBUTE_INFO;
1855 1909
1856/******************************************************************************/ 1910/******************************************************************************/
@@ -1947,7 +2001,8 @@ typedef struct {
1947 2001
1948struct file_allocation_info { 2002struct file_allocation_info {
1949 __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */ 2003 __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
1950} __attribute__((packed)); /* size used on disk, level 0x103 for set, 0x105 for query */ 2004} __attribute__((packed)); /* size used on disk, for level 0x103 for set,
2005 0x105 for query */
1951 2006
1952struct file_end_of_file_info { 2007struct file_end_of_file_info {
1953 __le64 FileSize; /* offset to end of file */ 2008 __le64 FileSize; /* offset to end of file */
@@ -2054,7 +2109,7 @@ typedef struct {
2054 __le32 ExtFileAttributes; 2109 __le32 ExtFileAttributes;
2055 __le32 FileNameLength; 2110 __le32 FileNameLength;
2056 char FileName[1]; 2111 char FileName[1];
2057} __attribute__((packed)) FILE_DIRECTORY_INFO; /* level 0x101 FF response data area */ 2112} __attribute__((packed)) FILE_DIRECTORY_INFO; /* level 0x101 FF resp data */
2058 2113
2059typedef struct { 2114typedef struct {
2060 __le32 NextEntryOffset; 2115 __le32 NextEntryOffset;
@@ -2069,7 +2124,7 @@ typedef struct {
2069 __le32 FileNameLength; 2124 __le32 FileNameLength;
2070 __le32 EaSize; /* length of the xattrs */ 2125 __le32 EaSize; /* length of the xattrs */
2071 char FileName[1]; 2126 char FileName[1];
2072} __attribute__((packed)) FILE_FULL_DIRECTORY_INFO; /* level 0x102 FF response data area */ 2127} __attribute__((packed)) FILE_FULL_DIRECTORY_INFO; /* level 0x102 rsp data */
2073 2128
2074typedef struct { 2129typedef struct {
2075 __le32 NextEntryOffset; 2130 __le32 NextEntryOffset;
@@ -2086,7 +2141,7 @@ typedef struct {
2086 __le32 Reserved; 2141 __le32 Reserved;
2087 __u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/ 2142 __u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
2088 char FileName[1]; 2143 char FileName[1];
2089} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF response data area */ 2144} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF rsp data */
2090 2145
2091typedef struct { 2146typedef struct {
2092 __le32 NextEntryOffset; 2147 __le32 NextEntryOffset;
@@ -2104,7 +2159,22 @@ typedef struct {
2104 __u8 Reserved; 2159 __u8 Reserved;
2105 __u8 ShortName[12]; 2160 __u8 ShortName[12];
2106 char FileName[1]; 2161 char FileName[1];
2107} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */ 2162} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FFrsp data */
2163
2164typedef struct {
2165 __u32 ResumeKey;
2166 __le16 CreationDate; /* SMB Date */
2167 __le16 CreationTime; /* SMB Time */
2168 __le16 LastAccessDate;
2169 __le16 LastAccessTime;
2170 __le16 LastWriteDate;
2171 __le16 LastWriteTime;
2172 __le32 DataSize; /* File Size (EOF) */
2173 __le32 AllocationSize;
2174 __le16 Attributes; /* verify not u32 */
2175 __u8 FileNameLength;
2176 char FileName[1];
2177} __attribute__((packed)) FIND_FILE_STANDARD_INFO; /* level 0x1 FF resp data */
2108 2178
2109 2179
2110struct win_dev { 2180struct win_dev {
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 310ea2f0e0bf..a5ddc62d6fe6 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -64,14 +64,12 @@ extern int map_smb_to_linux_error(struct smb_hdr *smb);
64extern void header_assemble(struct smb_hdr *, char /* command */ , 64extern void header_assemble(struct smb_hdr *, char /* command */ ,
65 const struct cifsTconInfo *, int /* length of 65 const struct cifsTconInfo *, int /* length of
66 fixed section (word count) in two byte units */); 66 fixed section (word count) in two byte units */);
67#ifdef CONFIG_CIFS_EXPERIMENTAL
68extern int small_smb_init_no_tc(const int smb_cmd, const int wct, 67extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
69 struct cifsSesInfo *ses, 68 struct cifsSesInfo *ses,
70 void ** request_buf); 69 void ** request_buf);
71extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, 70extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
72 const int stage, int * pNTLMv2_flg, 71 const int stage,
73 const struct nls_table *nls_cp); 72 const struct nls_table *nls_cp);
74#endif
75extern __u16 GetNextMid(struct TCP_Server_Info *server); 73extern __u16 GetNextMid(struct TCP_Server_Info *server);
76extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, 74extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
77 struct cifsTconInfo *); 75 struct cifsTconInfo *);
@@ -285,8 +283,14 @@ extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
285extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, 283extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
286 __u32 expected_sequence_number); 284 __u32 expected_sequence_number);
287extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); 285extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
288extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *); 286extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
289extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * ); 287 const struct nls_table *);
288extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
289extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
290 const struct nls_table *);
291#ifdef CONFIG_CIFS_WEAK_PW_HASH
292extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key);
293#endif /* CIFS_WEAK_PW_HASH */
290extern int CIFSSMBCopy(int xid, 294extern int CIFSSMBCopy(int xid,
291 struct cifsTconInfo *source_tcon, 295 struct cifsTconInfo *source_tcon,
292 const char *fromName, 296 const char *fromName,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 925881e00ff2..19678c575dfc 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -44,8 +44,11 @@ static struct {
44 int index; 44 int index;
45 char *name; 45 char *name;
46} protocols[] = { 46} protocols[] = {
47#ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"},
49#endif /* weak password hashing for legacy clients */
47 {CIFS_PROT, "\2NT LM 0.12"}, 50 {CIFS_PROT, "\2NT LM 0.12"},
48 {CIFS_PROT, "\2POSIX 2"}, 51 {POSIX_PROT, "\2POSIX 2"},
49 {BAD_PROT, "\2"} 52 {BAD_PROT, "\2"}
50}; 53};
51#else 54#else
@@ -53,11 +56,29 @@ static struct {
53 int index; 56 int index;
54 char *name; 57 char *name;
55} protocols[] = { 58} protocols[] = {
59#ifdef CONFIG_CIFS_WEAK_PW_HASH
60 {LANMAN_PROT, "\2LM1.2X002"},
61#endif /* weak password hashing for legacy clients */
56 {CIFS_PROT, "\2NT LM 0.12"}, 62 {CIFS_PROT, "\2NT LM 0.12"},
57 {BAD_PROT, "\2"} 63 {BAD_PROT, "\2"}
58}; 64};
59#endif 65#endif
60 66
67/* define the number of elements in the cifs dialect array */
68#ifdef CONFIG_CIFS_POSIX
69#ifdef CONFIG_CIFS_WEAK_PW_HASH
70#define CIFS_NUM_PROT 3
71#else
72#define CIFS_NUM_PROT 2
73#endif /* CIFS_WEAK_PW_HASH */
74#else /* not posix */
75#ifdef CONFIG_CIFS_WEAK_PW_HASH
76#define CIFS_NUM_PROT 2
77#else
78#define CIFS_NUM_PROT 1
79#endif /* CONFIG_CIFS_WEAK_PW_HASH */
80#endif /* CIFS_POSIX */
81
61 82
62/* Mark as invalid, all open files on tree connections since they 83/* Mark as invalid, all open files on tree connections since they
63 were closed when session to server was lost */ 84 were closed when session to server was lost */
@@ -188,7 +209,6 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
188 return rc; 209 return rc;
189} 210}
190 211
191#ifdef CONFIG_CIFS_EXPERIMENTAL
192int 212int
193small_smb_init_no_tc(const int smb_command, const int wct, 213small_smb_init_no_tc(const int smb_command, const int wct,
194 struct cifsSesInfo *ses, void **request_buf) 214 struct cifsSesInfo *ses, void **request_buf)
@@ -214,7 +234,6 @@ small_smb_init_no_tc(const int smb_command, const int wct,
214 234
215 return rc; 235 return rc;
216} 236}
217#endif /* CONFIG_CIFS_EXPERIMENTAL */
218 237
219/* If the return code is zero, this function must fill in request_buf pointer */ 238/* If the return code is zero, this function must fill in request_buf pointer */
220static int 239static int
@@ -322,7 +341,8 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
322 /* potential retries of smb operations it turns out we can determine */ 341 /* potential retries of smb operations it turns out we can determine */
323 /* from the mid flags when the request buffer can be resent without */ 342 /* from the mid flags when the request buffer can be resent without */
324 /* having to use a second distinct buffer for the response */ 343 /* having to use a second distinct buffer for the response */
325 *response_buf = *request_buf; 344 if(response_buf)
345 *response_buf = *request_buf;
326 346
327 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, 347 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
328 wct /*wct */ ); 348 wct /*wct */ );
@@ -373,8 +393,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
373 NEGOTIATE_RSP *pSMBr; 393 NEGOTIATE_RSP *pSMBr;
374 int rc = 0; 394 int rc = 0;
375 int bytes_returned; 395 int bytes_returned;
396 int i;
376 struct TCP_Server_Info * server; 397 struct TCP_Server_Info * server;
377 u16 count; 398 u16 count;
399 unsigned int secFlags;
378 400
379 if(ses->server) 401 if(ses->server)
380 server = ses->server; 402 server = ses->server;
@@ -386,101 +408,200 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
386 (void **) &pSMB, (void **) &pSMBr); 408 (void **) &pSMB, (void **) &pSMBr);
387 if (rc) 409 if (rc)
388 return rc; 410 return rc;
411
412 /* if any of auth flags (ie not sign or seal) are overriden use them */
413 if(ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
414 secFlags = ses->overrideSecFlg;
415 else /* if override flags set only sign/seal OR them with global auth */
416 secFlags = extended_security | ses->overrideSecFlg;
417
418 cFYI(1,("secFlags 0x%x",secFlags));
419
389 pSMB->hdr.Mid = GetNextMid(server); 420 pSMB->hdr.Mid = GetNextMid(server);
390 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 421 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
391 if (extended_security) 422 if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
392 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 423 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
393 424
394 count = strlen(protocols[0].name) + 1; 425 count = 0;
395 strncpy(pSMB->DialectsArray, protocols[0].name, 30); 426 for(i=0;i<CIFS_NUM_PROT;i++) {
396 /* null guaranteed to be at end of source and target buffers anyway */ 427 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
397 428 count += strlen(protocols[i].name) + 1;
429 /* null at end of source and target buffers anyway */
430 }
398 pSMB->hdr.smb_buf_length += count; 431 pSMB->hdr.smb_buf_length += count;
399 pSMB->ByteCount = cpu_to_le16(count); 432 pSMB->ByteCount = cpu_to_le16(count);
400 433
401 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, 434 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
402 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 435 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
403 if (rc == 0) { 436 if (rc != 0)
404 server->secMode = pSMBr->SecurityMode; 437 goto neg_err_exit;
405 if((server->secMode & SECMODE_USER) == 0) 438
406 cFYI(1,("share mode security")); 439 cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
407 server->secType = NTLM; /* BB override default for 440 /* Check wct = 1 error case */
408 NTLMv2 or kerberos v5 */ 441 if((pSMBr->hdr.WordCount < 13) || (pSMBr->DialectIndex == BAD_PROT)) {
409 /* one byte - no need to convert this or EncryptionKeyLen 442 /* core returns wct = 1, but we do not ask for core - otherwise
410 from little endian */ 443 small wct just comes when dialect index is -1 indicating we
411 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); 444 could not negotiate a common dialect */
412 /* probably no need to store and check maxvcs */ 445 rc = -EOPNOTSUPP;
413 server->maxBuf = 446 goto neg_err_exit;
414 min(le32_to_cpu(pSMBr->MaxBufferSize), 447#ifdef CONFIG_CIFS_WEAK_PW_HASH
448 } else if((pSMBr->hdr.WordCount == 13)
449 && (pSMBr->DialectIndex == LANMAN_PROT)) {
450 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
451
452 if((secFlags & CIFSSEC_MAY_LANMAN) ||
453 (secFlags & CIFSSEC_MAY_PLNTXT))
454 server->secType = LANMAN;
455 else {
456 cERROR(1, ("mount failed weak security disabled"
457 " in /proc/fs/cifs/SecurityFlags"));
458 rc = -EOPNOTSUPP;
459 goto neg_err_exit;
460 }
461 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
462 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
463 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
464 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
465 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
466 /* even though we do not use raw we might as well set this
467 accurately, in case we ever find a need for it */
468 if((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
469 server->maxRw = 0xFF00;
470 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
471 } else {
472 server->maxRw = 0;/* we do not need to use raw anyway */
473 server->capabilities = CAP_MPX_MODE;
474 }
475 server->timeZone = le16_to_cpu(rsp->ServerTimeZone);
476
477 /* BB get server time for time conversions and add
478 code to use it and timezone since this is not UTC */
479
480 if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
481 memcpy(server->cryptKey, rsp->EncryptionKey,
482 CIFS_CRYPTO_KEY_SIZE);
483 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
484 rc = -EIO; /* need cryptkey unless plain text */
485 goto neg_err_exit;
486 }
487
488 cFYI(1,("LANMAN negotiated"));
489 /* we will not end up setting signing flags - as no signing
490 was in LANMAN and server did not return the flags on */
491 goto signing_check;
492#else /* weak security disabled */
493 } else if(pSMBr->hdr.WordCount == 13) {
494 cERROR(1,("mount failed, cifs module not built "
495 "with CIFS_WEAK_PW_HASH support"));
496 rc = -EOPNOTSUPP;
497#endif /* WEAK_PW_HASH */
498 goto neg_err_exit;
499 } else if(pSMBr->hdr.WordCount != 17) {
500 /* unknown wct */
501 rc = -EOPNOTSUPP;
502 goto neg_err_exit;
503 }
504 /* else wct == 17 NTLM */
505 server->secMode = pSMBr->SecurityMode;
506 if((server->secMode & SECMODE_USER) == 0)
507 cFYI(1,("share mode security"));
508
509 if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
510#ifdef CONFIG_CIFS_WEAK_PW_HASH
511 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
512#endif /* CIFS_WEAK_PW_HASH */
513 cERROR(1,("Server requests plain text password"
514 " but client support disabled"));
515
516 if((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
517 server->secType = NTLMv2;
518 else if(secFlags & CIFSSEC_MAY_NTLM)
519 server->secType = NTLM;
520 else if(secFlags & CIFSSEC_MAY_NTLMV2)
521 server->secType = NTLMv2;
522 /* else krb5 ... any others ... */
523
524 /* one byte, so no need to convert this or EncryptionKeyLen from
525 little endian */
526 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
527 /* probably no need to store and check maxvcs */
528 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
415 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 529 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
416 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); 530 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
417 cFYI(0, ("Max buf = %d", ses->server->maxBuf)); 531 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
418 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); 532 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
419 server->capabilities = le32_to_cpu(pSMBr->Capabilities); 533 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
420 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); 534 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
421 /* BB with UTC do we ever need to be using srvr timezone? */ 535 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
422 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { 536 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
423 memcpy(server->cryptKey, pSMBr->u.EncryptionKey, 537 CIFS_CRYPTO_KEY_SIZE);
424 CIFS_CRYPTO_KEY_SIZE); 538 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
425 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) 539 && (pSMBr->EncryptionKeyLength == 0)) {
426 && (pSMBr->EncryptionKeyLength == 0)) { 540 /* decode security blob */
427 /* decode security blob */ 541 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
428 } else 542 rc = -EIO; /* no crypt key only if plain text pwd */
429 rc = -EIO; 543 goto neg_err_exit;
544 }
430 545
431 /* BB might be helpful to save off the domain of server here */ 546 /* BB might be helpful to save off the domain of server here */
432 547
433 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 548 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
434 (server->capabilities & CAP_EXTENDED_SECURITY)) { 549 (server->capabilities & CAP_EXTENDED_SECURITY)) {
435 count = pSMBr->ByteCount; 550 count = pSMBr->ByteCount;
436 if (count < 16) 551 if (count < 16)
437 rc = -EIO; 552 rc = -EIO;
438 else if (count == 16) { 553 else if (count == 16) {
439 server->secType = RawNTLMSSP; 554 server->secType = RawNTLMSSP;
440 if (server->socketUseCount.counter > 1) { 555 if (server->socketUseCount.counter > 1) {
441 if (memcmp 556 if (memcmp(server->server_GUID,
442 (server->server_GUID, 557 pSMBr->u.extended_response.
443 pSMBr->u.extended_response. 558 GUID, 16) != 0) {
444 GUID, 16) != 0) { 559 cFYI(1, ("server UID changed"));
445 cFYI(1, ("server UID changed"));
446 memcpy(server->
447 server_GUID,
448 pSMBr->u.
449 extended_response.
450 GUID, 16);
451 }
452 } else
453 memcpy(server->server_GUID, 560 memcpy(server->server_GUID,
454 pSMBr->u.extended_response. 561 pSMBr->u.extended_response.GUID,
455 GUID, 16); 562 16);
456 } else {
457 rc = decode_negTokenInit(pSMBr->u.
458 extended_response.
459 SecurityBlob,
460 count - 16,
461 &server->secType);
462 if(rc == 1) {
463 /* BB Need to fill struct for sessetup here */
464 rc = -EOPNOTSUPP;
465 } else {
466 rc = -EINVAL;
467 } 563 }
564 } else
565 memcpy(server->server_GUID,
566 pSMBr->u.extended_response.GUID, 16);
567 } else {
568 rc = decode_negTokenInit(pSMBr->u.extended_response.
569 SecurityBlob,
570 count - 16,
571 &server->secType);
572 if(rc == 1) {
573 /* BB Need to fill struct for sessetup here */
574 rc = -EOPNOTSUPP;
575 } else {
576 rc = -EINVAL;
468 } 577 }
469 } else
470 server->capabilities &= ~CAP_EXTENDED_SECURITY;
471 if(sign_CIFS_PDUs == FALSE) {
472 if(server->secMode & SECMODE_SIGN_REQUIRED)
473 cERROR(1,
474 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
475 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
476 } else if(sign_CIFS_PDUs == 1) {
477 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
478 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
479 } 578 }
480 579 } else
580 server->capabilities &= ~CAP_EXTENDED_SECURITY;
581
582#ifdef CONFIG_CIFS_WEAK_PW_HASH
583signing_check:
584#endif
585 if(sign_CIFS_PDUs == FALSE) {
586 if(server->secMode & SECMODE_SIGN_REQUIRED)
587 cERROR(1,("Server requires "
588 "/proc/fs/cifs/PacketSigningEnabled to be on"));
589 server->secMode &=
590 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
591 } else if(sign_CIFS_PDUs == 1) {
592 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
593 server->secMode &=
594 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
595 } else if(sign_CIFS_PDUs == 2) {
596 if((server->secMode &
597 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
598 cERROR(1,("signing required but server lacks support"));
599 }
481 } 600 }
482 601neg_err_exit:
483 cifs_buf_release(pSMB); 602 cifs_buf_release(pSMB);
603
604 cFYI(1,("negprot rc %d",rc));
484 return rc; 605 return rc;
485} 606}
486 607
@@ -2239,7 +2360,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2239 } 2360 }
2240 symlinkinfo[buflen] = 0; /* just in case so the caller 2361 symlinkinfo[buflen] = 0; /* just in case so the caller
2241 does not go off the end of the buffer */ 2362 does not go off the end of the buffer */
2242 cFYI(1,("readlink result - %s ",symlinkinfo)); 2363 cFYI(1,("readlink result - %s",symlinkinfo));
2243 } 2364 }
2244 } 2365 }
2245qreparse_out: 2366qreparse_out:
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index bae1479318d1..876eb9ef85fe 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -49,8 +49,6 @@
49 49
50static DECLARE_COMPLETION(cifsd_complete); 50static DECLARE_COMPLETION(cifsd_complete);
51 51
52extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
53 unsigned char *p24);
54extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 52extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
55 unsigned char *p24); 53 unsigned char *p24);
56 54
@@ -70,6 +68,7 @@ struct smb_vol {
70 gid_t linux_gid; 68 gid_t linux_gid;
71 mode_t file_mode; 69 mode_t file_mode;
72 mode_t dir_mode; 70 mode_t dir_mode;
71 unsigned secFlg;
73 unsigned rw:1; 72 unsigned rw:1;
74 unsigned retry:1; 73 unsigned retry:1;
75 unsigned intr:1; 74 unsigned intr:1;
@@ -83,12 +82,7 @@ struct smb_vol {
83 unsigned remap:1; /* set to remap seven reserved chars in filenames */ 82 unsigned remap:1; /* set to remap seven reserved chars in filenames */
84 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ 83 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
85 unsigned sfu_emul:1; 84 unsigned sfu_emul:1;
86 unsigned krb5:1;
87 unsigned ntlm:1;
88 unsigned ntlmv2:1;
89 unsigned nullauth:1; /* attempt to authenticate with null user */ 85 unsigned nullauth:1; /* attempt to authenticate with null user */
90 unsigned sign:1;
91 unsigned seal:1; /* encrypt */
92 unsigned nocase; /* request case insensitive filenames */ 86 unsigned nocase; /* request case insensitive filenames */
93 unsigned nobrl; /* disable sending byte range locks to srv */ 87 unsigned nobrl; /* disable sending byte range locks to srv */
94 unsigned int rsize; 88 unsigned int rsize;
@@ -369,21 +363,21 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
369 continue; 363 continue;
370 if (bigbuf == NULL) { 364 if (bigbuf == NULL) {
371 bigbuf = cifs_buf_get(); 365 bigbuf = cifs_buf_get();
372 if(bigbuf == NULL) { 366 if (!bigbuf) {
373 cERROR(1,("No memory for large SMB response")); 367 cERROR(1, ("No memory for large SMB response"));
374 msleep(3000); 368 msleep(3000);
375 /* retry will check if exiting */ 369 /* retry will check if exiting */
376 continue; 370 continue;
377 } 371 }
378 } else if(isLargeBuf) { 372 } else if (isLargeBuf) {
379 /* we are reusing a dirtry large buf, clear its start */ 373 /* we are reusing a dirty large buf, clear its start */
380 memset(bigbuf, 0, sizeof (struct smb_hdr)); 374 memset(bigbuf, 0, sizeof (struct smb_hdr));
381 } 375 }
382 376
383 if (smallbuf == NULL) { 377 if (smallbuf == NULL) {
384 smallbuf = cifs_small_buf_get(); 378 smallbuf = cifs_small_buf_get();
385 if(smallbuf == NULL) { 379 if (!smallbuf) {
386 cERROR(1,("No memory for SMB response")); 380 cERROR(1, ("No memory for SMB response"));
387 msleep(1000); 381 msleep(1000);
388 /* retry will check if exiting */ 382 /* retry will check if exiting */
389 continue; 383 continue;
@@ -403,12 +397,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
403 kernel_recvmsg(csocket, &smb_msg, 397 kernel_recvmsg(csocket, &smb_msg,
404 &iov, 1, 4, 0 /* BB see socket.h flags */); 398 &iov, 1, 4, 0 /* BB see socket.h flags */);
405 399
406 if(server->tcpStatus == CifsExiting) { 400 if (server->tcpStatus == CifsExiting) {
407 break; 401 break;
408 } else if (server->tcpStatus == CifsNeedReconnect) { 402 } else if (server->tcpStatus == CifsNeedReconnect) {
409 cFYI(1,("Reconnect after server stopped responding")); 403 cFYI(1, ("Reconnect after server stopped responding"));
410 cifs_reconnect(server); 404 cifs_reconnect(server);
411 cFYI(1,("call to reconnect done")); 405 cFYI(1, ("call to reconnect done"));
412 csocket = server->ssocket; 406 csocket = server->ssocket;
413 continue; 407 continue;
414 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { 408 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
@@ -417,15 +411,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
417 tcpStatus CifsNeedReconnect if server hung */ 411 tcpStatus CifsNeedReconnect if server hung */
418 continue; 412 continue;
419 } else if (length <= 0) { 413 } else if (length <= 0) {
420 if(server->tcpStatus == CifsNew) { 414 if (server->tcpStatus == CifsNew) {
421 cFYI(1,("tcp session abend after SMBnegprot")); 415 cFYI(1, ("tcp session abend after SMBnegprot"));
422 /* some servers kill the TCP session rather than 416 /* some servers kill the TCP session rather than
423 returning an SMB negprot error, in which 417 returning an SMB negprot error, in which
424 case reconnecting here is not going to help, 418 case reconnecting here is not going to help,
425 and so simply return error to mount */ 419 and so simply return error to mount */
426 break; 420 break;
427 } 421 }
428 if(length == -EINTR) { 422 if (!try_to_freeze() && (length == -EINTR)) {
429 cFYI(1,("cifsd thread killed")); 423 cFYI(1,("cifsd thread killed"));
430 break; 424 break;
431 } 425 }
@@ -585,9 +579,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
585 /* merge response - fix up 1st*/ 579 /* merge response - fix up 1st*/
586 if(coalesce_t2(smb_buffer, 580 if(coalesce_t2(smb_buffer,
587 mid_entry->resp_buf)) { 581 mid_entry->resp_buf)) {
582 mid_entry->multiRsp = 1;
588 break; 583 break;
589 } else { 584 } else {
590 /* all parts received */ 585 /* all parts received */
586 mid_entry->multiEnd = 1;
591 goto multi_t2_fnd; 587 goto multi_t2_fnd;
592 } 588 }
593 } else { 589 } else {
@@ -632,9 +628,14 @@ multi_t2_fnd:
632 wake_up_process(task_to_wake); 628 wake_up_process(task_to_wake);
633 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE) 629 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
634 && (isMultiRsp == FALSE)) { 630 && (isMultiRsp == FALSE)) {
635 cERROR(1, ("No task to wake, unknown frame rcvd!")); 631 cERROR(1, ("No task to wake, unknown frame rcvd! NumMids %d", midCount.counter));
636 cifs_dump_mem("Received Data is: ",(char *)smb_buffer, 632 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
637 sizeof(struct smb_hdr)); 633 sizeof(struct smb_hdr));
634#ifdef CONFIG_CIFS_DEBUG2
635 cifs_dump_detail(smb_buffer);
636 cifs_dump_mids(server);
637#endif /* CIFS_DEBUG2 */
638
638 } 639 }
639 } /* end while !EXITING */ 640 } /* end while !EXITING */
640 641
@@ -784,7 +785,6 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
784 785
785 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ 786 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
786 vol->rw = TRUE; 787 vol->rw = TRUE;
787 vol->ntlm = TRUE;
788 /* default is always to request posix paths. */ 788 /* default is always to request posix paths. */
789 vol->posix_paths = 1; 789 vol->posix_paths = 1;
790 790
@@ -915,30 +915,35 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
915 cERROR(1,("no security value specified")); 915 cERROR(1,("no security value specified"));
916 continue; 916 continue;
917 } else if (strnicmp(value, "krb5i", 5) == 0) { 917 } else if (strnicmp(value, "krb5i", 5) == 0) {
918 vol->sign = 1; 918 vol->secFlg |= CIFSSEC_MAY_KRB5 |
919 vol->krb5 = 1; 919 CIFSSEC_MUST_SIGN;
920 } else if (strnicmp(value, "krb5p", 5) == 0) { 920 } else if (strnicmp(value, "krb5p", 5) == 0) {
921 /* vol->seal = 1; 921 /* vol->secFlg |= CIFSSEC_MUST_SEAL |
922 vol->krb5 = 1; */ 922 CIFSSEC_MAY_KRB5; */
923 cERROR(1,("Krb5 cifs privacy not supported")); 923 cERROR(1,("Krb5 cifs privacy not supported"));
924 return 1; 924 return 1;
925 } else if (strnicmp(value, "krb5", 4) == 0) { 925 } else if (strnicmp(value, "krb5", 4) == 0) {
926 vol->krb5 = 1; 926 vol->secFlg |= CIFSSEC_MAY_KRB5;
927 } else if (strnicmp(value, "ntlmv2i", 7) == 0) { 927 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
928 vol->ntlmv2 = 1; 928 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
929 vol->sign = 1; 929 CIFSSEC_MUST_SIGN;
930 } else if (strnicmp(value, "ntlmv2", 6) == 0) { 930 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
931 vol->ntlmv2 = 1; 931 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
932 } else if (strnicmp(value, "ntlmi", 5) == 0) { 932 } else if (strnicmp(value, "ntlmi", 5) == 0) {
933 vol->ntlm = 1; 933 vol->secFlg |= CIFSSEC_MAY_NTLM |
934 vol->sign = 1; 934 CIFSSEC_MUST_SIGN;
935 } else if (strnicmp(value, "ntlm", 4) == 0) { 935 } else if (strnicmp(value, "ntlm", 4) == 0) {
936 /* ntlm is default so can be turned off too */ 936 /* ntlm is default so can be turned off too */
937 vol->ntlm = 1; 937 vol->secFlg |= CIFSSEC_MAY_NTLM;
938 } else if (strnicmp(value, "nontlm", 6) == 0) { 938 } else if (strnicmp(value, "nontlm", 6) == 0) {
939 vol->ntlm = 0; 939 /* BB is there a better way to do this? */
940 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
941#ifdef CONFIG_CIFS_WEAK_PW_HASH
942 } else if (strnicmp(value, "lanman", 6) == 0) {
943 vol->secFlg |= CIFSSEC_MAY_LANMAN;
944#endif
940 } else if (strnicmp(value, "none", 4) == 0) { 945 } else if (strnicmp(value, "none", 4) == 0) {
941 vol->nullauth = 1; 946 vol->nullauth = 1;
942 } else { 947 } else {
943 cERROR(1,("bad security option: %s", value)); 948 cERROR(1,("bad security option: %s", value));
944 return 1; 949 return 1;
@@ -976,7 +981,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
976 } 981 }
977 /* BB are there cases in which a comma can be valid in 982 /* BB are there cases in which a comma can be valid in
978 a domain name and need special handling? */ 983 a domain name and need special handling? */
979 if (strnlen(value, 65) < 65) { 984 if (strnlen(value, 256) < 256) {
980 vol->domainname = value; 985 vol->domainname = value;
981 cFYI(1, ("Domain name set")); 986 cFYI(1, ("Domain name set"));
982 } else { 987 } else {
@@ -1168,6 +1173,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
1168 vol->no_psx_acl = 0; 1173 vol->no_psx_acl = 0;
1169 } else if (strnicmp(data, "noacl",5) == 0) { 1174 } else if (strnicmp(data, "noacl",5) == 0) {
1170 vol->no_psx_acl = 1; 1175 vol->no_psx_acl = 1;
1176 } else if (strnicmp(data, "sign",4) == 0) {
1177 vol->secFlg |= CIFSSEC_MUST_SIGN;
1178/* } else if (strnicmp(data, "seal",4) == 0) {
1179 vol->secFlg |= CIFSSEC_MUST_SEAL; */
1171 } else if (strnicmp(data, "direct",6) == 0) { 1180 } else if (strnicmp(data, "direct",6) == 0) {
1172 vol->direct_io = 1; 1181 vol->direct_io = 1;
1173 } else if (strnicmp(data, "forcedirectio",13) == 0) { 1182 } else if (strnicmp(data, "forcedirectio",13) == 0) {
@@ -1762,11 +1771,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1762 if (volume_info.username) 1771 if (volume_info.username)
1763 strncpy(pSesInfo->userName, 1772 strncpy(pSesInfo->userName,
1764 volume_info.username,MAX_USERNAME_SIZE); 1773 volume_info.username,MAX_USERNAME_SIZE);
1765 if (volume_info.domainname) 1774 if (volume_info.domainname) {
1766 strncpy(pSesInfo->domainName, 1775 int len = strlen(volume_info.domainname);
1767 volume_info.domainname,MAX_USERNAME_SIZE); 1776 pSesInfo->domainName =
1777 kmalloc(len + 1, GFP_KERNEL);
1778 if(pSesInfo->domainName)
1779 strcpy(pSesInfo->domainName,
1780 volume_info.domainname);
1781 }
1768 pSesInfo->linux_uid = volume_info.linux_uid; 1782 pSesInfo->linux_uid = volume_info.linux_uid;
1783 pSesInfo->overrideSecFlg = volume_info.secFlg;
1769 down(&pSesInfo->sesSem); 1784 down(&pSesInfo->sesSem);
1785 /* BB FIXME need to pass vol->secFlgs BB */
1770 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); 1786 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1771 up(&pSesInfo->sesSem); 1787 up(&pSesInfo->sesSem);
1772 if(!rc) 1788 if(!rc)
@@ -1980,7 +1996,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1980 1996
1981static int 1997static int
1982CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, 1998CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1983 char session_key[CIFS_SESSION_KEY_SIZE], 1999 char session_key[CIFS_SESS_KEY_SIZE],
1984 const struct nls_table *nls_codepage) 2000 const struct nls_table *nls_codepage)
1985{ 2001{
1986 struct smb_hdr *smb_buffer; 2002 struct smb_hdr *smb_buffer;
@@ -2038,15 +2054,15 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2038 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); 2054 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2039 2055
2040 pSMB->req_no_secext.CaseInsensitivePasswordLength = 2056 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2041 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2057 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2042 2058
2043 pSMB->req_no_secext.CaseSensitivePasswordLength = 2059 pSMB->req_no_secext.CaseSensitivePasswordLength =
2044 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2060 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2045 bcc_ptr = pByteArea(smb_buffer); 2061 bcc_ptr = pByteArea(smb_buffer);
2046 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); 2062 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2047 bcc_ptr += CIFS_SESSION_KEY_SIZE; 2063 bcc_ptr += CIFS_SESS_KEY_SIZE;
2048 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); 2064 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2049 bcc_ptr += CIFS_SESSION_KEY_SIZE; 2065 bcc_ptr += CIFS_SESS_KEY_SIZE;
2050 2066
2051 if (ses->capabilities & CAP_UNICODE) { 2067 if (ses->capabilities & CAP_UNICODE) {
2052 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ 2068 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
@@ -2054,7 +2070,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2054 bcc_ptr++; 2070 bcc_ptr++;
2055 } 2071 }
2056 if(user == NULL) 2072 if(user == NULL)
2057 bytes_returned = 0; /* skill null user */ 2073 bytes_returned = 0; /* skip null user */
2058 else 2074 else
2059 bytes_returned = 2075 bytes_returned =
2060 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, 2076 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
@@ -2162,8 +2178,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2162 if (remaining_words > 0) { 2178 if (remaining_words > 0) {
2163 len = UniStrnlen((wchar_t *)bcc_ptr, 2179 len = UniStrnlen((wchar_t *)bcc_ptr,
2164 remaining_words-1); 2180 remaining_words-1);
2165 if(ses->serverNOS) 2181 kfree(ses->serverNOS);
2166 kfree(ses->serverNOS);
2167 ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL); 2182 ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
2168 if(ses->serverNOS == NULL) 2183 if(ses->serverNOS == NULL)
2169 goto sesssetup_nomem; 2184 goto sesssetup_nomem;
@@ -2203,12 +2218,10 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2203 /* if these kcallocs fail not much we 2218 /* if these kcallocs fail not much we
2204 can do, but better to not fail the 2219 can do, but better to not fail the
2205 sesssetup itself */ 2220 sesssetup itself */
2206 if(ses->serverDomain) 2221 kfree(ses->serverDomain);
2207 kfree(ses->serverDomain);
2208 ses->serverDomain = 2222 ses->serverDomain =
2209 kzalloc(2, GFP_KERNEL); 2223 kzalloc(2, GFP_KERNEL);
2210 if(ses->serverNOS) 2224 kfree(ses->serverNOS);
2211 kfree(ses->serverNOS);
2212 ses->serverNOS = 2225 ses->serverNOS =
2213 kzalloc(2, GFP_KERNEL); 2226 kzalloc(2, GFP_KERNEL);
2214 } 2227 }
@@ -2217,8 +2230,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2217 if (((long) bcc_ptr + len) - (long) 2230 if (((long) bcc_ptr + len) - (long)
2218 pByteArea(smb_buffer_response) 2231 pByteArea(smb_buffer_response)
2219 <= BCC(smb_buffer_response)) { 2232 <= BCC(smb_buffer_response)) {
2220 if(ses->serverOS) 2233 kfree(ses->serverOS);
2221 kfree(ses->serverOS);
2222 ses->serverOS = kzalloc(len + 1,GFP_KERNEL); 2234 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
2223 if(ses->serverOS == NULL) 2235 if(ses->serverOS == NULL)
2224 goto sesssetup_nomem; 2236 goto sesssetup_nomem;
@@ -2229,8 +2241,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2229 bcc_ptr++; 2241 bcc_ptr++;
2230 2242
2231 len = strnlen(bcc_ptr, 1024); 2243 len = strnlen(bcc_ptr, 1024);
2232 if(ses->serverNOS) 2244 kfree(ses->serverNOS);
2233 kfree(ses->serverNOS);
2234 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL); 2245 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2235 if(ses->serverNOS == NULL) 2246 if(ses->serverNOS == NULL)
2236 goto sesssetup_nomem; 2247 goto sesssetup_nomem;
@@ -2274,292 +2285,6 @@ sesssetup_nomem: /* do not return an error on nomem for the info strings,
2274} 2285}
2275 2286
2276static int 2287static int
2277CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2278 char *SecurityBlob,int SecurityBlobLength,
2279 const struct nls_table *nls_codepage)
2280{
2281 struct smb_hdr *smb_buffer;
2282 struct smb_hdr *smb_buffer_response;
2283 SESSION_SETUP_ANDX *pSMB;
2284 SESSION_SETUP_ANDX *pSMBr;
2285 char *bcc_ptr;
2286 char *user;
2287 char *domain;
2288 int rc = 0;
2289 int remaining_words = 0;
2290 int bytes_returned = 0;
2291 int len;
2292 __u32 capabilities;
2293 __u16 count;
2294
2295 cFYI(1, ("In spnego sesssetup "));
2296 if(ses == NULL)
2297 return -EINVAL;
2298 user = ses->userName;
2299 domain = ses->domainName;
2300
2301 smb_buffer = cifs_buf_get();
2302 if (smb_buffer == NULL) {
2303 return -ENOMEM;
2304 }
2305 smb_buffer_response = smb_buffer;
2306 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2307
2308 /* send SMBsessionSetup here */
2309 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2310 NULL /* no tCon exists yet */ , 12 /* wct */ );
2311
2312 smb_buffer->Mid = GetNextMid(ses->server);
2313 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2314 pSMB->req.AndXCommand = 0xFF;
2315 if(ses->server->maxBuf > 64*1024)
2316 ses->server->maxBuf = (64*1023);
2317 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2318 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2319
2320 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2321 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2322
2323 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2324 CAP_EXTENDED_SECURITY;
2325 if (ses->capabilities & CAP_UNICODE) {
2326 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2327 capabilities |= CAP_UNICODE;
2328 }
2329 if (ses->capabilities & CAP_STATUS32) {
2330 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2331 capabilities |= CAP_STATUS32;
2332 }
2333 if (ses->capabilities & CAP_DFS) {
2334 smb_buffer->Flags2 |= SMBFLG2_DFS;
2335 capabilities |= CAP_DFS;
2336 }
2337 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2338
2339 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2340 bcc_ptr = pByteArea(smb_buffer);
2341 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2342 bcc_ptr += SecurityBlobLength;
2343
2344 if (ses->capabilities & CAP_UNICODE) {
2345 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2346 *bcc_ptr = 0;
2347 bcc_ptr++;
2348 }
2349 bytes_returned =
2350 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage);
2351 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2352 bcc_ptr += 2; /* trailing null */
2353 if (domain == NULL)
2354 bytes_returned =
2355 cifs_strtoUCS((__le16 *) bcc_ptr,
2356 "CIFS_LINUX_DOM", 32, nls_codepage);
2357 else
2358 bytes_returned =
2359 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2360 nls_codepage);
2361 bcc_ptr += 2 * bytes_returned;
2362 bcc_ptr += 2;
2363 bytes_returned =
2364 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2365 32, nls_codepage);
2366 bcc_ptr += 2 * bytes_returned;
2367 bytes_returned =
2368 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2369 nls_codepage);
2370 bcc_ptr += 2 * bytes_returned;
2371 bcc_ptr += 2;
2372 bytes_returned =
2373 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2374 64, nls_codepage);
2375 bcc_ptr += 2 * bytes_returned;
2376 bcc_ptr += 2;
2377 } else {
2378 strncpy(bcc_ptr, user, 200);
2379 bcc_ptr += strnlen(user, 200);
2380 *bcc_ptr = 0;
2381 bcc_ptr++;
2382 if (domain == NULL) {
2383 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2384 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2385 } else {
2386 strncpy(bcc_ptr, domain, 64);
2387 bcc_ptr += strnlen(domain, 64);
2388 *bcc_ptr = 0;
2389 bcc_ptr++;
2390 }
2391 strcpy(bcc_ptr, "Linux version ");
2392 bcc_ptr += strlen("Linux version ");
2393 strcpy(bcc_ptr, system_utsname.release);
2394 bcc_ptr += strlen(system_utsname.release) + 1;
2395 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2396 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2397 }
2398 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2399 smb_buffer->smb_buf_length += count;
2400 pSMB->req.ByteCount = cpu_to_le16(count);
2401
2402 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2403 &bytes_returned, 1);
2404 if (rc) {
2405/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2406 } else if ((smb_buffer_response->WordCount == 3)
2407 || (smb_buffer_response->WordCount == 4)) {
2408 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2409 __u16 blob_len =
2410 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2411 if (action & GUEST_LOGIN)
2412 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2413 if (ses) {
2414 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2415 cFYI(1, ("UID = %d ", ses->Suid));
2416 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2417
2418 /* BB Fix below to make endian neutral !! */
2419
2420 if ((pSMBr->resp.hdr.WordCount == 3)
2421 || ((pSMBr->resp.hdr.WordCount == 4)
2422 && (blob_len <
2423 pSMBr->resp.ByteCount))) {
2424 if (pSMBr->resp.hdr.WordCount == 4) {
2425 bcc_ptr +=
2426 blob_len;
2427 cFYI(1,
2428 ("Security Blob Length %d ",
2429 blob_len));
2430 }
2431
2432 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2433 if ((long) (bcc_ptr) % 2) {
2434 remaining_words =
2435 (BCC(smb_buffer_response)
2436 - 1) / 2;
2437 bcc_ptr++; /* Unicode strings must be word aligned */
2438 } else {
2439 remaining_words =
2440 BCC
2441 (smb_buffer_response) / 2;
2442 }
2443 len =
2444 UniStrnlen((wchar_t *) bcc_ptr,
2445 remaining_words - 1);
2446/* We look for obvious messed up bcc or strings in response so we do not go off
2447 the end since (at least) WIN2K and Windows XP have a major bug in not null
2448 terminating last Unicode string in response */
2449 if(ses->serverOS)
2450 kfree(ses->serverOS);
2451 ses->serverOS =
2452 kzalloc(2 * (len + 1), GFP_KERNEL);
2453 cifs_strfromUCS_le(ses->serverOS,
2454 (__le16 *)
2455 bcc_ptr, len,
2456 nls_codepage);
2457 bcc_ptr += 2 * (len + 1);
2458 remaining_words -= len + 1;
2459 ses->serverOS[2 * len] = 0;
2460 ses->serverOS[1 + (2 * len)] = 0;
2461 if (remaining_words > 0) {
2462 len = UniStrnlen((wchar_t *)bcc_ptr,
2463 remaining_words
2464 - 1);
2465 if(ses->serverNOS)
2466 kfree(ses->serverNOS);
2467 ses->serverNOS =
2468 kzalloc(2 * (len + 1),
2469 GFP_KERNEL);
2470 cifs_strfromUCS_le(ses->serverNOS,
2471 (__le16 *)bcc_ptr,
2472 len,
2473 nls_codepage);
2474 bcc_ptr += 2 * (len + 1);
2475 ses->serverNOS[2 * len] = 0;
2476 ses->serverNOS[1 + (2 * len)] = 0;
2477 remaining_words -= len + 1;
2478 if (remaining_words > 0) {
2479 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2480 /* last string not null terminated (e.g.Windows XP/2000) */
2481 if(ses->serverDomain)
2482 kfree(ses->serverDomain);
2483 ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
2484 cifs_strfromUCS_le(ses->serverDomain,
2485 (__le16 *)bcc_ptr,
2486 len, nls_codepage);
2487 bcc_ptr += 2*(len+1);
2488 ses->serverDomain[2*len] = 0;
2489 ses->serverDomain[1+(2*len)] = 0;
2490 } /* else no more room so create dummy domain string */
2491 else {
2492 if(ses->serverDomain)
2493 kfree(ses->serverDomain);
2494 ses->serverDomain =
2495 kzalloc(2,GFP_KERNEL);
2496 }
2497 } else {/* no room use dummy domain&NOS */
2498 if(ses->serverDomain)
2499 kfree(ses->serverDomain);
2500 ses->serverDomain = kzalloc(2, GFP_KERNEL);
2501 if(ses->serverNOS)
2502 kfree(ses->serverNOS);
2503 ses->serverNOS = kzalloc(2, GFP_KERNEL);
2504 }
2505 } else { /* ASCII */
2506
2507 len = strnlen(bcc_ptr, 1024);
2508 if (((long) bcc_ptr + len) - (long)
2509 pByteArea(smb_buffer_response)
2510 <= BCC(smb_buffer_response)) {
2511 if(ses->serverOS)
2512 kfree(ses->serverOS);
2513 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
2514 strncpy(ses->serverOS, bcc_ptr, len);
2515
2516 bcc_ptr += len;
2517 bcc_ptr[0] = 0; /* null terminate the string */
2518 bcc_ptr++;
2519
2520 len = strnlen(bcc_ptr, 1024);
2521 if(ses->serverNOS)
2522 kfree(ses->serverNOS);
2523 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2524 strncpy(ses->serverNOS, bcc_ptr, len);
2525 bcc_ptr += len;
2526 bcc_ptr[0] = 0;
2527 bcc_ptr++;
2528
2529 len = strnlen(bcc_ptr, 1024);
2530 if(ses->serverDomain)
2531 kfree(ses->serverDomain);
2532 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
2533 strncpy(ses->serverDomain, bcc_ptr, len);
2534 bcc_ptr += len;
2535 bcc_ptr[0] = 0;
2536 bcc_ptr++;
2537 } else
2538 cFYI(1,
2539 ("Variable field of length %d extends beyond end of smb ",
2540 len));
2541 }
2542 } else {
2543 cERROR(1,
2544 (" Security Blob Length extends beyond end of SMB"));
2545 }
2546 } else {
2547 cERROR(1, ("No session structure passed in."));
2548 }
2549 } else {
2550 cERROR(1,
2551 (" Invalid Word count %d: ",
2552 smb_buffer_response->WordCount));
2553 rc = -EIO;
2554 }
2555
2556 if (smb_buffer)
2557 cifs_buf_release(smb_buffer);
2558
2559 return rc;
2560}
2561
2562static int
2563CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, 2288CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2564 struct cifsSesInfo *ses, int * pNTLMv2_flag, 2289 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2565 const struct nls_table *nls_codepage) 2290 const struct nls_table *nls_codepage)
@@ -2635,8 +2360,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2635 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; 2360 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2636 if(sign_CIFS_PDUs) 2361 if(sign_CIFS_PDUs)
2637 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; 2362 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2638 if(ntlmv2_support) 2363/* if(ntlmv2_support)
2639 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2; 2364 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2640 /* setup pointers to domain name and workstation name */ 2365 /* setup pointers to domain name and workstation name */
2641 bcc_ptr += SecurityBlobLength; 2366 bcc_ptr += SecurityBlobLength;
2642 2367
@@ -2783,8 +2508,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2783 bcc_ptr, 2508 bcc_ptr,
2784 remaining_words 2509 remaining_words
2785 - 1); 2510 - 1);
2786 if(ses->serverNOS) 2511 kfree(ses->serverNOS);
2787 kfree(ses->serverNOS);
2788 ses->serverNOS = 2512 ses->serverNOS =
2789 kzalloc(2 * (len + 1), 2513 kzalloc(2 * (len + 1),
2790 GFP_KERNEL); 2514 GFP_KERNEL);
@@ -2802,8 +2526,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2802 if (remaining_words > 0) { 2526 if (remaining_words > 0) {
2803 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 2527 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2804 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ 2528 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2805 if(ses->serverDomain) 2529 kfree(ses->serverDomain);
2806 kfree(ses->serverDomain);
2807 ses->serverDomain = 2530 ses->serverDomain =
2808 kzalloc(2 * 2531 kzalloc(2 *
2809 (len + 2532 (len +
@@ -2822,19 +2545,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2822 = 0; 2545 = 0;
2823 } /* else no more room so create dummy domain string */ 2546 } /* else no more room so create dummy domain string */
2824 else { 2547 else {
2825 if(ses->serverDomain) 2548 kfree(ses->serverDomain);
2826 kfree(ses->serverDomain);
2827 ses->serverDomain = 2549 ses->serverDomain =
2828 kzalloc(2, 2550 kzalloc(2,
2829 GFP_KERNEL); 2551 GFP_KERNEL);
2830 } 2552 }
2831 } else { /* no room so create dummy domain and NOS string */ 2553 } else { /* no room so create dummy domain and NOS string */
2832 if(ses->serverDomain); 2554 kfree(ses->serverDomain);
2833 kfree(ses->serverDomain);
2834 ses->serverDomain = 2555 ses->serverDomain =
2835 kzalloc(2, GFP_KERNEL); 2556 kzalloc(2, GFP_KERNEL);
2836 if(ses->serverNOS) 2557 kfree(ses->serverNOS);
2837 kfree(ses->serverNOS);
2838 ses->serverNOS = 2558 ses->serverNOS =
2839 kzalloc(2, GFP_KERNEL); 2559 kzalloc(2, GFP_KERNEL);
2840 } 2560 }
@@ -2856,8 +2576,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2856 bcc_ptr++; 2576 bcc_ptr++;
2857 2577
2858 len = strnlen(bcc_ptr, 1024); 2578 len = strnlen(bcc_ptr, 1024);
2859 if(ses->serverNOS) 2579 kfree(ses->serverNOS);
2860 kfree(ses->serverNOS);
2861 ses->serverNOS = 2580 ses->serverNOS =
2862 kzalloc(len + 1, 2581 kzalloc(len + 1,
2863 GFP_KERNEL); 2582 GFP_KERNEL);
@@ -2867,8 +2586,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2867 bcc_ptr++; 2586 bcc_ptr++;
2868 2587
2869 len = strnlen(bcc_ptr, 1024); 2588 len = strnlen(bcc_ptr, 1024);
2870 if(ses->serverDomain) 2589 kfree(ses->serverDomain);
2871 kfree(ses->serverDomain);
2872 ses->serverDomain = 2590 ses->serverDomain =
2873 kzalloc(len + 1, 2591 kzalloc(len + 1,
2874 GFP_KERNEL); 2592 GFP_KERNEL);
@@ -2994,14 +2712,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2994 SecurityBlob->LmChallengeResponse.Buffer = 0; 2712 SecurityBlob->LmChallengeResponse.Buffer = 0;
2995 2713
2996 SecurityBlob->NtChallengeResponse.Length = 2714 SecurityBlob->NtChallengeResponse.Length =
2997 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2715 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2998 SecurityBlob->NtChallengeResponse.MaximumLength = 2716 SecurityBlob->NtChallengeResponse.MaximumLength =
2999 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2717 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3000 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE); 2718 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
3001 SecurityBlob->NtChallengeResponse.Buffer = 2719 SecurityBlob->NtChallengeResponse.Buffer =
3002 cpu_to_le32(SecurityBlobLength); 2720 cpu_to_le32(SecurityBlobLength);
3003 SecurityBlobLength += CIFS_SESSION_KEY_SIZE; 2721 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
3004 bcc_ptr += CIFS_SESSION_KEY_SIZE; 2722 bcc_ptr += CIFS_SESS_KEY_SIZE;
3005 2723
3006 if (ses->capabilities & CAP_UNICODE) { 2724 if (ses->capabilities & CAP_UNICODE) {
3007 if (domain == NULL) { 2725 if (domain == NULL) {
@@ -3190,8 +2908,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3190 bcc_ptr, 2908 bcc_ptr,
3191 remaining_words 2909 remaining_words
3192 - 1); 2910 - 1);
3193 if(ses->serverNOS) 2911 kfree(ses->serverNOS);
3194 kfree(ses->serverNOS);
3195 ses->serverNOS = 2912 ses->serverNOS =
3196 kzalloc(2 * (len + 1), 2913 kzalloc(2 * (len + 1),
3197 GFP_KERNEL); 2914 GFP_KERNEL);
@@ -3244,8 +2961,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3244 if(ses->serverDomain) 2961 if(ses->serverDomain)
3245 kfree(ses->serverDomain); 2962 kfree(ses->serverDomain);
3246 ses->serverDomain = kzalloc(2, GFP_KERNEL); 2963 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3247 if(ses->serverNOS) 2964 kfree(ses->serverNOS);
3248 kfree(ses->serverNOS);
3249 ses->serverNOS = kzalloc(2, GFP_KERNEL); 2965 ses->serverNOS = kzalloc(2, GFP_KERNEL);
3250 } 2966 }
3251 } else { /* ASCII */ 2967 } else { /* ASCII */
@@ -3263,8 +2979,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3263 bcc_ptr++; 2979 bcc_ptr++;
3264 2980
3265 len = strnlen(bcc_ptr, 1024); 2981 len = strnlen(bcc_ptr, 1024);
3266 if(ses->serverNOS) 2982 kfree(ses->serverNOS);
3267 kfree(ses->serverNOS);
3268 ses->serverNOS = kzalloc(len+1,GFP_KERNEL); 2983 ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
3269 strncpy(ses->serverNOS, bcc_ptr, len); 2984 strncpy(ses->serverNOS, bcc_ptr, len);
3270 bcc_ptr += len; 2985 bcc_ptr += len;
@@ -3340,22 +3055,33 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3340 bcc_ptr = &pSMB->Password[0]; 3055 bcc_ptr = &pSMB->Password[0];
3341 if((ses->server->secMode) & SECMODE_USER) { 3056 if((ses->server->secMode) & SECMODE_USER) {
3342 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ 3057 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3058 *bcc_ptr = 0; /* password is null byte */
3343 bcc_ptr++; /* skip password */ 3059 bcc_ptr++; /* skip password */
3060 /* already aligned so no need to do it below */
3344 } else { 3061 } else {
3345 pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE); 3062 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
3346 /* BB FIXME add code to fail this if NTLMv2 or Kerberos 3063 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3347 specified as required (when that support is added to 3064 specified as required (when that support is added to
3348 the vfs in the future) as only NTLM or the much 3065 the vfs in the future) as only NTLM or the much
3349 weaker LANMAN (which we do not send) is accepted 3066 weaker LANMAN (which we do not send by default) is accepted
3350 by Samba (not sure whether other servers allow 3067 by Samba (not sure whether other servers allow
3351 NTLMv2 password here) */ 3068 NTLMv2 password here) */
3069#ifdef CONFIG_CIFS_WEAK_PW_HASH
3070 if((extended_security & CIFSSEC_MAY_LANMAN) &&
3071 (ses->server->secType == LANMAN))
3072 calc_lanman_hash(ses, bcc_ptr);
3073 else
3074#endif /* CIFS_WEAK_PW_HASH */
3352 SMBNTencrypt(ses->password, 3075 SMBNTencrypt(ses->password,
3353 ses->server->cryptKey, 3076 ses->server->cryptKey,
3354 bcc_ptr); 3077 bcc_ptr);
3355 3078
3356 bcc_ptr += CIFS_SESSION_KEY_SIZE; 3079 bcc_ptr += CIFS_SESS_KEY_SIZE;
3357 *bcc_ptr = 0; 3080 if(ses->capabilities & CAP_UNICODE) {
3358 bcc_ptr++; /* align */ 3081 /* must align unicode strings */
3082 *bcc_ptr = 0; /* null byte password */
3083 bcc_ptr++;
3084 }
3359 } 3085 }
3360 3086
3361 if(ses->server->secMode & 3087 if(ses->server->secMode &
@@ -3429,7 +3155,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3429 } 3155 }
3430 /* else do not bother copying these informational fields */ 3156 /* else do not bother copying these informational fields */
3431 } 3157 }
3432 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); 3158 if(smb_buffer_response->WordCount == 3)
3159 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3160 else
3161 tcon->Flags = 0;
3433 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags)); 3162 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3434 } else if ((rc == 0) && tcon == NULL) { 3163 } else if ((rc == 0) && tcon == NULL) {
3435 /* all we need to save for IPC$ connection */ 3164 /* all we need to save for IPC$ connection */
@@ -3494,7 +3223,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3494 struct nls_table * nls_info) 3223 struct nls_table * nls_info)
3495{ 3224{
3496 int rc = 0; 3225 int rc = 0;
3497 char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; 3226 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3498 int ntlmv2_flag = FALSE; 3227 int ntlmv2_flag = FALSE;
3499 int first_time = 0; 3228 int first_time = 0;
3500 3229
@@ -3526,20 +3255,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3526 pSesInfo->server->secMode, 3255 pSesInfo->server->secMode,
3527 pSesInfo->server->capabilities, 3256 pSesInfo->server->capabilities,
3528 pSesInfo->server->timeZone)); 3257 pSesInfo->server->timeZone));
3529#ifdef CONFIG_CIFS_EXPERIMENTAL 3258 if(experimEnabled < 2)
3530 if(experimEnabled > 1) 3259 rc = CIFS_SessSetup(xid, pSesInfo,
3531 rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */, 3260 first_time, nls_info);
3532 &ntlmv2_flag, nls_info); 3261 else if (extended_security
3533 else
3534#endif
3535 if (extended_security
3536 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3262 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3537 && (pSesInfo->server->secType == NTLMSSP)) { 3263 && (pSesInfo->server->secType == NTLMSSP)) {
3538 cFYI(1, ("New style sesssetup")); 3264 rc = -EOPNOTSUPP;
3539 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3540 NULL /* security blob */,
3541 0 /* blob length */,
3542 nls_info);
3543 } else if (extended_security 3265 } else if (extended_security
3544 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3266 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3545 && (pSesInfo->server->secType == RawNTLMSSP)) { 3267 && (pSesInfo->server->secType == RawNTLMSSP)) {
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 82315edc77d7..ba4cbe9b0684 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -113,7 +113,7 @@ cifs_bp_rename_retry:
113 full_path[namelen+2] = 0; 113 full_path[namelen+2] = 0;
114BB remove above eight lines BB */ 114BB remove above eight lines BB */
115 115
116/* Inode operations in similar order to how they appear in the Linux file fs.h */ 116/* Inode operations in similar order to how they appear in Linux file fs.h */
117 117
118int 118int
119cifs_create(struct inode *inode, struct dentry *direntry, int mode, 119cifs_create(struct inode *inode, struct dentry *direntry, int mode,
@@ -178,11 +178,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
178 FreeXid(xid); 178 FreeXid(xid);
179 return -ENOMEM; 179 return -ENOMEM;
180 } 180 }
181 181 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
182 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, 182 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
183 desiredAccess, CREATE_NOT_DIR, 183 desiredAccess, CREATE_NOT_DIR,
184 &fileHandle, &oplock, buf, cifs_sb->local_nls, 184 &fileHandle, &oplock, buf, cifs_sb->local_nls,
185 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 185 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
186 else
187 rc = -EIO; /* no NT SMB support fall into legacy open below */
188
186 if(rc == -EIO) { 189 if(rc == -EIO) {
187 /* old server, retry the open legacy style */ 190 /* old server, retry the open legacy style */
188 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, 191 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
@@ -191,7 +194,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
191 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 194 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
192 } 195 }
193 if (rc) { 196 if (rc) {
194 cFYI(1, ("cifs_create returned 0x%x ", rc)); 197 cFYI(1, ("cifs_create returned 0x%x", rc));
195 } else { 198 } else {
196 /* If Open reported that we actually created a file 199 /* If Open reported that we actually created a file
197 then we now have to set the mode if possible */ 200 then we now have to set the mode if possible */
@@ -369,6 +372,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
369 cifs_sb->mnt_cifs_flags & 372 cifs_sb->mnt_cifs_flags &
370 CIFS_MOUNT_MAP_SPECIAL_CHR); 373 CIFS_MOUNT_MAP_SPECIAL_CHR);
371 374
375 /* BB FIXME - add handling for backlevel servers
376 which need legacy open and check for all
377 calls to SMBOpen for fallback to
378 SMBLeagcyOpen */
372 if(!rc) { 379 if(!rc) {
373 /* BB Do not bother to decode buf since no 380 /* BB Do not bother to decode buf since no
374 local inode yet to put timestamps in, 381 local inode yet to put timestamps in,
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index 633a93811328..d91a3d44e9e3 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -91,14 +91,14 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
91 if(full_path == NULL) { 91 if(full_path == NULL) {
92 rc = -ENOMEM; 92 rc = -ENOMEM;
93 } else { 93 } else {
94 cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */ 94 cFYI(1,("dir notify on file %s Arg 0x%lx",full_path,arg));
95 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, 95 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
96 GENERIC_READ | SYNCHRONIZE, 0 /* create options */, 96 GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
97 &netfid, &oplock,NULL, cifs_sb->local_nls, 97 &netfid, &oplock,NULL, cifs_sb->local_nls,
98 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 98 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
99 /* BB fixme - add this handle to a notify handle list */ 99 /* BB fixme - add this handle to a notify handle list */
100 if(rc) { 100 if(rc) {
101 cERROR(1,("Could not open directory for notify")); /* BB remove BB */ 101 cFYI(1,("Could not open directory for notify"));
102 } else { 102 } else {
103 filter = convert_to_cifs_notify_flags(arg); 103 filter = convert_to_cifs_notify_flags(arg);
104 if(filter != 0) { 104 if(filter != 0) {
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index b4a18c1cab0a..5861eb42e626 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -110,7 +110,6 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
110 &pCifsInode->openFileList); 110 &pCifsInode->openFileList);
111 } 111 }
112 write_unlock(&GlobalSMBSeslock); 112 write_unlock(&GlobalSMBSeslock);
113 write_unlock(&file->f_owner.lock);
114 if (pCifsInode->clientCanCacheRead) { 113 if (pCifsInode->clientCanCacheRead) {
115 /* we have the inode open somewhere else 114 /* we have the inode open somewhere else
116 no need to discard cache data */ 115 no need to discard cache data */
@@ -201,7 +200,7 @@ int cifs_open(struct inode *inode, struct file *file)
201 } else { 200 } else {
202 if (file->f_flags & O_EXCL) 201 if (file->f_flags & O_EXCL)
203 cERROR(1, ("could not find file instance for " 202 cERROR(1, ("could not find file instance for "
204 "new file %p ", file)); 203 "new file %p", file));
205 } 204 }
206 } 205 }
207 206
@@ -260,10 +259,15 @@ int cifs_open(struct inode *inode, struct file *file)
260 rc = -ENOMEM; 259 rc = -ENOMEM;
261 goto out; 260 goto out;
262 } 261 }
263 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, 262
264 CREATE_NOT_DIR, &netfid, &oplock, buf, 263 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
264 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
265 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
265 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags 266 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
266 & CIFS_MOUNT_MAP_SPECIAL_CHR); 267 & CIFS_MOUNT_MAP_SPECIAL_CHR);
268 else
269 rc = -EIO; /* no NT SMB support fall into legacy open below */
270
267 if (rc == -EIO) { 271 if (rc == -EIO) {
268 /* Old server, try legacy style OpenX */ 272 /* Old server, try legacy style OpenX */
269 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, 273 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
@@ -272,7 +276,7 @@ int cifs_open(struct inode *inode, struct file *file)
272 & CIFS_MOUNT_MAP_SPECIAL_CHR); 276 & CIFS_MOUNT_MAP_SPECIAL_CHR);
273 } 277 }
274 if (rc) { 278 if (rc) {
275 cFYI(1, ("cifs_open returned 0x%x ", rc)); 279 cFYI(1, ("cifs_open returned 0x%x", rc));
276 goto out; 280 goto out;
277 } 281 }
278 file->private_data = 282 file->private_data =
@@ -282,7 +286,6 @@ int cifs_open(struct inode *inode, struct file *file)
282 goto out; 286 goto out;
283 } 287 }
284 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); 288 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
285 write_lock(&file->f_owner.lock);
286 write_lock(&GlobalSMBSeslock); 289 write_lock(&GlobalSMBSeslock);
287 list_add(&pCifsFile->tlist, &pTcon->openFileList); 290 list_add(&pCifsFile->tlist, &pTcon->openFileList);
288 291
@@ -293,7 +296,6 @@ int cifs_open(struct inode *inode, struct file *file)
293 &oplock, buf, full_path, xid); 296 &oplock, buf, full_path, xid);
294 } else { 297 } else {
295 write_unlock(&GlobalSMBSeslock); 298 write_unlock(&GlobalSMBSeslock);
296 write_unlock(&file->f_owner.lock);
297 } 299 }
298 300
299 if (oplock & CIFS_CREATE_ACTION) { 301 if (oplock & CIFS_CREATE_ACTION) {
@@ -409,8 +411,8 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
409 CIFS_MOUNT_MAP_SPECIAL_CHR); 411 CIFS_MOUNT_MAP_SPECIAL_CHR);
410 if (rc) { 412 if (rc) {
411 up(&pCifsFile->fh_sem); 413 up(&pCifsFile->fh_sem);
412 cFYI(1, ("cifs_open returned 0x%x ", rc)); 414 cFYI(1, ("cifs_open returned 0x%x", rc));
413 cFYI(1, ("oplock: %d ", oplock)); 415 cFYI(1, ("oplock: %d", oplock));
414 } else { 416 } else {
415 pCifsFile->netfid = netfid; 417 pCifsFile->netfid = netfid;
416 pCifsFile->invalidHandle = FALSE; 418 pCifsFile->invalidHandle = FALSE;
@@ -472,7 +474,6 @@ int cifs_close(struct inode *inode, struct file *file)
472 pTcon = cifs_sb->tcon; 474 pTcon = cifs_sb->tcon;
473 if (pSMBFile) { 475 if (pSMBFile) {
474 pSMBFile->closePend = TRUE; 476 pSMBFile->closePend = TRUE;
475 write_lock(&file->f_owner.lock);
476 if (pTcon) { 477 if (pTcon) {
477 /* no sense reconnecting to close a file that is 478 /* no sense reconnecting to close a file that is
478 already closed */ 479 already closed */
@@ -487,23 +488,18 @@ int cifs_close(struct inode *inode, struct file *file)
487 the struct would be in each open file, 488 the struct would be in each open file,
488 but this should give enough time to 489 but this should give enough time to
489 clear the socket */ 490 clear the socket */
490 write_unlock(&file->f_owner.lock);
491 cERROR(1,("close with pending writes")); 491 cERROR(1,("close with pending writes"));
492 msleep(timeout); 492 msleep(timeout);
493 write_lock(&file->f_owner.lock);
494 timeout *= 4; 493 timeout *= 4;
495 } 494 }
496 write_unlock(&file->f_owner.lock);
497 rc = CIFSSMBClose(xid, pTcon, 495 rc = CIFSSMBClose(xid, pTcon,
498 pSMBFile->netfid); 496 pSMBFile->netfid);
499 write_lock(&file->f_owner.lock);
500 } 497 }
501 } 498 }
502 write_lock(&GlobalSMBSeslock); 499 write_lock(&GlobalSMBSeslock);
503 list_del(&pSMBFile->flist); 500 list_del(&pSMBFile->flist);
504 list_del(&pSMBFile->tlist); 501 list_del(&pSMBFile->tlist);
505 write_unlock(&GlobalSMBSeslock); 502 write_unlock(&GlobalSMBSeslock);
506 write_unlock(&file->f_owner.lock);
507 kfree(pSMBFile->search_resume_name); 503 kfree(pSMBFile->search_resume_name);
508 kfree(file->private_data); 504 kfree(file->private_data);
509 file->private_data = NULL; 505 file->private_data = NULL;
@@ -531,7 +527,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
531 (struct cifsFileInfo *)file->private_data; 527 (struct cifsFileInfo *)file->private_data;
532 char *ptmp; 528 char *ptmp;
533 529
534 cFYI(1, ("Closedir inode = 0x%p with ", inode)); 530 cFYI(1, ("Closedir inode = 0x%p", inode));
535 531
536 xid = GetXid(); 532 xid = GetXid();
537 533
@@ -605,7 +601,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
605 } 601 }
606 if (pfLock->fl_flags & FL_ACCESS) 602 if (pfLock->fl_flags & FL_ACCESS)
607 cFYI(1, ("Process suspended by mandatory locking - " 603 cFYI(1, ("Process suspended by mandatory locking - "
608 "not implemented yet ")); 604 "not implemented yet"));
609 if (pfLock->fl_flags & FL_LEASE) 605 if (pfLock->fl_flags & FL_LEASE)
610 cFYI(1, ("Lease on file - not implemented yet")); 606 cFYI(1, ("Lease on file - not implemented yet"));
611 if (pfLock->fl_flags & 607 if (pfLock->fl_flags &
@@ -1375,7 +1371,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1375 1371
1376 xid = GetXid(); 1372 xid = GetXid();
1377 1373
1378 cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 1374 cFYI(1, ("Sync file - name: %s datasync: 0x%x",
1379 dentry->d_name.name, datasync)); 1375 dentry->d_name.name, datasync));
1380 1376
1381 rc = filemap_fdatawrite(inode->i_mapping); 1377 rc = filemap_fdatawrite(inode->i_mapping);
@@ -1404,7 +1400,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1404/* fill in rpages then 1400/* fill in rpages then
1405 result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */ 1401 result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
1406 1402
1407/* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index)); 1403/* cFYI(1, ("rpages is %d for sync page of Index %ld", rpages, index));
1408 1404
1409#if 0 1405#if 0
1410 if (rc < 0) 1406 if (rc < 0)
@@ -1836,7 +1832,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
1836 if (rc < 0) 1832 if (rc < 0)
1837 goto io_error; 1833 goto io_error;
1838 else 1834 else
1839 cFYI(1, ("Bytes read %d ",rc)); 1835 cFYI(1, ("Bytes read %d",rc));
1840 1836
1841 file->f_dentry->d_inode->i_atime = 1837 file->f_dentry->d_inode->i_atime =
1842 current_fs_time(file->f_dentry->d_inode->i_sb); 1838 current_fs_time(file->f_dentry->d_inode->i_sb);
@@ -1946,7 +1942,7 @@ static int cifs_prepare_write(struct file *file, struct page *page,
1946 return 0; 1942 return 0;
1947} 1943}
1948 1944
1949struct address_space_operations cifs_addr_ops = { 1945const struct address_space_operations cifs_addr_ops = {
1950 .readpage = cifs_readpage, 1946 .readpage = cifs_readpage,
1951 .readpages = cifs_readpages, 1947 .readpages = cifs_readpages,
1952 .writepage = cifs_writepage, 1948 .writepage = cifs_writepage,
@@ -1957,3 +1953,19 @@ struct address_space_operations cifs_addr_ops = {
1957 /* .sync_page = cifs_sync_page, */ 1953 /* .sync_page = cifs_sync_page, */
1958 /* .direct_IO = */ 1954 /* .direct_IO = */
1959}; 1955};
1956
1957/*
1958 * cifs_readpages requires the server to support a buffer large enough to
1959 * contain the header plus one complete page of data. Otherwise, we need
1960 * to leave cifs_readpages out of the address space operations.
1961 */
1962const struct address_space_operations cifs_addr_ops_smallbuf = {
1963 .readpage = cifs_readpage,
1964 .writepage = cifs_writepage,
1965 .writepages = cifs_writepages,
1966 .prepare_write = cifs_prepare_write,
1967 .commit_write = cifs_commit_write,
1968 .set_page_dirty = __set_page_dirty_nobuffers,
1969 /* .sync_page = cifs_sync_page, */
1970 /* .direct_IO = */
1971};
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 4093764ef461..b88147c1dc27 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -41,7 +41,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
41 char *tmp_path; 41 char *tmp_path;
42 42
43 pTcon = cifs_sb->tcon; 43 pTcon = cifs_sb->tcon;
44 cFYI(1, ("Getting info on %s ", search_path)); 44 cFYI(1, ("Getting info on %s", search_path));
45 /* could have done a find first instead but this returns more info */ 45 /* could have done a find first instead but this returns more info */
46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, 46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -97,9 +97,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
97 inode = *pinode; 97 inode = *pinode;
98 cifsInfo = CIFS_I(inode); 98 cifsInfo = CIFS_I(inode);
99 99
100 cFYI(1, ("Old time %ld ", cifsInfo->time)); 100 cFYI(1, ("Old time %ld", cifsInfo->time));
101 cifsInfo->time = jiffies; 101 cifsInfo->time = jiffies;
102 cFYI(1, ("New time %ld ", cifsInfo->time)); 102 cFYI(1, ("New time %ld", cifsInfo->time));
103 /* this is ok to set on every inode revalidate */ 103 /* this is ok to set on every inode revalidate */
104 atomic_set(&cifsInfo->inUse,1); 104 atomic_set(&cifsInfo->inUse,1);
105 105
@@ -180,11 +180,12 @@ int cifs_get_inode_info_unix(struct inode **pinode,
180 else /* not direct, send byte range locks */ 180 else /* not direct, send byte range locks */
181 inode->i_fop = &cifs_file_ops; 181 inode->i_fop = &cifs_file_ops;
182 182
183 inode->i_data.a_ops = &cifs_addr_ops;
184 /* check if server can support readpages */ 183 /* check if server can support readpages */
185 if(pTcon->ses->server->maxBuf < 184 if(pTcon->ses->server->maxBuf <
186 4096 + MAX_CIFS_HDR_SIZE) 185 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
187 inode->i_data.a_ops->readpages = NULL; 186 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
187 else
188 inode->i_data.a_ops = &cifs_addr_ops;
188 } else if (S_ISDIR(inode->i_mode)) { 189 } else if (S_ISDIR(inode->i_mode)) {
189 cFYI(1, ("Directory inode")); 190 cFYI(1, ("Directory inode"));
190 inode->i_op = &cifs_dir_inode_ops; 191 inode->i_op = &cifs_dir_inode_ops;
@@ -421,23 +422,23 @@ int cifs_get_inode_info(struct inode **pinode,
421 inode = *pinode; 422 inode = *pinode;
422 cifsInfo = CIFS_I(inode); 423 cifsInfo = CIFS_I(inode);
423 cifsInfo->cifsAttrs = attr; 424 cifsInfo->cifsAttrs = attr;
424 cFYI(1, ("Old time %ld ", cifsInfo->time)); 425 cFYI(1, ("Old time %ld", cifsInfo->time));
425 cifsInfo->time = jiffies; 426 cifsInfo->time = jiffies;
426 cFYI(1, ("New time %ld ", cifsInfo->time)); 427 cFYI(1, ("New time %ld", cifsInfo->time));
427 428
428 /* blksize needs to be multiple of two. So safer to default to 429 /* blksize needs to be multiple of two. So safer to default to
429 blksize and blkbits set in superblock so 2**blkbits and blksize 430 blksize and blkbits set in superblock so 2**blkbits and blksize
430 will match rather than setting to: 431 will match rather than setting to:
431 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ 432 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
432 433
433 /* Linux can not store file creation time unfortunately so we ignore it */ 434 /* Linux can not store file creation time so ignore it */
434 inode->i_atime = 435 inode->i_atime =
435 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); 436 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
436 inode->i_mtime = 437 inode->i_mtime =
437 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); 438 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
438 inode->i_ctime = 439 inode->i_ctime =
439 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); 440 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
440 cFYI(0, ("Attributes came in as 0x%x ", attr)); 441 cFYI(0, ("Attributes came in as 0x%x", attr));
441 442
442 /* set default mode. will override for dirs below */ 443 /* set default mode. will override for dirs below */
443 if (atomic_read(&cifsInfo->inUse) == 0) 444 if (atomic_read(&cifsInfo->inUse) == 0)
@@ -519,10 +520,11 @@ int cifs_get_inode_info(struct inode **pinode,
519 else /* not direct, send byte range locks */ 520 else /* not direct, send byte range locks */
520 inode->i_fop = &cifs_file_ops; 521 inode->i_fop = &cifs_file_ops;
521 522
522 inode->i_data.a_ops = &cifs_addr_ops;
523 if(pTcon->ses->server->maxBuf < 523 if(pTcon->ses->server->maxBuf <
524 4096 + MAX_CIFS_HDR_SIZE) 524 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
525 inode->i_data.a_ops->readpages = NULL; 525 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
526 else
527 inode->i_data.a_ops = &cifs_addr_ops;
526 } else if (S_ISDIR(inode->i_mode)) { 528 } else if (S_ISDIR(inode->i_mode)) {
527 cFYI(1, ("Directory inode")); 529 cFYI(1, ("Directory inode"));
528 inode->i_op = &cifs_dir_inode_ops; 530 inode->i_op = &cifs_dir_inode_ops;
@@ -731,7 +733,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
731 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, 733 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
732 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 734 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
733 if (rc) { 735 if (rc) {
734 cFYI(1, ("cifs_mkdir returned 0x%x ", rc)); 736 cFYI(1, ("cifs_mkdir returned 0x%x", rc));
735 d_drop(direntry); 737 d_drop(direntry);
736 } else { 738 } else {
737 inode->i_nlink++; 739 inode->i_nlink++;
@@ -798,7 +800,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
798 char *full_path = NULL; 800 char *full_path = NULL;
799 struct cifsInodeInfo *cifsInode; 801 struct cifsInodeInfo *cifsInode;
800 802
801 cFYI(1, ("cifs_rmdir, inode = 0x%p with ", inode)); 803 cFYI(1, ("cifs_rmdir, inode = 0x%p", inode));
802 804
803 xid = GetXid(); 805 xid = GetXid();
804 806
@@ -1121,7 +1123,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1121 1123
1122 xid = GetXid(); 1124 xid = GetXid();
1123 1125
1124 cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x ", 1126 cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
1125 direntry->d_name.name, attrs->ia_valid)); 1127 direntry->d_name.name, attrs->ia_valid));
1126 1128
1127 cifs_sb = CIFS_SB(direntry->d_inode->i_sb); 1129 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
@@ -1157,6 +1159,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1157 when the local oplock break takes longer to flush 1159 when the local oplock break takes longer to flush
1158 writebehind data than the SMB timeout for the SetPathInfo 1160 writebehind data than the SMB timeout for the SetPathInfo
1159 request would allow */ 1161 request would allow */
1162
1160 open_file = find_writable_file(cifsInode); 1163 open_file = find_writable_file(cifsInode);
1161 if (open_file) { 1164 if (open_file) {
1162 __u16 nfid = open_file->netfid; 1165 __u16 nfid = open_file->netfid;
@@ -1289,7 +1292,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1289 it may be useful to Windows - but we do 1292 it may be useful to Windows - but we do
1290 not want to set ctime unless some other 1293 not want to set ctime unless some other
1291 timestamp is changing */ 1294 timestamp is changing */
1292 cFYI(1, ("CIFS - CTIME changed ")); 1295 cFYI(1, ("CIFS - CTIME changed"));
1293 time_buf.ChangeTime = 1296 time_buf.ChangeTime =
1294 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); 1297 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1295 } else 1298 } else
@@ -1356,7 +1359,7 @@ cifs_setattr_exit:
1356 1359
1357void cifs_delete_inode(struct inode *inode) 1360void cifs_delete_inode(struct inode *inode)
1358{ 1361{
1359 cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode)); 1362 cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode));
1360 /* may have to add back in if and when safe distributed caching of 1363 /* may have to add back in if and when safe distributed caching of
1361 directories added e.g. via FindNotify */ 1364 directories added e.g. via FindNotify */
1362} 1365}
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 2ec99f833142..a57f5d6e6213 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -167,7 +167,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
167 return -ENOMEM; 167 return -ENOMEM;
168 } 168 }
169 169
170 cFYI(1, ("Full path: %s ", full_path)); 170 cFYI(1, ("Full path: %s", full_path));
171 cFYI(1, ("symname is %s", symname)); 171 cFYI(1, ("symname is %s", symname));
172 172
173 /* BB what if DFS and this volume is on different share? BB */ 173 /* BB what if DFS and this volume is on different share? BB */
@@ -186,8 +186,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
186 inode->i_sb,xid); 186 inode->i_sb,xid);
187 187
188 if (rc != 0) { 188 if (rc != 0) {
189 cFYI(1, 189 cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",
190 ("Create symlink worked but get_inode_info failed with rc = %d ",
191 rc)); 190 rc));
192 } else { 191 } else {
193 if (pTcon->nocase) 192 if (pTcon->nocase)
@@ -289,7 +288,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
289 else { 288 else {
290 cFYI(1,("num referral: %d",num_referrals)); 289 cFYI(1,("num referral: %d",num_referrals));
291 if(referrals) { 290 if(referrals) {
292 cFYI(1,("referral string: %s ",referrals)); 291 cFYI(1,("referral string: %s",referrals));
293 strncpy(tmpbuffer, referrals, len-1); 292 strncpy(tmpbuffer, referrals, len-1);
294 } 293 }
295 } 294 }
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index fafd056426e4..22c937e5884f 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -101,6 +101,7 @@ sesInfoFree(struct cifsSesInfo *buf_to_free)
101 kfree(buf_to_free->serverDomain); 101 kfree(buf_to_free->serverDomain);
102 kfree(buf_to_free->serverNOS); 102 kfree(buf_to_free->serverNOS);
103 kfree(buf_to_free->password); 103 kfree(buf_to_free->password);
104 kfree(buf_to_free->domainName);
104 kfree(buf_to_free); 105 kfree(buf_to_free);
105} 106}
106 107
@@ -499,11 +500,12 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
499 if(pSMBr->ByteCount > sizeof(struct file_notify_information)) { 500 if(pSMBr->ByteCount > sizeof(struct file_notify_information)) {
500 data_offset = le32_to_cpu(pSMBr->DataOffset); 501 data_offset = le32_to_cpu(pSMBr->DataOffset);
501 502
502 pnotify = (struct file_notify_information *)((char *)&pSMBr->hdr.Protocol 503 pnotify = (struct file_notify_information *)
503 + data_offset); 504 ((char *)&pSMBr->hdr.Protocol + data_offset);
504 cFYI(1,("dnotify on %s with action: 0x%x",pnotify->FileName, 505 cFYI(1,("dnotify on %s Action: 0x%x",pnotify->FileName,
505 pnotify->Action)); /* BB removeme BB */ 506 pnotify->Action)); /* BB removeme BB */
506 /* cifs_dump_mem("Received notify Data is: ",buf,sizeof(struct smb_hdr)+60); */ 507 /* cifs_dump_mem("Rcvd notify Data: ",buf,
508 sizeof(struct smb_hdr)+60); */
507 return TRUE; 509 return TRUE;
508 } 510 }
509 if(pSMBr->hdr.Status.CifsError) { 511 if(pSMBr->hdr.Status.CifsError) {
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 5de74d216fdd..b66eff5dc624 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -84,11 +84,11 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
84 84
85static const struct smb_to_posix_error mapping_table_ERRSRV[] = { 85static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
86 {ERRerror, -EIO}, 86 {ERRerror, -EIO},
87 {ERRbadpw, -EPERM}, 87 {ERRbadpw, -EACCES}, /* was EPERM */
88 {ERRbadtype, -EREMOTE}, 88 {ERRbadtype, -EREMOTE},
89 {ERRaccess, -EACCES}, 89 {ERRaccess, -EACCES},
90 {ERRinvtid, -ENXIO}, 90 {ERRinvtid, -ENXIO},
91 {ERRinvnetname, -ENODEV}, 91 {ERRinvnetname, -ENXIO},
92 {ERRinvdevice, -ENXIO}, 92 {ERRinvdevice, -ENXIO},
93 {ERRqfull, -ENOSPC}, 93 {ERRqfull, -ENOSPC},
94 {ERRqtoobig, -ENOSPC}, 94 {ERRqtoobig, -ENOSPC},
diff --git a/fs/cifs/ntlmssp.c b/fs/cifs/ntlmssp.c
deleted file mode 100644
index 115359cc7a32..000000000000
--- a/fs/cifs/ntlmssp.c
+++ /dev/null
@@ -1,143 +0,0 @@
1/*
2 * fs/cifs/ntlmssp.h
3 *
4 * Copyright (c) International Business Machines Corp., 2006
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include "cifspdu.h"
23#include "cifsglob.h"
24#include "cifsproto.h"
25#include "cifs_unicode.h"
26#include "cifs_debug.h"
27#include "ntlmssp.h"
28#include "nterr.h"
29
30#ifdef CONFIG_CIFS_EXPERIMENTAL
31static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
32{
33 __u32 capabilities = 0;
34
35 /* init fields common to all four types of SessSetup */
36 /* note that header is initialized to zero in header_assemble */
37 pSMB->req.AndXCommand = 0xFF;
38 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
39 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
40
41 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
42
43 /* BB verify whether signing required on neg or just on auth frame
44 (and NTLM case) */
45
46 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
47 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
48
49 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
50 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
51
52 if (ses->capabilities & CAP_UNICODE) {
53 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
54 capabilities |= CAP_UNICODE;
55 }
56 if (ses->capabilities & CAP_STATUS32) {
57 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
58 capabilities |= CAP_STATUS32;
59 }
60 if (ses->capabilities & CAP_DFS) {
61 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
62 capabilities |= CAP_DFS;
63 }
64
65 /* BB check whether to init vcnum BB */
66 return capabilities;
67}
68int
69CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, const int type,
70 int * pNTLMv2_flg, const struct nls_table *nls_cp)
71{
72 int rc = 0;
73 int wct;
74 struct smb_hdr *smb_buffer;
75 char *bcc_ptr;
76 SESSION_SETUP_ANDX *pSMB;
77 __u32 capabilities;
78
79 if(ses == NULL)
80 return -EINVAL;
81
82 cFYI(1,("SStp type: %d",type));
83 if(type < CIFS_NTLM) {
84#ifndef CONFIG_CIFS_WEAK_PW_HASH
85 /* LANMAN and plaintext are less secure and off by default.
86 So we make this explicitly be turned on in kconfig (in the
87 build) and turned on at runtime (changed from the default)
88 in proc/fs/cifs or via mount parm. Unfortunately this is
89 needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
90 return -EOPNOTSUPP;
91#endif
92 wct = 10; /* lanman 2 style sessionsetup */
93 } else if(type < CIFS_NTLMSSP_NEG)
94 wct = 13; /* old style NTLM sessionsetup */
95 else /* same size for negotiate or auth, NTLMSSP or extended security */
96 wct = 12;
97
98 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
99 (void **)&smb_buffer);
100 if(rc)
101 return rc;
102
103 pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
104
105 capabilities = cifs_ssetup_hdr(ses, pSMB);
106 bcc_ptr = pByteArea(smb_buffer);
107 if(type > CIFS_NTLM) {
108 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
109 capabilities |= CAP_EXTENDED_SECURITY;
110 pSMB->req.Capabilities = cpu_to_le32(capabilities);
111 /* BB set password lengths */
112 } else if(type < CIFS_NTLM) /* lanman */ {
113 /* no capabilities flags in old lanman negotiation */
114 /* pSMB->old_req.PasswordLength = */ /* BB fixme BB */
115 } else /* type CIFS_NTLM */ {
116 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
117 pSMB->req_no_secext.CaseInsensitivePasswordLength =
118 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
119 pSMB->req_no_secext.CaseSensitivePasswordLength =
120 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
121 }
122
123
124 /* copy session key */
125
126 /* if Unicode, align strings to two byte boundary */
127
128 /* copy user name */ /* BB Do we need to special case null user name? */
129
130 /* copy domain name */
131
132 /* copy Linux version */
133
134 /* copy network operating system name */
135
136 /* update bcc and smb buffer length */
137
138/* rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buf_type, 0); */
139 /* SMB request buf freed in SendReceive2 */
140
141 return rc;
142}
143#endif /* CONFIG_CIFS_EXPERIMENTAL */
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index b689c5035124..03bbcb377913 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -21,6 +21,7 @@
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */ 22 */
23#include <linux/fs.h> 23#include <linux/fs.h>
24#include <linux/pagemap.h>
24#include <linux/stat.h> 25#include <linux/stat.h>
25#include <linux/smp_lock.h> 26#include <linux/smp_lock.h>
26#include "cifspdu.h" 27#include "cifspdu.h"
@@ -31,8 +32,8 @@
31#include "cifs_fs_sb.h" 32#include "cifs_fs_sb.h"
32#include "cifsfs.h" 33#include "cifsfs.h"
33 34
34/* BB fixme - add debug wrappers around this function to disable it fixme BB */ 35#ifdef CONFIG_CIFS_DEBUG2
35/* static void dump_cifs_file_struct(struct file *file, char *label) 36static void dump_cifs_file_struct(struct file *file, char *label)
36{ 37{
37 struct cifsFileInfo * cf; 38 struct cifsFileInfo * cf;
38 39
@@ -53,7 +54,8 @@
53 } 54 }
54 55
55 } 56 }
56} */ 57}
58#endif /* DEBUG2 */
57 59
58/* Returns one if new inode created (which therefore needs to be hashed) */ 60/* Returns one if new inode created (which therefore needs to be hashed) */
59/* Might check in the future if inode number changed so we can rehash inode */ 61/* Might check in the future if inode number changed so we can rehash inode */
@@ -107,32 +109,52 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
107 return rc; 109 return rc;
108} 110}
109 111
110static void fill_in_inode(struct inode *tmp_inode, 112static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
111 FILE_DIRECTORY_INFO *pfindData, int *pobject_type, int isNewInode) 113 char * buf, int *pobject_type, int isNewInode)
112{ 114{
113 loff_t local_size; 115 loff_t local_size;
114 struct timespec local_mtime; 116 struct timespec local_mtime;
115 117
116 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); 118 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
117 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); 119 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
118 __u32 attr = le32_to_cpu(pfindData->ExtFileAttributes); 120 __u32 attr;
119 __u64 allocation_size = le64_to_cpu(pfindData->AllocationSize); 121 __u64 allocation_size;
120 __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile); 122 __u64 end_of_file;
121
122 cifsInfo->cifsAttrs = attr;
123 cifsInfo->time = jiffies;
124 123
125 /* save mtime and size */ 124 /* save mtime and size */
126 local_mtime = tmp_inode->i_mtime; 125 local_mtime = tmp_inode->i_mtime;
127 local_size = tmp_inode->i_size; 126 local_size = tmp_inode->i_size;
128 127
128 if(new_buf_type) {
129 FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf;
130
131 attr = le32_to_cpu(pfindData->ExtFileAttributes);
132 allocation_size = le64_to_cpu(pfindData->AllocationSize);
133 end_of_file = le64_to_cpu(pfindData->EndOfFile);
134 tmp_inode->i_atime =
135 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
136 tmp_inode->i_mtime =
137 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
138 tmp_inode->i_ctime =
139 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
140 } else { /* legacy, OS2 and DOS style */
141 FIND_FILE_STANDARD_INFO * pfindData =
142 (FIND_FILE_STANDARD_INFO *)buf;
143
144 attr = le16_to_cpu(pfindData->Attributes);
145 allocation_size = le32_to_cpu(pfindData->AllocationSize);
146 end_of_file = le32_to_cpu(pfindData->DataSize);
147 tmp_inode->i_atime = CURRENT_TIME;
148 /* tmp_inode->i_mtime = BB FIXME - add dos time handling
149 tmp_inode->i_ctime = 0; BB FIXME */
150
151 }
152
129 /* Linux can not store file creation time unfortunately so ignore it */ 153 /* Linux can not store file creation time unfortunately so ignore it */
130 tmp_inode->i_atime = 154
131 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); 155 cifsInfo->cifsAttrs = attr;
132 tmp_inode->i_mtime = 156 cifsInfo->time = jiffies;
133 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); 157
134 tmp_inode->i_ctime =
135 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
136 /* treat dos attribute of read-only as read-only mode bit e.g. 555? */ 158 /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
137 /* 2767 perms - indicate mandatory locking */ 159 /* 2767 perms - indicate mandatory locking */
138 /* BB fill in uid and gid here? with help from winbind? 160 /* BB fill in uid and gid here? with help from winbind?
@@ -215,11 +237,13 @@ static void fill_in_inode(struct inode *tmp_inode,
215 else 237 else
216 tmp_inode->i_fop = &cifs_file_ops; 238 tmp_inode->i_fop = &cifs_file_ops;
217 239
218 tmp_inode->i_data.a_ops = &cifs_addr_ops;
219 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && 240 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
220 (cifs_sb->tcon->ses->server->maxBuf < 241 (cifs_sb->tcon->ses->server->maxBuf <
221 4096 + MAX_CIFS_HDR_SIZE)) 242 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
222 tmp_inode->i_data.a_ops->readpages = NULL; 243 tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
244 else
245 tmp_inode->i_data.a_ops = &cifs_addr_ops;
246
223 if(isNewInode) 247 if(isNewInode)
224 return; /* No sense invalidating pages for new inode 248 return; /* No sense invalidating pages for new inode
225 since have not started caching readahead file 249 since have not started caching readahead file
@@ -338,11 +362,12 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
338 else 362 else
339 tmp_inode->i_fop = &cifs_file_ops; 363 tmp_inode->i_fop = &cifs_file_ops;
340 364
341 tmp_inode->i_data.a_ops = &cifs_addr_ops;
342 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && 365 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
343 (cifs_sb->tcon->ses->server->maxBuf < 366 (cifs_sb->tcon->ses->server->maxBuf <
344 4096 + MAX_CIFS_HDR_SIZE)) 367 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
345 tmp_inode->i_data.a_ops->readpages = NULL; 368 tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
369 else
370 tmp_inode->i_data.a_ops = &cifs_addr_ops;
346 371
347 if(isNewInode) 372 if(isNewInode)
348 return; /* No sense invalidating pages for new inode since we 373 return; /* No sense invalidating pages for new inode since we
@@ -415,7 +440,10 @@ static int initiate_cifs_search(const int xid, struct file *file)
415ffirst_retry: 440ffirst_retry:
416 /* test for Unix extensions */ 441 /* test for Unix extensions */
417 if (pTcon->ses->capabilities & CAP_UNIX) { 442 if (pTcon->ses->capabilities & CAP_UNIX) {
418 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; 443 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
444 } else if ((pTcon->ses->capabilities &
445 (CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
446 cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
419 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 447 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
420 cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO; 448 cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
421 } else /* not srvinos - BB fixme add check for backlevel? */ { 449 } else /* not srvinos - BB fixme add check for backlevel? */ {
@@ -451,12 +479,19 @@ static int cifs_unicode_bytelen(char *str)
451 return len << 1; 479 return len << 1;
452} 480}
453 481
454static char *nxt_dir_entry(char *old_entry, char *end_of_smb) 482static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
455{ 483{
456 char * new_entry; 484 char * new_entry;
457 FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry; 485 FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
458 486
459 new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset); 487 if(level == SMB_FIND_FILE_INFO_STANDARD) {
488 FIND_FILE_STANDARD_INFO * pfData;
489 pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo;
490
491 new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
492 pfData->FileNameLength;
493 } else
494 new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
460 cFYI(1,("new entry %p old entry %p",new_entry,old_entry)); 495 cFYI(1,("new entry %p old entry %p",new_entry,old_entry));
461 /* validate that new_entry is not past end of SMB */ 496 /* validate that new_entry is not past end of SMB */
462 if(new_entry >= end_of_smb) { 497 if(new_entry >= end_of_smb) {
@@ -464,7 +499,10 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb)
464 ("search entry %p began after end of SMB %p old entry %p", 499 ("search entry %p began after end of SMB %p old entry %p",
465 new_entry, end_of_smb, old_entry)); 500 new_entry, end_of_smb, old_entry));
466 return NULL; 501 return NULL;
467 } else if (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb) { 502 } else if(((level == SMB_FIND_FILE_INFO_STANDARD) &&
503 (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) ||
504 ((level != SMB_FIND_FILE_INFO_STANDARD) &&
505 (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
468 cERROR(1,("search entry %p extends after end of SMB %p", 506 cERROR(1,("search entry %p extends after end of SMB %p",
469 new_entry, end_of_smb)); 507 new_entry, end_of_smb));
470 return NULL; 508 return NULL;
@@ -482,7 +520,7 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
482 char * filename = NULL; 520 char * filename = NULL;
483 int len = 0; 521 int len = 0;
484 522
485 if(cfile->srch_inf.info_level == 0x202) { 523 if(cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
486 FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry; 524 FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
487 filename = &pFindData->FileName[0]; 525 filename = &pFindData->FileName[0];
488 if(cfile->srch_inf.unicode) { 526 if(cfile->srch_inf.unicode) {
@@ -491,26 +529,34 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
491 /* BB should we make this strnlen of PATH_MAX? */ 529 /* BB should we make this strnlen of PATH_MAX? */
492 len = strnlen(filename, 5); 530 len = strnlen(filename, 5);
493 } 531 }
494 } else if(cfile->srch_inf.info_level == 0x101) { 532 } else if(cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
495 FILE_DIRECTORY_INFO * pFindData = 533 FILE_DIRECTORY_INFO * pFindData =
496 (FILE_DIRECTORY_INFO *)current_entry; 534 (FILE_DIRECTORY_INFO *)current_entry;
497 filename = &pFindData->FileName[0]; 535 filename = &pFindData->FileName[0];
498 len = le32_to_cpu(pFindData->FileNameLength); 536 len = le32_to_cpu(pFindData->FileNameLength);
499 } else if(cfile->srch_inf.info_level == 0x102) { 537 } else if(cfile->srch_inf.info_level ==
538 SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
500 FILE_FULL_DIRECTORY_INFO * pFindData = 539 FILE_FULL_DIRECTORY_INFO * pFindData =
501 (FILE_FULL_DIRECTORY_INFO *)current_entry; 540 (FILE_FULL_DIRECTORY_INFO *)current_entry;
502 filename = &pFindData->FileName[0]; 541 filename = &pFindData->FileName[0];
503 len = le32_to_cpu(pFindData->FileNameLength); 542 len = le32_to_cpu(pFindData->FileNameLength);
504 } else if(cfile->srch_inf.info_level == 0x105) { 543 } else if(cfile->srch_inf.info_level ==
544 SMB_FIND_FILE_ID_FULL_DIR_INFO) {
505 SEARCH_ID_FULL_DIR_INFO * pFindData = 545 SEARCH_ID_FULL_DIR_INFO * pFindData =
506 (SEARCH_ID_FULL_DIR_INFO *)current_entry; 546 (SEARCH_ID_FULL_DIR_INFO *)current_entry;
507 filename = &pFindData->FileName[0]; 547 filename = &pFindData->FileName[0];
508 len = le32_to_cpu(pFindData->FileNameLength); 548 len = le32_to_cpu(pFindData->FileNameLength);
509 } else if(cfile->srch_inf.info_level == 0x104) { 549 } else if(cfile->srch_inf.info_level ==
550 SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
510 FILE_BOTH_DIRECTORY_INFO * pFindData = 551 FILE_BOTH_DIRECTORY_INFO * pFindData =
511 (FILE_BOTH_DIRECTORY_INFO *)current_entry; 552 (FILE_BOTH_DIRECTORY_INFO *)current_entry;
512 filename = &pFindData->FileName[0]; 553 filename = &pFindData->FileName[0];
513 len = le32_to_cpu(pFindData->FileNameLength); 554 len = le32_to_cpu(pFindData->FileNameLength);
555 } else if(cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) {
556 FIND_FILE_STANDARD_INFO * pFindData =
557 (FIND_FILE_STANDARD_INFO *)current_entry;
558 filename = &pFindData->FileName[0];
559 len = le32_to_cpu(pFindData->FileNameLength);
514 } else { 560 } else {
515 cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level)); 561 cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
516 } 562 }
@@ -597,7 +643,9 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
597 . and .. for the root of a drive and for those we need 643 . and .. for the root of a drive and for those we need
598 to start two entries earlier */ 644 to start two entries earlier */
599 645
600/* dump_cifs_file_struct(file, "In fce ");*/ 646#ifdef CONFIG_CIFS_DEBUG2
647 dump_cifs_file_struct(file, "In fce ");
648#endif
601 if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) && 649 if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
602 is_dir_changed(file)) || 650 is_dir_changed(file)) ||
603 (index_to_find < first_entry_in_buffer)) { 651 (index_to_find < first_entry_in_buffer)) {
@@ -644,10 +692,12 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
644 first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry 692 first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
645 - cifsFile->srch_inf.entries_in_buffer; 693 - cifsFile->srch_inf.entries_in_buffer;
646 pos_in_buf = index_to_find - first_entry_in_buffer; 694 pos_in_buf = index_to_find - first_entry_in_buffer;
647 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); 695 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
696
648 for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) { 697 for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
649 /* go entry by entry figuring out which is first */ 698 /* go entry by entry figuring out which is first */
650 current_entry = nxt_dir_entry(current_entry,end_of_smb); 699 current_entry = nxt_dir_entry(current_entry,end_of_smb,
700 cifsFile->srch_inf.info_level);
651 } 701 }
652 if((current_entry == NULL) && (i < pos_in_buf)) { 702 if((current_entry == NULL) && (i < pos_in_buf)) {
653 /* BB fixme - check if we should flag this error */ 703 /* BB fixme - check if we should flag this error */
@@ -674,7 +724,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
674/* inode num, inode type and filename returned */ 724/* inode num, inode type and filename returned */
675static int cifs_get_name_from_search_buf(struct qstr *pqst, 725static int cifs_get_name_from_search_buf(struct qstr *pqst,
676 char *current_entry, __u16 level, unsigned int unicode, 726 char *current_entry, __u16 level, unsigned int unicode,
677 struct cifs_sb_info * cifs_sb, ino_t *pinum) 727 struct cifs_sb_info * cifs_sb, int max_len, ino_t *pinum)
678{ 728{
679 int rc = 0; 729 int rc = 0;
680 unsigned int len = 0; 730 unsigned int len = 0;
@@ -718,10 +768,22 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
718 (FILE_BOTH_DIRECTORY_INFO *)current_entry; 768 (FILE_BOTH_DIRECTORY_INFO *)current_entry;
719 filename = &pFindData->FileName[0]; 769 filename = &pFindData->FileName[0];
720 len = le32_to_cpu(pFindData->FileNameLength); 770 len = le32_to_cpu(pFindData->FileNameLength);
771 } else if(level == SMB_FIND_FILE_INFO_STANDARD) {
772 FIND_FILE_STANDARD_INFO * pFindData =
773 (FIND_FILE_STANDARD_INFO *)current_entry;
774 filename = &pFindData->FileName[0];
775 /* one byte length, no name conversion */
776 len = (unsigned int)pFindData->FileNameLength;
721 } else { 777 } else {
722 cFYI(1,("Unknown findfirst level %d",level)); 778 cFYI(1,("Unknown findfirst level %d",level));
723 return -EINVAL; 779 return -EINVAL;
724 } 780 }
781
782 if(len > max_len) {
783 cERROR(1,("bad search response length %d past smb end", len));
784 return -EINVAL;
785 }
786
725 if(unicode) { 787 if(unicode) {
726 /* BB fixme - test with long names */ 788 /* BB fixme - test with long names */
727 /* Note converted filename can be longer than in unicode */ 789 /* Note converted filename can be longer than in unicode */
@@ -741,7 +803,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
741} 803}
742 804
743static int cifs_filldir(char *pfindEntry, struct file *file, 805static int cifs_filldir(char *pfindEntry, struct file *file,
744 filldir_t filldir, void *direntry, char *scratch_buf) 806 filldir_t filldir, void *direntry, char *scratch_buf, int max_len)
745{ 807{
746 int rc = 0; 808 int rc = 0;
747 struct qstr qstring; 809 struct qstr qstring;
@@ -777,6 +839,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
777 rc = cifs_get_name_from_search_buf(&qstring,pfindEntry, 839 rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
778 pCifsF->srch_inf.info_level, 840 pCifsF->srch_inf.info_level,
779 pCifsF->srch_inf.unicode,cifs_sb, 841 pCifsF->srch_inf.unicode,cifs_sb,
842 max_len,
780 &inum /* returned */); 843 &inum /* returned */);
781 844
782 if(rc) 845 if(rc)
@@ -798,13 +861,16 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
798 /* we pass in rc below, indicating whether it is a new inode, 861 /* we pass in rc below, indicating whether it is a new inode,
799 so we can figure out whether to invalidate the inode cached 862 so we can figure out whether to invalidate the inode cached
800 data if the file has changed */ 863 data if the file has changed */
801 if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) { 864 if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
802 unix_fill_in_inode(tmp_inode, 865 unix_fill_in_inode(tmp_inode,
803 (FILE_UNIX_INFO *)pfindEntry,&obj_type, rc); 866 (FILE_UNIX_INFO *)pfindEntry,
804 } else { 867 &obj_type, rc);
805 fill_in_inode(tmp_inode, 868 else if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
806 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc); 869 fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */,
807 } 870 pfindEntry, &obj_type, rc);
871 else
872 fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc);
873
808 874
809 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos, 875 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,
810 tmp_inode->i_ino,obj_type); 876 tmp_inode->i_ino,obj_type);
@@ -864,6 +930,12 @@ static int cifs_save_resume_key(const char *current_entry,
864 filename = &pFindData->FileName[0]; 930 filename = &pFindData->FileName[0];
865 len = le32_to_cpu(pFindData->FileNameLength); 931 len = le32_to_cpu(pFindData->FileNameLength);
866 cifsFile->srch_inf.resume_key = pFindData->FileIndex; 932 cifsFile->srch_inf.resume_key = pFindData->FileIndex;
933 } else if(level == SMB_FIND_FILE_INFO_STANDARD) {
934 FIND_FILE_STANDARD_INFO * pFindData =
935 (FIND_FILE_STANDARD_INFO *)current_entry;
936 filename = &pFindData->FileName[0];
937 /* one byte length, no name conversion */
938 len = (unsigned int)pFindData->FileNameLength;
867 } else { 939 } else {
868 cFYI(1,("Unknown findfirst level %d",level)); 940 cFYI(1,("Unknown findfirst level %d",level));
869 return -EINVAL; 941 return -EINVAL;
@@ -884,6 +956,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
884 int num_to_fill = 0; 956 int num_to_fill = 0;
885 char * tmp_buf = NULL; 957 char * tmp_buf = NULL;
886 char * end_of_smb; 958 char * end_of_smb;
959 int max_len;
887 960
888 xid = GetXid(); 961 xid = GetXid();
889 962
@@ -909,7 +982,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
909 case 1: 982 case 1:
910 if (filldir(direntry, "..", 2, file->f_pos, 983 if (filldir(direntry, "..", 2, file->f_pos,
911 file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { 984 file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
912 cERROR(1, ("Filldir for parent dir failed ")); 985 cERROR(1, ("Filldir for parent dir failed"));
913 rc = -ENOMEM; 986 rc = -ENOMEM;
914 break; 987 break;
915 } 988 }
@@ -959,10 +1032,11 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
959 goto rddir2_exit; 1032 goto rddir2_exit;
960 } 1033 }
961 cFYI(1,("loop through %d times filling dir for net buf %p", 1034 cFYI(1,("loop through %d times filling dir for net buf %p",
962 num_to_fill,cifsFile->srch_inf.ntwrk_buf_start)); 1035 num_to_fill,cifsFile->srch_inf.ntwrk_buf_start));
963 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + 1036 max_len = smbCalcSize((struct smb_hdr *)
964 smbCalcSize((struct smb_hdr *) 1037 cifsFile->srch_inf.ntwrk_buf_start);
965 cifsFile->srch_inf.ntwrk_buf_start); 1038 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
1039
966 /* To be safe - for UCS to UTF-8 with strings loaded 1040 /* To be safe - for UCS to UTF-8 with strings loaded
967 with the rare long characters alloc more to account for 1041 with the rare long characters alloc more to account for
968 such multibyte target UTF-8 characters. cifs_unicode.c, 1042 such multibyte target UTF-8 characters. cifs_unicode.c,
@@ -977,17 +1051,19 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
977 } 1051 }
978 /* if buggy server returns . and .. late do 1052 /* if buggy server returns . and .. late do
979 we want to check for that here? */ 1053 we want to check for that here? */
980 rc = cifs_filldir(current_entry, file, 1054 rc = cifs_filldir(current_entry, file,
981 filldir, direntry,tmp_buf); 1055 filldir, direntry, tmp_buf, max_len);
982 file->f_pos++; 1056 file->f_pos++;
983 if(file->f_pos == cifsFile->srch_inf.index_of_last_entry) { 1057 if(file->f_pos ==
1058 cifsFile->srch_inf.index_of_last_entry) {
984 cFYI(1,("last entry in buf at pos %lld %s", 1059 cFYI(1,("last entry in buf at pos %lld %s",
985 file->f_pos,tmp_buf)); /* BB removeme BB */ 1060 file->f_pos,tmp_buf));
986 cifs_save_resume_key(current_entry,cifsFile); 1061 cifs_save_resume_key(current_entry,cifsFile);
987 break; 1062 break;
988 } else 1063 } else
989 current_entry = nxt_dir_entry(current_entry, 1064 current_entry =
990 end_of_smb); 1065 nxt_dir_entry(current_entry, end_of_smb,
1066 cifsFile->srch_inf.info_level);
991 } 1067 }
992 kfree(tmp_buf); 1068 kfree(tmp_buf);
993 break; 1069 break;
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
new file mode 100644
index 000000000000..7202d534ef0b
--- /dev/null
+++ b/fs/cifs/sess.c
@@ -0,0 +1,538 @@
1/*
2 * fs/cifs/sess.c
3 *
4 * SMB/CIFS session setup handling routines
5 *
6 * Copyright (c) International Business Machines Corp., 2006
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include "cifspdu.h"
25#include "cifsglob.h"
26#include "cifsproto.h"
27#include "cifs_unicode.h"
28#include "cifs_debug.h"
29#include "ntlmssp.h"
30#include "nterr.h"
31#include <linux/utsname.h>
32
33extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
34 unsigned char *p24);
35
36static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
37{
38 __u32 capabilities = 0;
39
40 /* init fields common to all four types of SessSetup */
41 /* note that header is initialized to zero in header_assemble */
42 pSMB->req.AndXCommand = 0xFF;
43 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
44 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
45
46 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
47
48 /* BB verify whether signing required on neg or just on auth frame
49 (and NTLM case) */
50
51 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
52 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
53
54 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
55 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
56
57 if (ses->capabilities & CAP_UNICODE) {
58 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
59 capabilities |= CAP_UNICODE;
60 }
61 if (ses->capabilities & CAP_STATUS32) {
62 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
63 capabilities |= CAP_STATUS32;
64 }
65 if (ses->capabilities & CAP_DFS) {
66 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
67 capabilities |= CAP_DFS;
68 }
69 if (ses->capabilities & CAP_UNIX) {
70 capabilities |= CAP_UNIX;
71 }
72
73 /* BB check whether to init vcnum BB */
74 return capabilities;
75}
76
77static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
78 const struct nls_table * nls_cp)
79{
80 char * bcc_ptr = *pbcc_area;
81 int bytes_ret = 0;
82
83 /* BB FIXME add check that strings total less
84 than 335 or will need to send them as arrays */
85
86 /* unicode strings, must be word aligned before the call */
87/* if ((long) bcc_ptr % 2) {
88 *bcc_ptr = 0;
89 bcc_ptr++;
90 } */
91 /* copy user */
92 if(ses->userName == NULL) {
93 /* BB what about null user mounts - check that we do this BB */
94 } else { /* 300 should be long enough for any conceivable user name */
95 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
96 300, nls_cp);
97 }
98 bcc_ptr += 2 * bytes_ret;
99 bcc_ptr += 2; /* account for null termination */
100 /* copy domain */
101 if(ses->domainName == NULL)
102 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr,
103 "CIFS_LINUX_DOM", 32, nls_cp);
104 else
105 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
106 256, nls_cp);
107 bcc_ptr += 2 * bytes_ret;
108 bcc_ptr += 2; /* account for null terminator */
109
110 /* Copy OS version */
111 bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
112 nls_cp);
113 bcc_ptr += 2 * bytes_ret;
114 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
115 32, nls_cp);
116 bcc_ptr += 2 * bytes_ret;
117 bcc_ptr += 2; /* trailing null */
118
119 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
120 32, nls_cp);
121 bcc_ptr += 2 * bytes_ret;
122 bcc_ptr += 2; /* trailing null */
123
124 *pbcc_area = bcc_ptr;
125}
126
127static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
128 const struct nls_table * nls_cp)
129{
130 char * bcc_ptr = *pbcc_area;
131
132 /* copy user */
133 /* BB what about null user mounts - check that we do this BB */
134 /* copy user */
135 if(ses->userName == NULL) {
136 /* BB what about null user mounts - check that we do this BB */
137 } else { /* 300 should be long enough for any conceivable user name */
138 strncpy(bcc_ptr, ses->userName, 300);
139 }
140 /* BB improve check for overflow */
141 bcc_ptr += strnlen(ses->userName, 300);
142 *bcc_ptr = 0;
143 bcc_ptr++; /* account for null termination */
144
145 /* copy domain */
146
147 if(ses->domainName == NULL) {
148 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
149 bcc_ptr += 14; /* strlen(CIFS_LINUX_DOM) */
150 } else {
151 strncpy(bcc_ptr, ses->domainName, 256);
152 bcc_ptr += strnlen(ses->domainName, 256);
153 }
154 *bcc_ptr = 0;
155 bcc_ptr++;
156
157 /* BB check for overflow here */
158
159 strcpy(bcc_ptr, "Linux version ");
160 bcc_ptr += strlen("Linux version ");
161 strcpy(bcc_ptr, system_utsname.release);
162 bcc_ptr += strlen(system_utsname.release) + 1;
163
164 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
165 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
166
167 *pbcc_area = bcc_ptr;
168}
169
170static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
171 const struct nls_table * nls_cp)
172{
173 int rc = 0;
174 int words_left, len;
175 char * data = *pbcc_area;
176
177
178
179 cFYI(1,("bleft %d",bleft));
180
181
182 /* word align, if bytes remaining is not even */
183 if(bleft % 2) {
184 bleft--;
185 data++;
186 }
187 words_left = bleft / 2;
188
189 /* save off server operating system */
190 len = UniStrnlen((wchar_t *) data, words_left);
191
192/* We look for obvious messed up bcc or strings in response so we do not go off
193 the end since (at least) WIN2K and Windows XP have a major bug in not null
194 terminating last Unicode string in response */
195 if(len >= words_left)
196 return rc;
197
198 if(ses->serverOS)
199 kfree(ses->serverOS);
200 /* UTF-8 string will not grow more than four times as big as UCS-16 */
201 ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
202 if(ses->serverOS != NULL) {
203 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
204 nls_cp);
205 }
206 data += 2 * (len + 1);
207 words_left -= len + 1;
208
209 /* save off server network operating system */
210 len = UniStrnlen((wchar_t *) data, words_left);
211
212 if(len >= words_left)
213 return rc;
214
215 if(ses->serverNOS)
216 kfree(ses->serverNOS);
217 ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
218 if(ses->serverNOS != NULL) {
219 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
220 nls_cp);
221 if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) {
222 cFYI(1,("NT4 server"));
223 ses->flags |= CIFS_SES_NT4;
224 }
225 }
226 data += 2 * (len + 1);
227 words_left -= len + 1;
228
229 /* save off server domain */
230 len = UniStrnlen((wchar_t *) data, words_left);
231
232 if(len > words_left)
233 return rc;
234
235 if(ses->serverDomain)
236 kfree(ses->serverDomain);
237 ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
238 if(ses->serverDomain != NULL) {
239 cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
240 nls_cp);
241 ses->serverDomain[2*len] = 0;
242 ses->serverDomain[(2*len) + 1] = 0;
243 }
244 data += 2 * (len + 1);
245 words_left -= len + 1;
246
247 cFYI(1,("words left: %d",words_left));
248
249 return rc;
250}
251
252static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
253 const struct nls_table * nls_cp)
254{
255 int rc = 0;
256 int len;
257 char * bcc_ptr = *pbcc_area;
258
259 cFYI(1,("decode sessetup ascii. bleft %d", bleft));
260
261 len = strnlen(bcc_ptr, bleft);
262 if(len >= bleft)
263 return rc;
264
265 if(ses->serverOS)
266 kfree(ses->serverOS);
267
268 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
269 if(ses->serverOS)
270 strncpy(ses->serverOS, bcc_ptr, len);
271
272 bcc_ptr += len + 1;
273 bleft -= len + 1;
274
275 len = strnlen(bcc_ptr, bleft);
276 if(len >= bleft)
277 return rc;
278
279 if(ses->serverNOS)
280 kfree(ses->serverNOS);
281
282 ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
283 if(ses->serverNOS)
284 strncpy(ses->serverNOS, bcc_ptr, len);
285
286 bcc_ptr += len + 1;
287 bleft -= len + 1;
288
289 len = strnlen(bcc_ptr, bleft);
290 if(len > bleft)
291 return rc;
292
293 if(ses->serverDomain)
294 kfree(ses->serverDomain);
295
296 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
297 if(ses->serverOS)
298 strncpy(ses->serverOS, bcc_ptr, len);
299
300 bcc_ptr += len + 1;
301 bleft -= len + 1;
302
303 cFYI(1,("ascii: bytes left %d",bleft));
304
305 return rc;
306}
307
308int
309CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
310 const struct nls_table *nls_cp)
311{
312 int rc = 0;
313 int wct;
314 struct smb_hdr *smb_buf;
315 char *bcc_ptr;
316 char *str_area;
317 SESSION_SETUP_ANDX *pSMB;
318 __u32 capabilities;
319 int count;
320 int resp_buf_type = 0;
321 struct kvec iov[2];
322 enum securityEnum type;
323 __u16 action;
324 int bytes_remaining;
325
326 if(ses == NULL)
327 return -EINVAL;
328
329 type = ses->server->secType;
330
331 cFYI(1,("sess setup type %d",type));
332 if(type == LANMAN) {
333#ifndef CONFIG_CIFS_WEAK_PW_HASH
334 /* LANMAN and plaintext are less secure and off by default.
335 So we make this explicitly be turned on in kconfig (in the
336 build) and turned on at runtime (changed from the default)
337 in proc/fs/cifs or via mount parm. Unfortunately this is
338 needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
339 return -EOPNOTSUPP;
340#endif
341 wct = 10; /* lanman 2 style sessionsetup */
342 } else if((type == NTLM) || (type == NTLMv2)) {
343 /* For NTLMv2 failures eventually may need to retry NTLM */
344 wct = 13; /* old style NTLM sessionsetup */
345 } else /* same size for negotiate or auth, NTLMSSP or extended security */
346 wct = 12;
347
348 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
349 (void **)&smb_buf);
350 if(rc)
351 return rc;
352
353 pSMB = (SESSION_SETUP_ANDX *)smb_buf;
354
355 capabilities = cifs_ssetup_hdr(ses, pSMB);
356
357 /* we will send the SMB in two pieces,
358 a fixed length beginning part, and a
359 second part which will include the strings
360 and rest of bcc area, in order to avoid having
361 to do a large buffer 17K allocation */
362 iov[0].iov_base = (char *)pSMB;
363 iov[0].iov_len = smb_buf->smb_buf_length + 4;
364
365 /* 2000 big enough to fit max user, domain, NOS name etc. */
366 str_area = kmalloc(2000, GFP_KERNEL);
367 bcc_ptr = str_area;
368
369 if(type == LANMAN) {
370#ifdef CONFIG_CIFS_WEAK_PW_HASH
371 char lnm_session_key[CIFS_SESS_KEY_SIZE];
372
373 /* no capabilities flags in old lanman negotiation */
374
375 pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE;
376 /* BB calculate hash with password */
377 /* and copy into bcc */
378
379 calc_lanman_hash(ses, lnm_session_key);
380
381/* #ifdef CONFIG_CIFS_DEBUG2
382 cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
383 CIFS_SESS_KEY_SIZE);
384#endif */
385 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
386 bcc_ptr += CIFS_SESS_KEY_SIZE;
387
388 /* can not sign if LANMAN negotiated so no need
389 to calculate signing key? but what if server
390 changed to do higher than lanman dialect and
391 we reconnected would we ever calc signing_key? */
392
393 cFYI(1,("Negotiating LANMAN setting up strings"));
394 /* Unicode not allowed for LANMAN dialects */
395 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
396#endif
397 } else if (type == NTLM) {
398 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
399
400 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
401 pSMB->req_no_secext.CaseInsensitivePasswordLength =
402 cpu_to_le16(CIFS_SESS_KEY_SIZE);
403 pSMB->req_no_secext.CaseSensitivePasswordLength =
404 cpu_to_le16(CIFS_SESS_KEY_SIZE);
405
406 /* calculate session key */
407 SMBNTencrypt(ses->password, ses->server->cryptKey,
408 ntlm_session_key);
409
410 if(first_time) /* should this be moved into common code
411 with similar ntlmv2 path? */
412 cifs_calculate_mac_key(ses->server->mac_signing_key,
413 ntlm_session_key, ses->password);
414 /* copy session key */
415
416 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
417 bcc_ptr += CIFS_SESS_KEY_SIZE;
418 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
419 bcc_ptr += CIFS_SESS_KEY_SIZE;
420 if(ses->capabilities & CAP_UNICODE) {
421 /* unicode strings must be word aligned */
422 if (iov[0].iov_len % 2) {
423 *bcc_ptr = 0;
424 bcc_ptr++;
425 }
426 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
427 } else
428 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
429 } else if (type == NTLMv2) {
430 char * v2_sess_key =
431 kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
432
433 /* BB FIXME change all users of v2_sess_key to
434 struct ntlmv2_resp */
435
436 if(v2_sess_key == NULL) {
437 cifs_small_buf_release(smb_buf);
438 return -ENOMEM;
439 }
440
441 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
442
443 /* LM2 password would be here if we supported it */
444 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
445 /* cpu_to_le16(LM2_SESS_KEY_SIZE); */
446
447 pSMB->req_no_secext.CaseSensitivePasswordLength =
448 cpu_to_le16(sizeof(struct ntlmv2_resp));
449
450 /* calculate session key */
451 setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
452 if(first_time) /* should this be moved into common code
453 with similar ntlmv2 path? */
454 /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
455 response BB FIXME, v2_sess_key); */
456
457 /* copy session key */
458
459 /* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
460 bcc_ptr += LM2_SESS_KEY_SIZE; */
461 memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp));
462 bcc_ptr += sizeof(struct ntlmv2_resp);
463 kfree(v2_sess_key);
464 if(ses->capabilities & CAP_UNICODE) {
465 if(iov[0].iov_len % 2) {
466 *bcc_ptr = 0;
467 } bcc_ptr++;
468 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
469 } else
470 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
471 } else /* NTLMSSP or SPNEGO */ {
472 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
473 capabilities |= CAP_EXTENDED_SECURITY;
474 pSMB->req.Capabilities = cpu_to_le32(capabilities);
475 /* BB set password lengths */
476 }
477
478 count = (long) bcc_ptr - (long) str_area;
479 smb_buf->smb_buf_length += count;
480
481 BCC_LE(smb_buf) = cpu_to_le16(count);
482
483 iov[1].iov_base = str_area;
484 iov[1].iov_len = count;
485 rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
486 /* SMB request buf freed in SendReceive2 */
487
488 cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
489 if(rc)
490 goto ssetup_exit;
491
492 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
493 smb_buf = (struct smb_hdr *)iov[0].iov_base;
494
495 if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
496 rc = -EIO;
497 cERROR(1,("bad word count %d", smb_buf->WordCount));
498 goto ssetup_exit;
499 }
500 action = le16_to_cpu(pSMB->resp.Action);
501 if (action & GUEST_LOGIN)
502 cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
503 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
504 cFYI(1, ("UID = %d ", ses->Suid));
505 /* response can have either 3 or 4 word count - Samba sends 3 */
506 /* and lanman response is 3 */
507 bytes_remaining = BCC(smb_buf);
508 bcc_ptr = pByteArea(smb_buf);
509
510 if(smb_buf->WordCount == 4) {
511 __u16 blob_len;
512 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
513 bcc_ptr += blob_len;
514 if(blob_len > bytes_remaining) {
515 cERROR(1,("bad security blob length %d", blob_len));
516 rc = -EINVAL;
517 goto ssetup_exit;
518 }
519 bytes_remaining -= blob_len;
520 }
521
522 /* BB check if Unicode and decode strings */
523 if(smb_buf->Flags2 & SMBFLG2_UNICODE)
524 rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
525 ses, nls_cp);
526 else
527 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
528
529ssetup_exit:
530 kfree(str_area);
531 if(resp_buf_type == CIFS_SMALL_BUFFER) {
532 cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
533 cifs_small_buf_release(iov[0].iov_base);
534 } else if(resp_buf_type == CIFS_LARGE_BUFFER)
535 cifs_buf_release(iov[0].iov_base);
536
537 return rc;
538}
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 6103bcdfb16d..f518c5e45035 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -30,6 +30,7 @@
30#include <linux/random.h> 30#include <linux/random.h>
31#include "cifs_unicode.h" 31#include "cifs_unicode.h"
32#include "cifspdu.h" 32#include "cifspdu.h"
33#include "cifsglob.h"
33#include "md5.h" 34#include "md5.h"
34#include "cifs_debug.h" 35#include "cifs_debug.h"
35#include "cifsencrypt.h" 36#include "cifsencrypt.h"
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 3da80409466c..17ba329e2b3d 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -654,8 +654,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
654 654
655 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 655 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
656 up(&ses->server->tcpSem); 656 up(&ses->server->tcpSem);
657 cERROR(1, 657 cERROR(1, ("Illegal length, greater than maximum frame, %d",
658 ("Illegal length, greater than maximum frame, %d ",
659 in_buf->smb_buf_length)); 658 in_buf->smb_buf_length));
660 DeleteMidQEntry(midQ); 659 DeleteMidQEntry(midQ);
661 /* If not lock req, update # of requests on wire to server */ 660 /* If not lock req, update # of requests on wire to server */
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 7caee8d8ea3b..803aacf0d49c 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -28,7 +28,6 @@
28#include <linux/delay.h> 28#include <linux/delay.h>
29#include <linux/skbuff.h> 29#include <linux/skbuff.h>
30#include <linux/proc_fs.h> 30#include <linux/proc_fs.h>
31#include <linux/devfs_fs_kernel.h>
32#include <linux/vmalloc.h> 31#include <linux/vmalloc.h>
33#include <linux/fs.h> 32#include <linux/fs.h>
34#include <linux/file.h> 33#include <linux/file.h>
@@ -365,22 +364,12 @@ static int init_coda_psdev(void)
365 err = PTR_ERR(coda_psdev_class); 364 err = PTR_ERR(coda_psdev_class);
366 goto out_chrdev; 365 goto out_chrdev;
367 } 366 }
368 devfs_mk_dir ("coda"); 367 for (i = 0; i < MAX_CODADEVS; i++)
369 for (i = 0; i < MAX_CODADEVS; i++) {
370 class_device_create(coda_psdev_class, NULL, 368 class_device_create(coda_psdev_class, NULL,
371 MKDEV(CODA_PSDEV_MAJOR,i), NULL, "cfs%d", i); 369 MKDEV(CODA_PSDEV_MAJOR,i), NULL, "cfs%d", i);
372 err = devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i),
373 S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i);
374 if (err)
375 goto out_class;
376 }
377 coda_sysctl_init(); 370 coda_sysctl_init();
378 goto out; 371 goto out;
379 372
380out_class:
381 for (i = 0; i < MAX_CODADEVS; i++)
382 class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
383 class_destroy(coda_psdev_class);
384out_chrdev: 373out_chrdev:
385 unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); 374 unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
386out: 375out:
@@ -419,12 +408,9 @@ static int __init init_coda(void)
419 } 408 }
420 return 0; 409 return 0;
421out: 410out:
422 for (i = 0; i < MAX_CODADEVS; i++) { 411 for (i = 0; i < MAX_CODADEVS; i++)
423 class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i)); 412 class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
424 devfs_remove("coda/%d", i);
425 }
426 class_destroy(coda_psdev_class); 413 class_destroy(coda_psdev_class);
427 devfs_remove("coda");
428 unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); 414 unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
429 coda_sysctl_clean(); 415 coda_sysctl_clean();
430out1: 416out1:
@@ -441,12 +427,9 @@ static void __exit exit_coda(void)
441 if ( err != 0 ) { 427 if ( err != 0 ) {
442 printk("coda: failed to unregister filesystem\n"); 428 printk("coda: failed to unregister filesystem\n");
443 } 429 }
444 for (i = 0; i < MAX_CODADEVS; i++) { 430 for (i = 0; i < MAX_CODADEVS; i++)
445 class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i)); 431 class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
446 devfs_remove("coda/%d", i);
447 }
448 class_destroy(coda_psdev_class); 432 class_destroy(coda_psdev_class);
449 devfs_remove("coda");
450 unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); 433 unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
451 coda_sysctl_clean(); 434 coda_sysctl_clean();
452 coda_destroy_inodecache(); 435 coda_destroy_inodecache();
diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c
index b35e5bbd9c99..76e00a65a75b 100644
--- a/fs/coda/symlink.c
+++ b/fs/coda/symlink.c
@@ -50,6 +50,6 @@ fail:
50 return error; 50 return error;
51} 51}
52 52
53struct address_space_operations coda_symlink_aops = { 53const struct address_space_operations coda_symlink_aops = {
54 .readpage = coda_symlink_filler, 54 .readpage = coda_symlink_filler,
55}; 55};
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index d8ecfedef189..d8d50a70c58d 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -44,7 +44,6 @@
44#include <linux/loop.h> 44#include <linux/loop.h>
45#include <linux/auto_fs.h> 45#include <linux/auto_fs.h>
46#include <linux/auto_fs4.h> 46#include <linux/auto_fs4.h>
47#include <linux/devfs_fs.h>
48#include <linux/tty.h> 47#include <linux/tty.h>
49#include <linux/vt_kern.h> 48#include <linux/vt_kern.h>
50#include <linux/fb.h> 49#include <linux/fb.h>
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index c153bd9534cb..e14488ca6411 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -38,7 +38,7 @@
38 38
39extern struct super_block * configfs_sb; 39extern struct super_block * configfs_sb;
40 40
41static struct address_space_operations configfs_aops = { 41static const struct address_space_operations configfs_aops = {
42 .readpage = simple_readpage, 42 .readpage = simple_readpage,
43 .prepare_write = simple_prepare_write, 43 .prepare_write = simple_prepare_write,
44 .commit_write = simple_commit_write 44 .commit_write = simple_commit_write
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index c45d73860803..223c0431042d 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -30,7 +30,7 @@
30static struct super_operations cramfs_ops; 30static struct super_operations cramfs_ops;
31static struct inode_operations cramfs_dir_inode_operations; 31static struct inode_operations cramfs_dir_inode_operations;
32static const struct file_operations cramfs_directory_operations; 32static const struct file_operations cramfs_directory_operations;
33static struct address_space_operations cramfs_aops; 33static const struct address_space_operations cramfs_aops;
34 34
35static DEFINE_MUTEX(read_mutex); 35static DEFINE_MUTEX(read_mutex);
36 36
@@ -501,7 +501,7 @@ static int cramfs_readpage(struct file *file, struct page * page)
501 return 0; 501 return 0;
502} 502}
503 503
504static struct address_space_operations cramfs_aops = { 504static const struct address_space_operations cramfs_aops = {
505 .readpage = cramfs_readpage 505 .readpage = cramfs_readpage
506}; 506};
507 507
diff --git a/fs/devfs/Makefile b/fs/devfs/Makefile
deleted file mode 100644
index 6dd8d1245e2c..000000000000
--- a/fs/devfs/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
1#
2# Makefile for the linux devfs-filesystem routines.
3#
4
5obj-$(CONFIG_DEVFS_FS) += devfs.o
6
7devfs-objs := base.o util.o
8
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
deleted file mode 100644
index 51a97f132745..000000000000
--- a/fs/devfs/base.c
+++ /dev/null
@@ -1,2836 +0,0 @@
1/* devfs (Device FileSystem) driver.
2
3 Copyright (C) 1998-2002 Richard Gooch
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 Richard Gooch may be reached by email at rgooch@atnf.csiro.au
20 The postal address is:
21 Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
22
23 ChangeLog
24
25 19980110 Richard Gooch <rgooch@atnf.csiro.au>
26 Original version.
27 v0.1
28 19980111 Richard Gooch <rgooch@atnf.csiro.au>
29 Created per-fs inode table rather than using inode->u.generic_ip
30 v0.2
31 19980111 Richard Gooch <rgooch@atnf.csiro.au>
32 Created .epoch inode which has a ctime of 0.
33 Fixed loss of named pipes when dentries lost.
34 Fixed loss of inode data when devfs_register() follows mknod().
35 v0.3
36 19980111 Richard Gooch <rgooch@atnf.csiro.au>
37 Fix for when compiling with CONFIG_KERNELD.
38 19980112 Richard Gooch <rgooch@atnf.csiro.au>
39 Fix for readdir() which sometimes didn't show entries.
40 Added <<tolerant>> option to <devfs_register>.
41 v0.4
42 19980113 Richard Gooch <rgooch@atnf.csiro.au>
43 Created <devfs_fill_file> function.
44 v0.5
45 19980115 Richard Gooch <rgooch@atnf.csiro.au>
46 Added subdirectory support. Major restructuring.
47 19980116 Richard Gooch <rgooch@atnf.csiro.au>
48 Fixed <find_by_dev> to not search major=0,minor=0.
49 Added symlink support.
50 v0.6
51 19980120 Richard Gooch <rgooch@atnf.csiro.au>
52 Created <devfs_mk_dir> function and support directory unregister
53 19980120 Richard Gooch <rgooch@atnf.csiro.au>
54 Auto-ownership uses real uid/gid rather than effective uid/gid.
55 v0.7
56 19980121 Richard Gooch <rgooch@atnf.csiro.au>
57 Supported creation of sockets.
58 v0.8
59 19980122 Richard Gooch <rgooch@atnf.csiro.au>
60 Added DEVFS_FL_HIDE_UNREG flag.
61 Interface change to <devfs_mk_symlink>.
62 Created <devfs_symlink> to support symlink(2).
63 v0.9
64 19980123 Richard Gooch <rgooch@atnf.csiro.au>
65 Added check to <devfs_fill_file> to check inode is in devfs.
66 Added optional traversal of symlinks.
67 v0.10
68 19980124 Richard Gooch <rgooch@atnf.csiro.au>
69 Created <devfs_get_flags> and <devfs_set_flags>.
70 v0.11
71 19980125 C. Scott Ananian <cananian@alumni.princeton.edu>
72 Created <devfs_find_handle>.
73 19980125 Richard Gooch <rgooch@atnf.csiro.au>
74 Allow removal of symlinks.
75 v0.12
76 19980125 Richard Gooch <rgooch@atnf.csiro.au>
77 Created <devfs_set_symlink_destination>.
78 19980126 Richard Gooch <rgooch@atnf.csiro.au>
79 Moved DEVFS_SUPER_MAGIC into header file.
80 Added DEVFS_FL_HIDE flag.
81 Created <devfs_get_maj_min>.
82 Created <devfs_get_handle_from_inode>.
83 Fixed minor bug in <find_by_dev>.
84 19980127 Richard Gooch <rgooch@atnf.csiro.au>
85 Changed interface to <find_by_dev>, <find_entry>,
86 <devfs_unregister>, <devfs_fill_file> and <devfs_find_handle>.
87 Fixed inode times when symlink created with symlink(2).
88 v0.13
89 19980129 C. Scott Ananian <cananian@alumni.princeton.edu>
90 Exported <devfs_set_symlink_destination>, <devfs_get_maj_min>
91 and <devfs_get_handle_from_inode>.
92 19980129 Richard Gooch <rgooch@atnf.csiro.au>
93 Created <devfs_unlink> to support unlink(2).
94 v0.14
95 19980129 Richard Gooch <rgooch@atnf.csiro.au>
96 Fixed kerneld support for entries in devfs subdirectories.
97 19980130 Richard Gooch <rgooch@atnf.csiro.au>
98 Bugfixes in <call_kerneld>.
99 v0.15
100 19980207 Richard Gooch <rgooch@atnf.csiro.au>
101 Call kerneld when looking up unregistered entries.
102 v0.16
103 19980326 Richard Gooch <rgooch@atnf.csiro.au>
104 Modified interface to <devfs_find_handle> for symlink traversal.
105 v0.17
106 19980331 Richard Gooch <rgooch@atnf.csiro.au>
107 Fixed persistence bug with device numbers for manually created
108 device files.
109 Fixed problem with recreating symlinks with different content.
110 v0.18
111 19980401 Richard Gooch <rgooch@atnf.csiro.au>
112 Changed to CONFIG_KMOD.
113 Hide entries which are manually unlinked.
114 Always invalidate devfs dentry cache when registering entries.
115 Created <devfs_rmdir> to support rmdir(2).
116 Ensure directories created by <devfs_mk_dir> are visible.
117 v0.19
118 19980402 Richard Gooch <rgooch@atnf.csiro.au>
119 Invalidate devfs dentry cache when making directories.
120 Invalidate devfs dentry cache when removing entries.
121 Fixed persistence bug with fifos.
122 v0.20
123 19980421 Richard Gooch <rgooch@atnf.csiro.au>
124 Print process command when debugging kerneld/kmod.
125 Added debugging for register/unregister/change operations.
126 19980422 Richard Gooch <rgooch@atnf.csiro.au>
127 Added "devfs=" boot options.
128 v0.21
129 19980426 Richard Gooch <rgooch@atnf.csiro.au>
130 No longer lock/unlock superblock in <devfs_put_super>.
131 Drop negative dentries when they are released.
132 Manage dcache more efficiently.
133 v0.22
134 19980427 Richard Gooch <rgooch@atnf.csiro.au>
135 Added DEVFS_FL_AUTO_DEVNUM flag.
136 v0.23
137 19980430 Richard Gooch <rgooch@atnf.csiro.au>
138 No longer set unnecessary methods.
139 v0.24
140 19980504 Richard Gooch <rgooch@atnf.csiro.au>
141 Added PID display to <call_kerneld> debugging message.
142 Added "after" debugging message to <call_kerneld>.
143 19980519 Richard Gooch <rgooch@atnf.csiro.au>
144 Added "diread" and "diwrite" boot options.
145 19980520 Richard Gooch <rgooch@atnf.csiro.au>
146 Fixed persistence problem with permissions.
147 v0.25
148 19980602 Richard Gooch <rgooch@atnf.csiro.au>
149 Support legacy device nodes.
150 Fixed bug where recreated inodes were hidden.
151 v0.26
152 19980602 Richard Gooch <rgooch@atnf.csiro.au>
153 Improved debugging in <get_vfs_inode>.
154 19980607 Richard Gooch <rgooch@atnf.csiro.au>
155 No longer free old dentries in <devfs_mk_dir>.
156 Free all dentries for a given entry when deleting inodes.
157 v0.27
158 19980627 Richard Gooch <rgooch@atnf.csiro.au>
159 Limit auto-device numbering to majors 128 to 239.
160 v0.28
161 19980629 Richard Gooch <rgooch@atnf.csiro.au>
162 Fixed inode times persistence problem.
163 v0.29
164 19980704 Richard Gooch <rgooch@atnf.csiro.au>
165 Fixed spelling in <devfs_readlink> debug.
166 Fixed bug in <devfs_setup> parsing "dilookup".
167 v0.30
168 19980705 Richard Gooch <rgooch@atnf.csiro.au>
169 Fixed devfs inode leak when manually recreating inodes.
170 Fixed permission persistence problem when recreating inodes.
171 v0.31
172 19980727 Richard Gooch <rgooch@atnf.csiro.au>
173 Removed harmless "unused variable" compiler warning.
174 Fixed modes for manually recreated device nodes.
175 v0.32
176 19980728 Richard Gooch <rgooch@atnf.csiro.au>
177 Added NULL devfs inode warning in <devfs_read_inode>.
178 Force all inode nlink values to 1.
179 v0.33
180 19980730 Richard Gooch <rgooch@atnf.csiro.au>
181 Added "dimknod" boot option.
182 Set inode nlink to 0 when freeing dentries.
183 Fixed modes for manually recreated symlinks.
184 v0.34
185 19980802 Richard Gooch <rgooch@atnf.csiro.au>
186 Fixed bugs in recreated directories and symlinks.
187 v0.35
188 19980806 Richard Gooch <rgooch@atnf.csiro.au>
189 Fixed bugs in recreated device nodes.
190 19980807 Richard Gooch <rgooch@atnf.csiro.au>
191 Fixed bug in currently unused <devfs_get_handle_from_inode>.
192 Defined new <devfs_handle_t> type.
193 Improved debugging when getting entries.
194 Fixed bug where directories could be emptied.
195 v0.36
196 19980809 Richard Gooch <rgooch@atnf.csiro.au>
197 Replaced dummy .epoch inode with .devfsd character device.
198 19980810 Richard Gooch <rgooch@atnf.csiro.au>
199 Implemented devfsd protocol revision 0.
200 v0.37
201 19980819 Richard Gooch <rgooch@atnf.csiro.au>
202 Added soothing message to warning in <devfs_d_iput>.
203 v0.38
204 19980829 Richard Gooch <rgooch@atnf.csiro.au>
205 Use GCC extensions for structure initialisations.
206 Implemented async open notification.
207 Incremented devfsd protocol revision to 1.
208 v0.39
209 19980908 Richard Gooch <rgooch@atnf.csiro.au>
210 Moved async open notification to end of <devfs_open>.
211 v0.40
212 19980910 Richard Gooch <rgooch@atnf.csiro.au>
213 Prepended "/dev/" to module load request.
214 Renamed <call_kerneld> to <call_kmod>.
215 v0.41
216 19980910 Richard Gooch <rgooch@atnf.csiro.au>
217 Fixed typo "AYSNC" -> "ASYNC".
218 v0.42
219 19980910 Richard Gooch <rgooch@atnf.csiro.au>
220 Added open flag for files.
221 v0.43
222 19980927 Richard Gooch <rgooch@atnf.csiro.au>
223 Set i_blocks=0 and i_blksize=1024 in <devfs_read_inode>.
224 v0.44
225 19981005 Richard Gooch <rgooch@atnf.csiro.au>
226 Added test for empty <<name>> in <devfs_find_handle>.
227 Renamed <generate_path> to <devfs_generate_path> and published.
228 v0.45
229 19981006 Richard Gooch <rgooch@atnf.csiro.au>
230 Created <devfs_get_fops>.
231 v0.46
232 19981007 Richard Gooch <rgooch@atnf.csiro.au>
233 Limit auto-device numbering to majors 144 to 239.
234 v0.47
235 19981010 Richard Gooch <rgooch@atnf.csiro.au>
236 Updated <devfs_follow_link> for VFS change in 2.1.125.
237 v0.48
238 19981022 Richard Gooch <rgooch@atnf.csiro.au>
239 Created DEVFS_ FL_COMPAT flag.
240 v0.49
241 19981023 Richard Gooch <rgooch@atnf.csiro.au>
242 Created "nocompat" boot option.
243 v0.50
244 19981025 Richard Gooch <rgooch@atnf.csiro.au>
245 Replaced "mount" boot option with "nomount".
246 v0.51
247 19981110 Richard Gooch <rgooch@atnf.csiro.au>
248 Created "only" boot option.
249 v0.52
250 19981112 Richard Gooch <rgooch@atnf.csiro.au>
251 Added DEVFS_FL_REMOVABLE flag.
252 v0.53
253 19981114 Richard Gooch <rgooch@atnf.csiro.au>
254 Only call <scan_dir_for_removable> on first call to
255 <devfs_readdir>.
256 v0.54
257 19981205 Richard Gooch <rgooch@atnf.csiro.au>
258 Updated <devfs_rmdir> for VFS change in 2.1.131.
259 v0.55
260 19981218 Richard Gooch <rgooch@atnf.csiro.au>
261 Created <devfs_mk_compat>.
262 19981220 Richard Gooch <rgooch@atnf.csiro.au>
263 Check for partitions on removable media in <devfs_lookup>.
264 v0.56
265 19990118 Richard Gooch <rgooch@atnf.csiro.au>
266 Added support for registering regular files.
267 Created <devfs_set_file_size>.
268 Update devfs inodes from entries if not changed through FS.
269 v0.57
270 19990124 Richard Gooch <rgooch@atnf.csiro.au>
271 Fixed <devfs_fill_file> to only initialise temporary inodes.
272 Trap for NULL fops in <devfs_register>.
273 Return -ENODEV in <devfs_fill_file> for non-driver inodes.
274 v0.58
275 19990126 Richard Gooch <rgooch@atnf.csiro.au>
276 Switched from PATH_MAX to DEVFS_PATHLEN.
277 v0.59
278 19990127 Richard Gooch <rgooch@atnf.csiro.au>
279 Created "nottycompat" boot option.
280 v0.60
281 19990318 Richard Gooch <rgooch@atnf.csiro.au>
282 Fixed <devfsd_read> to not overrun event buffer.
283 v0.61
284 19990329 Richard Gooch <rgooch@atnf.csiro.au>
285 Created <devfs_auto_unregister>.
286 v0.62
287 19990330 Richard Gooch <rgooch@atnf.csiro.au>
288 Don't return unregistred entries in <devfs_find_handle>.
289 Panic in <devfs_unregister> if entry unregistered.
290 19990401 Richard Gooch <rgooch@atnf.csiro.au>
291 Don't panic in <devfs_auto_unregister> for duplicates.
292 v0.63
293 19990402 Richard Gooch <rgooch@atnf.csiro.au>
294 Don't unregister already unregistered entries in <unregister>.
295 v0.64
296 19990510 Richard Gooch <rgooch@atnf.csiro.au>
297 Disable warning messages when unable to read partition table for
298 removable media.
299 v0.65
300 19990512 Richard Gooch <rgooch@atnf.csiro.au>
301 Updated <devfs_lookup> for VFS change in 2.3.1-pre1.
302 Created "oops-on-panic" boot option.
303 Improved debugging in <devfs_register> and <devfs_unregister>.
304 v0.66
305 19990519 Richard Gooch <rgooch@atnf.csiro.au>
306 Added documentation for some functions.
307 19990525 Richard Gooch <rgooch@atnf.csiro.au>
308 Removed "oops-on-panic" boot option: now always Oops.
309 v0.67
310 19990531 Richard Gooch <rgooch@atnf.csiro.au>
311 Improved debugging in <devfs_register>.
312 v0.68
313 19990604 Richard Gooch <rgooch@atnf.csiro.au>
314 Added "diunlink" and "nokmod" boot options.
315 Removed superfluous warning message in <devfs_d_iput>.
316 v0.69
317 19990611 Richard Gooch <rgooch@atnf.csiro.au>
318 Took account of change to <d_alloc_root>.
319 v0.70
320 19990614 Richard Gooch <rgooch@atnf.csiro.au>
321 Created separate event queue for each mounted devfs.
322 Removed <devfs_invalidate_dcache>.
323 Created new ioctl()s.
324 Incremented devfsd protocol revision to 3.
325 Fixed bug when re-creating directories: contents were lost.
326 Block access to inodes until devfsd updates permissions.
327 19990615 Richard Gooch <rgooch@atnf.csiro.au>
328 Support 2.2.x kernels.
329 v0.71
330 19990623 Richard Gooch <rgooch@atnf.csiro.au>
331 Switched to sending process uid/gid to devfsd.
332 Renamed <call_kmod> to <try_modload>.
333 Added DEVFSD_NOTIFY_LOOKUP event.
334 19990624 Richard Gooch <rgooch@atnf.csiro.au>
335 Added DEVFSD_NOTIFY_CHANGE event.
336 Incremented devfsd protocol revision to 4.
337 v0.72
338 19990713 Richard Gooch <rgooch@atnf.csiro.au>
339 Return EISDIR rather than EINVAL for read(2) on directories.
340 v0.73
341 19990809 Richard Gooch <rgooch@atnf.csiro.au>
342 Changed <devfs_setup> to new __init scheme.
343 v0.74
344 19990901 Richard Gooch <rgooch@atnf.csiro.au>
345 Changed remaining function declarations to new __init scheme.
346 v0.75
347 19991013 Richard Gooch <rgooch@atnf.csiro.au>
348 Created <devfs_get_info>, <devfs_set_info>,
349 <devfs_get_first_child> and <devfs_get_next_sibling>.
350 Added <<dir>> parameter to <devfs_register>, <devfs_mk_compat>,
351 <devfs_mk_dir> and <devfs_find_handle>.
352 Work sponsored by SGI.
353 v0.76
354 19991017 Richard Gooch <rgooch@atnf.csiro.au>
355 Allow multiple unregistrations.
356 Work sponsored by SGI.
357 v0.77
358 19991026 Richard Gooch <rgooch@atnf.csiro.au>
359 Added major and minor number to devfsd protocol.
360 Incremented devfsd protocol revision to 5.
361 Work sponsored by SGI.
362 v0.78
363 19991030 Richard Gooch <rgooch@atnf.csiro.au>
364 Support info pointer for all devfs entry types.
365 Added <<info>> parameter to <devfs_mk_dir> and
366 <devfs_mk_symlink>.
367 Work sponsored by SGI.
368 v0.79
369 19991031 Richard Gooch <rgooch@atnf.csiro.au>
370 Support "../" when searching devfs namespace.
371 Work sponsored by SGI.
372 v0.80
373 19991101 Richard Gooch <rgooch@atnf.csiro.au>
374 Created <devfs_get_unregister_slave>.
375 Work sponsored by SGI.
376 v0.81
377 19991103 Richard Gooch <rgooch@atnf.csiro.au>
378 Exported <devfs_get_parent>.
379 Work sponsored by SGI.
380 v0.82
381 19991104 Richard Gooch <rgooch@atnf.csiro.au>
382 Removed unused <devfs_set_symlink_destination>.
383 19991105 Richard Gooch <rgooch@atnf.csiro.au>
384 Do not hide entries from devfsd or children.
385 Removed DEVFS_ FL_TTY_COMPAT flag.
386 Removed "nottycompat" boot option.
387 Removed <devfs_mk_compat>.
388 Work sponsored by SGI.
389 v0.83
390 19991107 Richard Gooch <rgooch@atnf.csiro.au>
391 Added DEVFS_FL_WAIT flag.
392 Work sponsored by SGI.
393 v0.84
394 19991107 Richard Gooch <rgooch@atnf.csiro.au>
395 Support new "disc" naming scheme in <get_removable_partition>.
396 Allow NULL fops in <devfs_register>.
397 Work sponsored by SGI.
398 v0.85
399 19991110 Richard Gooch <rgooch@atnf.csiro.au>
400 Fall back to major table if NULL fops given to <devfs_register>.
401 Work sponsored by SGI.
402 v0.86
403 19991204 Richard Gooch <rgooch@atnf.csiro.au>
404 Support fifos when unregistering.
405 Work sponsored by SGI.
406 v0.87
407 19991209 Richard Gooch <rgooch@atnf.csiro.au>
408 Removed obsolete DEVFS_ FL_COMPAT and DEVFS_ FL_TOLERANT flags.
409 Work sponsored by SGI.
410 v0.88
411 19991214 Richard Gooch <rgooch@atnf.csiro.au>
412 Removed kmod support.
413 Work sponsored by SGI.
414 v0.89
415 19991216 Richard Gooch <rgooch@atnf.csiro.au>
416 Improved debugging in <get_vfs_inode>.
417 Ensure dentries created by devfsd will be cleaned up.
418 Work sponsored by SGI.
419 v0.90
420 19991223 Richard Gooch <rgooch@atnf.csiro.au>
421 Created <devfs_get_name>.
422 Work sponsored by SGI.
423 v0.91
424 20000203 Richard Gooch <rgooch@atnf.csiro.au>
425 Ported to kernel 2.3.42.
426 Removed <devfs_fill_file>.
427 Work sponsored by SGI.
428 v0.92
429 20000306 Richard Gooch <rgooch@atnf.csiro.au>
430 Added DEVFS_ FL_NO_PERSISTENCE flag.
431 Removed unnecessary call to <update_devfs_inode_from_entry> in
432 <devfs_readdir>.
433 Work sponsored by SGI.
434 v0.93
435 20000413 Richard Gooch <rgooch@atnf.csiro.au>
436 Set inode->i_size to correct size for symlinks.
437 20000414 Richard Gooch <rgooch@atnf.csiro.au>
438 Only give lookup() method to directories to comply with new VFS
439 assumptions.
440 Work sponsored by SGI.
441 20000415 Richard Gooch <rgooch@atnf.csiro.au>
442 Remove unnecessary tests in symlink methods.
443 Don't kill existing block ops in <devfs_read_inode>.
444 Work sponsored by SGI.
445 v0.94
446 20000424 Richard Gooch <rgooch@atnf.csiro.au>
447 Don't create missing directories in <devfs_find_handle>.
448 Work sponsored by SGI.
449 v0.95
450 20000430 Richard Gooch <rgooch@atnf.csiro.au>
451 Added CONFIG_DEVFS_MOUNT.
452 Work sponsored by SGI.
453 v0.96
454 20000608 Richard Gooch <rgooch@atnf.csiro.au>
455 Disabled multi-mount capability (use VFS bindings instead).
456 Work sponsored by SGI.
457 v0.97
458 20000610 Richard Gooch <rgooch@atnf.csiro.au>
459 Switched to FS_SINGLE to disable multi-mounts.
460 20000612 Richard Gooch <rgooch@atnf.csiro.au>
461 Removed module support.
462 Removed multi-mount code.
463 Removed compatibility macros: VFS has changed too much.
464 Work sponsored by SGI.
465 v0.98
466 20000614 Richard Gooch <rgooch@atnf.csiro.au>
467 Merged devfs inode into devfs entry.
468 Work sponsored by SGI.
469 v0.99
470 20000619 Richard Gooch <rgooch@atnf.csiro.au>
471 Removed dead code in <devfs_register> which used to call
472 <free_dentries>.
473 Work sponsored by SGI.
474 v0.100
475 20000621 Richard Gooch <rgooch@atnf.csiro.au>
476 Changed interface to <devfs_register>.
477 Work sponsored by SGI.
478 v0.101
479 20000622 Richard Gooch <rgooch@atnf.csiro.au>
480 Simplified interface to <devfs_mk_symlink> and <devfs_mk_dir>.
481 Simplified interface to <devfs_find_handle>.
482 Work sponsored by SGI.
483 v0.102
484 20010519 Richard Gooch <rgooch@atnf.csiro.au>
485 Ensure <devfs_generate_path> terminates string for root entry.
486 Exported <devfs_get_name> to modules.
487 20010520 Richard Gooch <rgooch@atnf.csiro.au>
488 Make <devfs_mk_symlink> send events to devfsd.
489 Cleaned up option processing in <devfs_setup>.
490 20010521 Richard Gooch <rgooch@atnf.csiro.au>
491 Fixed bugs in handling symlinks: could leak or cause Oops.
492 20010522 Richard Gooch <rgooch@atnf.csiro.au>
493 Cleaned up directory handling by separating fops.
494 v0.103
495 20010601 Richard Gooch <rgooch@atnf.csiro.au>
496 Fixed handling of inverted options in <devfs_setup>.
497 v0.104
498 20010604 Richard Gooch <rgooch@atnf.csiro.au>
499 Adjusted <try_modload> to account for <devfs_generate_path> fix.
500 v0.105
501 20010617 Richard Gooch <rgooch@atnf.csiro.au>
502 Answered question posed by Al Viro and removed his comments.
503 Moved setting of registered flag after other fields are changed.
504 Fixed race between <devfsd_close> and <devfsd_notify_one>.
505 Global VFS changes added bogus BKL to <devfsd_close>: removed.
506 Widened locking in <devfs_readlink> and <devfs_follow_link>.
507 Replaced <devfsd_read> stack usage with <devfsd_ioctl> kmalloc.
508 Simplified locking in <devfsd_ioctl> and fixed memory leak.
509 v0.106
510 20010709 Richard Gooch <rgooch@atnf.csiro.au>
511 Removed broken devnum allocation and use <devfs_alloc_devnum>.
512 Fixed old devnum leak by calling new <devfs_dealloc_devnum>.
513 v0.107
514 20010712 Richard Gooch <rgooch@atnf.csiro.au>
515 Fixed bug in <devfs_setup> which could hang boot process.
516 v0.108
517 20010730 Richard Gooch <rgooch@atnf.csiro.au>
518 Added DEVFSD_NOTIFY_DELETE event.
519 20010801 Richard Gooch <rgooch@atnf.csiro.au>
520 Removed #include <asm/segment.h>.
521 v0.109
522 20010807 Richard Gooch <rgooch@atnf.csiro.au>
523 Fixed inode table races by removing it and using
524 inode->u.generic_ip instead.
525 Moved <devfs_read_inode> into <get_vfs_inode>.
526 Moved <devfs_write_inode> into <devfs_notify_change>.
527 v0.110
528 20010808 Richard Gooch <rgooch@atnf.csiro.au>
529 Fixed race in <devfs_do_symlink> for uni-processor.
530 v0.111
531 20010818 Richard Gooch <rgooch@atnf.csiro.au>
532 Removed remnant of multi-mount support in <devfs_mknod>.
533 Removed unused DEVFS_FL_SHOW_UNREG flag.
534 v0.112
535 20010820 Richard Gooch <rgooch@atnf.csiro.au>
536 Removed nlink field from struct devfs_inode.
537 v0.113
538 20010823 Richard Gooch <rgooch@atnf.csiro.au>
539 Replaced BKL with global rwsem to protect symlink data (quick
540 and dirty hack).
541 v0.114
542 20010827 Richard Gooch <rgooch@atnf.csiro.au>
543 Replaced global rwsem for symlink with per-link refcount.
544 v0.115
545 20010919 Richard Gooch <rgooch@atnf.csiro.au>
546 Set inode->i_mapping->a_ops for block nodes in <get_vfs_inode>.
547 v0.116
548 20011008 Richard Gooch <rgooch@atnf.csiro.au>
549 Fixed overrun in <devfs_link> by removing function (not needed).
550 20011009 Richard Gooch <rgooch@atnf.csiro.au>
551 Fixed buffer underrun in <try_modload>.
552 20011029 Richard Gooch <rgooch@atnf.csiro.au>
553 Fixed race in <devfsd_ioctl> when setting event mask.
554 20011114 Richard Gooch <rgooch@atnf.csiro.au>
555 First release of new locking code.
556 v1.0
557 20011117 Richard Gooch <rgooch@atnf.csiro.au>
558 Discard temporary buffer, now use "%s" for dentry names.
559 20011118 Richard Gooch <rgooch@atnf.csiro.au>
560 Don't generate path in <try_modload>: use fake entry instead.
561 Use "existing" directory in <_devfs_make_parent_for_leaf>.
562 20011122 Richard Gooch <rgooch@atnf.csiro.au>
563 Use slab cache rather than fixed buffer for devfsd events.
564 v1.1
565 20011125 Richard Gooch <rgooch@atnf.csiro.au>
566 Send DEVFSD_NOTIFY_REGISTERED events in <devfs_mk_dir>.
567 20011127 Richard Gooch <rgooch@atnf.csiro.au>
568 Fixed locking bug in <devfs_d_revalidate_wait> due to typo.
569 Do not send CREATE, CHANGE, ASYNC_OPEN or DELETE events from
570 devfsd or children.
571 v1.2
572 20011202 Richard Gooch <rgooch@atnf.csiro.au>
573 Fixed bug in <devfsd_read>: was dereferencing freed pointer.
574 v1.3
575 20011203 Richard Gooch <rgooch@atnf.csiro.au>
576 Fixed bug in <devfsd_close>: was dereferencing freed pointer.
577 Added process group check for devfsd privileges.
578 v1.4
579 20011204 Richard Gooch <rgooch@atnf.csiro.au>
580 Use SLAB_ATOMIC in <devfsd_notify_de> from <devfs_d_delete>.
581 v1.5
582 20011211 Richard Gooch <rgooch@atnf.csiro.au>
583 Return old entry in <devfs_mk_dir> for 2.4.x kernels.
584 20011212 Richard Gooch <rgooch@atnf.csiro.au>
585 Increment refcount on module in <check_disc_changed>.
586 20011215 Richard Gooch <rgooch@atnf.csiro.au>
587 Created <devfs_get_handle> and exported <devfs_put>.
588 Increment refcount on module in <devfs_get_ops>.
589 Created <devfs_put_ops>.
590 v1.6
591 20011216 Richard Gooch <rgooch@atnf.csiro.au>
592 Added poisoning to <devfs_put>.
593 Improved debugging messages.
594 v1.7
595 20011221 Richard Gooch <rgooch@atnf.csiro.au>
596 Corrected (made useful) debugging message in <unregister>.
597 Moved <kmem_cache_create> in <mount_devfs_fs> to <init_devfs_fs>
598 20011224 Richard Gooch <rgooch@atnf.csiro.au>
599 Added magic number to guard against scribbling drivers.
600 20011226 Richard Gooch <rgooch@atnf.csiro.au>
601 Only return old entry in <devfs_mk_dir> if a directory.
602 Defined macros for error and debug messages.
603 v1.8
604 20020113 Richard Gooch <rgooch@atnf.csiro.au>
605 Fixed (rare, old) race in <devfs_lookup>.
606 v1.9
607 20020120 Richard Gooch <rgooch@atnf.csiro.au>
608 Fixed deadlock bug in <devfs_d_revalidate_wait>.
609 Tag VFS deletable in <devfs_mk_symlink> if handle ignored.
610 v1.10
611 20020129 Richard Gooch <rgooch@atnf.csiro.au>
612 Added KERN_* to remaining messages.
613 Cleaned up declaration of <stat_read>.
614 v1.11
615 20020219 Richard Gooch <rgooch@atnf.csiro.au>
616 Changed <devfs_rmdir> to allow later additions if not yet empty.
617 v1.12
618 20020406 Richard Gooch <rgooch@atnf.csiro.au>
619 Removed silently introduced calls to lock_kernel() and
620 unlock_kernel() due to recent VFS locking changes. BKL isn't
621 required in devfs.
622 v1.13
623 20020428 Richard Gooch <rgooch@atnf.csiro.au>
624 Removed 2.4.x compatibility code.
625 v1.14
626 20020510 Richard Gooch <rgooch@atnf.csiro.au>
627 Added BKL to <devfs_open> because drivers still need it.
628 v1.15
629 20020512 Richard Gooch <rgooch@atnf.csiro.au>
630 Protected <scan_dir_for_removable> and <get_removable_partition>
631 from changing directory contents.
632 v1.16
633 20020514 Richard Gooch <rgooch@atnf.csiro.au>
634 Minor cleanup of <scan_dir_for_removable>.
635 v1.17
636 20020721 Richard Gooch <rgooch@atnf.csiro.au>
637 Switched to ISO C structure field initialisers.
638 Switch to set_current_state() and move before add_wait_queue().
639 20020722 Richard Gooch <rgooch@atnf.csiro.au>
640 Fixed devfs entry leak in <devfs_readdir> when *readdir fails.
641 v1.18
642 20020725 Richard Gooch <rgooch@atnf.csiro.au>
643 Created <devfs_find_and_unregister>.
644 v1.19
645 20020728 Richard Gooch <rgooch@atnf.csiro.au>
646 Removed deprecated <devfs_find_handle>.
647 v1.20
648 20020820 Richard Gooch <rgooch@atnf.csiro.au>
649 Fixed module unload race in <devfs_open>.
650 v1.21
651 20021013 Richard Gooch <rgooch@atnf.csiro.au>
652 Removed DEVFS_ FL_AUTO_OWNER.
653 Switched lingering structure field initialiser to ISO C.
654 Added locking when updating FCB flags.
655 v1.22
656*/
657#include <linux/types.h>
658#include <linux/errno.h>
659#include <linux/time.h>
660#include <linux/tty.h>
661#include <linux/timer.h>
662#include <linux/config.h>
663#include <linux/kernel.h>
664#include <linux/wait.h>
665#include <linux/string.h>
666#include <linux/slab.h>
667#include <linux/ioport.h>
668#include <linux/delay.h>
669#include <linux/ctype.h>
670#include <linux/mm.h>
671#include <linux/module.h>
672#include <linux/init.h>
673#include <linux/devfs_fs.h>
674#include <linux/devfs_fs_kernel.h>
675#include <linux/smp_lock.h>
676#include <linux/smp.h>
677#include <linux/rwsem.h>
678#include <linux/sched.h>
679#include <linux/namei.h>
680#include <linux/bitops.h>
681
682#include <asm/uaccess.h>
683#include <asm/io.h>
684#include <asm/processor.h>
685#include <asm/system.h>
686#include <asm/pgtable.h>
687#include <asm/atomic.h>
688
689#define DEVFS_VERSION "2004-01-31"
690
691#define DEVFS_NAME "devfs"
692
693#define FIRST_INODE 1
694
695#define STRING_LENGTH 256
696#define FAKE_BLOCK_SIZE 1024
697#define POISON_PTR ( *(void **) poison_array )
698#define MAGIC_VALUE 0x327db823
699
700#ifndef TRUE
701# define TRUE 1
702# define FALSE 0
703#endif
704
705#define MODE_DIR (S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO)
706
707#define DEBUG_NONE 0x0000000
708#define DEBUG_MODULE_LOAD 0x0000001
709#define DEBUG_REGISTER 0x0000002
710#define DEBUG_UNREGISTER 0x0000004
711#define DEBUG_FREE 0x0000008
712#define DEBUG_SET_FLAGS 0x0000010
713#define DEBUG_S_READ 0x0000100 /* Break */
714#define DEBUG_I_LOOKUP 0x0001000 /* Break */
715#define DEBUG_I_CREATE 0x0002000
716#define DEBUG_I_GET 0x0004000
717#define DEBUG_I_CHANGE 0x0008000
718#define DEBUG_I_UNLINK 0x0010000
719#define DEBUG_I_RLINK 0x0020000
720#define DEBUG_I_FLINK 0x0040000
721#define DEBUG_I_MKNOD 0x0080000
722#define DEBUG_F_READDIR 0x0100000 /* Break */
723#define DEBUG_D_DELETE 0x1000000 /* Break */
724#define DEBUG_D_RELEASE 0x2000000
725#define DEBUG_D_IPUT 0x4000000
726#define DEBUG_ALL 0xfffffff
727#define DEBUG_DISABLED DEBUG_NONE
728
729#define OPTION_NONE 0x00
730#define OPTION_MOUNT 0x01
731
732#define PRINTK(format, args...) \
733 {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);}
734
735#define OOPS(format, args...) \
736 {printk (KERN_CRIT "%s" format, __FUNCTION__ , ## args); \
737 printk ("Forcing Oops\n"); \
738 BUG();}
739
740#ifdef CONFIG_DEVFS_DEBUG
741# define VERIFY_ENTRY(de) \
742 {if ((de) && (de)->magic_number != MAGIC_VALUE) \
743 OOPS ("(%p): bad magic value: %x\n", (de), (de)->magic_number);}
744# define WRITE_ENTRY_MAGIC(de,magic) (de)->magic_number = (magic)
745# define DPRINTK(flag, format, args...) \
746 {if (devfs_debug & flag) \
747 printk (KERN_INFO "%s" format, __FUNCTION__ , ## args);}
748#else
749# define VERIFY_ENTRY(de)
750# define WRITE_ENTRY_MAGIC(de,magic)
751# define DPRINTK(flag, format, args...)
752#endif
753
754typedef struct devfs_entry *devfs_handle_t;
755
756struct directory_type {
757 rwlock_t lock; /* Lock for searching(R)/updating(W) */
758 struct devfs_entry *first;
759 struct devfs_entry *last;
760 unsigned char no_more_additions:1;
761};
762
763struct symlink_type {
764 unsigned int length; /* Not including the NULL-termimator */
765 char *linkname; /* This is NULL-terminated */
766};
767
768struct devfs_inode { /* This structure is for "persistent" inode storage */
769 struct dentry *dentry;
770 struct timespec atime;
771 struct timespec mtime;
772 struct timespec ctime;
773 unsigned int ino; /* Inode number as seen in the VFS */
774 uid_t uid;
775 gid_t gid;
776};
777
778struct devfs_entry {
779#ifdef CONFIG_DEVFS_DEBUG
780 unsigned int magic_number;
781#endif
782 void *info;
783 atomic_t refcount; /* When this drops to zero, it's unused */
784 union {
785 struct directory_type dir;
786 dev_t dev;
787 struct symlink_type symlink;
788 const char *name; /* Only used for (mode == 0) */
789 } u;
790 struct devfs_entry *prev; /* Previous entry in the parent directory */
791 struct devfs_entry *next; /* Next entry in the parent directory */
792 struct devfs_entry *parent; /* The parent directory */
793 struct devfs_inode inode;
794 umode_t mode;
795 unsigned short namelen; /* I think 64k+ filenames are a way off... */
796 unsigned char vfs:1; /* Whether the VFS may delete the entry */
797 char name[1]; /* This is just a dummy: the allocated array
798 is bigger. This is NULL-terminated */
799};
800
801/* The root of the device tree */
802static struct devfs_entry *root_entry;
803
804struct devfsd_buf_entry {
805 struct devfs_entry *de; /* The name is generated with this */
806 unsigned short type; /* The type of event */
807 umode_t mode;
808 uid_t uid;
809 gid_t gid;
810 struct devfsd_buf_entry *next;
811};
812
813struct fs_info { /* This structure is for the mounted devfs */
814 struct super_block *sb;
815 spinlock_t devfsd_buffer_lock; /* Lock when inserting/deleting events */
816 struct devfsd_buf_entry *devfsd_first_event;
817 struct devfsd_buf_entry *devfsd_last_event;
818 volatile int devfsd_sleeping;
819 volatile struct task_struct *devfsd_task;
820 volatile pid_t devfsd_pgrp;
821 volatile struct file *devfsd_file;
822 struct devfsd_notify_struct *devfsd_info;
823 volatile unsigned long devfsd_event_mask;
824 atomic_t devfsd_overrun_count;
825 wait_queue_head_t devfsd_wait_queue; /* Wake devfsd on input */
826 wait_queue_head_t revalidate_wait_queue; /* Wake when devfsd sleeps */
827};
828
829static struct fs_info fs_info = {.devfsd_buffer_lock = SPIN_LOCK_UNLOCKED };
830static kmem_cache_t *devfsd_buf_cache;
831#ifdef CONFIG_DEVFS_DEBUG
832static unsigned int devfs_debug_init __initdata = DEBUG_NONE;
833static unsigned int devfs_debug = DEBUG_NONE;
834static DEFINE_SPINLOCK(stat_lock);
835static unsigned int stat_num_entries;
836static unsigned int stat_num_bytes;
837#endif
838static unsigned char poison_array[8] =
839 { 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a };
840
841#ifdef CONFIG_DEVFS_MOUNT
842static unsigned int boot_options = OPTION_MOUNT;
843#else
844static unsigned int boot_options = OPTION_NONE;
845#endif
846
847/* Forward function declarations */
848static devfs_handle_t _devfs_walk_path(struct devfs_entry *dir,
849 const char *name, int namelen,
850 int traverse_symlink);
851static ssize_t devfsd_read(struct file *file, char __user *buf, size_t len,
852 loff_t * ppos);
853static int devfsd_ioctl(struct inode *inode, struct file *file,
854 unsigned int cmd, unsigned long arg);
855static int devfsd_close(struct inode *inode, struct file *file);
856#ifdef CONFIG_DEVFS_DEBUG
857static ssize_t stat_read(struct file *file, char __user *buf, size_t len,
858 loff_t * ppos);
859static const struct file_operations stat_fops = {
860 .open = nonseekable_open,
861 .read = stat_read,
862};
863#endif
864
865/* Devfs daemon file operations */
866static const struct file_operations devfsd_fops = {
867 .open = nonseekable_open,
868 .read = devfsd_read,
869 .ioctl = devfsd_ioctl,
870 .release = devfsd_close,
871};
872
873/* Support functions follow */
874
875/**
876 * devfs_get - Get a reference to a devfs entry.
877 * @de: The devfs entry.
878 */
879
880static struct devfs_entry *devfs_get(struct devfs_entry *de)
881{
882 VERIFY_ENTRY(de);
883 if (de)
884 atomic_inc(&de->refcount);
885 return de;
886} /* End Function devfs_get */
887
888/**
889 * devfs_put - Put (release) a reference to a devfs entry.
890 * @de: The handle to the devfs entry.
891 */
892
893static void devfs_put(devfs_handle_t de)
894{
895 if (!de)
896 return;
897 VERIFY_ENTRY(de);
898 if (de->info == POISON_PTR)
899 OOPS("(%p): poisoned pointer\n", de);
900 if (!atomic_dec_and_test(&de->refcount))
901 return;
902 if (de == root_entry)
903 OOPS("(%p): root entry being freed\n", de);
904 DPRINTK(DEBUG_FREE, "(%s): de: %p, parent: %p \"%s\"\n",
905 de->name, de, de->parent,
906 de->parent ? de->parent->name : "no parent");
907 if (S_ISLNK(de->mode))
908 kfree(de->u.symlink.linkname);
909 WRITE_ENTRY_MAGIC(de, 0);
910#ifdef CONFIG_DEVFS_DEBUG
911 spin_lock(&stat_lock);
912 --stat_num_entries;
913 stat_num_bytes -= sizeof *de + de->namelen;
914 if (S_ISLNK(de->mode))
915 stat_num_bytes -= de->u.symlink.length + 1;
916 spin_unlock(&stat_lock);
917#endif
918 de->info = POISON_PTR;
919 kfree(de);
920} /* End Function devfs_put */
921
922/**
923 * _devfs_search_dir - Search for a devfs entry in a directory.
924 * @dir: The directory to search.
925 * @name: The name of the entry to search for.
926 * @namelen: The number of characters in @name.
927 *
928 * Search for a devfs entry in a directory and returns a pointer to the entry
929 * on success, else %NULL. The directory must be locked already.
930 * An implicit devfs_get() is performed on the returned entry.
931 */
932
933static struct devfs_entry *_devfs_search_dir(struct devfs_entry *dir,
934 const char *name,
935 unsigned int namelen)
936{
937 struct devfs_entry *curr;
938
939 if (!S_ISDIR(dir->mode)) {
940 PRINTK("(%s): not a directory\n", dir->name);
941 return NULL;
942 }
943 for (curr = dir->u.dir.first; curr != NULL; curr = curr->next) {
944 if (curr->namelen != namelen)
945 continue;
946 if (memcmp(curr->name, name, namelen) == 0)
947 break;
948 /* Not found: try the next one */
949 }
950 return devfs_get(curr);
951} /* End Function _devfs_search_dir */
952
953/**
954 * _devfs_alloc_entry - Allocate a devfs entry.
955 * @name: the name of the entry
956 * @namelen: the number of characters in @name
957 * @mode: the mode for the entry
958 *
959 * Allocate a devfs entry and returns a pointer to the entry on success, else
960 * %NULL.
961 */
962
963static struct devfs_entry *_devfs_alloc_entry(const char *name,
964 unsigned int namelen,
965 umode_t mode)
966{
967 struct devfs_entry *new;
968 static unsigned long inode_counter = FIRST_INODE;
969 static DEFINE_SPINLOCK(counter_lock);
970
971 if (name && (namelen < 1))
972 namelen = strlen(name);
973 if ((new = kmalloc(sizeof *new + namelen, GFP_KERNEL)) == NULL)
974 return NULL;
975 memset(new, 0, sizeof *new + namelen); /* Will set '\0' on name */
976 new->mode = mode;
977 if (S_ISDIR(mode))
978 rwlock_init(&new->u.dir.lock);
979 atomic_set(&new->refcount, 1);
980 spin_lock(&counter_lock);
981 new->inode.ino = inode_counter++;
982 spin_unlock(&counter_lock);
983 if (name)
984 memcpy(new->name, name, namelen);
985 new->namelen = namelen;
986 WRITE_ENTRY_MAGIC(new, MAGIC_VALUE);
987#ifdef CONFIG_DEVFS_DEBUG
988 spin_lock(&stat_lock);
989 ++stat_num_entries;
990 stat_num_bytes += sizeof *new + namelen;
991 spin_unlock(&stat_lock);
992#endif
993 return new;
994} /* End Function _devfs_alloc_entry */
995
996/**
997 * _devfs_append_entry - Append a devfs entry to a directory's child list.
998 * @dir: The directory to add to.
999 * @de: The devfs entry to append.
1000 * @old_de: If an existing entry exists, it will be written here. This may
1001 * be %NULL. An implicit devfs_get() is performed on this entry.
1002 *
1003 * Append a devfs entry to a directory's list of children, checking first to
1004 * see if an entry of the same name exists. The directory will be locked.
1005 * The value 0 is returned on success, else a negative error code.
1006 * On failure, an implicit devfs_put() is performed on %de.
1007 */
1008
1009static int _devfs_append_entry(devfs_handle_t dir, devfs_handle_t de,
1010 devfs_handle_t * old_de)
1011{
1012 int retval;
1013
1014 if (old_de)
1015 *old_de = NULL;
1016 if (!S_ISDIR(dir->mode)) {
1017 PRINTK("(%s): dir: \"%s\" is not a directory\n", de->name,
1018 dir->name);
1019 devfs_put(de);
1020 return -ENOTDIR;
1021 }
1022 write_lock(&dir->u.dir.lock);
1023 if (dir->u.dir.no_more_additions)
1024 retval = -ENOENT;
1025 else {
1026 struct devfs_entry *old;
1027
1028 old = _devfs_search_dir(dir, de->name, de->namelen);
1029 if (old_de)
1030 *old_de = old;
1031 else
1032 devfs_put(old);
1033 if (old == NULL) {
1034 de->parent = dir;
1035 de->prev = dir->u.dir.last;
1036 /* Append to the directory's list of children */
1037 if (dir->u.dir.first == NULL)
1038 dir->u.dir.first = de;
1039 else
1040 dir->u.dir.last->next = de;
1041 dir->u.dir.last = de;
1042 retval = 0;
1043 } else
1044 retval = -EEXIST;
1045 }
1046 write_unlock(&dir->u.dir.lock);
1047 if (retval)
1048 devfs_put(de);
1049 return retval;
1050} /* End Function _devfs_append_entry */
1051
1052/**
1053 * _devfs_get_root_entry - Get the root devfs entry.
1054 *
1055 * Returns the root devfs entry on success, else %NULL.
1056 *
1057 * TODO it must be called asynchronously due to the fact
1058 * that devfs is initialized relatively late. Proper way
1059 * is to remove module_init from init_devfs_fs and manually
1060 * call it early enough during system init
1061 */
1062
1063static struct devfs_entry *_devfs_get_root_entry(void)
1064{
1065 struct devfs_entry *new;
1066 static DEFINE_SPINLOCK(root_lock);
1067
1068 if (root_entry)
1069 return root_entry;
1070
1071 new = _devfs_alloc_entry(NULL, 0, MODE_DIR);
1072 if (new == NULL)
1073 return NULL;
1074
1075 spin_lock(&root_lock);
1076 if (root_entry) {
1077 spin_unlock(&root_lock);
1078 devfs_put(new);
1079 return root_entry;
1080 }
1081 root_entry = new;
1082 spin_unlock(&root_lock);
1083
1084 return root_entry;
1085} /* End Function _devfs_get_root_entry */
1086
1087/**
1088 * _devfs_descend - Descend down a tree using the next component name.
1089 * @dir: The directory to search.
1090 * @name: The component name to search for.
1091 * @namelen: The length of %name.
1092 * @next_pos: The position of the next '/' or '\0' is written here.
1093 *
1094 * Descend into a directory, searching for a component. This function forms
1095 * the core of a tree-walking algorithm. The directory will be locked.
1096 * The devfs entry corresponding to the component is returned. If there is
1097 * no matching entry, %NULL is returned.
1098 * An implicit devfs_get() is performed on the returned entry.
1099 */
1100
1101static struct devfs_entry *_devfs_descend(struct devfs_entry *dir,
1102 const char *name, int namelen,
1103 int *next_pos)
1104{
1105 const char *stop, *ptr;
1106 struct devfs_entry *entry;
1107
1108 if ((namelen >= 3) && (strncmp(name, "../", 3) == 0)) { /* Special-case going to parent directory */
1109 *next_pos = 3;
1110 return devfs_get(dir->parent);
1111 }
1112 stop = name + namelen;
1113 /* Search for a possible '/' */
1114 for (ptr = name; (ptr < stop) && (*ptr != '/'); ++ptr) ;
1115 *next_pos = ptr - name;
1116 read_lock(&dir->u.dir.lock);
1117 entry = _devfs_search_dir(dir, name, *next_pos);
1118 read_unlock(&dir->u.dir.lock);
1119 return entry;
1120} /* End Function _devfs_descend */
1121
1122static devfs_handle_t _devfs_make_parent_for_leaf(struct devfs_entry *dir,
1123 const char *name,
1124 int namelen, int *leaf_pos)
1125{
1126 int next_pos = 0;
1127
1128 if (dir == NULL)
1129 dir = _devfs_get_root_entry();
1130 if (dir == NULL)
1131 return NULL;
1132 devfs_get(dir);
1133 /* Search for possible trailing component and ignore it */
1134 for (--namelen; (namelen > 0) && (name[namelen] != '/'); --namelen) ;
1135 *leaf_pos = (name[namelen] == '/') ? (namelen + 1) : 0;
1136 for (; namelen > 0; name += next_pos, namelen -= next_pos) {
1137 struct devfs_entry *de, *old = NULL;
1138
1139 if ((de =
1140 _devfs_descend(dir, name, namelen, &next_pos)) == NULL) {
1141 de = _devfs_alloc_entry(name, next_pos, MODE_DIR);
1142 devfs_get(de);
1143 if (!de || _devfs_append_entry(dir, de, &old)) {
1144 devfs_put(de);
1145 if (!old || !S_ISDIR(old->mode)) {
1146 devfs_put(old);
1147 devfs_put(dir);
1148 return NULL;
1149 }
1150 de = old; /* Use the existing directory */
1151 }
1152 }
1153 if (de == dir->parent) {
1154 devfs_put(dir);
1155 devfs_put(de);
1156 return NULL;
1157 }
1158 devfs_put(dir);
1159 dir = de;
1160 if (name[next_pos] == '/')
1161 ++next_pos;
1162 }
1163 return dir;
1164} /* End Function _devfs_make_parent_for_leaf */
1165
1166static devfs_handle_t _devfs_prepare_leaf(devfs_handle_t * dir,
1167 const char *name, umode_t mode)
1168{
1169 int namelen, leaf_pos;
1170 struct devfs_entry *de;
1171
1172 namelen = strlen(name);
1173 if ((*dir = _devfs_make_parent_for_leaf(*dir, name, namelen,
1174 &leaf_pos)) == NULL) {
1175 PRINTK("(%s): could not create parent path\n", name);
1176 return NULL;
1177 }
1178 if ((de = _devfs_alloc_entry(name + leaf_pos, namelen - leaf_pos, mode))
1179 == NULL) {
1180 PRINTK("(%s): could not allocate entry\n", name);
1181 devfs_put(*dir);
1182 return NULL;
1183 }
1184 return de;
1185} /* End Function _devfs_prepare_leaf */
1186
1187static devfs_handle_t _devfs_walk_path(struct devfs_entry *dir,
1188 const char *name, int namelen,
1189 int traverse_symlink)
1190{
1191 int next_pos = 0;
1192
1193 if (dir == NULL)
1194 dir = _devfs_get_root_entry();
1195 if (dir == NULL)
1196 return NULL;
1197 devfs_get(dir);
1198 for (; namelen > 0; name += next_pos, namelen -= next_pos) {
1199 struct devfs_entry *de, *link;
1200
1201 if (!S_ISDIR(dir->mode)) {
1202 devfs_put(dir);
1203 return NULL;
1204 }
1205
1206 if ((de =
1207 _devfs_descend(dir, name, namelen, &next_pos)) == NULL) {
1208 devfs_put(dir);
1209 return NULL;
1210 }
1211 if (S_ISLNK(de->mode) && traverse_symlink) { /* Need to follow the link: this is a stack chomper */
1212 /* FIXME what if it puts outside of mounted tree? */
1213 link = _devfs_walk_path(dir, de->u.symlink.linkname,
1214 de->u.symlink.length, TRUE);
1215 devfs_put(de);
1216 if (!link) {
1217 devfs_put(dir);
1218 return NULL;
1219 }
1220 de = link;
1221 }
1222 devfs_put(dir);
1223 dir = de;
1224 if (name[next_pos] == '/')
1225 ++next_pos;
1226 }
1227 return dir;
1228} /* End Function _devfs_walk_path */
1229
1230/**
1231 * _devfs_find_entry - Find a devfs entry.
1232 * @dir: The handle to the parent devfs directory entry. If this is %NULL the
1233 * name is relative to the root of the devfs.
1234 * @name: The name of the entry. This may be %NULL.
1235 * @traverse_symlink: If %TRUE then symbolic links are traversed.
1236 *
1237 * Returns the devfs_entry pointer on success, else %NULL. An implicit
1238 * devfs_get() is performed.
1239 */
1240
1241static struct devfs_entry *_devfs_find_entry(devfs_handle_t dir,
1242 const char *name,
1243 int traverse_symlink)
1244{
1245 unsigned int namelen = strlen(name);
1246
1247 if (name[0] == '/') {
1248 /* Skip leading pathname component */
1249 if (namelen < 2) {
1250 PRINTK("(%s): too short\n", name);
1251 return NULL;
1252 }
1253 for (++name, --namelen; (*name != '/') && (namelen > 0);
1254 ++name, --namelen) ;
1255 if (namelen < 2) {
1256 PRINTK("(%s): too short\n", name);
1257 return NULL;
1258 }
1259 ++name;
1260 --namelen;
1261 }
1262 return _devfs_walk_path(dir, name, namelen, traverse_symlink);
1263} /* End Function _devfs_find_entry */
1264
1265static struct devfs_entry *get_devfs_entry_from_vfs_inode(struct inode *inode)
1266{
1267 if (inode == NULL)
1268 return NULL;
1269 VERIFY_ENTRY((struct devfs_entry *)inode->u.generic_ip);
1270 return inode->u.generic_ip;
1271} /* End Function get_devfs_entry_from_vfs_inode */
1272
1273/**
1274 * free_dentry - Free the dentry for a device entry and invalidate inode.
1275 * @de: The entry.
1276 *
1277 * This must only be called after the entry has been unhooked from its
1278 * parent directory.
1279 */
1280
1281static void free_dentry(struct devfs_entry *de)
1282{
1283 struct dentry *dentry = de->inode.dentry;
1284
1285 if (!dentry)
1286 return;
1287 spin_lock(&dcache_lock);
1288 dget_locked(dentry);
1289 spin_unlock(&dcache_lock);
1290 /* Forcefully remove the inode */
1291 if (dentry->d_inode != NULL)
1292 dentry->d_inode->i_nlink = 0;
1293 d_drop(dentry);
1294 dput(dentry);
1295} /* End Function free_dentry */
1296
1297/**
1298 * is_devfsd_or_child - Test if the current process is devfsd or one of its children.
1299 * @fs_info: The filesystem information.
1300 *
1301 * Returns %TRUE if devfsd or child, else %FALSE.
1302 */
1303
1304static int is_devfsd_or_child(struct fs_info *fs_info)
1305{
1306 struct task_struct *p = current;
1307
1308 if (p == fs_info->devfsd_task)
1309 return (TRUE);
1310 if (process_group(p) == fs_info->devfsd_pgrp)
1311 return (TRUE);
1312 read_lock(&tasklist_lock);
1313 for (; p != &init_task; p = p->real_parent) {
1314 if (p == fs_info->devfsd_task) {
1315 read_unlock(&tasklist_lock);
1316 return (TRUE);
1317 }
1318 }
1319 read_unlock(&tasklist_lock);
1320 return (FALSE);
1321} /* End Function is_devfsd_or_child */
1322
1323/**
1324 * devfsd_queue_empty - Test if devfsd has work pending in its event queue.
1325 * @fs_info: The filesystem information.
1326 *
1327 * Returns %TRUE if the queue is empty, else %FALSE.
1328 */
1329
1330static inline int devfsd_queue_empty(struct fs_info *fs_info)
1331{
1332 return (fs_info->devfsd_last_event) ? FALSE : TRUE;
1333} /* End Function devfsd_queue_empty */
1334
1335/**
1336 * wait_for_devfsd_finished - Wait for devfsd to finish processing its event queue.
1337 * @fs_info: The filesystem information.
1338 *
1339 * Returns %TRUE if no more waiting will be required, else %FALSE.
1340 */
1341
1342static int wait_for_devfsd_finished(struct fs_info *fs_info)
1343{
1344 DECLARE_WAITQUEUE(wait, current);
1345
1346 if (fs_info->devfsd_task == NULL)
1347 return (TRUE);
1348 if (devfsd_queue_empty(fs_info) && fs_info->devfsd_sleeping)
1349 return TRUE;
1350 if (is_devfsd_or_child(fs_info))
1351 return (FALSE);
1352 set_current_state(TASK_UNINTERRUPTIBLE);
1353 add_wait_queue(&fs_info->revalidate_wait_queue, &wait);
1354 if (!devfsd_queue_empty(fs_info) || !fs_info->devfsd_sleeping)
1355 if (fs_info->devfsd_task)
1356 schedule();
1357 remove_wait_queue(&fs_info->revalidate_wait_queue, &wait);
1358 __set_current_state(TASK_RUNNING);
1359 return (TRUE);
1360} /* End Function wait_for_devfsd_finished */
1361
1362/**
1363 * devfsd_notify_de - Notify the devfsd daemon of a change.
1364 * @de: The devfs entry that has changed. This and all parent entries will
1365 * have their reference counts incremented if the event was queued.
1366 * @type: The type of change.
1367 * @mode: The mode of the entry.
1368 * @uid: The user ID.
1369 * @gid: The group ID.
1370 * @fs_info: The filesystem info.
1371 *
1372 * Returns %TRUE if an event was queued and devfsd woken up, else %FALSE.
1373 */
1374
1375static int devfsd_notify_de(struct devfs_entry *de,
1376 unsigned short type, umode_t mode,
1377 uid_t uid, gid_t gid, struct fs_info *fs_info)
1378{
1379 struct devfsd_buf_entry *entry;
1380 struct devfs_entry *curr;
1381
1382 if (!(fs_info->devfsd_event_mask & (1 << type)))
1383 return (FALSE);
1384 if ((entry = kmem_cache_alloc(devfsd_buf_cache, SLAB_KERNEL)) == NULL) {
1385 atomic_inc(&fs_info->devfsd_overrun_count);
1386 return (FALSE);
1387 }
1388 for (curr = de; curr != NULL; curr = curr->parent)
1389 devfs_get(curr);
1390 entry->de = de;
1391 entry->type = type;
1392 entry->mode = mode;
1393 entry->uid = uid;
1394 entry->gid = gid;
1395 entry->next = NULL;
1396 spin_lock(&fs_info->devfsd_buffer_lock);
1397 if (!fs_info->devfsd_first_event)
1398 fs_info->devfsd_first_event = entry;
1399 if (fs_info->devfsd_last_event)
1400 fs_info->devfsd_last_event->next = entry;
1401 fs_info->devfsd_last_event = entry;
1402 spin_unlock(&fs_info->devfsd_buffer_lock);
1403 wake_up_interruptible(&fs_info->devfsd_wait_queue);
1404 return (TRUE);
1405} /* End Function devfsd_notify_de */
1406
1407/**
1408 * devfsd_notify - Notify the devfsd daemon of a change.
1409 * @de: The devfs entry that has changed.
1410 * @type: The type of change event.
1411 * @wait: If TRUE, the function waits for the daemon to finish processing
1412 * the event.
1413 */
1414
1415static void devfsd_notify(struct devfs_entry *de, unsigned short type)
1416{
1417 devfsd_notify_de(de, type, de->mode, current->euid,
1418 current->egid, &fs_info);
1419}
1420
1421static int devfs_mk_dev(dev_t dev, umode_t mode, const char *fmt, va_list args)
1422{
1423 struct devfs_entry *dir = NULL, *de;
1424 char buf[64];
1425 int error, n;
1426
1427 n = vsnprintf(buf, sizeof(buf), fmt, args);
1428 if (n >= sizeof(buf) || !buf[0]) {
1429 printk(KERN_WARNING "%s: invalid format string %s\n",
1430 __FUNCTION__, fmt);
1431 return -EINVAL;
1432 }
1433
1434 de = _devfs_prepare_leaf(&dir, buf, mode);
1435 if (!de) {
1436 printk(KERN_WARNING "%s: could not prepare leaf for %s\n",
1437 __FUNCTION__, buf);
1438 return -ENOMEM; /* could be more accurate... */
1439 }
1440
1441 de->u.dev = dev;
1442
1443 error = _devfs_append_entry(dir, de, NULL);
1444 if (error) {
1445 printk(KERN_WARNING "%s: could not append to parent for %s\n",
1446 __FUNCTION__, buf);
1447 goto out;
1448 }
1449
1450 devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED);
1451 out:
1452 devfs_put(dir);
1453 return error;
1454}
1455
1456int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...)
1457{
1458 va_list args;
1459
1460 if (!S_ISBLK(mode)) {
1461 printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
1462 __FUNCTION__, mode, fmt);
1463 return -EINVAL;
1464 }
1465
1466 va_start(args, fmt);
1467 return devfs_mk_dev(dev, mode, fmt, args);
1468}
1469
1470EXPORT_SYMBOL(devfs_mk_bdev);
1471
1472int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
1473{
1474 va_list args;
1475
1476 if (!S_ISCHR(mode)) {
1477 printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
1478 __FUNCTION__, mode, fmt);
1479 return -EINVAL;
1480 }
1481
1482 va_start(args, fmt);
1483 return devfs_mk_dev(dev, mode, fmt, args);
1484}
1485
1486EXPORT_SYMBOL(devfs_mk_cdev);
1487
1488/**
1489 * _devfs_unhook - Unhook a device entry from its parents list
1490 * @de: The entry to unhook.
1491 *
1492 * Returns %TRUE if the entry was unhooked, else %FALSE if it was
1493 * previously unhooked.
1494 * The caller must have a write lock on the parent directory.
1495 */
1496
1497static int _devfs_unhook(struct devfs_entry *de)
1498{
1499 struct devfs_entry *parent;
1500
1501 if (!de || (de->prev == de))
1502 return FALSE;
1503 parent = de->parent;
1504 if (de->prev == NULL)
1505 parent->u.dir.first = de->next;
1506 else
1507 de->prev->next = de->next;
1508 if (de->next == NULL)
1509 parent->u.dir.last = de->prev;
1510 else
1511 de->next->prev = de->prev;
1512 de->prev = de; /* Indicate we're unhooked */
1513 de->next = NULL; /* Force early termination for <devfs_readdir> */
1514 return TRUE;
1515} /* End Function _devfs_unhook */
1516
1517/**
1518 * _devfs_unregister - Unregister a device entry from its parent.
1519 * @dir: The parent directory.
1520 * @de: The entry to unregister.
1521 *
1522 * The caller must have a write lock on the parent directory, which is
1523 * unlocked by this function.
1524 */
1525
1526static void _devfs_unregister(struct devfs_entry *dir, struct devfs_entry *de)
1527{
1528 int unhooked = _devfs_unhook(de);
1529
1530 write_unlock(&dir->u.dir.lock);
1531 if (!unhooked)
1532 return;
1533 devfs_get(dir);
1534 devfsd_notify(de, DEVFSD_NOTIFY_UNREGISTERED);
1535 free_dentry(de);
1536 devfs_put(dir);
1537 if (!S_ISDIR(de->mode))
1538 return;
1539 while (TRUE) { /* Recursively unregister: this is a stack chomper */
1540 struct devfs_entry *child;
1541
1542 write_lock(&de->u.dir.lock);
1543 de->u.dir.no_more_additions = TRUE;
1544 child = de->u.dir.first;
1545 VERIFY_ENTRY(child);
1546 _devfs_unregister(de, child);
1547 if (!child)
1548 break;
1549 DPRINTK(DEBUG_UNREGISTER, "(%s): child: %p refcount: %d\n",
1550 child->name, child, atomic_read(&child->refcount));
1551 devfs_put(child);
1552 }
1553} /* End Function _devfs_unregister */
1554
1555static int devfs_do_symlink(devfs_handle_t dir, const char *name,
1556 const char *link, devfs_handle_t * handle)
1557{
1558 int err;
1559 unsigned int linklength;
1560 char *newlink;
1561 struct devfs_entry *de;
1562
1563 if (handle != NULL)
1564 *handle = NULL;
1565 if (name == NULL) {
1566 PRINTK("(): NULL name pointer\n");
1567 return -EINVAL;
1568 }
1569 if (link == NULL) {
1570 PRINTK("(%s): NULL link pointer\n", name);
1571 return -EINVAL;
1572 }
1573 linklength = strlen(link);
1574 if ((newlink = kmalloc(linklength + 1, GFP_KERNEL)) == NULL)
1575 return -ENOMEM;
1576 memcpy(newlink, link, linklength);
1577 newlink[linklength] = '\0';
1578 if ((de = _devfs_prepare_leaf(&dir, name, S_IFLNK | S_IRUGO | S_IXUGO))
1579 == NULL) {
1580 PRINTK("(%s): could not prepare leaf\n", name);
1581 kfree(newlink);
1582 return -ENOTDIR;
1583 }
1584 de->info = NULL;
1585 de->u.symlink.linkname = newlink;
1586 de->u.symlink.length = linklength;
1587 if ((err = _devfs_append_entry(dir, de, NULL)) != 0) {
1588 PRINTK("(%s): could not append to parent, err: %d\n", name,
1589 err);
1590 devfs_put(dir);
1591 return err;
1592 }
1593 devfs_put(dir);
1594#ifdef CONFIG_DEVFS_DEBUG
1595 spin_lock(&stat_lock);
1596 stat_num_bytes += linklength + 1;
1597 spin_unlock(&stat_lock);
1598#endif
1599 if (handle != NULL)
1600 *handle = de;
1601 return 0;
1602} /* End Function devfs_do_symlink */
1603
1604/**
1605 * devfs_mk_symlink Create a symbolic link in the devfs namespace.
1606 * @from: The name of the entry.
1607 * @to: Name of the destination
1608 *
1609 * Returns 0 on success, else a negative error code is returned.
1610 */
1611
1612int devfs_mk_symlink(const char *from, const char *to)
1613{
1614 devfs_handle_t de;
1615 int err;
1616
1617 err = devfs_do_symlink(NULL, from, to, &de);
1618 if (!err) {
1619 de->vfs = TRUE;
1620 devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED);
1621 }
1622
1623 return err;
1624}
1625
1626/**
1627 * devfs_mk_dir - Create a directory in the devfs namespace.
1628 * new name is relative to the root of the devfs.
1629 * @fmt: The name of the entry.
1630 *
1631 * Use of this function is optional. The devfs_register() function
1632 * will automatically create intermediate directories as needed. This function
1633 * is provided for efficiency reasons, as it provides a handle to a directory.
1634 * On failure %NULL is returned.
1635 */
1636
1637int devfs_mk_dir(const char *fmt, ...)
1638{
1639 struct devfs_entry *dir = NULL, *de = NULL, *old;
1640 char buf[64];
1641 va_list args;
1642 int error, n;
1643
1644 va_start(args, fmt);
1645 n = vsnprintf(buf, 64, fmt, args);
1646 if (n >= 64 || !buf[0]) {
1647 printk(KERN_WARNING "%s: invalid argument.", __FUNCTION__);
1648 return -EINVAL;
1649 }
1650
1651 de = _devfs_prepare_leaf(&dir, buf, MODE_DIR);
1652 if (!de) {
1653 PRINTK("(%s): could not prepare leaf\n", buf);
1654 return -EINVAL;
1655 }
1656
1657 error = _devfs_append_entry(dir, de, &old);
1658 if (error == -EEXIST && S_ISDIR(old->mode)) {
1659 /*
1660 * devfs_mk_dir() of an already-existing directory will
1661 * return success.
1662 */
1663 error = 0;
1664 goto out_put;
1665 } else if (error) {
1666 PRINTK("(%s): could not append to dir: %p \"%s\"\n",
1667 buf, dir, dir->name);
1668 devfs_put(old);
1669 goto out_put;
1670 }
1671
1672 devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED);
1673
1674 out_put:
1675 devfs_put(dir);
1676 return error;
1677}
1678
1679void devfs_remove(const char *fmt, ...)
1680{
1681 char buf[64];
1682 va_list args;
1683 int n;
1684
1685 va_start(args, fmt);
1686 n = vsnprintf(buf, sizeof(buf), fmt, args);
1687 if (n < sizeof(buf) && buf[0]) {
1688 devfs_handle_t de = _devfs_find_entry(NULL, buf, 0);
1689
1690 if (!de) {
1691 printk(KERN_ERR "%s: %s not found, cannot remove\n",
1692 __FUNCTION__, buf);
1693 dump_stack();
1694 return;
1695 }
1696
1697 write_lock(&de->parent->u.dir.lock);
1698 _devfs_unregister(de->parent, de);
1699 devfs_put(de);
1700 devfs_put(de);
1701 }
1702}
1703
1704/**
1705 * devfs_generate_path - Generate a pathname for an entry, relative to the devfs root.
1706 * @de: The devfs entry.
1707 * @path: The buffer to write the pathname to. The pathname and '\0'
1708 * terminator will be written at the end of the buffer.
1709 * @buflen: The length of the buffer.
1710 *
1711 * Returns the offset in the buffer where the pathname starts on success,
1712 * else a negative error code.
1713 */
1714
1715static int devfs_generate_path(devfs_handle_t de, char *path, int buflen)
1716{
1717 int pos;
1718#define NAMEOF(de) ( (de)->mode ? (de)->name : (de)->u.name )
1719
1720 if (de == NULL)
1721 return -EINVAL;
1722 VERIFY_ENTRY(de);
1723 if (de->namelen >= buflen)
1724 return -ENAMETOOLONG; /* Must be first */
1725 path[buflen - 1] = '\0';
1726 if (de->parent == NULL)
1727 return buflen - 1; /* Don't prepend root */
1728 pos = buflen - de->namelen - 1;
1729 memcpy(path + pos, NAMEOF(de), de->namelen);
1730 for (de = de->parent; de->parent != NULL; de = de->parent) {
1731 if (pos - de->namelen - 1 < 0)
1732 return -ENAMETOOLONG;
1733 path[--pos] = '/';
1734 pos -= de->namelen;
1735 memcpy(path + pos, NAMEOF(de), de->namelen);
1736 }
1737 return pos;
1738} /* End Function devfs_generate_path */
1739
1740/**
1741 * devfs_setup - Process kernel boot options.
1742 * @str: The boot options after the "devfs=".
1743 */
1744
1745static int __init devfs_setup(char *str)
1746{
1747 static struct {
1748 char *name;
1749 unsigned int mask;
1750 unsigned int *opt;
1751 } devfs_options_tab[] __initdata = {
1752#ifdef CONFIG_DEVFS_DEBUG
1753 {
1754 "dall", DEBUG_ALL, &devfs_debug_init}, {
1755 "dmod", DEBUG_MODULE_LOAD, &devfs_debug_init}, {
1756 "dreg", DEBUG_REGISTER, &devfs_debug_init}, {
1757 "dunreg", DEBUG_UNREGISTER, &devfs_debug_init}, {
1758 "dfree", DEBUG_FREE, &devfs_debug_init}, {
1759 "diget", DEBUG_I_GET, &devfs_debug_init}, {
1760 "dchange", DEBUG_SET_FLAGS, &devfs_debug_init}, {
1761 "dsread", DEBUG_S_READ, &devfs_debug_init}, {
1762 "dichange", DEBUG_I_CHANGE, &devfs_debug_init}, {
1763 "dimknod", DEBUG_I_MKNOD, &devfs_debug_init}, {
1764 "dilookup", DEBUG_I_LOOKUP, &devfs_debug_init}, {
1765 "diunlink", DEBUG_I_UNLINK, &devfs_debug_init},
1766#endif /* CONFIG_DEVFS_DEBUG */
1767 {
1768 "mount", OPTION_MOUNT, &boot_options}, {
1769 NULL, 0, NULL}
1770 };
1771
1772 while ((*str != '\0') && !isspace(*str)) {
1773 int i, found = 0, invert = 0;
1774
1775 if (strncmp(str, "no", 2) == 0) {
1776 invert = 1;
1777 str += 2;
1778 }
1779 for (i = 0; devfs_options_tab[i].name != NULL; i++) {
1780 int len = strlen(devfs_options_tab[i].name);
1781
1782 if (strncmp(str, devfs_options_tab[i].name, len) == 0) {
1783 if (invert)
1784 *devfs_options_tab[i].opt &=
1785 ~devfs_options_tab[i].mask;
1786 else
1787 *devfs_options_tab[i].opt |=
1788 devfs_options_tab[i].mask;
1789 str += len;
1790 found = 1;
1791 break;
1792 }
1793 }
1794 if (!found)
1795 return 0; /* No match */
1796 if (*str != ',')
1797 return 0; /* No more options */
1798 ++str;
1799 }
1800 return 1;
1801} /* End Function devfs_setup */
1802
1803__setup("devfs=", devfs_setup);
1804
1805EXPORT_SYMBOL(devfs_mk_dir);
1806EXPORT_SYMBOL(devfs_remove);
1807
1808/**
1809 * try_modload - Notify devfsd of an inode lookup by a non-devfsd process.
1810 * @parent: The parent devfs entry.
1811 * @fs_info: The filesystem info.
1812 * @name: The device name.
1813 * @namelen: The number of characters in @name.
1814 * @buf: A working area that will be used. This must not go out of scope
1815 * until devfsd is idle again.
1816 *
1817 * Returns 0 on success (event was queued), else a negative error code.
1818 */
1819
1820static int try_modload(struct devfs_entry *parent, struct fs_info *fs_info,
1821 const char *name, unsigned namelen,
1822 struct devfs_entry *buf)
1823{
1824 if (!(fs_info->devfsd_event_mask & (1 << DEVFSD_NOTIFY_LOOKUP)))
1825 return -ENOENT;
1826 if (is_devfsd_or_child(fs_info))
1827 return -ENOENT;
1828 memset(buf, 0, sizeof *buf);
1829 atomic_set(&buf->refcount, 1);
1830 buf->parent = parent;
1831 buf->namelen = namelen;
1832 buf->u.name = name;
1833 WRITE_ENTRY_MAGIC(buf, MAGIC_VALUE);
1834 if (!devfsd_notify_de(buf, DEVFSD_NOTIFY_LOOKUP, 0,
1835 current->euid, current->egid, fs_info))
1836 return -ENOENT;
1837 /* Possible success: event has been queued */
1838 return 0;
1839} /* End Function try_modload */
1840
1841/* Superblock operations follow */
1842
1843static struct inode_operations devfs_iops;
1844static struct inode_operations devfs_dir_iops;
1845static const struct file_operations devfs_fops;
1846static const struct file_operations devfs_dir_fops;
1847static struct inode_operations devfs_symlink_iops;
1848
1849static int devfs_notify_change(struct dentry *dentry, struct iattr *iattr)
1850{
1851 int retval;
1852 struct devfs_entry *de;
1853 struct inode *inode = dentry->d_inode;
1854 struct fs_info *fs_info = inode->i_sb->s_fs_info;
1855
1856 de = get_devfs_entry_from_vfs_inode(inode);
1857 if (de == NULL)
1858 return -ENODEV;
1859 retval = inode_change_ok(inode, iattr);
1860 if (retval != 0)
1861 return retval;
1862 retval = inode_setattr(inode, iattr);
1863 if (retval != 0)
1864 return retval;
1865 DPRINTK(DEBUG_I_CHANGE, "(%d): VFS inode: %p devfs_entry: %p\n",
1866 (int)inode->i_ino, inode, de);
1867 DPRINTK(DEBUG_I_CHANGE, "(): mode: 0%o uid: %d gid: %d\n",
1868 (int)inode->i_mode, (int)inode->i_uid, (int)inode->i_gid);
1869 /* Inode is not on hash chains, thus must save permissions here rather
1870 than in a write_inode() method */
1871 de->mode = inode->i_mode;
1872 de->inode.uid = inode->i_uid;
1873 de->inode.gid = inode->i_gid;
1874 de->inode.atime = inode->i_atime;
1875 de->inode.mtime = inode->i_mtime;
1876 de->inode.ctime = inode->i_ctime;
1877 if ((iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) &&
1878 !is_devfsd_or_child(fs_info))
1879 devfsd_notify_de(de, DEVFSD_NOTIFY_CHANGE, inode->i_mode,
1880 inode->i_uid, inode->i_gid, fs_info);
1881 return 0;
1882} /* End Function devfs_notify_change */
1883
1884static struct super_operations devfs_sops = {
1885 .drop_inode = generic_delete_inode,
1886 .statfs = simple_statfs,
1887};
1888
1889/**
1890 * _devfs_get_vfs_inode - Get a VFS inode.
1891 * @sb: The super block.
1892 * @de: The devfs inode.
1893 * @dentry: The dentry to register with the devfs inode.
1894 *
1895 * Returns the inode on success, else %NULL. An implicit devfs_get() is
1896 * performed if the inode is created.
1897 */
1898
1899static struct inode *_devfs_get_vfs_inode(struct super_block *sb,
1900 struct devfs_entry *de,
1901 struct dentry *dentry)
1902{
1903 struct inode *inode;
1904
1905 if (de->prev == de)
1906 return NULL; /* Quick check to see if unhooked */
1907 if ((inode = new_inode(sb)) == NULL) {
1908 PRINTK("(%s): new_inode() failed, de: %p\n", de->name, de);
1909 return NULL;
1910 }
1911 if (de->parent) {
1912 read_lock(&de->parent->u.dir.lock);
1913 if (de->prev != de)
1914 de->inode.dentry = dentry; /* Not unhooked */
1915 read_unlock(&de->parent->u.dir.lock);
1916 } else
1917 de->inode.dentry = dentry; /* Root: no locking needed */
1918 if (de->inode.dentry != dentry) { /* Must have been unhooked */
1919 iput(inode);
1920 return NULL;
1921 }
1922 /* FIXME where is devfs_put? */
1923 inode->u.generic_ip = devfs_get(de);
1924 inode->i_ino = de->inode.ino;
1925 DPRINTK(DEBUG_I_GET, "(%d): VFS inode: %p devfs_entry: %p\n",
1926 (int)inode->i_ino, inode, de);
1927 inode->i_blocks = 0;
1928 inode->i_blksize = FAKE_BLOCK_SIZE;
1929 inode->i_op = &devfs_iops;
1930 inode->i_mode = de->mode;
1931 if (S_ISDIR(de->mode)) {
1932 inode->i_op = &devfs_dir_iops;
1933 inode->i_fop = &devfs_dir_fops;
1934 } else if (S_ISLNK(de->mode)) {
1935 inode->i_op = &devfs_symlink_iops;
1936 inode->i_size = de->u.symlink.length;
1937 } else if (S_ISCHR(de->mode) || S_ISBLK(de->mode)) {
1938 init_special_inode(inode, de->mode, de->u.dev);
1939 } else if (S_ISFIFO(de->mode) || S_ISSOCK(de->mode)) {
1940 init_special_inode(inode, de->mode, 0);
1941 } else {
1942 PRINTK("(%s): unknown mode %o de: %p\n",
1943 de->name, de->mode, de);
1944 iput(inode);
1945 devfs_put(de);
1946 return NULL;
1947 }
1948
1949 inode->i_uid = de->inode.uid;
1950 inode->i_gid = de->inode.gid;
1951 inode->i_atime = de->inode.atime;
1952 inode->i_mtime = de->inode.mtime;
1953 inode->i_ctime = de->inode.ctime;
1954 DPRINTK(DEBUG_I_GET, "(): mode: 0%o uid: %d gid: %d\n",
1955 (int)inode->i_mode, (int)inode->i_uid, (int)inode->i_gid);
1956 return inode;
1957} /* End Function _devfs_get_vfs_inode */
1958
1959/* File operations for device entries follow */
1960
1961static int devfs_readdir(struct file *file, void *dirent, filldir_t filldir)
1962{
1963 int err, count;
1964 int stored = 0;
1965 struct fs_info *fs_info;
1966 struct devfs_entry *parent, *de, *next = NULL;
1967 struct inode *inode = file->f_dentry->d_inode;
1968
1969 fs_info = inode->i_sb->s_fs_info;
1970 parent = get_devfs_entry_from_vfs_inode(file->f_dentry->d_inode);
1971 if ((long)file->f_pos < 0)
1972 return -EINVAL;
1973 DPRINTK(DEBUG_F_READDIR, "(%s): fs_info: %p pos: %ld\n",
1974 parent->name, fs_info, (long)file->f_pos);
1975 switch ((long)file->f_pos) {
1976 case 0:
1977 err = (*filldir) (dirent, "..", 2, file->f_pos,
1978 parent_ino(file->f_dentry), DT_DIR);
1979 if (err == -EINVAL)
1980 break;
1981 if (err < 0)
1982 return err;
1983 file->f_pos++;
1984 ++stored;
1985 /* Fall through */
1986 case 1:
1987 err =
1988 (*filldir) (dirent, ".", 1, file->f_pos, inode->i_ino,
1989 DT_DIR);
1990 if (err == -EINVAL)
1991 break;
1992 if (err < 0)
1993 return err;
1994 file->f_pos++;
1995 ++stored;
1996 /* Fall through */
1997 default:
1998 /* Skip entries */
1999 count = file->f_pos - 2;
2000 read_lock(&parent->u.dir.lock);
2001 for (de = parent->u.dir.first; de && (count > 0); de = de->next)
2002 --count;
2003 devfs_get(de);
2004 read_unlock(&parent->u.dir.lock);
2005 /* Now add all remaining entries */
2006 while (de) {
2007 err = (*filldir) (dirent, de->name, de->namelen,
2008 file->f_pos, de->inode.ino,
2009 de->mode >> 12);
2010 if (err < 0)
2011 devfs_put(de);
2012 else {
2013 file->f_pos++;
2014 ++stored;
2015 }
2016 if (err == -EINVAL)
2017 break;
2018 if (err < 0)
2019 return err;
2020 read_lock(&parent->u.dir.lock);
2021 next = devfs_get(de->next);
2022 read_unlock(&parent->u.dir.lock);
2023 devfs_put(de);
2024 de = next;
2025 }
2026 break;
2027 }
2028 return stored;
2029} /* End Function devfs_readdir */
2030
2031/* Open devfs specific special files */
2032static int devfs_open(struct inode *inode, struct file *file)
2033{
2034 int err;
2035 int minor = MINOR(inode->i_rdev);
2036 struct file_operations *old_fops, *new_fops;
2037
2038 switch (minor) {
2039 case 0: /* /dev/.devfsd */
2040 new_fops = fops_get(&devfsd_fops);
2041 break;
2042#ifdef CONFIG_DEVFS_DEBUG
2043 case 1: /* /dev/.stat */
2044 new_fops = fops_get(&stat_fops);
2045 break;
2046#endif
2047 default:
2048 return -ENODEV;
2049 }
2050
2051 if (new_fops == NULL)
2052 return -ENODEV;
2053 old_fops = file->f_op;
2054 file->f_op = new_fops;
2055 err = new_fops->open ? new_fops->open(inode, file) : 0;
2056 if (err) {
2057 file->f_op = old_fops;
2058 fops_put(new_fops);
2059 } else
2060 fops_put(old_fops);
2061 return err;
2062} /* End Function devfs_open */
2063
2064static const struct file_operations devfs_fops = {
2065 .open = devfs_open,
2066};
2067
2068static const struct file_operations devfs_dir_fops = {
2069 .read = generic_read_dir,
2070 .readdir = devfs_readdir,
2071};
2072
2073/* Dentry operations for device entries follow */
2074
2075/**
2076 * devfs_d_release - Callback for when a dentry is freed.
2077 * @dentry: The dentry.
2078 */
2079
2080static void devfs_d_release(struct dentry *dentry)
2081{
2082 DPRINTK(DEBUG_D_RELEASE, "(%p): inode: %p\n", dentry, dentry->d_inode);
2083} /* End Function devfs_d_release */
2084
2085/**
2086 * devfs_d_iput - Callback for when a dentry loses its inode.
2087 * @dentry: The dentry.
2088 * @inode: The inode.
2089 */
2090
2091static void devfs_d_iput(struct dentry *dentry, struct inode *inode)
2092{
2093 struct devfs_entry *de;
2094
2095 de = get_devfs_entry_from_vfs_inode(inode);
2096 DPRINTK(DEBUG_D_IPUT,
2097 "(%s): dentry: %p inode: %p de: %p de->dentry: %p\n", de->name,
2098 dentry, inode, de, de->inode.dentry);
2099 if (de->inode.dentry && (de->inode.dentry != dentry))
2100 OOPS("(%s): de: %p dentry: %p de->dentry: %p\n",
2101 de->name, de, dentry, de->inode.dentry);
2102 de->inode.dentry = NULL;
2103 iput(inode);
2104 devfs_put(de);
2105} /* End Function devfs_d_iput */
2106
2107static int devfs_d_delete(struct dentry *dentry);
2108
2109static struct dentry_operations devfs_dops = {
2110 .d_delete = devfs_d_delete,
2111 .d_release = devfs_d_release,
2112 .d_iput = devfs_d_iput,
2113};
2114
2115static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *);
2116
2117static struct dentry_operations devfs_wait_dops = {
2118 .d_delete = devfs_d_delete,
2119 .d_release = devfs_d_release,
2120 .d_iput = devfs_d_iput,
2121 .d_revalidate = devfs_d_revalidate_wait,
2122};
2123
2124/**
2125 * devfs_d_delete - Callback for when all files for a dentry are closed.
2126 * @dentry: The dentry.
2127 */
2128
2129static int devfs_d_delete(struct dentry *dentry)
2130{
2131 struct inode *inode = dentry->d_inode;
2132
2133 if (dentry->d_op == &devfs_wait_dops)
2134 dentry->d_op = &devfs_dops;
2135 /* Unhash dentry if negative (has no inode) */
2136 if (inode == NULL) {
2137 DPRINTK(DEBUG_D_DELETE, "(%p): dropping negative dentry\n",
2138 dentry);
2139 return 1;
2140 }
2141 return 0;
2142} /* End Function devfs_d_delete */
2143
2144struct devfs_lookup_struct {
2145 devfs_handle_t de;
2146 wait_queue_head_t wait_queue;
2147};
2148
2149/* XXX: this doesn't handle the case where we got a negative dentry
2150 but a devfs entry has been registered in the meanwhile */
2151static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *nd)
2152{
2153 struct inode *dir = dentry->d_parent->d_inode;
2154 struct fs_info *fs_info = dir->i_sb->s_fs_info;
2155 devfs_handle_t parent = get_devfs_entry_from_vfs_inode(dir);
2156 struct devfs_lookup_struct *lookup_info = dentry->d_fsdata;
2157 DECLARE_WAITQUEUE(wait, current);
2158 int need_lock;
2159
2160 /*
2161 * FIXME HACK
2162 *
2163 * make sure that
2164 * d_instantiate always runs under lock
2165 * we release i_mutex lock before going to sleep
2166 *
2167 * unfortunately sometimes d_revalidate is called with
2168 * and sometimes without i_mutex lock held. The following checks
2169 * attempt to deduce when we need to add (and drop resp.) lock
2170 * here. This relies on current (2.6.2) calling coventions:
2171 *
2172 * lookup_hash is always run under i_mutex and is passing NULL
2173 * as nd
2174 *
2175 * open(...,O_CREATE,...) calls _lookup_hash under i_mutex
2176 * and sets flags to LOOKUP_OPEN|LOOKUP_CREATE
2177 *
2178 * all other invocations of ->d_revalidate seem to happen
2179 * outside of i_mutex
2180 */
2181 need_lock = nd &&
2182 (!(nd->flags & LOOKUP_CREATE) || (nd->flags & LOOKUP_PARENT));
2183
2184 if (need_lock)
2185 mutex_lock(&dir->i_mutex);
2186
2187 if (is_devfsd_or_child(fs_info)) {
2188 devfs_handle_t de = lookup_info->de;
2189 struct inode *inode;
2190
2191 DPRINTK(DEBUG_I_LOOKUP,
2192 "(%s): dentry: %p inode: %p de: %p by: \"%s\"\n",
2193 dentry->d_name.name, dentry, dentry->d_inode, de,
2194 current->comm);
2195 if (dentry->d_inode)
2196 goto out;
2197 if (de == NULL) {
2198 read_lock(&parent->u.dir.lock);
2199 de = _devfs_search_dir(parent, dentry->d_name.name,
2200 dentry->d_name.len);
2201 read_unlock(&parent->u.dir.lock);
2202 if (de == NULL)
2203 goto out;
2204 lookup_info->de = de;
2205 }
2206 /* Create an inode, now that the driver information is available */
2207 inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry);
2208 if (!inode)
2209 goto out;
2210 DPRINTK(DEBUG_I_LOOKUP,
2211 "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n",
2212 de->name, de->inode.ino, inode, de, current->comm);
2213 d_instantiate(dentry, inode);
2214 goto out;
2215 }
2216 if (lookup_info == NULL)
2217 goto out; /* Early termination */
2218 read_lock(&parent->u.dir.lock);
2219 if (dentry->d_fsdata) {
2220 set_current_state(TASK_UNINTERRUPTIBLE);
2221 add_wait_queue(&lookup_info->wait_queue, &wait);
2222 read_unlock(&parent->u.dir.lock);
2223 /* at this point it is always (hopefully) locked */
2224 mutex_unlock(&dir->i_mutex);
2225 schedule();
2226 mutex_lock(&dir->i_mutex);
2227 /*
2228 * This does not need nor should remove wait from wait_queue.
2229 * Wait queue head is never reused - nothing is ever added to it
2230 * after all waiters have been waked up and head itself disappears
2231 * very soon after it. Moreover it is local variable on stack that
2232 * is likely to have already disappeared so any reference to it
2233 * at this point is buggy.
2234 */
2235
2236 } else
2237 read_unlock(&parent->u.dir.lock);
2238
2239 out:
2240 if (need_lock)
2241 mutex_unlock(&dir->i_mutex);
2242 return 1;
2243} /* End Function devfs_d_revalidate_wait */
2244
2245/* Inode operations for device entries follow */
2246
2247static struct dentry *devfs_lookup(struct inode *dir, struct dentry *dentry,
2248 struct nameidata *nd)
2249{
2250 struct devfs_entry tmp; /* Must stay in scope until devfsd idle again */
2251 struct devfs_lookup_struct lookup_info;
2252 struct fs_info *fs_info = dir->i_sb->s_fs_info;
2253 struct devfs_entry *parent, *de;
2254 struct inode *inode;
2255 struct dentry *retval = NULL;
2256
2257 /* Set up the dentry operations before anything else, to ensure cleaning
2258 up on any error */
2259 dentry->d_op = &devfs_dops;
2260 /* First try to get the devfs entry for this directory */
2261 parent = get_devfs_entry_from_vfs_inode(dir);
2262 DPRINTK(DEBUG_I_LOOKUP, "(%s): dentry: %p parent: %p by: \"%s\"\n",
2263 dentry->d_name.name, dentry, parent, current->comm);
2264 if (parent == NULL)
2265 return ERR_PTR(-ENOENT);
2266 read_lock(&parent->u.dir.lock);
2267 de = _devfs_search_dir(parent, dentry->d_name.name, dentry->d_name.len);
2268 read_unlock(&parent->u.dir.lock);
2269 lookup_info.de = de;
2270 init_waitqueue_head(&lookup_info.wait_queue);
2271 dentry->d_fsdata = &lookup_info;
2272 if (de == NULL) { /* Try with devfsd. For any kind of failure, leave a negative dentry
2273 so someone else can deal with it (in the case where the sysadmin
2274 does a mknod()). It's important to do this before hashing the
2275 dentry, so that the devfsd queue is filled before revalidates
2276 can start */
2277 if (try_modload(parent, fs_info, dentry->d_name.name, dentry->d_name.len, &tmp) < 0) { /* Lookup event was not queued to devfsd */
2278 d_add(dentry, NULL);
2279 return NULL;
2280 }
2281 }
2282 dentry->d_op = &devfs_wait_dops;
2283 d_add(dentry, NULL); /* Open the floodgates */
2284 /* Unlock directory semaphore, which will release any waiters. They
2285 will get the hashed dentry, and may be forced to wait for
2286 revalidation */
2287 mutex_unlock(&dir->i_mutex);
2288 wait_for_devfsd_finished(fs_info); /* If I'm not devfsd, must wait */
2289 mutex_lock(&dir->i_mutex); /* Grab it again because them's the rules */
2290 de = lookup_info.de;
2291 /* If someone else has been so kind as to make the inode, we go home
2292 early */
2293 if (dentry->d_inode)
2294 goto out;
2295 if (de == NULL) {
2296 read_lock(&parent->u.dir.lock);
2297 de = _devfs_search_dir(parent, dentry->d_name.name,
2298 dentry->d_name.len);
2299 read_unlock(&parent->u.dir.lock);
2300 if (de == NULL)
2301 goto out;
2302 /* OK, there's an entry now, but no VFS inode yet */
2303 }
2304 /* Create an inode, now that the driver information is available */
2305 inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry);
2306 if (!inode) {
2307 retval = ERR_PTR(-ENOMEM);
2308 goto out;
2309 }
2310 DPRINTK(DEBUG_I_LOOKUP,
2311 "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n", de->name,
2312 de->inode.ino, inode, de, current->comm);
2313 d_instantiate(dentry, inode);
2314 out:
2315 write_lock(&parent->u.dir.lock);
2316 dentry->d_op = &devfs_dops;
2317 dentry->d_fsdata = NULL;
2318 wake_up(&lookup_info.wait_queue);
2319 write_unlock(&parent->u.dir.lock);
2320 devfs_put(de);
2321 return retval;
2322} /* End Function devfs_lookup */
2323
2324static int devfs_unlink(struct inode *dir, struct dentry *dentry)
2325{
2326 int unhooked;
2327 struct devfs_entry *de;
2328 struct inode *inode = dentry->d_inode;
2329 struct fs_info *fs_info = dir->i_sb->s_fs_info;
2330
2331 de = get_devfs_entry_from_vfs_inode(inode);
2332 DPRINTK(DEBUG_I_UNLINK, "(%s): de: %p\n", dentry->d_name.name, de);
2333 if (de == NULL)
2334 return -ENOENT;
2335 if (!de->vfs)
2336 return -EPERM;
2337 write_lock(&de->parent->u.dir.lock);
2338 unhooked = _devfs_unhook(de);
2339 write_unlock(&de->parent->u.dir.lock);
2340 if (!unhooked)
2341 return -ENOENT;
2342 if (!is_devfsd_or_child(fs_info))
2343 devfsd_notify_de(de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
2344 inode->i_uid, inode->i_gid, fs_info);
2345 free_dentry(de);
2346 devfs_put(de);
2347 return 0;
2348} /* End Function devfs_unlink */
2349
2350static int devfs_symlink(struct inode *dir, struct dentry *dentry,
2351 const char *symname)
2352{
2353 int err;
2354 struct fs_info *fs_info = dir->i_sb->s_fs_info;
2355 struct devfs_entry *parent, *de;
2356 struct inode *inode;
2357
2358 /* First try to get the devfs entry for this directory */
2359 parent = get_devfs_entry_from_vfs_inode(dir);
2360 if (parent == NULL)
2361 return -ENOENT;
2362 err = devfs_do_symlink(parent, dentry->d_name.name, symname, &de);
2363 DPRINTK(DEBUG_DISABLED, "(%s): errcode from <devfs_do_symlink>: %d\n",
2364 dentry->d_name.name, err);
2365 if (err < 0)
2366 return err;
2367 de->vfs = TRUE;
2368 de->inode.uid = current->euid;
2369 de->inode.gid = current->egid;
2370 de->inode.atime = CURRENT_TIME;
2371 de->inode.mtime = CURRENT_TIME;
2372 de->inode.ctime = CURRENT_TIME;
2373 if ((inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry)) == NULL)
2374 return -ENOMEM;
2375 DPRINTK(DEBUG_DISABLED, "(%s): new VFS inode(%u): %p dentry: %p\n",
2376 dentry->d_name.name, de->inode.ino, inode, dentry);
2377 d_instantiate(dentry, inode);
2378 if (!is_devfsd_or_child(fs_info))
2379 devfsd_notify_de(de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
2380 inode->i_uid, inode->i_gid, fs_info);
2381 return 0;
2382} /* End Function devfs_symlink */
2383
2384static int devfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
2385{
2386 int err;
2387 struct fs_info *fs_info = dir->i_sb->s_fs_info;
2388 struct devfs_entry *parent, *de;
2389 struct inode *inode;
2390
2391 mode = (mode & ~S_IFMT) | S_IFDIR; /* VFS doesn't pass S_IFMT part */
2392 parent = get_devfs_entry_from_vfs_inode(dir);
2393 if (parent == NULL)
2394 return -ENOENT;
2395 de = _devfs_alloc_entry(dentry->d_name.name, dentry->d_name.len, mode);
2396 if (!de)
2397 return -ENOMEM;
2398 de->vfs = TRUE;
2399 if ((err = _devfs_append_entry(parent, de, NULL)) != 0)
2400 return err;
2401 de->inode.uid = current->euid;
2402 de->inode.gid = current->egid;
2403 de->inode.atime = CURRENT_TIME;
2404 de->inode.mtime = CURRENT_TIME;
2405 de->inode.ctime = CURRENT_TIME;
2406 if ((inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry)) == NULL)
2407 return -ENOMEM;
2408 DPRINTK(DEBUG_DISABLED, "(%s): new VFS inode(%u): %p dentry: %p\n",
2409 dentry->d_name.name, de->inode.ino, inode, dentry);
2410 d_instantiate(dentry, inode);
2411 if (!is_devfsd_or_child(fs_info))
2412 devfsd_notify_de(de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
2413 inode->i_uid, inode->i_gid, fs_info);
2414 return 0;
2415} /* End Function devfs_mkdir */
2416
2417static int devfs_rmdir(struct inode *dir, struct dentry *dentry)
2418{
2419 int err = 0;
2420 struct devfs_entry *de;
2421 struct fs_info *fs_info = dir->i_sb->s_fs_info;
2422 struct inode *inode = dentry->d_inode;
2423
2424 if (dir->i_sb->s_fs_info != inode->i_sb->s_fs_info)
2425 return -EINVAL;
2426 de = get_devfs_entry_from_vfs_inode(inode);
2427 if (de == NULL)
2428 return -ENOENT;
2429 if (!S_ISDIR(de->mode))
2430 return -ENOTDIR;
2431 if (!de->vfs)
2432 return -EPERM;
2433 /* First ensure the directory is empty and will stay that way */
2434 write_lock(&de->u.dir.lock);
2435 if (de->u.dir.first)
2436 err = -ENOTEMPTY;
2437 else
2438 de->u.dir.no_more_additions = TRUE;
2439 write_unlock(&de->u.dir.lock);
2440 if (err)
2441 return err;
2442 /* Now unhook the directory from its parent */
2443 write_lock(&de->parent->u.dir.lock);
2444 if (!_devfs_unhook(de))
2445 err = -ENOENT;
2446 write_unlock(&de->parent->u.dir.lock);
2447 if (err)
2448 return err;
2449 if (!is_devfsd_or_child(fs_info))
2450 devfsd_notify_de(de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
2451 inode->i_uid, inode->i_gid, fs_info);
2452 free_dentry(de);
2453 devfs_put(de);
2454 return 0;
2455} /* End Function devfs_rmdir */
2456
2457static int devfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
2458 dev_t rdev)
2459{
2460 int err;
2461 struct fs_info *fs_info = dir->i_sb->s_fs_info;
2462 struct devfs_entry *parent, *de;
2463 struct inode *inode;
2464
2465 DPRINTK(DEBUG_I_MKNOD, "(%s): mode: 0%o dev: %u:%u\n",
2466 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
2467 parent = get_devfs_entry_from_vfs_inode(dir);
2468 if (parent == NULL)
2469 return -ENOENT;
2470 de = _devfs_alloc_entry(dentry->d_name.name, dentry->d_name.len, mode);
2471 if (!de)
2472 return -ENOMEM;
2473 de->vfs = TRUE;
2474 if (S_ISCHR(mode) || S_ISBLK(mode))
2475 de->u.dev = rdev;
2476 if ((err = _devfs_append_entry(parent, de, NULL)) != 0)
2477 return err;
2478 de->inode.uid = current->euid;
2479 de->inode.gid = current->egid;
2480 de->inode.atime = CURRENT_TIME;
2481 de->inode.mtime = CURRENT_TIME;
2482 de->inode.ctime = CURRENT_TIME;
2483 if ((inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry)) == NULL)
2484 return -ENOMEM;
2485 DPRINTK(DEBUG_I_MKNOD, ": new VFS inode(%u): %p dentry: %p\n",
2486 de->inode.ino, inode, dentry);
2487 d_instantiate(dentry, inode);
2488 if (!is_devfsd_or_child(fs_info))
2489 devfsd_notify_de(de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
2490 inode->i_uid, inode->i_gid, fs_info);
2491 return 0;
2492} /* End Function devfs_mknod */
2493
2494static void *devfs_follow_link(struct dentry *dentry, struct nameidata *nd)
2495{
2496 struct devfs_entry *p = get_devfs_entry_from_vfs_inode(dentry->d_inode);
2497 nd_set_link(nd, p ? p->u.symlink.linkname : ERR_PTR(-ENODEV));
2498 return NULL;
2499} /* End Function devfs_follow_link */
2500
2501static struct inode_operations devfs_iops = {
2502 .setattr = devfs_notify_change,
2503};
2504
2505static struct inode_operations devfs_dir_iops = {
2506 .lookup = devfs_lookup,
2507 .unlink = devfs_unlink,
2508 .symlink = devfs_symlink,
2509 .mkdir = devfs_mkdir,
2510 .rmdir = devfs_rmdir,
2511 .mknod = devfs_mknod,
2512 .setattr = devfs_notify_change,
2513};
2514
2515static struct inode_operations devfs_symlink_iops = {
2516 .readlink = generic_readlink,
2517 .follow_link = devfs_follow_link,
2518 .setattr = devfs_notify_change,
2519};
2520
2521static int devfs_fill_super(struct super_block *sb, void *data, int silent)
2522{
2523 struct inode *root_inode = NULL;
2524
2525 if (_devfs_get_root_entry() == NULL)
2526 goto out_no_root;
2527 atomic_set(&fs_info.devfsd_overrun_count, 0);
2528 init_waitqueue_head(&fs_info.devfsd_wait_queue);
2529 init_waitqueue_head(&fs_info.revalidate_wait_queue);
2530 fs_info.sb = sb;
2531 sb->s_fs_info = &fs_info;
2532 sb->s_blocksize = 1024;
2533 sb->s_blocksize_bits = 10;
2534 sb->s_magic = DEVFS_SUPER_MAGIC;
2535 sb->s_op = &devfs_sops;
2536 sb->s_time_gran = 1;
2537 if ((root_inode = _devfs_get_vfs_inode(sb, root_entry, NULL)) == NULL)
2538 goto out_no_root;
2539 sb->s_root = d_alloc_root(root_inode);
2540 if (!sb->s_root)
2541 goto out_no_root;
2542 DPRINTK(DEBUG_S_READ, "(): made devfs ptr: %p\n", sb->s_fs_info);
2543 return 0;
2544
2545 out_no_root:
2546 PRINTK("(): get root inode failed\n");
2547 if (root_inode)
2548 iput(root_inode);
2549 return -EINVAL;
2550} /* End Function devfs_fill_super */
2551
2552static int devfs_get_sb(struct file_system_type *fs_type,
2553 int flags, const char *dev_name,
2554 void *data, struct vfsmount *mnt)
2555{
2556 return get_sb_single(fs_type, flags, data, devfs_fill_super, mnt);
2557}
2558
2559static struct file_system_type devfs_fs_type = {
2560 .name = DEVFS_NAME,
2561 .get_sb = devfs_get_sb,
2562 .kill_sb = kill_anon_super,
2563};
2564
2565/* File operations for devfsd follow */
2566
2567static ssize_t devfsd_read(struct file *file, char __user *buf, size_t len,
2568 loff_t * ppos)
2569{
2570 int done = FALSE;
2571 int ival;
2572 loff_t pos, devname_offset, tlen, rpos;
2573 devfs_handle_t de;
2574 struct devfsd_buf_entry *entry;
2575 struct fs_info *fs_info = file->f_dentry->d_inode->i_sb->s_fs_info;
2576 struct devfsd_notify_struct *info = fs_info->devfsd_info;
2577 DECLARE_WAITQUEUE(wait, current);
2578
2579 /* Verify the task has grabbed the queue */
2580 if (fs_info->devfsd_task != current)
2581 return -EPERM;
2582 info->major = 0;
2583 info->minor = 0;
2584 /* Block for a new entry */
2585 set_current_state(TASK_INTERRUPTIBLE);
2586 add_wait_queue(&fs_info->devfsd_wait_queue, &wait);
2587 while (devfsd_queue_empty(fs_info)) {
2588 fs_info->devfsd_sleeping = TRUE;
2589 wake_up(&fs_info->revalidate_wait_queue);
2590 schedule();
2591 fs_info->devfsd_sleeping = FALSE;
2592 if (signal_pending(current)) {
2593 remove_wait_queue(&fs_info->devfsd_wait_queue, &wait);
2594 __set_current_state(TASK_RUNNING);
2595 return -EINTR;
2596 }
2597 set_current_state(TASK_INTERRUPTIBLE);
2598 }
2599 remove_wait_queue(&fs_info->devfsd_wait_queue, &wait);
2600 __set_current_state(TASK_RUNNING);
2601 /* Now play with the data */
2602 ival = atomic_read(&fs_info->devfsd_overrun_count);
2603 info->overrun_count = ival;
2604 entry = fs_info->devfsd_first_event;
2605 info->type = entry->type;
2606 info->mode = entry->mode;
2607 info->uid = entry->uid;
2608 info->gid = entry->gid;
2609 de = entry->de;
2610 if (S_ISCHR(de->mode) || S_ISBLK(de->mode)) {
2611 info->major = MAJOR(de->u.dev);
2612 info->minor = MINOR(de->u.dev);
2613 }
2614 pos = devfs_generate_path(de, info->devname, DEVFS_PATHLEN);
2615 if (pos < 0)
2616 return pos;
2617 info->namelen = DEVFS_PATHLEN - pos - 1;
2618 if (info->mode == 0)
2619 info->mode = de->mode;
2620 devname_offset = info->devname - (char *)info;
2621 rpos = *ppos;
2622 if (rpos < devname_offset) {
2623 /* Copy parts of the header */
2624 tlen = devname_offset - rpos;
2625 if (tlen > len)
2626 tlen = len;
2627 if (copy_to_user(buf, (char *)info + rpos, tlen)) {
2628 return -EFAULT;
2629 }
2630 rpos += tlen;
2631 buf += tlen;
2632 len -= tlen;
2633 }
2634 if ((rpos >= devname_offset) && (len > 0)) {
2635 /* Copy the name */
2636 tlen = info->namelen + 1;
2637 if (tlen > len)
2638 tlen = len;
2639 else
2640 done = TRUE;
2641 if (copy_to_user
2642 (buf, info->devname + pos + rpos - devname_offset, tlen)) {
2643 return -EFAULT;
2644 }
2645 rpos += tlen;
2646 }
2647 tlen = rpos - *ppos;
2648 if (done) {
2649 devfs_handle_t parent;
2650
2651 spin_lock(&fs_info->devfsd_buffer_lock);
2652 fs_info->devfsd_first_event = entry->next;
2653 if (entry->next == NULL)
2654 fs_info->devfsd_last_event = NULL;
2655 spin_unlock(&fs_info->devfsd_buffer_lock);
2656 for (; de != NULL; de = parent) {
2657 parent = de->parent;
2658 devfs_put(de);
2659 }
2660 kmem_cache_free(devfsd_buf_cache, entry);
2661 if (ival > 0)
2662 atomic_sub(ival, &fs_info->devfsd_overrun_count);
2663 *ppos = 0;
2664 } else
2665 *ppos = rpos;
2666 return tlen;
2667} /* End Function devfsd_read */
2668
2669static int devfsd_ioctl(struct inode *inode, struct file *file,
2670 unsigned int cmd, unsigned long arg)
2671{
2672 int ival;
2673 struct fs_info *fs_info = inode->i_sb->s_fs_info;
2674
2675 switch (cmd) {
2676 case DEVFSDIOC_GET_PROTO_REV:
2677 ival = DEVFSD_PROTOCOL_REVISION_KERNEL;
2678 if (copy_to_user((void __user *)arg, &ival, sizeof ival))
2679 return -EFAULT;
2680 break;
2681 case DEVFSDIOC_SET_EVENT_MASK:
2682 /* Ensure only one reader has access to the queue. This scheme will
2683 work even if the global kernel lock were to be removed, because it
2684 doesn't matter who gets in first, as long as only one gets it */
2685 if (fs_info->devfsd_task == NULL) {
2686 static DEFINE_SPINLOCK(lock);
2687
2688 if (!spin_trylock(&lock))
2689 return -EBUSY;
2690 if (fs_info->devfsd_task != NULL) { /* We lost the race... */
2691 spin_unlock(&lock);
2692 return -EBUSY;
2693 }
2694 fs_info->devfsd_task = current;
2695 spin_unlock(&lock);
2696 fs_info->devfsd_pgrp =
2697 (process_group(current) ==
2698 current->pid) ? process_group(current) : 0;
2699 fs_info->devfsd_file = file;
2700 fs_info->devfsd_info =
2701 kmalloc(sizeof *fs_info->devfsd_info, GFP_KERNEL);
2702 if (!fs_info->devfsd_info) {
2703 devfsd_close(inode, file);
2704 return -ENOMEM;
2705 }
2706 } else if (fs_info->devfsd_task != current)
2707 return -EBUSY;
2708 fs_info->devfsd_event_mask = arg; /* Let the masses come forth */
2709 break;
2710 case DEVFSDIOC_RELEASE_EVENT_QUEUE:
2711 if (fs_info->devfsd_file != file)
2712 return -EPERM;
2713 return devfsd_close(inode, file);
2714 /*break; */
2715#ifdef CONFIG_DEVFS_DEBUG
2716 case DEVFSDIOC_SET_DEBUG_MASK:
2717 if (copy_from_user(&ival, (void __user *)arg, sizeof ival))
2718 return -EFAULT;
2719 devfs_debug = ival;
2720 break;
2721#endif
2722 default:
2723 return -ENOIOCTLCMD;
2724 }
2725 return 0;
2726} /* End Function devfsd_ioctl */
2727
2728static int devfsd_close(struct inode *inode, struct file *file)
2729{
2730 struct devfsd_buf_entry *entry, *next;
2731 struct fs_info *fs_info = inode->i_sb->s_fs_info;
2732
2733 if (fs_info->devfsd_file != file)
2734 return 0;
2735 fs_info->devfsd_event_mask = 0;
2736 fs_info->devfsd_file = NULL;
2737 spin_lock(&fs_info->devfsd_buffer_lock);
2738 entry = fs_info->devfsd_first_event;
2739 fs_info->devfsd_first_event = NULL;
2740 fs_info->devfsd_last_event = NULL;
2741 kfree(fs_info->devfsd_info);
2742 fs_info->devfsd_info = NULL;
2743 spin_unlock(&fs_info->devfsd_buffer_lock);
2744 fs_info->devfsd_pgrp = 0;
2745 fs_info->devfsd_task = NULL;
2746 wake_up(&fs_info->revalidate_wait_queue);
2747 for (; entry; entry = next) {
2748 next = entry->next;
2749 kmem_cache_free(devfsd_buf_cache, entry);
2750 }
2751 return 0;
2752} /* End Function devfsd_close */
2753
2754#ifdef CONFIG_DEVFS_DEBUG
2755static ssize_t stat_read(struct file *file, char __user *buf, size_t len,
2756 loff_t * ppos)
2757{
2758 ssize_t num;
2759 char txt[80];
2760
2761 num = sprintf(txt, "Number of entries: %u number of bytes: %u\n",
2762 stat_num_entries, stat_num_bytes) + 1;
2763 if (*ppos >= num)
2764 return 0;
2765 if (*ppos + len > num)
2766 len = num - *ppos;
2767 if (copy_to_user(buf, txt + *ppos, len))
2768 return -EFAULT;
2769 *ppos += len;
2770 return len;
2771} /* End Function stat_read */
2772#endif
2773
2774static int __init init_devfs_fs(void)
2775{
2776 int err;
2777 int major;
2778 struct devfs_entry *devfsd;
2779#ifdef CONFIG_DEVFS_DEBUG
2780 struct devfs_entry *stat;
2781#endif
2782
2783 if (_devfs_get_root_entry() == NULL)
2784 return -ENOMEM;
2785
2786 printk(KERN_INFO "%s: %s Richard Gooch (rgooch@atnf.csiro.au)\n",
2787 DEVFS_NAME, DEVFS_VERSION);
2788 devfsd_buf_cache = kmem_cache_create("devfsd_event",
2789 sizeof(struct devfsd_buf_entry),
2790 0, 0, NULL, NULL);
2791 if (!devfsd_buf_cache)
2792 OOPS("(): unable to allocate event slab\n");
2793#ifdef CONFIG_DEVFS_DEBUG
2794 devfs_debug = devfs_debug_init;
2795 printk(KERN_INFO "%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug);
2796#endif
2797 printk(KERN_INFO "%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options);
2798
2799 /* register special device for devfsd communication */
2800 major = register_chrdev(0, "devfs", &devfs_fops);
2801 if (major < 0)
2802 return major;
2803
2804 /* And create the entry for ".devfsd" */
2805 devfsd = _devfs_alloc_entry(".devfsd", 0, S_IFCHR | S_IRUSR | S_IWUSR);
2806 if (devfsd == NULL)
2807 return -ENOMEM;
2808 devfsd->u.dev = MKDEV(major, 0);
2809 _devfs_append_entry(root_entry, devfsd, NULL);
2810
2811#ifdef CONFIG_DEVFS_DEBUG
2812 stat = _devfs_alloc_entry(".stat", 0, S_IFCHR | S_IRUGO);
2813 if (stat == NULL)
2814 return -ENOMEM;
2815 stat->u.dev = MKDEV(major, 1);
2816 _devfs_append_entry(root_entry, stat, NULL);
2817#endif
2818
2819 err = register_filesystem(&devfs_fs_type);
2820 return err;
2821} /* End Function init_devfs_fs */
2822
2823void __init mount_devfs_fs(void)
2824{
2825 int err;
2826
2827 if (!(boot_options & OPTION_MOUNT))
2828 return;
2829 err = do_mount("none", "/dev", "devfs", 0, NULL);
2830 if (err == 0)
2831 printk(KERN_INFO "Mounted devfs on /dev\n");
2832 else
2833 PRINTK("(): unable to mount devfs, err: %d\n", err);
2834} /* End Function mount_devfs_fs */
2835
2836module_init(init_devfs_fs)
diff --git a/fs/devfs/util.c b/fs/devfs/util.c
deleted file mode 100644
index db06d388c9ac..000000000000
--- a/fs/devfs/util.c
+++ /dev/null
@@ -1,97 +0,0 @@
1/* devfs (Device FileSystem) utilities.
2
3 Copyright (C) 1999-2002 Richard Gooch
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 Richard Gooch may be reached by email at rgooch@atnf.csiro.au
20 The postal address is:
21 Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
22
23 ChangeLog
24
25 19991031 Richard Gooch <rgooch@atnf.csiro.au>
26 Created.
27 19991103 Richard Gooch <rgooch@atnf.csiro.au>
28 Created <_devfs_convert_name> and supported SCSI and IDE CD-ROMs
29 20000203 Richard Gooch <rgooch@atnf.csiro.au>
30 Changed operations pointer type to void *.
31 20000621 Richard Gooch <rgooch@atnf.csiro.au>
32 Changed interface to <devfs_register_series>.
33 20000622 Richard Gooch <rgooch@atnf.csiro.au>
34 Took account of interface change to <devfs_mk_symlink>.
35 Took account of interface change to <devfs_mk_dir>.
36 20010519 Richard Gooch <rgooch@atnf.csiro.au>
37 Documentation cleanup.
38 20010709 Richard Gooch <rgooch@atnf.csiro.au>
39 Created <devfs_*alloc_major> and <devfs_*alloc_devnum>.
40 20010710 Richard Gooch <rgooch@atnf.csiro.au>
41 Created <devfs_*alloc_unique_number>.
42 20010730 Richard Gooch <rgooch@atnf.csiro.au>
43 Documentation typo fix.
44 20010806 Richard Gooch <rgooch@atnf.csiro.au>
45 Made <block_semaphore> and <char_semaphore> private.
46 20010813 Richard Gooch <rgooch@atnf.csiro.au>
47 Fixed bug in <devfs_alloc_unique_number>: limited to 128 numbers
48 20010818 Richard Gooch <rgooch@atnf.csiro.au>
49 Updated major masks up to Linus' "no new majors" proclamation.
50 Block: were 126 now 122 free, char: were 26 now 19 free.
51 20020324 Richard Gooch <rgooch@atnf.csiro.au>
52 Fixed bug in <devfs_alloc_unique_number>: was clearing beyond
53 bitfield.
54 20020326 Richard Gooch <rgooch@atnf.csiro.au>
55 Fixed bitfield data type for <devfs_*alloc_devnum>.
56 Made major bitfield type and initialiser 64 bit safe.
57 20020413 Richard Gooch <rgooch@atnf.csiro.au>
58 Fixed shift warning on 64 bit machines.
59 20020428 Richard Gooch <rgooch@atnf.csiro.au>
60 Copied and used macro for error messages from fs/devfs/base.c
61 20021013 Richard Gooch <rgooch@atnf.csiro.au>
62 Documentation fix.
63 20030101 Adam J. Richter <adam@yggdrasil.com>
64 Eliminate DEVFS_SPECIAL_{CHR,BLK}. Use mode_t instead.
65 20030106 Christoph Hellwig <hch@infradead.org>
66 Rewrite devfs_{,de}alloc_devnum to look like C code.
67*/
68#include <linux/module.h>
69#include <linux/init.h>
70#include <linux/devfs_fs_kernel.h>
71#include <linux/slab.h>
72#include <linux/vmalloc.h>
73#include <linux/genhd.h>
74#include <linux/bitops.h>
75
76int devfs_register_tape(const char *name)
77{
78 char tname[32], dest[64];
79 static unsigned int tape_counter;
80 unsigned int n = tape_counter++;
81
82 sprintf(dest, "../%s", name);
83 sprintf(tname, "tapes/tape%u", n);
84 devfs_mk_symlink(tname, dest);
85
86 return n;
87}
88
89EXPORT_SYMBOL(devfs_register_tape);
90
91void devfs_unregister_tape(int num)
92{
93 if (num >= 0)
94 devfs_remove("tapes/tape%u", num);
95}
96
97EXPORT_SYMBOL(devfs_unregister_tape);
diff --git a/fs/efs/inode.c b/fs/efs/inode.c
index 180607f9314d..174696f9bf14 100644
--- a/fs/efs/inode.c
+++ b/fs/efs/inode.c
@@ -21,7 +21,7 @@ static sector_t _efs_bmap(struct address_space *mapping, sector_t block)
21{ 21{
22 return generic_block_bmap(mapping,block,efs_get_block); 22 return generic_block_bmap(mapping,block,efs_get_block);
23} 23}
24static struct address_space_operations efs_aops = { 24static const struct address_space_operations efs_aops = {
25 .readpage = efs_readpage, 25 .readpage = efs_readpage,
26 .sync_page = block_sync_page, 26 .sync_page = block_sync_page,
27 .bmap = _efs_bmap 27 .bmap = _efs_bmap
diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c
index 3d9a350e3e7f..e249cf733a6b 100644
--- a/fs/efs/symlink.c
+++ b/fs/efs/symlink.c
@@ -53,6 +53,6 @@ fail:
53 return err; 53 return err;
54} 54}
55 55
56struct address_space_operations efs_symlink_aops = { 56const struct address_space_operations efs_symlink_aops = {
57 .readpage = efs_symlink_readpage 57 .readpage = efs_symlink_readpage
58}; 58};
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 9f74a62be555..e65a019fc7a5 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -162,9 +162,9 @@ extern const struct file_operations ext2_file_operations;
162extern const struct file_operations ext2_xip_file_operations; 162extern const struct file_operations ext2_xip_file_operations;
163 163
164/* inode.c */ 164/* inode.c */
165extern struct address_space_operations ext2_aops; 165extern const struct address_space_operations ext2_aops;
166extern struct address_space_operations ext2_aops_xip; 166extern const struct address_space_operations ext2_aops_xip;
167extern struct address_space_operations ext2_nobh_aops; 167extern const struct address_space_operations ext2_nobh_aops;
168 168
169/* namei.c */ 169/* namei.c */
170extern struct inode_operations ext2_dir_inode_operations; 170extern struct inode_operations ext2_dir_inode_operations;
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 04af9c45dce2..fb4d3220eb8d 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -684,7 +684,7 @@ ext2_writepages(struct address_space *mapping, struct writeback_control *wbc)
684 return mpage_writepages(mapping, wbc, ext2_get_block); 684 return mpage_writepages(mapping, wbc, ext2_get_block);
685} 685}
686 686
687struct address_space_operations ext2_aops = { 687const struct address_space_operations ext2_aops = {
688 .readpage = ext2_readpage, 688 .readpage = ext2_readpage,
689 .readpages = ext2_readpages, 689 .readpages = ext2_readpages,
690 .writepage = ext2_writepage, 690 .writepage = ext2_writepage,
@@ -697,12 +697,12 @@ struct address_space_operations ext2_aops = {
697 .migratepage = buffer_migrate_page, 697 .migratepage = buffer_migrate_page,
698}; 698};
699 699
700struct address_space_operations ext2_aops_xip = { 700const struct address_space_operations ext2_aops_xip = {
701 .bmap = ext2_bmap, 701 .bmap = ext2_bmap,
702 .get_xip_page = ext2_get_xip_page, 702 .get_xip_page = ext2_get_xip_page,
703}; 703};
704 704
705struct address_space_operations ext2_nobh_aops = { 705const struct address_space_operations ext2_nobh_aops = {
706 .readpage = ext2_readpage, 706 .readpage = ext2_readpage,
707 .readpages = ext2_readpages, 707 .readpages = ext2_readpages,
708 .writepage = ext2_nobh_writepage, 708 .writepage = ext2_nobh_writepage,
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 0321e1b9034a..f804d5e9d60c 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1698,7 +1698,7 @@ static int ext3_journalled_set_page_dirty(struct page *page)
1698 return __set_page_dirty_nobuffers(page); 1698 return __set_page_dirty_nobuffers(page);
1699} 1699}
1700 1700
1701static struct address_space_operations ext3_ordered_aops = { 1701static const struct address_space_operations ext3_ordered_aops = {
1702 .readpage = ext3_readpage, 1702 .readpage = ext3_readpage,
1703 .readpages = ext3_readpages, 1703 .readpages = ext3_readpages,
1704 .writepage = ext3_ordered_writepage, 1704 .writepage = ext3_ordered_writepage,
@@ -1712,7 +1712,7 @@ static struct address_space_operations ext3_ordered_aops = {
1712 .migratepage = buffer_migrate_page, 1712 .migratepage = buffer_migrate_page,
1713}; 1713};
1714 1714
1715static struct address_space_operations ext3_writeback_aops = { 1715static const struct address_space_operations ext3_writeback_aops = {
1716 .readpage = ext3_readpage, 1716 .readpage = ext3_readpage,
1717 .readpages = ext3_readpages, 1717 .readpages = ext3_readpages,
1718 .writepage = ext3_writeback_writepage, 1718 .writepage = ext3_writeback_writepage,
@@ -1726,7 +1726,7 @@ static struct address_space_operations ext3_writeback_aops = {
1726 .migratepage = buffer_migrate_page, 1726 .migratepage = buffer_migrate_page,
1727}; 1727};
1728 1728
1729static struct address_space_operations ext3_journalled_aops = { 1729static const struct address_space_operations ext3_journalled_aops = {
1730 .readpage = ext3_readpage, 1730 .readpage = ext3_readpage,
1731 .readpages = ext3_readpages, 1731 .readpages = ext3_readpages,
1732 .writepage = ext3_journalled_writepage, 1732 .writepage = ext3_journalled_writepage,
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 7c35d582ec10..31b7174176ba 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -196,7 +196,7 @@ static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
196 return generic_block_bmap(mapping, block, fat_get_block); 196 return generic_block_bmap(mapping, block, fat_get_block);
197} 197}
198 198
199static struct address_space_operations fat_aops = { 199static const struct address_space_operations fat_aops = {
200 .readpage = fat_readpage, 200 .readpage = fat_readpage,
201 .readpages = fat_readpages, 201 .readpages = fat_readpages,
202 .writepage = fat_writepage, 202 .writepage = fat_writepage,
diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c
index 6f5df1700e95..4e25f3fbed86 100644
--- a/fs/freevxfs/vxfs_immed.c
+++ b/fs/freevxfs/vxfs_immed.c
@@ -56,7 +56,7 @@ struct inode_operations vxfs_immed_symlink_iops = {
56/* 56/*
57 * Adress space operations for immed files and directories. 57 * Adress space operations for immed files and directories.
58 */ 58 */
59struct address_space_operations vxfs_immed_aops = { 59const struct address_space_operations vxfs_immed_aops = {
60 .readpage = vxfs_immed_readpage, 60 .readpage = vxfs_immed_readpage,
61}; 61};
62 62
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index f544aae9169f..ca6a39714771 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -41,8 +41,8 @@
41#include "vxfs_extern.h" 41#include "vxfs_extern.h"
42 42
43 43
44extern struct address_space_operations vxfs_aops; 44extern const struct address_space_operations vxfs_aops;
45extern struct address_space_operations vxfs_immed_aops; 45extern const struct address_space_operations vxfs_immed_aops;
46 46
47extern struct inode_operations vxfs_immed_symlink_iops; 47extern struct inode_operations vxfs_immed_symlink_iops;
48 48
@@ -295,7 +295,7 @@ vxfs_read_inode(struct inode *ip)
295{ 295{
296 struct super_block *sbp = ip->i_sb; 296 struct super_block *sbp = ip->i_sb;
297 struct vxfs_inode_info *vip; 297 struct vxfs_inode_info *vip;
298 struct address_space_operations *aops; 298 const struct address_space_operations *aops;
299 ino_t ino = ip->i_ino; 299 ino_t ino = ip->i_ino;
300 300
301 if (!(vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist))) 301 if (!(vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist)))
diff --git a/fs/freevxfs/vxfs_subr.c b/fs/freevxfs/vxfs_subr.c
index c1be118fc067..decac62efe57 100644
--- a/fs/freevxfs/vxfs_subr.c
+++ b/fs/freevxfs/vxfs_subr.c
@@ -42,7 +42,7 @@
42static int vxfs_readpage(struct file *, struct page *); 42static int vxfs_readpage(struct file *, struct page *);
43static sector_t vxfs_bmap(struct address_space *, sector_t); 43static sector_t vxfs_bmap(struct address_space *, sector_t);
44 44
45struct address_space_operations vxfs_aops = { 45const struct address_space_operations vxfs_aops = {
46 .readpage = vxfs_readpage, 46 .readpage = vxfs_readpage,
47 .bmap = vxfs_bmap, 47 .bmap = vxfs_bmap,
48 .sync_page = block_sync_page, 48 .sync_page = block_sync_page,
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 28aa81eae2cc..63614ed16336 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -770,7 +770,7 @@ static const struct file_operations fuse_direct_io_file_operations = {
770 /* no mmap and sendfile */ 770 /* no mmap and sendfile */
771}; 771};
772 772
773static struct address_space_operations fuse_file_aops = { 773static const struct address_space_operations fuse_file_aops = {
774 .readpage = fuse_readpage, 774 .readpage = fuse_readpage,
775 .prepare_write = fuse_prepare_write, 775 .prepare_write = fuse_prepare_write,
776 .commit_write = fuse_commit_write, 776 .commit_write = fuse_commit_write,
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 3ed8663a8db1..735332dfd1b8 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -182,8 +182,8 @@ extern void hfs_file_truncate(struct inode *);
182extern int hfs_get_block(struct inode *, sector_t, struct buffer_head *, int); 182extern int hfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
183 183
184/* inode.c */ 184/* inode.c */
185extern struct address_space_operations hfs_aops; 185extern const struct address_space_operations hfs_aops;
186extern struct address_space_operations hfs_btree_aops; 186extern const struct address_space_operations hfs_btree_aops;
187 187
188extern struct inode *hfs_new_inode(struct inode *, struct qstr *, int); 188extern struct inode *hfs_new_inode(struct inode *, struct qstr *, int);
189extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *); 189extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 2d4ced22201b..315cf44a90b2 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -114,7 +114,7 @@ static int hfs_writepages(struct address_space *mapping,
114 return mpage_writepages(mapping, wbc, hfs_get_block); 114 return mpage_writepages(mapping, wbc, hfs_get_block);
115} 115}
116 116
117struct address_space_operations hfs_btree_aops = { 117const struct address_space_operations hfs_btree_aops = {
118 .readpage = hfs_readpage, 118 .readpage = hfs_readpage,
119 .writepage = hfs_writepage, 119 .writepage = hfs_writepage,
120 .sync_page = block_sync_page, 120 .sync_page = block_sync_page,
@@ -124,7 +124,7 @@ struct address_space_operations hfs_btree_aops = {
124 .releasepage = hfs_releasepage, 124 .releasepage = hfs_releasepage,
125}; 125};
126 126
127struct address_space_operations hfs_aops = { 127const struct address_space_operations hfs_aops = {
128 .readpage = hfs_readpage, 128 .readpage = hfs_readpage,
129 .writepage = hfs_writepage, 129 .writepage = hfs_writepage,
130 .sync_page = block_sync_page, 130 .sync_page = block_sync_page,
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 7ae393637a0c..8a1ca5ef7ada 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -323,8 +323,8 @@ int hfsplus_file_extend(struct inode *);
323void hfsplus_file_truncate(struct inode *); 323void hfsplus_file_truncate(struct inode *);
324 324
325/* inode.c */ 325/* inode.c */
326extern struct address_space_operations hfsplus_aops; 326extern const struct address_space_operations hfsplus_aops;
327extern struct address_space_operations hfsplus_btree_aops; 327extern const struct address_space_operations hfsplus_btree_aops;
328 328
329void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *); 329void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *);
330void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *); 330void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *);
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index acf66dba3e01..924ecdef8091 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -109,7 +109,7 @@ static int hfsplus_writepages(struct address_space *mapping,
109 return mpage_writepages(mapping, wbc, hfsplus_get_block); 109 return mpage_writepages(mapping, wbc, hfsplus_get_block);
110} 110}
111 111
112struct address_space_operations hfsplus_btree_aops = { 112const struct address_space_operations hfsplus_btree_aops = {
113 .readpage = hfsplus_readpage, 113 .readpage = hfsplus_readpage,
114 .writepage = hfsplus_writepage, 114 .writepage = hfsplus_writepage,
115 .sync_page = block_sync_page, 115 .sync_page = block_sync_page,
@@ -119,7 +119,7 @@ struct address_space_operations hfsplus_btree_aops = {
119 .releasepage = hfsplus_releasepage, 119 .releasepage = hfsplus_releasepage,
120}; 120};
121 121
122struct address_space_operations hfsplus_aops = { 122const struct address_space_operations hfsplus_aops = {
123 .readpage = hfsplus_readpage, 123 .readpage = hfsplus_readpage,
124 .writepage = hfsplus_writepage, 124 .writepage = hfsplus_writepage,
125 .sync_page = block_sync_page, 125 .sync_page = block_sync_page,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 8e0d37743e7c..b82e3d9c8790 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -54,7 +54,7 @@ static int append = 0;
54 54
55static struct inode_operations hostfs_iops; 55static struct inode_operations hostfs_iops;
56static struct inode_operations hostfs_dir_iops; 56static struct inode_operations hostfs_dir_iops;
57static struct address_space_operations hostfs_link_aops; 57static const struct address_space_operations hostfs_link_aops;
58 58
59#ifndef MODULE 59#ifndef MODULE
60static int __init hostfs_args(char *options, int *add) 60static int __init hostfs_args(char *options, int *add)
@@ -518,7 +518,7 @@ int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
518 return(err); 518 return(err);
519} 519}
520 520
521static struct address_space_operations hostfs_aops = { 521static const struct address_space_operations hostfs_aops = {
522 .writepage = hostfs_writepage, 522 .writepage = hostfs_writepage,
523 .readpage = hostfs_readpage, 523 .readpage = hostfs_readpage,
524 .set_page_dirty = __set_page_dirty_nobuffers, 524 .set_page_dirty = __set_page_dirty_nobuffers,
@@ -935,7 +935,7 @@ int hostfs_link_readpage(struct file *file, struct page *page)
935 return(err); 935 return(err);
936} 936}
937 937
938static struct address_space_operations hostfs_link_aops = { 938static const struct address_space_operations hostfs_link_aops = {
939 .readpage = hostfs_link_readpage, 939 .readpage = hostfs_link_readpage,
940}; 940};
941 941
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index d3b9fffe45a1..d9eb19b7b8ae 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -99,7 +99,7 @@ static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block)
99{ 99{
100 return generic_block_bmap(mapping,block,hpfs_get_block); 100 return generic_block_bmap(mapping,block,hpfs_get_block);
101} 101}
102struct address_space_operations hpfs_aops = { 102const struct address_space_operations hpfs_aops = {
103 .readpage = hpfs_readpage, 103 .readpage = hpfs_readpage,
104 .writepage = hpfs_writepage, 104 .writepage = hpfs_writepage,
105 .sync_page = block_sync_page, 105 .sync_page = block_sync_page,
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 29b7a3e55173..f687d54ed442 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -268,7 +268,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int);
268int hpfs_file_fsync(struct file *, struct dentry *, int); 268int hpfs_file_fsync(struct file *, struct dentry *, int);
269extern const struct file_operations hpfs_file_ops; 269extern const struct file_operations hpfs_file_ops;
270extern struct inode_operations hpfs_file_iops; 270extern struct inode_operations hpfs_file_iops;
271extern struct address_space_operations hpfs_aops; 271extern const struct address_space_operations hpfs_aops;
272 272
273/* inode.c */ 273/* inode.c */
274 274
@@ -304,7 +304,7 @@ void hpfs_decide_conv(struct inode *, unsigned char *, unsigned);
304/* namei.c */ 304/* namei.c */
305 305
306extern struct inode_operations hpfs_dir_iops; 306extern struct inode_operations hpfs_dir_iops;
307extern struct address_space_operations hpfs_symlink_aops; 307extern const struct address_space_operations hpfs_symlink_aops;
308 308
309static inline struct hpfs_inode_info *hpfs_i(struct inode *inode) 309static inline struct hpfs_inode_info *hpfs_i(struct inode *inode)
310{ 310{
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index a03abb12c610..59e7dc182a0c 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -538,7 +538,7 @@ fail:
538 return err; 538 return err;
539} 539}
540 540
541struct address_space_operations hpfs_symlink_aops = { 541const struct address_space_operations hpfs_symlink_aops = {
542 .readpage = hpfs_symlink_readpage 542 .readpage = hpfs_symlink_readpage
543}; 543};
544 544
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index e6410d8edd0e..6449cb697967 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -34,7 +34,7 @@
34#define HUGETLBFS_MAGIC 0x958458f6 34#define HUGETLBFS_MAGIC 0x958458f6
35 35
36static struct super_operations hugetlbfs_ops; 36static struct super_operations hugetlbfs_ops;
37static struct address_space_operations hugetlbfs_aops; 37static const struct address_space_operations hugetlbfs_aops;
38const struct file_operations hugetlbfs_file_operations; 38const struct file_operations hugetlbfs_file_operations;
39static struct inode_operations hugetlbfs_dir_inode_operations; 39static struct inode_operations hugetlbfs_dir_inode_operations;
40static struct inode_operations hugetlbfs_inode_operations; 40static struct inode_operations hugetlbfs_inode_operations;
@@ -547,7 +547,7 @@ static void hugetlbfs_destroy_inode(struct inode *inode)
547 kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode)); 547 kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode));
548} 548}
549 549
550static struct address_space_operations hugetlbfs_aops = { 550static const struct address_space_operations hugetlbfs_aops = {
551 .readpage = hugetlbfs_readpage, 551 .readpage = hugetlbfs_readpage,
552 .prepare_write = hugetlbfs_prepare_write, 552 .prepare_write = hugetlbfs_prepare_write,
553 .commit_write = hugetlbfs_commit_write, 553 .commit_write = hugetlbfs_commit_write,
diff --git a/fs/inode.c b/fs/inode.c
index 3a2446a27d2c..f42961eb983b 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -102,7 +102,7 @@ static kmem_cache_t * inode_cachep __read_mostly;
102 102
103static struct inode *alloc_inode(struct super_block *sb) 103static struct inode *alloc_inode(struct super_block *sb)
104{ 104{
105 static struct address_space_operations empty_aops; 105 static const struct address_space_operations empty_aops;
106 static struct inode_operations empty_iops; 106 static struct inode_operations empty_iops;
107 static const struct file_operations empty_fops; 107 static const struct file_operations empty_fops;
108 struct inode *inode; 108 struct inode *inode;
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c
index 4917315db732..3a39158cca96 100644
--- a/fs/isofs/compress.c
+++ b/fs/isofs/compress.c
@@ -312,7 +312,7 @@ eio:
312 return err; 312 return err;
313} 313}
314 314
315struct address_space_operations zisofs_aops = { 315const struct address_space_operations zisofs_aops = {
316 .readpage = zisofs_readpage, 316 .readpage = zisofs_readpage,
317 /* No sync_page operation supported? */ 317 /* No sync_page operation supported? */
318 /* No bmap operation supported */ 318 /* No bmap operation supported */
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 3f9c8ba1fa1f..bb11c7fb4019 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -1054,7 +1054,7 @@ static sector_t _isofs_bmap(struct address_space *mapping, sector_t block)
1054 return generic_block_bmap(mapping,block,isofs_get_block); 1054 return generic_block_bmap(mapping,block,isofs_get_block);
1055} 1055}
1056 1056
1057static struct address_space_operations isofs_aops = { 1057static const struct address_space_operations isofs_aops = {
1058 .readpage = isofs_readpage, 1058 .readpage = isofs_readpage,
1059 .sync_page = block_sync_page, 1059 .sync_page = block_sync_page,
1060 .bmap = _isofs_bmap 1060 .bmap = _isofs_bmap
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index b87ba066f5e7..e6308c8b5735 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -176,5 +176,5 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de,
176 176
177extern struct inode_operations isofs_dir_inode_operations; 177extern struct inode_operations isofs_dir_inode_operations;
178extern const struct file_operations isofs_dir_operations; 178extern const struct file_operations isofs_dir_operations;
179extern struct address_space_operations isofs_symlink_aops; 179extern const struct address_space_operations isofs_symlink_aops;
180extern struct export_operations isofs_export_ops; 180extern struct export_operations isofs_export_ops;
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 4326cb47f8fa..f3a1db3098de 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -754,6 +754,6 @@ error:
754 return -EIO; 754 return -EIO;
755} 755}
756 756
757struct address_space_operations isofs_symlink_aops = { 757const struct address_space_operations isofs_symlink_aops = {
758 .readpage = rock_ridge_symlink_readpage 758 .readpage = rock_ridge_symlink_readpage
759}; 759};
diff --git a/fs/isofs/zisofs.h b/fs/isofs/zisofs.h
index d78485d101c2..273795709155 100644
--- a/fs/isofs/zisofs.h
+++ b/fs/isofs/zisofs.h
@@ -15,7 +15,7 @@
15 */ 15 */
16 16
17#ifdef CONFIG_ZISOFS 17#ifdef CONFIG_ZISOFS
18extern struct address_space_operations zisofs_aops; 18extern const struct address_space_operations zisofs_aops;
19extern int __init zisofs_init(void); 19extern int __init zisofs_init(void);
20extern void zisofs_cleanup(void); 20extern void zisofs_cleanup(void);
21#endif 21#endif
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 7f96b5cb6781..8c9b28dff119 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -34,6 +34,7 @@
34#include <linux/suspend.h> 34#include <linux/suspend.h>
35#include <linux/pagemap.h> 35#include <linux/pagemap.h>
36#include <linux/kthread.h> 36#include <linux/kthread.h>
37#include <linux/poison.h>
37#include <linux/proc_fs.h> 38#include <linux/proc_fs.h>
38 39
39#include <asm/uaccess.h> 40#include <asm/uaccess.h>
@@ -1675,7 +1676,7 @@ static void journal_free_journal_head(struct journal_head *jh)
1675{ 1676{
1676#ifdef CONFIG_JBD_DEBUG 1677#ifdef CONFIG_JBD_DEBUG
1677 atomic_dec(&nr_journal_heads); 1678 atomic_dec(&nr_journal_heads);
1678 memset(jh, 0x5b, sizeof(*jh)); 1679 memset(jh, JBD_POISON_FREE, sizeof(*jh));
1679#endif 1680#endif
1680 kmem_cache_free(journal_head_cache, jh); 1681 kmem_cache_free(journal_head_cache, jh);
1681} 1682}
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index 9e46ea6da752..93068697a9bf 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -59,7 +59,7 @@ static const struct file_operations jffs_file_operations;
59static struct inode_operations jffs_file_inode_operations; 59static struct inode_operations jffs_file_inode_operations;
60static const struct file_operations jffs_dir_operations; 60static const struct file_operations jffs_dir_operations;
61static struct inode_operations jffs_dir_inode_operations; 61static struct inode_operations jffs_dir_inode_operations;
62static struct address_space_operations jffs_address_operations; 62static const struct address_space_operations jffs_address_operations;
63 63
64kmem_cache_t *node_cache = NULL; 64kmem_cache_t *node_cache = NULL;
65kmem_cache_t *fm_cache = NULL; 65kmem_cache_t *fm_cache = NULL;
@@ -1614,7 +1614,7 @@ jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1614} /* jffs_ioctl() */ 1614} /* jffs_ioctl() */
1615 1615
1616 1616
1617static struct address_space_operations jffs_address_operations = { 1617static const struct address_space_operations jffs_address_operations = {
1618 .readpage = jffs_readpage, 1618 .readpage = jffs_readpage,
1619 .prepare_write = jffs_prepare_write, 1619 .prepare_write = jffs_prepare_write,
1620 .commit_write = jffs_commit_write, 1620 .commit_write = jffs_commit_write,
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 320dd48b834e..9c2077e7e081 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -267,6 +267,8 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
267 } 267 }
268 268
269 rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0); 269 rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0);
270 if (!value && rc == -ENODATA)
271 rc = 0;
270 if (value) 272 if (value)
271 kfree(value); 273 kfree(value);
272 if (!rc) { 274 if (!rc) {
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index b8886f048eaa..ad0121088dde 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -225,7 +225,6 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
225 at the end of the linked list. Stash it and continue 225 at the end of the linked list. Stash it and continue
226 from the beginning of the list */ 226 from the beginning of the list */
227 ic = (struct jffs2_inode_cache *)(*prev); 227 ic = (struct jffs2_inode_cache *)(*prev);
228 BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
229 prev = &ic->nodes; 228 prev = &ic->nodes;
230 continue; 229 continue;
231 } 230 }
@@ -249,7 +248,8 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
249 248
250 /* PARANOIA */ 249 /* PARANOIA */
251 if (!ic) { 250 if (!ic) {
252 printk(KERN_WARNING "inode_cache not found in remove_node_refs()!!\n"); 251 JFFS2_WARNING("inode_cache/xattr_datum/xattr_ref"
252 " not found in remove_node_refs()!!\n");
253 return; 253 return;
254 } 254 }
255 255
@@ -274,8 +274,19 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
274 printk("\n"); 274 printk("\n");
275 }); 275 });
276 276
277 if (ic->nodes == (void *)ic && ic->nlink == 0) 277 switch (ic->class) {
278 jffs2_del_ino_cache(c, ic); 278#ifdef CONFIG_JFFS2_FS_XATTR
279 case RAWNODE_CLASS_XATTR_DATUM:
280 jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
281 break;
282 case RAWNODE_CLASS_XATTR_REF:
283 jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
284 break;
285#endif
286 default:
287 if (ic->nodes == (void *)ic && ic->nlink == 0)
288 jffs2_del_ino_cache(c, ic);
289 }
279} 290}
280 291
281void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 292void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index bb8844f40e48..3ed6e3e120b6 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -62,7 +62,7 @@ struct inode_operations jffs2_file_inode_operations =
62 .removexattr = jffs2_removexattr 62 .removexattr = jffs2_removexattr
63}; 63};
64 64
65struct address_space_operations jffs2_file_address_operations = 65const struct address_space_operations jffs2_file_address_operations =
66{ 66{
67 .readpage = jffs2_readpage, 67 .readpage = jffs2_readpage,
68 .prepare_write =jffs2_prepare_write, 68 .prepare_write =jffs2_prepare_write,
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 2900ec3ec3af..97caa77d60cf 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -227,8 +227,6 @@ void jffs2_clear_inode (struct inode *inode)
227 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 227 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
228 228
229 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));
230
231 jffs2_xattr_delete_inode(c, f->inocache);
232 jffs2_do_clear_inode(c, f); 230 jffs2_do_clear_inode(c, f);
233} 231}
234 232
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 477c526d638b..daff3341ff92 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -165,6 +165,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
165 D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n", 165 D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n",
166 ic->ino)); 166 ic->ino));
167 spin_unlock(&c->inocache_lock); 167 spin_unlock(&c->inocache_lock);
168 jffs2_xattr_delete_inode(c, ic);
168 continue; 169 continue;
169 } 170 }
170 switch(ic->state) { 171 switch(ic->state) {
@@ -275,13 +276,12 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
275 * We can decide whether this node is inode or xattr by ic->class. */ 276 * We can decide whether this node is inode or xattr by ic->class. */
276 if (ic->class == RAWNODE_CLASS_XATTR_DATUM 277 if (ic->class == RAWNODE_CLASS_XATTR_DATUM
277 || ic->class == RAWNODE_CLASS_XATTR_REF) { 278 || ic->class == RAWNODE_CLASS_XATTR_REF) {
278 BUG_ON(raw->next_in_ino != (void *)ic);
279 spin_unlock(&c->erase_completion_lock); 279 spin_unlock(&c->erase_completion_lock);
280 280
281 if (ic->class == RAWNODE_CLASS_XATTR_DATUM) { 281 if (ic->class == RAWNODE_CLASS_XATTR_DATUM) {
282 ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic); 282 ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic, raw);
283 } else { 283 } else {
284 ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic); 284 ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic, raw);
285 } 285 }
286 goto release_sem; 286 goto release_sem;
287 } 287 }
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 935fec1b1201..b98594992eed 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -119,8 +119,11 @@ struct jffs2_sb_info {
119#ifdef CONFIG_JFFS2_FS_XATTR 119#ifdef CONFIG_JFFS2_FS_XATTR
120#define XATTRINDEX_HASHSIZE (57) 120#define XATTRINDEX_HASHSIZE (57)
121 uint32_t highest_xid; 121 uint32_t highest_xid;
122 uint32_t highest_xseqno;
122 struct list_head xattrindex[XATTRINDEX_HASHSIZE]; 123 struct list_head xattrindex[XATTRINDEX_HASHSIZE];
123 struct list_head xattr_unchecked; 124 struct list_head xattr_unchecked;
125 struct list_head xattr_dead_list;
126 struct jffs2_xattr_ref *xref_dead_list;
124 struct jffs2_xattr_ref *xref_temp; 127 struct jffs2_xattr_ref *xref_temp;
125 struct rw_semaphore xattr_sem; 128 struct rw_semaphore xattr_sem;
126 uint32_t xdatum_mem_usage; 129 uint32_t xdatum_mem_usage;
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
index 4889d0700c0e..8310c95478e9 100644
--- a/fs/jffs2/malloc.c
+++ b/fs/jffs2/malloc.c
@@ -291,6 +291,7 @@ struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void)
291 291
292 memset(xd, 0, sizeof(struct jffs2_xattr_datum)); 292 memset(xd, 0, sizeof(struct jffs2_xattr_datum));
293 xd->class = RAWNODE_CLASS_XATTR_DATUM; 293 xd->class = RAWNODE_CLASS_XATTR_DATUM;
294 xd->node = (void *)xd;
294 INIT_LIST_HEAD(&xd->xindex); 295 INIT_LIST_HEAD(&xd->xindex);
295 return xd; 296 return xd;
296} 297}
@@ -309,6 +310,7 @@ struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
309 310
310 memset(ref, 0, sizeof(struct jffs2_xattr_ref)); 311 memset(ref, 0, sizeof(struct jffs2_xattr_ref));
311 ref->class = RAWNODE_CLASS_XATTR_REF; 312 ref->class = RAWNODE_CLASS_XATTR_REF;
313 ref->node = (void *)ref;
312 return ref; 314 return ref;
313} 315}
314 316
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 927dfe42ba76..7675b33396c7 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -906,6 +906,9 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
906{ 906{
907 struct jffs2_inode_cache **prev; 907 struct jffs2_inode_cache **prev;
908 908
909#ifdef CONFIG_JFFS2_FS_XATTR
910 BUG_ON(old->xref);
911#endif
909 dbg_inocache("del %p (ino #%u)\n", old, old->ino); 912 dbg_inocache("del %p (ino #%u)\n", old, old->ino);
910 spin_lock(&c->inocache_lock); 913 spin_lock(&c->inocache_lock);
911 914
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index ac0c350ed7d7..d88376992ed9 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -683,19 +683,26 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
683 spin_lock(&c->erase_completion_lock); 683 spin_lock(&c->erase_completion_lock);
684 684
685 ic = jffs2_raw_ref_to_ic(ref); 685 ic = jffs2_raw_ref_to_ic(ref);
686 /* It seems we should never call jffs2_mark_node_obsolete() for
687 XATTR nodes.... yet. Make sure we notice if/when we change
688 that :) */
689 BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
690 for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino)) 686 for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino))
691 ; 687 ;
692 688
693 *p = ref->next_in_ino; 689 *p = ref->next_in_ino;
694 ref->next_in_ino = NULL; 690 ref->next_in_ino = NULL;
695 691
696 if (ic->nodes == (void *)ic && ic->nlink == 0) 692 switch (ic->class) {
697 jffs2_del_ino_cache(c, ic); 693#ifdef CONFIG_JFFS2_FS_XATTR
698 694 case RAWNODE_CLASS_XATTR_DATUM:
695 jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
696 break;
697 case RAWNODE_CLASS_XATTR_REF:
698 jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
699 break;
700#endif
701 default:
702 if (ic->nodes == (void *)ic && ic->nlink == 0)
703 jffs2_del_ino_cache(c, ic);
704 break;
705 }
699 spin_unlock(&c->erase_completion_lock); 706 spin_unlock(&c->erase_completion_lock);
700 } 707 }
701 708
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 6b5223565405..9f41fc01a371 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -158,7 +158,7 @@ extern struct inode_operations jffs2_dir_inode_operations;
158/* file.c */ 158/* file.c */
159extern const struct file_operations jffs2_file_operations; 159extern const struct file_operations jffs2_file_operations;
160extern struct inode_operations jffs2_file_inode_operations; 160extern struct inode_operations jffs2_file_inode_operations;
161extern struct address_space_operations jffs2_file_address_operations; 161extern const struct address_space_operations jffs2_file_address_operations;
162int jffs2_fsync(struct file *, struct dentry *, int); 162int jffs2_fsync(struct file *, struct dentry *, int);
163int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg); 163int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg);
164 164
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 5fec012b02ed..cc1899268c43 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -968,6 +968,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
968 struct jffs2_full_dirent *fd, *fds; 968 struct jffs2_full_dirent *fd, *fds;
969 int deleted; 969 int deleted;
970 970
971 jffs2_xattr_delete_inode(c, f->inocache);
971 down(&f->sem); 972 down(&f->sem);
972 deleted = f->inocache && !f->inocache->nlink; 973 deleted = f->inocache && !f->inocache->nlink;
973 974
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 61618080b86f..2bfdc33752d3 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -317,20 +317,23 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
317 struct jffs2_summary *s) 317 struct jffs2_summary *s)
318{ 318{
319 struct jffs2_xattr_datum *xd; 319 struct jffs2_xattr_datum *xd;
320 uint32_t totlen, crc; 320 uint32_t xid, version, totlen, crc;
321 int err; 321 int err;
322 322
323 crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4); 323 crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4);
324 if (crc != je32_to_cpu(rx->node_crc)) { 324 if (crc != je32_to_cpu(rx->node_crc)) {
325 if (je32_to_cpu(rx->node_crc) != 0xffffffff) 325 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
326 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 326 ofs, je32_to_cpu(rx->node_crc), crc);
327 ofs, je32_to_cpu(rx->node_crc), crc);
328 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen)))) 327 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
329 return err; 328 return err;
330 return 0; 329 return 0;
331 } 330 }
332 331
333 totlen = PAD(sizeof(*rx) + rx->name_len + 1 + je16_to_cpu(rx->value_len)); 332 xid = je32_to_cpu(rx->xid);
333 version = je32_to_cpu(rx->version);
334
335 totlen = PAD(sizeof(struct jffs2_raw_xattr)
336 + rx->name_len + 1 + je16_to_cpu(rx->value_len));
334 if (totlen != je32_to_cpu(rx->totlen)) { 337 if (totlen != je32_to_cpu(rx->totlen)) {
335 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n", 338 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n",
336 ofs, je32_to_cpu(rx->totlen), totlen); 339 ofs, je32_to_cpu(rx->totlen), totlen);
@@ -339,22 +342,24 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
339 return 0; 342 return 0;
340 } 343 }
341 344
342 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version)); 345 xd = jffs2_setup_xattr_datum(c, xid, version);
343 if (IS_ERR(xd)) { 346 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); 347 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 348
356 xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL); 349 if (xd->version > version) {
357 /* FIXME */ xd->node->next_in_ino = (void *)xd; 350 struct jffs2_raw_node_ref *raw
351 = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
352 raw->next_in_ino = xd->node->next_in_ino;
353 xd->node->next_in_ino = raw;
354 } else {
355 xd->version = version;
356 xd->xprefix = rx->xprefix;
357 xd->name_len = rx->name_len;
358 xd->value_len = je16_to_cpu(rx->value_len);
359 xd->data_crc = je32_to_cpu(rx->data_crc);
360
361 jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, (void *)xd);
362 }
358 363
359 if (jffs2_sum_active()) 364 if (jffs2_sum_active())
360 jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset); 365 jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
@@ -373,9 +378,8 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
373 378
374 crc = crc32(0, rr, sizeof(*rr) - 4); 379 crc = crc32(0, rr, sizeof(*rr) - 4);
375 if (crc != je32_to_cpu(rr->node_crc)) { 380 if (crc != je32_to_cpu(rr->node_crc)) {
376 if (je32_to_cpu(rr->node_crc) != 0xffffffff) 381 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
377 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 382 ofs, je32_to_cpu(rr->node_crc), crc);
378 ofs, je32_to_cpu(rr->node_crc), crc);
379 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen))))) 383 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen)))))
380 return err; 384 return err;
381 return 0; 385 return 0;
@@ -395,6 +399,7 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
395 return -ENOMEM; 399 return -ENOMEM;
396 400
397 /* BEFORE jffs2_build_xattr_subsystem() called, 401 /* BEFORE jffs2_build_xattr_subsystem() called,
402 * and AFTER xattr_ref is marked as a dead xref,
398 * ref->xid is used to store 32bit xid, xd is not used 403 * 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 404 * ref->ino is used to store 32bit inode-number, ic is not used
400 * Thoes variables are declared as union, thus using those 405 * Thoes variables are declared as union, thus using those
@@ -404,11 +409,13 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
404 */ 409 */
405 ref->ino = je32_to_cpu(rr->ino); 410 ref->ino = je32_to_cpu(rr->ino);
406 ref->xid = je32_to_cpu(rr->xid); 411 ref->xid = je32_to_cpu(rr->xid);
412 ref->xseqno = je32_to_cpu(rr->xseqno);
413 if (ref->xseqno > c->highest_xseqno)
414 c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
407 ref->next = c->xref_temp; 415 ref->next = c->xref_temp;
408 c->xref_temp = ref; 416 c->xref_temp = ref;
409 417
410 ref->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), NULL); 418 jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), (void *)ref);
411 /* FIXME */ ref->node->next_in_ino = (void *)ref;
412 419
413 if (jffs2_sum_active()) 420 if (jffs2_sum_active())
414 jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset); 421 jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index be1acc3dad97..c19bd476e8ec 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -5,7 +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 * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
9 * 9 *
10 * For licensing information, see the file 'LICENCE' in this directory. 10 * For licensing information, see the file 'LICENCE' in this directory.
11 * 11 *
@@ -310,8 +310,6 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
310#ifdef CONFIG_JFFS2_FS_XATTR 310#ifdef CONFIG_JFFS2_FS_XATTR
311 case JFFS2_NODETYPE_XATTR: { 311 case JFFS2_NODETYPE_XATTR: {
312 struct jffs2_sum_xattr_mem *temp; 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); 313 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
316 if (!temp) 314 if (!temp)
317 goto no_mem; 315 goto no_mem;
@@ -327,10 +325,6 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
327 } 325 }
328 case JFFS2_NODETYPE_XREF: { 326 case JFFS2_NODETYPE_XREF: {
329 struct jffs2_sum_xref_mem *temp; 327 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); 328 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
335 if (!temp) 329 if (!temp)
336 goto no_mem; 330 goto no_mem;
@@ -483,22 +477,20 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
483 477
484 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid), 478 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
485 je32_to_cpu(spx->version)); 479 je32_to_cpu(spx->version));
486 if (IS_ERR(xd)) { 480 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); 481 return PTR_ERR(xd);
482 if (xd->version > je32_to_cpu(spx->version)) {
483 /* node is not the newest one */
484 struct jffs2_raw_node_ref *raw
485 = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
486 PAD(je32_to_cpu(spx->totlen)), NULL);
487 raw->next_in_ino = xd->node->next_in_ino;
488 xd->node->next_in_ino = raw;
489 } else {
490 xd->version = je32_to_cpu(spx->version);
491 sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
492 PAD(je32_to_cpu(spx->totlen)), (void *)xd);
496 } 493 }
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); 494 *pseudo_random += je32_to_cpu(spx->xid);
503 sp += JFFS2_SUMMARY_XATTR_SIZE; 495 sp += JFFS2_SUMMARY_XATTR_SIZE;
504 496
@@ -519,14 +511,11 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
519 JFFS2_NOTICE("allocation of xattr_datum failed\n"); 511 JFFS2_NOTICE("allocation of xattr_datum failed\n");
520 return -ENOMEM; 512 return -ENOMEM;
521 } 513 }
522 ref->ino = 0xfffffffe;
523 ref->xid = 0xfffffffd;
524 ref->next = c->xref_temp; 514 ref->next = c->xref_temp;
525 c->xref_temp = ref; 515 c->xref_temp = ref;
526 516
527 ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED, 517 sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
528 PAD(sizeof(struct jffs2_raw_xref)), NULL); 518 PAD(sizeof(struct jffs2_raw_xref)), (void *)ref);
529 /* FIXME */ ref->node->next_in_ino = (void *)ref;
530 519
531 *pseudo_random += ref->node->flash_offset; 520 *pseudo_random += ref->node->flash_offset;
532 sp += JFFS2_SUMMARY_XREF_SIZE; 521 sp += JFFS2_SUMMARY_XREF_SIZE;
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 2d82e250be34..18e66dbf23b4 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -23,18 +23,15 @@
23 * xattr_datum_hashkey(xprefix, xname, xvalue, xsize) 23 * xattr_datum_hashkey(xprefix, xname, xvalue, xsize)
24 * is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is 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). 25 * the index of the xattr name/value pair cache (c->xattrindex).
26 * is_xattr_datum_unchecked(c, xd)
27 * returns 1, if xdatum contains any unchecked raw nodes. if all raw nodes are not
28 * unchecked, it returns 0.
26 * unload_xattr_datum(c, xd) 29 * unload_xattr_datum(c, xd)
27 * is used to release xattr name/value pair and detach from c->xattrindex. 30 * is used to release xattr name/value pair and detach from c->xattrindex.
28 * reclaim_xattr_datum(c) 31 * reclaim_xattr_datum(c)
29 * is used to reclaim xattr name/value pairs on the xattr name/value pair cache when 32 * 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 33 * memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold
31 * is hard coded as 32KiB. 34 * 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) 35 * do_verify_xattr_datum(c, xd)
39 * is used to load the xdatum informations without name/value pair from the medium. 36 * 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 37 * It's necessary once, because those informations are not collected during mounting
@@ -53,8 +50,10 @@
53 * is used to write xdatum to medium. xd->version will be incremented. 50 * is used to write xdatum to medium. xd->version will be incremented.
54 * create_xattr_datum(c, xprefix, xname, xvalue, xsize) 51 * create_xattr_datum(c, xprefix, xname, xvalue, xsize)
55 * is used to create new xdatum and write to medium. 52 * is used to create new xdatum and write to medium.
53 * delete_xattr_datum(c, xd)
54 * is used to delete a xdatum. It marks xd JFFS2_XFLAGS_DEAD, and allows
55 * GC to reclaim those physical nodes.
56 * -------------------------------------------------- */ 56 * -------------------------------------------------- */
57
58static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize) 57static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
59{ 58{
60 int name_len = strlen(xname); 59 int name_len = strlen(xname);
@@ -62,6 +61,22 @@ static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *
62 return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize); 61 return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize);
63} 62}
64 63
64static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
65{
66 struct jffs2_raw_node_ref *raw;
67 int rc = 0;
68
69 spin_lock(&c->erase_completion_lock);
70 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
71 if (ref_flags(raw) == REF_UNCHECKED) {
72 rc = 1;
73 break;
74 }
75 }
76 spin_unlock(&c->erase_completion_lock);
77 return rc;
78}
79
65static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 80static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
66{ 81{
67 /* must be called under down_write(xattr_sem) */ 82 /* must be called under down_write(xattr_sem) */
@@ -107,77 +122,33 @@ static void reclaim_xattr_datum(struct jffs2_sb_info *c)
107 before, c->xdatum_mem_usage, before - c->xdatum_mem_usage); 122 before, c->xdatum_mem_usage, before - c->xdatum_mem_usage);
108} 123}
109 124
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) 125static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
159{ 126{
160 /* must be called under down_write(xattr_sem) */ 127 /* must be called under down_write(xattr_sem) */
161 struct jffs2_eraseblock *jeb; 128 struct jffs2_eraseblock *jeb;
129 struct jffs2_raw_node_ref *raw;
162 struct jffs2_raw_xattr rx; 130 struct jffs2_raw_xattr rx;
163 size_t readlen; 131 size_t readlen;
164 uint32_t crc, totlen; 132 uint32_t crc, offset, totlen;
165 int rc; 133 int rc;
166 134
167 BUG_ON(!xd->node); 135 spin_lock(&c->erase_completion_lock);
168 BUG_ON(ref_flags(xd->node) != REF_UNCHECKED); 136 offset = ref_offset(xd->node);
137 if (ref_flags(xd->node) == REF_PRISTINE)
138 goto complete;
139 spin_unlock(&c->erase_completion_lock);
169 140
170 rc = jffs2_flash_read(c, ref_offset(xd->node), sizeof(rx), &readlen, (char *)&rx); 141 rc = jffs2_flash_read(c, offset, sizeof(rx), &readlen, (char *)&rx);
171 if (rc || readlen != sizeof(rx)) { 142 if (rc || readlen != sizeof(rx)) {
172 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", 143 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
173 rc, sizeof(rx), readlen, ref_offset(xd->node)); 144 rc, sizeof(rx), readlen, offset);
174 return rc ? rc : -EIO; 145 return rc ? rc : -EIO;
175 } 146 }
176 crc = crc32(0, &rx, sizeof(rx) - 4); 147 crc = crc32(0, &rx, sizeof(rx) - 4);
177 if (crc != je32_to_cpu(rx.node_crc)) { 148 if (crc != je32_to_cpu(rx.node_crc)) {
178 if (je32_to_cpu(rx.node_crc) != 0xffffffff) 149 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
179 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 150 offset, je32_to_cpu(rx.hdr_crc), crc);
180 ref_offset(xd->node), je32_to_cpu(rx.hdr_crc), crc); 151 xd->flags |= JFFS2_XFLAGS_INVALID;
181 return EIO; 152 return EIO;
182 } 153 }
183 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len)); 154 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
@@ -188,11 +159,12 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat
188 || je32_to_cpu(rx.version) != xd->version) { 159 || je32_to_cpu(rx.version) != xd->version) {
189 JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, " 160 JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, "
190 "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n", 161 "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, 162 offset, je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK,
192 je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR, 163 je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR,
193 je32_to_cpu(rx.totlen), totlen, 164 je32_to_cpu(rx.totlen), totlen,
194 je32_to_cpu(rx.xid), xd->xid, 165 je32_to_cpu(rx.xid), xd->xid,
195 je32_to_cpu(rx.version), xd->version); 166 je32_to_cpu(rx.version), xd->version);
167 xd->flags |= JFFS2_XFLAGS_INVALID;
196 return EIO; 168 return EIO;
197 } 169 }
198 xd->xprefix = rx.xprefix; 170 xd->xprefix = rx.xprefix;
@@ -200,14 +172,17 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat
200 xd->value_len = je16_to_cpu(rx.value_len); 172 xd->value_len = je16_to_cpu(rx.value_len);
201 xd->data_crc = je32_to_cpu(rx.data_crc); 173 xd->data_crc = je32_to_cpu(rx.data_crc);
202 174
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); 175 spin_lock(&c->erase_completion_lock);
208 c->unchecked_size -= totlen; c->used_size += totlen; 176 complete:
209 jeb->unchecked_size -= totlen; jeb->used_size += totlen; 177 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
210 xd->node->flash_offset = ref_offset(xd->node) | REF_PRISTINE; 178 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
179 totlen = PAD(ref_totlen(c, jeb, raw));
180 if (ref_flags(raw) == REF_UNCHECKED) {
181 c->unchecked_size -= totlen; c->used_size += totlen;
182 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
183 }
184 raw->flash_offset = ref_offset(raw) | ((xd->node==raw) ? REF_PRISTINE : REF_NORMAL);
185 }
211 spin_unlock(&c->erase_completion_lock); 186 spin_unlock(&c->erase_completion_lock);
212 187
213 /* unchecked xdatum is chained with c->xattr_unchecked */ 188 /* unchecked xdatum is chained with c->xattr_unchecked */
@@ -227,7 +202,6 @@ static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum
227 uint32_t crc, length; 202 uint32_t crc, length;
228 int i, ret, retry = 0; 203 int i, ret, retry = 0;
229 204
230 BUG_ON(!xd->node);
231 BUG_ON(ref_flags(xd->node) != REF_PRISTINE); 205 BUG_ON(ref_flags(xd->node) != REF_PRISTINE);
232 BUG_ON(!list_empty(&xd->xindex)); 206 BUG_ON(!list_empty(&xd->xindex));
233 retry: 207 retry:
@@ -253,6 +227,7 @@ static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum
253 " at %#08x, read: 0x%08x calculated: 0x%08x\n", 227 " at %#08x, read: 0x%08x calculated: 0x%08x\n",
254 ref_offset(xd->node), xd->data_crc, crc); 228 ref_offset(xd->node), xd->data_crc, crc);
255 kfree(data); 229 kfree(data);
230 xd->flags |= JFFS2_XFLAGS_INVALID;
256 return EIO; 231 return EIO;
257 } 232 }
258 233
@@ -286,16 +261,14 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
286 * rc > 0 : Unrecoverable error, this node should be deleted. 261 * rc > 0 : Unrecoverable error, this node should be deleted.
287 */ 262 */
288 int rc = 0; 263 int rc = 0;
289 BUG_ON(xd->xname); 264
290 if (!xd->node) 265 BUG_ON(xd->flags & JFFS2_XFLAGS_DEAD);
266 if (xd->xname)
267 return 0;
268 if (xd->flags & JFFS2_XFLAGS_INVALID)
291 return EIO; 269 return EIO;
292 if (unlikely(ref_flags(xd->node) != REF_PRISTINE)) { 270 if (unlikely(is_xattr_datum_unchecked(c, xd)))
293 rc = do_verify_xattr_datum(c, xd); 271 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) 272 if (!rc)
300 rc = do_load_xattr_datum(c, xd); 273 rc = do_load_xattr_datum(c, xd);
301 return rc; 274 return rc;
@@ -304,7 +277,6 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
304static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 277static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
305{ 278{
306 /* must be called under down_write(xattr_sem) */ 279 /* must be called under down_write(xattr_sem) */
307 struct jffs2_raw_node_ref *raw;
308 struct jffs2_raw_xattr rx; 280 struct jffs2_raw_xattr rx;
309 struct kvec vecs[2]; 281 struct kvec vecs[2];
310 size_t length; 282 size_t length;
@@ -312,14 +284,16 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
312 uint32_t phys_ofs = write_ofs(c); 284 uint32_t phys_ofs = write_ofs(c);
313 285
314 BUG_ON(!xd->xname); 286 BUG_ON(!xd->xname);
287 BUG_ON(xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID));
315 288
316 vecs[0].iov_base = &rx; 289 vecs[0].iov_base = &rx;
317 vecs[0].iov_len = PAD(sizeof(rx)); 290 vecs[0].iov_len = sizeof(rx);
318 vecs[1].iov_base = xd->xname; 291 vecs[1].iov_base = xd->xname;
319 vecs[1].iov_len = xd->name_len + 1 + xd->value_len; 292 vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
320 totlen = vecs[0].iov_len + vecs[1].iov_len; 293 totlen = vecs[0].iov_len + vecs[1].iov_len;
321 294
322 /* Setup raw-xattr */ 295 /* Setup raw-xattr */
296 memset(&rx, 0, sizeof(rx));
323 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 297 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
324 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); 298 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
325 rx.totlen = cpu_to_je32(PAD(totlen)); 299 rx.totlen = cpu_to_je32(PAD(totlen));
@@ -343,14 +317,8 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
343 317
344 return rc; 318 return rc;
345 } 319 }
346
347 /* success */ 320 /* success */
348 raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), NULL); 321 jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), (void *)xd);
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 322
355 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n", 323 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n",
356 xd->xid, xd->version, xd->xprefix, xd->xname); 324 xd->xid, xd->version, xd->xprefix, xd->xname);
@@ -377,7 +345,7 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
377 && xd->value_len==xsize 345 && xd->value_len==xsize
378 && !strcmp(xd->xname, xname) 346 && !strcmp(xd->xname, xname)
379 && !memcmp(xd->xvalue, xvalue, xsize)) { 347 && !memcmp(xd->xvalue, xvalue, xsize)) {
380 xd->refcnt++; 348 atomic_inc(&xd->refcnt);
381 return xd; 349 return xd;
382 } 350 }
383 } 351 }
@@ -397,7 +365,7 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
397 strcpy(data, xname); 365 strcpy(data, xname);
398 memcpy(data + name_len + 1, xvalue, xsize); 366 memcpy(data + name_len + 1, xvalue, xsize);
399 367
400 xd->refcnt = 1; 368 atomic_set(&xd->refcnt, 1);
401 xd->xid = ++c->highest_xid; 369 xd->xid = ++c->highest_xid;
402 xd->flags |= JFFS2_XFLAGS_HOT; 370 xd->flags |= JFFS2_XFLAGS_HOT;
403 xd->xprefix = xprefix; 371 xd->xprefix = xprefix;
@@ -426,20 +394,36 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
426 return xd; 394 return xd;
427} 395}
428 396
397static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
398{
399 /* must be called under down_write(xattr_sem) */
400 BUG_ON(atomic_read(&xd->refcnt));
401
402 unload_xattr_datum(c, xd);
403 xd->flags |= JFFS2_XFLAGS_DEAD;
404 spin_lock(&c->erase_completion_lock);
405 if (xd->node == (void *)xd) {
406 BUG_ON(!(xd->flags & JFFS2_XFLAGS_INVALID));
407 jffs2_free_xattr_datum(xd);
408 } else {
409 list_add(&xd->xindex, &c->xattr_dead_list);
410 }
411 spin_unlock(&c->erase_completion_lock);
412 dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xd->xid, xd->version);
413}
414
429/* -------- xref related functions ------------------ 415/* -------- xref related functions ------------------
430 * verify_xattr_ref(c, ref) 416 * verify_xattr_ref(c, ref)
431 * is used to load xref information from medium. Because summary data does not 417 * 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. 418 * 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) 419 * save_xattr_ref(c, ref)
440 * is used to write xref to medium. 420 * is used to write xref to medium. If delete marker is marked, it write
421 * a delete marker of xref into medium.
441 * create_xattr_ref(c, ic, xd) 422 * create_xattr_ref(c, ic, xd)
442 * is used to create a new xref and write to medium. 423 * is used to create a new xref and write to medium.
424 * delete_xattr_ref(c, ref)
425 * is used to delete jffs2_xattr_ref. It marks xref XREF_DELETE_MARKER,
426 * and allows GC to reclaim those physical nodes.
443 * jffs2_xattr_delete_inode(c, ic) 427 * jffs2_xattr_delete_inode(c, ic)
444 * is called to remove xrefs related to obsolete inode when inode is unlinked. 428 * is called to remove xrefs related to obsolete inode when inode is unlinked.
445 * jffs2_xattr_free_inode(c, ic) 429 * jffs2_xattr_free_inode(c, ic)
@@ -450,25 +434,29 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
450static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) 434static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
451{ 435{
452 struct jffs2_eraseblock *jeb; 436 struct jffs2_eraseblock *jeb;
437 struct jffs2_raw_node_ref *raw;
453 struct jffs2_raw_xref rr; 438 struct jffs2_raw_xref rr;
454 size_t readlen; 439 size_t readlen;
455 uint32_t crc, totlen; 440 uint32_t crc, offset, totlen;
456 int rc; 441 int rc;
457 442
458 BUG_ON(ref_flags(ref->node) != REF_UNCHECKED); 443 spin_lock(&c->erase_completion_lock);
444 if (ref_flags(ref->node) != REF_UNCHECKED)
445 goto complete;
446 offset = ref_offset(ref->node);
447 spin_unlock(&c->erase_completion_lock);
459 448
460 rc = jffs2_flash_read(c, ref_offset(ref->node), sizeof(rr), &readlen, (char *)&rr); 449 rc = jffs2_flash_read(c, offset, sizeof(rr), &readlen, (char *)&rr);
461 if (rc || sizeof(rr) != readlen) { 450 if (rc || sizeof(rr) != readlen) {
462 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n", 451 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n",
463 rc, sizeof(rr), readlen, ref_offset(ref->node)); 452 rc, sizeof(rr), readlen, offset);
464 return rc ? rc : -EIO; 453 return rc ? rc : -EIO;
465 } 454 }
466 /* obsolete node */ 455 /* obsolete node */
467 crc = crc32(0, &rr, sizeof(rr) - 4); 456 crc = crc32(0, &rr, sizeof(rr) - 4);
468 if (crc != je32_to_cpu(rr.node_crc)) { 457 if (crc != je32_to_cpu(rr.node_crc)) {
469 if (je32_to_cpu(rr.node_crc) != 0xffffffff) 458 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
470 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 459 offset, je32_to_cpu(rr.node_crc), crc);
471 ref_offset(ref->node), je32_to_cpu(rr.node_crc), crc);
472 return EIO; 460 return EIO;
473 } 461 }
474 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK 462 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
@@ -476,22 +464,28 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref
476 || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) { 464 || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {
477 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, " 465 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "
478 "nodetype=%#04x/%#04x, totlen=%u/%zu\n", 466 "nodetype=%#04x/%#04x, totlen=%u/%zu\n",
479 ref_offset(ref->node), je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK, 467 offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
480 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF, 468 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
481 je32_to_cpu(rr.totlen), PAD(sizeof(rr))); 469 je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
482 return EIO; 470 return EIO;
483 } 471 }
484 ref->ino = je32_to_cpu(rr.ino); 472 ref->ino = je32_to_cpu(rr.ino);
485 ref->xid = je32_to_cpu(rr.xid); 473 ref->xid = je32_to_cpu(rr.xid);
486 474 ref->xseqno = je32_to_cpu(rr.xseqno);
487 /* fixup superblock/eraseblock info */ 475 if (ref->xseqno > c->highest_xseqno)
488 jeb = &c->blocks[ref_offset(ref->node) / c->sector_size]; 476 c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
489 totlen = PAD(sizeof(rr));
490 477
491 spin_lock(&c->erase_completion_lock); 478 spin_lock(&c->erase_completion_lock);
492 c->unchecked_size -= totlen; c->used_size += totlen; 479 complete:
493 jeb->unchecked_size -= totlen; jeb->used_size += totlen; 480 for (raw=ref->node; raw != (void *)ref; raw=raw->next_in_ino) {
494 ref->node->flash_offset = ref_offset(ref->node) | REF_PRISTINE; 481 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
482 totlen = PAD(ref_totlen(c, jeb, raw));
483 if (ref_flags(raw) == REF_UNCHECKED) {
484 c->unchecked_size -= totlen; c->used_size += totlen;
485 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
486 }
487 raw->flash_offset = ref_offset(raw) | ((ref->node==raw) ? REF_PRISTINE : REF_NORMAL);
488 }
495 spin_unlock(&c->erase_completion_lock); 489 spin_unlock(&c->erase_completion_lock);
496 490
497 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n", 491 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",
@@ -499,58 +493,12 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref
499 return 0; 493 return 0;
500} 494}
501 495
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) 496static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
548{ 497{
549 /* must be called under down_write(xattr_sem) */ 498 /* must be called under down_write(xattr_sem) */
550 struct jffs2_raw_node_ref *raw;
551 struct jffs2_raw_xref rr; 499 struct jffs2_raw_xref rr;
552 size_t length; 500 size_t length;
553 uint32_t phys_ofs = write_ofs(c); 501 uint32_t xseqno, phys_ofs = write_ofs(c);
554 int ret; 502 int ret;
555 503
556 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 504 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -558,8 +506,16 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
558 rr.totlen = cpu_to_je32(PAD(sizeof(rr))); 506 rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
559 rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4)); 507 rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4));
560 508
561 rr.ino = cpu_to_je32(ref->ic->ino); 509 xseqno = (c->highest_xseqno += 2);
562 rr.xid = cpu_to_je32(ref->xd->xid); 510 if (is_xattr_ref_dead(ref)) {
511 xseqno |= XREF_DELETE_MARKER;
512 rr.ino = cpu_to_je32(ref->ino);
513 rr.xid = cpu_to_je32(ref->xid);
514 } else {
515 rr.ino = cpu_to_je32(ref->ic->ino);
516 rr.xid = cpu_to_je32(ref->xd->xid);
517 }
518 rr.xseqno = cpu_to_je32(xseqno);
563 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4)); 519 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));
564 520
565 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr); 521 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);
@@ -572,12 +528,9 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
572 528
573 return ret; 529 return ret;
574 } 530 }
575 531 /* success */
576 raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), NULL); 532 ref->xseqno = xseqno;
577 /* FIXME */ raw->next_in_ino = (void *)ref; 533 jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), (void *)ref);
578 if (ref->node)
579 delete_xattr_ref_node(c, ref);
580 ref->node = raw;
581 534
582 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid); 535 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);
583 536
@@ -610,6 +563,27 @@ static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct
610 return ref; /* success */ 563 return ref; /* success */
611} 564}
612 565
566static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
567{
568 /* must be called under down_write(xattr_sem) */
569 struct jffs2_xattr_datum *xd;
570
571 xd = ref->xd;
572 ref->xseqno |= XREF_DELETE_MARKER;
573 ref->ino = ref->ic->ino;
574 ref->xid = ref->xd->xid;
575 spin_lock(&c->erase_completion_lock);
576 ref->next = c->xref_dead_list;
577 c->xref_dead_list = ref;
578 spin_unlock(&c->erase_completion_lock);
579
580 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) was removed.\n",
581 ref->ino, ref->xid, ref->xseqno);
582
583 if (atomic_dec_and_test(&xd->refcnt))
584 delete_xattr_datum(c, xd);
585}
586
613void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) 587void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
614{ 588{
615 /* It's called from jffs2_clear_inode() on inode removing. 589 /* It's called from jffs2_clear_inode() on inode removing.
@@ -638,8 +612,7 @@ void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
638 for (ref = ic->xref; ref; ref = _ref) { 612 for (ref = ic->xref; ref; ref = _ref) {
639 _ref = ref->next; 613 _ref = ref->next;
640 xd = ref->xd; 614 xd = ref->xd;
641 xd->refcnt--; 615 if (atomic_dec_and_test(&xd->refcnt)) {
642 if (!xd->refcnt) {
643 unload_xattr_datum(c, xd); 616 unload_xattr_datum(c, xd);
644 jffs2_free_xattr_datum(xd); 617 jffs2_free_xattr_datum(xd);
645 } 618 }
@@ -655,7 +628,7 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
655 * duplicate name/value pairs. If duplicate name/value pair would be found, 628 * duplicate name/value pairs. If duplicate name/value pair would be found,
656 * one will be removed. 629 * one will be removed.
657 */ 630 */
658 struct jffs2_xattr_ref *ref, *cmp, **pref; 631 struct jffs2_xattr_ref *ref, *cmp, **pref, **pcmp;
659 int rc = 0; 632 int rc = 0;
660 633
661 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED)) 634 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
@@ -673,13 +646,13 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
673 } else if (unlikely(rc < 0)) 646 } else if (unlikely(rc < 0))
674 goto out; 647 goto out;
675 } 648 }
676 for (cmp=ref->next, pref=&ref->next; cmp; pref=&cmp->next, cmp=cmp->next) { 649 for (cmp=ref->next, pcmp=&ref->next; cmp; pcmp=&cmp->next, cmp=cmp->next) {
677 if (!cmp->xd->xname) { 650 if (!cmp->xd->xname) {
678 ref->xd->flags |= JFFS2_XFLAGS_BIND; 651 ref->xd->flags |= JFFS2_XFLAGS_BIND;
679 rc = load_xattr_datum(c, cmp->xd); 652 rc = load_xattr_datum(c, cmp->xd);
680 ref->xd->flags &= ~JFFS2_XFLAGS_BIND; 653 ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
681 if (unlikely(rc > 0)) { 654 if (unlikely(rc > 0)) {
682 *pref = cmp->next; 655 *pcmp = cmp->next;
683 delete_xattr_ref(c, cmp); 656 delete_xattr_ref(c, cmp);
684 goto retry; 657 goto retry;
685 } else if (unlikely(rc < 0)) 658 } else if (unlikely(rc < 0))
@@ -687,8 +660,13 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
687 } 660 }
688 if (ref->xd->xprefix == cmp->xd->xprefix 661 if (ref->xd->xprefix == cmp->xd->xprefix
689 && !strcmp(ref->xd->xname, cmp->xd->xname)) { 662 && !strcmp(ref->xd->xname, cmp->xd->xname)) {
690 *pref = cmp->next; 663 if (ref->xseqno > cmp->xseqno) {
691 delete_xattr_ref(c, cmp); 664 *pcmp = cmp->next;
665 delete_xattr_ref(c, cmp);
666 } else {
667 *pref = ref->next;
668 delete_xattr_ref(c, ref);
669 }
692 goto retry; 670 goto retry;
693 } 671 }
694 } 672 }
@@ -719,9 +697,13 @@ void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c)
719 for (i=0; i < XATTRINDEX_HASHSIZE; i++) 697 for (i=0; i < XATTRINDEX_HASHSIZE; i++)
720 INIT_LIST_HEAD(&c->xattrindex[i]); 698 INIT_LIST_HEAD(&c->xattrindex[i]);
721 INIT_LIST_HEAD(&c->xattr_unchecked); 699 INIT_LIST_HEAD(&c->xattr_unchecked);
700 INIT_LIST_HEAD(&c->xattr_dead_list);
701 c->xref_dead_list = NULL;
722 c->xref_temp = NULL; 702 c->xref_temp = NULL;
723 703
724 init_rwsem(&c->xattr_sem); 704 init_rwsem(&c->xattr_sem);
705 c->highest_xid = 0;
706 c->highest_xseqno = 0;
725 c->xdatum_mem_usage = 0; 707 c->xdatum_mem_usage = 0;
726 c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */ 708 c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */
727} 709}
@@ -751,7 +733,11 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
751 _ref = ref->next; 733 _ref = ref->next;
752 jffs2_free_xattr_ref(ref); 734 jffs2_free_xattr_ref(ref);
753 } 735 }
754 c->xref_temp = NULL; 736
737 for (ref=c->xref_dead_list; ref; ref = _ref) {
738 _ref = ref->next;
739 jffs2_free_xattr_ref(ref);
740 }
755 741
756 for (i=0; i < XATTRINDEX_HASHSIZE; i++) { 742 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
757 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { 743 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
@@ -761,100 +747,143 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
761 jffs2_free_xattr_datum(xd); 747 jffs2_free_xattr_datum(xd);
762 } 748 }
763 } 749 }
750
751 list_for_each_entry_safe(xd, _xd, &c->xattr_dead_list, xindex) {
752 list_del(&xd->xindex);
753 jffs2_free_xattr_datum(xd);
754 }
764} 755}
765 756
757#define XREF_TMPHASH_SIZE (128)
766void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) 758void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
767{ 759{
768 struct jffs2_xattr_ref *ref, *_ref; 760 struct jffs2_xattr_ref *ref, *_ref;
761 struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE];
769 struct jffs2_xattr_datum *xd, *_xd; 762 struct jffs2_xattr_datum *xd, *_xd;
770 struct jffs2_inode_cache *ic; 763 struct jffs2_inode_cache *ic;
771 int i, xdatum_count =0, xdatum_unchecked_count = 0, xref_count = 0; 764 struct jffs2_raw_node_ref *raw;
765 int i, xdatum_count = 0, xdatum_unchecked_count = 0, xref_count = 0;
766 int xdatum_orphan_count = 0, xref_orphan_count = 0, xref_dead_count = 0;
772 767
773 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); 768 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
774 769
775 /* Phase.1 */ 770 /* Phase.1 : Merge same xref */
771 for (i=0; i < XREF_TMPHASH_SIZE; i++)
772 xref_tmphash[i] = NULL;
776 for (ref=c->xref_temp; ref; ref=_ref) { 773 for (ref=c->xref_temp; ref; ref=_ref) {
774 struct jffs2_xattr_ref *tmp;
775
777 _ref = ref->next; 776 _ref = ref->next;
778 /* checking REF_UNCHECKED nodes */
779 if (ref_flags(ref->node) != REF_PRISTINE) { 777 if (ref_flags(ref->node) != REF_PRISTINE) {
780 if (verify_xattr_ref(c, ref)) { 778 if (verify_xattr_ref(c, ref)) {
781 delete_xattr_ref_node(c, ref); 779 BUG_ON(ref->node->next_in_ino != (void *)ref);
780 ref->node->next_in_ino = NULL;
781 jffs2_mark_node_obsolete(c, ref->node);
782 jffs2_free_xattr_ref(ref); 782 jffs2_free_xattr_ref(ref);
783 continue; 783 continue;
784 } 784 }
785 } 785 }
786 /* At this point, ref->xid and ref->ino contain XID and inode number. 786
787 ref->xd and ref->ic are not valid yet. */ 787 i = (ref->ino ^ ref->xid) % XREF_TMPHASH_SIZE;
788 xd = jffs2_find_xattr_datum(c, ref->xid); 788 for (tmp=xref_tmphash[i]; tmp; tmp=tmp->next) {
789 ic = jffs2_get_ino_cache(c, ref->ino); 789 if (tmp->ino == ref->ino && tmp->xid == ref->xid)
790 if (!xd || !ic) { 790 break;
791 if (ref_flags(ref->node) != REF_UNCHECKED) 791 }
792 JFFS2_WARNING("xref(ino=%u, xid=%u) is orphan. \n", 792 if (tmp) {
793 ref->ino, ref->xid); 793 raw = ref->node;
794 delete_xattr_ref_node(c, ref); 794 if (ref->xseqno > tmp->xseqno) {
795 tmp->xseqno = ref->xseqno;
796 raw->next_in_ino = tmp->node;
797 tmp->node = raw;
798 } else {
799 raw->next_in_ino = tmp->node->next_in_ino;
800 tmp->node->next_in_ino = raw;
801 }
795 jffs2_free_xattr_ref(ref); 802 jffs2_free_xattr_ref(ref);
796 continue; 803 continue;
804 } else {
805 ref->next = xref_tmphash[i];
806 xref_tmphash[i] = ref;
797 } 807 }
798 ref->xd = xd;
799 ref->ic = ic;
800 xd->refcnt++;
801 ref->next = ic->xref;
802 ic->xref = ref;
803 xref_count++;
804 } 808 }
805 c->xref_temp = NULL; 809 c->xref_temp = NULL;
806 /* After this, ref->xid/ino are NEVER used. */
807 810
808 /* Phase.2 */ 811 /* Phase.2 : Bind xref with inode_cache and xattr_datum */
812 for (i=0; i < XREF_TMPHASH_SIZE; i++) {
813 for (ref=xref_tmphash[i]; ref; ref=_ref) {
814 xref_count++;
815 _ref = ref->next;
816 if (is_xattr_ref_dead(ref)) {
817 ref->next = c->xref_dead_list;
818 c->xref_dead_list = ref;
819 xref_dead_count++;
820 continue;
821 }
822 /* At this point, ref->xid and ref->ino contain XID and inode number.
823 ref->xd and ref->ic are not valid yet. */
824 xd = jffs2_find_xattr_datum(c, ref->xid);
825 ic = jffs2_get_ino_cache(c, ref->ino);
826 if (!xd || !ic) {
827 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
828 ref->ino, ref->xid, ref->xseqno);
829 ref->xseqno |= XREF_DELETE_MARKER;
830 ref->next = c->xref_dead_list;
831 c->xref_dead_list = ref;
832 xref_orphan_count++;
833 continue;
834 }
835 ref->xd = xd;
836 ref->ic = ic;
837 atomic_inc(&xd->refcnt);
838 ref->next = ic->xref;
839 ic->xref = ref;
840 }
841 }
842
843 /* Phase.3 : Link unchecked xdatum to xattr_unchecked list */
809 for (i=0; i < XATTRINDEX_HASHSIZE; i++) { 844 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
810 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { 845 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
846 xdatum_count++;
811 list_del_init(&xd->xindex); 847 list_del_init(&xd->xindex);
812 if (!xd->refcnt) { 848 if (!atomic_read(&xd->refcnt)) {
813 if (ref_flags(xd->node) != REF_UNCHECKED) 849 dbg_xattr("xdatum(xid=%u, version=%u) is orphan.\n",
814 JFFS2_WARNING("orphan xdatum(xid=%u, version=%u) at %#08x\n", 850 xd->xid, xd->version);
815 xd->xid, xd->version, ref_offset(xd->node)); 851 xd->flags |= JFFS2_XFLAGS_DEAD;
816 delete_xattr_datum(c, xd); 852 list_add(&xd->xindex, &c->xattr_unchecked);
853 xdatum_orphan_count++;
817 continue; 854 continue;
818 } 855 }
819 if (ref_flags(xd->node) != REF_PRISTINE) { 856 if (is_xattr_datum_unchecked(c, xd)) {
820 dbg_xattr("unchecked xdatum(xid=%u) at %#08x\n", 857 dbg_xattr("unchecked xdatum(xid=%u, version=%u)\n",
821 xd->xid, ref_offset(xd->node)); 858 xd->xid, xd->version);
822 list_add(&xd->xindex, &c->xattr_unchecked); 859 list_add(&xd->xindex, &c->xattr_unchecked);
823 xdatum_unchecked_count++; 860 xdatum_unchecked_count++;
824 } 861 }
825 xdatum_count++;
826 } 862 }
827 } 863 }
828 /* build complete */ 864 /* build complete */
829 JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum (%u unchecked) and " 865 JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum"
830 "%u of xref found.\n", xdatum_count, xdatum_unchecked_count, xref_count); 866 " (%u unchecked, %u orphan) and "
867 "%u of xref (%u dead, %u orphan) found.\n",
868 xdatum_count, xdatum_unchecked_count, xdatum_orphan_count,
869 xref_count, xref_dead_count, xref_orphan_count);
831} 870}
832 871
833struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, 872struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
834 uint32_t xid, uint32_t version) 873 uint32_t xid, uint32_t version)
835{ 874{
836 struct jffs2_xattr_datum *xd, *_xd; 875 struct jffs2_xattr_datum *xd;
837 876
838 _xd = jffs2_find_xattr_datum(c, xid); 877 xd = jffs2_find_xattr_datum(c, xid);
839 if (_xd) { 878 if (!xd) {
840 dbg_xattr("duplicate xdatum (xid=%u, version=%u/%u) at %#08x\n", 879 xd = jffs2_alloc_xattr_datum();
841 xid, version, _xd->version, ref_offset(_xd->node)); 880 if (!xd)
842 if (version < _xd->version) 881 return ERR_PTR(-ENOMEM);
843 return ERR_PTR(-EEXIST); 882 xd->xid = xid;
844 } 883 xd->version = version;
845 xd = jffs2_alloc_xattr_datum(); 884 if (xd->xid > c->highest_xid)
846 if (!xd) 885 c->highest_xid = xd->xid;
847 return ERR_PTR(-ENOMEM); 886 list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);
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 } 887 }
859 return xd; 888 return xd;
860} 889}
@@ -1080,9 +1109,23 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1080 goto out; 1109 goto out;
1081 } 1110 }
1082 if (!buffer) { 1111 if (!buffer) {
1083 *pref = ref->next; 1112 ref->ino = ic->ino;
1084 delete_xattr_ref(c, ref); 1113 ref->xid = xd->xid;
1085 rc = 0; 1114 ref->xseqno |= XREF_DELETE_MARKER;
1115 rc = save_xattr_ref(c, ref);
1116 if (!rc) {
1117 *pref = ref->next;
1118 spin_lock(&c->erase_completion_lock);
1119 ref->next = c->xref_dead_list;
1120 c->xref_dead_list = ref;
1121 spin_unlock(&c->erase_completion_lock);
1122 if (atomic_dec_and_test(&xd->refcnt))
1123 delete_xattr_datum(c, xd);
1124 } else {
1125 ref->ic = ic;
1126 ref->xd = xd;
1127 ref->xseqno &= ~XREF_DELETE_MARKER;
1128 }
1086 goto out; 1129 goto out;
1087 } 1130 }
1088 goto found; 1131 goto found;
@@ -1094,7 +1137,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1094 goto out; 1137 goto out;
1095 } 1138 }
1096 if (!buffer) { 1139 if (!buffer) {
1097 rc = -EINVAL; 1140 rc = -ENODATA;
1098 goto out; 1141 goto out;
1099 } 1142 }
1100 found: 1143 found:
@@ -1110,16 +1153,14 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1110 request = PAD(sizeof(struct jffs2_raw_xref)); 1153 request = PAD(sizeof(struct jffs2_raw_xref));
1111 rc = jffs2_reserve_space(c, request, &length, 1154 rc = jffs2_reserve_space(c, request, &length,
1112 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE); 1155 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE);
1156 down_write(&c->xattr_sem);
1113 if (rc) { 1157 if (rc) {
1114 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); 1158 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1115 down_write(&c->xattr_sem); 1159 if (atomic_dec_and_test(&xd->refcnt))
1116 xd->refcnt--;
1117 if (!xd->refcnt)
1118 delete_xattr_datum(c, xd); 1160 delete_xattr_datum(c, xd);
1119 up_write(&c->xattr_sem); 1161 up_write(&c->xattr_sem);
1120 return rc; 1162 return rc;
1121 } 1163 }
1122 down_write(&c->xattr_sem);
1123 if (ref) 1164 if (ref)
1124 *pref = ref->next; 1165 *pref = ref->next;
1125 newref = create_xattr_ref(c, ic, xd); 1166 newref = create_xattr_ref(c, ic, xd);
@@ -1129,8 +1170,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1129 ic->xref = ref; 1170 ic->xref = ref;
1130 } 1171 }
1131 rc = PTR_ERR(newref); 1172 rc = PTR_ERR(newref);
1132 xd->refcnt--; 1173 if (atomic_dec_and_test(&xd->refcnt))
1133 if (!xd->refcnt)
1134 delete_xattr_datum(c, xd); 1174 delete_xattr_datum(c, xd);
1135 } else if (ref) { 1175 } else if (ref) {
1136 delete_xattr_ref(c, ref); 1176 delete_xattr_ref(c, ref);
@@ -1142,38 +1182,40 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1142} 1182}
1143 1183
1144/* -------- garbage collector functions ------------- 1184/* -------- garbage collector functions -------------
1145 * jffs2_garbage_collect_xattr_datum(c, xd) 1185 * jffs2_garbage_collect_xattr_datum(c, xd, raw)
1146 * is used to move xdatum into new node. 1186 * is used to move xdatum into new node.
1147 * jffs2_garbage_collect_xattr_ref(c, ref) 1187 * jffs2_garbage_collect_xattr_ref(c, ref, raw)
1148 * is used to move xref into new node. 1188 * is used to move xref into new node.
1149 * jffs2_verify_xattr(c) 1189 * jffs2_verify_xattr(c)
1150 * is used to call do_verify_xattr_datum() before garbage collecting. 1190 * is used to call do_verify_xattr_datum() before garbage collecting.
1191 * jffs2_release_xattr_datum(c, xd)
1192 * is used to release an in-memory object of xdatum.
1193 * jffs2_release_xattr_ref(c, ref)
1194 * is used to release an in-memory object of xref.
1151 * -------------------------------------------------- */ 1195 * -------------------------------------------------- */
1152int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 1196int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,
1197 struct jffs2_raw_node_ref *raw)
1153{ 1198{
1154 uint32_t totlen, length, old_ofs; 1199 uint32_t totlen, length, old_ofs;
1155 int rc = -EINVAL; 1200 int rc = 0;
1156 1201
1157 down_write(&c->xattr_sem); 1202 down_write(&c->xattr_sem);
1158 BUG_ON(!xd->node); 1203 if (xd->node != raw)
1159 1204 goto out;
1160 old_ofs = ref_offset(xd->node); 1205 if (xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID))
1161 totlen = ref_totlen(c, c->gcblock, xd->node);
1162 if (totlen < sizeof(struct jffs2_raw_xattr))
1163 goto out; 1206 goto out;
1164 1207
1165 if (!xd->xname) { 1208 rc = load_xattr_datum(c, xd);
1166 rc = load_xattr_datum(c, xd); 1209 if (unlikely(rc)) {
1167 if (unlikely(rc > 0)) { 1210 rc = (rc > 0) ? 0 : rc;
1168 delete_xattr_datum_node(c, xd); 1211 goto out;
1169 rc = 0;
1170 goto out;
1171 } else if (unlikely(rc < 0))
1172 goto out;
1173 } 1212 }
1213 old_ofs = ref_offset(xd->node);
1214 totlen = PAD(sizeof(struct jffs2_raw_xattr)
1215 + xd->name_len + 1 + xd->value_len);
1174 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); 1216 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE);
1175 if (rc || length < totlen) { 1217 if (rc) {
1176 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen); 1218 JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen);
1177 rc = rc ? rc : -EBADFD; 1219 rc = rc ? rc : -EBADFD;
1178 goto out; 1220 goto out;
1179 } 1221 }
@@ -1182,27 +1224,32 @@ int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xatt
1182 dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n", 1224 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)); 1225 xd->xid, xd->version, old_ofs, ref_offset(xd->node));
1184 out: 1226 out:
1227 if (!rc)
1228 jffs2_mark_node_obsolete(c, raw);
1185 up_write(&c->xattr_sem); 1229 up_write(&c->xattr_sem);
1186 return rc; 1230 return rc;
1187} 1231}
1188 1232
1189 1233int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
1190int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) 1234 struct jffs2_raw_node_ref *raw)
1191{ 1235{
1192 uint32_t totlen, length, old_ofs; 1236 uint32_t totlen, length, old_ofs;
1193 int rc = -EINVAL; 1237 int rc = 0;
1194 1238
1195 down_write(&c->xattr_sem); 1239 down_write(&c->xattr_sem);
1196 BUG_ON(!ref->node); 1240 BUG_ON(!ref->node);
1197 1241
1242 if (ref->node != raw)
1243 goto out;
1244 if (is_xattr_ref_dead(ref) && (raw->next_in_ino == (void *)ref))
1245 goto out;
1246
1198 old_ofs = ref_offset(ref->node); 1247 old_ofs = ref_offset(ref->node);
1199 totlen = ref_totlen(c, c->gcblock, ref->node); 1248 totlen = ref_totlen(c, c->gcblock, ref->node);
1200 if (totlen != sizeof(struct jffs2_raw_xref))
1201 goto out;
1202 1249
1203 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE); 1250 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);
1204 if (rc || length < totlen) { 1251 if (rc) {
1205 JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n", 1252 JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n",
1206 __FUNCTION__, rc, totlen); 1253 __FUNCTION__, rc, totlen);
1207 rc = rc ? rc : -EBADFD; 1254 rc = rc ? rc : -EBADFD;
1208 goto out; 1255 goto out;
@@ -1212,6 +1259,8 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_
1212 dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n", 1259 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)); 1260 ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node));
1214 out: 1261 out:
1262 if (!rc)
1263 jffs2_mark_node_obsolete(c, raw);
1215 up_write(&c->xattr_sem); 1264 up_write(&c->xattr_sem);
1216 return rc; 1265 return rc;
1217} 1266}
@@ -1219,20 +1268,59 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_
1219int jffs2_verify_xattr(struct jffs2_sb_info *c) 1268int jffs2_verify_xattr(struct jffs2_sb_info *c)
1220{ 1269{
1221 struct jffs2_xattr_datum *xd, *_xd; 1270 struct jffs2_xattr_datum *xd, *_xd;
1271 struct jffs2_eraseblock *jeb;
1272 struct jffs2_raw_node_ref *raw;
1273 uint32_t totlen;
1222 int rc; 1274 int rc;
1223 1275
1224 down_write(&c->xattr_sem); 1276 down_write(&c->xattr_sem);
1225 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) { 1277 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
1226 rc = do_verify_xattr_datum(c, xd); 1278 rc = do_verify_xattr_datum(c, xd);
1227 if (rc == 0) { 1279 if (rc < 0)
1228 list_del_init(&xd->xindex); 1280 continue;
1229 break; 1281 list_del_init(&xd->xindex);
1230 } else if (rc > 0) { 1282 spin_lock(&c->erase_completion_lock);
1231 list_del_init(&xd->xindex); 1283 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
1232 delete_xattr_datum_node(c, xd); 1284 if (ref_flags(raw) != REF_UNCHECKED)
1285 continue;
1286 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
1287 totlen = PAD(ref_totlen(c, jeb, raw));
1288 c->unchecked_size -= totlen; c->used_size += totlen;
1289 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
1290 raw->flash_offset = ref_offset(raw)
1291 | ((xd->node == (void *)raw) ? REF_PRISTINE : REF_NORMAL);
1233 } 1292 }
1293 if (xd->flags & JFFS2_XFLAGS_DEAD)
1294 list_add(&xd->xindex, &c->xattr_dead_list);
1295 spin_unlock(&c->erase_completion_lock);
1234 } 1296 }
1235 up_write(&c->xattr_sem); 1297 up_write(&c->xattr_sem);
1236
1237 return list_empty(&c->xattr_unchecked) ? 1 : 0; 1298 return list_empty(&c->xattr_unchecked) ? 1 : 0;
1238} 1299}
1300
1301void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
1302{
1303 /* must be called under spin_lock(&c->erase_completion_lock) */
1304 if (atomic_read(&xd->refcnt) || xd->node != (void *)xd)
1305 return;
1306
1307 list_del(&xd->xindex);
1308 jffs2_free_xattr_datum(xd);
1309}
1310
1311void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
1312{
1313 /* must be called under spin_lock(&c->erase_completion_lock) */
1314 struct jffs2_xattr_ref *tmp, **ptmp;
1315
1316 if (ref->node != (void *)ref)
1317 return;
1318
1319 for (tmp=c->xref_dead_list, ptmp=&c->xref_dead_list; tmp; ptmp=&tmp->next, tmp=tmp->next) {
1320 if (ref == tmp) {
1321 *ptmp = tmp->next;
1322 break;
1323 }
1324 }
1325 jffs2_free_xattr_ref(ref);
1326}
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index 2c199856c582..06a5c69dcf8b 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -16,6 +16,8 @@
16 16
17#define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */ 17#define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */
18#define JFFS2_XFLAGS_BIND (0x02) /* This datum is not reclaimed */ 18#define JFFS2_XFLAGS_BIND (0x02) /* This datum is not reclaimed */
19#define JFFS2_XFLAGS_DEAD (0x40) /* This datum is already dead */
20#define JFFS2_XFLAGS_INVALID (0x80) /* This datum contains crc error */
19 21
20struct jffs2_xattr_datum 22struct jffs2_xattr_datum
21{ 23{
@@ -23,10 +25,10 @@ struct jffs2_xattr_datum
23 struct jffs2_raw_node_ref *node; 25 struct jffs2_raw_node_ref *node;
24 uint8_t class; 26 uint8_t class;
25 uint8_t flags; 27 uint8_t flags;
26 uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */ 28 uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */
27 29
28 struct list_head xindex; /* chained from c->xattrindex[n] */ 30 struct list_head xindex; /* chained from c->xattrindex[n] */
29 uint32_t refcnt; /* # of xattr_ref refers this */ 31 atomic_t refcnt; /* # of xattr_ref refers this */
30 uint32_t xid; 32 uint32_t xid;
31 uint32_t version; 33 uint32_t version;
32 34
@@ -47,6 +49,7 @@ struct jffs2_xattr_ref
47 uint8_t flags; /* Currently unused */ 49 uint8_t flags; /* Currently unused */
48 u16 unused; 50 u16 unused;
49 51
52 uint32_t xseqno;
50 union { 53 union {
51 struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */ 54 struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */
52 uint32_t ino; /* only used in scanning/building */ 55 uint32_t ino; /* only used in scanning/building */
@@ -58,6 +61,12 @@ struct jffs2_xattr_ref
58 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */ 61 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */
59}; 62};
60 63
64#define XREF_DELETE_MARKER (0x00000001)
65static inline int is_xattr_ref_dead(struct jffs2_xattr_ref *ref)
66{
67 return ((ref->xseqno & XREF_DELETE_MARKER) != 0);
68}
69
61#ifdef CONFIG_JFFS2_FS_XATTR 70#ifdef CONFIG_JFFS2_FS_XATTR
62 71
63extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c); 72extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c);
@@ -70,9 +79,13 @@ extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c
70extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); 79extern 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); 80extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
72 81
73extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd); 82extern 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); 83 struct jffs2_raw_node_ref *raw);
84extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
85 struct jffs2_raw_node_ref *raw);
75extern int jffs2_verify_xattr(struct jffs2_sb_info *c); 86extern int jffs2_verify_xattr(struct jffs2_sb_info *c);
87extern void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd);
88extern void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref);
76 89
77extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname, 90extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
78 char *buffer, size_t size); 91 char *buffer, size_t size);
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 04eb78f1252e..43e3f566aad6 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -305,7 +305,7 @@ static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb,
305 offset, nr_segs, jfs_get_block, NULL); 305 offset, nr_segs, jfs_get_block, NULL);
306} 306}
307 307
308struct address_space_operations jfs_aops = { 308const struct address_space_operations jfs_aops = {
309 .readpage = jfs_readpage, 309 .readpage = jfs_readpage,
310 .readpages = jfs_readpages, 310 .readpages = jfs_readpages,
311 .writepage = jfs_writepage, 311 .writepage = jfs_writepage,
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index c30072674464..b5c7da6190dc 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -33,7 +33,7 @@ extern void jfs_free_zero_link(struct inode *);
33extern struct dentry *jfs_get_parent(struct dentry *dentry); 33extern struct dentry *jfs_get_parent(struct dentry *dentry);
34extern void jfs_set_inode_flags(struct inode *); 34extern void jfs_set_inode_flags(struct inode *);
35 35
36extern struct address_space_operations jfs_aops; 36extern const struct address_space_operations jfs_aops;
37extern struct inode_operations jfs_dir_inode_operations; 37extern struct inode_operations jfs_dir_inode_operations;
38extern const struct file_operations jfs_dir_operations; 38extern const struct file_operations jfs_dir_operations;
39extern struct inode_operations jfs_file_inode_operations; 39extern struct inode_operations jfs_file_inode_operations;
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 7f6e88039700..e1e0a6e6ebdf 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -577,7 +577,7 @@ static void metapage_invalidatepage(struct page *page, unsigned long offset)
577 metapage_releasepage(page, 0); 577 metapage_releasepage(page, 0);
578} 578}
579 579
580struct address_space_operations jfs_metapage_aops = { 580const struct address_space_operations jfs_metapage_aops = {
581 .readpage = metapage_readpage, 581 .readpage = metapage_readpage,
582 .writepage = metapage_writepage, 582 .writepage = metapage_writepage,
583 .sync_page = block_sync_page, 583 .sync_page = block_sync_page,
diff --git a/fs/jfs/jfs_metapage.h b/fs/jfs/jfs_metapage.h
index f0b7d3282b07..d17a3290f5aa 100644
--- a/fs/jfs/jfs_metapage.h
+++ b/fs/jfs/jfs_metapage.h
@@ -139,7 +139,7 @@ static inline void metapage_homeok(struct metapage *mp)
139 put_metapage(mp); 139 put_metapage(mp);
140} 140}
141 141
142extern struct address_space_operations jfs_metapage_aops; 142extern const struct address_space_operations jfs_metapage_aops;
143 143
144/* 144/*
145 * This routines invalidate all pages for an extent. 145 * This routines invalidate all pages for an extent.
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index a6fb509b7341..9ea91c5eeb7b 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -335,7 +335,7 @@ static sector_t minix_bmap(struct address_space *mapping, sector_t block)
335{ 335{
336 return generic_block_bmap(mapping,block,minix_get_block); 336 return generic_block_bmap(mapping,block,minix_get_block);
337} 337}
338static struct address_space_operations minix_aops = { 338static const struct address_space_operations minix_aops = {
339 .readpage = minix_readpage, 339 .readpage = minix_readpage,
340 .writepage = minix_writepage, 340 .writepage = minix_writepage,
341 .sync_page = block_sync_page, 341 .sync_page = block_sync_page,
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 90d2ea28f333..6c51c1198464 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -105,7 +105,7 @@ static struct super_operations ncp_sops =
105 105
106extern struct dentry_operations ncp_root_dentry_operations; 106extern struct dentry_operations ncp_root_dentry_operations;
107#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) 107#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
108extern struct address_space_operations ncp_symlink_aops; 108extern const struct address_space_operations ncp_symlink_aops;
109extern int ncp_symlink(struct inode*, struct dentry*, const char*); 109extern int ncp_symlink(struct inode*, struct dentry*, const char*);
110#endif 110#endif
111 111
diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c
index e935f1b34bc2..f76b1392a012 100644
--- a/fs/ncpfs/symlink.c
+++ b/fs/ncpfs/symlink.c
@@ -99,7 +99,7 @@ fail:
99/* 99/*
100 * symlinks can't do much... 100 * symlinks can't do much...
101 */ 101 */
102struct address_space_operations ncp_symlink_aops = { 102const struct address_space_operations ncp_symlink_aops = {
103 .readpage = ncp_symlink_readpage, 103 .readpage = ncp_symlink_readpage,
104}; 104};
105 105
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 402005c35ab3..8ca9707be6c9 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -909,7 +909,7 @@ int __init nfs_init_directcache(void)
909 * nfs_destroy_directcache - destroy the slab cache for nfs_direct_req structures 909 * nfs_destroy_directcache - destroy the slab cache for nfs_direct_req structures
910 * 910 *
911 */ 911 */
912void __exit nfs_destroy_directcache(void) 912void nfs_destroy_directcache(void)
913{ 913{
914 if (kmem_cache_destroy(nfs_direct_cachep)) 914 if (kmem_cache_destroy(nfs_direct_cachep))
915 printk(KERN_INFO "nfs_direct_cache: not all structures were freed\n"); 915 printk(KERN_INFO "nfs_direct_cache: not all structures were freed\n");
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index add289138836..cc2b874ad5a4 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -315,7 +315,7 @@ static int nfs_release_page(struct page *page, gfp_t gfp)
315 return !nfs_wb_page(page->mapping->host, page); 315 return !nfs_wb_page(page->mapping->host, page);
316} 316}
317 317
318struct address_space_operations nfs_file_aops = { 318const struct address_space_operations nfs_file_aops = {
319 .readpage = nfs_readpage, 319 .readpage = nfs_readpage,
320 .readpages = nfs_readpages, 320 .readpages = nfs_readpages,
321 .set_page_dirty = __set_page_dirty_nobuffers, 321 .set_page_dirty = __set_page_dirty_nobuffers,
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 51bc88b662fe..c5b916605fb0 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1132,7 +1132,7 @@ static int __init nfs_init_inodecache(void)
1132 return 0; 1132 return 0;
1133} 1133}
1134 1134
1135static void __exit nfs_destroy_inodecache(void) 1135static void nfs_destroy_inodecache(void)
1136{ 1136{
1137 if (kmem_cache_destroy(nfs_inode_cachep)) 1137 if (kmem_cache_destroy(nfs_inode_cachep))
1138 printk(KERN_INFO "nfs_inode_cache: not all structures were freed\n"); 1138 printk(KERN_INFO "nfs_inode_cache: not all structures were freed\n");
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index bd2815e2dec1..4fe51c1292bb 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -31,15 +31,15 @@ extern struct svc_version nfs4_callback_version1;
31 31
32/* pagelist.c */ 32/* pagelist.c */
33extern int __init nfs_init_nfspagecache(void); 33extern int __init nfs_init_nfspagecache(void);
34extern void __exit nfs_destroy_nfspagecache(void); 34extern void nfs_destroy_nfspagecache(void);
35extern int __init nfs_init_readpagecache(void); 35extern int __init nfs_init_readpagecache(void);
36extern void __exit nfs_destroy_readpagecache(void); 36extern void nfs_destroy_readpagecache(void);
37extern int __init nfs_init_writepagecache(void); 37extern int __init nfs_init_writepagecache(void);
38extern void __exit nfs_destroy_writepagecache(void); 38extern void nfs_destroy_writepagecache(void);
39 39
40#ifdef CONFIG_NFS_DIRECTIO 40#ifdef CONFIG_NFS_DIRECTIO
41extern int __init nfs_init_directcache(void); 41extern int __init nfs_init_directcache(void);
42extern void __exit nfs_destroy_directcache(void); 42extern void nfs_destroy_directcache(void);
43#else 43#else
44#define nfs_init_directcache() (0) 44#define nfs_init_directcache() (0)
45#define nfs_destroy_directcache() do {} while(0) 45#define nfs_destroy_directcache() do {} while(0)
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index ef9429643ebc..d89f6fb3b3a3 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -390,7 +390,7 @@ int __init nfs_init_nfspagecache(void)
390 return 0; 390 return 0;
391} 391}
392 392
393void __exit nfs_destroy_nfspagecache(void) 393void nfs_destroy_nfspagecache(void)
394{ 394{
395 if (kmem_cache_destroy(nfs_page_cachep)) 395 if (kmem_cache_destroy(nfs_page_cachep))
396 printk(KERN_INFO "nfs_page: not all structures were freed\n"); 396 printk(KERN_INFO "nfs_page: not all structures were freed\n");
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 41c2ffee24f5..32cf3773af0c 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -711,7 +711,7 @@ int __init nfs_init_readpagecache(void)
711 return 0; 711 return 0;
712} 712}
713 713
714void __exit nfs_destroy_readpagecache(void) 714void nfs_destroy_readpagecache(void)
715{ 715{
716 mempool_destroy(nfs_rdata_mempool); 716 mempool_destroy(nfs_rdata_mempool);
717 if (kmem_cache_destroy(nfs_rdata_cachep)) 717 if (kmem_cache_destroy(nfs_rdata_cachep))
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index b383fdd3a15c..8fccb9cb173b 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1551,7 +1551,7 @@ int __init nfs_init_writepagecache(void)
1551 return 0; 1551 return 0;
1552} 1552}
1553 1553
1554void __exit nfs_destroy_writepagecache(void) 1554void nfs_destroy_writepagecache(void)
1555{ 1555{
1556 mempool_destroy(nfs_commit_mempool); 1556 mempool_destroy(nfs_commit_mempool);
1557 mempool_destroy(nfs_wdata_mempool); 1557 mempool_destroy(nfs_wdata_mempool);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 1630b5670dc2..7c7d01672d35 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -123,7 +123,7 @@ static void release_stateid(struct nfs4_stateid *stp, int flags);
123 */ 123 */
124 124
125/* recall_lock protects the del_recall_lru */ 125/* recall_lock protects the del_recall_lru */
126static spinlock_t recall_lock = SPIN_LOCK_UNLOCKED; 126static DEFINE_SPINLOCK(recall_lock);
127static struct list_head del_recall_lru; 127static struct list_head del_recall_lru;
128 128
129static void 129static void
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index 580412d330cb..bc579bfdfbd8 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -1544,7 +1544,7 @@ err_out:
1544/** 1544/**
1545 * ntfs_aops - general address space operations for inodes and attributes 1545 * ntfs_aops - general address space operations for inodes and attributes
1546 */ 1546 */
1547struct address_space_operations ntfs_aops = { 1547const struct address_space_operations ntfs_aops = {
1548 .readpage = ntfs_readpage, /* Fill page with data. */ 1548 .readpage = ntfs_readpage, /* Fill page with data. */
1549 .sync_page = block_sync_page, /* Currently, just unplugs the 1549 .sync_page = block_sync_page, /* Currently, just unplugs the
1550 disk request queue. */ 1550 disk request queue. */
@@ -1560,7 +1560,7 @@ struct address_space_operations ntfs_aops = {
1560 * ntfs_mst_aops - general address space operations for mst protecteed inodes 1560 * ntfs_mst_aops - general address space operations for mst protecteed inodes
1561 * and attributes 1561 * and attributes
1562 */ 1562 */
1563struct address_space_operations ntfs_mst_aops = { 1563const struct address_space_operations ntfs_mst_aops = {
1564 .readpage = ntfs_readpage, /* Fill page with data. */ 1564 .readpage = ntfs_readpage, /* Fill page with data. */
1565 .sync_page = block_sync_page, /* Currently, just unplugs the 1565 .sync_page = block_sync_page, /* Currently, just unplugs the
1566 disk request queue. */ 1566 disk request queue. */
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h
index bf7b3d7c0930..ddd3d503097c 100644
--- a/fs/ntfs/ntfs.h
+++ b/fs/ntfs/ntfs.h
@@ -57,8 +57,8 @@ extern struct kmem_cache *ntfs_attr_ctx_cache;
57extern struct kmem_cache *ntfs_index_ctx_cache; 57extern struct kmem_cache *ntfs_index_ctx_cache;
58 58
59/* The various operations structs defined throughout the driver files. */ 59/* The various operations structs defined throughout the driver files. */
60extern struct address_space_operations ntfs_aops; 60extern const struct address_space_operations ntfs_aops;
61extern struct address_space_operations ntfs_mst_aops; 61extern const struct address_space_operations ntfs_mst_aops;
62 62
63extern const struct file_operations ntfs_file_ops; 63extern const struct file_operations ntfs_file_ops;
64extern struct inode_operations ntfs_file_inode_ops; 64extern struct inode_operations ntfs_file_inode_ops;
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 47152bf9a7f2..cca71317b6d6 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -666,7 +666,7 @@ out:
666 return ret; 666 return ret;
667} 667}
668 668
669struct address_space_operations ocfs2_aops = { 669const struct address_space_operations ocfs2_aops = {
670 .readpage = ocfs2_readpage, 670 .readpage = ocfs2_readpage,
671 .writepage = ocfs2_writepage, 671 .writepage = ocfs2_writepage,
672 .prepare_write = ocfs2_prepare_write, 672 .prepare_write = ocfs2_prepare_write,
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 21f38accd039..1d26cfcd9f84 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -54,7 +54,7 @@ static DECLARE_RWSEM(o2hb_callback_sem);
54 * multiple hb threads are watching multiple regions. A node is live 54 * multiple hb threads are watching multiple regions. A node is live
55 * whenever any of the threads sees activity from the node in its region. 55 * whenever any of the threads sees activity from the node in its region.
56 */ 56 */
57static spinlock_t o2hb_live_lock = SPIN_LOCK_UNLOCKED; 57static DEFINE_SPINLOCK(o2hb_live_lock);
58static struct list_head o2hb_live_slots[O2NM_MAX_NODES]; 58static struct list_head o2hb_live_slots[O2NM_MAX_NODES];
59static unsigned long o2hb_live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; 59static unsigned long o2hb_live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
60static LIST_HEAD(o2hb_node_events); 60static LIST_HEAD(o2hb_node_events);
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 0f60cc0d3985..1591eb37a723 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -108,7 +108,7 @@
108 ##args); \ 108 ##args); \
109} while (0) 109} while (0)
110 110
111static rwlock_t o2net_handler_lock = RW_LOCK_UNLOCKED; 111static DEFINE_RWLOCK(o2net_handler_lock);
112static struct rb_root o2net_handler_tree = RB_ROOT; 112static struct rb_root o2net_handler_tree = RB_ROOT;
113 113
114static struct o2net_node o2net_nodes[O2NM_MAX_NODES]; 114static struct o2net_node o2net_nodes[O2NM_MAX_NODES];
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index ba27c5c5e959..b8c23f7ba67e 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -88,7 +88,7 @@ out_free:
88 * 88 *
89 */ 89 */
90 90
91spinlock_t dlm_domain_lock = SPIN_LOCK_UNLOCKED; 91DEFINE_SPINLOCK(dlm_domain_lock);
92LIST_HEAD(dlm_domains); 92LIST_HEAD(dlm_domains);
93static DECLARE_WAIT_QUEUE_HEAD(dlm_domain_events); 93static DECLARE_WAIT_QUEUE_HEAD(dlm_domain_events);
94 94
diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
index d6f89577e25f..5ca57ec650c7 100644
--- a/fs/ocfs2/dlm/dlmlock.c
+++ b/fs/ocfs2/dlm/dlmlock.c
@@ -53,7 +53,7 @@
53#define MLOG_MASK_PREFIX ML_DLM 53#define MLOG_MASK_PREFIX ML_DLM
54#include "cluster/masklog.h" 54#include "cluster/masklog.h"
55 55
56static spinlock_t dlm_cookie_lock = SPIN_LOCK_UNLOCKED; 56static DEFINE_SPINLOCK(dlm_cookie_lock);
57static u64 dlm_next_cookie = 1; 57static u64 dlm_next_cookie = 1;
58 58
59static enum dlm_status dlm_send_remote_lock_request(struct dlm_ctxt *dlm, 59static enum dlm_status dlm_send_remote_lock_request(struct dlm_ctxt *dlm,
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index da399013516f..29b2845f370d 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -98,8 +98,8 @@ static void dlm_mig_lockres_worker(struct dlm_work_item *item, void *data);
98 98
99static u64 dlm_get_next_mig_cookie(void); 99static u64 dlm_get_next_mig_cookie(void);
100 100
101static spinlock_t dlm_reco_state_lock = SPIN_LOCK_UNLOCKED; 101static DEFINE_SPINLOCK(dlm_reco_state_lock);
102static spinlock_t dlm_mig_cookie_lock = SPIN_LOCK_UNLOCKED; 102static DEFINE_SPINLOCK(dlm_mig_cookie_lock);
103static u64 dlm_mig_cookie = 1; 103static u64 dlm_mig_cookie = 1;
104 104
105static u64 dlm_get_next_mig_cookie(void) 105static u64 dlm_get_next_mig_cookie(void)
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 64cd52860c87..4acd37286bdd 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -242,7 +242,7 @@ static void ocfs2_build_lock_name(enum ocfs2_lock_type type,
242 mlog_exit_void(); 242 mlog_exit_void();
243} 243}
244 244
245static spinlock_t ocfs2_dlm_tracking_lock = SPIN_LOCK_UNLOCKED; 245static DEFINE_SPINLOCK(ocfs2_dlm_tracking_lock);
246 246
247static void ocfs2_add_lockres_tracking(struct ocfs2_lock_res *res, 247static void ocfs2_add_lockres_tracking(struct ocfs2_lock_res *res,
248 struct ocfs2_dlm_debug *dlm_debug) 248 struct ocfs2_dlm_debug *dlm_debug)
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
index 84c507961287..35140f6cf840 100644
--- a/fs/ocfs2/inode.h
+++ b/fs/ocfs2/inode.h
@@ -114,7 +114,7 @@ static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode)
114 114
115extern kmem_cache_t *ocfs2_inode_cache; 115extern kmem_cache_t *ocfs2_inode_cache;
116 116
117extern struct address_space_operations ocfs2_aops; 117extern const struct address_space_operations ocfs2_aops;
118 118
119struct buffer_head *ocfs2_bread(struct inode *inode, int block, 119struct buffer_head *ocfs2_bread(struct inode *inode, int block,
120 int *err, int reada); 120 int *err, int reada);
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 3fe8781c22cb..910a601b2e98 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -49,7 +49,7 @@
49 49
50#include "buffer_head_io.h" 50#include "buffer_head_io.h"
51 51
52spinlock_t trans_inc_lock = SPIN_LOCK_UNLOCKED; 52DEFINE_SPINLOCK(trans_inc_lock);
53 53
54static int ocfs2_force_read_journal(struct inode *inode); 54static int ocfs2_force_read_journal(struct inode *inode);
55static int ocfs2_recover_node(struct ocfs2_super *osb, 55static int ocfs2_recover_node(struct ocfs2_super *osb,
diff --git a/fs/ocfs2/vote.c b/fs/ocfs2/vote.c
index ee42765a8553..cf70fe2075b8 100644
--- a/fs/ocfs2/vote.c
+++ b/fs/ocfs2/vote.c
@@ -988,9 +988,7 @@ int ocfs2_request_mount_vote(struct ocfs2_super *osb)
988 } 988 }
989 989
990bail: 990bail:
991 if (request) 991 kfree(request);
992 kfree(request);
993
994 return status; 992 return status;
995} 993}
996 994
@@ -1021,9 +1019,7 @@ int ocfs2_request_umount_vote(struct ocfs2_super *osb)
1021 } 1019 }
1022 1020
1023bail: 1021bail:
1024 if (request) 1022 kfree(request);
1025 kfree(request);
1026
1027 return status; 1023 return status;
1028} 1024}
1029 1025
diff --git a/fs/partitions/Makefile b/fs/partitions/Makefile
index 42c7d3878ed0..d713ce6b3e12 100644
--- a/fs/partitions/Makefile
+++ b/fs/partitions/Makefile
@@ -4,7 +4,6 @@
4 4
5obj-y := check.o 5obj-y := check.o
6 6
7obj-$(CONFIG_DEVFS_FS) += devfs.o
8obj-$(CONFIG_ACORN_PARTITION) += acorn.o 7obj-$(CONFIG_ACORN_PARTITION) += acorn.o
9obj-$(CONFIG_AMIGA_PARTITION) += amiga.o 8obj-$(CONFIG_AMIGA_PARTITION) += amiga.o
10obj-$(CONFIG_ATARI_PARTITION) += atari.o 9obj-$(CONFIG_ATARI_PARTITION) += atari.o
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 2ef313a96b66..839634026eb5 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -18,10 +18,8 @@
18#include <linux/fs.h> 18#include <linux/fs.h>
19#include <linux/kmod.h> 19#include <linux/kmod.h>
20#include <linux/ctype.h> 20#include <linux/ctype.h>
21#include <linux/devfs_fs_kernel.h>
22 21
23#include "check.h" 22#include "check.h"
24#include "devfs.h"
25 23
26#include "acorn.h" 24#include "acorn.h"
27#include "amiga.h" 25#include "amiga.h"
@@ -161,18 +159,11 @@ check_partition(struct gendisk *hd, struct block_device *bdev)
161 if (!state) 159 if (!state)
162 return NULL; 160 return NULL;
163 161
164#ifdef CONFIG_DEVFS_FS 162 disk_name(hd, 0, state->name);
165 if (hd->devfs_name[0] != '\0') { 163 printk(KERN_INFO " %s:", state->name);
166 printk(KERN_INFO " /dev/%s:", hd->devfs_name); 164 if (isdigit(state->name[strlen(state->name)-1]))
167 sprintf(state->name, "p"); 165 sprintf(state->name, "p");
168 } 166
169#endif
170 else {
171 disk_name(hd, 0, state->name);
172 printk(KERN_INFO " %s:", state->name);
173 if (isdigit(state->name[strlen(state->name)-1]))
174 sprintf(state->name, "p");
175 }
176 state->limit = hd->minors; 167 state->limit = hd->minors;
177 i = res = 0; 168 i = res = 0;
178 while (!res && check_part[i]) { 169 while (!res && check_part[i]) {
@@ -328,7 +319,6 @@ void delete_partition(struct gendisk *disk, int part)
328 p->nr_sects = 0; 319 p->nr_sects = 0;
329 p->ios[0] = p->ios[1] = 0; 320 p->ios[0] = p->ios[1] = 0;
330 p->sectors[0] = p->sectors[1] = 0; 321 p->sectors[0] = p->sectors[1] = 0;
331 devfs_remove("%s/part%d", disk->devfs_name, part);
332 sysfs_remove_link(&p->kobj, "subsystem"); 322 sysfs_remove_link(&p->kobj, "subsystem");
333 if (p->holder_dir) 323 if (p->holder_dir)
334 kobject_unregister(p->holder_dir); 324 kobject_unregister(p->holder_dir);
@@ -350,10 +340,6 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
350 p->nr_sects = len; 340 p->nr_sects = len;
351 p->partno = part; 341 p->partno = part;
352 342
353 devfs_mk_bdev(MKDEV(disk->major, disk->first_minor + part),
354 S_IFBLK|S_IRUSR|S_IWUSR,
355 "%s/part%d", disk->devfs_name, part);
356
357 if (isdigit(disk->kobj.name[strlen(disk->kobj.name)-1])) 343 if (isdigit(disk->kobj.name[strlen(disk->kobj.name)-1]))
358 snprintf(p->kobj.name,KOBJ_NAME_LEN,"%sp%d",disk->kobj.name,part); 344 snprintf(p->kobj.name,KOBJ_NAME_LEN,"%sp%d",disk->kobj.name,part);
359 else 345 else
@@ -423,14 +409,8 @@ void register_disk(struct gendisk *disk)
423 disk_sysfs_add_subdirs(disk); 409 disk_sysfs_add_subdirs(disk);
424 410
425 /* No minors to use for partitions */ 411 /* No minors to use for partitions */
426 if (disk->minors == 1) { 412 if (disk->minors == 1)
427 if (disk->devfs_name[0] != '\0')
428 devfs_add_disk(disk);
429 goto exit; 413 goto exit;
430 }
431
432 /* always add handle for the whole disk */
433 devfs_add_partitioned(disk);
434 414
435 /* No such device (e.g., media were just removed) */ 415 /* No such device (e.g., media were just removed) */
436 if (!get_capacity(disk)) 416 if (!get_capacity(disk))
@@ -538,8 +518,6 @@ void del_gendisk(struct gendisk *disk)
538 disk_stat_set_all(disk, 0); 518 disk_stat_set_all(disk, 0);
539 disk->stamp = 0; 519 disk->stamp = 0;
540 520
541 devfs_remove_disk(disk);
542
543 kobject_uevent(&disk->kobj, KOBJ_REMOVE); 521 kobject_uevent(&disk->kobj, KOBJ_REMOVE);
544 if (disk->holder_dir) 522 if (disk->holder_dir)
545 kobject_unregister(disk->holder_dir); 523 kobject_unregister(disk->holder_dir);
diff --git a/fs/partitions/devfs.c b/fs/partitions/devfs.c
deleted file mode 100644
index 3f0a780c9cec..000000000000
--- a/fs/partitions/devfs.c
+++ /dev/null
@@ -1,130 +0,0 @@
1/*
2 * This tries to keep block devices away from devfs as much as possible.
3 */
4#include <linux/fs.h>
5#include <linux/devfs_fs_kernel.h>
6#include <linux/vmalloc.h>
7#include <linux/genhd.h>
8#include <linux/bitops.h>
9#include <linux/mutex.h>
10
11
12struct unique_numspace {
13 u32 num_free; /* Num free in bits */
14 u32 length; /* Array length in bytes */
15 unsigned long *bits;
16 struct semaphore mutex;
17};
18
19static DEFINE_MUTEX(numspace_mutex);
20
21static int expand_numspace(struct unique_numspace *s)
22{
23 u32 length;
24 void *bits;
25
26 if (s->length < 16)
27 length = 16;
28 else
29 length = s->length << 1;
30
31 bits = vmalloc(length);
32 if (!bits)
33 return -ENOMEM;
34 if (s->bits) {
35 memcpy(bits, s->bits, s->length);
36 vfree(s->bits);
37 }
38
39 s->num_free = (length - s->length) << 3;
40 s->bits = bits;
41 memset(bits + s->length, 0, length - s->length);
42 s->length = length;
43
44 return 0;
45}
46
47static int alloc_unique_number(struct unique_numspace *s)
48{
49 int rval = 0;
50
51 mutex_lock(&numspace_mutex);
52 if (s->num_free < 1)
53 rval = expand_numspace(s);
54 if (!rval) {
55 rval = find_first_zero_bit(s->bits, s->length << 3);
56 --s->num_free;
57 __set_bit(rval, s->bits);
58 }
59 mutex_unlock(&numspace_mutex);
60
61 return rval;
62}
63
64static void dealloc_unique_number(struct unique_numspace *s, int number)
65{
66 int old_val;
67
68 if (number >= 0) {
69 mutex_lock(&numspace_mutex);
70 old_val = __test_and_clear_bit(number, s->bits);
71 if (old_val)
72 ++s->num_free;
73 mutex_unlock(&numspace_mutex);
74 }
75}
76
77static struct unique_numspace disc_numspace;
78static struct unique_numspace cdrom_numspace;
79
80void devfs_add_partitioned(struct gendisk *disk)
81{
82 char dirname[64], symlink[16];
83
84 devfs_mk_dir(disk->devfs_name);
85 devfs_mk_bdev(MKDEV(disk->major, disk->first_minor),
86 S_IFBLK|S_IRUSR|S_IWUSR,
87 "%s/disc", disk->devfs_name);
88
89 disk->number = alloc_unique_number(&disc_numspace);
90
91 sprintf(symlink, "discs/disc%d", disk->number);
92 sprintf(dirname, "../%s", disk->devfs_name);
93 devfs_mk_symlink(symlink, dirname);
94
95}
96
97void devfs_add_disk(struct gendisk *disk)
98{
99 devfs_mk_bdev(MKDEV(disk->major, disk->first_minor),
100 (disk->flags & GENHD_FL_CD) ?
101 S_IFBLK|S_IRUGO|S_IWUGO :
102 S_IFBLK|S_IRUSR|S_IWUSR,
103 "%s", disk->devfs_name);
104
105 if (disk->flags & GENHD_FL_CD) {
106 char dirname[64], symlink[16];
107
108 disk->number = alloc_unique_number(&cdrom_numspace);
109
110 sprintf(symlink, "cdroms/cdrom%d", disk->number);
111 sprintf(dirname, "../%s", disk->devfs_name);
112 devfs_mk_symlink(symlink, dirname);
113 }
114}
115
116void devfs_remove_disk(struct gendisk *disk)
117{
118 if (disk->minors != 1) {
119 devfs_remove("discs/disc%d", disk->number);
120 dealloc_unique_number(&disc_numspace, disk->number);
121 devfs_remove("%s/disc", disk->devfs_name);
122 }
123 if (disk->flags & GENHD_FL_CD) {
124 devfs_remove("cdroms/cdrom%d", disk->number);
125 dealloc_unique_number(&cdrom_numspace, disk->number);
126 }
127 devfs_remove(disk->devfs_name);
128}
129
130
diff --git a/fs/partitions/devfs.h b/fs/partitions/devfs.h
deleted file mode 100644
index 176118b4e492..000000000000
--- a/fs/partitions/devfs.h
+++ /dev/null
@@ -1,10 +0,0 @@
1
2#ifdef CONFIG_DEVFS_FS
3void devfs_add_disk(struct gendisk *dev);
4void devfs_add_partitioned(struct gendisk *dev);
5void devfs_remove_disk(struct gendisk *dev);
6#else
7# define devfs_add_disk(disk) do { } while (0)
8# define devfs_add_partitioned(disk) do { } while (0)
9# define devfs_remove_disk(disk) do { } while (0)
10#endif
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 0137ec4c1368..0a163a4f7764 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -122,6 +122,11 @@ struct mem_size_stats
122 unsigned long private_dirty; 122 unsigned long private_dirty;
123}; 123};
124 124
125__attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma)
126{
127 return NULL;
128}
129
125static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss) 130static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
126{ 131{
127 struct proc_maps_private *priv = m->private; 132 struct proc_maps_private *priv = m->private;
@@ -158,22 +163,23 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
158 pad_len_spaces(m, len); 163 pad_len_spaces(m, len);
159 seq_path(m, file->f_vfsmnt, file->f_dentry, "\n"); 164 seq_path(m, file->f_vfsmnt, file->f_dentry, "\n");
160 } else { 165 } else {
161 if (mm) { 166 const char *name = arch_vma_name(vma);
162 if (vma->vm_start <= mm->start_brk && 167 if (!name) {
168 if (mm) {
169 if (vma->vm_start <= mm->start_brk &&
163 vma->vm_end >= mm->brk) { 170 vma->vm_end >= mm->brk) {
164 pad_len_spaces(m, len); 171 name = "[heap]";
165 seq_puts(m, "[heap]"); 172 } else if (vma->vm_start <= mm->start_stack &&
166 } else { 173 vma->vm_end >= mm->start_stack) {
167 if (vma->vm_start <= mm->start_stack && 174 name = "[stack]";
168 vma->vm_end >= mm->start_stack) {
169
170 pad_len_spaces(m, len);
171 seq_puts(m, "[stack]");
172 } 175 }
176 } else {
177 name = "[vdso]";
173 } 178 }
174 } else { 179 }
180 if (name) {
175 pad_len_spaces(m, len); 181 pad_len_spaces(m, len);
176 seq_puts(m, "[vdso]"); 182 seq_puts(m, name);
177 } 183 }
178 } 184 }
179 seq_putc(m, '\n'); 185 seq_putc(m, '\n');
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 2f24c46f72a1..8bc182a88748 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -450,7 +450,7 @@ static sector_t qnx4_bmap(struct address_space *mapping, sector_t block)
450{ 450{
451 return generic_block_bmap(mapping,block,qnx4_get_block); 451 return generic_block_bmap(mapping,block,qnx4_get_block);
452} 452}
453static struct address_space_operations qnx4_aops = { 453static const struct address_space_operations qnx4_aops = {
454 .readpage = qnx4_readpage, 454 .readpage = qnx4_readpage,
455 .writepage = qnx4_writepage, 455 .writepage = qnx4_writepage,
456 .sync_page = block_sync_page, 456 .sync_page = block_sync_page,
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index 00a933eb820c..86f14cacf641 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -26,7 +26,7 @@
26 26
27#include <linux/fs.h> 27#include <linux/fs.h>
28 28
29struct address_space_operations ramfs_aops = { 29const struct address_space_operations ramfs_aops = {
30 .readpage = simple_readpage, 30 .readpage = simple_readpage,
31 .prepare_write = simple_prepare_write, 31 .prepare_write = simple_prepare_write,
32 .commit_write = simple_commit_write 32 .commit_write = simple_commit_write
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index f443a84b98a5..99fffc9e1bfd 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -27,7 +27,7 @@
27 27
28static int ramfs_nommu_setattr(struct dentry *, struct iattr *); 28static int ramfs_nommu_setattr(struct dentry *, struct iattr *);
29 29
30struct address_space_operations ramfs_aops = { 30const struct address_space_operations ramfs_aops = {
31 .readpage = simple_readpage, 31 .readpage = simple_readpage,
32 .prepare_write = simple_prepare_write, 32 .prepare_write = simple_prepare_write,
33 .commit_write = simple_commit_write 33 .commit_write = simple_commit_write
diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h
index 313237631b49..c2bb58e74653 100644
--- a/fs/ramfs/internal.h
+++ b/fs/ramfs/internal.h
@@ -10,6 +10,6 @@
10 */ 10 */
11 11
12 12
13extern struct address_space_operations ramfs_aops; 13extern const struct address_space_operations ramfs_aops;
14extern const struct file_operations ramfs_file_operations; 14extern const struct file_operations ramfs_file_operations;
15extern struct inode_operations ramfs_file_inode_operations; 15extern struct inode_operations ramfs_file_inode_operations;
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 9857e50f85e7..a24858a632fa 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2996,7 +2996,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
2996 return error; 2996 return error;
2997} 2997}
2998 2998
2999struct address_space_operations reiserfs_address_space_operations = { 2999const struct address_space_operations reiserfs_address_space_operations = {
3000 .writepage = reiserfs_writepage, 3000 .writepage = reiserfs_writepage,
3001 .readpage = reiserfs_readpage, 3001 .readpage = reiserfs_readpage,
3002 .readpages = reiserfs_readpages, 3002 .readpages = reiserfs_readpages,
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index 283fbc6b8eea..22eed61ebf69 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -459,7 +459,7 @@ err_out:
459 459
460/* Mapping from our types to the kernel */ 460/* Mapping from our types to the kernel */
461 461
462static struct address_space_operations romfs_aops = { 462static const struct address_space_operations romfs_aops = {
463 .readpage = romfs_readpage 463 .readpage = romfs_readpage
464}; 464};
465 465
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index ed9a24d19d7d..dae67048baba 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -306,7 +306,7 @@ static int smb_commit_write(struct file *file, struct page *page,
306 return status; 306 return status;
307} 307}
308 308
309struct address_space_operations smb_file_aops = { 309const struct address_space_operations smb_file_aops = {
310 .readpage = smb_readpage, 310 .readpage = smb_readpage,
311 .writepage = smb_writepage, 311 .writepage = smb_writepage,
312 .prepare_write = smb_prepare_write, 312 .prepare_write = smb_prepare_write,
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h
index 972ed7dad388..34fb462b2379 100644
--- a/fs/smbfs/proto.h
+++ b/fs/smbfs/proto.h
@@ -63,7 +63,7 @@ extern int smb_revalidate_inode(struct dentry *dentry);
63extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); 63extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
64extern int smb_notify_change(struct dentry *dentry, struct iattr *attr); 64extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
65/* file.c */ 65/* file.c */
66extern struct address_space_operations smb_file_aops; 66extern const struct address_space_operations smb_file_aops;
67extern const struct file_operations smb_file_operations; 67extern const struct file_operations smb_file_operations;
68extern struct inode_operations smb_file_inode_operations; 68extern struct inode_operations smb_file_inode_operations;
69/* ioctl.c */ 69/* ioctl.c */
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index f0b347bd12ca..5e0e31cc46f5 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -16,7 +16,7 @@
16 16
17extern struct super_block * sysfs_sb; 17extern struct super_block * sysfs_sb;
18 18
19static struct address_space_operations sysfs_aops = { 19static const struct address_space_operations sysfs_aops = {
20 .readpage = simple_readpage, 20 .readpage = simple_readpage,
21 .prepare_write = simple_prepare_write, 21 .prepare_write = simple_prepare_write,
22 .commit_write = simple_commit_write 22 .commit_write = simple_commit_write
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index 86f5f8d43d0f..f2bcccd1d6fc 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -465,7 +465,7 @@ static sector_t sysv_bmap(struct address_space *mapping, sector_t block)
465{ 465{
466 return generic_block_bmap(mapping,block,get_block); 466 return generic_block_bmap(mapping,block,get_block);
467} 467}
468struct address_space_operations sysv_aops = { 468const struct address_space_operations sysv_aops = {
469 .readpage = sysv_readpage, 469 .readpage = sysv_readpage,
470 .writepage = sysv_writepage, 470 .writepage = sysv_writepage,
471 .sync_page = block_sync_page, 471 .sync_page = block_sync_page,
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index 393a480e4deb..9dcc82120935 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -161,7 +161,7 @@ extern struct inode_operations sysv_dir_inode_operations;
161extern struct inode_operations sysv_fast_symlink_inode_operations; 161extern struct inode_operations sysv_fast_symlink_inode_operations;
162extern const struct file_operations sysv_file_operations; 162extern const struct file_operations sysv_file_operations;
163extern const struct file_operations sysv_dir_operations; 163extern const struct file_operations sysv_dir_operations;
164extern struct address_space_operations sysv_aops; 164extern const struct address_space_operations sysv_aops;
165extern struct super_operations sysv_sops; 165extern struct super_operations sysv_sops;
166extern struct dentry_operations sysv_dentry_operations; 166extern struct dentry_operations sysv_dentry_operations;
167 167
diff --git a/fs/udf/file.c b/fs/udf/file.c
index e34b00e303f1..a59e5f33daf6 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -95,7 +95,7 @@ static int udf_adinicb_commit_write(struct file *file, struct page *page, unsign
95 return 0; 95 return 0;
96} 96}
97 97
98struct address_space_operations udf_adinicb_aops = { 98const struct address_space_operations udf_adinicb_aops = {
99 .readpage = udf_adinicb_readpage, 99 .readpage = udf_adinicb_readpage,
100 .writepage = udf_adinicb_writepage, 100 .writepage = udf_adinicb_writepage,
101 .sync_page = block_sync_page, 101 .sync_page = block_sync_page,
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 2983afd5e7fd..605f5111b6d8 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -132,7 +132,7 @@ static sector_t udf_bmap(struct address_space *mapping, sector_t block)
132 return generic_block_bmap(mapping,block,udf_get_block); 132 return generic_block_bmap(mapping,block,udf_get_block);
133} 133}
134 134
135struct address_space_operations udf_aops = { 135const struct address_space_operations udf_aops = {
136 .readpage = udf_readpage, 136 .readpage = udf_readpage,
137 .writepage = udf_writepage, 137 .writepage = udf_writepage,
138 .sync_page = block_sync_page, 138 .sync_page = block_sync_page,
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
index 674bb40edc83..ba068a786563 100644
--- a/fs/udf/symlink.c
+++ b/fs/udf/symlink.c
@@ -113,6 +113,6 @@ out:
113/* 113/*
114 * symlinks can't do much... 114 * symlinks can't do much...
115 */ 115 */
116struct address_space_operations udf_symlink_aops = { 116const struct address_space_operations udf_symlink_aops = {
117 .readpage = udf_symlink_filler, 117 .readpage = udf_symlink_filler,
118}; 118};
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 023e19ba5a2e..2f992387cc9e 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -47,9 +47,9 @@ extern struct inode_operations udf_dir_inode_operations;
47extern const struct file_operations udf_dir_operations; 47extern const struct file_operations udf_dir_operations;
48extern struct inode_operations udf_file_inode_operations; 48extern struct inode_operations udf_file_inode_operations;
49extern const struct file_operations udf_file_operations; 49extern const struct file_operations udf_file_operations;
50extern struct address_space_operations udf_aops; 50extern const struct address_space_operations udf_aops;
51extern struct address_space_operations udf_adinicb_aops; 51extern const struct address_space_operations udf_adinicb_aops;
52extern struct address_space_operations udf_symlink_aops; 52extern const struct address_space_operations udf_symlink_aops;
53 53
54struct udf_fileident_bh 54struct udf_fileident_bh
55{ 55{
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index f2dbdf5a8769..488b5ff48afb 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -98,7 +98,9 @@ static u64 ufs_frag_map(struct inode *inode, sector_t frag)
98 u64 temp = 0L; 98 u64 temp = 0L;
99 99
100 UFSD(": frag = %llu depth = %d\n", (unsigned long long)frag, depth); 100 UFSD(": frag = %llu depth = %d\n", (unsigned long long)frag, depth);
101 UFSD(": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",uspi->s_fpbshift,uspi->s_apbmask,mask); 101 UFSD(": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",
102 uspi->s_fpbshift, uspi->s_apbmask,
103 (unsigned long long)mask);
102 104
103 if (depth == 0) 105 if (depth == 0)
104 return 0; 106 return 0;
@@ -429,7 +431,7 @@ int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head
429 431
430 if (!create) { 432 if (!create) {
431 phys64 = ufs_frag_map(inode, fragment); 433 phys64 = ufs_frag_map(inode, fragment);
432 UFSD("phys64 = %llu \n",phys64); 434 UFSD("phys64 = %llu\n", (unsigned long long)phys64);
433 if (phys64) 435 if (phys64)
434 map_bh(bh_result, sb, phys64); 436 map_bh(bh_result, sb, phys64);
435 return 0; 437 return 0;
@@ -574,7 +576,7 @@ static sector_t ufs_bmap(struct address_space *mapping, sector_t block)
574{ 576{
575 return generic_block_bmap(mapping,block,ufs_getfrag_block); 577 return generic_block_bmap(mapping,block,ufs_getfrag_block);
576} 578}
577struct address_space_operations ufs_aops = { 579const struct address_space_operations ufs_aops = {
578 .readpage = ufs_readpage, 580 .readpage = ufs_readpage,
579 .writepage = ufs_writepage, 581 .writepage = ufs_writepage,
580 .sync_page = block_sync_page, 582 .sync_page = block_sync_page,
@@ -605,39 +607,12 @@ static void ufs_set_inode_ops(struct inode *inode)
605 ufs_get_inode_dev(inode->i_sb, UFS_I(inode))); 607 ufs_get_inode_dev(inode->i_sb, UFS_I(inode)));
606} 608}
607 609
608void ufs_read_inode (struct inode * inode) 610static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
609{ 611{
610 struct ufs_inode_info *ufsi = UFS_I(inode); 612 struct ufs_inode_info *ufsi = UFS_I(inode);
611 struct super_block * sb; 613 struct super_block *sb = inode->i_sb;
612 struct ufs_sb_private_info * uspi;
613 struct ufs_inode * ufs_inode;
614 struct ufs2_inode *ufs2_inode;
615 struct buffer_head * bh;
616 mode_t mode; 614 mode_t mode;
617 unsigned i; 615 unsigned i;
618 unsigned flags;
619
620 UFSD("ENTER, ino %lu\n", inode->i_ino);
621
622 sb = inode->i_sb;
623 uspi = UFS_SB(sb)->s_uspi;
624 flags = UFS_SB(sb)->s_flags;
625
626 if (inode->i_ino < UFS_ROOTINO ||
627 inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
628 ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino);
629 goto bad_inode;
630 }
631
632 bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino));
633 if (!bh) {
634 ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
635 goto bad_inode;
636 }
637 if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
638 goto ufs2_inode;
639
640 ufs_inode = (struct ufs_inode *) (bh->b_data + sizeof(struct ufs_inode) * ufs_inotofsbo(inode->i_ino));
641 616
642 /* 617 /*
643 * Copy data to the in-core inode. 618 * Copy data to the in-core inode.
@@ -661,14 +636,11 @@ void ufs_read_inode (struct inode * inode)
661 inode->i_atime.tv_nsec = 0; 636 inode->i_atime.tv_nsec = 0;
662 inode->i_ctime.tv_nsec = 0; 637 inode->i_ctime.tv_nsec = 0;
663 inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks); 638 inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks);
664 inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat) */
665 inode->i_version++;
666 ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags); 639 ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags);
667 ufsi->i_gen = fs32_to_cpu(sb, ufs_inode->ui_gen); 640 ufsi->i_gen = fs32_to_cpu(sb, ufs_inode->ui_gen);
668 ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); 641 ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
669 ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); 642 ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
670 ufsi->i_lastfrag = (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; 643
671 ufsi->i_dir_start_lookup = 0;
672 644
673 if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { 645 if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) {
674 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) 646 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
@@ -677,24 +649,16 @@ void ufs_read_inode (struct inode * inode)
677 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) 649 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++)
678 ufsi->i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i]; 650 ufsi->i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i];
679 } 651 }
680 ufsi->i_osync = 0; 652}
681
682 ufs_set_inode_ops(inode);
683
684 brelse (bh);
685
686 UFSD("EXIT\n");
687 return;
688 653
689bad_inode: 654static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode)
690 make_bad_inode(inode); 655{
691 return; 656 struct ufs_inode_info *ufsi = UFS_I(inode);
657 struct super_block *sb = inode->i_sb;
658 mode_t mode;
659 unsigned i;
692 660
693ufs2_inode :
694 UFSD("Reading ufs2 inode, ino %lu\n", inode->i_ino); 661 UFSD("Reading ufs2 inode, ino %lu\n", inode->i_ino);
695
696 ufs2_inode = (struct ufs2_inode *)(bh->b_data + sizeof(struct ufs2_inode) * ufs_inotofsbo(inode->i_ino));
697
698 /* 662 /*
699 * Copy data to the in-core inode. 663 * Copy data to the in-core inode.
700 */ 664 */
@@ -717,26 +681,64 @@ ufs2_inode :
717 inode->i_atime.tv_nsec = 0; 681 inode->i_atime.tv_nsec = 0;
718 inode->i_ctime.tv_nsec = 0; 682 inode->i_ctime.tv_nsec = 0;
719 inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks); 683 inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks);
720 inode->i_blksize = PAGE_SIZE; /*This is the optimal IO size(for stat)*/
721
722 inode->i_version++;
723 ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags); 684 ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags);
724 ufsi->i_gen = fs32_to_cpu(sb, ufs2_inode->ui_gen); 685 ufsi->i_gen = fs32_to_cpu(sb, ufs2_inode->ui_gen);
725 /* 686 /*
726 ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); 687 ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
727 ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); 688 ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
728 */ 689 */
729 ufsi->i_lastfrag= (inode->i_size + uspi->s_fsize- 1) >> uspi->s_fshift;
730 690
731 if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { 691 if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) {
732 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) 692 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
733 ufsi->i_u1.u2_i_data[i] = 693 ufsi->i_u1.u2_i_data[i] =
734 ufs2_inode->ui_u2.ui_addr.ui_db[i]; 694 ufs2_inode->ui_u2.ui_addr.ui_db[i];
735 } 695 } else {
736 else {
737 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) 696 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++)
738 ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i]; 697 ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i];
739 } 698 }
699}
700
701void ufs_read_inode(struct inode * inode)
702{
703 struct ufs_inode_info *ufsi = UFS_I(inode);
704 struct super_block * sb;
705 struct ufs_sb_private_info * uspi;
706 struct buffer_head * bh;
707
708 UFSD("ENTER, ino %lu\n", inode->i_ino);
709
710 sb = inode->i_sb;
711 uspi = UFS_SB(sb)->s_uspi;
712
713 if (inode->i_ino < UFS_ROOTINO ||
714 inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
715 ufs_warning(sb, "ufs_read_inode", "bad inode number (%lu)\n",
716 inode->i_ino);
717 goto bad_inode;
718 }
719
720 bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino));
721 if (!bh) {
722 ufs_warning(sb, "ufs_read_inode", "unable to read inode %lu\n",
723 inode->i_ino);
724 goto bad_inode;
725 }
726 if ((UFS_SB(sb)->s_flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
727 struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data;
728
729 ufs2_read_inode(inode,
730 ufs2_inode + ufs_inotofsbo(inode->i_ino));
731 } else {
732 struct ufs_inode *ufs_inode = (struct ufs_inode *)bh->b_data;
733
734 ufs1_read_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino));
735 }
736
737 inode->i_blksize = PAGE_SIZE;/*This is the optimal IO size (for stat)*/
738 inode->i_version++;
739 ufsi->i_lastfrag =
740 (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
741 ufsi->i_dir_start_lookup = 0;
740 ufsi->i_osync = 0; 742 ufsi->i_osync = 0;
741 743
742 ufs_set_inode_ops(inode); 744 ufs_set_inode_ops(inode);
@@ -745,6 +747,9 @@ ufs2_inode :
745 747
746 UFSD("EXIT\n"); 748 UFSD("EXIT\n");
747 return; 749 return;
750
751bad_inode:
752 make_bad_inode(inode);
748} 753}
749 754
750static int ufs_update_inode(struct inode * inode, int do_sync) 755static int ufs_update_inode(struct inode * inode, int do_sync)
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 3e807b828e22..c40f81ba9b13 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -1454,7 +1454,7 @@ xfs_vm_invalidatepage(
1454 block_invalidatepage(page, offset); 1454 block_invalidatepage(page, offset);
1455} 1455}
1456 1456
1457struct address_space_operations xfs_address_space_operations = { 1457const struct address_space_operations xfs_address_space_operations = {
1458 .readpage = xfs_vm_readpage, 1458 .readpage = xfs_vm_readpage,
1459 .readpages = xfs_vm_readpages, 1459 .readpages = xfs_vm_readpages,
1460 .writepage = xfs_vm_writepage, 1460 .writepage = xfs_vm_writepage,
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h
index 706d8c781b8a..2244e516b66a 100644
--- a/fs/xfs/linux-2.6/xfs_aops.h
+++ b/fs/xfs/linux-2.6/xfs_aops.h
@@ -40,7 +40,7 @@ typedef struct xfs_ioend {
40 struct work_struct io_work; /* xfsdatad work queue */ 40 struct work_struct io_work; /* xfsdatad work queue */
41} xfs_ioend_t; 41} xfs_ioend_t;
42 42
43extern struct address_space_operations xfs_address_space_operations; 43extern const 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_AOPS_H__ */ 46#endif /* __XFS_AOPS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 26fed0756f01..2af528dcfb04 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -1520,7 +1520,7 @@ xfs_mapping_buftarg(
1520 struct backing_dev_info *bdi; 1520 struct backing_dev_info *bdi;
1521 struct inode *inode; 1521 struct inode *inode;
1522 struct address_space *mapping; 1522 struct address_space *mapping;
1523 static struct address_space_operations mapping_aops = { 1523 static const struct address_space_operations mapping_aops = {
1524 .sync_page = block_sync_page, 1524 .sync_page = block_sync_page,
1525 .migratepage = fail_migrate_page, 1525 .migratepage = fail_migrate_page,
1526 }; 1526 };
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 12810baeb5d4..d9180020de63 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -419,16 +419,15 @@ xfs_vn_link(
419 int error; 419 int error;
420 420
421 ip = old_dentry->d_inode; /* inode being linked to */ 421 ip = old_dentry->d_inode; /* inode being linked to */
422 if (S_ISDIR(ip->i_mode))
423 return -EPERM;
424
425 tdvp = vn_from_inode(dir); 422 tdvp = vn_from_inode(dir);
426 vp = vn_from_inode(ip); 423 vp = vn_from_inode(ip);
427 424
425 VN_HOLD(vp);
428 error = bhv_vop_link(tdvp, vp, dentry, NULL); 426 error = bhv_vop_link(tdvp, vp, dentry, NULL);
429 if (likely(!error)) { 427 if (unlikely(error)) {
428 VN_RELE(vp);
429 } else {
430 VMODIFY(tdvp); 430 VMODIFY(tdvp);
431 VN_HOLD(vp);
432 xfs_validate_fields(ip, &vattr); 431 xfs_validate_fields(ip, &vattr);
433 d_instantiate(dentry, ip); 432 d_instantiate(dentry, ip);
434 } 433 }
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index aa26ab906c88..028eb17ec2ed 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -140,9 +140,7 @@ BUFFER_FNS(PrivateStart, unwritten);
140#define current_pid() (current->pid) 140#define current_pid() (current->pid)
141#define current_fsuid(cred) (current->fsuid) 141#define current_fsuid(cred) (current->fsuid)
142#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)) 143#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) \ 144#define current_set_flags_nested(sp, f) \
147 (*(sp) = current->flags, current->flags |= (f)) 145 (*(sp) = current->flags, current->flags |= (f))
148#define current_clear_flags_nested(sp, f) \ 146#define current_clear_flags_nested(sp, f) \
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 35c6a01963a7..c42b3221b20c 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -93,7 +93,7 @@ typedef enum {
93 */ 93 */
94static inline struct bhv_vnode *vn_from_inode(struct inode *inode) 94static inline struct bhv_vnode *vn_from_inode(struct inode *inode)
95{ 95{
96 return (bhv_vnode_t *)list_entry(inode, bhv_vnode_t, v_inode); 96 return container_of(inode, bhv_vnode_t, v_inode);
97} 97}
98static inline struct inode *vn_to_inode(struct bhv_vnode *vnode) 98static inline struct inode *vn_to_inode(struct bhv_vnode *vnode)
99{ 99{
diff --git a/fs/xfs/xfs_behavior.h b/fs/xfs/xfs_behavior.h
index 1d8ff103201c..6e6e56fb352d 100644
--- a/fs/xfs/xfs_behavior.h
+++ b/fs/xfs/xfs_behavior.h
@@ -78,15 +78,12 @@
78 * 78 *
79 */ 79 */
80 80
81struct bhv_head_lock;
82
83/* 81/*
84 * Behavior head. Head of the chain of behaviors. 82 * Behavior head. Head of the chain of behaviors.
85 * Contained within each virtualized object data structure. 83 * Contained within each virtualized object data structure.
86 */ 84 */
87typedef struct bhv_head { 85typedef struct bhv_head {
88 struct bhv_desc *bh_first; /* first behavior in chain */ 86 struct bhv_desc *bh_first; /* first behavior in chain */
89 struct bhv_head_lock *bh_lockp; /* pointer to lock info struct */
90} bhv_head_t; 87} bhv_head_t;
91 88
92/* 89/*
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 5fa0adb7e173..86c1bf0bba9e 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1961,9 +1961,9 @@ xfs_iunlink_remove(
1961 xfs_agino_t agino; 1961 xfs_agino_t agino;
1962 xfs_agino_t next_agino; 1962 xfs_agino_t next_agino;
1963 xfs_buf_t *last_ibp; 1963 xfs_buf_t *last_ibp;
1964 xfs_dinode_t *last_dip; 1964 xfs_dinode_t *last_dip = NULL;
1965 short bucket_index; 1965 short bucket_index;
1966 int offset, last_offset; 1966 int offset, last_offset = 0;
1967 int error; 1967 int error;
1968 int agi_ok; 1968 int agi_ok;
1969 1969
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index d8f5d4cbe8b7..e730328636c3 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -1740,10 +1740,10 @@ xlog_write(xfs_mount_t * mp,
1740 xlog_in_core_t **commit_iclog, 1740 xlog_in_core_t **commit_iclog,
1741 uint flags) 1741 uint flags)
1742{ 1742{
1743 xlog_t *log = mp->m_log; 1743 xlog_t *log = mp->m_log;
1744 xlog_ticket_t *ticket = (xlog_ticket_t *)tic; 1744 xlog_ticket_t *ticket = (xlog_ticket_t *)tic;
1745 xlog_in_core_t *iclog = NULL; /* ptr to current in-core log */
1745 xlog_op_header_t *logop_head; /* ptr to log operation header */ 1746 xlog_op_header_t *logop_head; /* ptr to log operation header */
1746 xlog_in_core_t *iclog; /* ptr to current in-core log */
1747 __psint_t ptr; /* copy address into data region */ 1747 __psint_t ptr; /* copy address into data region */
1748 int len; /* # xlog_write() bytes 2 still copy */ 1748 int len; /* # xlog_write() bytes 2 still copy */
1749 int index; /* region index currently copying */ 1749 int index; /* region index currently copying */
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 55b4237c2153..3cb678e3a132 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -990,6 +990,8 @@ xlog_find_zeroed(
990 xfs_daddr_t num_scan_bblks; 990 xfs_daddr_t num_scan_bblks;
991 int error, log_bbnum = log->l_logBBsize; 991 int error, log_bbnum = log->l_logBBsize;
992 992
993 *blk_no = 0;
994
993 /* check totally zeroed log */ 995 /* check totally zeroed log */
994 bp = xlog_get_bp(log, 1); 996 bp = xlog_get_bp(log, 1);
995 if (!bp) 997 if (!bp)
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 10dbf203c62f..4be5c0b2d296 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1721,15 +1721,14 @@ xfs_mount_log_sbunit(
1721 * is present to prevent thrashing). 1721 * is present to prevent thrashing).
1722 */ 1722 */
1723 1723
1724#ifdef CONFIG_HOTPLUG_CPU
1724/* 1725/*
1725 * hot-plug CPU notifier support. 1726 * hot-plug CPU notifier support.
1726 * 1727 *
1727 * We cannot use the hotcpu_register() function because it does 1728 * We need a notifier per filesystem as we need to be able to identify
1728 * not allow notifier instances. We need a notifier per filesystem 1729 * the filesystem to balance the counters out. This is achieved by
1729 * as we need to be able to identify the filesystem to balance 1730 * having a notifier block embedded in the xfs_mount_t and doing pointer
1730 * the counters out. This is achieved by having a notifier block 1731 * magic to get the mount pointer from the notifier block address.
1731 * embedded in the xfs_mount_t and doing pointer magic to get the
1732 * mount pointer from the notifier block address.
1733 */ 1732 */
1734STATIC int 1733STATIC int
1735xfs_icsb_cpu_notify( 1734xfs_icsb_cpu_notify(
@@ -1779,6 +1778,7 @@ xfs_icsb_cpu_notify(
1779 1778
1780 return NOTIFY_OK; 1779 return NOTIFY_OK;
1781} 1780}
1781#endif /* CONFIG_HOTPLUG_CPU */
1782 1782
1783int 1783int
1784xfs_icsb_init_counters( 1784xfs_icsb_init_counters(
@@ -1791,9 +1791,11 @@ xfs_icsb_init_counters(
1791 if (mp->m_sb_cnts == NULL) 1791 if (mp->m_sb_cnts == NULL)
1792 return -ENOMEM; 1792 return -ENOMEM;
1793 1793
1794#ifdef CONFIG_HOTPLUG_CPU
1794 mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify; 1795 mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify;
1795 mp->m_icsb_notifier.priority = 0; 1796 mp->m_icsb_notifier.priority = 0;
1796 register_cpu_notifier(&mp->m_icsb_notifier); 1797 register_hotcpu_notifier(&mp->m_icsb_notifier);
1798#endif /* CONFIG_HOTPLUG_CPU */
1797 1799
1798 for_each_online_cpu(i) { 1800 for_each_online_cpu(i) {
1799 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); 1801 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
@@ -1812,7 +1814,7 @@ xfs_icsb_destroy_counters(
1812 xfs_mount_t *mp) 1814 xfs_mount_t *mp)
1813{ 1815{
1814 if (mp->m_sb_cnts) { 1816 if (mp->m_sb_cnts) {
1815 unregister_cpu_notifier(&mp->m_icsb_notifier); 1817 unregister_hotcpu_notifier(&mp->m_icsb_notifier);
1816 free_percpu(mp->m_sb_cnts); 1818 free_percpu(mp->m_sb_cnts);
1817 } 1819 }
1818} 1820}
@@ -2026,7 +2028,7 @@ xfs_icsb_balance_counter(
2026 xfs_sb_field_t field, 2028 xfs_sb_field_t field,
2027 int flags) 2029 int flags)
2028{ 2030{
2029 uint64_t count, resid = 0; 2031 uint64_t count, resid;
2030 int weight = num_online_cpus(); 2032 int weight = num_online_cpus();
2031 int s; 2033 int s;
2032 2034
@@ -2058,6 +2060,7 @@ xfs_icsb_balance_counter(
2058 break; 2060 break;
2059 default: 2061 default:
2060 BUG(); 2062 BUG();
2063 count = resid = 0; /* quiet, gcc */
2061 break; 2064 break;
2062 } 2065 }
2063 2066
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 0c1e42b037ef..5a0b678956e0 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1929,7 +1929,7 @@ xfs_growfs_rt(
1929 /* 1929 /*
1930 * Initial error checking. 1930 * Initial error checking.
1931 */ 1931 */
1932 if (mp->m_rtdev_targp || mp->m_rbmip == NULL || 1932 if (mp->m_rtdev_targp == NULL || mp->m_rbmip == NULL ||
1933 (nrblocks = in->newblocks) <= sbp->sb_rblocks || 1933 (nrblocks = in->newblocks) <= sbp->sb_rblocks ||
1934 (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize))) 1934 (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))
1935 return XFS_ERROR(EINVAL); 1935 return XFS_ERROR(EINVAL);
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index cb65c3a603f5..9dc88b380608 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -338,8 +338,6 @@ typedef void (*xfs_trans_callback_t)(struct xfs_trans *, void *);
338typedef struct xfs_trans { 338typedef struct xfs_trans {
339 unsigned int t_magic; /* magic number */ 339 unsigned int t_magic; /* magic number */
340 xfs_log_callback_t t_logcb; /* log callback struct */ 340 xfs_log_callback_t t_logcb; /* log callback struct */
341 struct xfs_trans *t_forw; /* async list pointers */
342 struct xfs_trans *t_back; /* async list pointers */
343 unsigned int t_type; /* transaction type */ 341 unsigned int t_type; /* transaction type */
344 unsigned int t_log_res; /* amt of log space resvd */ 342 unsigned int t_log_res; /* amt of log space resvd */
345 unsigned int t_log_count; /* count for perm log res */ 343 unsigned int t_log_count; /* count for perm log res */
@@ -364,9 +362,11 @@ typedef struct xfs_trans {
364 long t_res_fdblocks_delta; /* on-disk only chg */ 362 long t_res_fdblocks_delta; /* on-disk only chg */
365 long t_frextents_delta;/* superblock freextents chg*/ 363 long t_frextents_delta;/* superblock freextents chg*/
366 long t_res_frextents_delta; /* on-disk only chg */ 364 long t_res_frextents_delta; /* on-disk only chg */
365#ifdef DEBUG
367 long t_ag_freeblks_delta; /* debugging counter */ 366 long t_ag_freeblks_delta; /* debugging counter */
368 long t_ag_flist_delta; /* debugging counter */ 367 long t_ag_flist_delta; /* debugging counter */
369 long t_ag_btree_delta; /* debugging counter */ 368 long t_ag_btree_delta; /* debugging counter */
369#endif
370 long t_dblocks_delta;/* superblock dblocks change */ 370 long t_dblocks_delta;/* superblock dblocks change */
371 long t_agcount_delta;/* superblock agcount change */ 371 long t_agcount_delta;/* superblock agcount change */
372 long t_imaxpct_delta;/* superblock imaxpct change */ 372 long t_imaxpct_delta;/* superblock imaxpct change */
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 00a6b7dc24a0..23cfa5837728 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -2603,8 +2603,7 @@ xfs_link(
2603 vn_trace_entry(src_vp, __FUNCTION__, (inst_t *)__return_address); 2603 vn_trace_entry(src_vp, __FUNCTION__, (inst_t *)__return_address);
2604 2604
2605 target_namelen = VNAMELEN(dentry); 2605 target_namelen = VNAMELEN(dentry);
2606 if (VN_ISDIR(src_vp)) 2606 ASSERT(!VN_ISDIR(src_vp));
2607 return XFS_ERROR(EPERM);
2608 2607
2609 sip = xfs_vtoi(src_vp); 2608 sip = xfs_vtoi(src_vp);
2610 tdp = XFS_BHVTOI(target_dir_bdp); 2609 tdp = XFS_BHVTOI(target_dir_bdp);
@@ -2699,9 +2698,8 @@ xfs_link(
2699 xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE); 2698 xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE);
2700 2699
2701 error = xfs_bumplink(tp, sip); 2700 error = xfs_bumplink(tp, sip);
2702 if (error) { 2701 if (error)
2703 goto abort_return; 2702 goto abort_return;
2704 }
2705 2703
2706 /* 2704 /*
2707 * If this is a synchronous mount, make sure that the 2705 * If this is a synchronous mount, make sure that the
@@ -2719,9 +2717,8 @@ xfs_link(
2719 } 2717 }
2720 2718
2721 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); 2719 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
2722 if (error) { 2720 if (error)
2723 goto std_return; 2721 goto std_return;
2724 }
2725 2722
2726 /* Fall through to std_return with error = 0. */ 2723 /* Fall through to std_return with error = 0. */
2727std_return: 2724std_return:
@@ -2742,6 +2739,8 @@ std_return:
2742 xfs_trans_cancel(tp, cancel_flags); 2739 xfs_trans_cancel(tp, cancel_flags);
2743 goto std_return; 2740 goto std_return;
2744} 2741}
2742
2743
2745/* 2744/*
2746 * xfs_mkdir 2745 * xfs_mkdir
2747 * 2746 *