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