aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/Makefile1
-rw-r--r--fs/9p/v9fs_vfs.h1
-rw-r--r--fs/9p/vfs_addr.c109
-rw-r--r--fs/9p/vfs_file.c4
-rw-r--r--fs/9p/vfs_inode.c1
-rw-r--r--fs/compat.c308
-rw-r--r--fs/exec.c2
-rw-r--r--fs/exportfs/expfs.c79
-rw-r--r--fs/hfs/bfind.c3
-rw-r--r--fs/hfs/bnode.c6
-rw-r--r--fs/hfs/brec.c2
-rw-r--r--fs/hfs/btree.c10
-rw-r--r--fs/hfs/catalog.c2
-rw-r--r--fs/hfs/dir.c12
-rw-r--r--fs/hfs/hfs_fs.h3
-rw-r--r--fs/hfs/inode.c1
-rw-r--r--fs/hfs/mdb.c22
-rw-r--r--fs/hfs/super.c40
-rw-r--r--fs/hfsplus/bfind.c3
-rw-r--r--fs/hfsplus/bnode.c11
-rw-r--r--fs/hfsplus/brec.c2
-rw-r--r--fs/hfsplus/btree.c37
-rw-r--r--fs/hfsplus/catalog.c44
-rw-r--r--fs/hfsplus/dir.c47
-rw-r--r--fs/hfsplus/extents.c6
-rw-r--r--fs/hfsplus/hfsplus_fs.h12
-rw-r--r--fs/hfsplus/hfsplus_raw.h13
-rw-r--r--fs/hfsplus/inode.c11
-rw-r--r--fs/hfsplus/options.c18
-rw-r--r--fs/hfsplus/super.c54
-rw-r--r--fs/hfsplus/unicode.c30
-rw-r--r--fs/hfsplus/wrapper.c17
-rw-r--r--fs/inotify.c1
-rw-r--r--fs/jbd/checkpoint.c2
-rw-r--r--fs/jbd/commit.c3
-rw-r--r--fs/namei.c172
-rw-r--r--fs/nfsctl.c1
-rw-r--r--fs/nfsd/nfs4proc.c55
-rw-r--r--fs/nfsd/nfs4recover.c10
-rw-r--r--fs/nfsd/nfs4state.c220
-rw-r--r--fs/nfsd/nfs4xdr.c10
-rw-r--r--fs/nfsd/nfsproc.c37
-rw-r--r--fs/nfsd/vfs.c89
-rw-r--r--fs/open.c83
-rw-r--r--fs/select.c348
-rw-r--r--fs/stat.c66
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c29
47 files changed, 1429 insertions, 608 deletions
diff --git a/fs/9p/Makefile b/fs/9p/Makefile
index 3d023089707e..2f4ce43f7b6c 100644
--- a/fs/9p/Makefile
+++ b/fs/9p/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_9P_FS) := 9p2000.o
8 conv.o \ 8 conv.o \
9 vfs_super.o \ 9 vfs_super.o \
10 vfs_inode.o \ 10 vfs_inode.o \
11 vfs_addr.o \
11 vfs_file.o \ 12 vfs_file.o \
12 vfs_dir.o \ 13 vfs_dir.o \
13 vfs_dentry.o \ 14 vfs_dentry.o \
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index c78502ad00ed..69cf2905dc90 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -39,6 +39,7 @@
39 */ 39 */
40 40
41extern struct file_system_type v9fs_fs_type; 41extern struct file_system_type v9fs_fs_type;
42extern struct address_space_operations v9fs_addr_operations;
42extern struct file_operations v9fs_file_operations; 43extern struct file_operations v9fs_file_operations;
43extern struct file_operations v9fs_dir_operations; 44extern struct file_operations v9fs_dir_operations;
44extern struct dentry_operations v9fs_dentry_operations; 45extern struct dentry_operations v9fs_dentry_operations;
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
new file mode 100644
index 000000000000..8100fb5171b7
--- /dev/null
+++ b/fs/9p/vfs_addr.c
@@ -0,0 +1,109 @@
1/*
2 * linux/fs/9p/vfs_addr.c
3 *
4 * This file contians vfs address (mmap) ops for 9P2000.
5 *
6 * Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com>
7 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program 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 the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to:
21 * Free Software Foundation
22 * 51 Franklin Street, Fifth Floor
23 * Boston, MA 02111-1301 USA
24 *
25 */
26
27#include <linux/module.h>
28#include <linux/errno.h>
29#include <linux/fs.h>
30#include <linux/file.h>
31#include <linux/stat.h>
32#include <linux/string.h>
33#include <linux/smp_lock.h>
34#include <linux/inet.h>
35#include <linux/version.h>
36#include <linux/pagemap.h>
37#include <linux/idr.h>
38
39#include "debug.h"
40#include "v9fs.h"
41#include "9p.h"
42#include "v9fs_vfs.h"
43#include "fid.h"
44
45/**
46 * v9fs_vfs_readpage - read an entire page in from 9P
47 *
48 * @file: file being read
49 * @page: structure to page
50 *
51 */
52
53static int v9fs_vfs_readpage(struct file *filp, struct page *page)
54{
55 char *buffer = NULL;
56 int retval = -EIO;
57 loff_t offset = page_offset(page);
58 int count = PAGE_CACHE_SIZE;
59 struct inode *inode = filp->f_dentry->d_inode;
60 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
61 int rsize = v9ses->maxdata - V9FS_IOHDRSZ;
62 struct v9fs_fid *v9f = filp->private_data;
63 struct v9fs_fcall *fcall = NULL;
64 int fid = v9f->fid;
65 int total = 0;
66 int result = 0;
67
68 buffer = kmap(page);
69 do {
70 if (count < rsize)
71 rsize = count;
72
73 result = v9fs_t_read(v9ses, fid, offset, rsize, &fcall);
74
75 if (result < 0) {
76 printk(KERN_ERR "v9fs_t_read returned %d\n",
77 result);
78
79 kfree(fcall);
80 goto UnmapAndUnlock;
81 } else
82 offset += result;
83
84 memcpy(buffer, fcall->params.rread.data, result);
85
86 count -= result;
87 buffer += result;
88 total += result;
89
90 kfree(fcall);
91
92 if (result < rsize)
93 break;
94 } while (count);
95
96 memset(buffer, 0, count);
97 flush_dcache_page(page);
98 SetPageUptodate(page);
99 retval = 0;
100
101UnmapAndUnlock:
102 kunmap(page);
103 unlock_page(page);
104 return retval;
105}
106
107struct address_space_operations v9fs_addr_operations = {
108 .readpage = v9fs_vfs_readpage,
109};
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 6852f0eb96ed..c7e14d917215 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -289,6 +289,9 @@ v9fs_file_write(struct file *filp, const char __user * data,
289 total += result; 289 total += result;
290 } while (count); 290 } while (count);
291 291
292 if(inode->i_mapping->nrpages)
293 invalidate_inode_pages2(inode->i_mapping);
294
292 return total; 295 return total;
293} 296}
294 297
@@ -299,4 +302,5 @@ struct file_operations v9fs_file_operations = {
299 .open = v9fs_file_open, 302 .open = v9fs_file_open,
300 .release = v9fs_dir_release, 303 .release = v9fs_dir_release,
301 .lock = v9fs_file_lock, 304 .lock = v9fs_file_lock,
305 .mmap = generic_file_mmap,
302}; 306};
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index a17b28854288..91f552454c76 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -177,6 +177,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
177 inode->i_blocks = 0; 177 inode->i_blocks = 0;
178 inode->i_rdev = 0; 178 inode->i_rdev = 0;
179 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 179 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
180 inode->i_mapping->a_ops = &v9fs_addr_operations;
180 181
181 switch (mode & S_IFMT) { 182 switch (mode & S_IFMT) {
182 case S_IFIFO: 183 case S_IFIFO:
diff --git a/fs/compat.c b/fs/compat.c
index 2468ac1df2f0..18b21b4c9e3a 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -53,6 +53,8 @@
53#include <asm/mmu_context.h> 53#include <asm/mmu_context.h>
54#include <asm/ioctls.h> 54#include <asm/ioctls.h>
55 55
56extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
57
56/* 58/*
57 * Not all architectures have sys_utime, so implement this in terms 59 * Not all architectures have sys_utime, so implement this in terms
58 * of sys_utimes. 60 * of sys_utimes.
@@ -68,10 +70,10 @@ asmlinkage long compat_sys_utime(char __user *filename, struct compat_utimbuf __
68 tv[0].tv_usec = 0; 70 tv[0].tv_usec = 0;
69 tv[1].tv_usec = 0; 71 tv[1].tv_usec = 0;
70 } 72 }
71 return do_utimes(filename, t ? tv : NULL); 73 return do_utimes(AT_FDCWD, filename, t ? tv : NULL);
72} 74}
73 75
74asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t) 76asmlinkage long compat_sys_futimesat(int dfd, char __user *filename, struct compat_timeval __user *t)
75{ 77{
76 struct timeval tv[2]; 78 struct timeval tv[2];
77 79
@@ -82,14 +84,19 @@ asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval _
82 get_user(tv[1].tv_usec, &t[1].tv_usec)) 84 get_user(tv[1].tv_usec, &t[1].tv_usec))
83 return -EFAULT; 85 return -EFAULT;
84 } 86 }
85 return do_utimes(filename, t ? tv : NULL); 87 return do_utimes(dfd, filename, t ? tv : NULL);
88}
89
90asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t)
91{
92 return compat_sys_futimesat(AT_FDCWD, filename, t);
86} 93}
87 94
88asmlinkage long compat_sys_newstat(char __user * filename, 95asmlinkage long compat_sys_newstat(char __user * filename,
89 struct compat_stat __user *statbuf) 96 struct compat_stat __user *statbuf)
90{ 97{
91 struct kstat stat; 98 struct kstat stat;
92 int error = vfs_stat(filename, &stat); 99 int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
93 100
94 if (!error) 101 if (!error)
95 error = cp_compat_stat(&stat, statbuf); 102 error = cp_compat_stat(&stat, statbuf);
@@ -100,10 +107,31 @@ asmlinkage long compat_sys_newlstat(char __user * filename,
100 struct compat_stat __user *statbuf) 107 struct compat_stat __user *statbuf)
101{ 108{
102 struct kstat stat; 109 struct kstat stat;
103 int error = vfs_lstat(filename, &stat); 110 int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
111
112 if (!error)
113 error = cp_compat_stat(&stat, statbuf);
114 return error;
115}
116
117asmlinkage long compat_sys_newfstatat(int dfd, char __user *filename,
118 struct compat_stat __user *statbuf, int flag)
119{
120 struct kstat stat;
121 int error = -EINVAL;
122
123 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
124 goto out;
125
126 if (flag & AT_SYMLINK_NOFOLLOW)
127 error = vfs_lstat_fd(dfd, filename, &stat);
128 else
129 error = vfs_stat_fd(dfd, filename, &stat);
104 130
105 if (!error) 131 if (!error)
106 error = cp_compat_stat(&stat, statbuf); 132 error = cp_compat_stat(&stat, statbuf);
133
134out:
107 return error; 135 return error;
108} 136}
109 137
@@ -1290,7 +1318,17 @@ out:
1290asmlinkage long 1318asmlinkage long
1291compat_sys_open(const char __user *filename, int flags, int mode) 1319compat_sys_open(const char __user *filename, int flags, int mode)
1292{ 1320{
1293 return do_sys_open(filename, flags, mode); 1321 return do_sys_open(AT_FDCWD, filename, flags, mode);
1322}
1323
1324/*
1325 * Exactly like fs/open.c:sys_openat(), except that it doesn't set the
1326 * O_LARGEFILE flag.
1327 */
1328asmlinkage long
1329compat_sys_openat(int dfd, const char __user *filename, int flags, int mode)
1330{
1331 return do_sys_open(dfd, filename, flags, mode);
1294} 1332}
1295 1333
1296/* 1334/*
@@ -1621,36 +1659,14 @@ static void select_bits_free(void *bits, int size)
1621#define MAX_SELECT_SECONDS \ 1659#define MAX_SELECT_SECONDS \
1622 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) 1660 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
1623 1661
1624asmlinkage long 1662int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1625compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, 1663 compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout)
1626 compat_ulong_t __user *exp, struct compat_timeval __user *tvp)
1627{ 1664{
1628 fd_set_bits fds; 1665 fd_set_bits fds;
1629 char *bits; 1666 char *bits;
1630 long timeout;
1631 int size, max_fdset, ret = -EINVAL; 1667 int size, max_fdset, ret = -EINVAL;
1632 struct fdtable *fdt; 1668 struct fdtable *fdt;
1633 1669
1634 timeout = MAX_SCHEDULE_TIMEOUT;
1635 if (tvp) {
1636 time_t sec, usec;
1637
1638 if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
1639 || __get_user(sec, &tvp->tv_sec)
1640 || __get_user(usec, &tvp->tv_usec)) {
1641 ret = -EFAULT;
1642 goto out_nofds;
1643 }
1644
1645 if (sec < 0 || usec < 0)
1646 goto out_nofds;
1647
1648 if ((unsigned long) sec < MAX_SELECT_SECONDS) {
1649 timeout = ROUND_UP(usec, 1000000/HZ);
1650 timeout += sec * (unsigned long) HZ;
1651 }
1652 }
1653
1654 if (n < 0) 1670 if (n < 0)
1655 goto out_nofds; 1671 goto out_nofds;
1656 1672
@@ -1687,19 +1703,7 @@ compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp
1687 zero_fd_set(n, fds.res_out); 1703 zero_fd_set(n, fds.res_out);
1688 zero_fd_set(n, fds.res_ex); 1704 zero_fd_set(n, fds.res_ex);
1689 1705
1690 ret = do_select(n, &fds, &timeout); 1706 ret = do_select(n, &fds, timeout);
1691
1692 if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
1693 time_t sec = 0, usec = 0;
1694 if (timeout) {
1695 sec = timeout / HZ;
1696 usec = timeout % HZ;
1697 usec *= (1000000/HZ);
1698 }
1699 if (put_user(sec, &tvp->tv_sec) ||
1700 put_user(usec, &tvp->tv_usec))
1701 ret = -EFAULT;
1702 }
1703 1707
1704 if (ret < 0) 1708 if (ret < 0)
1705 goto out; 1709 goto out;
@@ -1720,6 +1724,224 @@ out_nofds:
1720 return ret; 1724 return ret;
1721} 1725}
1722 1726
1727asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
1728 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1729 struct compat_timeval __user *tvp)
1730{
1731 s64 timeout = -1;
1732 struct compat_timeval tv;
1733 int ret;
1734
1735 if (tvp) {
1736 if (copy_from_user(&tv, tvp, sizeof(tv)))
1737 return -EFAULT;
1738
1739 if (tv.tv_sec < 0 || tv.tv_usec < 0)
1740 return -EINVAL;
1741
1742 /* Cast to u64 to make GCC stop complaining */
1743 if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
1744 timeout = -1; /* infinite */
1745 else {
1746 timeout = ROUND_UP(tv.tv_sec, 1000000/HZ);
1747 timeout += tv.tv_sec * HZ;
1748 }
1749 }
1750
1751 ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
1752
1753 if (tvp) {
1754 if (current->personality & STICKY_TIMEOUTS)
1755 goto sticky;
1756 tv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
1757 tv.tv_sec = timeout;
1758 if (copy_to_user(tvp, &tv, sizeof(tv))) {
1759sticky:
1760 /*
1761 * If an application puts its timeval in read-only
1762 * memory, we don't want the Linux-specific update to
1763 * the timeval to cause a fault after the select has
1764 * completed successfully. However, because we're not
1765 * updating the timeval, we can't restart the system
1766 * call.
1767 */
1768 if (ret == -ERESTARTNOHAND)
1769 ret = -EINTR;
1770 }
1771 }
1772
1773 return ret;
1774}
1775
1776#ifdef TIF_RESTORE_SIGMASK
1777asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
1778 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1779 struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
1780 compat_size_t sigsetsize)
1781{
1782 compat_sigset_t ss32;
1783 sigset_t ksigmask, sigsaved;
1784 long timeout = MAX_SCHEDULE_TIMEOUT;
1785 struct compat_timespec ts;
1786 int ret;
1787
1788 if (tsp) {
1789 if (copy_from_user(&ts, tsp, sizeof(ts)))
1790 return -EFAULT;
1791
1792 if (ts.tv_sec < 0 || ts.tv_nsec < 0)
1793 return -EINVAL;
1794 }
1795
1796 if (sigmask) {
1797 if (sigsetsize != sizeof(compat_sigset_t))
1798 return -EINVAL;
1799 if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1800 return -EFAULT;
1801 sigset_from_compat(&ksigmask, &ss32);
1802
1803 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1804 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1805 }
1806
1807 do {
1808 if (tsp) {
1809 if ((unsigned long)ts.tv_sec < MAX_SELECT_SECONDS) {
1810 timeout = ROUND_UP(ts.tv_nsec, 1000000000/HZ);
1811 timeout += ts.tv_sec * (unsigned long)HZ;
1812 ts.tv_sec = 0;
1813 ts.tv_nsec = 0;
1814 } else {
1815 ts.tv_sec -= MAX_SELECT_SECONDS;
1816 timeout = MAX_SELECT_SECONDS * HZ;
1817 }
1818 }
1819
1820 ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
1821
1822 } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec));
1823
1824 if (tsp && !(current->personality & STICKY_TIMEOUTS)) {
1825 ts.tv_sec += timeout / HZ;
1826 ts.tv_nsec += (timeout % HZ) * (1000000000/HZ);
1827 if (ts.tv_nsec >= 1000000000) {
1828 ts.tv_sec++;
1829 ts.tv_nsec -= 1000000000;
1830 }
1831 (void)copy_to_user(tsp, &ts, sizeof(ts));
1832 }
1833
1834 if (ret == -ERESTARTNOHAND) {
1835 /*
1836 * Don't restore the signal mask yet. Let do_signal() deliver
1837 * the signal on the way back to userspace, before the signal
1838 * mask is restored.
1839 */
1840 if (sigmask) {
1841 memcpy(&current->saved_sigmask, &sigsaved,
1842 sizeof(sigsaved));
1843 set_thread_flag(TIF_RESTORE_SIGMASK);
1844 }
1845 } else if (sigmask)
1846 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1847
1848 return ret;
1849}
1850
1851asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
1852 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1853 struct compat_timespec __user *tsp, void __user *sig)
1854{
1855 compat_size_t sigsetsize = 0;
1856 compat_uptr_t up = 0;
1857
1858 if (sig) {
1859 if (!access_ok(VERIFY_READ, sig,
1860 sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
1861 __get_user(up, (compat_uptr_t __user *)sig) ||
1862 __get_user(sigsetsize,
1863 (compat_size_t __user *)(sig+sizeof(up))))
1864 return -EFAULT;
1865 }
1866 return compat_sys_pselect7(n, inp, outp, exp, tsp, compat_ptr(up),
1867 sigsetsize);
1868}
1869
1870asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1871 unsigned int nfds, struct compat_timespec __user *tsp,
1872 const compat_sigset_t __user *sigmask, compat_size_t sigsetsize)
1873{
1874 compat_sigset_t ss32;
1875 sigset_t ksigmask, sigsaved;
1876 struct compat_timespec ts;
1877 s64 timeout = -1;
1878 int ret;
1879
1880 if (tsp) {
1881 if (copy_from_user(&ts, tsp, sizeof(ts)))
1882 return -EFAULT;
1883
1884 /* We assume that ts.tv_sec is always lower than
1885 the number of seconds that can be expressed in
1886 an s64. Otherwise the compiler bitches at us */
1887 timeout = ROUND_UP(ts.tv_sec, 1000000000/HZ);
1888 timeout += ts.tv_sec * HZ;
1889 }
1890
1891 if (sigmask) {
1892 if (sigsetsize |= sizeof(compat_sigset_t))
1893 return -EINVAL;
1894 if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1895 return -EFAULT;
1896 sigset_from_compat(&ksigmask, &ss32);
1897
1898 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1899 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1900 }
1901
1902 ret = do_sys_poll(ufds, nfds, &timeout);
1903
1904 /* We can restart this syscall, usually */
1905 if (ret == -EINTR) {
1906 /*
1907 * Don't restore the signal mask yet. Let do_signal() deliver
1908 * the signal on the way back to userspace, before the signal
1909 * mask is restored.
1910 */
1911 if (sigmask) {
1912 memcpy(&current->saved_sigmask, &sigsaved,
1913 sizeof(sigsaved));
1914 set_thread_flag(TIF_RESTORE_SIGMASK);
1915 }
1916 ret = -ERESTARTNOHAND;
1917 } else if (sigmask)
1918 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1919
1920 if (tsp && timeout >= 0) {
1921 if (current->personality & STICKY_TIMEOUTS)
1922 goto sticky;
1923 /* Yes, we know it's actually an s64, but it's also positive. */
1924 ts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * 1000;
1925 ts.tv_sec = timeout;
1926 if (copy_to_user(tsp, &ts, sizeof(ts))) {
1927sticky:
1928 /*
1929 * If an application puts its timeval in read-only
1930 * memory, we don't want the Linux-specific update to
1931 * the timeval to cause a fault after the select has
1932 * completed successfully. However, because we're not
1933 * updating the timeval, we can't restart the system
1934 * call.
1935 */
1936 if (ret == -ERESTARTNOHAND && timeout >= 0)
1937 ret = -EINTR;
1938 }
1939 }
1940
1941 return ret;
1942}
1943#endif /* TIF_RESTORE_SIGMASK */
1944
1723#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) 1945#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
1724/* Stuff for NFS server syscalls... */ 1946/* Stuff for NFS server syscalls... */
1725struct compat_nfsctl_svc { 1947struct compat_nfsctl_svc {
diff --git a/fs/exec.c b/fs/exec.c
index 62b40af68cc4..055378d2513e 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -477,7 +477,7 @@ struct file *open_exec(const char *name)
477 int err; 477 int err;
478 struct file *file; 478 struct file *file;
479 479
480 err = path_lookup_open(name, LOOKUP_FOLLOW, &nd, FMODE_READ); 480 err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ);
481 file = ERR_PTR(err); 481 file = ERR_PTR(err);
482 482
483 if (!err) { 483 if (!err) {
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 5bfe40085fbc..b06b54f1bbbb 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -11,6 +11,33 @@ struct export_operations export_op_default;
11 11
12#define dprintk(fmt, args...) do{}while(0) 12#define dprintk(fmt, args...) do{}while(0)
13 13
14static struct dentry *
15find_acceptable_alias(struct dentry *result,
16 int (*acceptable)(void *context, struct dentry *dentry),
17 void *context)
18{
19 struct dentry *dentry, *toput = NULL;
20
21 spin_lock(&dcache_lock);
22 list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) {
23 dget_locked(dentry);
24 spin_unlock(&dcache_lock);
25 if (toput)
26 dput(toput);
27 if (dentry != result && acceptable(context, dentry)) {
28 dput(result);
29 return dentry;
30 }
31 spin_lock(&dcache_lock);
32 toput = dentry;
33 }
34 spin_unlock(&dcache_lock);
35
36 if (toput)
37 dput(toput);
38 return NULL;
39}
40
14/** 41/**
15 * find_exported_dentry - helper routine to implement export_operations->decode_fh 42 * find_exported_dentry - helper routine to implement export_operations->decode_fh
16 * @sb: The &super_block identifying the filesystem 43 * @sb: The &super_block identifying the filesystem
@@ -52,8 +79,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
52 struct dentry *target_dir; 79 struct dentry *target_dir;
53 int err; 80 int err;
54 struct export_operations *nops = sb->s_export_op; 81 struct export_operations *nops = sb->s_export_op;
55 struct list_head *le, *head; 82 struct dentry *alias;
56 struct dentry *toput = NULL;
57 int noprogress; 83 int noprogress;
58 char nbuf[NAME_MAX+1]; 84 char nbuf[NAME_MAX+1];
59 85
@@ -79,27 +105,10 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
79 /* there is no other dentry, so fail */ 105 /* there is no other dentry, so fail */
80 goto err_result; 106 goto err_result;
81 } 107 }
82 /* try any other aliases */ 108
83 spin_lock(&dcache_lock); 109 alias = find_acceptable_alias(result, acceptable, context);
84 head = &result->d_inode->i_dentry; 110 if (alias)
85 list_for_each(le, head) { 111 return alias;
86 struct dentry *dentry = list_entry(le, struct dentry, d_alias);
87 dget_locked(dentry);
88 spin_unlock(&dcache_lock);
89 if (toput)
90 dput(toput);
91 toput = NULL;
92 if (dentry != result &&
93 acceptable(context, dentry)) {
94 dput(result);
95 return dentry;
96 }
97 spin_lock(&dcache_lock);
98 toput = dentry;
99 }
100 spin_unlock(&dcache_lock);
101 if (toput)
102 dput(toput);
103 } 112 }
104 113
105 /* It's a directory, or we are required to confirm the file's 114 /* It's a directory, or we are required to confirm the file's
@@ -258,26 +267,10 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
258 /* now result is properly connected, it is our best bet */ 267 /* now result is properly connected, it is our best bet */
259 if (acceptable(context, result)) 268 if (acceptable(context, result))
260 return result; 269 return result;
261 /* one last try of the aliases.. */ 270
262 spin_lock(&dcache_lock); 271 alias = find_acceptable_alias(result, acceptable, context);
263 toput = NULL; 272 if (alias)
264 head = &result->d_inode->i_dentry; 273 return alias;
265 list_for_each(le, head) {
266 struct dentry *dentry = list_entry(le, struct dentry, d_alias);
267 dget_locked(dentry);
268 spin_unlock(&dcache_lock);
269 if (toput) dput(toput);
270 if (dentry != result &&
271 acceptable(context, dentry)) {
272 dput(result);
273 return dentry;
274 }
275 spin_lock(&dcache_lock);
276 toput = dentry;
277 }
278 spin_unlock(&dcache_lock);
279 if (toput)
280 dput(toput);
281 274
282 /* drat - I just cannot find anything acceptable */ 275 /* drat - I just cannot find anything acceptable */
283 dput(result); 276 dput(result);
diff --git a/fs/hfs/bfind.c b/fs/hfs/bfind.c
index 89450ae32228..f13f1494d4fe 100644
--- a/fs/hfs/bfind.c
+++ b/fs/hfs/bfind.c
@@ -64,7 +64,6 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
64 else 64 else
65 e = rec - 1; 65 e = rec - 1;
66 } while (b <= e); 66 } while (b <= e);
67 //printk("%d: %d,%d,%d\n", bnode->this, b, e, rec);
68 if (rec != e && e >= 0) { 67 if (rec != e && e >= 0) {
69 len = hfs_brec_lenoff(bnode, e, &off); 68 len = hfs_brec_lenoff(bnode, e, &off);
70 keylen = hfs_brec_keylen(bnode, e); 69 keylen = hfs_brec_keylen(bnode, e);
@@ -127,7 +126,7 @@ int hfs_brec_find(struct hfs_find_data *fd)
127 return res; 126 return res;
128 127
129invalid: 128invalid:
130 printk("HFS: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n", 129 printk(KERN_ERR "hfs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
131 height, bnode->height, bnode->type, nidx, parent); 130 height, bnode->height, bnode->type, nidx, parent);
132 res = -EIO; 131 res = -EIO;
133release: 132release:
diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index 3d5cdc6847c0..a7a7d77f3fd3 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -198,7 +198,7 @@ void hfs_bnode_unlink(struct hfs_bnode *node)
198 198
199 // move down? 199 // move down?
200 if (!node->prev && !node->next) { 200 if (!node->prev && !node->next) {
201 printk("hfs_btree_del_level\n"); 201 printk(KERN_DEBUG "hfs_btree_del_level\n");
202 } 202 }
203 if (!node->parent) { 203 if (!node->parent) {
204 tree->root = 0; 204 tree->root = 0;
@@ -219,7 +219,7 @@ struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid)
219 struct hfs_bnode *node; 219 struct hfs_bnode *node;
220 220
221 if (cnid >= tree->node_count) { 221 if (cnid >= tree->node_count) {
222 printk("HFS: request for non-existent node %d in B*Tree\n", cnid); 222 printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
223 return NULL; 223 return NULL;
224 } 224 }
225 225
@@ -242,7 +242,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
242 loff_t off; 242 loff_t off;
243 243
244 if (cnid >= tree->node_count) { 244 if (cnid >= tree->node_count) {
245 printk("HFS: request for non-existent node %d in B*Tree\n", cnid); 245 printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
246 return NULL; 246 return NULL;
247 } 247 }
248 248
diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c
index 7d8fff2c25fc..5c87cf4801fc 100644
--- a/fs/hfs/brec.c
+++ b/fs/hfs/brec.c
@@ -362,7 +362,7 @@ again:
362 end_off = hfs_bnode_read_u16(parent, end_rec_off); 362 end_off = hfs_bnode_read_u16(parent, end_rec_off);
363 if (end_rec_off - end_off < diff) { 363 if (end_rec_off - end_off < diff) {
364 364
365 printk("splitting index node...\n"); 365 printk(KERN_DEBUG "hfs: splitting index node...\n");
366 fd->bnode = parent; 366 fd->bnode = parent;
367 new_node = hfs_bnode_split(fd); 367 new_node = hfs_bnode_split(fd);
368 if (IS_ERR(new_node)) 368 if (IS_ERR(new_node))
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index 394725efa1c8..7bb11edd1488 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -111,7 +111,7 @@ void hfs_btree_close(struct hfs_btree *tree)
111 while ((node = tree->node_hash[i])) { 111 while ((node = tree->node_hash[i])) {
112 tree->node_hash[i] = node->next_hash; 112 tree->node_hash[i] = node->next_hash;
113 if (atomic_read(&node->refcnt)) 113 if (atomic_read(&node->refcnt))
114 printk("HFS: node %d:%d still has %d user(s)!\n", 114 printk(KERN_ERR "hfs: node %d:%d still has %d user(s)!\n",
115 node->tree->cnid, node->this, atomic_read(&node->refcnt)); 115 node->tree->cnid, node->this, atomic_read(&node->refcnt));
116 hfs_bnode_free(node); 116 hfs_bnode_free(node);
117 tree->node_hash_cnt--; 117 tree->node_hash_cnt--;
@@ -252,7 +252,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
252 kunmap(*pagep); 252 kunmap(*pagep);
253 nidx = node->next; 253 nidx = node->next;
254 if (!nidx) { 254 if (!nidx) {
255 printk("create new bmap node...\n"); 255 printk(KERN_DEBUG "hfs: create new bmap node...\n");
256 next_node = hfs_bmap_new_bmap(node, idx); 256 next_node = hfs_bmap_new_bmap(node, idx);
257 } else 257 } else
258 next_node = hfs_bnode_find(tree, nidx); 258 next_node = hfs_bnode_find(tree, nidx);
@@ -292,7 +292,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
292 hfs_bnode_put(node); 292 hfs_bnode_put(node);
293 if (!i) { 293 if (!i) {
294 /* panic */; 294 /* panic */;
295 printk("HFS: unable to free bnode %u. bmap not found!\n", node->this); 295 printk(KERN_CRIT "hfs: unable to free bnode %u. bmap not found!\n", node->this);
296 return; 296 return;
297 } 297 }
298 node = hfs_bnode_find(tree, i); 298 node = hfs_bnode_find(tree, i);
@@ -300,7 +300,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
300 return; 300 return;
301 if (node->type != HFS_NODE_MAP) { 301 if (node->type != HFS_NODE_MAP) {
302 /* panic */; 302 /* panic */;
303 printk("HFS: invalid bmap found! (%u,%d)\n", node->this, node->type); 303 printk(KERN_CRIT "hfs: invalid bmap found! (%u,%d)\n", node->this, node->type);
304 hfs_bnode_put(node); 304 hfs_bnode_put(node);
305 return; 305 return;
306 } 306 }
@@ -313,7 +313,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
313 m = 1 << (~nidx & 7); 313 m = 1 << (~nidx & 7);
314 byte = data[off]; 314 byte = data[off];
315 if (!(byte & m)) { 315 if (!(byte & m)) {
316 printk("HFS: trying to free free bnode %u(%d)\n", node->this, node->type); 316 printk(KERN_CRIT "hfs: trying to free free bnode %u(%d)\n", node->this, node->type);
317 kunmap(page); 317 kunmap(page);
318 hfs_bnode_put(node); 318 hfs_bnode_put(node);
319 return; 319 return;
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c
index 2fcd679f0238..ba851576ebb1 100644
--- a/fs/hfs/catalog.c
+++ b/fs/hfs/catalog.c
@@ -184,7 +184,7 @@ int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
184 184
185 type = rec.type; 185 type = rec.type;
186 if (type != HFS_CDR_THD && type != HFS_CDR_FTH) { 186 if (type != HFS_CDR_THD && type != HFS_CDR_FTH) {
187 printk("HFS-fs: Found bad thread record in catalog\n"); 187 printk(KERN_ERR "hfs: found bad thread record in catalog\n");
188 return -EIO; 188 return -EIO;
189 } 189 }
190 190
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index e1f24befba58..534e5a7480ef 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -81,12 +81,12 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
81 case 1: 81 case 1:
82 hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); 82 hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
83 if (entry.type != HFS_CDR_THD) { 83 if (entry.type != HFS_CDR_THD) {
84 printk("HFS: bad catalog folder thread\n"); 84 printk(KERN_ERR "hfs: bad catalog folder thread\n");
85 err = -EIO; 85 err = -EIO;
86 goto out; 86 goto out;
87 } 87 }
88 //if (fd.entrylength < HFS_MIN_THREAD_SZ) { 88 //if (fd.entrylength < HFS_MIN_THREAD_SZ) {
89 // printk("HFS: truncated catalog thread\n"); 89 // printk(KERN_ERR "hfs: truncated catalog thread\n");
90 // err = -EIO; 90 // err = -EIO;
91 // goto out; 91 // goto out;
92 //} 92 //}
@@ -105,7 +105,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
105 105
106 for (;;) { 106 for (;;) {
107 if (be32_to_cpu(fd.key->cat.ParID) != inode->i_ino) { 107 if (be32_to_cpu(fd.key->cat.ParID) != inode->i_ino) {
108 printk("HFS: walked past end of dir\n"); 108 printk(KERN_ERR "hfs: walked past end of dir\n");
109 err = -EIO; 109 err = -EIO;
110 goto out; 110 goto out;
111 } 111 }
@@ -114,7 +114,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
114 len = hfs_mac2asc(sb, strbuf, &fd.key->cat.CName); 114 len = hfs_mac2asc(sb, strbuf, &fd.key->cat.CName);
115 if (type == HFS_CDR_DIR) { 115 if (type == HFS_CDR_DIR) {
116 if (fd.entrylength < sizeof(struct hfs_cat_dir)) { 116 if (fd.entrylength < sizeof(struct hfs_cat_dir)) {
117 printk("HFS: small dir entry\n"); 117 printk(KERN_ERR "hfs: small dir entry\n");
118 err = -EIO; 118 err = -EIO;
119 goto out; 119 goto out;
120 } 120 }
@@ -123,7 +123,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
123 break; 123 break;
124 } else if (type == HFS_CDR_FIL) { 124 } else if (type == HFS_CDR_FIL) {
125 if (fd.entrylength < sizeof(struct hfs_cat_file)) { 125 if (fd.entrylength < sizeof(struct hfs_cat_file)) {
126 printk("HFS: small file entry\n"); 126 printk(KERN_ERR "hfs: small file entry\n");
127 err = -EIO; 127 err = -EIO;
128 goto out; 128 goto out;
129 } 129 }
@@ -131,7 +131,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
131 be32_to_cpu(entry.file.FlNum), DT_REG)) 131 be32_to_cpu(entry.file.FlNum), DT_REG))
132 break; 132 break;
133 } else { 133 } else {
134 printk("HFS: bad catalog entry type %d\n", type); 134 printk(KERN_ERR "hfs: bad catalog entry type %d\n", type);
135 err = -EIO; 135 err = -EIO;
136 goto out; 136 goto out;
137 } 137 }
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index cc5dcd52e23d..18ce47ab1b71 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -35,9 +35,6 @@
35#define dprint(flg, fmt, args...) \ 35#define dprint(flg, fmt, args...) \
36 if (flg & DBG_MASK) printk(fmt , ## args) 36 if (flg & DBG_MASK) printk(fmt , ## args)
37 37
38#define hfs_warn(format, args...) printk(KERN_WARNING format , ## args)
39#define hfs_error(format, args...) printk(KERN_ERR format , ## args)
40
41/* 38/*
42 * struct hfs_inode_info 39 * struct hfs_inode_info
43 * 40 *
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 050a49276499..39fd85b9b916 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -95,7 +95,6 @@ static int hfs_releasepage(struct page *page, gfp_t mask)
95 } while (--i && nidx < tree->node_count); 95 } while (--i && nidx < tree->node_count);
96 spin_unlock(&tree->hash_lock); 96 spin_unlock(&tree->hash_lock);
97 } 97 }
98 //printk("releasepage: %lu,%x = %d\n", page->index, mask, res);
99 return res ? try_to_free_buffers(page) : 0; 98 return res ? try_to_free_buffers(page) : 0;
100} 99}
101 100
diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c
index 0a473f79c89f..b4651e128d7f 100644
--- a/fs/hfs/mdb.c
+++ b/fs/hfs/mdb.c
@@ -47,7 +47,7 @@ static int hfs_get_last_session(struct super_block *sb,
47 *start = (sector_t)te.cdte_addr.lba << 2; 47 *start = (sector_t)te.cdte_addr.lba << 2;
48 return 0; 48 return 0;
49 } 49 }
50 printk(KERN_ERR "HFS: Invalid session number or type of track\n"); 50 printk(KERN_ERR "hfs: invalid session number or type of track\n");
51 return -EINVAL; 51 return -EINVAL;
52 } 52 }
53 ms_info.addr_format = CDROM_LBA; 53 ms_info.addr_format = CDROM_LBA;
@@ -100,7 +100,7 @@ int hfs_mdb_get(struct super_block *sb)
100 100
101 HFS_SB(sb)->alloc_blksz = size = be32_to_cpu(mdb->drAlBlkSiz); 101 HFS_SB(sb)->alloc_blksz = size = be32_to_cpu(mdb->drAlBlkSiz);
102 if (!size || (size & (HFS_SECTOR_SIZE - 1))) { 102 if (!size || (size & (HFS_SECTOR_SIZE - 1))) {
103 hfs_warn("hfs_fs: bad allocation block size %d\n", size); 103 printk(KERN_ERR "hfs: bad allocation block size %d\n", size);
104 goto out_bh; 104 goto out_bh;
105 } 105 }
106 106
@@ -117,7 +117,7 @@ int hfs_mdb_get(struct super_block *sb)
117 size >>= 1; 117 size >>= 1;
118 brelse(bh); 118 brelse(bh);
119 if (!sb_set_blocksize(sb, size)) { 119 if (!sb_set_blocksize(sb, size)) {
120 printk("hfs_fs: unable to set blocksize to %u\n", size); 120 printk(KERN_ERR "hfs: unable to set blocksize to %u\n", size);
121 goto out; 121 goto out;
122 } 122 }
123 123
@@ -161,8 +161,8 @@ int hfs_mdb_get(struct super_block *sb)
161 } 161 }
162 162
163 if (!HFS_SB(sb)->alt_mdb) { 163 if (!HFS_SB(sb)->alt_mdb) {
164 hfs_warn("hfs_fs: unable to locate alternate MDB\n"); 164 printk(KERN_WARNING "hfs: unable to locate alternate MDB\n");
165 hfs_warn("hfs_fs: continuing without an alternate MDB\n"); 165 printk(KERN_WARNING "hfs: continuing without an alternate MDB\n");
166 } 166 }
167 167
168 HFS_SB(sb)->bitmap = (__be32 *)__get_free_pages(GFP_KERNEL, PAGE_SIZE < 8192 ? 1 : 0); 168 HFS_SB(sb)->bitmap = (__be32 *)__get_free_pages(GFP_KERNEL, PAGE_SIZE < 8192 ? 1 : 0);
@@ -177,7 +177,7 @@ int hfs_mdb_get(struct super_block *sb)
177 while (size) { 177 while (size) {
178 bh = sb_bread(sb, off >> sb->s_blocksize_bits); 178 bh = sb_bread(sb, off >> sb->s_blocksize_bits);
179 if (!bh) { 179 if (!bh) {
180 hfs_warn("hfs_fs: unable to read volume bitmap\n"); 180 printk(KERN_ERR "hfs: unable to read volume bitmap\n");
181 goto out; 181 goto out;
182 } 182 }
183 off2 = off & (sb->s_blocksize - 1); 183 off2 = off & (sb->s_blocksize - 1);
@@ -191,23 +191,23 @@ int hfs_mdb_get(struct super_block *sb)
191 191
192 HFS_SB(sb)->ext_tree = hfs_btree_open(sb, HFS_EXT_CNID, hfs_ext_keycmp); 192 HFS_SB(sb)->ext_tree = hfs_btree_open(sb, HFS_EXT_CNID, hfs_ext_keycmp);
193 if (!HFS_SB(sb)->ext_tree) { 193 if (!HFS_SB(sb)->ext_tree) {
194 hfs_warn("hfs_fs: unable to open extent tree\n"); 194 printk(KERN_ERR "hfs: unable to open extent tree\n");
195 goto out; 195 goto out;
196 } 196 }
197 HFS_SB(sb)->cat_tree = hfs_btree_open(sb, HFS_CAT_CNID, hfs_cat_keycmp); 197 HFS_SB(sb)->cat_tree = hfs_btree_open(sb, HFS_CAT_CNID, hfs_cat_keycmp);
198 if (!HFS_SB(sb)->cat_tree) { 198 if (!HFS_SB(sb)->cat_tree) {
199 hfs_warn("hfs_fs: unable to open catalog tree\n"); 199 printk(KERN_ERR "hfs: unable to open catalog tree\n");
200 goto out; 200 goto out;
201 } 201 }
202 202
203 attrib = mdb->drAtrb; 203 attrib = mdb->drAtrb;
204 if (!(attrib & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) { 204 if (!(attrib & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) {
205 hfs_warn("HFS-fs warning: Filesystem was not cleanly unmounted, " 205 printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, "
206 "running fsck.hfs is recommended. mounting read-only.\n"); 206 "running fsck.hfs is recommended. mounting read-only.\n");
207 sb->s_flags |= MS_RDONLY; 207 sb->s_flags |= MS_RDONLY;
208 } 208 }
209 if ((attrib & cpu_to_be16(HFS_SB_ATTRIB_SLOCK))) { 209 if ((attrib & cpu_to_be16(HFS_SB_ATTRIB_SLOCK))) {
210 hfs_warn("HFS-fs: Filesystem is marked locked, mounting read-only.\n"); 210 printk(KERN_WARNING "hfs: filesystem is marked locked, mounting read-only.\n");
211 sb->s_flags |= MS_RDONLY; 211 sb->s_flags |= MS_RDONLY;
212 } 212 }
213 if (!(sb->s_flags & MS_RDONLY)) { 213 if (!(sb->s_flags & MS_RDONLY)) {
@@ -303,7 +303,7 @@ void hfs_mdb_commit(struct super_block *sb)
303 while (size) { 303 while (size) {
304 bh = sb_bread(sb, block); 304 bh = sb_bread(sb, block);
305 if (!bh) { 305 if (!bh) {
306 hfs_warn("hfs_fs: unable to read volume bitmap\n"); 306 printk(KERN_ERR "hfs: unable to read volume bitmap\n");
307 break; 307 break;
308 } 308 }
309 len = min((int)sb->s_blocksize - off, size); 309 len = min((int)sb->s_blocksize - off, size);
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index c5074aeafcae..1181d116117d 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -101,12 +101,12 @@ static int hfs_remount(struct super_block *sb, int *flags, char *data)
101 return 0; 101 return 0;
102 if (!(*flags & MS_RDONLY)) { 102 if (!(*flags & MS_RDONLY)) {
103 if (!(HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) { 103 if (!(HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) {
104 printk("HFS-fs warning: Filesystem was not cleanly unmounted, " 104 printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, "
105 "running fsck.hfs is recommended. leaving read-only.\n"); 105 "running fsck.hfs is recommended. leaving read-only.\n");
106 sb->s_flags |= MS_RDONLY; 106 sb->s_flags |= MS_RDONLY;
107 *flags |= MS_RDONLY; 107 *flags |= MS_RDONLY;
108 } else if (HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_SLOCK)) { 108 } else if (HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_SLOCK)) {
109 printk("HFS-fs: Filesystem is marked locked, leaving read-only.\n"); 109 printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n");
110 sb->s_flags |= MS_RDONLY; 110 sb->s_flags |= MS_RDONLY;
111 *flags |= MS_RDONLY; 111 *flags |= MS_RDONLY;
112 } 112 }
@@ -229,21 +229,21 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
229 switch (token) { 229 switch (token) {
230 case opt_uid: 230 case opt_uid:
231 if (match_int(&args[0], &tmp)) { 231 if (match_int(&args[0], &tmp)) {
232 printk("HFS: uid requires an argument\n"); 232 printk(KERN_ERR "hfs: uid requires an argument\n");
233 return 0; 233 return 0;
234 } 234 }
235 hsb->s_uid = (uid_t)tmp; 235 hsb->s_uid = (uid_t)tmp;
236 break; 236 break;
237 case opt_gid: 237 case opt_gid:
238 if (match_int(&args[0], &tmp)) { 238 if (match_int(&args[0], &tmp)) {
239 printk("HFS: gid requires an argument\n"); 239 printk(KERN_ERR "hfs: gid requires an argument\n");
240 return 0; 240 return 0;
241 } 241 }
242 hsb->s_gid = (gid_t)tmp; 242 hsb->s_gid = (gid_t)tmp;
243 break; 243 break;
244 case opt_umask: 244 case opt_umask:
245 if (match_octal(&args[0], &tmp)) { 245 if (match_octal(&args[0], &tmp)) {
246 printk("HFS: umask requires a value\n"); 246 printk(KERN_ERR "hfs: umask requires a value\n");
247 return 0; 247 return 0;
248 } 248 }
249 hsb->s_file_umask = (umode_t)tmp; 249 hsb->s_file_umask = (umode_t)tmp;
@@ -251,39 +251,39 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
251 break; 251 break;
252 case opt_file_umask: 252 case opt_file_umask:
253 if (match_octal(&args[0], &tmp)) { 253 if (match_octal(&args[0], &tmp)) {
254 printk("HFS: file_umask requires a value\n"); 254 printk(KERN_ERR "hfs: file_umask requires a value\n");
255 return 0; 255 return 0;
256 } 256 }
257 hsb->s_file_umask = (umode_t)tmp; 257 hsb->s_file_umask = (umode_t)tmp;
258 break; 258 break;
259 case opt_dir_umask: 259 case opt_dir_umask:
260 if (match_octal(&args[0], &tmp)) { 260 if (match_octal(&args[0], &tmp)) {
261 printk("HFS: dir_umask requires a value\n"); 261 printk(KERN_ERR "hfs: dir_umask requires a value\n");
262 return 0; 262 return 0;
263 } 263 }
264 hsb->s_dir_umask = (umode_t)tmp; 264 hsb->s_dir_umask = (umode_t)tmp;
265 break; 265 break;
266 case opt_part: 266 case opt_part:
267 if (match_int(&args[0], &hsb->part)) { 267 if (match_int(&args[0], &hsb->part)) {
268 printk("HFS: part requires an argument\n"); 268 printk(KERN_ERR "hfs: part requires an argument\n");
269 return 0; 269 return 0;
270 } 270 }
271 break; 271 break;
272 case opt_session: 272 case opt_session:
273 if (match_int(&args[0], &hsb->session)) { 273 if (match_int(&args[0], &hsb->session)) {
274 printk("HFS: session requires an argument\n"); 274 printk(KERN_ERR "hfs: session requires an argument\n");
275 return 0; 275 return 0;
276 } 276 }
277 break; 277 break;
278 case opt_type: 278 case opt_type:
279 if (match_fourchar(&args[0], &hsb->s_type)) { 279 if (match_fourchar(&args[0], &hsb->s_type)) {
280 printk("HFS+-fs: type requires a 4 character value\n"); 280 printk(KERN_ERR "hfs: type requires a 4 character value\n");
281 return 0; 281 return 0;
282 } 282 }
283 break; 283 break;
284 case opt_creator: 284 case opt_creator:
285 if (match_fourchar(&args[0], &hsb->s_creator)) { 285 if (match_fourchar(&args[0], &hsb->s_creator)) {
286 printk("HFS+-fs: creator requires a 4 character value\n"); 286 printk(KERN_ERR "hfs: creator requires a 4 character value\n");
287 return 0; 287 return 0;
288 } 288 }
289 break; 289 break;
@@ -292,13 +292,13 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
292 break; 292 break;
293 case opt_codepage: 293 case opt_codepage:
294 if (hsb->nls_disk) { 294 if (hsb->nls_disk) {
295 printk("HFS+-fs: unable to change codepage\n"); 295 printk(KERN_ERR "hfs: unable to change codepage\n");
296 return 0; 296 return 0;
297 } 297 }
298 p = match_strdup(&args[0]); 298 p = match_strdup(&args[0]);
299 hsb->nls_disk = load_nls(p); 299 hsb->nls_disk = load_nls(p);
300 if (!hsb->nls_disk) { 300 if (!hsb->nls_disk) {
301 printk("HFS+-fs: unable to load codepage \"%s\"\n", p); 301 printk(KERN_ERR "hfs: unable to load codepage \"%s\"\n", p);
302 kfree(p); 302 kfree(p);
303 return 0; 303 return 0;
304 } 304 }
@@ -306,13 +306,13 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
306 break; 306 break;
307 case opt_iocharset: 307 case opt_iocharset:
308 if (hsb->nls_io) { 308 if (hsb->nls_io) {
309 printk("HFS: unable to change iocharset\n"); 309 printk(KERN_ERR "hfs: unable to change iocharset\n");
310 return 0; 310 return 0;
311 } 311 }
312 p = match_strdup(&args[0]); 312 p = match_strdup(&args[0]);
313 hsb->nls_io = load_nls(p); 313 hsb->nls_io = load_nls(p);
314 if (!hsb->nls_io) { 314 if (!hsb->nls_io) {
315 printk("HFS: unable to load iocharset \"%s\"\n", p); 315 printk(KERN_ERR "hfs: unable to load iocharset \"%s\"\n", p);
316 kfree(p); 316 kfree(p);
317 return 0; 317 return 0;
318 } 318 }
@@ -326,7 +326,7 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
326 if (hsb->nls_disk && !hsb->nls_io) { 326 if (hsb->nls_disk && !hsb->nls_io) {
327 hsb->nls_io = load_nls_default(); 327 hsb->nls_io = load_nls_default();
328 if (!hsb->nls_io) { 328 if (!hsb->nls_io) {
329 printk("HFS: unable to load default iocharset\n"); 329 printk(KERN_ERR "hfs: unable to load default iocharset\n");
330 return 0; 330 return 0;
331 } 331 }
332 } 332 }
@@ -364,7 +364,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
364 364
365 res = -EINVAL; 365 res = -EINVAL;
366 if (!parse_options((char *)data, sbi)) { 366 if (!parse_options((char *)data, sbi)) {
367 hfs_warn("hfs_fs: unable to parse mount options.\n"); 367 printk(KERN_ERR "hfs: unable to parse mount options.\n");
368 goto bail; 368 goto bail;
369 } 369 }
370 370
@@ -375,7 +375,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
375 res = hfs_mdb_get(sb); 375 res = hfs_mdb_get(sb);
376 if (res) { 376 if (res) {
377 if (!silent) 377 if (!silent)
378 hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n", 378 printk(KERN_WARNING "hfs: can't find a HFS filesystem on dev %s.\n",
379 hfs_mdb_name(sb)); 379 hfs_mdb_name(sb));
380 res = -EINVAL; 380 res = -EINVAL;
381 goto bail; 381 goto bail;
@@ -407,7 +407,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
407bail_iput: 407bail_iput:
408 iput(root_inode); 408 iput(root_inode);
409bail_no_root: 409bail_no_root:
410 hfs_warn("hfs_fs: get root inode failed.\n"); 410 printk(KERN_ERR "hfs: get root inode failed.\n");
411bail: 411bail:
412 hfs_mdb_put(sb); 412 hfs_mdb_put(sb);
413 return res; 413 return res;
@@ -454,7 +454,7 @@ static void __exit exit_hfs_fs(void)
454{ 454{
455 unregister_filesystem(&hfs_fs_type); 455 unregister_filesystem(&hfs_fs_type);
456 if (kmem_cache_destroy(hfs_inode_cachep)) 456 if (kmem_cache_destroy(hfs_inode_cachep))
457 printk(KERN_INFO "hfs_inode_cache: not all structures were freed\n"); 457 printk(KERN_ERR "hfs_inode_cache: not all structures were freed\n");
458} 458}
459 459
460module_init(init_hfs_fs) 460module_init(init_hfs_fs)
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index 257cdde0514b..5007a41f1be9 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -64,7 +64,6 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
64 else 64 else
65 e = rec - 1; 65 e = rec - 1;
66 } while (b <= e); 66 } while (b <= e);
67 //printk("%d: %d,%d,%d\n", bnode->this, b, e, rec);
68 if (rec != e && e >= 0) { 67 if (rec != e && e >= 0) {
69 len = hfs_brec_lenoff(bnode, e, &off); 68 len = hfs_brec_lenoff(bnode, e, &off);
70 keylen = hfs_brec_keylen(bnode, e); 69 keylen = hfs_brec_keylen(bnode, e);
@@ -127,7 +126,7 @@ int hfs_brec_find(struct hfs_find_data *fd)
127 return res; 126 return res;
128 127
129invalid: 128invalid:
130 printk("HFS+-fs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n", 129 printk(KERN_ERR "hfs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
131 height, bnode->height, bnode->type, nidx, parent); 130 height, bnode->height, bnode->type, nidx, parent);
132 res = -EIO; 131 res = -EIO;
133release: 132release:
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 930cd9212de8..8f07e8fbd03d 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -358,7 +358,7 @@ void hfs_bnode_unlink(struct hfs_bnode *node)
358 358
359 // move down? 359 // move down?
360 if (!node->prev && !node->next) { 360 if (!node->prev && !node->next) {
361 printk("hfs_btree_del_level\n"); 361 printk(KERN_DEBUG "hfs_btree_del_level\n");
362 } 362 }
363 if (!node->parent) { 363 if (!node->parent) {
364 tree->root = 0; 364 tree->root = 0;
@@ -379,7 +379,7 @@ struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid)
379 struct hfs_bnode *node; 379 struct hfs_bnode *node;
380 380
381 if (cnid >= tree->node_count) { 381 if (cnid >= tree->node_count) {
382 printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid); 382 printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
383 return NULL; 383 return NULL;
384 } 384 }
385 385
@@ -402,7 +402,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
402 loff_t off; 402 loff_t off;
403 403
404 if (cnid >= tree->node_count) { 404 if (cnid >= tree->node_count) {
405 printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid); 405 printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
406 return NULL; 406 return NULL;
407 } 407 }
408 408
@@ -576,8 +576,9 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
576 node = hfs_bnode_findhash(tree, num); 576 node = hfs_bnode_findhash(tree, num);
577 spin_unlock(&tree->hash_lock); 577 spin_unlock(&tree->hash_lock);
578 if (node) { 578 if (node) {
579 printk("new node %u already hashed?\n", num); 579 printk(KERN_CRIT "new node %u already hashed?\n", num);
580 BUG(); 580 WARN_ON(1);
581 return node;
581 } 582 }
582 node = __hfs_bnode_create(tree, num); 583 node = __hfs_bnode_create(tree, num);
583 if (!node) 584 if (!node)
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
index 0ccef2ab790c..c88e5d72a402 100644
--- a/fs/hfsplus/brec.c
+++ b/fs/hfsplus/brec.c
@@ -360,7 +360,7 @@ again:
360 end_off = hfs_bnode_read_u16(parent, end_rec_off); 360 end_off = hfs_bnode_read_u16(parent, end_rec_off);
361 if (end_rec_off - end_off < diff) { 361 if (end_rec_off - end_off < diff) {
362 362
363 printk("splitting index node...\n"); 363 printk(KERN_DEBUG "hfs: splitting index node...\n");
364 fd->bnode = parent; 364 fd->bnode = parent;
365 new_node = hfs_bnode_split(fd); 365 new_node = hfs_bnode_split(fd);
366 if (IS_ERR(new_node)) 366 if (IS_ERR(new_node))
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index 44326aa2bd34..a67edfa34e9e 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -31,17 +31,8 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
31 31
32 init_MUTEX(&tree->tree_lock); 32 init_MUTEX(&tree->tree_lock);
33 spin_lock_init(&tree->hash_lock); 33 spin_lock_init(&tree->hash_lock);
34 /* Set the correct compare function */
35 tree->sb = sb; 34 tree->sb = sb;
36 tree->cnid = id; 35 tree->cnid = id;
37 if (id == HFSPLUS_EXT_CNID) {
38 tree->keycmp = hfsplus_ext_cmp_key;
39 } else if (id == HFSPLUS_CAT_CNID) {
40 tree->keycmp = hfsplus_cat_cmp_key;
41 } else {
42 printk("HFS+-fs: unknown B*Tree requested\n");
43 goto free_tree;
44 }
45 tree->inode = iget(sb, id); 36 tree->inode = iget(sb, id);
46 if (!tree->inode) 37 if (!tree->inode)
47 goto free_tree; 38 goto free_tree;
@@ -64,6 +55,20 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
64 tree->max_key_len = be16_to_cpu(head->max_key_len); 55 tree->max_key_len = be16_to_cpu(head->max_key_len);
65 tree->depth = be16_to_cpu(head->depth); 56 tree->depth = be16_to_cpu(head->depth);
66 57
58 /* Set the correct compare function */
59 if (id == HFSPLUS_EXT_CNID) {
60 tree->keycmp = hfsplus_ext_cmp_key;
61 } else if (id == HFSPLUS_CAT_CNID) {
62 if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) &&
63 (head->key_type == HFSPLUS_KEY_BINARY))
64 tree->keycmp = hfsplus_cat_bin_cmp_key;
65 else
66 tree->keycmp = hfsplus_cat_case_cmp_key;
67 } else {
68 printk(KERN_ERR "hfs: unknown B*Tree requested\n");
69 goto fail_page;
70 }
71
67 size = tree->node_size; 72 size = tree->node_size;
68 if (!size || size & (size - 1)) 73 if (!size || size & (size - 1))
69 goto fail_page; 74 goto fail_page;
@@ -99,7 +104,7 @@ void hfs_btree_close(struct hfs_btree *tree)
99 while ((node = tree->node_hash[i])) { 104 while ((node = tree->node_hash[i])) {
100 tree->node_hash[i] = node->next_hash; 105 tree->node_hash[i] = node->next_hash;
101 if (atomic_read(&node->refcnt)) 106 if (atomic_read(&node->refcnt))
102 printk("HFS+: node %d:%d still has %d user(s)!\n", 107 printk(KERN_CRIT "hfs: node %d:%d still has %d user(s)!\n",
103 node->tree->cnid, node->this, atomic_read(&node->refcnt)); 108 node->tree->cnid, node->this, atomic_read(&node->refcnt));
104 hfs_bnode_free(node); 109 hfs_bnode_free(node);
105 tree->node_hash_cnt--; 110 tree->node_hash_cnt--;
@@ -223,10 +228,6 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
223 tree->free_nodes--; 228 tree->free_nodes--;
224 mark_inode_dirty(tree->inode); 229 mark_inode_dirty(tree->inode);
225 hfs_bnode_put(node); 230 hfs_bnode_put(node);
226 if (!idx) {
227 printk("unexpected idx %u (%u)\n", idx, node->this);
228 BUG();
229 }
230 return hfs_bnode_create(tree, idx); 231 return hfs_bnode_create(tree, idx);
231 } 232 }
232 } 233 }
@@ -242,7 +243,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
242 kunmap(*pagep); 243 kunmap(*pagep);
243 nidx = node->next; 244 nidx = node->next;
244 if (!nidx) { 245 if (!nidx) {
245 printk("create new bmap node...\n"); 246 printk(KERN_DEBUG "hfs: create new bmap node...\n");
246 next_node = hfs_bmap_new_bmap(node, idx); 247 next_node = hfs_bmap_new_bmap(node, idx);
247 } else 248 } else
248 next_node = hfs_bnode_find(tree, nidx); 249 next_node = hfs_bnode_find(tree, nidx);
@@ -284,7 +285,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
284 hfs_bnode_put(node); 285 hfs_bnode_put(node);
285 if (!i) { 286 if (!i) {
286 /* panic */; 287 /* panic */;
287 printk("HFS: unable to free bnode %u. bmap not found!\n", node->this); 288 printk(KERN_CRIT "hfs: unable to free bnode %u. bmap not found!\n", node->this);
288 return; 289 return;
289 } 290 }
290 node = hfs_bnode_find(tree, i); 291 node = hfs_bnode_find(tree, i);
@@ -292,7 +293,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
292 return; 293 return;
293 if (node->type != HFS_NODE_MAP) { 294 if (node->type != HFS_NODE_MAP) {
294 /* panic */; 295 /* panic */;
295 printk("HFS: invalid bmap found! (%u,%d)\n", node->this, node->type); 296 printk(KERN_CRIT "hfs: invalid bmap found! (%u,%d)\n", node->this, node->type);
296 hfs_bnode_put(node); 297 hfs_bnode_put(node);
297 return; 298 return;
298 } 299 }
@@ -305,7 +306,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
305 m = 1 << (~nidx & 7); 306 m = 1 << (~nidx & 7);
306 byte = data[off]; 307 byte = data[off];
307 if (!(byte & m)) { 308 if (!(byte & m)) {
308 printk("HFS: trying to free free bnode %u(%d)\n", node->this, node->type); 309 printk(KERN_CRIT "hfs: trying to free free bnode %u(%d)\n", node->this, node->type);
309 kunmap(page); 310 kunmap(page);
310 hfs_bnode_put(node); 311 hfs_bnode_put(node);
311 return; 312 return;
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 94712790c8b3..f2d7c49ce759 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -13,7 +13,8 @@
13#include "hfsplus_fs.h" 13#include "hfsplus_fs.h"
14#include "hfsplus_raw.h" 14#include "hfsplus_raw.h"
15 15
16int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2) 16int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *k1,
17 const hfsplus_btree_key *k2)
17{ 18{
18 __be32 k1p, k2p; 19 __be32 k1p, k2p;
19 20
@@ -22,7 +23,20 @@ int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
22 if (k1p != k2p) 23 if (k1p != k2p)
23 return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1; 24 return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1;
24 25
25 return hfsplus_unistrcmp(&k1->cat.name, &k2->cat.name); 26 return hfsplus_strcasecmp(&k1->cat.name, &k2->cat.name);
27}
28
29int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *k1,
30 const hfsplus_btree_key *k2)
31{
32 __be32 k1p, k2p;
33
34 k1p = k1->cat.parent;
35 k2p = k2->cat.parent;
36 if (k1p != k2p)
37 return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1;
38
39 return hfsplus_strcmp(&k1->cat.name, &k2->cat.name);
26} 40}
27 41
28void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key, 42void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key,
@@ -80,8 +94,11 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
80 memset(folder, 0, sizeof(*folder)); 94 memset(folder, 0, sizeof(*folder));
81 folder->type = cpu_to_be16(HFSPLUS_FOLDER); 95 folder->type = cpu_to_be16(HFSPLUS_FOLDER);
82 folder->id = cpu_to_be32(inode->i_ino); 96 folder->id = cpu_to_be32(inode->i_ino);
83 folder->create_date = folder->content_mod_date = 97 HFSPLUS_I(inode).create_date =
84 folder->attribute_mod_date = folder->access_date = hfsp_now2mt(); 98 folder->create_date =
99 folder->content_mod_date =
100 folder->attribute_mod_date =
101 folder->access_date = hfsp_now2mt();
85 hfsplus_set_perms(inode, &folder->permissions); 102 hfsplus_set_perms(inode, &folder->permissions);
86 if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir) 103 if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir)
87 /* invisible and namelocked */ 104 /* invisible and namelocked */
@@ -95,18 +112,27 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
95 file->type = cpu_to_be16(HFSPLUS_FILE); 112 file->type = cpu_to_be16(HFSPLUS_FILE);
96 file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS); 113 file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS);
97 file->id = cpu_to_be32(cnid); 114 file->id = cpu_to_be32(cnid);
98 file->create_date = file->content_mod_date = 115 HFSPLUS_I(inode).create_date =
99 file->attribute_mod_date = file->access_date = hfsp_now2mt(); 116 file->create_date =
117 file->content_mod_date =
118 file->attribute_mod_date =
119 file->access_date = hfsp_now2mt();
100 if (cnid == inode->i_ino) { 120 if (cnid == inode->i_ino) {
101 hfsplus_set_perms(inode, &file->permissions); 121 hfsplus_set_perms(inode, &file->permissions);
102 file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type); 122 if (S_ISLNK(inode->i_mode)) {
103 file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator); 123 file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE);
124 file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR);
125 } else {
126 file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type);
127 file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator);
128 }
104 if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) 129 if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
105 file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); 130 file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
106 } else { 131 } else {
107 file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE); 132 file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE);
108 file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR); 133 file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR);
109 file->user_info.fdFlags = cpu_to_be16(0x100); 134 file->user_info.fdFlags = cpu_to_be16(0x100);
135 file->create_date = HFSPLUS_I(HFSPLUS_SB(inode->i_sb).hidden_dir).create_date;
110 file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev); 136 file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev);
111 } 137 }
112 return sizeof(*file); 138 return sizeof(*file);
@@ -139,7 +165,7 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,
139 165
140 type = be16_to_cpu(tmp.type); 166 type = be16_to_cpu(tmp.type);
141 if (type != HFSPLUS_FOLDER_THREAD && type != HFSPLUS_FILE_THREAD) { 167 if (type != HFSPLUS_FOLDER_THREAD && type != HFSPLUS_FILE_THREAD) {
142 printk("HFS+-fs: Found bad thread record in catalog\n"); 168 printk(KERN_ERR "hfs: found bad thread record in catalog\n");
143 return -EIO; 169 return -EIO;
144 } 170 }
145 171
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 50c8f44b6c66..01a6fe3a395c 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -66,25 +66,32 @@ again:
66 } 66 }
67 cnid = be32_to_cpu(entry.file.id); 67 cnid = be32_to_cpu(entry.file.id);
68 if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && 68 if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) &&
69 entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR)) { 69 entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) &&
70 (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date ||
71 entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) &&
72 HFSPLUS_SB(sb).hidden_dir) {
70 struct qstr str; 73 struct qstr str;
71 char name[32]; 74 char name[32];
72 75
73 if (dentry->d_fsdata) { 76 if (dentry->d_fsdata) {
74 err = -ENOENT; 77 /*
75 inode = NULL; 78 * We found a link pointing to another link,
76 goto out; 79 * so ignore it and treat it as regular file.
80 */
81 cnid = (unsigned long)dentry->d_fsdata;
82 linkid = 0;
83 } else {
84 dentry->d_fsdata = (void *)(unsigned long)cnid;
85 linkid = be32_to_cpu(entry.file.permissions.dev);
86 str.len = sprintf(name, "iNode%d", linkid);
87 str.name = name;
88 hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
89 goto again;
77 } 90 }
78 dentry->d_fsdata = (void *)(unsigned long)cnid;
79 linkid = be32_to_cpu(entry.file.permissions.dev);
80 str.len = sprintf(name, "iNode%d", linkid);
81 str.name = name;
82 hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
83 goto again;
84 } else if (!dentry->d_fsdata) 91 } else if (!dentry->d_fsdata)
85 dentry->d_fsdata = (void *)(unsigned long)cnid; 92 dentry->d_fsdata = (void *)(unsigned long)cnid;
86 } else { 93 } else {
87 printk("HFS+-fs: Illegal catalog entry type in lookup\n"); 94 printk(KERN_ERR "hfs: invalid catalog entry type in lookup\n");
88 err = -EIO; 95 err = -EIO;
89 goto fail; 96 goto fail;
90 } 97 }
@@ -132,12 +139,12 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
132 case 1: 139 case 1:
133 hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); 140 hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
134 if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) { 141 if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) {
135 printk("HFS+-fs: bad catalog folder thread\n"); 142 printk(KERN_ERR "hfs: bad catalog folder thread\n");
136 err = -EIO; 143 err = -EIO;
137 goto out; 144 goto out;
138 } 145 }
139 if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) { 146 if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) {
140 printk("HFS+-fs: truncated catalog thread\n"); 147 printk(KERN_ERR "hfs: truncated catalog thread\n");
141 err = -EIO; 148 err = -EIO;
142 goto out; 149 goto out;
143 } 150 }
@@ -156,7 +163,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
156 163
157 for (;;) { 164 for (;;) {
158 if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) { 165 if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) {
159 printk("HFS+-fs: walked past end of dir\n"); 166 printk(KERN_ERR "hfs: walked past end of dir\n");
160 err = -EIO; 167 err = -EIO;
161 goto out; 168 goto out;
162 } 169 }
@@ -168,7 +175,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
168 goto out; 175 goto out;
169 if (type == HFSPLUS_FOLDER) { 176 if (type == HFSPLUS_FOLDER) {
170 if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) { 177 if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
171 printk("HFS+-fs: small dir entry\n"); 178 printk(KERN_ERR "hfs: small dir entry\n");
172 err = -EIO; 179 err = -EIO;
173 goto out; 180 goto out;
174 } 181 }
@@ -180,7 +187,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
180 break; 187 break;
181 } else if (type == HFSPLUS_FILE) { 188 } else if (type == HFSPLUS_FILE) {
182 if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { 189 if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
183 printk("HFS+-fs: small file entry\n"); 190 printk(KERN_ERR "hfs: small file entry\n");
184 err = -EIO; 191 err = -EIO;
185 goto out; 192 goto out;
186 } 193 }
@@ -188,7 +195,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
188 be32_to_cpu(entry.file.id), DT_REG)) 195 be32_to_cpu(entry.file.id), DT_REG))
189 break; 196 break;
190 } else { 197 } else {
191 printk("HFS+-fs: bad catalog entry type\n"); 198 printk(KERN_ERR "hfs: bad catalog entry type\n");
192 err = -EIO; 199 err = -EIO;
193 goto out; 200 goto out;
194 } 201 }
@@ -330,7 +337,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
330 if (res) 337 if (res)
331 return res; 338 return res;
332 339
333 inode->i_nlink--; 340 if (inode->i_nlink > 0)
341 inode->i_nlink--;
334 hfsplus_delete_inode(inode); 342 hfsplus_delete_inode(inode);
335 if (inode->i_ino != cnid && !inode->i_nlink) { 343 if (inode->i_ino != cnid && !inode->i_nlink) {
336 if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { 344 if (!atomic_read(&HFSPLUS_I(inode).opencnt)) {
@@ -339,7 +347,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
339 hfsplus_delete_inode(inode); 347 hfsplus_delete_inode(inode);
340 } else 348 } else
341 inode->i_flags |= S_DEAD; 349 inode->i_flags |= S_DEAD;
342 } 350 } else
351 inode->i_nlink = 0;
343 inode->i_ctime = CURRENT_TIME_SEC; 352 inode->i_ctime = CURRENT_TIME_SEC;
344 mark_inode_dirty(inode); 353 mark_inode_dirty(inode);
345 354
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index e3ff56a03011..1a7480089e82 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -16,7 +16,8 @@
16#include "hfsplus_raw.h" 16#include "hfsplus_raw.h"
17 17
18/* Compare two extents keys, returns 0 on same, pos/neg for difference */ 18/* Compare two extents keys, returns 0 on same, pos/neg for difference */
19int hfsplus_ext_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2) 19int hfsplus_ext_cmp_key(const hfsplus_btree_key *k1,
20 const hfsplus_btree_key *k2)
20{ 21{
21 __be32 k1id, k2id; 22 __be32 k1id, k2id;
22 __be32 k1s, k2s; 23 __be32 k1s, k2s;
@@ -349,10 +350,9 @@ int hfsplus_file_extend(struct inode *inode)
349 350
350 if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) { 351 if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) {
351 // extend alloc file 352 // extend alloc file
352 printk("extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8, 353 printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8,
353 HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks); 354 HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks);
354 return -ENOSPC; 355 return -ENOSPC;
355 //BUG();
356 } 356 }
357 357
358 down(&HFSPLUS_I(inode).extents_lock); 358 down(&HFSPLUS_I(inode).extents_lock);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 0fa1ab6250bf..7ae393637a0c 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -36,7 +36,7 @@
36#define HFSPLUS_TYPE_DATA 0x00 36#define HFSPLUS_TYPE_DATA 0x00
37#define HFSPLUS_TYPE_RSRC 0xFF 37#define HFSPLUS_TYPE_RSRC 0xFF
38 38
39typedef int (*btree_keycmp)(hfsplus_btree_key *, hfsplus_btree_key *); 39typedef int (*btree_keycmp)(const hfsplus_btree_key *, const hfsplus_btree_key *);
40 40
41#define NODE_HASH_SIZE 256 41#define NODE_HASH_SIZE 256
42 42
@@ -149,6 +149,7 @@ struct hfsplus_sb_info {
149#define HFSPLUS_SB_WRITEBACKUP 0x0001 149#define HFSPLUS_SB_WRITEBACKUP 0x0001
150#define HFSPLUS_SB_NODECOMPOSE 0x0002 150#define HFSPLUS_SB_NODECOMPOSE 0x0002
151#define HFSPLUS_SB_FORCE 0x0004 151#define HFSPLUS_SB_FORCE 0x0004
152#define HFSPLUS_SB_HFSX 0x0008
152 153
153 154
154struct hfsplus_inode_info { 155struct hfsplus_inode_info {
@@ -165,6 +166,7 @@ struct hfsplus_inode_info {
165 struct inode *rsrc_inode; 166 struct inode *rsrc_inode;
166 unsigned long flags; 167 unsigned long flags;
167 168
169 __be32 create_date;
168 /* Device number in hfsplus_permissions in catalog */ 170 /* Device number in hfsplus_permissions in catalog */
169 u32 dev; 171 u32 dev;
170 /* BSD system and user file flags */ 172 /* BSD system and user file flags */
@@ -303,7 +305,8 @@ int hfs_brec_read(struct hfs_find_data *, void *, int);
303int hfs_brec_goto(struct hfs_find_data *, int); 305int hfs_brec_goto(struct hfs_find_data *, int);
304 306
305/* catalog.c */ 307/* catalog.c */
306int hfsplus_cat_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *); 308int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
309int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
307void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *); 310void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *);
308int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *); 311int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *);
309int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *); 312int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *);
@@ -312,7 +315,7 @@ int hfsplus_rename_cat(u32, struct inode *, struct qstr *,
312 struct inode *, struct qstr *); 315 struct inode *, struct qstr *);
313 316
314/* extents.c */ 317/* extents.c */
315int hfsplus_ext_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *); 318int hfsplus_ext_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
316void hfsplus_ext_write_extent(struct inode *); 319void hfsplus_ext_write_extent(struct inode *);
317int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int); 320int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int);
318int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int); 321int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int);
@@ -350,7 +353,8 @@ extern u16 hfsplus_decompose_table[];
350extern u16 hfsplus_compose_table[]; 353extern u16 hfsplus_compose_table[];
351 354
352/* unicode.c */ 355/* unicode.c */
353int hfsplus_unistrcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *); 356int hfsplus_strcasecmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
357int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
354int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *); 358int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *);
355int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int); 359int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int);
356 360
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
index b4fbed633219..49205531a500 100644
--- a/fs/hfsplus/hfsplus_raw.h
+++ b/fs/hfsplus/hfsplus_raw.h
@@ -22,8 +22,10 @@
22#define HFSPLUS_SECTOR_SHIFT 9 22#define HFSPLUS_SECTOR_SHIFT 9
23#define HFSPLUS_VOLHEAD_SECTOR 2 23#define HFSPLUS_VOLHEAD_SECTOR 2
24#define HFSPLUS_VOLHEAD_SIG 0x482b 24#define HFSPLUS_VOLHEAD_SIG 0x482b
25#define HFSPLUS_VOLHEAD_SIGX 0x4858
25#define HFSPLUS_SUPER_MAGIC 0x482b 26#define HFSPLUS_SUPER_MAGIC 0x482b
26#define HFSPLUS_CURRENT_VERSION 4 27#define HFSPLUS_MIN_VERSION 4
28#define HFSPLUS_CURRENT_VERSION 5
27 29
28#define HFSP_WRAP_MAGIC 0x4244 30#define HFSP_WRAP_MAGIC 0x4244
29#define HFSP_WRAP_ATTRIB_SLOCK 0x8000 31#define HFSP_WRAP_ATTRIB_SLOCK 0x8000
@@ -41,6 +43,9 @@
41#define HFSP_HARDLINK_TYPE 0x686c6e6b /* 'hlnk' */ 43#define HFSP_HARDLINK_TYPE 0x686c6e6b /* 'hlnk' */
42#define HFSP_HFSPLUS_CREATOR 0x6866732b /* 'hfs+' */ 44#define HFSP_HFSPLUS_CREATOR 0x6866732b /* 'hfs+' */
43 45
46#define HFSP_SYMLINK_TYPE 0x736c6e6b /* 'slnk' */
47#define HFSP_SYMLINK_CREATOR 0x72686170 /* 'rhap' */
48
44#define HFSP_MOUNT_VERSION 0x482b4c78 /* 'H+Lx' */ 49#define HFSP_MOUNT_VERSION 0x482b4c78 /* 'H+Lx' */
45 50
46/* Structures used on disk */ 51/* Structures used on disk */
@@ -161,7 +166,7 @@ struct hfs_btree_header_rec {
161 u16 reserved1; 166 u16 reserved1;
162 __be32 clump_size; 167 __be32 clump_size;
163 u8 btree_type; 168 u8 btree_type;
164 u8 reserved2; 169 u8 key_type;
165 __be32 attributes; 170 __be32 attributes;
166 u32 reserved3[16]; 171 u32 reserved3[16];
167} __packed; 172} __packed;
@@ -186,6 +191,10 @@ struct hfs_btree_header_rec {
186#define HFSPLUS_EXCH_CNID 15 /* ExchangeFiles temp id */ 191#define HFSPLUS_EXCH_CNID 15 /* ExchangeFiles temp id */
187#define HFSPLUS_FIRSTUSER_CNID 16 /* first available user id */ 192#define HFSPLUS_FIRSTUSER_CNID 16 /* first available user id */
188 193
194/* btree key type */
195#define HFSPLUS_KEY_CASEFOLDING 0xCF /* case-insensitive */
196#define HFSPLUS_KEY_BINARY 0xBC /* case-sensitive */
197
189/* HFS+ catalog entry key */ 198/* HFS+ catalog entry key */
190struct hfsplus_cat_key { 199struct hfsplus_cat_key {
191 __be16 key_len; 200 __be16 key_len;
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 7acff6c5464f..12ed2b7d046b 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -18,13 +18,11 @@
18 18
19static int hfsplus_readpage(struct file *file, struct page *page) 19static int hfsplus_readpage(struct file *file, struct page *page)
20{ 20{
21 //printk("readpage: %lu\n", page->index);
22 return block_read_full_page(page, hfsplus_get_block); 21 return block_read_full_page(page, hfsplus_get_block);
23} 22}
24 23
25static int hfsplus_writepage(struct page *page, struct writeback_control *wbc) 24static int hfsplus_writepage(struct page *page, struct writeback_control *wbc)
26{ 25{
27 //printk("writepage: %lu\n", page->index);
28 return block_write_full_page(page, hfsplus_get_block, wbc); 26 return block_write_full_page(page, hfsplus_get_block, wbc);
29} 27}
30 28
@@ -92,7 +90,6 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
92 } while (--i && nidx < tree->node_count); 90 } while (--i && nidx < tree->node_count);
93 spin_unlock(&tree->hash_lock); 91 spin_unlock(&tree->hash_lock);
94 } 92 }
95 //printk("releasepage: %lu,%x = %d\n", page->index, mask, res);
96 return res ? try_to_free_buffers(page) : 0; 93 return res ? try_to_free_buffers(page) : 0;
97} 94}
98 95
@@ -434,7 +431,8 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
434 inode->i_size = 2 + be32_to_cpu(folder->valence); 431 inode->i_size = 2 + be32_to_cpu(folder->valence);
435 inode->i_atime = hfsp_mt2ut(folder->access_date); 432 inode->i_atime = hfsp_mt2ut(folder->access_date);
436 inode->i_mtime = hfsp_mt2ut(folder->content_mod_date); 433 inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
437 inode->i_ctime = inode->i_mtime; 434 inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
435 HFSPLUS_I(inode).create_date = folder->create_date;
438 HFSPLUS_I(inode).fs_blocks = 0; 436 HFSPLUS_I(inode).fs_blocks = 0;
439 inode->i_op = &hfsplus_dir_inode_operations; 437 inode->i_op = &hfsplus_dir_inode_operations;
440 inode->i_fop = &hfsplus_dir_operations; 438 inode->i_fop = &hfsplus_dir_operations;
@@ -465,9 +463,10 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
465 } 463 }
466 inode->i_atime = hfsp_mt2ut(file->access_date); 464 inode->i_atime = hfsp_mt2ut(file->access_date);
467 inode->i_mtime = hfsp_mt2ut(file->content_mod_date); 465 inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
468 inode->i_ctime = inode->i_mtime; 466 inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date);
467 HFSPLUS_I(inode).create_date = file->create_date;
469 } else { 468 } else {
470 printk("HFS+-fs: bad catalog entry used to create inode\n"); 469 printk(KERN_ERR "hfs: bad catalog entry used to create inode\n");
471 res = -EIO; 470 res = -EIO;
472 } 471 }
473 return res; 472 return res;
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index 935dafba0078..dc64fac00831 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -83,58 +83,58 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi)
83 switch (token) { 83 switch (token) {
84 case opt_creator: 84 case opt_creator:
85 if (match_fourchar(&args[0], &sbi->creator)) { 85 if (match_fourchar(&args[0], &sbi->creator)) {
86 printk("HFS+-fs: creator requires a 4 character value\n"); 86 printk(KERN_ERR "hfs: creator requires a 4 character value\n");
87 return 0; 87 return 0;
88 } 88 }
89 break; 89 break;
90 case opt_type: 90 case opt_type:
91 if (match_fourchar(&args[0], &sbi->type)) { 91 if (match_fourchar(&args[0], &sbi->type)) {
92 printk("HFS+-fs: type requires a 4 character value\n"); 92 printk(KERN_ERR "hfs: type requires a 4 character value\n");
93 return 0; 93 return 0;
94 } 94 }
95 break; 95 break;
96 case opt_umask: 96 case opt_umask:
97 if (match_octal(&args[0], &tmp)) { 97 if (match_octal(&args[0], &tmp)) {
98 printk("HFS+-fs: umask requires a value\n"); 98 printk(KERN_ERR "hfs: umask requires a value\n");
99 return 0; 99 return 0;
100 } 100 }
101 sbi->umask = (umode_t)tmp; 101 sbi->umask = (umode_t)tmp;
102 break; 102 break;
103 case opt_uid: 103 case opt_uid:
104 if (match_int(&args[0], &tmp)) { 104 if (match_int(&args[0], &tmp)) {
105 printk("HFS+-fs: uid requires an argument\n"); 105 printk(KERN_ERR "hfs: uid requires an argument\n");
106 return 0; 106 return 0;
107 } 107 }
108 sbi->uid = (uid_t)tmp; 108 sbi->uid = (uid_t)tmp;
109 break; 109 break;
110 case opt_gid: 110 case opt_gid:
111 if (match_int(&args[0], &tmp)) { 111 if (match_int(&args[0], &tmp)) {
112 printk("HFS+-fs: gid requires an argument\n"); 112 printk(KERN_ERR "hfs: gid requires an argument\n");
113 return 0; 113 return 0;
114 } 114 }
115 sbi->gid = (gid_t)tmp; 115 sbi->gid = (gid_t)tmp;
116 break; 116 break;
117 case opt_part: 117 case opt_part:
118 if (match_int(&args[0], &sbi->part)) { 118 if (match_int(&args[0], &sbi->part)) {
119 printk("HFS+-fs: part requires an argument\n"); 119 printk(KERN_ERR "hfs: part requires an argument\n");
120 return 0; 120 return 0;
121 } 121 }
122 break; 122 break;
123 case opt_session: 123 case opt_session:
124 if (match_int(&args[0], &sbi->session)) { 124 if (match_int(&args[0], &sbi->session)) {
125 printk("HFS+-fs: session requires an argument\n"); 125 printk(KERN_ERR "hfs: session requires an argument\n");
126 return 0; 126 return 0;
127 } 127 }
128 break; 128 break;
129 case opt_nls: 129 case opt_nls:
130 if (sbi->nls) { 130 if (sbi->nls) {
131 printk("HFS+-fs: unable to change nls mapping\n"); 131 printk(KERN_ERR "hfs: unable to change nls mapping\n");
132 return 0; 132 return 0;
133 } 133 }
134 p = match_strdup(&args[0]); 134 p = match_strdup(&args[0]);
135 sbi->nls = load_nls(p); 135 sbi->nls = load_nls(p);
136 if (!sbi->nls) { 136 if (!sbi->nls) {
137 printk("HFS+-fs: unable to load nls mapping \"%s\"\n", p); 137 printk(KERN_ERR "hfs: unable to load nls mapping \"%s\"\n", p);
138 kfree(p); 138 kfree(p);
139 return 0; 139 return 0;
140 } 140 }
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index d791780def50..7843f792a4b7 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -169,7 +169,7 @@ static void hfsplus_write_super(struct super_block *sb)
169 block = HFSPLUS_SB(sb).blockoffset; 169 block = HFSPLUS_SB(sb).blockoffset;
170 block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9); 170 block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9);
171 offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1); 171 offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1);
172 printk("backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset, 172 printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset,
173 HFSPLUS_SB(sb).sect_count, block, offset); 173 HFSPLUS_SB(sb).sect_count, block, offset);
174 bh = sb_bread(sb, block); 174 bh = sb_bread(sb, block);
175 if (bh) { 175 if (bh) {
@@ -179,7 +179,7 @@ static void hfsplus_write_super(struct super_block *sb)
179 mark_buffer_dirty(bh); 179 mark_buffer_dirty(bh);
180 brelse(bh); 180 brelse(bh);
181 } else 181 } else
182 printk("backup not found!\n"); 182 printk(KERN_WARNING "hfs: backup not found!\n");
183 } 183 }
184 } 184 }
185 HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP; 185 HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP;
@@ -240,18 +240,18 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
240 return -EINVAL; 240 return -EINVAL;
241 241
242 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { 242 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
243 printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " 243 printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, "
244 "running fsck.hfsplus is recommended. leaving read-only.\n"); 244 "running fsck.hfsplus is recommended. leaving read-only.\n");
245 sb->s_flags |= MS_RDONLY; 245 sb->s_flags |= MS_RDONLY;
246 *flags |= MS_RDONLY; 246 *flags |= MS_RDONLY;
247 } else if (sbi.flags & HFSPLUS_SB_FORCE) { 247 } else if (sbi.flags & HFSPLUS_SB_FORCE) {
248 /* nothing */ 248 /* nothing */
249 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { 249 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
250 printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n"); 250 printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n");
251 sb->s_flags |= MS_RDONLY; 251 sb->s_flags |= MS_RDONLY;
252 *flags |= MS_RDONLY; 252 *flags |= MS_RDONLY;
253 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { 253 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
254 printk("HFS+-fs: Filesystem is marked journaled, leaving read-only.\n"); 254 printk(KERN_WARNING "hfs: filesystem is marked journaled, leaving read-only.\n");
255 sb->s_flags |= MS_RDONLY; 255 sb->s_flags |= MS_RDONLY;
256 *flags |= MS_RDONLY; 256 *flags |= MS_RDONLY;
257 } 257 }
@@ -292,8 +292,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
292 INIT_HLIST_HEAD(&sbi->rsrc_inodes); 292 INIT_HLIST_HEAD(&sbi->rsrc_inodes);
293 hfsplus_fill_defaults(sbi); 293 hfsplus_fill_defaults(sbi);
294 if (!hfsplus_parse_options(data, sbi)) { 294 if (!hfsplus_parse_options(data, sbi)) {
295 if (!silent) 295 printk(KERN_ERR "hfs: unable to parse mount options\n");
296 printk("HFS+-fs: unable to parse mount options\n");
297 err = -EINVAL; 296 err = -EINVAL;
298 goto cleanup; 297 goto cleanup;
299 } 298 }
@@ -302,7 +301,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
302 nls = sbi->nls; 301 nls = sbi->nls;
303 sbi->nls = load_nls("utf8"); 302 sbi->nls = load_nls("utf8");
304 if (!sbi->nls) { 303 if (!sbi->nls) {
305 printk("HFS+: unable to load nls for utf8\n"); 304 printk(KERN_ERR "hfs: unable to load nls for utf8\n");
306 err = -EINVAL; 305 err = -EINVAL;
307 goto cleanup; 306 goto cleanup;
308 } 307 }
@@ -310,17 +309,17 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
310 /* Grab the volume header */ 309 /* Grab the volume header */
311 if (hfsplus_read_wrapper(sb)) { 310 if (hfsplus_read_wrapper(sb)) {
312 if (!silent) 311 if (!silent)
313 printk("HFS+-fs: unable to find HFS+ superblock\n"); 312 printk(KERN_WARNING "hfs: unable to find HFS+ superblock\n");
314 err = -EINVAL; 313 err = -EINVAL;
315 goto cleanup; 314 goto cleanup;
316 } 315 }
317 vhdr = HFSPLUS_SB(sb).s_vhdr; 316 vhdr = HFSPLUS_SB(sb).s_vhdr;
318 317
319 /* Copy parts of the volume header into the superblock */ 318 /* Copy parts of the volume header into the superblock */
320 sb->s_magic = be16_to_cpu(vhdr->signature); 319 sb->s_magic = HFSPLUS_VOLHEAD_SIG;
321 if (be16_to_cpu(vhdr->version) != HFSPLUS_CURRENT_VERSION) { 320 if (be16_to_cpu(vhdr->version) < HFSPLUS_MIN_VERSION ||
322 if (!silent) 321 be16_to_cpu(vhdr->version) > HFSPLUS_CURRENT_VERSION) {
323 printk("HFS+-fs: wrong filesystem version\n"); 322 printk(KERN_ERR "hfs: wrong filesystem version\n");
324 goto cleanup; 323 goto cleanup;
325 } 324 }
326 HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks); 325 HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks);
@@ -341,20 +340,17 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
341 sb->s_maxbytes = MAX_LFS_FILESIZE; 340 sb->s_maxbytes = MAX_LFS_FILESIZE;
342 341
343 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { 342 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
344 if (!silent) 343 printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, "
345 printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " 344 "running fsck.hfsplus is recommended. mounting read-only.\n");
346 "running fsck.hfsplus is recommended. mounting read-only.\n");
347 sb->s_flags |= MS_RDONLY; 345 sb->s_flags |= MS_RDONLY;
348 } else if (sbi->flags & HFSPLUS_SB_FORCE) { 346 } else if (sbi->flags & HFSPLUS_SB_FORCE) {
349 /* nothing */ 347 /* nothing */
350 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { 348 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
351 if (!silent) 349 printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n");
352 printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n");
353 sb->s_flags |= MS_RDONLY; 350 sb->s_flags |= MS_RDONLY;
354 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { 351 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
355 if (!silent) 352 printk(KERN_WARNING "hfs: write access to a jounaled filesystem is not supported, "
356 printk("HFS+-fs: write access to a jounaled filesystem is not supported, " 353 "use the force option at your own risk, mounting read-only.\n");
357 "use the force option at your own risk, mounting read-only.\n");
358 sb->s_flags |= MS_RDONLY; 354 sb->s_flags |= MS_RDONLY;
359 } 355 }
360 sbi->flags &= ~HFSPLUS_SB_FORCE; 356 sbi->flags &= ~HFSPLUS_SB_FORCE;
@@ -362,21 +358,18 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
362 /* Load metadata objects (B*Trees) */ 358 /* Load metadata objects (B*Trees) */
363 HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); 359 HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);
364 if (!HFSPLUS_SB(sb).ext_tree) { 360 if (!HFSPLUS_SB(sb).ext_tree) {
365 if (!silent) 361 printk(KERN_ERR "hfs: failed to load extents file\n");
366 printk("HFS+-fs: failed to load extents file\n");
367 goto cleanup; 362 goto cleanup;
368 } 363 }
369 HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); 364 HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID);
370 if (!HFSPLUS_SB(sb).cat_tree) { 365 if (!HFSPLUS_SB(sb).cat_tree) {
371 if (!silent) 366 printk(KERN_ERR "hfs: failed to load catalog file\n");
372 printk("HFS+-fs: failed to load catalog file\n");
373 goto cleanup; 367 goto cleanup;
374 } 368 }
375 369
376 HFSPLUS_SB(sb).alloc_file = iget(sb, HFSPLUS_ALLOC_CNID); 370 HFSPLUS_SB(sb).alloc_file = iget(sb, HFSPLUS_ALLOC_CNID);
377 if (!HFSPLUS_SB(sb).alloc_file) { 371 if (!HFSPLUS_SB(sb).alloc_file) {
378 if (!silent) 372 printk(KERN_ERR "hfs: failed to load allocation file\n");
379 printk("HFS+-fs: failed to load allocation file\n");
380 goto cleanup; 373 goto cleanup;
381 } 374 }
382 375
@@ -384,8 +377,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
384 root = iget(sb, HFSPLUS_ROOT_CNID); 377 root = iget(sb, HFSPLUS_ROOT_CNID);
385 sb->s_root = d_alloc_root(root); 378 sb->s_root = d_alloc_root(root);
386 if (!sb->s_root) { 379 if (!sb->s_root) {
387 if (!silent) 380 printk(KERN_ERR "hfs: failed to load root directory\n");
388 printk("HFS+-fs: failed to load root directory\n");
389 iput(root); 381 iput(root);
390 goto cleanup; 382 goto cleanup;
391 } 383 }
@@ -419,7 +411,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
419 sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh); 411 sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh);
420 412
421 if (!HFSPLUS_SB(sb).hidden_dir) { 413 if (!HFSPLUS_SB(sb).hidden_dir) {
422 printk("HFS+: create hidden dir...\n"); 414 printk(KERN_DEBUG "hfs: create hidden dir...\n");
423 HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR); 415 HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR);
424 hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode, 416 hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode,
425 &str, HFSPLUS_SB(sb).hidden_dir); 417 &str, HFSPLUS_SB(sb).hidden_dir);
@@ -499,7 +491,7 @@ static void __exit exit_hfsplus_fs(void)
499{ 491{
500 unregister_filesystem(&hfsplus_fs_type); 492 unregister_filesystem(&hfsplus_fs_type);
501 if (kmem_cache_destroy(hfsplus_inode_cachep)) 493 if (kmem_cache_destroy(hfsplus_inode_cachep))
502 printk(KERN_INFO "hfsplus_inode_cache: not all structures were freed\n"); 494 printk(KERN_ERR "hfsplus_inode_cache: not all structures were freed\n");
503} 495}
504 496
505module_init(init_hfsplus_fs) 497module_init(init_hfsplus_fs)
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index 060c69048c3d..689c8bd721fb 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -28,7 +28,8 @@ static inline u16 case_fold(u16 c)
28} 28}
29 29
30/* Compare unicode strings, return values like normal strcmp */ 30/* Compare unicode strings, return values like normal strcmp */
31int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unistr *s2) 31int hfsplus_strcasecmp(const struct hfsplus_unistr *s1,
32 const struct hfsplus_unistr *s2)
32{ 33{
33 u16 len1, len2, c1, c2; 34 u16 len1, len2, c1, c2;
34 const hfsplus_unichr *p1, *p2; 35 const hfsplus_unichr *p1, *p2;
@@ -59,6 +60,33 @@ int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unis
59 } 60 }
60} 61}
61 62
63/* Compare names as a sequence of 16-bit unsigned integers */
64int hfsplus_strcmp(const struct hfsplus_unistr *s1,
65 const struct hfsplus_unistr *s2)
66{
67 u16 len1, len2, c1, c2;
68 const hfsplus_unichr *p1, *p2;
69 int len;
70
71 len1 = be16_to_cpu(s1->length);
72 len2 = be16_to_cpu(s2->length);
73 p1 = s1->unicode;
74 p2 = s2->unicode;
75
76 for (len = min(len1, len2); len > 0; len--) {
77 c1 = be16_to_cpu(*p1);
78 c2 = be16_to_cpu(*p2);
79 if (c1 != c2)
80 return c1 < c2 ? -1 : 1;
81 p1++;
82 p2++;
83 }
84
85 return len1 < len2 ? -1 :
86 len1 > len2 ? 1 : 0;
87}
88
89
62#define Hangul_SBase 0xac00 90#define Hangul_SBase 0xac00
63#define Hangul_LBase 0x1100 91#define Hangul_LBase 0x1100
64#define Hangul_VBase 0x1161 92#define Hangul_VBase 0x1161
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
index 95455e839231..72cab78f0509 100644
--- a/fs/hfsplus/wrapper.c
+++ b/fs/hfsplus/wrapper.c
@@ -28,8 +28,11 @@ static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd)
28{ 28{
29 u32 extent; 29 u32 extent;
30 u16 attrib; 30 u16 attrib;
31 __be16 sig;
31 32
32 if (be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG) 33 sig = *(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG);
34 if (sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIG) &&
35 sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIGX))
33 return 0; 36 return 0;
34 37
35 attrib = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ATTRIB)); 38 attrib = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ATTRIB));
@@ -70,7 +73,7 @@ static int hfsplus_get_last_session(struct super_block *sb,
70 *start = (sector_t)te.cdte_addr.lba << 2; 73 *start = (sector_t)te.cdte_addr.lba << 2;
71 return 0; 74 return 0;
72 } 75 }
73 printk(KERN_ERR "HFS: Invalid session number or type of track\n"); 76 printk(KERN_ERR "hfs: invalid session number or type of track\n");
74 return -EINVAL; 77 return -EINVAL;
75 } 78 }
76 ms_info.addr_format = CDROM_LBA; 79 ms_info.addr_format = CDROM_LBA;
@@ -114,6 +117,10 @@ int hfsplus_read_wrapper(struct super_block *sb)
114 } 117 }
115 if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) 118 if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG))
116 break; 119 break;
120 if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) {
121 HFSPLUS_SB(sb).flags |= HFSPLUS_SB_HFSX;
122 break;
123 }
117 brelse(bh); 124 brelse(bh);
118 125
119 /* check for a partition block 126 /* check for a partition block
@@ -143,7 +150,7 @@ int hfsplus_read_wrapper(struct super_block *sb)
143 blocksize >>= 1; 150 blocksize >>= 1;
144 151
145 if (sb_set_blocksize(sb, blocksize) != blocksize) { 152 if (sb_set_blocksize(sb, blocksize) != blocksize) {
146 printk("HFS+: unable to blocksize to %u!\n", blocksize); 153 printk(KERN_ERR "hfs: unable to set blocksize to %u!\n", blocksize);
147 return -EINVAL; 154 return -EINVAL;
148 } 155 }
149 156
@@ -158,7 +165,9 @@ int hfsplus_read_wrapper(struct super_block *sb)
158 return -EIO; 165 return -EIO;
159 166
160 /* should still be the same... */ 167 /* should still be the same... */
161 if (be16_to_cpu(vhdr->signature) != HFSPLUS_VOLHEAD_SIG) 168 if (vhdr->signature != (HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX ?
169 cpu_to_be16(HFSPLUS_VOLHEAD_SIGX) :
170 cpu_to_be16(HFSPLUS_VOLHEAD_SIG)))
162 goto error; 171 goto error;
163 HFSPLUS_SB(sb).s_vhbh = bh; 172 HFSPLUS_SB(sb).s_vhbh = bh;
164 HFSPLUS_SB(sb).s_vhdr = vhdr; 173 HFSPLUS_SB(sb).s_vhdr = vhdr;
diff --git a/fs/inotify.c b/fs/inotify.c
index 2fecb7af4a77..878ccca61213 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -33,6 +33,7 @@
33#include <linux/list.h> 33#include <linux/list.h>
34#include <linux/writeback.h> 34#include <linux/writeback.h>
35#include <linux/inotify.h> 35#include <linux/inotify.h>
36#include <linux/syscalls.h>
36 37
37#include <asm/ioctls.h> 38#include <asm/ioctls.h>
38 39
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
index cb3cef525c3b..e6265a0b56b8 100644
--- a/fs/jbd/checkpoint.c
+++ b/fs/jbd/checkpoint.c
@@ -338,7 +338,7 @@ restart:
338 * done (maybe it's a new transaction, but it fell at the same 338 * done (maybe it's a new transaction, but it fell at the same
339 * address). 339 * address).
340 */ 340 */
341 if (journal->j_checkpoint_transactions == transaction || 341 if (journal->j_checkpoint_transactions == transaction &&
342 transaction->t_tid == this_tid) { 342 transaction->t_tid == this_tid) {
343 int batch_count = 0; 343 int batch_count = 0;
344 struct buffer_head *bhs[NR_BATCH]; 344 struct buffer_head *bhs[NR_BATCH];
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 002ad2bbc769..29e62d98bae6 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -829,7 +829,8 @@ restart_loop:
829 journal->j_committing_transaction = NULL; 829 journal->j_committing_transaction = NULL;
830 spin_unlock(&journal->j_state_lock); 830 spin_unlock(&journal->j_state_lock);
831 831
832 if (commit_transaction->t_checkpoint_list == NULL) { 832 if (commit_transaction->t_checkpoint_list == NULL &&
833 commit_transaction->t_checkpoint_io_list == NULL) {
833 __journal_drop_transaction(journal, commit_transaction); 834 __journal_drop_transaction(journal, commit_transaction);
834 } else { 835 } else {
835 if (journal->j_checkpoint_transactions == NULL) { 836 if (journal->j_checkpoint_transactions == NULL) {
diff --git a/fs/namei.c b/fs/namei.c
index 33fb5bd34a81..4acdac043b6b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -30,6 +30,8 @@
30#include <linux/audit.h> 30#include <linux/audit.h>
31#include <linux/capability.h> 31#include <linux/capability.h>
32#include <linux/file.h> 32#include <linux/file.h>
33#include <linux/fcntl.h>
34#include <linux/namei.h>
33#include <asm/namei.h> 35#include <asm/namei.h>
34#include <asm/uaccess.h> 36#include <asm/uaccess.h>
35 37
@@ -1063,7 +1065,8 @@ set_it:
1063} 1065}
1064 1066
1065/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ 1067/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
1066int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd) 1068static int fastcall do_path_lookup(int dfd, const char *name,
1069 unsigned int flags, struct nameidata *nd)
1067{ 1070{
1068 int retval = 0; 1071 int retval = 0;
1069 1072
@@ -1083,9 +1086,38 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata
1083 } 1086 }
1084 nd->mnt = mntget(current->fs->rootmnt); 1087 nd->mnt = mntget(current->fs->rootmnt);
1085 nd->dentry = dget(current->fs->root); 1088 nd->dentry = dget(current->fs->root);
1086 } else { 1089 } else if (dfd == AT_FDCWD) {
1087 nd->mnt = mntget(current->fs->pwdmnt); 1090 nd->mnt = mntget(current->fs->pwdmnt);
1088 nd->dentry = dget(current->fs->pwd); 1091 nd->dentry = dget(current->fs->pwd);
1092 } else {
1093 struct file *file;
1094 int fput_needed;
1095 struct dentry *dentry;
1096
1097 file = fget_light(dfd, &fput_needed);
1098 if (!file) {
1099 retval = -EBADF;
1100 goto out_fail;
1101 }
1102
1103 dentry = file->f_dentry;
1104
1105 if (!S_ISDIR(dentry->d_inode->i_mode)) {
1106 retval = -ENOTDIR;
1107 fput_light(file, fput_needed);
1108 goto out_fail;
1109 }
1110
1111 retval = file_permission(file, MAY_EXEC);
1112 if (retval) {
1113 fput_light(file, fput_needed);
1114 goto out_fail;
1115 }
1116
1117 nd->mnt = mntget(file->f_vfsmnt);
1118 nd->dentry = dget(dentry);
1119
1120 fput_light(file, fput_needed);
1089 } 1121 }
1090 read_unlock(&current->fs->lock); 1122 read_unlock(&current->fs->lock);
1091 current->total_link_count = 0; 1123 current->total_link_count = 0;
@@ -1094,11 +1126,19 @@ out:
1094 if (unlikely(current->audit_context 1126 if (unlikely(current->audit_context
1095 && nd && nd->dentry && nd->dentry->d_inode)) 1127 && nd && nd->dentry && nd->dentry->d_inode))
1096 audit_inode(name, nd->dentry->d_inode, flags); 1128 audit_inode(name, nd->dentry->d_inode, flags);
1129out_fail:
1097 return retval; 1130 return retval;
1098} 1131}
1099 1132
1100static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags, 1133int fastcall path_lookup(const char *name, unsigned int flags,
1101 struct nameidata *nd, int open_flags, int create_mode) 1134 struct nameidata *nd)
1135{
1136 return do_path_lookup(AT_FDCWD, name, flags, nd);
1137}
1138
1139static int __path_lookup_intent_open(int dfd, const char *name,
1140 unsigned int lookup_flags, struct nameidata *nd,
1141 int open_flags, int create_mode)
1102{ 1142{
1103 struct file *filp = get_empty_filp(); 1143 struct file *filp = get_empty_filp();
1104 int err; 1144 int err;
@@ -1108,7 +1148,7 @@ static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags
1108 nd->intent.open.file = filp; 1148 nd->intent.open.file = filp;
1109 nd->intent.open.flags = open_flags; 1149 nd->intent.open.flags = open_flags;
1110 nd->intent.open.create_mode = create_mode; 1150 nd->intent.open.create_mode = create_mode;
1111 err = path_lookup(name, lookup_flags|LOOKUP_OPEN, nd); 1151 err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd);
1112 if (IS_ERR(nd->intent.open.file)) { 1152 if (IS_ERR(nd->intent.open.file)) {
1113 if (err == 0) { 1153 if (err == 0) {
1114 err = PTR_ERR(nd->intent.open.file); 1154 err = PTR_ERR(nd->intent.open.file);
@@ -1126,10 +1166,10 @@ static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags
1126 * @nd: pointer to nameidata 1166 * @nd: pointer to nameidata
1127 * @open_flags: open intent flags 1167 * @open_flags: open intent flags
1128 */ 1168 */
1129int path_lookup_open(const char *name, unsigned int lookup_flags, 1169int path_lookup_open(int dfd, const char *name, unsigned int lookup_flags,
1130 struct nameidata *nd, int open_flags) 1170 struct nameidata *nd, int open_flags)
1131{ 1171{
1132 return __path_lookup_intent_open(name, lookup_flags, nd, 1172 return __path_lookup_intent_open(dfd, name, lookup_flags, nd,
1133 open_flags, 0); 1173 open_flags, 0);
1134} 1174}
1135 1175
@@ -1141,12 +1181,12 @@ int path_lookup_open(const char *name, unsigned int lookup_flags,
1141 * @open_flags: open intent flags 1181 * @open_flags: open intent flags
1142 * @create_mode: create intent flags 1182 * @create_mode: create intent flags
1143 */ 1183 */
1144static int path_lookup_create(const char *name, unsigned int lookup_flags, 1184static int path_lookup_create(int dfd, const char *name,
1145 struct nameidata *nd, int open_flags, 1185 unsigned int lookup_flags, struct nameidata *nd,
1146 int create_mode) 1186 int open_flags, int create_mode)
1147{ 1187{
1148 return __path_lookup_intent_open(name, lookup_flags|LOOKUP_CREATE, nd, 1188 return __path_lookup_intent_open(dfd, name, lookup_flags|LOOKUP_CREATE,
1149 open_flags, create_mode); 1189 nd, open_flags, create_mode);
1150} 1190}
1151 1191
1152int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags, 1192int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
@@ -1156,7 +1196,7 @@ int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
1156 int err = PTR_ERR(tmp); 1196 int err = PTR_ERR(tmp);
1157 1197
1158 if (!IS_ERR(tmp)) { 1198 if (!IS_ERR(tmp)) {
1159 err = __path_lookup_intent_open(tmp, lookup_flags, nd, open_flags, 0); 1199 err = __path_lookup_intent_open(AT_FDCWD, tmp, lookup_flags, nd, open_flags, 0);
1160 putname(tmp); 1200 putname(tmp);
1161 } 1201 }
1162 return err; 1202 return err;
@@ -1248,18 +1288,24 @@ access:
1248 * that namei follows links, while lnamei does not. 1288 * that namei follows links, while lnamei does not.
1249 * SMP-safe 1289 * SMP-safe
1250 */ 1290 */
1251int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) 1291int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
1292 struct nameidata *nd)
1252{ 1293{
1253 char *tmp = getname(name); 1294 char *tmp = getname(name);
1254 int err = PTR_ERR(tmp); 1295 int err = PTR_ERR(tmp);
1255 1296
1256 if (!IS_ERR(tmp)) { 1297 if (!IS_ERR(tmp)) {
1257 err = path_lookup(tmp, flags, nd); 1298 err = do_path_lookup(dfd, tmp, flags, nd);
1258 putname(tmp); 1299 putname(tmp);
1259 } 1300 }
1260 return err; 1301 return err;
1261} 1302}
1262 1303
1304int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd)
1305{
1306 return __user_walk_fd(AT_FDCWD, name, flags, nd);
1307}
1308
1263/* 1309/*
1264 * It's inline, so penalty for filesystems that don't use sticky bit is 1310 * It's inline, so penalty for filesystems that don't use sticky bit is
1265 * minimal. 1311 * minimal.
@@ -1518,7 +1564,8 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
1518 * for symlinks (where the permissions are checked later). 1564 * for symlinks (where the permissions are checked later).
1519 * SMP-safe 1565 * SMP-safe
1520 */ 1566 */
1521int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) 1567int open_namei(int dfd, const char *pathname, int flag,
1568 int mode, struct nameidata *nd)
1522{ 1569{
1523 int acc_mode, error; 1570 int acc_mode, error;
1524 struct path path; 1571 struct path path;
@@ -1540,7 +1587,8 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
1540 * The simplest case - just a plain lookup. 1587 * The simplest case - just a plain lookup.
1541 */ 1588 */
1542 if (!(flag & O_CREAT)) { 1589 if (!(flag & O_CREAT)) {
1543 error = path_lookup_open(pathname, lookup_flags(flag), nd, flag); 1590 error = path_lookup_open(dfd, pathname, lookup_flags(flag),
1591 nd, flag);
1544 if (error) 1592 if (error)
1545 return error; 1593 return error;
1546 goto ok; 1594 goto ok;
@@ -1549,7 +1597,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
1549 /* 1597 /*
1550 * Create - we need to know the parent. 1598 * Create - we need to know the parent.
1551 */ 1599 */
1552 error = path_lookup_create(pathname, LOOKUP_PARENT, nd, flag, mode); 1600 error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode);
1553 if (error) 1601 if (error)
1554 return error; 1602 return error;
1555 1603
@@ -1744,7 +1792,8 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
1744 return error; 1792 return error;
1745} 1793}
1746 1794
1747asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev) 1795asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
1796 unsigned dev)
1748{ 1797{
1749 int error = 0; 1798 int error = 0;
1750 char * tmp; 1799 char * tmp;
@@ -1757,7 +1806,7 @@ asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev)
1757 if (IS_ERR(tmp)) 1806 if (IS_ERR(tmp))
1758 return PTR_ERR(tmp); 1807 return PTR_ERR(tmp);
1759 1808
1760 error = path_lookup(tmp, LOOKUP_PARENT, &nd); 1809 error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
1761 if (error) 1810 if (error)
1762 goto out; 1811 goto out;
1763 dentry = lookup_create(&nd, 0); 1812 dentry = lookup_create(&nd, 0);
@@ -1793,6 +1842,11 @@ out:
1793 return error; 1842 return error;
1794} 1843}
1795 1844
1845asmlinkage long sys_mknod(const char __user *filename, int mode, unsigned dev)
1846{
1847 return sys_mknodat(AT_FDCWD, filename, mode, dev);
1848}
1849
1796int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 1850int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1797{ 1851{
1798 int error = may_create(dir, dentry, NULL); 1852 int error = may_create(dir, dentry, NULL);
@@ -1815,7 +1869,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1815 return error; 1869 return error;
1816} 1870}
1817 1871
1818asmlinkage long sys_mkdir(const char __user * pathname, int mode) 1872asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode)
1819{ 1873{
1820 int error = 0; 1874 int error = 0;
1821 char * tmp; 1875 char * tmp;
@@ -1826,7 +1880,7 @@ asmlinkage long sys_mkdir(const char __user * pathname, int mode)
1826 struct dentry *dentry; 1880 struct dentry *dentry;
1827 struct nameidata nd; 1881 struct nameidata nd;
1828 1882
1829 error = path_lookup(tmp, LOOKUP_PARENT, &nd); 1883 error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
1830 if (error) 1884 if (error)
1831 goto out; 1885 goto out;
1832 dentry = lookup_create(&nd, 1); 1886 dentry = lookup_create(&nd, 1);
@@ -1846,6 +1900,11 @@ out:
1846 return error; 1900 return error;
1847} 1901}
1848 1902
1903asmlinkage long sys_mkdir(const char __user *pathname, int mode)
1904{
1905 return sys_mkdirat(AT_FDCWD, pathname, mode);
1906}
1907
1849/* 1908/*
1850 * We try to drop the dentry early: we should have 1909 * We try to drop the dentry early: we should have
1851 * a usage count of 2 if we're the only user of this 1910 * a usage count of 2 if we're the only user of this
@@ -1907,7 +1966,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
1907 return error; 1966 return error;
1908} 1967}
1909 1968
1910asmlinkage long sys_rmdir(const char __user * pathname) 1969static long do_rmdir(int dfd, const char __user *pathname)
1911{ 1970{
1912 int error = 0; 1971 int error = 0;
1913 char * name; 1972 char * name;
@@ -1918,7 +1977,7 @@ asmlinkage long sys_rmdir(const char __user * pathname)
1918 if(IS_ERR(name)) 1977 if(IS_ERR(name))
1919 return PTR_ERR(name); 1978 return PTR_ERR(name);
1920 1979
1921 error = path_lookup(name, LOOKUP_PARENT, &nd); 1980 error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd);
1922 if (error) 1981 if (error)
1923 goto exit; 1982 goto exit;
1924 1983
@@ -1948,6 +2007,11 @@ exit:
1948 return error; 2007 return error;
1949} 2008}
1950 2009
2010asmlinkage long sys_rmdir(const char __user *pathname)
2011{
2012 return do_rmdir(AT_FDCWD, pathname);
2013}
2014
1951int vfs_unlink(struct inode *dir, struct dentry *dentry) 2015int vfs_unlink(struct inode *dir, struct dentry *dentry)
1952{ 2016{
1953 int error = may_delete(dir, dentry, 0); 2017 int error = may_delete(dir, dentry, 0);
@@ -1984,7 +2048,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
1984 * writeout happening, and we don't want to prevent access to the directory 2048 * writeout happening, and we don't want to prevent access to the directory
1985 * while waiting on the I/O. 2049 * while waiting on the I/O.
1986 */ 2050 */
1987asmlinkage long sys_unlink(const char __user * pathname) 2051static long do_unlinkat(int dfd, const char __user *pathname)
1988{ 2052{
1989 int error = 0; 2053 int error = 0;
1990 char * name; 2054 char * name;
@@ -1996,7 +2060,7 @@ asmlinkage long sys_unlink(const char __user * pathname)
1996 if(IS_ERR(name)) 2060 if(IS_ERR(name))
1997 return PTR_ERR(name); 2061 return PTR_ERR(name);
1998 2062
1999 error = path_lookup(name, LOOKUP_PARENT, &nd); 2063 error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd);
2000 if (error) 2064 if (error)
2001 goto exit; 2065 goto exit;
2002 error = -EISDIR; 2066 error = -EISDIR;
@@ -2031,6 +2095,22 @@ slashes:
2031 goto exit2; 2095 goto exit2;
2032} 2096}
2033 2097
2098asmlinkage long sys_unlinkat(int dfd, const char __user *pathname, int flag)
2099{
2100 if ((flag & ~AT_REMOVEDIR) != 0)
2101 return -EINVAL;
2102
2103 if (flag & AT_REMOVEDIR)
2104 return do_rmdir(dfd, pathname);
2105
2106 return do_unlinkat(dfd, pathname);
2107}
2108
2109asmlinkage long sys_unlink(const char __user *pathname)
2110{
2111 return do_unlinkat(AT_FDCWD, pathname);
2112}
2113
2034int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode) 2114int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode)
2035{ 2115{
2036 int error = may_create(dir, dentry, NULL); 2116 int error = may_create(dir, dentry, NULL);
@@ -2052,7 +2132,8 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, i
2052 return error; 2132 return error;
2053} 2133}
2054 2134
2055asmlinkage long sys_symlink(const char __user * oldname, const char __user * newname) 2135asmlinkage long sys_symlinkat(const char __user *oldname,
2136 int newdfd, const char __user *newname)
2056{ 2137{
2057 int error = 0; 2138 int error = 0;
2058 char * from; 2139 char * from;
@@ -2067,7 +2148,7 @@ asmlinkage long sys_symlink(const char __user * oldname, const char __user * new
2067 struct dentry *dentry; 2148 struct dentry *dentry;
2068 struct nameidata nd; 2149 struct nameidata nd;
2069 2150
2070 error = path_lookup(to, LOOKUP_PARENT, &nd); 2151 error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
2071 if (error) 2152 if (error)
2072 goto out; 2153 goto out;
2073 dentry = lookup_create(&nd, 0); 2154 dentry = lookup_create(&nd, 0);
@@ -2085,6 +2166,11 @@ out:
2085 return error; 2166 return error;
2086} 2167}
2087 2168
2169asmlinkage long sys_symlink(const char __user *oldname, const char __user *newname)
2170{
2171 return sys_symlinkat(oldname, AT_FDCWD, newname);
2172}
2173
2088int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) 2174int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2089{ 2175{
2090 struct inode *inode = old_dentry->d_inode; 2176 struct inode *inode = old_dentry->d_inode;
@@ -2132,7 +2218,8 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
2132 * with linux 2.0, and to avoid hard-linking to directories 2218 * with linux 2.0, and to avoid hard-linking to directories
2133 * and other special files. --ADM 2219 * and other special files. --ADM
2134 */ 2220 */
2135asmlinkage long sys_link(const char __user * oldname, const char __user * newname) 2221asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
2222 int newdfd, const char __user *newname)
2136{ 2223{
2137 struct dentry *new_dentry; 2224 struct dentry *new_dentry;
2138 struct nameidata nd, old_nd; 2225 struct nameidata nd, old_nd;
@@ -2143,10 +2230,10 @@ asmlinkage long sys_link(const char __user * oldname, const char __user * newnam
2143 if (IS_ERR(to)) 2230 if (IS_ERR(to))
2144 return PTR_ERR(to); 2231 return PTR_ERR(to);
2145 2232
2146 error = __user_walk(oldname, 0, &old_nd); 2233 error = __user_walk_fd(olddfd, oldname, 0, &old_nd);
2147 if (error) 2234 if (error)
2148 goto exit; 2235 goto exit;
2149 error = path_lookup(to, LOOKUP_PARENT, &nd); 2236 error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
2150 if (error) 2237 if (error)
2151 goto out; 2238 goto out;
2152 error = -EXDEV; 2239 error = -EXDEV;
@@ -2169,6 +2256,11 @@ exit:
2169 return error; 2256 return error;
2170} 2257}
2171 2258
2259asmlinkage long sys_link(const char __user *oldname, const char __user *newname)
2260{
2261 return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname);
2262}
2263
2172/* 2264/*
2173 * The worst of all namespace operations - renaming directory. "Perverted" 2265 * The worst of all namespace operations - renaming directory. "Perverted"
2174 * doesn't even start to describe it. Somebody in UCB had a heck of a trip... 2266 * doesn't even start to describe it. Somebody in UCB had a heck of a trip...
@@ -2315,7 +2407,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
2315 return error; 2407 return error;
2316} 2408}
2317 2409
2318static int do_rename(const char * oldname, const char * newname) 2410static int do_rename(int olddfd, const char *oldname,
2411 int newdfd, const char *newname)
2319{ 2412{
2320 int error = 0; 2413 int error = 0;
2321 struct dentry * old_dir, * new_dir; 2414 struct dentry * old_dir, * new_dir;
@@ -2323,11 +2416,11 @@ static int do_rename(const char * oldname, const char * newname)
2323 struct dentry * trap; 2416 struct dentry * trap;
2324 struct nameidata oldnd, newnd; 2417 struct nameidata oldnd, newnd;
2325 2418
2326 error = path_lookup(oldname, LOOKUP_PARENT, &oldnd); 2419 error = do_path_lookup(olddfd, oldname, LOOKUP_PARENT, &oldnd);
2327 if (error) 2420 if (error)
2328 goto exit; 2421 goto exit;
2329 2422
2330 error = path_lookup(newname, LOOKUP_PARENT, &newnd); 2423 error = do_path_lookup(newdfd, newname, LOOKUP_PARENT, &newnd);
2331 if (error) 2424 if (error)
2332 goto exit1; 2425 goto exit1;
2333 2426
@@ -2391,7 +2484,8 @@ exit:
2391 return error; 2484 return error;
2392} 2485}
2393 2486
2394asmlinkage long sys_rename(const char __user * oldname, const char __user * newname) 2487asmlinkage long sys_renameat(int olddfd, const char __user *oldname,
2488 int newdfd, const char __user *newname)
2395{ 2489{
2396 int error; 2490 int error;
2397 char * from; 2491 char * from;
@@ -2403,13 +2497,18 @@ asmlinkage long sys_rename(const char __user * oldname, const char __user * newn
2403 to = getname(newname); 2497 to = getname(newname);
2404 error = PTR_ERR(to); 2498 error = PTR_ERR(to);
2405 if (!IS_ERR(to)) { 2499 if (!IS_ERR(to)) {
2406 error = do_rename(from,to); 2500 error = do_rename(olddfd, from, newdfd, to);
2407 putname(to); 2501 putname(to);
2408 } 2502 }
2409 putname(from); 2503 putname(from);
2410 return error; 2504 return error;
2411} 2505}
2412 2506
2507asmlinkage long sys_rename(const char __user *oldname, const char __user *newname)
2508{
2509 return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname);
2510}
2511
2413int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) 2512int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link)
2414{ 2513{
2415 int len; 2514 int len;
@@ -2553,6 +2652,7 @@ struct inode_operations page_symlink_inode_operations = {
2553}; 2652};
2554 2653
2555EXPORT_SYMBOL(__user_walk); 2654EXPORT_SYMBOL(__user_walk);
2655EXPORT_SYMBOL(__user_walk_fd);
2556EXPORT_SYMBOL(follow_down); 2656EXPORT_SYMBOL(follow_down);
2557EXPORT_SYMBOL(follow_up); 2657EXPORT_SYMBOL(follow_up);
2558EXPORT_SYMBOL(get_write_access); /* binfmt_aout */ 2658EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
diff --git a/fs/nfsctl.c b/fs/nfsctl.c
index 0b14938b5b62..0d4cf9486068 100644
--- a/fs/nfsctl.c
+++ b/fs/nfsctl.c
@@ -5,6 +5,7 @@
5 * 5 *
6 */ 6 */
7#include <linux/config.h> 7#include <linux/config.h>
8#include <linux/types.h>
8#include <linux/file.h> 9#include <linux/file.h>
9#include <linux/fs.h> 10#include <linux/fs.h>
10#include <linux/sunrpc/svc.h> 11#include <linux/sunrpc/svc.h>
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 361b4007d4a0..a00fe8686293 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -192,6 +192,14 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
192 } 192 }
193 if (status) 193 if (status)
194 goto out; 194 goto out;
195
196 /* Openowner is now set, so sequence id will get bumped. Now we need
197 * these checks before we do any creates: */
198 if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
199 return nfserr_grace;
200 if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
201 return nfserr_no_grace;
202
195 switch (open->op_claim_type) { 203 switch (open->op_claim_type) {
196 case NFS4_OPEN_CLAIM_DELEGATE_CUR: 204 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
197 status = nfserr_inval; 205 status = nfserr_inval;
@@ -210,6 +218,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
210 goto out; 218 goto out;
211 break; 219 break;
212 case NFS4_OPEN_CLAIM_PREVIOUS: 220 case NFS4_OPEN_CLAIM_PREVIOUS:
221 open->op_stateowner->so_confirmed = 1;
213 /* 222 /*
214 * The CURRENT_FH is already set to the file being 223 * The CURRENT_FH is already set to the file being
215 * opened. (1) set open->op_cinfo, (2) set 224 * opened. (1) set open->op_cinfo, (2) set
@@ -221,6 +230,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
221 goto out; 230 goto out;
222 break; 231 break;
223 case NFS4_OPEN_CLAIM_DELEGATE_PREV: 232 case NFS4_OPEN_CLAIM_DELEGATE_PREV:
233 open->op_stateowner->so_confirmed = 1;
224 printk("NFSD: unsupported OPEN claim type %d\n", 234 printk("NFSD: unsupported OPEN claim type %d\n",
225 open->op_claim_type); 235 open->op_claim_type);
226 status = nfserr_notsupp; 236 status = nfserr_notsupp;
@@ -584,31 +594,23 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
584{ 594{
585 int status = nfs_ok; 595 int status = nfs_ok;
586 596
587 if (!current_fh->fh_dentry)
588 return nfserr_nofilehandle;
589
590 status = nfs_ok;
591 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { 597 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
592 nfs4_lock_state(); 598 nfs4_lock_state();
593 if ((status = nfs4_preprocess_stateid_op(current_fh, 599 status = nfs4_preprocess_stateid_op(current_fh,
594 &setattr->sa_stateid, 600 &setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
595 CHECK_FH | WR_STATE, NULL))) {
596 dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
597 goto out_unlock;
598 }
599 nfs4_unlock_state(); 601 nfs4_unlock_state();
602 if (status) {
603 dprintk("NFSD: nfsd4_setattr: couldn't process stateid!");
604 return status;
605 }
600 } 606 }
601 status = nfs_ok; 607 status = nfs_ok;
602 if (setattr->sa_acl != NULL) 608 if (setattr->sa_acl != NULL)
603 status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl); 609 status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl);
604 if (status) 610 if (status)
605 goto out; 611 return status;
606 status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr, 612 status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr,
607 0, (time_t)0); 613 0, (time_t)0);
608out:
609 return status;
610out_unlock:
611 nfs4_unlock_state();
612 return status; 614 return status;
613} 615}
614 616
@@ -626,15 +628,17 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
626 return nfserr_inval; 628 return nfserr_inval;
627 629
628 nfs4_lock_state(); 630 nfs4_lock_state();
629 if ((status = nfs4_preprocess_stateid_op(current_fh, stateid, 631 status = nfs4_preprocess_stateid_op(current_fh, stateid,
630 CHECK_FH | WR_STATE, &filp))) { 632 CHECK_FH | WR_STATE, &filp);
631 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
632 goto out;
633 }
634 if (filp) 633 if (filp)
635 get_file(filp); 634 get_file(filp);
636 nfs4_unlock_state(); 635 nfs4_unlock_state();
637 636
637 if (status) {
638 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
639 return status;
640 }
641
638 write->wr_bytes_written = write->wr_buflen; 642 write->wr_bytes_written = write->wr_buflen;
639 write->wr_how_written = write->wr_stable_how; 643 write->wr_how_written = write->wr_stable_how;
640 p = (u32 *)write->wr_verifier.data; 644 p = (u32 *)write->wr_verifier.data;
@@ -650,9 +654,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
650 if (status == nfserr_symlink) 654 if (status == nfserr_symlink)
651 status = nfserr_inval; 655 status = nfserr_inval;
652 return status; 656 return status;
653out:
654 nfs4_unlock_state();
655 return status;
656} 657}
657 658
658/* This routine never returns NFS_OK! If there are no other errors, it 659/* This routine never returns NFS_OK! If there are no other errors, it
@@ -768,6 +769,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
768 while (!status && resp->opcnt < args->opcnt) { 769 while (!status && resp->opcnt < args->opcnt) {
769 op = &args->ops[resp->opcnt++]; 770 op = &args->ops[resp->opcnt++];
770 771
772 dprintk("nfsv4 compound op #%d: %d\n", resp->opcnt, op->opnum);
773
771 /* 774 /*
772 * The XDR decode routines may have pre-set op->status; 775 * The XDR decode routines may have pre-set op->status;
773 * for example, if there is a miscellaneous XDR error 776 * for example, if there is a miscellaneous XDR error
@@ -792,17 +795,13 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
792 /* All operations except RENEW, SETCLIENTID, RESTOREFH 795 /* All operations except RENEW, SETCLIENTID, RESTOREFH
793 * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH 796 * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
794 * require a valid current filehandle 797 * require a valid current filehandle
795 *
796 * SETATTR NOFILEHANDLE error handled in nfsd4_setattr
797 * due to required returned bitmap argument
798 */ 798 */
799 if ((!current_fh->fh_dentry) && 799 if ((!current_fh->fh_dentry) &&
800 !((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) || 800 !((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) ||
801 (op->opnum == OP_SETCLIENTID) || 801 (op->opnum == OP_SETCLIENTID) ||
802 (op->opnum == OP_SETCLIENTID_CONFIRM) || 802 (op->opnum == OP_SETCLIENTID_CONFIRM) ||
803 (op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) || 803 (op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) ||
804 (op->opnum == OP_RELEASE_LOCKOWNER) || 804 (op->opnum == OP_RELEASE_LOCKOWNER))) {
805 (op->opnum == OP_SETATTR))) {
806 op->status = nfserr_nofilehandle; 805 op->status = nfserr_nofilehandle;
807 goto encode_op; 806 goto encode_op;
808 } 807 }
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index be963a133aaa..06da7506363c 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -222,8 +222,7 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
222 222
223 nfs4_save_user(&uid, &gid); 223 nfs4_save_user(&uid, &gid);
224 224
225 filp = dentry_open(dget(dir), mntget(rec_dir.mnt), 225 filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
226 O_RDWR);
227 status = PTR_ERR(filp); 226 status = PTR_ERR(filp);
228 if (IS_ERR(filp)) 227 if (IS_ERR(filp))
229 goto out; 228 goto out;
@@ -400,9 +399,10 @@ nfsd4_init_recdir(char *rec_dirname)
400 399
401 nfs4_save_user(&uid, &gid); 400 nfs4_save_user(&uid, &gid);
402 401
403 status = path_lookup(rec_dirname, LOOKUP_FOLLOW, &rec_dir); 402 status = path_lookup(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
404 if (status == -ENOENT) 403 &rec_dir);
405 printk("NFSD: recovery directory %s doesn't exist\n", 404 if (status)
405 printk("NFSD: unable to find recovery directory %s\n",
406 rec_dirname); 406 rec_dirname);
407 407
408 if (!status) 408 if (!status)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6bbefd06f10d..1143cfb64549 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1088,7 +1088,7 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
1088 sop->so_seqid = open->op_seqid; 1088 sop->so_seqid = open->op_seqid;
1089 sop->so_confirmed = 0; 1089 sop->so_confirmed = 0;
1090 rp = &sop->so_replay; 1090 rp = &sop->so_replay;
1091 rp->rp_status = NFSERR_SERVERFAULT; 1091 rp->rp_status = nfserr_serverfault;
1092 rp->rp_buflen = 0; 1092 rp->rp_buflen = 0;
1093 rp->rp_buf = rp->rp_ibuf; 1093 rp->rp_buf = rp->rp_ibuf;
1094 return sop; 1094 return sop;
@@ -1178,7 +1178,6 @@ release_stateid(struct nfs4_stateid *stp, int flags)
1178 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner); 1178 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
1179 put_nfs4_file(stp->st_file); 1179 put_nfs4_file(stp->st_file);
1180 kmem_cache_free(stateid_slab, stp); 1180 kmem_cache_free(stateid_slab, stp);
1181 stp = NULL;
1182} 1181}
1183 1182
1184static void 1183static void
@@ -1191,22 +1190,6 @@ move_to_close_lru(struct nfs4_stateowner *sop)
1191 sop->so_time = get_seconds(); 1190 sop->so_time = get_seconds();
1192} 1191}
1193 1192
1194static void
1195release_state_owner(struct nfs4_stateid *stp, int flag)
1196{
1197 struct nfs4_stateowner *sop = stp->st_stateowner;
1198
1199 dprintk("NFSD: release_state_owner\n");
1200 release_stateid(stp, flag);
1201
1202 /* place unused nfs4_stateowners on so_close_lru list to be
1203 * released by the laundromat service after the lease period
1204 * to enable us to handle CLOSE replay
1205 */
1206 if (sop->so_confirmed && list_empty(&sop->so_stateids))
1207 move_to_close_lru(sop);
1208}
1209
1210static int 1193static int
1211cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) { 1194cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) {
1212 return ((sop->so_owner.len == owner->len) && 1195 return ((sop->so_owner.len == owner->len) &&
@@ -1446,92 +1429,61 @@ static struct lock_manager_operations nfsd_lease_mng_ops = {
1446}; 1429};
1447 1430
1448 1431
1449/*
1450 * nfsd4_process_open1()
1451 * lookup stateowner.
1452 * found:
1453 * check confirmed
1454 * confirmed:
1455 * check seqid
1456 * not confirmed:
1457 * delete owner
1458 * create new owner
1459 * notfound:
1460 * verify clientid
1461 * create new owner
1462 *
1463 * called with nfs4_lock_state() held.
1464 */
1465int 1432int
1466nfsd4_process_open1(struct nfsd4_open *open) 1433nfsd4_process_open1(struct nfsd4_open *open)
1467{ 1434{
1468 int status;
1469 clientid_t *clientid = &open->op_clientid; 1435 clientid_t *clientid = &open->op_clientid;
1470 struct nfs4_client *clp = NULL; 1436 struct nfs4_client *clp = NULL;
1471 unsigned int strhashval; 1437 unsigned int strhashval;
1472 struct nfs4_stateowner *sop = NULL; 1438 struct nfs4_stateowner *sop = NULL;
1473 1439
1474 status = nfserr_inval;
1475 if (!check_name(open->op_owner)) 1440 if (!check_name(open->op_owner))
1476 goto out; 1441 return nfserr_inval;
1477 1442
1478 if (STALE_CLIENTID(&open->op_clientid)) 1443 if (STALE_CLIENTID(&open->op_clientid))
1479 return nfserr_stale_clientid; 1444 return nfserr_stale_clientid;
1480 1445
1481 strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner); 1446 strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
1482 sop = find_openstateowner_str(strhashval, open); 1447 sop = find_openstateowner_str(strhashval, open);
1483 if (sop) { 1448 open->op_stateowner = sop;
1484 open->op_stateowner = sop; 1449 if (!sop) {
1485 /* check for replay */ 1450 /* Make sure the client's lease hasn't expired. */
1486 if (open->op_seqid == sop->so_seqid - 1){
1487 if (sop->so_replay.rp_buflen)
1488 return NFSERR_REPLAY_ME;
1489 else {
1490 /* The original OPEN failed so spectacularly
1491 * that we don't even have replay data saved!
1492 * Therefore, we have no choice but to continue
1493 * processing this OPEN; presumably, we'll
1494 * fail again for the same reason.
1495 */
1496 dprintk("nfsd4_process_open1:"
1497 " replay with no replay cache\n");
1498 goto renew;
1499 }
1500 } else if (sop->so_confirmed) {
1501 if (open->op_seqid == sop->so_seqid)
1502 goto renew;
1503 status = nfserr_bad_seqid;
1504 goto out;
1505 } else {
1506 /* If we get here, we received an OPEN for an
1507 * unconfirmed nfs4_stateowner. Since the seqid's are
1508 * different, purge the existing nfs4_stateowner, and
1509 * instantiate a new one.
1510 */
1511 clp = sop->so_client;
1512 release_stateowner(sop);
1513 }
1514 } else {
1515 /* nfs4_stateowner not found.
1516 * Verify clientid and instantiate new nfs4_stateowner.
1517 * If verify fails this is presumably the result of the
1518 * client's lease expiring.
1519 */
1520 status = nfserr_expired;
1521 clp = find_confirmed_client(clientid); 1451 clp = find_confirmed_client(clientid);
1522 if (clp == NULL) 1452 if (clp == NULL)
1523 goto out; 1453 return nfserr_expired;
1454 goto renew;
1524 } 1455 }
1525 status = nfserr_resource; 1456 if (!sop->so_confirmed) {
1526 sop = alloc_init_open_stateowner(strhashval, clp, open); 1457 /* Replace unconfirmed owners without checking for replay. */
1527 if (sop == NULL) 1458 clp = sop->so_client;
1528 goto out; 1459 release_stateowner(sop);
1529 open->op_stateowner = sop; 1460 open->op_stateowner = NULL;
1461 goto renew;
1462 }
1463 if (open->op_seqid == sop->so_seqid - 1) {
1464 if (sop->so_replay.rp_buflen)
1465 return NFSERR_REPLAY_ME;
1466 /* The original OPEN failed so spectacularly
1467 * that we don't even have replay data saved!
1468 * Therefore, we have no choice but to continue
1469 * processing this OPEN; presumably, we'll
1470 * fail again for the same reason.
1471 */
1472 dprintk("nfsd4_process_open1: replay with no replay cache\n");
1473 goto renew;
1474 }
1475 if (open->op_seqid != sop->so_seqid)
1476 return nfserr_bad_seqid;
1530renew: 1477renew:
1531 status = nfs_ok; 1478 if (open->op_stateowner == NULL) {
1479 sop = alloc_init_open_stateowner(strhashval, clp, open);
1480 if (sop == NULL)
1481 return nfserr_resource;
1482 open->op_stateowner = sop;
1483 }
1484 list_del_init(&sop->so_close_lru);
1532 renew_client(sop->so_client); 1485 renew_client(sop->so_client);
1533out: 1486 return nfs_ok;
1534 return status;
1535} 1487}
1536 1488
1537static inline int 1489static inline int
@@ -1648,7 +1600,7 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
1648 if (!open->op_truncate) 1600 if (!open->op_truncate)
1649 return 0; 1601 return 0;
1650 if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE)) 1602 if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
1651 return -EINVAL; 1603 return nfserr_inval;
1652 return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0); 1604 return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0);
1653} 1605}
1654 1606
@@ -1657,26 +1609,26 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
1657{ 1609{
1658 struct file *filp = stp->st_vfs_file; 1610 struct file *filp = stp->st_vfs_file;
1659 struct inode *inode = filp->f_dentry->d_inode; 1611 struct inode *inode = filp->f_dentry->d_inode;
1660 unsigned int share_access; 1612 unsigned int share_access, new_writer;
1661 int status; 1613 int status;
1662 1614
1663 set_access(&share_access, stp->st_access_bmap); 1615 set_access(&share_access, stp->st_access_bmap);
1664 share_access = ~share_access; 1616 new_writer = (~share_access) & open->op_share_access
1665 share_access &= open->op_share_access; 1617 & NFS4_SHARE_ACCESS_WRITE;
1666
1667 if (!(share_access & NFS4_SHARE_ACCESS_WRITE))
1668 return nfsd4_truncate(rqstp, cur_fh, open);
1669 1618
1670 status = get_write_access(inode); 1619 if (new_writer) {
1671 if (status) 1620 status = get_write_access(inode);
1672 return nfserrno(status); 1621 if (status)
1622 return nfserrno(status);
1623 }
1673 status = nfsd4_truncate(rqstp, cur_fh, open); 1624 status = nfsd4_truncate(rqstp, cur_fh, open);
1674 if (status) { 1625 if (status) {
1675 put_write_access(inode); 1626 if (new_writer)
1627 put_write_access(inode);
1676 return status; 1628 return status;
1677 } 1629 }
1678 /* remember the open */ 1630 /* remember the open */
1679 filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ; 1631 filp->f_mode |= open->op_share_access;
1680 set_bit(open->op_share_access, &stp->st_access_bmap); 1632 set_bit(open->op_share_access, &stp->st_access_bmap);
1681 set_bit(open->op_share_deny, &stp->st_deny_bmap); 1633 set_bit(open->op_share_deny, &stp->st_deny_bmap);
1682 1634
@@ -1780,12 +1732,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1780 struct nfs4_delegation *dp = NULL; 1732 struct nfs4_delegation *dp = NULL;
1781 int status; 1733 int status;
1782 1734
1783 if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
1784 return nfserr_grace;
1785
1786 if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
1787 return nfserr_no_grace;
1788
1789 status = nfserr_inval; 1735 status = nfserr_inval;
1790 if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny)) 1736 if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
1791 goto out; 1737 goto out;
@@ -2423,15 +2369,19 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos
2423 CHECK_FH | OPEN_STATE | CLOSE_STATE, 2369 CHECK_FH | OPEN_STATE | CLOSE_STATE,
2424 &close->cl_stateowner, &stp, NULL))) 2370 &close->cl_stateowner, &stp, NULL)))
2425 goto out; 2371 goto out;
2426 /*
2427 * Return success, but first update the stateid.
2428 */
2429 status = nfs_ok; 2372 status = nfs_ok;
2430 update_stateid(&stp->st_stateid); 2373 update_stateid(&stp->st_stateid);
2431 memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t)); 2374 memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
2432 2375
2433 /* release_state_owner() calls nfsd_close() if needed */ 2376 /* release_stateid() calls nfsd_close() if needed */
2434 release_state_owner(stp, OPEN_STATE); 2377 release_stateid(stp, OPEN_STATE);
2378
2379 /* place unused nfs4_stateowners on so_close_lru list to be
2380 * released by the laundromat service after the lease period
2381 * to enable us to handle CLOSE replay
2382 */
2383 if (list_empty(&close->cl_stateowner->so_stateids))
2384 move_to_close_lru(close->cl_stateowner);
2435out: 2385out:
2436 if (close->cl_stateowner) { 2386 if (close->cl_stateowner) {
2437 nfs4_get_stateowner(close->cl_stateowner); 2387 nfs4_get_stateowner(close->cl_stateowner);
@@ -2633,7 +2583,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
2633 sop->so_seqid = lock->lk_new_lock_seqid + 1; 2583 sop->so_seqid = lock->lk_new_lock_seqid + 1;
2634 sop->so_confirmed = 1; 2584 sop->so_confirmed = 1;
2635 rp = &sop->so_replay; 2585 rp = &sop->so_replay;
2636 rp->rp_status = NFSERR_SERVERFAULT; 2586 rp->rp_status = nfserr_serverfault;
2637 rp->rp_buflen = 0; 2587 rp->rp_buflen = 0;
2638 rp->rp_buf = rp->rp_ibuf; 2588 rp->rp_buf = rp->rp_ibuf;
2639 return sop; 2589 return sop;
@@ -2700,6 +2650,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2700 if (check_lock_length(lock->lk_offset, lock->lk_length)) 2650 if (check_lock_length(lock->lk_offset, lock->lk_length))
2701 return nfserr_inval; 2651 return nfserr_inval;
2702 2652
2653 if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
2654 dprintk("NFSD: nfsd4_lock: permission denied!\n");
2655 return status;
2656 }
2657
2703 nfs4_lock_state(); 2658 nfs4_lock_state();
2704 2659
2705 if (lock->lk_is_new) { 2660 if (lock->lk_is_new) {
@@ -2720,11 +2675,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2720 lock->lk_new_open_seqid, 2675 lock->lk_new_open_seqid,
2721 &lock->lk_new_open_stateid, 2676 &lock->lk_new_open_stateid,
2722 CHECK_FH | OPEN_STATE, 2677 CHECK_FH | OPEN_STATE,
2723 &lock->lk_stateowner, &open_stp, 2678 &lock->lk_replay_owner, &open_stp,
2724 lock); 2679 lock);
2725 if (status) 2680 if (status)
2726 goto out; 2681 goto out;
2727 open_sop = lock->lk_stateowner; 2682 open_sop = lock->lk_replay_owner;
2728 /* create lockowner and lock stateid */ 2683 /* create lockowner and lock stateid */
2729 fp = open_stp->st_file; 2684 fp = open_stp->st_file;
2730 strhashval = lock_ownerstr_hashval(fp->fi_inode, 2685 strhashval = lock_ownerstr_hashval(fp->fi_inode,
@@ -2739,29 +2694,22 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2739 if (lock_sop == NULL) 2694 if (lock_sop == NULL)
2740 goto out; 2695 goto out;
2741 lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp); 2696 lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp);
2742 if (lock_stp == NULL) { 2697 if (lock_stp == NULL)
2743 release_stateowner(lock_sop);
2744 goto out; 2698 goto out;
2745 }
2746 } else { 2699 } else {
2747 /* lock (lock owner + lock stateid) already exists */ 2700 /* lock (lock owner + lock stateid) already exists */
2748 status = nfs4_preprocess_seqid_op(current_fh, 2701 status = nfs4_preprocess_seqid_op(current_fh,
2749 lock->lk_old_lock_seqid, 2702 lock->lk_old_lock_seqid,
2750 &lock->lk_old_lock_stateid, 2703 &lock->lk_old_lock_stateid,
2751 CHECK_FH | LOCK_STATE, 2704 CHECK_FH | LOCK_STATE,
2752 &lock->lk_stateowner, &lock_stp, lock); 2705 &lock->lk_replay_owner, &lock_stp, lock);
2753 if (status) 2706 if (status)
2754 goto out; 2707 goto out;
2755 lock_sop = lock->lk_stateowner; 2708 lock_sop = lock->lk_replay_owner;
2756 } 2709 }
2757 /* lock->lk_stateowner and lock_stp have been created or found */ 2710 /* lock->lk_replay_owner and lock_stp have been created or found */
2758 filp = lock_stp->st_vfs_file; 2711 filp = lock_stp->st_vfs_file;
2759 2712
2760 if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
2761 dprintk("NFSD: nfsd4_lock: permission denied!\n");
2762 goto out;
2763 }
2764
2765 status = nfserr_grace; 2713 status = nfserr_grace;
2766 if (nfs4_in_grace() && !lock->lk_reclaim) 2714 if (nfs4_in_grace() && !lock->lk_reclaim)
2767 goto out; 2715 goto out;
@@ -2802,8 +2750,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2802 */ 2750 */
2803 2751
2804 status = posix_lock_file(filp, &file_lock); 2752 status = posix_lock_file(filp, &file_lock);
2805 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
2806 file_lock.fl_ops->fl_release_private(&file_lock);
2807 dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status); 2753 dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status);
2808 switch (-status) { 2754 switch (-status) {
2809 case 0: /* success! */ 2755 case 0: /* success! */
@@ -2815,9 +2761,12 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2815 goto conflicting_lock; 2761 goto conflicting_lock;
2816 case (EDEADLK): 2762 case (EDEADLK):
2817 status = nfserr_deadlock; 2763 status = nfserr_deadlock;
2764 dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
2765 goto out;
2818 default: 2766 default:
2767 status = nfserrno(status);
2819 dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status); 2768 dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
2820 goto out_destroy_new_stateid; 2769 goto out;
2821 } 2770 }
2822 2771
2823conflicting_lock: 2772conflicting_lock:
@@ -2831,20 +2780,12 @@ conflicting_lock:
2831 goto out; 2780 goto out;
2832 } 2781 }
2833 nfs4_set_lock_denied(conflock, &lock->lk_denied); 2782 nfs4_set_lock_denied(conflock, &lock->lk_denied);
2834
2835out_destroy_new_stateid:
2836 if (lock->lk_is_new) {
2837 dprintk("NFSD: nfsd4_lock: destroy new stateid!\n");
2838 /*
2839 * An error encountered after instantiation of the new
2840 * stateid has forced us to destroy it.
2841 */
2842 release_state_owner(lock_stp, LOCK_STATE);
2843 }
2844out: 2783out:
2845 if (lock->lk_stateowner) { 2784 if (status && lock->lk_is_new && lock_sop)
2846 nfs4_get_stateowner(lock->lk_stateowner); 2785 release_stateowner(lock_sop);
2847 *replay_owner = lock->lk_stateowner; 2786 if (lock->lk_replay_owner) {
2787 nfs4_get_stateowner(lock->lk_replay_owner);
2788 *replay_owner = lock->lk_replay_owner;
2848 } 2789 }
2849 nfs4_unlock_state(); 2790 nfs4_unlock_state();
2850 return status; 2791 return status;
@@ -2977,8 +2918,6 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2977 * Try to unlock the file in the VFS. 2918 * Try to unlock the file in the VFS.
2978 */ 2919 */
2979 status = posix_lock_file(filp, &file_lock); 2920 status = posix_lock_file(filp, &file_lock);
2980 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
2981 file_lock.fl_ops->fl_release_private(&file_lock);
2982 if (status) { 2921 if (status) {
2983 dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n"); 2922 dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n");
2984 goto out_nfserr; 2923 goto out_nfserr;
@@ -3016,9 +2955,10 @@ check_for_locks(struct file *filp, struct nfs4_stateowner *lowner)
3016 2955
3017 lock_kernel(); 2956 lock_kernel();
3018 for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) { 2957 for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
3019 if ((*flpp)->fl_owner == (fl_owner_t)lowner) 2958 if ((*flpp)->fl_owner == (fl_owner_t)lowner) {
3020 status = 1; 2959 status = 1;
3021 goto out; 2960 goto out;
2961 }
3022 } 2962 }
3023out: 2963out:
3024 unlock_kernel(); 2964 unlock_kernel();
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index dcd673186944..69d3501173a8 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -528,7 +528,7 @@ nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
528{ 528{
529 DECODE_HEAD; 529 DECODE_HEAD;
530 530
531 lock->lk_stateowner = NULL; 531 lock->lk_replay_owner = NULL;
532 /* 532 /*
533 * type, reclaim(boolean), offset, length, new_lock_owner(boolean) 533 * type, reclaim(boolean), offset, length, new_lock_owner(boolean)
534 */ 534 */
@@ -1764,10 +1764,11 @@ nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen,
1764 */ 1764 */
1765 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)) 1765 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
1766 goto fail; 1766 goto fail;
1767 nfserr = nfserr_toosmall;
1768 p = nfsd4_encode_rdattr_error(p, buflen, nfserr); 1767 p = nfsd4_encode_rdattr_error(p, buflen, nfserr);
1769 if (p == NULL) 1768 if (p == NULL) {
1769 nfserr = nfserr_toosmall;
1770 goto fail; 1770 goto fail;
1771 }
1771 } 1772 }
1772 cd->buflen -= (p - cd->buffer); 1773 cd->buflen -= (p - cd->buffer);
1773 cd->buffer = p; 1774 cd->buffer = p;
@@ -1895,7 +1896,6 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie
1895static void 1896static void
1896nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock) 1897nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock)
1897{ 1898{
1898
1899 ENCODE_SEQID_OP_HEAD; 1899 ENCODE_SEQID_OP_HEAD;
1900 1900
1901 if (!nfserr) { 1901 if (!nfserr) {
@@ -1906,7 +1906,7 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock
1906 } else if (nfserr == nfserr_denied) 1906 } else if (nfserr == nfserr_denied)
1907 nfsd4_encode_lock_denied(resp, &lock->lk_denied); 1907 nfsd4_encode_lock_denied(resp, &lock->lk_denied);
1908 1908
1909 ENCODE_SEQID_OP_TAIL(lock->lk_stateowner); 1909 ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner);
1910} 1910}
1911 1911
1912static void 1912static void
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 0aa1b9603d7f..3e6b75cd90fd 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -36,6 +36,22 @@ nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
36 return nfs_ok; 36 return nfs_ok;
37} 37}
38 38
39static int
40nfsd_return_attrs(int err, struct nfsd_attrstat *resp)
41{
42 if (err) return err;
43 return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
44 resp->fh.fh_dentry,
45 &resp->stat));
46}
47static int
48nfsd_return_dirop(int err, struct nfsd_diropres *resp)
49{
50 if (err) return err;
51 return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
52 resp->fh.fh_dentry,
53 &resp->stat));
54}
39/* 55/*
40 * Get a file's attributes 56 * Get a file's attributes
41 * N.B. After this call resp->fh needs an fh_put 57 * N.B. After this call resp->fh needs an fh_put
@@ -44,10 +60,12 @@ static int
44nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, 60nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
45 struct nfsd_attrstat *resp) 61 struct nfsd_attrstat *resp)
46{ 62{
63 int nfserr;
47 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh)); 64 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
48 65
49 fh_copy(&resp->fh, &argp->fh); 66 fh_copy(&resp->fh, &argp->fh);
50 return fh_verify(rqstp, &resp->fh, 0, MAY_NOP); 67 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
68 return nfsd_return_attrs(nfserr, resp);
51} 69}
52 70
53/* 71/*
@@ -58,12 +76,14 @@ static int
58nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp, 76nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
59 struct nfsd_attrstat *resp) 77 struct nfsd_attrstat *resp)
60{ 78{
79 int nfserr;
61 dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n", 80 dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n",
62 SVCFH_fmt(&argp->fh), 81 SVCFH_fmt(&argp->fh),
63 argp->attrs.ia_valid, (long) argp->attrs.ia_size); 82 argp->attrs.ia_valid, (long) argp->attrs.ia_size);
64 83
65 fh_copy(&resp->fh, &argp->fh); 84 fh_copy(&resp->fh, &argp->fh);
66 return nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0); 85 nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0);
86 return nfsd_return_attrs(nfserr, resp);
67} 87}
68 88
69/* 89/*
@@ -86,7 +106,7 @@ nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
86 &resp->fh); 106 &resp->fh);
87 107
88 fh_put(&argp->fh); 108 fh_put(&argp->fh);
89 return nfserr; 109 return nfsd_return_dirop(nfserr, resp);
90} 110}
91 111
92/* 112/*
@@ -142,7 +162,10 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
142 argp->vec, argp->vlen, 162 argp->vec, argp->vlen,
143 &resp->count); 163 &resp->count);
144 164
145 return nfserr; 165 if (nfserr) return nfserr;
166 return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
167 resp->fh.fh_dentry,
168 &resp->stat));
146} 169}
147 170
148/* 171/*
@@ -165,7 +188,7 @@ nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp,
165 argp->vec, argp->vlen, 188 argp->vec, argp->vlen,
166 argp->len, 189 argp->len,
167 &stable); 190 &stable);
168 return nfserr; 191 return nfsd_return_attrs(nfserr, resp);
169} 192}
170 193
171/* 194/*
@@ -322,7 +345,7 @@ out_unlock:
322 345
323done: 346done:
324 fh_put(dirfhp); 347 fh_put(dirfhp);
325 return nfserr; 348 return nfsd_return_dirop(nfserr, resp);
326} 349}
327 350
328static int 351static int
@@ -425,7 +448,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
425 nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len, 448 nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
426 &argp->attrs, S_IFDIR, 0, &resp->fh); 449 &argp->attrs, S_IFDIR, 0, &resp->fh);
427 fh_put(&argp->fh); 450 fh_put(&argp->fh);
428 return nfserr; 451 return nfsd_return_dirop(nfserr, resp);
429} 452}
430 453
431/* 454/*
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index eef0576a7785..5320e5afaddb 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -710,14 +710,15 @@ static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
710{ 710{
711 struct inode *inode = dp->d_inode; 711 struct inode *inode = dp->d_inode;
712 int (*fsync) (struct file *, struct dentry *, int); 712 int (*fsync) (struct file *, struct dentry *, int);
713 int err = nfs_ok; 713 int err;
714 714
715 filemap_fdatawrite(inode->i_mapping); 715 err = filemap_fdatawrite(inode->i_mapping);
716 if (fop && (fsync = fop->fsync)) 716 if (err == 0 && fop && (fsync = fop->fsync))
717 err=fsync(filp, dp, 0); 717 err = fsync(filp, dp, 0);
718 filemap_fdatawait(inode->i_mapping); 718 if (err == 0)
719 err = filemap_fdatawait(inode->i_mapping);
719 720
720 return nfserrno(err); 721 return err;
721} 722}
722 723
723 724
@@ -734,10 +735,10 @@ nfsd_sync(struct file *filp)
734 return err; 735 return err;
735} 736}
736 737
737void 738int
738nfsd_sync_dir(struct dentry *dp) 739nfsd_sync_dir(struct dentry *dp)
739{ 740{
740 nfsd_dosync(NULL, dp, dp->d_inode->i_fop); 741 return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
741} 742}
742 743
743/* 744/*
@@ -814,7 +815,7 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset
814 return size; 815 return size;
815} 816}
816 817
817static inline int 818static int
818nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 819nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
819 loff_t offset, struct kvec *vec, int vlen, unsigned long *count) 820 loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
820{ 821{
@@ -878,7 +879,7 @@ static void kill_suid(struct dentry *dentry)
878 mutex_unlock(&dentry->d_inode->i_mutex); 879 mutex_unlock(&dentry->d_inode->i_mutex);
879} 880}
880 881
881static inline int 882static int
882nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 883nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
883 loff_t offset, struct kvec *vec, int vlen, 884 loff_t offset, struct kvec *vec, int vlen,
884 unsigned long cnt, int *stablep) 885 unsigned long cnt, int *stablep)
@@ -890,9 +891,9 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
890 int err = 0; 891 int err = 0;
891 int stable = *stablep; 892 int stable = *stablep;
892 893
894#ifdef MSNFS
893 err = nfserr_perm; 895 err = nfserr_perm;
894 896
895#ifdef MSNFS
896 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && 897 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
897 (!lock_may_write(file->f_dentry->d_inode, offset, cnt))) 898 (!lock_may_write(file->f_dentry->d_inode, offset, cnt)))
898 goto out; 899 goto out;
@@ -1064,7 +1065,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
1064 return err; 1065 return err;
1065 if (EX_ISSYNC(fhp->fh_export)) { 1066 if (EX_ISSYNC(fhp->fh_export)) {
1066 if (file->f_op && file->f_op->fsync) { 1067 if (file->f_op && file->f_op->fsync) {
1067 err = nfsd_sync(file); 1068 err = nfserrno(nfsd_sync(file));
1068 } else { 1069 } else {
1069 err = nfserr_notsupp; 1070 err = nfserr_notsupp;
1070 } 1071 }
@@ -1132,7 +1133,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1132 "nfsd_create: parent %s/%s not locked!\n", 1133 "nfsd_create: parent %s/%s not locked!\n",
1133 dentry->d_parent->d_name.name, 1134 dentry->d_parent->d_name.name,
1134 dentry->d_name.name); 1135 dentry->d_name.name);
1135 err = -EIO; 1136 err = nfserr_io;
1136 goto out; 1137 goto out;
1137 } 1138 }
1138 } 1139 }
@@ -1175,7 +1176,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1175 goto out_nfserr; 1176 goto out_nfserr;
1176 1177
1177 if (EX_ISSYNC(fhp->fh_export)) { 1178 if (EX_ISSYNC(fhp->fh_export)) {
1178 nfsd_sync_dir(dentry); 1179 err = nfserrno(nfsd_sync_dir(dentry));
1179 write_inode_now(dchild->d_inode, 1); 1180 write_inode_now(dchild->d_inode, 1);
1180 } 1181 }
1181 1182
@@ -1185,9 +1186,11 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1185 * send along the gid when it tries to implement setgid 1186 * send along the gid when it tries to implement setgid
1186 * directories via NFS. 1187 * directories via NFS.
1187 */ 1188 */
1188 err = 0; 1189 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) {
1189 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) 1190 int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
1190 err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); 1191 if (err2)
1192 err = err2;
1193 }
1191 /* 1194 /*
1192 * Update the file handle to get the new inode info. 1195 * Update the file handle to get the new inode info.
1193 */ 1196 */
@@ -1306,17 +1309,10 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1306 goto out_nfserr; 1309 goto out_nfserr;
1307 1310
1308 if (EX_ISSYNC(fhp->fh_export)) { 1311 if (EX_ISSYNC(fhp->fh_export)) {
1309 nfsd_sync_dir(dentry); 1312 err = nfserrno(nfsd_sync_dir(dentry));
1310 /* setattr will sync the child (or not) */ 1313 /* setattr will sync the child (or not) */
1311 } 1314 }
1312 1315
1313 /*
1314 * Update the filehandle to get the new inode info.
1315 */
1316 err = fh_update(resfhp);
1317 if (err)
1318 goto out;
1319
1320 if (createmode == NFS3_CREATE_EXCLUSIVE) { 1316 if (createmode == NFS3_CREATE_EXCLUSIVE) {
1321 /* Cram the verifier into atime/mtime/mode */ 1317 /* Cram the verifier into atime/mtime/mode */
1322 iap->ia_valid = ATTR_MTIME|ATTR_ATIME 1318 iap->ia_valid = ATTR_MTIME|ATTR_ATIME
@@ -1337,8 +1333,17 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1337 * implement setgid directories via NFS. Clear out all that cruft. 1333 * implement setgid directories via NFS. Clear out all that cruft.
1338 */ 1334 */
1339 set_attr: 1335 set_attr:
1340 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) 1336 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) {
1341 err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); 1337 int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
1338 if (err2)
1339 err = err2;
1340 }
1341
1342 /*
1343 * Update the filehandle to get the new inode info.
1344 */
1345 if (!err)
1346 err = fh_update(resfhp);
1342 1347
1343 out: 1348 out:
1344 fh_unlock(fhp); 1349 fh_unlock(fhp);
@@ -1447,10 +1452,10 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1447 } else 1452 } else
1448 err = vfs_symlink(dentry->d_inode, dnew, path, mode); 1453 err = vfs_symlink(dentry->d_inode, dnew, path, mode);
1449 1454
1450 if (!err) { 1455 if (!err)
1451 if (EX_ISSYNC(fhp->fh_export)) 1456 if (EX_ISSYNC(fhp->fh_export))
1452 nfsd_sync_dir(dentry); 1457 err = nfsd_sync_dir(dentry);
1453 } else 1458 if (err)
1454 err = nfserrno(err); 1459 err = nfserrno(err);
1455 fh_unlock(fhp); 1460 fh_unlock(fhp);
1456 1461
@@ -1506,7 +1511,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1506 err = vfs_link(dold, dirp, dnew); 1511 err = vfs_link(dold, dirp, dnew);
1507 if (!err) { 1512 if (!err) {
1508 if (EX_ISSYNC(ffhp->fh_export)) { 1513 if (EX_ISSYNC(ffhp->fh_export)) {
1509 nfsd_sync_dir(ddir); 1514 err = nfserrno(nfsd_sync_dir(ddir));
1510 write_inode_now(dest, 1); 1515 write_inode_now(dest, 1);
1511 } 1516 }
1512 } else { 1517 } else {
@@ -1590,13 +1595,14 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1590 if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) && 1595 if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1591 ((atomic_read(&odentry->d_count) > 1) 1596 ((atomic_read(&odentry->d_count) > 1)
1592 || (atomic_read(&ndentry->d_count) > 1))) { 1597 || (atomic_read(&ndentry->d_count) > 1))) {
1593 err = nfserr_perm; 1598 err = -EPERM;
1594 } else 1599 } else
1595#endif 1600#endif
1596 err = vfs_rename(fdir, odentry, tdir, ndentry); 1601 err = vfs_rename(fdir, odentry, tdir, ndentry);
1597 if (!err && EX_ISSYNC(tfhp->fh_export)) { 1602 if (!err && EX_ISSYNC(tfhp->fh_export)) {
1598 nfsd_sync_dir(tdentry); 1603 err = nfsd_sync_dir(tdentry);
1599 nfsd_sync_dir(fdentry); 1604 if (!err)
1605 err = nfsd_sync_dir(fdentry);
1600 } 1606 }
1601 1607
1602 out_dput_new: 1608 out_dput_new:
@@ -1661,7 +1667,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1661#ifdef MSNFS 1667#ifdef MSNFS
1662 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && 1668 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1663 (atomic_read(&rdentry->d_count) > 1)) { 1669 (atomic_read(&rdentry->d_count) > 1)) {
1664 err = nfserr_perm; 1670 err = -EPERM;
1665 } else 1671 } else
1666#endif 1672#endif
1667 err = vfs_unlink(dirp, rdentry); 1673 err = vfs_unlink(dirp, rdentry);
@@ -1671,17 +1677,14 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1671 1677
1672 dput(rdentry); 1678 dput(rdentry);
1673 1679
1674 if (err) 1680 if (err == 0 &&
1675 goto out_nfserr; 1681 EX_ISSYNC(fhp->fh_export))
1676 if (EX_ISSYNC(fhp->fh_export)) 1682 err = nfsd_sync_dir(dentry);
1677 nfsd_sync_dir(dentry);
1678
1679out:
1680 return err;
1681 1683
1682out_nfserr: 1684out_nfserr:
1683 err = nfserrno(err); 1685 err = nfserrno(err);
1684 goto out; 1686out:
1687 return err;
1685} 1688}
1686 1689
1687/* 1690/*
diff --git a/fs/open.c b/fs/open.c
index 8e20c1f32563..70e0230d8e77 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -20,6 +20,7 @@
20#include <linux/security.h> 20#include <linux/security.h>
21#include <linux/mount.h> 21#include <linux/mount.h>
22#include <linux/vfs.h> 22#include <linux/vfs.h>
23#include <linux/fcntl.h>
23#include <asm/uaccess.h> 24#include <asm/uaccess.h>
24#include <linux/fs.h> 25#include <linux/fs.h>
25#include <linux/personality.h> 26#include <linux/personality.h>
@@ -383,7 +384,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
383 384
384 error = get_user(newattrs.ia_atime.tv_sec, &times->actime); 385 error = get_user(newattrs.ia_atime.tv_sec, &times->actime);
385 newattrs.ia_atime.tv_nsec = 0; 386 newattrs.ia_atime.tv_nsec = 0;
386 if (!error) 387 if (!error)
387 error = get_user(newattrs.ia_mtime.tv_sec, &times->modtime); 388 error = get_user(newattrs.ia_mtime.tv_sec, &times->modtime);
388 newattrs.ia_mtime.tv_nsec = 0; 389 newattrs.ia_mtime.tv_nsec = 0;
389 if (error) 390 if (error)
@@ -414,14 +415,14 @@ out:
414 * must be owner or have write permission. 415 * must be owner or have write permission.
415 * Else, update from *times, must be owner or super user. 416 * Else, update from *times, must be owner or super user.
416 */ 417 */
417long do_utimes(char __user * filename, struct timeval * times) 418long do_utimes(int dfd, char __user *filename, struct timeval *times)
418{ 419{
419 int error; 420 int error;
420 struct nameidata nd; 421 struct nameidata nd;
421 struct inode * inode; 422 struct inode * inode;
422 struct iattr newattrs; 423 struct iattr newattrs;
423 424
424 error = user_path_walk(filename, &nd); 425 error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
425 426
426 if (error) 427 if (error)
427 goto out; 428 goto out;
@@ -461,13 +462,18 @@ out:
461 return error; 462 return error;
462} 463}
463 464
464asmlinkage long sys_utimes(char __user * filename, struct timeval __user * utimes) 465asmlinkage long sys_futimesat(int dfd, char __user *filename, struct timeval __user *utimes)
465{ 466{
466 struct timeval times[2]; 467 struct timeval times[2];
467 468
468 if (utimes && copy_from_user(&times, utimes, sizeof(times))) 469 if (utimes && copy_from_user(&times, utimes, sizeof(times)))
469 return -EFAULT; 470 return -EFAULT;
470 return do_utimes(filename, utimes ? times : NULL); 471 return do_utimes(dfd, filename, utimes ? times : NULL);
472}
473
474asmlinkage long sys_utimes(char __user *filename, struct timeval __user *utimes)
475{
476 return sys_futimesat(AT_FDCWD, filename, utimes);
471} 477}
472 478
473 479
@@ -476,7 +482,7 @@ asmlinkage long sys_utimes(char __user * filename, struct timeval __user * utime
476 * We do this by temporarily clearing all FS-related capabilities and 482 * We do this by temporarily clearing all FS-related capabilities and
477 * switching the fsuid/fsgid around to the real ones. 483 * switching the fsuid/fsgid around to the real ones.
478 */ 484 */
479asmlinkage long sys_access(const char __user * filename, int mode) 485asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
480{ 486{
481 struct nameidata nd; 487 struct nameidata nd;
482 int old_fsuid, old_fsgid; 488 int old_fsuid, old_fsgid;
@@ -506,7 +512,7 @@ asmlinkage long sys_access(const char __user * filename, int mode)
506 else 512 else
507 current->cap_effective = current->cap_permitted; 513 current->cap_effective = current->cap_permitted;
508 514
509 res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); 515 res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
510 if (!res) { 516 if (!res) {
511 res = vfs_permission(&nd, mode); 517 res = vfs_permission(&nd, mode);
512 /* SuS v2 requires we report a read only fs too */ 518 /* SuS v2 requires we report a read only fs too */
@@ -523,6 +529,11 @@ asmlinkage long sys_access(const char __user * filename, int mode)
523 return res; 529 return res;
524} 530}
525 531
532asmlinkage long sys_access(const char __user *filename, int mode)
533{
534 return sys_faccessat(AT_FDCWD, filename, mode);
535}
536
526asmlinkage long sys_chdir(const char __user * filename) 537asmlinkage long sys_chdir(const char __user * filename)
527{ 538{
528 struct nameidata nd; 539 struct nameidata nd;
@@ -635,14 +646,15 @@ out:
635 return err; 646 return err;
636} 647}
637 648
638asmlinkage long sys_chmod(const char __user * filename, mode_t mode) 649asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
650 mode_t mode)
639{ 651{
640 struct nameidata nd; 652 struct nameidata nd;
641 struct inode * inode; 653 struct inode * inode;
642 int error; 654 int error;
643 struct iattr newattrs; 655 struct iattr newattrs;
644 656
645 error = user_path_walk(filename, &nd); 657 error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
646 if (error) 658 if (error)
647 goto out; 659 goto out;
648 inode = nd.dentry->d_inode; 660 inode = nd.dentry->d_inode;
@@ -669,6 +681,11 @@ out:
669 return error; 681 return error;
670} 682}
671 683
684asmlinkage long sys_chmod(const char __user *filename, mode_t mode)
685{
686 return sys_fchmodat(AT_FDCWD, filename, mode);
687}
688
672static int chown_common(struct dentry * dentry, uid_t user, gid_t group) 689static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
673{ 690{
674 struct inode * inode; 691 struct inode * inode;
@@ -717,6 +734,26 @@ asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
717 return error; 734 return error;
718} 735}
719 736
737asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
738 gid_t group, int flag)
739{
740 struct nameidata nd;
741 int error = -EINVAL;
742 int follow;
743
744 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
745 goto out;
746
747 follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
748 error = __user_walk_fd(dfd, filename, follow, &nd);
749 if (!error) {
750 error = chown_common(nd.dentry, user, group);
751 path_release(&nd);
752 }
753out:
754 return error;
755}
756
720asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group) 757asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group)
721{ 758{
722 struct nameidata nd; 759 struct nameidata nd;
@@ -820,7 +857,8 @@ cleanup_file:
820 * for the internal routines (ie open_namei()/follow_link() etc). 00 is 857 * for the internal routines (ie open_namei()/follow_link() etc). 00 is
821 * used by symlinks. 858 * used by symlinks.
822 */ 859 */
823struct file *filp_open(const char * filename, int flags, int mode) 860static struct file *do_filp_open(int dfd, const char *filename, int flags,
861 int mode)
824{ 862{
825 int namei_flags, error; 863 int namei_flags, error;
826 struct nameidata nd; 864 struct nameidata nd;
@@ -829,12 +867,17 @@ struct file *filp_open(const char * filename, int flags, int mode)
829 if ((namei_flags+1) & O_ACCMODE) 867 if ((namei_flags+1) & O_ACCMODE)
830 namei_flags++; 868 namei_flags++;
831 869
832 error = open_namei(filename, namei_flags, mode, &nd); 870 error = open_namei(dfd, filename, namei_flags, mode, &nd);
833 if (!error) 871 if (!error)
834 return nameidata_to_filp(&nd, flags); 872 return nameidata_to_filp(&nd, flags);
835 873
836 return ERR_PTR(error); 874 return ERR_PTR(error);
837} 875}
876
877struct file *filp_open(const char *filename, int flags, int mode)
878{
879 return do_filp_open(AT_FDCWD, filename, flags, mode);
880}
838EXPORT_SYMBOL(filp_open); 881EXPORT_SYMBOL(filp_open);
839 882
840/** 883/**
@@ -991,7 +1034,7 @@ void fastcall put_unused_fd(unsigned int fd)
991EXPORT_SYMBOL(put_unused_fd); 1034EXPORT_SYMBOL(put_unused_fd);
992 1035
993/* 1036/*
994 * Install a file pointer in the fd array. 1037 * Install a file pointer in the fd array.
995 * 1038 *
996 * The VFS is full of places where we drop the files lock between 1039 * The VFS is full of places where we drop the files lock between
997 * setting the open_fds bitmap and installing the file in the file 1040 * setting the open_fds bitmap and installing the file in the file
@@ -1016,7 +1059,7 @@ void fastcall fd_install(unsigned int fd, struct file * file)
1016 1059
1017EXPORT_SYMBOL(fd_install); 1060EXPORT_SYMBOL(fd_install);
1018 1061
1019long do_sys_open(const char __user *filename, int flags, int mode) 1062long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
1020{ 1063{
1021 char *tmp = getname(filename); 1064 char *tmp = getname(filename);
1022 int fd = PTR_ERR(tmp); 1065 int fd = PTR_ERR(tmp);
@@ -1024,7 +1067,7 @@ long do_sys_open(const char __user *filename, int flags, int mode)
1024 if (!IS_ERR(tmp)) { 1067 if (!IS_ERR(tmp)) {
1025 fd = get_unused_fd(); 1068 fd = get_unused_fd();
1026 if (fd >= 0) { 1069 if (fd >= 0) {
1027 struct file *f = filp_open(tmp, flags, mode); 1070 struct file *f = do_filp_open(dfd, tmp, flags, mode);
1028 if (IS_ERR(f)) { 1071 if (IS_ERR(f)) {
1029 put_unused_fd(fd); 1072 put_unused_fd(fd);
1030 fd = PTR_ERR(f); 1073 fd = PTR_ERR(f);
@@ -1043,10 +1086,20 @@ asmlinkage long sys_open(const char __user *filename, int flags, int mode)
1043 if (force_o_largefile()) 1086 if (force_o_largefile())
1044 flags |= O_LARGEFILE; 1087 flags |= O_LARGEFILE;
1045 1088
1046 return do_sys_open(filename, flags, mode); 1089 return do_sys_open(AT_FDCWD, filename, flags, mode);
1047} 1090}
1048EXPORT_SYMBOL_GPL(sys_open); 1091EXPORT_SYMBOL_GPL(sys_open);
1049 1092
1093asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
1094 int mode)
1095{
1096 if (force_o_largefile())
1097 flags |= O_LARGEFILE;
1098
1099 return do_sys_open(dfd, filename, flags, mode);
1100}
1101EXPORT_SYMBOL_GPL(sys_openat);
1102
1050#ifndef __alpha__ 1103#ifndef __alpha__
1051 1104
1052/* 1105/*
diff --git a/fs/select.c b/fs/select.c
index f10a10317d54..c0f02d36c60e 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -179,12 +179,11 @@ get_max:
179#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR) 179#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
180#define POLLEX_SET (POLLPRI) 180#define POLLEX_SET (POLLPRI)
181 181
182int do_select(int n, fd_set_bits *fds, long *timeout) 182int do_select(int n, fd_set_bits *fds, s64 *timeout)
183{ 183{
184 struct poll_wqueues table; 184 struct poll_wqueues table;
185 poll_table *wait; 185 poll_table *wait;
186 int retval, i; 186 int retval, i;
187 long __timeout = *timeout;
188 187
189 rcu_read_lock(); 188 rcu_read_lock();
190 retval = max_select_fd(n, fds); 189 retval = max_select_fd(n, fds);
@@ -196,11 +195,12 @@ int do_select(int n, fd_set_bits *fds, long *timeout)
196 195
197 poll_initwait(&table); 196 poll_initwait(&table);
198 wait = &table.pt; 197 wait = &table.pt;
199 if (!__timeout) 198 if (!*timeout)
200 wait = NULL; 199 wait = NULL;
201 retval = 0; 200 retval = 0;
202 for (;;) { 201 for (;;) {
203 unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp; 202 unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;
203 long __timeout;
204 204
205 set_current_state(TASK_INTERRUPTIBLE); 205 set_current_state(TASK_INTERRUPTIBLE);
206 206
@@ -255,22 +255,32 @@ int do_select(int n, fd_set_bits *fds, long *timeout)
255 *rexp = res_ex; 255 *rexp = res_ex;
256 } 256 }
257 wait = NULL; 257 wait = NULL;
258 if (retval || !__timeout || signal_pending(current)) 258 if (retval || !*timeout || signal_pending(current))
259 break; 259 break;
260 if(table.error) { 260 if(table.error) {
261 retval = table.error; 261 retval = table.error;
262 break; 262 break;
263 } 263 }
264
265 if (*timeout < 0) {
266 /* Wait indefinitely */
267 __timeout = MAX_SCHEDULE_TIMEOUT;
268 } else if (unlikely(*timeout >= (s64)MAX_SCHEDULE_TIMEOUT - 1)) {
269 /* Wait for longer than MAX_SCHEDULE_TIMEOUT. Do it in a loop */
270 __timeout = MAX_SCHEDULE_TIMEOUT - 1;
271 *timeout -= __timeout;
272 } else {
273 __timeout = *timeout;
274 *timeout = 0;
275 }
264 __timeout = schedule_timeout(__timeout); 276 __timeout = schedule_timeout(__timeout);
277 if (*timeout >= 0)
278 *timeout += __timeout;
265 } 279 }
266 __set_current_state(TASK_RUNNING); 280 __set_current_state(TASK_RUNNING);
267 281
268 poll_freewait(&table); 282 poll_freewait(&table);
269 283
270 /*
271 * Up-to-date the caller timeout.
272 */
273 *timeout = __timeout;
274 return retval; 284 return retval;
275} 285}
276 286
@@ -295,36 +305,14 @@ static void select_bits_free(void *bits, int size)
295#define MAX_SELECT_SECONDS \ 305#define MAX_SELECT_SECONDS \
296 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) 306 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
297 307
298asmlinkage long 308static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
299sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp) 309 fd_set __user *exp, s64 *timeout)
300{ 310{
301 fd_set_bits fds; 311 fd_set_bits fds;
302 char *bits; 312 char *bits;
303 long timeout;
304 int ret, size, max_fdset; 313 int ret, size, max_fdset;
305 struct fdtable *fdt; 314 struct fdtable *fdt;
306 315
307 timeout = MAX_SCHEDULE_TIMEOUT;
308 if (tvp) {
309 time_t sec, usec;
310
311 if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
312 || __get_user(sec, &tvp->tv_sec)
313 || __get_user(usec, &tvp->tv_usec)) {
314 ret = -EFAULT;
315 goto out_nofds;
316 }
317
318 ret = -EINVAL;
319 if (sec < 0 || usec < 0)
320 goto out_nofds;
321
322 if ((unsigned long) sec < MAX_SELECT_SECONDS) {
323 timeout = ROUND_UP(usec, 1000000/HZ);
324 timeout += sec * (unsigned long) HZ;
325 }
326 }
327
328 ret = -EINVAL; 316 ret = -EINVAL;
329 if (n < 0) 317 if (n < 0)
330 goto out_nofds; 318 goto out_nofds;
@@ -362,18 +350,7 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s
362 zero_fd_set(n, fds.res_out); 350 zero_fd_set(n, fds.res_out);
363 zero_fd_set(n, fds.res_ex); 351 zero_fd_set(n, fds.res_ex);
364 352
365 ret = do_select(n, &fds, &timeout); 353 ret = do_select(n, &fds, timeout);
366
367 if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
368 time_t sec = 0, usec = 0;
369 if (timeout) {
370 sec = timeout / HZ;
371 usec = timeout % HZ;
372 usec *= (1000000/HZ);
373 }
374 put_user(sec, &tvp->tv_sec);
375 put_user(usec, &tvp->tv_usec);
376 }
377 354
378 if (ret < 0) 355 if (ret < 0)
379 goto out; 356 goto out;
@@ -395,6 +372,154 @@ out_nofds:
395 return ret; 372 return ret;
396} 373}
397 374
375asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
376 fd_set __user *exp, struct timeval __user *tvp)
377{
378 s64 timeout = -1;
379 struct timeval tv;
380 int ret;
381
382 if (tvp) {
383 if (copy_from_user(&tv, tvp, sizeof(tv)))
384 return -EFAULT;
385
386 if (tv.tv_sec < 0 || tv.tv_usec < 0)
387 return -EINVAL;
388
389 /* Cast to u64 to make GCC stop complaining */
390 if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
391 timeout = -1; /* infinite */
392 else {
393 timeout = ROUND_UP(tv.tv_usec, USEC_PER_SEC/HZ);
394 timeout += tv.tv_sec * HZ;
395 }
396 }
397
398 ret = core_sys_select(n, inp, outp, exp, &timeout);
399
400 if (tvp) {
401 if (current->personality & STICKY_TIMEOUTS)
402 goto sticky;
403 tv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
404 tv.tv_sec = timeout;
405 if (copy_to_user(tvp, &tv, sizeof(tv))) {
406sticky:
407 /*
408 * If an application puts its timeval in read-only
409 * memory, we don't want the Linux-specific update to
410 * the timeval to cause a fault after the select has
411 * completed successfully. However, because we're not
412 * updating the timeval, we can't restart the system
413 * call.
414 */
415 if (ret == -ERESTARTNOHAND)
416 ret = -EINTR;
417 }
418 }
419
420 return ret;
421}
422
423#ifdef TIF_RESTORE_SIGMASK
424asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp,
425 fd_set __user *exp, struct timespec __user *tsp,
426 const sigset_t __user *sigmask, size_t sigsetsize)
427{
428 s64 timeout = MAX_SCHEDULE_TIMEOUT;
429 sigset_t ksigmask, sigsaved;
430 struct timespec ts;
431 int ret;
432
433 if (tsp) {
434 if (copy_from_user(&ts, tsp, sizeof(ts)))
435 return -EFAULT;
436
437 if (ts.tv_sec < 0 || ts.tv_nsec < 0)
438 return -EINVAL;
439
440 /* Cast to u64 to make GCC stop complaining */
441 if ((u64)ts.tv_sec >= (u64)MAX_INT64_SECONDS)
442 timeout = -1; /* infinite */
443 else {
444 timeout = ROUND_UP(ts.tv_nsec, NSEC_PER_SEC/HZ);
445 timeout += ts.tv_sec * HZ;
446 }
447 }
448
449 if (sigmask) {
450 /* XXX: Don't preclude handling different sized sigset_t's. */
451 if (sigsetsize != sizeof(sigset_t))
452 return -EINVAL;
453 if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
454 return -EFAULT;
455
456 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
457 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
458 }
459
460 ret = core_sys_select(n, inp, outp, exp, &timeout);
461
462 if (tsp) {
463 if (current->personality & STICKY_TIMEOUTS)
464 goto sticky;
465 ts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * 1000;
466 ts.tv_sec = timeout;
467 if (copy_to_user(tsp, &ts, sizeof(ts))) {
468sticky:
469 /*
470 * If an application puts its timeval in read-only
471 * memory, we don't want the Linux-specific update to
472 * the timeval to cause a fault after the select has
473 * completed successfully. However, because we're not
474 * updating the timeval, we can't restart the system
475 * call.
476 */
477 if (ret == -ERESTARTNOHAND)
478 ret = -EINTR;
479 }
480 }
481
482 if (ret == -ERESTARTNOHAND) {
483 /*
484 * Don't restore the signal mask yet. Let do_signal() deliver
485 * the signal on the way back to userspace, before the signal
486 * mask is restored.
487 */
488 if (sigmask) {
489 memcpy(&current->saved_sigmask, &sigsaved,
490 sizeof(sigsaved));
491 set_thread_flag(TIF_RESTORE_SIGMASK);
492 }
493 } else if (sigmask)
494 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
495
496 return ret;
497}
498
499/*
500 * Most architectures can't handle 7-argument syscalls. So we provide a
501 * 6-argument version where the sixth argument is a pointer to a structure
502 * which has a pointer to the sigset_t itself followed by a size_t containing
503 * the sigset size.
504 */
505asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp,
506 fd_set __user *exp, struct timespec __user *tsp, void __user *sig)
507{
508 size_t sigsetsize = 0;
509 sigset_t __user *up = NULL;
510
511 if (sig) {
512 if (!access_ok(VERIFY_READ, sig, sizeof(void *)+sizeof(size_t))
513 || __get_user(up, (sigset_t * __user *)sig)
514 || __get_user(sigsetsize,
515 (size_t * __user)(sig+sizeof(void *))))
516 return -EFAULT;
517 }
518
519 return sys_pselect7(n, inp, outp, exp, tsp, up, sigsetsize);
520}
521#endif /* TIF_RESTORE_SIGMASK */
522
398struct poll_list { 523struct poll_list {
399 struct poll_list *next; 524 struct poll_list *next;
400 int len; 525 int len;
@@ -436,16 +561,19 @@ static void do_pollfd(unsigned int num, struct pollfd * fdpage,
436} 561}
437 562
438static int do_poll(unsigned int nfds, struct poll_list *list, 563static int do_poll(unsigned int nfds, struct poll_list *list,
439 struct poll_wqueues *wait, long timeout) 564 struct poll_wqueues *wait, s64 *timeout)
440{ 565{
441 int count = 0; 566 int count = 0;
442 poll_table* pt = &wait->pt; 567 poll_table* pt = &wait->pt;
443 568
444 if (!timeout) 569 /* Optimise the no-wait case */
570 if (!(*timeout))
445 pt = NULL; 571 pt = NULL;
446 572
447 for (;;) { 573 for (;;) {
448 struct poll_list *walk; 574 struct poll_list *walk;
575 long __timeout;
576
449 set_current_state(TASK_INTERRUPTIBLE); 577 set_current_state(TASK_INTERRUPTIBLE);
450 walk = list; 578 walk = list;
451 while(walk != NULL) { 579 while(walk != NULL) {
@@ -453,18 +581,36 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
453 walk = walk->next; 581 walk = walk->next;
454 } 582 }
455 pt = NULL; 583 pt = NULL;
456 if (count || !timeout || signal_pending(current)) 584 if (count || !*timeout || signal_pending(current))
457 break; 585 break;
458 count = wait->error; 586 count = wait->error;
459 if (count) 587 if (count)
460 break; 588 break;
461 timeout = schedule_timeout(timeout); 589
590 if (*timeout < 0) {
591 /* Wait indefinitely */
592 __timeout = MAX_SCHEDULE_TIMEOUT;
593 } else if (unlikely(*timeout >= (s64)MAX_SCHEDULE_TIMEOUT-1)) {
594 /*
595 * Wait for longer than MAX_SCHEDULE_TIMEOUT. Do it in
596 * a loop
597 */
598 __timeout = MAX_SCHEDULE_TIMEOUT - 1;
599 *timeout -= __timeout;
600 } else {
601 __timeout = *timeout;
602 *timeout = 0;
603 }
604
605 __timeout = schedule_timeout(__timeout);
606 if (*timeout >= 0)
607 *timeout += __timeout;
462 } 608 }
463 __set_current_state(TASK_RUNNING); 609 __set_current_state(TASK_RUNNING);
464 return count; 610 return count;
465} 611}
466 612
467asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long timeout) 613int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
468{ 614{
469 struct poll_wqueues table; 615 struct poll_wqueues table;
470 int fdcount, err; 616 int fdcount, err;
@@ -482,14 +628,6 @@ asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long ti
482 if (nfds > max_fdset && nfds > OPEN_MAX) 628 if (nfds > max_fdset && nfds > OPEN_MAX)
483 return -EINVAL; 629 return -EINVAL;
484 630
485 if (timeout) {
486 /* Careful about overflow in the intermediate values */
487 if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ)
488 timeout = (unsigned long)(timeout*HZ+999)/1000+1;
489 else /* Negative or overflow */
490 timeout = MAX_SCHEDULE_TIMEOUT;
491 }
492
493 poll_initwait(&table); 631 poll_initwait(&table);
494 632
495 head = NULL; 633 head = NULL;
@@ -519,6 +657,7 @@ asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long ti
519 } 657 }
520 i -= pp->len; 658 i -= pp->len;
521 } 659 }
660
522 fdcount = do_poll(nfds, head, &table, timeout); 661 fdcount = do_poll(nfds, head, &table, timeout);
523 662
524 /* OK, now copy the revents fields back to user space. */ 663 /* OK, now copy the revents fields back to user space. */
@@ -547,3 +686,98 @@ out_fds:
547 poll_freewait(&table); 686 poll_freewait(&table);
548 return err; 687 return err;
549} 688}
689
690asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
691 long timeout_msecs)
692{
693 s64 timeout_jiffies = 0;
694
695 if (timeout_msecs) {
696#if HZ > 1000
697 /* We can only overflow if HZ > 1000 */
698 if (timeout_msecs / 1000 > (s64)0x7fffffffffffffffULL / (s64)HZ)
699 timeout_jiffies = -1;
700 else
701#endif
702 timeout_jiffies = msecs_to_jiffies(timeout_msecs);
703 }
704
705 return do_sys_poll(ufds, nfds, &timeout_jiffies);
706}
707
708#ifdef TIF_RESTORE_SIGMASK
709asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
710 struct timespec __user *tsp, const sigset_t __user *sigmask,
711 size_t sigsetsize)
712{
713 sigset_t ksigmask, sigsaved;
714 struct timespec ts;
715 s64 timeout = -1;
716 int ret;
717
718 if (tsp) {
719 if (copy_from_user(&ts, tsp, sizeof(ts)))
720 return -EFAULT;
721
722 /* Cast to u64 to make GCC stop complaining */
723 if ((u64)ts.tv_sec >= (u64)MAX_INT64_SECONDS)
724 timeout = -1; /* infinite */
725 else {
726 timeout = ROUND_UP(ts.tv_nsec, NSEC_PER_SEC/HZ);
727 timeout += ts.tv_sec * HZ;
728 }
729 }
730
731 if (sigmask) {
732 /* XXX: Don't preclude handling different sized sigset_t's. */
733 if (sigsetsize != sizeof(sigset_t))
734 return -EINVAL;
735 if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
736 return -EFAULT;
737
738 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
739 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
740 }
741
742 ret = do_sys_poll(ufds, nfds, &timeout);
743
744 /* We can restart this syscall, usually */
745 if (ret == -EINTR) {
746 /*
747 * Don't restore the signal mask yet. Let do_signal() deliver
748 * the signal on the way back to userspace, before the signal
749 * mask is restored.
750 */
751 if (sigmask) {
752 memcpy(&current->saved_sigmask, &sigsaved,
753 sizeof(sigsaved));
754 set_thread_flag(TIF_RESTORE_SIGMASK);
755 }
756 ret = -ERESTARTNOHAND;
757 } else if (sigmask)
758 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
759
760 if (tsp && timeout >= 0) {
761 if (current->personality & STICKY_TIMEOUTS)
762 goto sticky;
763 /* Yes, we know it's actually an s64, but it's also positive. */
764 ts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * 1000;
765 ts.tv_sec = timeout;
766 if (copy_to_user(tsp, &ts, sizeof(ts))) {
767 sticky:
768 /*
769 * If an application puts its timeval in read-only
770 * memory, we don't want the Linux-specific update to
771 * the timeval to cause a fault after the select has
772 * completed successfully. However, because we're not
773 * updating the timeval, we can't restart the system
774 * call.
775 */
776 if (ret == -ERESTARTNOHAND && timeout >= 0)
777 ret = -EINTR;
778 }
779 }
780
781 return ret;
782}
783#endif /* TIF_RESTORE_SIGMASK */
diff --git a/fs/stat.c b/fs/stat.c
index b8a0e5110ab2..24211b030f39 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -63,12 +63,12 @@ int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
63 63
64EXPORT_SYMBOL(vfs_getattr); 64EXPORT_SYMBOL(vfs_getattr);
65 65
66int vfs_stat(char __user *name, struct kstat *stat) 66int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
67{ 67{
68 struct nameidata nd; 68 struct nameidata nd;
69 int error; 69 int error;
70 70
71 error = user_path_walk(name, &nd); 71 error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
72 if (!error) { 72 if (!error) {
73 error = vfs_getattr(nd.mnt, nd.dentry, stat); 73 error = vfs_getattr(nd.mnt, nd.dentry, stat);
74 path_release(&nd); 74 path_release(&nd);
@@ -76,14 +76,19 @@ int vfs_stat(char __user *name, struct kstat *stat)
76 return error; 76 return error;
77} 77}
78 78
79int vfs_stat(char __user *name, struct kstat *stat)
80{
81 return vfs_stat_fd(AT_FDCWD, name, stat);
82}
83
79EXPORT_SYMBOL(vfs_stat); 84EXPORT_SYMBOL(vfs_stat);
80 85
81int vfs_lstat(char __user *name, struct kstat *stat) 86int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat)
82{ 87{
83 struct nameidata nd; 88 struct nameidata nd;
84 int error; 89 int error;
85 90
86 error = user_path_walk_link(name, &nd); 91 error = __user_walk_fd(dfd, name, 0, &nd);
87 if (!error) { 92 if (!error) {
88 error = vfs_getattr(nd.mnt, nd.dentry, stat); 93 error = vfs_getattr(nd.mnt, nd.dentry, stat);
89 path_release(&nd); 94 path_release(&nd);
@@ -91,6 +96,11 @@ int vfs_lstat(char __user *name, struct kstat *stat)
91 return error; 96 return error;
92} 97}
93 98
99int vfs_lstat(char __user *name, struct kstat *stat)
100{
101 return vfs_lstat_fd(AT_FDCWD, name, stat);
102}
103
94EXPORT_SYMBOL(vfs_lstat); 104EXPORT_SYMBOL(vfs_lstat);
95 105
96int vfs_fstat(unsigned int fd, struct kstat *stat) 106int vfs_fstat(unsigned int fd, struct kstat *stat)
@@ -151,7 +161,7 @@ static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * sta
151asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user * statbuf) 161asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user * statbuf)
152{ 162{
153 struct kstat stat; 163 struct kstat stat;
154 int error = vfs_stat(filename, &stat); 164 int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
155 165
156 if (!error) 166 if (!error)
157 error = cp_old_stat(&stat, statbuf); 167 error = cp_old_stat(&stat, statbuf);
@@ -161,7 +171,7 @@ asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user
161asmlinkage long sys_lstat(char __user * filename, struct __old_kernel_stat __user * statbuf) 171asmlinkage long sys_lstat(char __user * filename, struct __old_kernel_stat __user * statbuf)
162{ 172{
163 struct kstat stat; 173 struct kstat stat;
164 int error = vfs_lstat(filename, &stat); 174 int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
165 175
166 if (!error) 176 if (!error)
167 error = cp_old_stat(&stat, statbuf); 177 error = cp_old_stat(&stat, statbuf);
@@ -229,27 +239,50 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
229 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 239 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
230} 240}
231 241
232asmlinkage long sys_newstat(char __user * filename, struct stat __user * statbuf) 242asmlinkage long sys_newstat(char __user *filename, struct stat __user *statbuf)
233{ 243{
234 struct kstat stat; 244 struct kstat stat;
235 int error = vfs_stat(filename, &stat); 245 int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
236 246
237 if (!error) 247 if (!error)
238 error = cp_new_stat(&stat, statbuf); 248 error = cp_new_stat(&stat, statbuf);
239 249
240 return error; 250 return error;
241} 251}
242asmlinkage long sys_newlstat(char __user * filename, struct stat __user * statbuf) 252
253asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf)
243{ 254{
244 struct kstat stat; 255 struct kstat stat;
245 int error = vfs_lstat(filename, &stat); 256 int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
246 257
247 if (!error) 258 if (!error)
248 error = cp_new_stat(&stat, statbuf); 259 error = cp_new_stat(&stat, statbuf);
249 260
250 return error; 261 return error;
251} 262}
252asmlinkage long sys_newfstat(unsigned int fd, struct stat __user * statbuf) 263
264asmlinkage long sys_newfstatat(int dfd, char __user *filename,
265 struct stat __user *statbuf, int flag)
266{
267 struct kstat stat;
268 int error = -EINVAL;
269
270 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
271 goto out;
272
273 if (flag & AT_SYMLINK_NOFOLLOW)
274 error = vfs_lstat_fd(dfd, filename, &stat);
275 else
276 error = vfs_stat_fd(dfd, filename, &stat);
277
278 if (!error)
279 error = cp_new_stat(&stat, statbuf);
280
281out:
282 return error;
283}
284
285asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf)
253{ 286{
254 struct kstat stat; 287 struct kstat stat;
255 int error = vfs_fstat(fd, &stat); 288 int error = vfs_fstat(fd, &stat);
@@ -260,7 +293,8 @@ asmlinkage long sys_newfstat(unsigned int fd, struct stat __user * statbuf)
260 return error; 293 return error;
261} 294}
262 295
263asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bufsiz) 296asmlinkage long sys_readlinkat(int dfd, const char __user *path,
297 char __user *buf, int bufsiz)
264{ 298{
265 struct nameidata nd; 299 struct nameidata nd;
266 int error; 300 int error;
@@ -268,7 +302,7 @@ asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bu
268 if (bufsiz <= 0) 302 if (bufsiz <= 0)
269 return -EINVAL; 303 return -EINVAL;
270 304
271 error = user_path_walk_link(path, &nd); 305 error = __user_walk_fd(dfd, path, 0, &nd);
272 if (!error) { 306 if (!error) {
273 struct inode * inode = nd.dentry->d_inode; 307 struct inode * inode = nd.dentry->d_inode;
274 308
@@ -285,6 +319,12 @@ asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bu
285 return error; 319 return error;
286} 320}
287 321
322asmlinkage long sys_readlink(const char __user *path, char __user *buf,
323 int bufsiz)
324{
325 return sys_readlinkat(AT_FDCWD, path, buf, bufsiz);
326}
327
288 328
289/* ---------- LFS-64 ----------- */ 329/* ---------- LFS-64 ----------- */
290#ifdef __ARCH_WANT_STAT64 330#ifdef __ARCH_WANT_STAT64
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index d1db8c17a74e..120626789406 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -336,24 +336,47 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)
336} 336}
337 337
338/* 338/*
339 * Submit all of the bios for all of the ioends we have saved up, 339 * Submit all of the bios for all of the ioends we have saved up, covering the
340 * covering the initial writepage page and also any probed pages. 340 * initial writepage page and also any probed pages.
341 *
342 * Because we may have multiple ioends spanning a page, we need to start
343 * writeback on all the buffers before we submit them for I/O. If we mark the
344 * buffers as we got, then we can end up with a page that only has buffers
345 * marked async write and I/O complete on can occur before we mark the other
346 * buffers async write.
347 *
348 * The end result of this is that we trip a bug in end_page_writeback() because
349 * we call it twice for the one page as the code in end_buffer_async_write()
350 * assumes that all buffers on the page are started at the same time.
351 *
352 * The fix is two passes across the ioend list - one to start writeback on the
353 * bufferheads, and then the second one submit them for I/O.
341 */ 354 */
342STATIC void 355STATIC void
343xfs_submit_ioend( 356xfs_submit_ioend(
344 xfs_ioend_t *ioend) 357 xfs_ioend_t *ioend)
345{ 358{
359 xfs_ioend_t *head = ioend;
346 xfs_ioend_t *next; 360 xfs_ioend_t *next;
347 struct buffer_head *bh; 361 struct buffer_head *bh;
348 struct bio *bio; 362 struct bio *bio;
349 sector_t lastblock = 0; 363 sector_t lastblock = 0;
350 364
365 /* Pass 1 - start writeback */
366 do {
367 next = ioend->io_list;
368 for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) {
369 xfs_start_buffer_writeback(bh);
370 }
371 } while ((ioend = next) != NULL);
372
373 /* Pass 2 - submit I/O */
374 ioend = head;
351 do { 375 do {
352 next = ioend->io_list; 376 next = ioend->io_list;
353 bio = NULL; 377 bio = NULL;
354 378
355 for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) { 379 for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) {
356 xfs_start_buffer_writeback(bh);
357 380
358 if (!bio) { 381 if (!bio) {
359 retry: 382 retry: