diff options
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 101 |
1 files changed, 61 insertions, 40 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index d0b991a92327..937fbfc381bb 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -65,7 +65,7 @@ static int nfs_write_inode(struct inode *,int); | |||
65 | static void nfs_delete_inode(struct inode *); | 65 | static void nfs_delete_inode(struct inode *); |
66 | static void nfs_clear_inode(struct inode *); | 66 | static void nfs_clear_inode(struct inode *); |
67 | static void nfs_umount_begin(struct super_block *); | 67 | static void nfs_umount_begin(struct super_block *); |
68 | static int nfs_statfs(struct super_block *, struct kstatfs *); | 68 | static int nfs_statfs(struct dentry *, struct kstatfs *); |
69 | static int nfs_show_options(struct seq_file *, struct vfsmount *); | 69 | static int nfs_show_options(struct seq_file *, struct vfsmount *); |
70 | static int nfs_show_stats(struct seq_file *, struct vfsmount *); | 70 | static int nfs_show_stats(struct seq_file *, struct vfsmount *); |
71 | static void nfs_zap_acl_cache(struct inode *); | 71 | static void nfs_zap_acl_cache(struct inode *); |
@@ -534,8 +534,9 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent) | |||
534 | } | 534 | } |
535 | 535 | ||
536 | static int | 536 | static int |
537 | nfs_statfs(struct super_block *sb, struct kstatfs *buf) | 537 | nfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
538 | { | 538 | { |
539 | struct super_block *sb = dentry->d_sb; | ||
539 | struct nfs_server *server = NFS_SB(sb); | 540 | struct nfs_server *server = NFS_SB(sb); |
540 | unsigned char blockbits; | 541 | unsigned char blockbits; |
541 | unsigned long blockres; | 542 | unsigned long blockres; |
@@ -1690,8 +1691,8 @@ static int nfs_compare_super(struct super_block *sb, void *data) | |||
1690 | return !nfs_compare_fh(&old->fh, &server->fh); | 1691 | return !nfs_compare_fh(&old->fh, &server->fh); |
1691 | } | 1692 | } |
1692 | 1693 | ||
1693 | static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | 1694 | static int nfs_get_sb(struct file_system_type *fs_type, |
1694 | int flags, const char *dev_name, void *raw_data) | 1695 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) |
1695 | { | 1696 | { |
1696 | int error; | 1697 | int error; |
1697 | struct nfs_server *server = NULL; | 1698 | struct nfs_server *server = NULL; |
@@ -1699,14 +1700,14 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1699 | struct nfs_fh *root; | 1700 | struct nfs_fh *root; |
1700 | struct nfs_mount_data *data = raw_data; | 1701 | struct nfs_mount_data *data = raw_data; |
1701 | 1702 | ||
1702 | s = ERR_PTR(-EINVAL); | 1703 | error = -EINVAL; |
1703 | if (data == NULL) { | 1704 | if (data == NULL) { |
1704 | dprintk("%s: missing data argument\n", __FUNCTION__); | 1705 | dprintk("%s: missing data argument\n", __FUNCTION__); |
1705 | goto out_err; | 1706 | goto out_err_noserver; |
1706 | } | 1707 | } |
1707 | if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { | 1708 | if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { |
1708 | dprintk("%s: bad mount version\n", __FUNCTION__); | 1709 | dprintk("%s: bad mount version\n", __FUNCTION__); |
1709 | goto out_err; | 1710 | goto out_err_noserver; |
1710 | } | 1711 | } |
1711 | switch (data->version) { | 1712 | switch (data->version) { |
1712 | case 1: | 1713 | case 1: |
@@ -1718,7 +1719,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1718 | dprintk("%s: mount structure version %d does not support NFSv3\n", | 1719 | dprintk("%s: mount structure version %d does not support NFSv3\n", |
1719 | __FUNCTION__, | 1720 | __FUNCTION__, |
1720 | data->version); | 1721 | data->version); |
1721 | goto out_err; | 1722 | goto out_err_noserver; |
1722 | } | 1723 | } |
1723 | data->root.size = NFS2_FHSIZE; | 1724 | data->root.size = NFS2_FHSIZE; |
1724 | memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); | 1725 | memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); |
@@ -1727,24 +1728,24 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1727 | dprintk("%s: mount structure version %d does not support strong security\n", | 1728 | dprintk("%s: mount structure version %d does not support strong security\n", |
1728 | __FUNCTION__, | 1729 | __FUNCTION__, |
1729 | data->version); | 1730 | data->version); |
1730 | goto out_err; | 1731 | goto out_err_noserver; |
1731 | } | 1732 | } |
1732 | case 5: | 1733 | case 5: |
1733 | memset(data->context, 0, sizeof(data->context)); | 1734 | memset(data->context, 0, sizeof(data->context)); |
1734 | } | 1735 | } |
1735 | #ifndef CONFIG_NFS_V3 | 1736 | #ifndef CONFIG_NFS_V3 |
1736 | /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ | 1737 | /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ |
1737 | s = ERR_PTR(-EPROTONOSUPPORT); | 1738 | error = -EPROTONOSUPPORT; |
1738 | if (data->flags & NFS_MOUNT_VER3) { | 1739 | if (data->flags & NFS_MOUNT_VER3) { |
1739 | dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); | 1740 | dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); |
1740 | goto out_err; | 1741 | goto out_err_noserver; |
1741 | } | 1742 | } |
1742 | #endif /* CONFIG_NFS_V3 */ | 1743 | #endif /* CONFIG_NFS_V3 */ |
1743 | 1744 | ||
1744 | s = ERR_PTR(-ENOMEM); | 1745 | error = -ENOMEM; |
1745 | server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); | 1746 | server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); |
1746 | if (!server) | 1747 | if (!server) |
1747 | goto out_err; | 1748 | goto out_err_noserver; |
1748 | /* Zero out the NFS state stuff */ | 1749 | /* Zero out the NFS state stuff */ |
1749 | init_nfsv4_state(server); | 1750 | init_nfsv4_state(server); |
1750 | server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); | 1751 | server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); |
@@ -1754,7 +1755,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1754 | root->size = data->root.size; | 1755 | root->size = data->root.size; |
1755 | else | 1756 | else |
1756 | root->size = NFS2_FHSIZE; | 1757 | root->size = NFS2_FHSIZE; |
1757 | s = ERR_PTR(-EINVAL); | 1758 | error = -EINVAL; |
1758 | if (root->size > sizeof(root->data)) { | 1759 | if (root->size > sizeof(root->data)) { |
1759 | dprintk("%s: invalid root filehandle\n", __FUNCTION__); | 1760 | dprintk("%s: invalid root filehandle\n", __FUNCTION__); |
1760 | goto out_err; | 1761 | goto out_err; |
@@ -1770,15 +1771,20 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1770 | } | 1771 | } |
1771 | 1772 | ||
1772 | /* Fire up rpciod if not yet running */ | 1773 | /* Fire up rpciod if not yet running */ |
1773 | s = ERR_PTR(rpciod_up()); | 1774 | error = rpciod_up(); |
1774 | if (IS_ERR(s)) { | 1775 | if (error < 0) { |
1775 | dprintk("%s: couldn't start rpciod! Error = %ld\n", | 1776 | dprintk("%s: couldn't start rpciod! Error = %d\n", |
1776 | __FUNCTION__, PTR_ERR(s)); | 1777 | __FUNCTION__, error); |
1777 | goto out_err; | 1778 | goto out_err; |
1778 | } | 1779 | } |
1779 | 1780 | ||
1780 | s = sget(fs_type, nfs_compare_super, nfs_set_super, server); | 1781 | s = sget(fs_type, nfs_compare_super, nfs_set_super, server); |
1781 | if (IS_ERR(s) || s->s_root) | 1782 | if (IS_ERR(s)) { |
1783 | error = PTR_ERR(s); | ||
1784 | goto out_err_rpciod; | ||
1785 | } | ||
1786 | |||
1787 | if (s->s_root) | ||
1782 | goto out_rpciod_down; | 1788 | goto out_rpciod_down; |
1783 | 1789 | ||
1784 | s->s_flags = flags; | 1790 | s->s_flags = flags; |
@@ -1787,15 +1793,22 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1787 | if (error) { | 1793 | if (error) { |
1788 | up_write(&s->s_umount); | 1794 | up_write(&s->s_umount); |
1789 | deactivate_super(s); | 1795 | deactivate_super(s); |
1790 | return ERR_PTR(error); | 1796 | return error; |
1791 | } | 1797 | } |
1792 | s->s_flags |= MS_ACTIVE; | 1798 | s->s_flags |= MS_ACTIVE; |
1793 | return s; | 1799 | return simple_set_mnt(mnt, s); |
1800 | |||
1794 | out_rpciod_down: | 1801 | out_rpciod_down: |
1795 | rpciod_down(); | 1802 | rpciod_down(); |
1803 | kfree(server); | ||
1804 | return simple_set_mnt(mnt, s); | ||
1805 | |||
1806 | out_err_rpciod: | ||
1807 | rpciod_down(); | ||
1796 | out_err: | 1808 | out_err: |
1797 | kfree(server); | 1809 | kfree(server); |
1798 | return s; | 1810 | out_err_noserver: |
1811 | return error; | ||
1799 | } | 1812 | } |
1800 | 1813 | ||
1801 | static void nfs_kill_super(struct super_block *s) | 1814 | static void nfs_kill_super(struct super_block *s) |
@@ -2032,8 +2045,8 @@ nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) | |||
2032 | return dst; | 2045 | return dst; |
2033 | } | 2046 | } |
2034 | 2047 | ||
2035 | static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, | 2048 | static int nfs4_get_sb(struct file_system_type *fs_type, |
2036 | int flags, const char *dev_name, void *raw_data) | 2049 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) |
2037 | { | 2050 | { |
2038 | int error; | 2051 | int error; |
2039 | struct nfs_server *server; | 2052 | struct nfs_server *server; |
@@ -2043,16 +2056,16 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, | |||
2043 | 2056 | ||
2044 | if (data == NULL) { | 2057 | if (data == NULL) { |
2045 | dprintk("%s: missing data argument\n", __FUNCTION__); | 2058 | dprintk("%s: missing data argument\n", __FUNCTION__); |
2046 | return ERR_PTR(-EINVAL); | 2059 | return -EINVAL; |
2047 | } | 2060 | } |
2048 | if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { | 2061 | if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { |
2049 | dprintk("%s: bad mount version\n", __FUNCTION__); | 2062 | dprintk("%s: bad mount version\n", __FUNCTION__); |
2050 | return ERR_PTR(-EINVAL); | 2063 | return -EINVAL; |
2051 | } | 2064 | } |
2052 | 2065 | ||
2053 | server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); | 2066 | server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); |
2054 | if (!server) | 2067 | if (!server) |
2055 | return ERR_PTR(-ENOMEM); | 2068 | return -ENOMEM; |
2056 | /* Zero out the NFS state stuff */ | 2069 | /* Zero out the NFS state stuff */ |
2057 | init_nfsv4_state(server); | 2070 | init_nfsv4_state(server); |
2058 | server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); | 2071 | server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); |
@@ -2074,33 +2087,41 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, | |||
2074 | 2087 | ||
2075 | /* We now require that the mount process passes the remote address */ | 2088 | /* We now require that the mount process passes the remote address */ |
2076 | if (data->host_addrlen != sizeof(server->addr)) { | 2089 | if (data->host_addrlen != sizeof(server->addr)) { |
2077 | s = ERR_PTR(-EINVAL); | 2090 | error = -EINVAL; |
2078 | goto out_free; | 2091 | goto out_free; |
2079 | } | 2092 | } |
2080 | if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { | 2093 | if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { |
2081 | s = ERR_PTR(-EFAULT); | 2094 | error = -EFAULT; |
2082 | goto out_free; | 2095 | goto out_free; |
2083 | } | 2096 | } |
2084 | if (server->addr.sin_family != AF_INET || | 2097 | if (server->addr.sin_family != AF_INET || |
2085 | server->addr.sin_addr.s_addr == INADDR_ANY) { | 2098 | server->addr.sin_addr.s_addr == INADDR_ANY) { |
2086 | dprintk("%s: mount program didn't pass remote IP address!\n", | 2099 | dprintk("%s: mount program didn't pass remote IP address!\n", |
2087 | __FUNCTION__); | 2100 | __FUNCTION__); |
2088 | s = ERR_PTR(-EINVAL); | 2101 | error = -EINVAL; |
2089 | goto out_free; | 2102 | goto out_free; |
2090 | } | 2103 | } |
2091 | 2104 | ||
2092 | /* Fire up rpciod if not yet running */ | 2105 | /* Fire up rpciod if not yet running */ |
2093 | s = ERR_PTR(rpciod_up()); | 2106 | error = rpciod_up(); |
2094 | if (IS_ERR(s)) { | 2107 | if (error < 0) { |
2095 | dprintk("%s: couldn't start rpciod! Error = %ld\n", | 2108 | dprintk("%s: couldn't start rpciod! Error = %d\n", |
2096 | __FUNCTION__, PTR_ERR(s)); | 2109 | __FUNCTION__, error); |
2097 | goto out_free; | 2110 | goto out_free; |
2098 | } | 2111 | } |
2099 | 2112 | ||
2100 | s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); | 2113 | s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); |
2101 | 2114 | if (IS_ERR(s)) { | |
2102 | if (IS_ERR(s) || s->s_root) | 2115 | error = PTR_ERR(s); |
2103 | goto out_free; | 2116 | goto out_free; |
2117 | } | ||
2118 | |||
2119 | if (s->s_root) { | ||
2120 | kfree(server->mnt_path); | ||
2121 | kfree(server->hostname); | ||
2122 | kfree(server); | ||
2123 | return simple_set_mnt(mnt, s); | ||
2124 | } | ||
2104 | 2125 | ||
2105 | s->s_flags = flags; | 2126 | s->s_flags = flags; |
2106 | 2127 | ||
@@ -2108,17 +2129,17 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, | |||
2108 | if (error) { | 2129 | if (error) { |
2109 | up_write(&s->s_umount); | 2130 | up_write(&s->s_umount); |
2110 | deactivate_super(s); | 2131 | deactivate_super(s); |
2111 | return ERR_PTR(error); | 2132 | return error; |
2112 | } | 2133 | } |
2113 | s->s_flags |= MS_ACTIVE; | 2134 | s->s_flags |= MS_ACTIVE; |
2114 | return s; | 2135 | return simple_set_mnt(mnt, s); |
2115 | out_err: | 2136 | out_err: |
2116 | s = (struct super_block *)p; | 2137 | error = PTR_ERR(p); |
2117 | out_free: | 2138 | out_free: |
2118 | kfree(server->mnt_path); | 2139 | kfree(server->mnt_path); |
2119 | kfree(server->hostname); | 2140 | kfree(server->hostname); |
2120 | kfree(server); | 2141 | kfree(server); |
2121 | return s; | 2142 | return error; |
2122 | } | 2143 | } |
2123 | 2144 | ||
2124 | static void nfs4_kill_super(struct super_block *sb) | 2145 | static void nfs4_kill_super(struct super_block *sb) |