|
@@ -1690,8 +1690,8 @@ static int nfs_compare_super(struct super_block *sb, void *data)
|
|
|
return !nfs_compare_fh(&old->fh, &server->fh);
|
|
|
}
|
|
|
|
|
|
-static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
|
|
|
- int flags, const char *dev_name, void *raw_data)
|
|
|
+static int nfs_get_sb(struct file_system_type *fs_type,
|
|
|
+ int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
|
|
|
{
|
|
|
int error;
|
|
|
struct nfs_server *server = NULL;
|
|
@@ -1699,14 +1699,14 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
|
|
|
struct nfs_fh *root;
|
|
|
struct nfs_mount_data *data = raw_data;
|
|
|
|
|
|
- s = ERR_PTR(-EINVAL);
|
|
|
+ error = -EINVAL;
|
|
|
if (data == NULL) {
|
|
|
dprintk("%s: missing data argument\n", __FUNCTION__);
|
|
|
- goto out_err;
|
|
|
+ goto out_err_noserver;
|
|
|
}
|
|
|
if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
|
|
|
dprintk("%s: bad mount version\n", __FUNCTION__);
|
|
|
- goto out_err;
|
|
|
+ goto out_err_noserver;
|
|
|
}
|
|
|
switch (data->version) {
|
|
|
case 1:
|
|
@@ -1718,7 +1718,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
|
|
|
dprintk("%s: mount structure version %d does not support NFSv3\n",
|
|
|
__FUNCTION__,
|
|
|
data->version);
|
|
|
- goto out_err;
|
|
|
+ goto out_err_noserver;
|
|
|
}
|
|
|
data->root.size = NFS2_FHSIZE;
|
|
|
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,
|
|
|
dprintk("%s: mount structure version %d does not support strong security\n",
|
|
|
__FUNCTION__,
|
|
|
data->version);
|
|
|
- goto out_err;
|
|
|
+ goto out_err_noserver;
|
|
|
}
|
|
|
case 5:
|
|
|
memset(data->context, 0, sizeof(data->context));
|
|
|
}
|
|
|
#ifndef CONFIG_NFS_V3
|
|
|
/* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
|
|
|
- s = ERR_PTR(-EPROTONOSUPPORT);
|
|
|
+ error = -EPROTONOSUPPORT;
|
|
|
if (data->flags & NFS_MOUNT_VER3) {
|
|
|
dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
|
|
|
- goto out_err;
|
|
|
+ goto out_err_noserver;
|
|
|
}
|
|
|
#endif /* CONFIG_NFS_V3 */
|
|
|
|
|
|
- s = ERR_PTR(-ENOMEM);
|
|
|
+ error = -ENOMEM;
|
|
|
server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
|
|
|
if (!server)
|
|
|
- goto out_err;
|
|
|
+ goto out_err_noserver;
|
|
|
/* Zero out the NFS state stuff */
|
|
|
init_nfsv4_state(server);
|
|
|
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,
|
|
|
root->size = data->root.size;
|
|
|
else
|
|
|
root->size = NFS2_FHSIZE;
|
|
|
- s = ERR_PTR(-EINVAL);
|
|
|
+ error = -EINVAL;
|
|
|
if (root->size > sizeof(root->data)) {
|
|
|
dprintk("%s: invalid root filehandle\n", __FUNCTION__);
|
|
|
goto out_err;
|
|
@@ -1770,15 +1770,20 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
|
|
|
}
|
|
|
|
|
|
/* Fire up rpciod if not yet running */
|
|
|
- s = ERR_PTR(rpciod_up());
|
|
|
- if (IS_ERR(s)) {
|
|
|
- dprintk("%s: couldn't start rpciod! Error = %ld\n",
|
|
|
- __FUNCTION__, PTR_ERR(s));
|
|
|
+ error = rpciod_up();
|
|
|
+ if (error < 0) {
|
|
|
+ dprintk("%s: couldn't start rpciod! Error = %d\n",
|
|
|
+ __FUNCTION__, error);
|
|
|
goto out_err;
|
|
|
}
|
|
|
|
|
|
s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
|
|
|
- if (IS_ERR(s) || s->s_root)
|
|
|
+ if (IS_ERR(s)) {
|
|
|
+ error = PTR_ERR(s);
|
|
|
+ goto out_err_rpciod;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (s->s_root)
|
|
|
goto out_rpciod_down;
|
|
|
|
|
|
s->s_flags = flags;
|
|
@@ -1787,15 +1792,22 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
|
|
|
if (error) {
|
|
|
up_write(&s->s_umount);
|
|
|
deactivate_super(s);
|
|
|
- return ERR_PTR(error);
|
|
|
+ return error;
|
|
|
}
|
|
|
s->s_flags |= MS_ACTIVE;
|
|
|
- return s;
|
|
|
+ return simple_set_mnt(mnt, s);
|
|
|
+
|
|
|
out_rpciod_down:
|
|
|
rpciod_down();
|
|
|
+ kfree(server);
|
|
|
+ return simple_set_mnt(mnt, s);
|
|
|
+
|
|
|
+out_err_rpciod:
|
|
|
+ rpciod_down();
|
|
|
out_err:
|
|
|
kfree(server);
|
|
|
- return s;
|
|
|
+out_err_noserver:
|
|
|
+ return error;
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
return dst;
|
|
|
}
|
|
|
|
|
|
-static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
|
|
|
- int flags, const char *dev_name, void *raw_data)
|
|
|
+static int nfs4_get_sb(struct file_system_type *fs_type,
|
|
|
+ int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
|
|
|
{
|
|
|
int error;
|
|
|
struct nfs_server *server;
|
|
@@ -2043,16 +2055,16 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
|
|
|
|
|
|
if (data == NULL) {
|
|
|
dprintk("%s: missing data argument\n", __FUNCTION__);
|
|
|
- return ERR_PTR(-EINVAL);
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
|
|
|
dprintk("%s: bad mount version\n", __FUNCTION__);
|
|
|
- return ERR_PTR(-EINVAL);
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
|
|
|
if (!server)
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
+ return -ENOMEM;
|
|
|
/* Zero out the NFS state stuff */
|
|
|
init_nfsv4_state(server);
|
|
|
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,
|
|
|
|
|
|
/* We now require that the mount process passes the remote address */
|
|
|
if (data->host_addrlen != sizeof(server->addr)) {
|
|
|
- s = ERR_PTR(-EINVAL);
|
|
|
+ error = -EINVAL;
|
|
|
goto out_free;
|
|
|
}
|
|
|
if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) {
|
|
|
- s = ERR_PTR(-EFAULT);
|
|
|
+ error = -EFAULT;
|
|
|
goto out_free;
|
|
|
}
|
|
|
if (server->addr.sin_family != AF_INET ||
|
|
|
server->addr.sin_addr.s_addr == INADDR_ANY) {
|
|
|
dprintk("%s: mount program didn't pass remote IP address!\n",
|
|
|
__FUNCTION__);
|
|
|
- s = ERR_PTR(-EINVAL);
|
|
|
+ error = -EINVAL;
|
|
|
goto out_free;
|
|
|
}
|
|
|
|
|
|
/* Fire up rpciod if not yet running */
|
|
|
- s = ERR_PTR(rpciod_up());
|
|
|
- if (IS_ERR(s)) {
|
|
|
- dprintk("%s: couldn't start rpciod! Error = %ld\n",
|
|
|
- __FUNCTION__, PTR_ERR(s));
|
|
|
+ error = rpciod_up();
|
|
|
+ if (error < 0) {
|
|
|
+ dprintk("%s: couldn't start rpciod! Error = %d\n",
|
|
|
+ __FUNCTION__, error);
|
|
|
goto out_free;
|
|
|
}
|
|
|
|
|
|
s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
|
|
|
-
|
|
|
- if (IS_ERR(s) || s->s_root)
|
|
|
+ if (IS_ERR(s)) {
|
|
|
+ error = PTR_ERR(s);
|
|
|
goto out_free;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (s->s_root) {
|
|
|
+ kfree(server->mnt_path);
|
|
|
+ kfree(server->hostname);
|
|
|
+ kfree(server);
|
|
|
+ return simple_set_mnt(mnt, s);
|
|
|
+ }
|
|
|
|
|
|
s->s_flags = flags;
|
|
|
|
|
@@ -2108,17 +2128,17 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
|
|
|
if (error) {
|
|
|
up_write(&s->s_umount);
|
|
|
deactivate_super(s);
|
|
|
- return ERR_PTR(error);
|
|
|
+ return error;
|
|
|
}
|
|
|
s->s_flags |= MS_ACTIVE;
|
|
|
- return s;
|
|
|
+ return simple_set_mnt(mnt, s);
|
|
|
out_err:
|
|
|
- s = (struct super_block *)p;
|
|
|
+ error = PTR_ERR(p);
|
|
|
out_free:
|
|
|
kfree(server->mnt_path);
|
|
|
kfree(server->hostname);
|
|
|
kfree(server);
|
|
|
- return s;
|
|
|
+ return error;
|
|
|
}
|
|
|
|
|
|
static void nfs4_kill_super(struct super_block *sb)
|