diff options
Diffstat (limited to 'fs')
41 files changed, 541 insertions, 176 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index 3f00a9faabcb..530581628311 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -325,8 +325,8 @@ config FS_POSIX_ACL | |||
325 | source "fs/xfs/Kconfig" | 325 | source "fs/xfs/Kconfig" |
326 | 326 | ||
327 | config OCFS2_FS | 327 | config OCFS2_FS |
328 | tristate "OCFS2 file system support (EXPERIMENTAL)" | 328 | tristate "OCFS2 file system support" |
329 | depends on NET && SYSFS && EXPERIMENTAL | 329 | depends on NET && SYSFS |
330 | select CONFIGFS_FS | 330 | select CONFIGFS_FS |
331 | select JBD | 331 | select JBD |
332 | select CRC32 | 332 | select CRC32 |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 0feb3bd49cb8..1eb9a2ec0a3b 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,3 +1,7 @@ | |||
1 | Version 1.46 | ||
2 | ------------ | ||
3 | Support deep tree mounts. Better support OS/2, Win9x (DOS) time stamps. | ||
4 | |||
1 | Version 1.45 | 5 | Version 1.45 |
2 | ------------ | 6 | ------------ |
3 | Do not time out lockw calls when using posix extensions. Do not | 7 | Do not time out lockw calls when using posix extensions. Do not |
@@ -6,7 +10,8 @@ on requests on other threads. Improve POSIX locking emulation, | |||
6 | (lock cancel now works, and unlock of merged range works even | 10 | (lock cancel now works, and unlock of merged range works even |
7 | to Windows servers now). Fix oops on mount to lanman servers | 11 | to Windows servers now). Fix oops on mount to lanman servers |
8 | (win9x, os/2 etc.) when null password. Do not send listxattr | 12 | (win9x, os/2 etc.) when null password. Do not send listxattr |
9 | (SMB to query all EAs) if nouser_xattr specified. | 13 | (SMB to query all EAs) if nouser_xattr specified. Fix SE Linux |
14 | problem (instantiate inodes/dentries in right order for readdir). | ||
10 | 15 | ||
11 | Version 1.44 | 16 | Version 1.44 |
12 | ------------ | 17 | ------------ |
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index ad58eb0c4d6d..fd1e52ebcee6 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
@@ -40,5 +40,7 @@ struct cifs_sb_info { | |||
40 | mode_t mnt_file_mode; | 40 | mode_t mnt_file_mode; |
41 | mode_t mnt_dir_mode; | 41 | mode_t mnt_dir_mode; |
42 | int mnt_cifs_flags; | 42 | int mnt_cifs_flags; |
43 | int prepathlen; | ||
44 | char * prepath; | ||
43 | }; | 45 | }; |
44 | #endif /* _CIFS_FS_SB_H */ | 46 | #endif /* _CIFS_FS_SB_H */ |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 3cd750029be2..c3ef1c0d0e68 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -189,7 +189,6 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
189 | buf->f_files = 0; /* undefined */ | 189 | buf->f_files = 0; /* undefined */ |
190 | buf->f_ffree = 0; /* unlimited */ | 190 | buf->f_ffree = 0; /* unlimited */ |
191 | 191 | ||
192 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
193 | /* BB we could add a second check for a QFS Unix capability bit */ | 192 | /* BB we could add a second check for a QFS Unix capability bit */ |
194 | /* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */ | 193 | /* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */ |
195 | if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS & | 194 | if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS & |
@@ -199,7 +198,6 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
199 | /* Only need to call the old QFSInfo if failed | 198 | /* Only need to call the old QFSInfo if failed |
200 | on newer one */ | 199 | on newer one */ |
201 | if(rc) | 200 | if(rc) |
202 | #endif /* CIFS_EXPERIMENTAL */ | ||
203 | rc = CIFSSMBQFSInfo(xid, pTcon, buf); | 201 | rc = CIFSSMBQFSInfo(xid, pTcon, buf); |
204 | 202 | ||
205 | /* Old Windows servers do not support level 103, retry with level | 203 | /* Old Windows servers do not support level 103, retry with level |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 39ee8ef3bdeb..bea875d9a46a 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); | |||
100 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 100 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
101 | extern int cifs_ioctl (struct inode * inode, struct file * filep, | 101 | extern int cifs_ioctl (struct inode * inode, struct file * filep, |
102 | unsigned int command, unsigned long arg); | 102 | unsigned int command, unsigned long arg); |
103 | #define CIFS_VERSION "1.45" | 103 | #define CIFS_VERSION "1.46" |
104 | #endif /* _CIFSFS_H */ | 104 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 86239023545b..81df2bf8e75a 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -1344,6 +1344,7 @@ struct smb_t2_rsp { | |||
1344 | #define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */ | 1344 | #define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */ |
1345 | #define SMB_QUERY_POSIX_PERMISSION 0x207 | 1345 | #define SMB_QUERY_POSIX_PERMISSION 0x207 |
1346 | #define SMB_QUERY_POSIX_LOCK 0x208 | 1346 | #define SMB_QUERY_POSIX_LOCK 0x208 |
1347 | /* #define SMB_POSIX_OPEN 0x209 */ | ||
1347 | #define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee | 1348 | #define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee |
1348 | #define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 | 1349 | #define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 |
1349 | #define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ | 1350 | #define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ |
@@ -1363,6 +1364,7 @@ struct smb_t2_rsp { | |||
1363 | #define SMB_SET_XATTR 0x205 | 1364 | #define SMB_SET_XATTR 0x205 |
1364 | #define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */ | 1365 | #define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */ |
1365 | #define SMB_SET_POSIX_LOCK 0x208 | 1366 | #define SMB_SET_POSIX_LOCK 0x208 |
1367 | #define SMB_POSIX_OPEN 0x209 | ||
1366 | #define SMB_SET_FILE_BASIC_INFO2 0x3ec | 1368 | #define SMB_SET_FILE_BASIC_INFO2 0x3ec |
1367 | #define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ | 1369 | #define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ |
1368 | #define SMB_FILE_ALL_INFO2 0x3fa | 1370 | #define SMB_FILE_ALL_INFO2 0x3fa |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 5d394c726860..0e9ba0b9d71e 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -89,6 +89,7 @@ struct smb_vol { | |||
89 | unsigned int wsize; | 89 | unsigned int wsize; |
90 | unsigned int sockopt; | 90 | unsigned int sockopt; |
91 | unsigned short int port; | 91 | unsigned short int port; |
92 | char * prepath; | ||
92 | }; | 93 | }; |
93 | 94 | ||
94 | static int ipv4_connect(struct sockaddr_in *psin_server, | 95 | static int ipv4_connect(struct sockaddr_in *psin_server, |
@@ -993,6 +994,28 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
993 | printk(KERN_WARNING "CIFS: domain name too long\n"); | 994 | printk(KERN_WARNING "CIFS: domain name too long\n"); |
994 | return 1; | 995 | return 1; |
995 | } | 996 | } |
997 | } else if (strnicmp(data, "prefixpath", 10) == 0) { | ||
998 | if (!value || !*value) { | ||
999 | printk(KERN_WARNING | ||
1000 | "CIFS: invalid path prefix\n"); | ||
1001 | return 1; /* needs_arg; */ | ||
1002 | } | ||
1003 | if ((temp_len = strnlen(value, 1024)) < 1024) { | ||
1004 | if(value[0] != '/') | ||
1005 | temp_len++; /* missing leading slash */ | ||
1006 | vol->prepath = kmalloc(temp_len+1,GFP_KERNEL); | ||
1007 | if(vol->prepath == NULL) | ||
1008 | return 1; | ||
1009 | if(value[0] != '/') { | ||
1010 | vol->prepath[0] = '/'; | ||
1011 | strcpy(vol->prepath+1,value); | ||
1012 | } else | ||
1013 | strcpy(vol->prepath,value); | ||
1014 | cFYI(1,("prefix path %s",vol->prepath)); | ||
1015 | } else { | ||
1016 | printk(KERN_WARNING "CIFS: prefix too long\n"); | ||
1017 | return 1; | ||
1018 | } | ||
996 | } else if (strnicmp(data, "iocharset", 9) == 0) { | 1019 | } else if (strnicmp(data, "iocharset", 9) == 0) { |
997 | if (!value || !*value) { | 1020 | if (!value || !*value) { |
998 | printk(KERN_WARNING "CIFS: invalid iocharset specified\n"); | 1021 | printk(KERN_WARNING "CIFS: invalid iocharset specified\n"); |
@@ -1605,6 +1628,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1605 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { | 1628 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { |
1606 | kfree(volume_info.UNC); | 1629 | kfree(volume_info.UNC); |
1607 | kfree(volume_info.password); | 1630 | kfree(volume_info.password); |
1631 | kfree(volume_info.prepath); | ||
1608 | FreeXid(xid); | 1632 | FreeXid(xid); |
1609 | return -EINVAL; | 1633 | return -EINVAL; |
1610 | } | 1634 | } |
@@ -1619,6 +1643,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1619 | locations such as env variables and files on disk */ | 1643 | locations such as env variables and files on disk */ |
1620 | kfree(volume_info.UNC); | 1644 | kfree(volume_info.UNC); |
1621 | kfree(volume_info.password); | 1645 | kfree(volume_info.password); |
1646 | kfree(volume_info.prepath); | ||
1622 | FreeXid(xid); | 1647 | FreeXid(xid); |
1623 | return -EINVAL; | 1648 | return -EINVAL; |
1624 | } | 1649 | } |
@@ -1639,6 +1664,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1639 | /* we failed translating address */ | 1664 | /* we failed translating address */ |
1640 | kfree(volume_info.UNC); | 1665 | kfree(volume_info.UNC); |
1641 | kfree(volume_info.password); | 1666 | kfree(volume_info.password); |
1667 | kfree(volume_info.prepath); | ||
1642 | FreeXid(xid); | 1668 | FreeXid(xid); |
1643 | return -EINVAL; | 1669 | return -EINVAL; |
1644 | } | 1670 | } |
@@ -1651,6 +1677,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1651 | cERROR(1,("Connecting to DFS root not implemented yet")); | 1677 | cERROR(1,("Connecting to DFS root not implemented yet")); |
1652 | kfree(volume_info.UNC); | 1678 | kfree(volume_info.UNC); |
1653 | kfree(volume_info.password); | 1679 | kfree(volume_info.password); |
1680 | kfree(volume_info.prepath); | ||
1654 | FreeXid(xid); | 1681 | FreeXid(xid); |
1655 | return -EINVAL; | 1682 | return -EINVAL; |
1656 | } else /* which servers DFS root would we conect to */ { | 1683 | } else /* which servers DFS root would we conect to */ { |
@@ -1658,6 +1685,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1658 | ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified")); | 1685 | ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified")); |
1659 | kfree(volume_info.UNC); | 1686 | kfree(volume_info.UNC); |
1660 | kfree(volume_info.password); | 1687 | kfree(volume_info.password); |
1688 | kfree(volume_info.prepath); | ||
1661 | FreeXid(xid); | 1689 | FreeXid(xid); |
1662 | return -EINVAL; | 1690 | return -EINVAL; |
1663 | } | 1691 | } |
@@ -1672,6 +1700,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1672 | cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset)); | 1700 | cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset)); |
1673 | kfree(volume_info.UNC); | 1701 | kfree(volume_info.UNC); |
1674 | kfree(volume_info.password); | 1702 | kfree(volume_info.password); |
1703 | kfree(volume_info.prepath); | ||
1675 | FreeXid(xid); | 1704 | FreeXid(xid); |
1676 | return -ELIBACC; | 1705 | return -ELIBACC; |
1677 | } | 1706 | } |
@@ -1688,6 +1717,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1688 | else { | 1717 | else { |
1689 | kfree(volume_info.UNC); | 1718 | kfree(volume_info.UNC); |
1690 | kfree(volume_info.password); | 1719 | kfree(volume_info.password); |
1720 | kfree(volume_info.prepath); | ||
1691 | FreeXid(xid); | 1721 | FreeXid(xid); |
1692 | return -EINVAL; | 1722 | return -EINVAL; |
1693 | } | 1723 | } |
@@ -1710,6 +1740,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1710 | sock_release(csocket); | 1740 | sock_release(csocket); |
1711 | kfree(volume_info.UNC); | 1741 | kfree(volume_info.UNC); |
1712 | kfree(volume_info.password); | 1742 | kfree(volume_info.password); |
1743 | kfree(volume_info.prepath); | ||
1713 | FreeXid(xid); | 1744 | FreeXid(xid); |
1714 | return rc; | 1745 | return rc; |
1715 | } | 1746 | } |
@@ -1720,6 +1751,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1720 | sock_release(csocket); | 1751 | sock_release(csocket); |
1721 | kfree(volume_info.UNC); | 1752 | kfree(volume_info.UNC); |
1722 | kfree(volume_info.password); | 1753 | kfree(volume_info.password); |
1754 | kfree(volume_info.prepath); | ||
1723 | FreeXid(xid); | 1755 | FreeXid(xid); |
1724 | return rc; | 1756 | return rc; |
1725 | } else { | 1757 | } else { |
@@ -1744,6 +1776,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1744 | sock_release(csocket); | 1776 | sock_release(csocket); |
1745 | kfree(volume_info.UNC); | 1777 | kfree(volume_info.UNC); |
1746 | kfree(volume_info.password); | 1778 | kfree(volume_info.password); |
1779 | kfree(volume_info.prepath); | ||
1747 | FreeXid(xid); | 1780 | FreeXid(xid); |
1748 | return rc; | 1781 | return rc; |
1749 | } | 1782 | } |
@@ -1831,6 +1864,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1831 | /* Windows ME may prefer this */ | 1864 | /* Windows ME may prefer this */ |
1832 | cFYI(1,("readsize set to minimum 2048")); | 1865 | cFYI(1,("readsize set to minimum 2048")); |
1833 | } | 1866 | } |
1867 | /* calculate prepath */ | ||
1868 | cifs_sb->prepath = volume_info.prepath; | ||
1869 | if(cifs_sb->prepath) { | ||
1870 | cifs_sb->prepathlen = strlen(cifs_sb->prepath); | ||
1871 | cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb); | ||
1872 | volume_info.prepath = NULL; | ||
1873 | } else | ||
1874 | cifs_sb->prepathlen = 0; | ||
1834 | cifs_sb->mnt_uid = volume_info.linux_uid; | 1875 | cifs_sb->mnt_uid = volume_info.linux_uid; |
1835 | cifs_sb->mnt_gid = volume_info.linux_gid; | 1876 | cifs_sb->mnt_gid = volume_info.linux_gid; |
1836 | cifs_sb->mnt_file_mode = volume_info.file_mode; | 1877 | cifs_sb->mnt_file_mode = volume_info.file_mode; |
@@ -2008,6 +2049,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2008 | the password ptr is put in the new session structure (in which case the | 2049 | the password ptr is put in the new session structure (in which case the |
2009 | password will be freed at unmount time) */ | 2050 | password will be freed at unmount time) */ |
2010 | kfree(volume_info.UNC); | 2051 | kfree(volume_info.UNC); |
2052 | kfree(volume_info.prepath); | ||
2011 | FreeXid(xid); | 2053 | FreeXid(xid); |
2012 | return rc; | 2054 | return rc; |
2013 | } | 2055 | } |
@@ -3195,6 +3237,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
3195 | int xid; | 3237 | int xid; |
3196 | struct cifsSesInfo *ses = NULL; | 3238 | struct cifsSesInfo *ses = NULL; |
3197 | struct task_struct *cifsd_task; | 3239 | struct task_struct *cifsd_task; |
3240 | char * tmp; | ||
3198 | 3241 | ||
3199 | xid = GetXid(); | 3242 | xid = GetXid(); |
3200 | 3243 | ||
@@ -3228,6 +3271,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
3228 | } | 3271 | } |
3229 | 3272 | ||
3230 | cifs_sb->tcon = NULL; | 3273 | cifs_sb->tcon = NULL; |
3274 | tmp = cifs_sb->prepath; | ||
3275 | cifs_sb->prepathlen = 0; | ||
3276 | cifs_sb->prepath = NULL; | ||
3277 | kfree(tmp); | ||
3231 | if (ses) | 3278 | if (ses) |
3232 | schedule_timeout_interruptible(msecs_to_jiffies(500)); | 3279 | schedule_timeout_interruptible(msecs_to_jiffies(500)); |
3233 | if (ses) | 3280 | if (ses) |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 914239d53634..66b825ade3e1 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -46,7 +46,8 @@ char * | |||
46 | build_path_from_dentry(struct dentry *direntry) | 46 | build_path_from_dentry(struct dentry *direntry) |
47 | { | 47 | { |
48 | struct dentry *temp; | 48 | struct dentry *temp; |
49 | int namelen = 0; | 49 | int namelen; |
50 | int pplen; | ||
50 | char *full_path; | 51 | char *full_path; |
51 | char dirsep; | 52 | char dirsep; |
52 | 53 | ||
@@ -56,7 +57,9 @@ build_path_from_dentry(struct dentry *direntry) | |||
56 | when the server crashed */ | 57 | when the server crashed */ |
57 | 58 | ||
58 | dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); | 59 | dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); |
60 | pplen = CIFS_SB(direntry->d_sb)->prepathlen; | ||
59 | cifs_bp_rename_retry: | 61 | cifs_bp_rename_retry: |
62 | namelen = pplen; | ||
60 | for (temp = direntry; !IS_ROOT(temp);) { | 63 | for (temp = direntry; !IS_ROOT(temp);) { |
61 | namelen += (1 + temp->d_name.len); | 64 | namelen += (1 + temp->d_name.len); |
62 | temp = temp->d_parent; | 65 | temp = temp->d_parent; |
@@ -70,7 +73,6 @@ cifs_bp_rename_retry: | |||
70 | if(full_path == NULL) | 73 | if(full_path == NULL) |
71 | return full_path; | 74 | return full_path; |
72 | full_path[namelen] = 0; /* trailing null */ | 75 | full_path[namelen] = 0; /* trailing null */ |
73 | |||
74 | for (temp = direntry; !IS_ROOT(temp);) { | 76 | for (temp = direntry; !IS_ROOT(temp);) { |
75 | namelen -= 1 + temp->d_name.len; | 77 | namelen -= 1 + temp->d_name.len; |
76 | if (namelen < 0) { | 78 | if (namelen < 0) { |
@@ -79,7 +81,7 @@ cifs_bp_rename_retry: | |||
79 | full_path[namelen] = dirsep; | 81 | full_path[namelen] = dirsep; |
80 | strncpy(full_path + namelen + 1, temp->d_name.name, | 82 | strncpy(full_path + namelen + 1, temp->d_name.name, |
81 | temp->d_name.len); | 83 | temp->d_name.len); |
82 | cFYI(0, (" name: %s ", full_path + namelen)); | 84 | cFYI(0, ("name: %s", full_path + namelen)); |
83 | } | 85 | } |
84 | temp = temp->d_parent; | 86 | temp = temp->d_parent; |
85 | if(temp == NULL) { | 87 | if(temp == NULL) { |
@@ -88,18 +90,23 @@ cifs_bp_rename_retry: | |||
88 | return NULL; | 90 | return NULL; |
89 | } | 91 | } |
90 | } | 92 | } |
91 | if (namelen != 0) { | 93 | if (namelen != pplen) { |
92 | cERROR(1, | 94 | cERROR(1, |
93 | ("We did not end path lookup where we expected namelen is %d", | 95 | ("did not end path lookup where expected namelen is %d", |
94 | namelen)); | 96 | namelen)); |
95 | /* presumably this is only possible if we were racing with a rename | 97 | /* presumably this is only possible if racing with a rename |
96 | of one of the parent directories (we can not lock the dentries | 98 | of one of the parent directories (we can not lock the dentries |
97 | above us to prevent this, but retrying should be harmless) */ | 99 | above us to prevent this, but retrying should be harmless) */ |
98 | kfree(full_path); | 100 | kfree(full_path); |
99 | namelen = 0; | ||
100 | goto cifs_bp_rename_retry; | 101 | goto cifs_bp_rename_retry; |
101 | } | 102 | } |
102 | 103 | /* DIR_SEP already set for byte 0 / vs \ but not for | |
104 | subsequent slashes in prepath which currently must | ||
105 | be entered the right way - not sure if there is an alternative | ||
106 | since the '\' is a valid posix character so we can not switch | ||
107 | those safely to '/' if any are found in the middle of the prepath */ | ||
108 | /* BB test paths to Windows with '/' in the midst of prepath */ | ||
109 | strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen); | ||
103 | return full_path; | 110 | return full_path; |
104 | } | 111 | } |
105 | 112 | ||
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e9c5ba9084fc..ddb012a68023 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -752,6 +752,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
752 | int stored_rc = 0; | 752 | int stored_rc = 0; |
753 | struct cifsLockInfo *li, *tmp; | 753 | struct cifsLockInfo *li, *tmp; |
754 | 754 | ||
755 | rc = 0; | ||
755 | down(&fid->lock_sem); | 756 | down(&fid->lock_sem); |
756 | list_for_each_entry_safe(li, tmp, &fid->llist, llist) { | 757 | list_for_each_entry_safe(li, tmp, &fid->llist, llist) { |
757 | if (pfLock->fl_start <= li->offset && | 758 | if (pfLock->fl_start <= li->offset && |
@@ -766,7 +767,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
766 | kfree(li); | 767 | kfree(li); |
767 | } | 768 | } |
768 | } | 769 | } |
769 | up(&fid->lock_sem); | 770 | up(&fid->lock_sem); |
770 | } | 771 | } |
771 | } | 772 | } |
772 | 773 | ||
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 067648b7179b..18fcec190f8b 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -269,7 +269,7 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, | |||
269 | rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, | 269 | rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, |
270 | ea_value, buf_size, | 270 | ea_value, buf_size, |
271 | ACL_TYPE_ACCESS); | 271 | ACL_TYPE_ACCESS); |
272 | CIFSSMBClose(xid, pTcon, fid) | 272 | CIFSSMBClose(xid, pTcon, fid); |
273 | } | 273 | } |
274 | } */ /* BB enable after fixing up return data */ | 274 | } */ /* BB enable after fixing up return data */ |
275 | 275 | ||
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index df025453dd97..816e8ef64560 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -86,6 +86,32 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * pare | |||
86 | return sd; | 86 | return sd; |
87 | } | 87 | } |
88 | 88 | ||
89 | /* | ||
90 | * | ||
91 | * Return -EEXIST if there is already a configfs element with the same | ||
92 | * name for the same parent. | ||
93 | * | ||
94 | * called with parent inode's i_mutex held | ||
95 | */ | ||
96 | int configfs_dirent_exists(struct configfs_dirent *parent_sd, | ||
97 | const unsigned char *new) | ||
98 | { | ||
99 | struct configfs_dirent * sd; | ||
100 | |||
101 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | ||
102 | if (sd->s_element) { | ||
103 | const unsigned char *existing = configfs_get_name(sd); | ||
104 | if (strcmp(existing, new)) | ||
105 | continue; | ||
106 | else | ||
107 | return -EEXIST; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | |||
89 | int configfs_make_dirent(struct configfs_dirent * parent_sd, | 115 | int configfs_make_dirent(struct configfs_dirent * parent_sd, |
90 | struct dentry * dentry, void * element, | 116 | struct dentry * dentry, void * element, |
91 | umode_t mode, int type) | 117 | umode_t mode, int type) |
@@ -136,8 +162,10 @@ static int create_dir(struct config_item * k, struct dentry * p, | |||
136 | int error; | 162 | int error; |
137 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; | 163 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; |
138 | 164 | ||
139 | error = configfs_make_dirent(p->d_fsdata, d, k, mode, | 165 | error = configfs_dirent_exists(p->d_fsdata, d->d_name.name); |
140 | CONFIGFS_DIR); | 166 | if (!error) |
167 | error = configfs_make_dirent(p->d_fsdata, d, k, mode, | ||
168 | CONFIGFS_DIR); | ||
141 | if (!error) { | 169 | if (!error) { |
142 | error = configfs_create(d, mode, init_dir); | 170 | error = configfs_create(d, mode, init_dir); |
143 | if (!error) { | 171 | if (!error) { |
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index d4870432ecfc..b1981d0e95ad 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c | |||
@@ -539,7 +539,6 @@ unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars) | |||
539 | 539 | ||
540 | #endif /* EXT2FS_DEBUG */ | 540 | #endif /* EXT2FS_DEBUG */ |
541 | 541 | ||
542 | /* Superblock must be locked */ | ||
543 | unsigned long ext2_count_free_blocks (struct super_block * sb) | 542 | unsigned long ext2_count_free_blocks (struct super_block * sb) |
544 | { | 543 | { |
545 | struct ext2_group_desc * desc; | 544 | struct ext2_group_desc * desc; |
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index de85c61c58c5..695f69ccf908 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c | |||
@@ -637,7 +637,6 @@ fail: | |||
637 | return ERR_PTR(err); | 637 | return ERR_PTR(err); |
638 | } | 638 | } |
639 | 639 | ||
640 | /* Superblock must be locked */ | ||
641 | unsigned long ext2_count_free_inodes (struct super_block * sb) | 640 | unsigned long ext2_count_free_inodes (struct super_block * sb) |
642 | { | 641 | { |
643 | struct ext2_group_desc *desc; | 642 | struct ext2_group_desc *desc; |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index ca5bfb6914d2..4286ff6330b6 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -1083,7 +1083,6 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf) | |||
1083 | unsigned long overhead; | 1083 | unsigned long overhead; |
1084 | int i; | 1084 | int i; |
1085 | 1085 | ||
1086 | lock_super(sb); | ||
1087 | if (test_opt (sb, MINIX_DF)) | 1086 | if (test_opt (sb, MINIX_DF)) |
1088 | overhead = 0; | 1087 | overhead = 0; |
1089 | else { | 1088 | else { |
@@ -1124,7 +1123,6 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf) | |||
1124 | buf->f_files = le32_to_cpu(sbi->s_es->s_inodes_count); | 1123 | buf->f_files = le32_to_cpu(sbi->s_es->s_inodes_count); |
1125 | buf->f_ffree = ext2_count_free_inodes (sb); | 1124 | buf->f_ffree = ext2_count_free_inodes (sb); |
1126 | buf->f_namelen = EXT2_NAME_LEN; | 1125 | buf->f_namelen = EXT2_NAME_LEN; |
1127 | unlock_super(sb); | ||
1128 | return 0; | 1126 | return 0; |
1129 | } | 1127 | } |
1130 | 1128 | ||
diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h index 2e0cc8e00b85..3a566077ac95 100644 --- a/fs/jffs2/jffs2_fs_i.h +++ b/fs/jffs2/jffs2_fs_i.h | |||
@@ -41,11 +41,7 @@ struct jffs2_inode_info { | |||
41 | 41 | ||
42 | uint16_t flags; | 42 | uint16_t flags; |
43 | uint8_t usercompr; | 43 | uint8_t usercompr; |
44 | #if !defined (__ECOS) | ||
45 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2) | ||
46 | struct inode vfs_inode; | 44 | struct inode vfs_inode; |
47 | #endif | ||
48 | #endif | ||
49 | #ifdef CONFIG_JFFS2_FS_POSIX_ACL | 45 | #ifdef CONFIG_JFFS2_FS_POSIX_ACL |
50 | struct posix_acl *i_acl_access; | 46 | struct posix_acl *i_acl_access; |
51 | struct posix_acl *i_acl_default; | 47 | struct posix_acl *i_acl_default; |
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 7675b33396c7..5a6b4d64206c 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c | |||
@@ -21,6 +21,9 @@ | |||
21 | #include <linux/pagemap.h> | 21 | #include <linux/pagemap.h> |
22 | #include "nodelist.h" | 22 | #include "nodelist.h" |
23 | 23 | ||
24 | static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, | ||
25 | struct jffs2_node_frag *this); | ||
26 | |||
24 | void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) | 27 | void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) |
25 | { | 28 | { |
26 | struct jffs2_full_dirent **prev = list; | 29 | struct jffs2_full_dirent **prev = list; |
@@ -87,7 +90,8 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint | |||
87 | } | 90 | } |
88 | } | 91 | } |
89 | 92 | ||
90 | void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this) | 93 | static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, |
94 | struct jffs2_node_frag *this) | ||
91 | { | 95 | { |
92 | if (this->node) { | 96 | if (this->node) { |
93 | this->node->frags--; | 97 | this->node->frags--; |
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index cae92c14116d..0ddfd70307fb 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h | |||
@@ -334,7 +334,6 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c_delete); | |||
334 | struct rb_node *rb_next(struct rb_node *); | 334 | struct rb_node *rb_next(struct rb_node *); |
335 | struct rb_node *rb_prev(struct rb_node *); | 335 | struct rb_node *rb_prev(struct rb_node *); |
336 | void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); | 336 | void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); |
337 | void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this); | ||
338 | int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); | 337 | int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); |
339 | void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); | 338 | void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); |
340 | int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); | 339 | int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); |
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 25bc1ae08648..4da09ce1d1f5 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c | |||
@@ -1215,7 +1215,6 @@ int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xatt | |||
1215 | rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); | 1215 | rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); |
1216 | if (rc) { | 1216 | if (rc) { |
1217 | JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen); | 1217 | JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen); |
1218 | rc = rc ? rc : -EBADFD; | ||
1219 | goto out; | 1218 | goto out; |
1220 | } | 1219 | } |
1221 | rc = save_xattr_datum(c, xd); | 1220 | rc = save_xattr_datum(c, xd); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 153898e1331f..b14145b7b87f 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -970,7 +970,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
970 | status = -ENOMEM; | 970 | status = -ENOMEM; |
971 | opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr); | 971 | opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr); |
972 | if (opendata == NULL) | 972 | if (opendata == NULL) |
973 | goto err_put_state_owner; | 973 | goto err_release_rwsem; |
974 | 974 | ||
975 | status = _nfs4_proc_open(opendata); | 975 | status = _nfs4_proc_open(opendata); |
976 | if (status != 0) | 976 | if (status != 0) |
@@ -989,11 +989,11 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
989 | return 0; | 989 | return 0; |
990 | err_opendata_free: | 990 | err_opendata_free: |
991 | nfs4_opendata_free(opendata); | 991 | nfs4_opendata_free(opendata); |
992 | err_release_rwsem: | ||
993 | up_read(&clp->cl_sem); | ||
992 | err_put_state_owner: | 994 | err_put_state_owner: |
993 | nfs4_put_state_owner(sp); | 995 | nfs4_put_state_owner(sp); |
994 | out_err: | 996 | out_err: |
995 | /* Note: clp->cl_sem must be released before nfs4_put_open_state()! */ | ||
996 | up_read(&clp->cl_sem); | ||
997 | *res = NULL; | 997 | *res = NULL; |
998 | return status; | 998 | return status; |
999 | } | 999 | } |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 7a9ee00e0c61..f0aff824a291 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -204,9 +204,11 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode, | |||
204 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; | 204 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; |
205 | spin_unlock(&inode->i_lock); | 205 | spin_unlock(&inode->i_lock); |
206 | 206 | ||
207 | nfs_readpage_truncate_uninitialised_page(rdata); | 207 | if (rdata->res.eof || rdata->res.count == rdata->args.count) { |
208 | if (rdata->res.eof || rdata->res.count == rdata->args.count) | ||
209 | SetPageUptodate(page); | 208 | SetPageUptodate(page); |
209 | if (rdata->res.eof && count != 0) | ||
210 | memclear_highpage_flush(page, rdata->args.pgbase, count); | ||
211 | } | ||
210 | result = 0; | 212 | result = 0; |
211 | 213 | ||
212 | io_error: | 214 | io_error: |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 8ab3cf10d792..7084ac9a6455 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -590,8 +590,8 @@ static void nfs_cancel_commit_list(struct list_head *head) | |||
590 | req = nfs_list_entry(head->next); | 590 | req = nfs_list_entry(head->next); |
591 | nfs_list_remove_request(req); | 591 | nfs_list_remove_request(req); |
592 | nfs_inode_remove_request(req); | 592 | nfs_inode_remove_request(req); |
593 | nfs_clear_page_writeback(req); | ||
594 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 593 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
594 | nfs_clear_page_writeback(req); | ||
595 | } | 595 | } |
596 | } | 596 | } |
597 | 597 | ||
@@ -1386,8 +1386,8 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) | |||
1386 | req = nfs_list_entry(head->next); | 1386 | req = nfs_list_entry(head->next); |
1387 | nfs_list_remove_request(req); | 1387 | nfs_list_remove_request(req); |
1388 | nfs_mark_request_commit(req); | 1388 | nfs_mark_request_commit(req); |
1389 | nfs_clear_page_writeback(req); | ||
1390 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 1389 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
1390 | nfs_clear_page_writeback(req); | ||
1391 | } | 1391 | } |
1392 | return -ENOMEM; | 1392 | return -ENOMEM; |
1393 | } | 1393 | } |
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 06da7506363c..e35d7e52fdeb 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -33,7 +33,7 @@ | |||
33 | * | 33 | * |
34 | */ | 34 | */ |
35 | 35 | ||
36 | 36 | #include <linux/err.h> | |
37 | #include <linux/sunrpc/svc.h> | 37 | #include <linux/sunrpc/svc.h> |
38 | #include <linux/nfsd/nfsd.h> | 38 | #include <linux/nfsd/nfsd.h> |
39 | #include <linux/nfs4.h> | 39 | #include <linux/nfs4.h> |
@@ -87,34 +87,35 @@ int | |||
87 | nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) | 87 | nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) |
88 | { | 88 | { |
89 | struct xdr_netobj cksum; | 89 | struct xdr_netobj cksum; |
90 | struct crypto_tfm *tfm; | 90 | struct hash_desc desc; |
91 | struct scatterlist sg[1]; | 91 | struct scatterlist sg[1]; |
92 | int status = nfserr_resource; | 92 | int status = nfserr_resource; |
93 | 93 | ||
94 | dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", | 94 | dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", |
95 | clname->len, clname->data); | 95 | clname->len, clname->data); |
96 | tfm = crypto_alloc_tfm("md5", CRYPTO_TFM_REQ_MAY_SLEEP); | 96 | desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; |
97 | if (tfm == NULL) | 97 | desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); |
98 | goto out; | 98 | if (IS_ERR(desc.tfm)) |
99 | cksum.len = crypto_tfm_alg_digestsize(tfm); | 99 | goto out_no_tfm; |
100 | cksum.len = crypto_hash_digestsize(desc.tfm); | ||
100 | cksum.data = kmalloc(cksum.len, GFP_KERNEL); | 101 | cksum.data = kmalloc(cksum.len, GFP_KERNEL); |
101 | if (cksum.data == NULL) | 102 | if (cksum.data == NULL) |
102 | goto out; | 103 | goto out; |
103 | crypto_digest_init(tfm); | ||
104 | 104 | ||
105 | sg[0].page = virt_to_page(clname->data); | 105 | sg[0].page = virt_to_page(clname->data); |
106 | sg[0].offset = offset_in_page(clname->data); | 106 | sg[0].offset = offset_in_page(clname->data); |
107 | sg[0].length = clname->len; | 107 | sg[0].length = clname->len; |
108 | 108 | ||
109 | crypto_digest_update(tfm, sg, 1); | 109 | if (crypto_hash_digest(&desc, sg, sg->length, cksum.data)) |
110 | crypto_digest_final(tfm, cksum.data); | 110 | goto out; |
111 | 111 | ||
112 | md5_to_hex(dname, cksum.data); | 112 | md5_to_hex(dname, cksum.data); |
113 | 113 | ||
114 | kfree(cksum.data); | 114 | kfree(cksum.data); |
115 | status = nfs_ok; | 115 | status = nfs_ok; |
116 | out: | 116 | out: |
117 | crypto_free_tfm(tfm); | 117 | crypto_free_hash(desc.tfm); |
118 | out_no_tfm: | ||
118 | return status; | 119 | return status; |
119 | } | 120 | } |
120 | 121 | ||
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile index 7d3be845a614..9fb8132f19b0 100644 --- a/fs/ocfs2/Makefile +++ b/fs/ocfs2/Makefile | |||
@@ -16,6 +16,7 @@ ocfs2-objs := \ | |||
16 | file.o \ | 16 | file.o \ |
17 | heartbeat.o \ | 17 | heartbeat.o \ |
18 | inode.o \ | 18 | inode.o \ |
19 | ioctl.o \ | ||
19 | journal.o \ | 20 | journal.o \ |
20 | localalloc.o \ | 21 | localalloc.o \ |
21 | mmap.o \ | 22 | mmap.o \ |
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index edaab05a93e0..f43bc5f18a35 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -1717,17 +1717,29 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb, | |||
1717 | 1717 | ||
1718 | ocfs2_remove_from_cache(inode, eb_bh); | 1718 | ocfs2_remove_from_cache(inode, eb_bh); |
1719 | 1719 | ||
1720 | BUG_ON(eb->h_suballoc_slot); | ||
1721 | BUG_ON(el->l_recs[0].e_clusters); | 1720 | BUG_ON(el->l_recs[0].e_clusters); |
1722 | BUG_ON(el->l_recs[0].e_cpos); | 1721 | BUG_ON(el->l_recs[0].e_cpos); |
1723 | BUG_ON(el->l_recs[0].e_blkno); | 1722 | BUG_ON(el->l_recs[0].e_blkno); |
1724 | status = ocfs2_free_extent_block(handle, | 1723 | if (eb->h_suballoc_slot == 0) { |
1725 | tc->tc_ext_alloc_inode, | 1724 | /* |
1726 | tc->tc_ext_alloc_bh, | 1725 | * This code only understands how to |
1727 | eb); | 1726 | * lock the suballocator in slot 0, |
1728 | if (status < 0) { | 1727 | * which is fine because allocation is |
1729 | mlog_errno(status); | 1728 | * only ever done out of that |
1730 | goto bail; | 1729 | * suballocator too. A future version |
1730 | * might change that however, so avoid | ||
1731 | * a free if we don't know how to | ||
1732 | * handle it. This way an fs incompat | ||
1733 | * bit will not be necessary. | ||
1734 | */ | ||
1735 | status = ocfs2_free_extent_block(handle, | ||
1736 | tc->tc_ext_alloc_inode, | ||
1737 | tc->tc_ext_alloc_bh, | ||
1738 | eb); | ||
1739 | if (status < 0) { | ||
1740 | mlog_errno(status); | ||
1741 | goto bail; | ||
1742 | } | ||
1731 | } | 1743 | } |
1732 | } | 1744 | } |
1733 | brelse(eb_bh); | 1745 | brelse(eb_bh); |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index f1d1c342ce01..3d7c082a8f58 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -391,31 +391,28 @@ out: | |||
391 | static int ocfs2_commit_write(struct file *file, struct page *page, | 391 | static int ocfs2_commit_write(struct file *file, struct page *page, |
392 | unsigned from, unsigned to) | 392 | unsigned from, unsigned to) |
393 | { | 393 | { |
394 | int ret, extending = 0, locklevel = 0; | 394 | int ret; |
395 | loff_t new_i_size; | ||
396 | struct buffer_head *di_bh = NULL; | 395 | struct buffer_head *di_bh = NULL; |
397 | struct inode *inode = page->mapping->host; | 396 | struct inode *inode = page->mapping->host; |
398 | struct ocfs2_journal_handle *handle = NULL; | 397 | struct ocfs2_journal_handle *handle = NULL; |
398 | struct ocfs2_dinode *di; | ||
399 | 399 | ||
400 | mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to); | 400 | mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to); |
401 | 401 | ||
402 | /* NOTE: ocfs2_file_aio_write has ensured that it's safe for | 402 | /* NOTE: ocfs2_file_aio_write has ensured that it's safe for |
403 | * us to sample inode->i_size here without the metadata lock: | 403 | * us to continue here without rechecking the I/O against |
404 | * changed inode values. | ||
404 | * | 405 | * |
405 | * 1) We're currently holding the inode alloc lock, so no | 406 | * 1) We're currently holding the inode alloc lock, so no |
406 | * nodes can change it underneath us. | 407 | * nodes can change it underneath us. |
407 | * | 408 | * |
408 | * 2) We've had to take the metadata lock at least once | 409 | * 2) We've had to take the metadata lock at least once |
409 | * already to check for extending writes, hence insuring | 410 | * already to check for extending writes, suid removal, etc. |
410 | * that our current copy is also up to date. | 411 | * The meta data update code then ensures that we don't get a |
412 | * stale inode allocation image (i_size, i_clusters, etc). | ||
411 | */ | 413 | */ |
412 | new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; | ||
413 | if (new_i_size > i_size_read(inode)) { | ||
414 | extending = 1; | ||
415 | locklevel = 1; | ||
416 | } | ||
417 | 414 | ||
418 | ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, locklevel, page); | 415 | ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, 1, page); |
419 | if (ret != 0) { | 416 | if (ret != 0) { |
420 | mlog_errno(ret); | 417 | mlog_errno(ret); |
421 | goto out; | 418 | goto out; |
@@ -427,23 +424,20 @@ static int ocfs2_commit_write(struct file *file, struct page *page, | |||
427 | goto out_unlock_meta; | 424 | goto out_unlock_meta; |
428 | } | 425 | } |
429 | 426 | ||
430 | if (extending) { | 427 | handle = ocfs2_start_walk_page_trans(inode, page, from, to); |
431 | handle = ocfs2_start_walk_page_trans(inode, page, from, to); | 428 | if (IS_ERR(handle)) { |
432 | if (IS_ERR(handle)) { | 429 | ret = PTR_ERR(handle); |
433 | ret = PTR_ERR(handle); | 430 | goto out_unlock_data; |
434 | handle = NULL; | 431 | } |
435 | goto out_unlock_data; | ||
436 | } | ||
437 | 432 | ||
438 | /* Mark our buffer early. We'd rather catch this error up here | 433 | /* Mark our buffer early. We'd rather catch this error up here |
439 | * as opposed to after a successful commit_write which would | 434 | * as opposed to after a successful commit_write which would |
440 | * require us to set back inode->i_size. */ | 435 | * require us to set back inode->i_size. */ |
441 | ret = ocfs2_journal_access(handle, inode, di_bh, | 436 | ret = ocfs2_journal_access(handle, inode, di_bh, |
442 | OCFS2_JOURNAL_ACCESS_WRITE); | 437 | OCFS2_JOURNAL_ACCESS_WRITE); |
443 | if (ret < 0) { | 438 | if (ret < 0) { |
444 | mlog_errno(ret); | 439 | mlog_errno(ret); |
445 | goto out_commit; | 440 | goto out_commit; |
446 | } | ||
447 | } | 441 | } |
448 | 442 | ||
449 | /* might update i_size */ | 443 | /* might update i_size */ |
@@ -453,37 +447,28 @@ static int ocfs2_commit_write(struct file *file, struct page *page, | |||
453 | goto out_commit; | 447 | goto out_commit; |
454 | } | 448 | } |
455 | 449 | ||
456 | if (extending) { | 450 | di = (struct ocfs2_dinode *)di_bh->b_data; |
457 | loff_t size = (u64) i_size_read(inode); | ||
458 | struct ocfs2_dinode *di = | ||
459 | (struct ocfs2_dinode *)di_bh->b_data; | ||
460 | 451 | ||
461 | /* ocfs2_mark_inode_dirty is too heavy to use here. */ | 452 | /* ocfs2_mark_inode_dirty() is too heavy to use here. */ |
462 | inode->i_blocks = ocfs2_align_bytes_to_sectors(size); | 453 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
463 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; | 454 | di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec); |
455 | di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); | ||
464 | 456 | ||
465 | di->i_size = cpu_to_le64(size); | 457 | inode->i_blocks = ocfs2_align_bytes_to_sectors((u64)(i_size_read(inode))); |
466 | di->i_ctime = di->i_mtime = | 458 | di->i_size = cpu_to_le64((u64)i_size_read(inode)); |
467 | cpu_to_le64(inode->i_mtime.tv_sec); | ||
468 | di->i_ctime_nsec = di->i_mtime_nsec = | ||
469 | cpu_to_le32(inode->i_mtime.tv_nsec); | ||
470 | 459 | ||
471 | ret = ocfs2_journal_dirty(handle, di_bh); | 460 | ret = ocfs2_journal_dirty(handle, di_bh); |
472 | if (ret < 0) { | 461 | if (ret < 0) { |
473 | mlog_errno(ret); | 462 | mlog_errno(ret); |
474 | goto out_commit; | 463 | goto out_commit; |
475 | } | ||
476 | } | 464 | } |
477 | 465 | ||
478 | BUG_ON(extending && (i_size_read(inode) != new_i_size)); | ||
479 | |||
480 | out_commit: | 466 | out_commit: |
481 | if (handle) | 467 | ocfs2_commit_trans(handle); |
482 | ocfs2_commit_trans(handle); | ||
483 | out_unlock_data: | 468 | out_unlock_data: |
484 | ocfs2_data_unlock(inode, 1); | 469 | ocfs2_data_unlock(inode, 1); |
485 | out_unlock_meta: | 470 | out_unlock_meta: |
486 | ocfs2_meta_unlock(inode, locklevel); | 471 | ocfs2_meta_unlock(inode, 1); |
487 | out: | 472 | out: |
488 | if (di_bh) | 473 | if (di_bh) |
489 | brelse(di_bh); | 474 | brelse(di_bh); |
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index 9a24adf9be6e..c9037414f4f6 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c | |||
@@ -100,6 +100,9 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
100 | mlog_entry("(block=(%llu), nr=(%d), flags=%d, inode=%p)\n", | 100 | mlog_entry("(block=(%llu), nr=(%d), flags=%d, inode=%p)\n", |
101 | (unsigned long long)block, nr, flags, inode); | 101 | (unsigned long long)block, nr, flags, inode); |
102 | 102 | ||
103 | BUG_ON((flags & OCFS2_BH_READAHEAD) && | ||
104 | (!inode || !(flags & OCFS2_BH_CACHED))); | ||
105 | |||
103 | if (osb == NULL || osb->sb == NULL || bhs == NULL) { | 106 | if (osb == NULL || osb->sb == NULL || bhs == NULL) { |
104 | status = -EINVAL; | 107 | status = -EINVAL; |
105 | mlog_errno(status); | 108 | mlog_errno(status); |
@@ -140,6 +143,30 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
140 | bh = bhs[i]; | 143 | bh = bhs[i]; |
141 | ignore_cache = 0; | 144 | ignore_cache = 0; |
142 | 145 | ||
146 | /* There are three read-ahead cases here which we need to | ||
147 | * be concerned with. All three assume a buffer has | ||
148 | * previously been submitted with OCFS2_BH_READAHEAD | ||
149 | * and it hasn't yet completed I/O. | ||
150 | * | ||
151 | * 1) The current request is sync to disk. This rarely | ||
152 | * happens these days, and never when performance | ||
153 | * matters - the code can just wait on the buffer | ||
154 | * lock and re-submit. | ||
155 | * | ||
156 | * 2) The current request is cached, but not | ||
157 | * readahead. ocfs2_buffer_uptodate() will return | ||
158 | * false anyway, so we'll wind up waiting on the | ||
159 | * buffer lock to do I/O. We re-check the request | ||
160 | * with after getting the lock to avoid a re-submit. | ||
161 | * | ||
162 | * 3) The current request is readahead (and so must | ||
163 | * also be a caching one). We short circuit if the | ||
164 | * buffer is locked (under I/O) and if it's in the | ||
165 | * uptodate cache. The re-check from #2 catches the | ||
166 | * case that the previous read-ahead completes just | ||
167 | * before our is-it-in-flight check. | ||
168 | */ | ||
169 | |||
143 | if (flags & OCFS2_BH_CACHED && | 170 | if (flags & OCFS2_BH_CACHED && |
144 | !ocfs2_buffer_uptodate(inode, bh)) { | 171 | !ocfs2_buffer_uptodate(inode, bh)) { |
145 | mlog(ML_UPTODATE, | 172 | mlog(ML_UPTODATE, |
@@ -169,6 +196,14 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
169 | continue; | 196 | continue; |
170 | } | 197 | } |
171 | 198 | ||
199 | /* A read-ahead request was made - if the | ||
200 | * buffer is already under read-ahead from a | ||
201 | * previously submitted request than we are | ||
202 | * done here. */ | ||
203 | if ((flags & OCFS2_BH_READAHEAD) | ||
204 | && ocfs2_buffer_read_ahead(inode, bh)) | ||
205 | continue; | ||
206 | |||
172 | lock_buffer(bh); | 207 | lock_buffer(bh); |
173 | if (buffer_jbd(bh)) { | 208 | if (buffer_jbd(bh)) { |
174 | #ifdef CATCH_BH_JBD_RACES | 209 | #ifdef CATCH_BH_JBD_RACES |
@@ -181,13 +216,22 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
181 | continue; | 216 | continue; |
182 | #endif | 217 | #endif |
183 | } | 218 | } |
219 | |||
220 | /* Re-check ocfs2_buffer_uptodate() as a | ||
221 | * previously read-ahead buffer may have | ||
222 | * completed I/O while we were waiting for the | ||
223 | * buffer lock. */ | ||
224 | if ((flags & OCFS2_BH_CACHED) | ||
225 | && !(flags & OCFS2_BH_READAHEAD) | ||
226 | && ocfs2_buffer_uptodate(inode, bh)) { | ||
227 | unlock_buffer(bh); | ||
228 | continue; | ||
229 | } | ||
230 | |||
184 | clear_buffer_uptodate(bh); | 231 | clear_buffer_uptodate(bh); |
185 | get_bh(bh); /* for end_buffer_read_sync() */ | 232 | get_bh(bh); /* for end_buffer_read_sync() */ |
186 | bh->b_end_io = end_buffer_read_sync; | 233 | bh->b_end_io = end_buffer_read_sync; |
187 | if (flags & OCFS2_BH_READAHEAD) | 234 | submit_bh(READ, bh); |
188 | submit_bh(READA, bh); | ||
189 | else | ||
190 | submit_bh(READ, bh); | ||
191 | continue; | 235 | continue; |
192 | } | 236 | } |
193 | } | 237 | } |
@@ -197,34 +241,39 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
197 | for (i = (nr - 1); i >= 0; i--) { | 241 | for (i = (nr - 1); i >= 0; i--) { |
198 | bh = bhs[i]; | 242 | bh = bhs[i]; |
199 | 243 | ||
200 | /* We know this can't have changed as we hold the | 244 | if (!(flags & OCFS2_BH_READAHEAD)) { |
201 | * inode sem. Avoid doing any work on the bh if the | 245 | /* We know this can't have changed as we hold the |
202 | * journal has it. */ | 246 | * inode sem. Avoid doing any work on the bh if the |
203 | if (!buffer_jbd(bh)) | 247 | * journal has it. */ |
204 | wait_on_buffer(bh); | 248 | if (!buffer_jbd(bh)) |
205 | 249 | wait_on_buffer(bh); | |
206 | if (!buffer_uptodate(bh)) { | 250 | |
207 | /* Status won't be cleared from here on out, | 251 | if (!buffer_uptodate(bh)) { |
208 | * so we can safely record this and loop back | 252 | /* Status won't be cleared from here on out, |
209 | * to cleanup the other buffers. Don't need to | 253 | * so we can safely record this and loop back |
210 | * remove the clustered uptodate information | 254 | * to cleanup the other buffers. Don't need to |
211 | * for this bh as it's not marked locally | 255 | * remove the clustered uptodate information |
212 | * uptodate. */ | 256 | * for this bh as it's not marked locally |
213 | status = -EIO; | 257 | * uptodate. */ |
214 | brelse(bh); | 258 | status = -EIO; |
215 | bhs[i] = NULL; | 259 | brelse(bh); |
216 | continue; | 260 | bhs[i] = NULL; |
261 | continue; | ||
262 | } | ||
217 | } | 263 | } |
218 | 264 | ||
265 | /* Always set the buffer in the cache, even if it was | ||
266 | * a forced read, or read-ahead which hasn't yet | ||
267 | * completed. */ | ||
219 | if (inode) | 268 | if (inode) |
220 | ocfs2_set_buffer_uptodate(inode, bh); | 269 | ocfs2_set_buffer_uptodate(inode, bh); |
221 | } | 270 | } |
222 | if (inode) | 271 | if (inode) |
223 | mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); | 272 | mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); |
224 | 273 | ||
225 | mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s\n", | 274 | mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n", |
226 | (unsigned long long)block, nr, | 275 | (unsigned long long)block, nr, |
227 | (!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes"); | 276 | (!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes", flags); |
228 | 277 | ||
229 | bail: | 278 | bail: |
230 | 279 | ||
diff --git a/fs/ocfs2/buffer_head_io.h b/fs/ocfs2/buffer_head_io.h index 6ecb90937b68..6cc20930fac3 100644 --- a/fs/ocfs2/buffer_head_io.h +++ b/fs/ocfs2/buffer_head_io.h | |||
@@ -49,7 +49,7 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, | |||
49 | 49 | ||
50 | 50 | ||
51 | #define OCFS2_BH_CACHED 1 | 51 | #define OCFS2_BH_CACHED 1 |
52 | #define OCFS2_BH_READAHEAD 8 /* use this to pass READA down to submit_bh */ | 52 | #define OCFS2_BH_READAHEAD 8 |
53 | 53 | ||
54 | static inline int ocfs2_read_block(struct ocfs2_super * osb, u64 off, | 54 | static inline int ocfs2_read_block(struct ocfs2_super * osb, u64 off, |
55 | struct buffer_head **bh, int flags, | 55 | struct buffer_head **bh, int flags, |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 504595d6cf65..305cba3681fe 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
@@ -320,8 +320,12 @@ static int compute_max_sectors(struct block_device *bdev) | |||
320 | max_pages = q->max_hw_segments; | 320 | max_pages = q->max_hw_segments; |
321 | max_pages--; /* Handle I/Os that straddle a page */ | 321 | max_pages--; /* Handle I/Os that straddle a page */ |
322 | 322 | ||
323 | max_sectors = max_pages << (PAGE_SHIFT - 9); | 323 | if (max_pages) { |
324 | 324 | max_sectors = max_pages << (PAGE_SHIFT - 9); | |
325 | } else { | ||
326 | /* If BIO contains 1 or less than 1 page. */ | ||
327 | max_sectors = q->max_sectors; | ||
328 | } | ||
325 | /* Why is fls() 1-based???? */ | 329 | /* Why is fls() 1-based???? */ |
326 | pow_two_sectors = 1 << (fls(max_sectors) - 1); | 330 | pow_two_sectors = 1 << (fls(max_sectors) - 1); |
327 | 331 | ||
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 3d494d1a5f36..04e01915b86e 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -74,14 +74,14 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
74 | int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | 74 | int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) |
75 | { | 75 | { |
76 | int error = 0; | 76 | int error = 0; |
77 | unsigned long offset, blk; | 77 | unsigned long offset, blk, last_ra_blk = 0; |
78 | int i, num, stored; | 78 | int i, stored; |
79 | struct buffer_head * bh, * tmp; | 79 | struct buffer_head * bh, * tmp; |
80 | struct ocfs2_dir_entry * de; | 80 | struct ocfs2_dir_entry * de; |
81 | int err; | 81 | int err; |
82 | struct inode *inode = filp->f_dentry->d_inode; | 82 | struct inode *inode = filp->f_dentry->d_inode; |
83 | struct super_block * sb = inode->i_sb; | 83 | struct super_block * sb = inode->i_sb; |
84 | int have_disk_lock = 0; | 84 | unsigned int ra_sectors = 16; |
85 | 85 | ||
86 | mlog_entry("dirino=%llu\n", | 86 | mlog_entry("dirino=%llu\n", |
87 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 87 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
@@ -95,9 +95,8 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
95 | mlog_errno(error); | 95 | mlog_errno(error); |
96 | /* we haven't got any yet, so propagate the error. */ | 96 | /* we haven't got any yet, so propagate the error. */ |
97 | stored = error; | 97 | stored = error; |
98 | goto bail; | 98 | goto bail_nolock; |
99 | } | 99 | } |
100 | have_disk_lock = 1; | ||
101 | 100 | ||
102 | offset = filp->f_pos & (sb->s_blocksize - 1); | 101 | offset = filp->f_pos & (sb->s_blocksize - 1); |
103 | 102 | ||
@@ -113,16 +112,21 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
113 | continue; | 112 | continue; |
114 | } | 113 | } |
115 | 114 | ||
116 | /* | 115 | /* The idea here is to begin with 8k read-ahead and to stay |
117 | * Do the readahead (8k) | 116 | * 4k ahead of our current position. |
118 | */ | 117 | * |
119 | if (!offset) { | 118 | * TODO: Use the pagecache for this. We just need to |
120 | for (i = 16 >> (sb->s_blocksize_bits - 9), num = 0; | 119 | * make sure it's cluster-safe... */ |
120 | if (!last_ra_blk | ||
121 | || (((last_ra_blk - blk) << 9) <= (ra_sectors / 2))) { | ||
122 | for (i = ra_sectors >> (sb->s_blocksize_bits - 9); | ||
121 | i > 0; i--) { | 123 | i > 0; i--) { |
122 | tmp = ocfs2_bread(inode, ++blk, &err, 1); | 124 | tmp = ocfs2_bread(inode, ++blk, &err, 1); |
123 | if (tmp) | 125 | if (tmp) |
124 | brelse(tmp); | 126 | brelse(tmp); |
125 | } | 127 | } |
128 | last_ra_blk = blk; | ||
129 | ra_sectors = 8; | ||
126 | } | 130 | } |
127 | 131 | ||
128 | revalidate: | 132 | revalidate: |
@@ -194,9 +198,9 @@ revalidate: | |||
194 | 198 | ||
195 | stored = 0; | 199 | stored = 0; |
196 | bail: | 200 | bail: |
197 | if (have_disk_lock) | 201 | ocfs2_meta_unlock(inode, 0); |
198 | ocfs2_meta_unlock(inode, 0); | ||
199 | 202 | ||
203 | bail_nolock: | ||
200 | mlog_exit(stored); | 204 | mlog_exit(stored); |
201 | 205 | ||
202 | return stored; | 206 | return stored; |
diff --git a/fs/ocfs2/dlm/dlmast.c b/fs/ocfs2/dlm/dlmast.c index 42775e2bbe2c..f13a4bac41f0 100644 --- a/fs/ocfs2/dlm/dlmast.c +++ b/fs/ocfs2/dlm/dlmast.c | |||
@@ -367,12 +367,10 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data) | |||
367 | goto do_ast; | 367 | goto do_ast; |
368 | } | 368 | } |
369 | 369 | ||
370 | mlog(ML_ERROR, "got %sast for unknown lock! cookie=%u:%llu, " | 370 | mlog(0, "got %sast for unknown lock! cookie=%u:%llu, " |
371 | "name=%.*s, namelen=%u\n", | 371 | "name=%.*s, namelen=%u\n", past->type == DLM_AST ? "" : "b", |
372 | past->type == DLM_AST ? "" : "b", | 372 | dlm_get_lock_cookie_node(cookie), dlm_get_lock_cookie_seq(cookie), |
373 | dlm_get_lock_cookie_node(cookie), | 373 | locklen, name, locklen); |
374 | dlm_get_lock_cookie_seq(cookie), | ||
375 | locklen, name, locklen); | ||
376 | 374 | ||
377 | ret = DLM_NORMAL; | 375 | ret = DLM_NORMAL; |
378 | unlock_out: | 376 | unlock_out: |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 762eb1fbb34d..151b41781eab 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -1330,6 +1330,7 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) | |||
1330 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime)); | 1330 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime)); |
1331 | lvb->lvb_imtime_packed = | 1331 | lvb->lvb_imtime_packed = |
1332 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime)); | 1332 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime)); |
1333 | lvb->lvb_iattr = cpu_to_be32(oi->ip_attr); | ||
1333 | 1334 | ||
1334 | mlog_meta_lvb(0, lockres); | 1335 | mlog_meta_lvb(0, lockres); |
1335 | 1336 | ||
@@ -1360,6 +1361,9 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode) | |||
1360 | oi->ip_clusters = be32_to_cpu(lvb->lvb_iclusters); | 1361 | oi->ip_clusters = be32_to_cpu(lvb->lvb_iclusters); |
1361 | i_size_write(inode, be64_to_cpu(lvb->lvb_isize)); | 1362 | i_size_write(inode, be64_to_cpu(lvb->lvb_isize)); |
1362 | 1363 | ||
1364 | oi->ip_attr = be32_to_cpu(lvb->lvb_iattr); | ||
1365 | ocfs2_set_inode_flags(inode); | ||
1366 | |||
1363 | /* fast-symlinks are a special case */ | 1367 | /* fast-symlinks are a special case */ |
1364 | if (S_ISLNK(inode->i_mode) && !oi->ip_clusters) | 1368 | if (S_ISLNK(inode->i_mode) && !oi->ip_clusters) |
1365 | inode->i_blocks = 0; | 1369 | inode->i_blocks = 0; |
@@ -2899,8 +2903,9 @@ void ocfs2_dump_meta_lvb_info(u64 level, | |||
2899 | be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid), | 2903 | be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid), |
2900 | be16_to_cpu(lvb->lvb_imode)); | 2904 | be16_to_cpu(lvb->lvb_imode)); |
2901 | mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, " | 2905 | mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, " |
2902 | "mtime_packed 0x%llx\n", be16_to_cpu(lvb->lvb_inlink), | 2906 | "mtime_packed 0x%llx iattr 0x%x\n", be16_to_cpu(lvb->lvb_inlink), |
2903 | (long long)be64_to_cpu(lvb->lvb_iatime_packed), | 2907 | (long long)be64_to_cpu(lvb->lvb_iatime_packed), |
2904 | (long long)be64_to_cpu(lvb->lvb_ictime_packed), | 2908 | (long long)be64_to_cpu(lvb->lvb_ictime_packed), |
2905 | (long long)be64_to_cpu(lvb->lvb_imtime_packed)); | 2909 | (long long)be64_to_cpu(lvb->lvb_imtime_packed), |
2910 | be32_to_cpu(lvb->lvb_iattr)); | ||
2906 | } | 2911 | } |
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h index 8f2d1db2d9ea..243ae862ece5 100644 --- a/fs/ocfs2/dlmglue.h +++ b/fs/ocfs2/dlmglue.h | |||
@@ -27,7 +27,7 @@ | |||
27 | #ifndef DLMGLUE_H | 27 | #ifndef DLMGLUE_H |
28 | #define DLMGLUE_H | 28 | #define DLMGLUE_H |
29 | 29 | ||
30 | #define OCFS2_LVB_VERSION 2 | 30 | #define OCFS2_LVB_VERSION 3 |
31 | 31 | ||
32 | struct ocfs2_meta_lvb { | 32 | struct ocfs2_meta_lvb { |
33 | __be32 lvb_version; | 33 | __be32 lvb_version; |
@@ -40,7 +40,8 @@ struct ocfs2_meta_lvb { | |||
40 | __be64 lvb_isize; | 40 | __be64 lvb_isize; |
41 | __be16 lvb_imode; | 41 | __be16 lvb_imode; |
42 | __be16 lvb_inlink; | 42 | __be16 lvb_inlink; |
43 | __be32 lvb_reserved[3]; | 43 | __be32 lvb_iattr; |
44 | __be32 lvb_reserved[2]; | ||
44 | }; | 45 | }; |
45 | 46 | ||
46 | /* ocfs2_meta_lock_full() and ocfs2_data_lock_full() 'arg_flags' flags */ | 47 | /* ocfs2_meta_lock_full() and ocfs2_data_lock_full() 'arg_flags' flags */ |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index a9559c874530..2bbfa17090cf 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include "file.h" | 44 | #include "file.h" |
45 | #include "sysfile.h" | 45 | #include "sysfile.h" |
46 | #include "inode.h" | 46 | #include "inode.h" |
47 | #include "ioctl.h" | ||
47 | #include "journal.h" | 48 | #include "journal.h" |
48 | #include "mmap.h" | 49 | #include "mmap.h" |
49 | #include "suballoc.h" | 50 | #include "suballoc.h" |
@@ -1227,10 +1228,12 @@ const struct file_operations ocfs2_fops = { | |||
1227 | .open = ocfs2_file_open, | 1228 | .open = ocfs2_file_open, |
1228 | .aio_read = ocfs2_file_aio_read, | 1229 | .aio_read = ocfs2_file_aio_read, |
1229 | .aio_write = ocfs2_file_aio_write, | 1230 | .aio_write = ocfs2_file_aio_write, |
1231 | .ioctl = ocfs2_ioctl, | ||
1230 | }; | 1232 | }; |
1231 | 1233 | ||
1232 | const struct file_operations ocfs2_dops = { | 1234 | const struct file_operations ocfs2_dops = { |
1233 | .read = generic_read_dir, | 1235 | .read = generic_read_dir, |
1234 | .readdir = ocfs2_readdir, | 1236 | .readdir = ocfs2_readdir, |
1235 | .fsync = ocfs2_sync_file, | 1237 | .fsync = ocfs2_sync_file, |
1238 | .ioctl = ocfs2_ioctl, | ||
1236 | }; | 1239 | }; |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 327a5b7b86ed..7bcf69154592 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -71,6 +71,26 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, | |||
71 | struct inode *inode, | 71 | struct inode *inode, |
72 | struct buffer_head *fe_bh); | 72 | struct buffer_head *fe_bh); |
73 | 73 | ||
74 | void ocfs2_set_inode_flags(struct inode *inode) | ||
75 | { | ||
76 | unsigned int flags = OCFS2_I(inode)->ip_attr; | ||
77 | |||
78 | inode->i_flags &= ~(S_IMMUTABLE | | ||
79 | S_SYNC | S_APPEND | S_NOATIME | S_DIRSYNC); | ||
80 | |||
81 | if (flags & OCFS2_IMMUTABLE_FL) | ||
82 | inode->i_flags |= S_IMMUTABLE; | ||
83 | |||
84 | if (flags & OCFS2_SYNC_FL) | ||
85 | inode->i_flags |= S_SYNC; | ||
86 | if (flags & OCFS2_APPEND_FL) | ||
87 | inode->i_flags |= S_APPEND; | ||
88 | if (flags & OCFS2_NOATIME_FL) | ||
89 | inode->i_flags |= S_NOATIME; | ||
90 | if (flags & OCFS2_DIRSYNC_FL) | ||
91 | inode->i_flags |= S_DIRSYNC; | ||
92 | } | ||
93 | |||
74 | struct inode *ocfs2_ilookup_for_vote(struct ocfs2_super *osb, | 94 | struct inode *ocfs2_ilookup_for_vote(struct ocfs2_super *osb, |
75 | u64 blkno, | 95 | u64 blkno, |
76 | int delete_vote) | 96 | int delete_vote) |
@@ -260,7 +280,6 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
260 | inode->i_blocks = | 280 | inode->i_blocks = |
261 | ocfs2_align_bytes_to_sectors(le64_to_cpu(fe->i_size)); | 281 | ocfs2_align_bytes_to_sectors(le64_to_cpu(fe->i_size)); |
262 | inode->i_mapping->a_ops = &ocfs2_aops; | 282 | inode->i_mapping->a_ops = &ocfs2_aops; |
263 | inode->i_flags |= S_NOATIME; | ||
264 | inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime); | 283 | inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime); |
265 | inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec); | 284 | inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec); |
266 | inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime); | 285 | inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime); |
@@ -276,6 +295,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
276 | 295 | ||
277 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); | 296 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); |
278 | OCFS2_I(inode)->ip_orphaned_slot = OCFS2_INVALID_SLOT; | 297 | OCFS2_I(inode)->ip_orphaned_slot = OCFS2_INVALID_SLOT; |
298 | OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); | ||
279 | 299 | ||
280 | if (create_ino) | 300 | if (create_ino) |
281 | inode->i_ino = ino_from_blkno(inode->i_sb, | 301 | inode->i_ino = ino_from_blkno(inode->i_sb, |
@@ -330,6 +350,9 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
330 | ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_data_lockres, | 350 | ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_data_lockres, |
331 | OCFS2_LOCK_TYPE_DATA, inode); | 351 | OCFS2_LOCK_TYPE_DATA, inode); |
332 | 352 | ||
353 | ocfs2_set_inode_flags(inode); | ||
354 | inode->i_flags |= S_NOATIME; | ||
355 | |||
333 | status = 0; | 356 | status = 0; |
334 | bail: | 357 | bail: |
335 | mlog_exit(status); | 358 | mlog_exit(status); |
@@ -1027,12 +1050,8 @@ struct buffer_head *ocfs2_bread(struct inode *inode, | |||
1027 | u64 p_blkno; | 1050 | u64 p_blkno; |
1028 | int readflags = OCFS2_BH_CACHED; | 1051 | int readflags = OCFS2_BH_CACHED; |
1029 | 1052 | ||
1030 | #if 0 | ||
1031 | /* only turn this on if we know we can deal with read_block | ||
1032 | * returning nothing */ | ||
1033 | if (reada) | 1053 | if (reada) |
1034 | readflags |= OCFS2_BH_READAHEAD; | 1054 | readflags |= OCFS2_BH_READAHEAD; |
1035 | #endif | ||
1036 | 1055 | ||
1037 | if (((u64)block << inode->i_sb->s_blocksize_bits) >= | 1056 | if (((u64)block << inode->i_sb->s_blocksize_bits) >= |
1038 | i_size_read(inode)) { | 1057 | i_size_read(inode)) { |
@@ -1131,6 +1150,7 @@ int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle, | |||
1131 | 1150 | ||
1132 | spin_lock(&OCFS2_I(inode)->ip_lock); | 1151 | spin_lock(&OCFS2_I(inode)->ip_lock); |
1133 | fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters); | 1152 | fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters); |
1153 | fe->i_attr = cpu_to_le32(OCFS2_I(inode)->ip_attr); | ||
1134 | spin_unlock(&OCFS2_I(inode)->ip_lock); | 1154 | spin_unlock(&OCFS2_I(inode)->ip_lock); |
1135 | 1155 | ||
1136 | fe->i_size = cpu_to_le64(i_size_read(inode)); | 1156 | fe->i_size = cpu_to_le64(i_size_read(inode)); |
@@ -1169,6 +1189,8 @@ void ocfs2_refresh_inode(struct inode *inode, | |||
1169 | spin_lock(&OCFS2_I(inode)->ip_lock); | 1189 | spin_lock(&OCFS2_I(inode)->ip_lock); |
1170 | 1190 | ||
1171 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); | 1191 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); |
1192 | OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); | ||
1193 | ocfs2_set_inode_flags(inode); | ||
1172 | i_size_write(inode, le64_to_cpu(fe->i_size)); | 1194 | i_size_write(inode, le64_to_cpu(fe->i_size)); |
1173 | inode->i_nlink = le16_to_cpu(fe->i_links_count); | 1195 | inode->i_nlink = le16_to_cpu(fe->i_links_count); |
1174 | inode->i_uid = le32_to_cpu(fe->i_uid); | 1196 | inode->i_uid = le32_to_cpu(fe->i_uid); |
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index 35140f6cf840..4d1e53992566 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h | |||
@@ -56,6 +56,7 @@ struct ocfs2_inode_info | |||
56 | struct ocfs2_journal_handle *ip_handle; | 56 | struct ocfs2_journal_handle *ip_handle; |
57 | 57 | ||
58 | u32 ip_flags; /* see below */ | 58 | u32 ip_flags; /* see below */ |
59 | u32 ip_attr; /* inode attributes */ | ||
59 | 60 | ||
60 | /* protected by recovery_lock. */ | 61 | /* protected by recovery_lock. */ |
61 | struct inode *ip_next_orphan; | 62 | struct inode *ip_next_orphan; |
@@ -142,4 +143,6 @@ int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle, | |||
142 | int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb); | 143 | int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb); |
143 | int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb); | 144 | int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb); |
144 | 145 | ||
146 | void ocfs2_set_inode_flags(struct inode *inode); | ||
147 | |||
145 | #endif /* OCFS2_INODE_H */ | 148 | #endif /* OCFS2_INODE_H */ |
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c new file mode 100644 index 000000000000..3663cef80689 --- /dev/null +++ b/fs/ocfs2/ioctl.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * linux/fs/ocfs2/ioctl.c | ||
3 | * | ||
4 | * Copyright (C) 2006 Herbert Poetzl | ||
5 | * adapted from Remy Card's ext2/ioctl.c | ||
6 | */ | ||
7 | |||
8 | #include <linux/fs.h> | ||
9 | #include <linux/mount.h> | ||
10 | |||
11 | #define MLOG_MASK_PREFIX ML_INODE | ||
12 | #include <cluster/masklog.h> | ||
13 | |||
14 | #include "ocfs2.h" | ||
15 | #include "alloc.h" | ||
16 | #include "dlmglue.h" | ||
17 | #include "inode.h" | ||
18 | #include "journal.h" | ||
19 | |||
20 | #include "ocfs2_fs.h" | ||
21 | #include "ioctl.h" | ||
22 | |||
23 | #include <linux/ext2_fs.h> | ||
24 | |||
25 | static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) | ||
26 | { | ||
27 | int status; | ||
28 | |||
29 | status = ocfs2_meta_lock(inode, NULL, NULL, 0); | ||
30 | if (status < 0) { | ||
31 | mlog_errno(status); | ||
32 | return status; | ||
33 | } | ||
34 | *flags = OCFS2_I(inode)->ip_attr; | ||
35 | ocfs2_meta_unlock(inode, 0); | ||
36 | |||
37 | mlog_exit(status); | ||
38 | return status; | ||
39 | } | ||
40 | |||
41 | static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, | ||
42 | unsigned mask) | ||
43 | { | ||
44 | struct ocfs2_inode_info *ocfs2_inode = OCFS2_I(inode); | ||
45 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
46 | struct ocfs2_journal_handle *handle = NULL; | ||
47 | struct buffer_head *bh = NULL; | ||
48 | unsigned oldflags; | ||
49 | int status; | ||
50 | |||
51 | mutex_lock(&inode->i_mutex); | ||
52 | |||
53 | status = ocfs2_meta_lock(inode, NULL, &bh, 1); | ||
54 | if (status < 0) { | ||
55 | mlog_errno(status); | ||
56 | goto bail; | ||
57 | } | ||
58 | |||
59 | status = -EROFS; | ||
60 | if (IS_RDONLY(inode)) | ||
61 | goto bail_unlock; | ||
62 | |||
63 | status = -EACCES; | ||
64 | if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | ||
65 | goto bail_unlock; | ||
66 | |||
67 | if (!S_ISDIR(inode->i_mode)) | ||
68 | flags &= ~OCFS2_DIRSYNC_FL; | ||
69 | |||
70 | handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS); | ||
71 | if (IS_ERR(handle)) { | ||
72 | status = PTR_ERR(handle); | ||
73 | mlog_errno(status); | ||
74 | goto bail_unlock; | ||
75 | } | ||
76 | |||
77 | oldflags = ocfs2_inode->ip_attr; | ||
78 | flags = flags & mask; | ||
79 | flags |= oldflags & ~mask; | ||
80 | |||
81 | /* | ||
82 | * The IMMUTABLE and APPEND_ONLY flags can only be changed by | ||
83 | * the relevant capability. | ||
84 | */ | ||
85 | status = -EPERM; | ||
86 | if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) & | ||
87 | (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) { | ||
88 | if (!capable(CAP_LINUX_IMMUTABLE)) | ||
89 | goto bail_unlock; | ||
90 | } | ||
91 | |||
92 | ocfs2_inode->ip_attr = flags; | ||
93 | ocfs2_set_inode_flags(inode); | ||
94 | |||
95 | status = ocfs2_mark_inode_dirty(handle, inode, bh); | ||
96 | if (status < 0) | ||
97 | mlog_errno(status); | ||
98 | |||
99 | ocfs2_commit_trans(handle); | ||
100 | bail_unlock: | ||
101 | ocfs2_meta_unlock(inode, 1); | ||
102 | bail: | ||
103 | mutex_unlock(&inode->i_mutex); | ||
104 | |||
105 | if (bh) | ||
106 | brelse(bh); | ||
107 | |||
108 | mlog_exit(status); | ||
109 | return status; | ||
110 | } | ||
111 | |||
112 | int ocfs2_ioctl(struct inode * inode, struct file * filp, | ||
113 | unsigned int cmd, unsigned long arg) | ||
114 | { | ||
115 | unsigned int flags; | ||
116 | int status; | ||
117 | |||
118 | switch (cmd) { | ||
119 | case OCFS2_IOC_GETFLAGS: | ||
120 | status = ocfs2_get_inode_attr(inode, &flags); | ||
121 | if (status < 0) | ||
122 | return status; | ||
123 | |||
124 | flags &= OCFS2_FL_VISIBLE; | ||
125 | return put_user(flags, (int __user *) arg); | ||
126 | case OCFS2_IOC_SETFLAGS: | ||
127 | if (get_user(flags, (int __user *) arg)) | ||
128 | return -EFAULT; | ||
129 | |||
130 | return ocfs2_set_inode_attr(inode, flags, | ||
131 | OCFS2_FL_MODIFIABLE); | ||
132 | default: | ||
133 | return -ENOTTY; | ||
134 | } | ||
135 | } | ||
136 | |||
diff --git a/fs/ocfs2/ioctl.h b/fs/ocfs2/ioctl.h new file mode 100644 index 000000000000..4a7c82931dba --- /dev/null +++ b/fs/ocfs2/ioctl.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * ioctl.h | ||
3 | * | ||
4 | * Function prototypes | ||
5 | * | ||
6 | * Copyright (C) 2006 Herbert Poetzl | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #ifndef OCFS2_IOCTL_H | ||
11 | #define OCFS2_IOCTL_H | ||
12 | |||
13 | int ocfs2_ioctl(struct inode * inode, struct file * filp, | ||
14 | unsigned int cmd, unsigned long arg); | ||
15 | |||
16 | #endif /* OCFS2_IOCTL_H */ | ||
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 0673862c8bdd..0d3e939b1f56 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include "journal.h" | 56 | #include "journal.h" |
57 | #include "namei.h" | 57 | #include "namei.h" |
58 | #include "suballoc.h" | 58 | #include "suballoc.h" |
59 | #include "super.h" | ||
59 | #include "symlink.h" | 60 | #include "symlink.h" |
60 | #include "sysfile.h" | 61 | #include "sysfile.h" |
61 | #include "uptodate.h" | 62 | #include "uptodate.h" |
@@ -310,13 +311,6 @@ static int ocfs2_mknod(struct inode *dir, | |||
310 | /* get our super block */ | 311 | /* get our super block */ |
311 | osb = OCFS2_SB(dir->i_sb); | 312 | osb = OCFS2_SB(dir->i_sb); |
312 | 313 | ||
313 | if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) { | ||
314 | mlog(ML_ERROR, "inode %llu has i_nlink of %u\n", | ||
315 | (unsigned long long)OCFS2_I(dir)->ip_blkno, dir->i_nlink); | ||
316 | status = -EMLINK; | ||
317 | goto leave; | ||
318 | } | ||
319 | |||
320 | handle = ocfs2_alloc_handle(osb); | 314 | handle = ocfs2_alloc_handle(osb); |
321 | if (handle == NULL) { | 315 | if (handle == NULL) { |
322 | status = -ENOMEM; | 316 | status = -ENOMEM; |
@@ -331,6 +325,11 @@ static int ocfs2_mknod(struct inode *dir, | |||
331 | goto leave; | 325 | goto leave; |
332 | } | 326 | } |
333 | 327 | ||
328 | if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) { | ||
329 | status = -EMLINK; | ||
330 | goto leave; | ||
331 | } | ||
332 | |||
334 | dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; | 333 | dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; |
335 | if (!dirfe->i_links_count) { | 334 | if (!dirfe->i_links_count) { |
336 | /* can't make a file in a deleted directory. */ | 335 | /* can't make a file in a deleted directory. */ |
@@ -643,11 +642,6 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
643 | goto bail; | 642 | goto bail; |
644 | } | 643 | } |
645 | 644 | ||
646 | if (inode->i_nlink >= OCFS2_LINK_MAX) { | ||
647 | err = -EMLINK; | ||
648 | goto bail; | ||
649 | } | ||
650 | |||
651 | handle = ocfs2_alloc_handle(osb); | 645 | handle = ocfs2_alloc_handle(osb); |
652 | if (handle == NULL) { | 646 | if (handle == NULL) { |
653 | err = -ENOMEM; | 647 | err = -ENOMEM; |
@@ -661,6 +655,11 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
661 | goto bail; | 655 | goto bail; |
662 | } | 656 | } |
663 | 657 | ||
658 | if (!dir->i_nlink) { | ||
659 | err = -ENOENT; | ||
660 | goto bail; | ||
661 | } | ||
662 | |||
664 | err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, | 663 | err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, |
665 | dentry->d_name.len); | 664 | dentry->d_name.len); |
666 | if (err) | 665 | if (err) |
@@ -1964,13 +1963,8 @@ restart: | |||
1964 | } | 1963 | } |
1965 | num++; | 1964 | num++; |
1966 | 1965 | ||
1967 | /* XXX: questionable readahead stuff here */ | ||
1968 | bh = ocfs2_bread(dir, b++, &err, 1); | 1966 | bh = ocfs2_bread(dir, b++, &err, 1); |
1969 | bh_use[ra_max] = bh; | 1967 | bh_use[ra_max] = bh; |
1970 | #if 0 // ??? | ||
1971 | if (bh) | ||
1972 | ll_rw_block(READ, 1, &bh); | ||
1973 | #endif | ||
1974 | } | 1968 | } |
1975 | } | 1969 | } |
1976 | if ((bh = bh_use[ra_ptr++]) == NULL) | 1970 | if ((bh = bh_use[ra_ptr++]) == NULL) |
@@ -1978,6 +1972,10 @@ restart: | |||
1978 | wait_on_buffer(bh); | 1972 | wait_on_buffer(bh); |
1979 | if (!buffer_uptodate(bh)) { | 1973 | if (!buffer_uptodate(bh)) { |
1980 | /* read error, skip block & hope for the best */ | 1974 | /* read error, skip block & hope for the best */ |
1975 | ocfs2_error(dir->i_sb, "reading directory %llu, " | ||
1976 | "offset %lu\n", | ||
1977 | (unsigned long long)OCFS2_I(dir)->ip_blkno, | ||
1978 | block); | ||
1981 | brelse(bh); | 1979 | brelse(bh); |
1982 | goto next; | 1980 | goto next; |
1983 | } | 1981 | } |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index c5b1ac547c15..3330a5dc6be2 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
@@ -114,6 +114,26 @@ | |||
114 | #define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ | 114 | #define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ |
115 | #define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ | 115 | #define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ |
116 | 116 | ||
117 | /* Inode attributes, keep in sync with EXT2 */ | ||
118 | #define OCFS2_SECRM_FL (0x00000001) /* Secure deletion */ | ||
119 | #define OCFS2_UNRM_FL (0x00000002) /* Undelete */ | ||
120 | #define OCFS2_COMPR_FL (0x00000004) /* Compress file */ | ||
121 | #define OCFS2_SYNC_FL (0x00000008) /* Synchronous updates */ | ||
122 | #define OCFS2_IMMUTABLE_FL (0x00000010) /* Immutable file */ | ||
123 | #define OCFS2_APPEND_FL (0x00000020) /* writes to file may only append */ | ||
124 | #define OCFS2_NODUMP_FL (0x00000040) /* do not dump file */ | ||
125 | #define OCFS2_NOATIME_FL (0x00000080) /* do not update atime */ | ||
126 | #define OCFS2_DIRSYNC_FL (0x00010000) /* dirsync behaviour (directories only) */ | ||
127 | |||
128 | #define OCFS2_FL_VISIBLE (0x000100FF) /* User visible flags */ | ||
129 | #define OCFS2_FL_MODIFIABLE (0x000100FF) /* User modifiable flags */ | ||
130 | |||
131 | /* | ||
132 | * ioctl commands | ||
133 | */ | ||
134 | #define OCFS2_IOC_GETFLAGS _IOR('f', 1, long) | ||
135 | #define OCFS2_IOC_SETFLAGS _IOW('f', 2, long) | ||
136 | |||
117 | /* | 137 | /* |
118 | * Journal Flags (ocfs2_dinode.id1.journal1.i_flags) | 138 | * Journal Flags (ocfs2_dinode.id1.journal1.i_flags) |
119 | */ | 139 | */ |
@@ -399,7 +419,9 @@ struct ocfs2_dinode { | |||
399 | __le32 i_atime_nsec; | 419 | __le32 i_atime_nsec; |
400 | __le32 i_ctime_nsec; | 420 | __le32 i_ctime_nsec; |
401 | __le32 i_mtime_nsec; | 421 | __le32 i_mtime_nsec; |
402 | /*70*/ __le64 i_reserved1[9]; | 422 | __le32 i_attr; |
423 | __le32 i_reserved1; | ||
424 | /*70*/ __le64 i_reserved2[8]; | ||
403 | /*B8*/ union { | 425 | /*B8*/ union { |
404 | __le64 i_pad1; /* Generic way to refer to this | 426 | __le64 i_pad1; /* Generic way to refer to this |
405 | 64bit union */ | 427 | 64bit union */ |
diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c index b8a00a793326..9707ed7a3206 100644 --- a/fs/ocfs2/uptodate.c +++ b/fs/ocfs2/uptodate.c | |||
@@ -206,7 +206,10 @@ static int ocfs2_buffer_cached(struct ocfs2_inode_info *oi, | |||
206 | } | 206 | } |
207 | 207 | ||
208 | /* Warning: even if it returns true, this does *not* guarantee that | 208 | /* Warning: even if it returns true, this does *not* guarantee that |
209 | * the block is stored in our inode metadata cache. */ | 209 | * the block is stored in our inode metadata cache. |
210 | * | ||
211 | * This can be called under lock_buffer() | ||
212 | */ | ||
210 | int ocfs2_buffer_uptodate(struct inode *inode, | 213 | int ocfs2_buffer_uptodate(struct inode *inode, |
211 | struct buffer_head *bh) | 214 | struct buffer_head *bh) |
212 | { | 215 | { |
@@ -226,6 +229,16 @@ int ocfs2_buffer_uptodate(struct inode *inode, | |||
226 | return ocfs2_buffer_cached(OCFS2_I(inode), bh); | 229 | return ocfs2_buffer_cached(OCFS2_I(inode), bh); |
227 | } | 230 | } |
228 | 231 | ||
232 | /* | ||
233 | * Determine whether a buffer is currently out on a read-ahead request. | ||
234 | * ip_io_sem should be held to serialize submitters with the logic here. | ||
235 | */ | ||
236 | int ocfs2_buffer_read_ahead(struct inode *inode, | ||
237 | struct buffer_head *bh) | ||
238 | { | ||
239 | return buffer_locked(bh) && ocfs2_buffer_cached(OCFS2_I(inode), bh); | ||
240 | } | ||
241 | |||
229 | /* Requires ip_lock */ | 242 | /* Requires ip_lock */ |
230 | static void ocfs2_append_cache_array(struct ocfs2_caching_info *ci, | 243 | static void ocfs2_append_cache_array(struct ocfs2_caching_info *ci, |
231 | sector_t block) | 244 | sector_t block) |
@@ -403,7 +416,11 @@ out_free: | |||
403 | * | 416 | * |
404 | * Note that this function may actually fail to insert the block if | 417 | * Note that this function may actually fail to insert the block if |
405 | * memory cannot be allocated. This is not fatal however (but may | 418 | * memory cannot be allocated. This is not fatal however (but may |
406 | * result in a performance penalty) */ | 419 | * result in a performance penalty) |
420 | * | ||
421 | * Readahead buffers can be passed in here before the I/O request is | ||
422 | * completed. | ||
423 | */ | ||
407 | void ocfs2_set_buffer_uptodate(struct inode *inode, | 424 | void ocfs2_set_buffer_uptodate(struct inode *inode, |
408 | struct buffer_head *bh) | 425 | struct buffer_head *bh) |
409 | { | 426 | { |
diff --git a/fs/ocfs2/uptodate.h b/fs/ocfs2/uptodate.h index 01cd32d26b06..2e73206059a8 100644 --- a/fs/ocfs2/uptodate.h +++ b/fs/ocfs2/uptodate.h | |||
@@ -40,5 +40,7 @@ void ocfs2_set_new_buffer_uptodate(struct inode *inode, | |||
40 | struct buffer_head *bh); | 40 | struct buffer_head *bh); |
41 | void ocfs2_remove_from_cache(struct inode *inode, | 41 | void ocfs2_remove_from_cache(struct inode *inode, |
42 | struct buffer_head *bh); | 42 | struct buffer_head *bh); |
43 | int ocfs2_buffer_read_ahead(struct inode *inode, | ||
44 | struct buffer_head *bh); | ||
43 | 45 | ||
44 | #endif /* OCFS2_UPTODATE_H */ | 46 | #endif /* OCFS2_UPTODATE_H */ |