diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/inode.c | 111 |
1 files changed, 64 insertions, 47 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index db62a5a7e4fc..ebdab885c475 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -1717,14 +1717,13 @@ struct nfs_clone_mount { | |||
1717 | }; | 1717 | }; |
1718 | 1718 | ||
1719 | static struct super_block *nfs_clone_generic_sb(struct nfs_clone_mount *data, | 1719 | static struct super_block *nfs_clone_generic_sb(struct nfs_clone_mount *data, |
1720 | struct super_block *(*clone_client)(struct nfs_server *, struct nfs_clone_mount *)) | 1720 | struct super_block *(*fill_sb)(struct nfs_server *, struct nfs_clone_mount *), |
1721 | struct nfs_server *(*fill_server)(struct super_block *, struct nfs_clone_mount *)) | ||
1721 | { | 1722 | { |
1722 | struct nfs_server *server; | 1723 | struct nfs_server *server; |
1723 | struct nfs_server *parent = NFS_SB(data->sb); | 1724 | struct nfs_server *parent = NFS_SB(data->sb); |
1724 | struct super_block *sb = ERR_PTR(-EINVAL); | 1725 | struct super_block *sb = ERR_PTR(-EINVAL); |
1725 | void *err = ERR_PTR(-ENOMEM); | 1726 | void *err = ERR_PTR(-ENOMEM); |
1726 | struct inode *root_inode; | ||
1727 | struct nfs_fsinfo fsinfo; | ||
1728 | int len; | 1727 | int len; |
1729 | 1728 | ||
1730 | server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); | 1729 | server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); |
@@ -1736,53 +1735,17 @@ static struct super_block *nfs_clone_generic_sb(struct nfs_clone_mount *data, | |||
1736 | if (server->hostname == NULL) | 1735 | if (server->hostname == NULL) |
1737 | goto free_server; | 1736 | goto free_server; |
1738 | memcpy(server->hostname, parent->hostname, len); | 1737 | memcpy(server->hostname, parent->hostname, len); |
1739 | server->fsid = data->fattr->fsid; | ||
1740 | nfs_copy_fh(&server->fh, data->fh); | ||
1741 | if (rpciod_up() != 0) | 1738 | if (rpciod_up() != 0) |
1742 | goto free_hostname; | 1739 | goto free_hostname; |
1743 | 1740 | ||
1744 | sb = clone_client(server, data); | 1741 | sb = fill_sb(server, data); |
1745 | if (IS_ERR((err = sb)) || sb->s_root) | 1742 | if (IS_ERR((err = sb)) || sb->s_root) |
1746 | goto kill_rpciod; | 1743 | goto kill_rpciod; |
1747 | 1744 | ||
1748 | sb->s_op = data->sb->s_op; | 1745 | server = fill_server(sb, data); |
1749 | sb->s_blocksize = data->sb->s_blocksize; | 1746 | if (IS_ERR((err = server))) |
1750 | sb->s_blocksize_bits = data->sb->s_blocksize_bits; | ||
1751 | sb->s_maxbytes = data->sb->s_maxbytes; | ||
1752 | |||
1753 | server->client_sys = server->client_acl = ERR_PTR(-EINVAL); | ||
1754 | err = ERR_PTR(-ENOMEM); | ||
1755 | server->io_stats = nfs_alloc_iostats(); | ||
1756 | if (server->io_stats == NULL) | ||
1757 | goto out_deactivate; | 1747 | goto out_deactivate; |
1758 | |||
1759 | server->client = rpc_clone_client(parent->client); | ||
1760 | if (IS_ERR((err = server->client))) | ||
1761 | goto out_deactivate; | ||
1762 | if (!IS_ERR(parent->client_sys)) { | ||
1763 | server->client_sys = rpc_clone_client(parent->client_sys); | ||
1764 | if (IS_ERR((err = server->client_sys))) | ||
1765 | goto out_deactivate; | ||
1766 | } | ||
1767 | if (!IS_ERR(parent->client_acl)) { | ||
1768 | server->client_acl = rpc_clone_client(parent->client_acl); | ||
1769 | if (IS_ERR((err = server->client_acl))) | ||
1770 | goto out_deactivate; | ||
1771 | } | ||
1772 | root_inode = nfs_fhget(sb, data->fh, data->fattr); | ||
1773 | if (!root_inode) | ||
1774 | goto out_deactivate; | ||
1775 | sb->s_root = d_alloc_root(root_inode); | ||
1776 | if (!sb->s_root) | ||
1777 | goto out_put_root; | ||
1778 | fsinfo.fattr = data->fattr; | ||
1779 | if (NFS_PROTO(root_inode)->fsinfo(server, data->fh, &fsinfo) == 0) | ||
1780 | nfs_super_set_maxbytes(sb, fsinfo.maxfilesize); | ||
1781 | sb->s_root->d_op = server->rpc_ops->dentry_ops; | ||
1782 | sb->s_flags |= MS_ACTIVE; | ||
1783 | return sb; | 1748 | return sb; |
1784 | out_put_root: | ||
1785 | iput(root_inode); | ||
1786 | out_deactivate: | 1749 | out_deactivate: |
1787 | up_write(&sb->s_umount); | 1750 | up_write(&sb->s_umount); |
1788 | deactivate_super(sb); | 1751 | deactivate_super(sb); |
@@ -1955,21 +1918,73 @@ static struct file_system_type nfs_fs_type = { | |||
1955 | .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 1918 | .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
1956 | }; | 1919 | }; |
1957 | 1920 | ||
1958 | static struct super_block *nfs_clone_client(struct nfs_server *server, struct nfs_clone_mount *data) | 1921 | static struct super_block *nfs_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data) |
1959 | { | 1922 | { |
1960 | struct super_block *sb; | 1923 | struct super_block *sb; |
1961 | 1924 | ||
1925 | server->fsid = data->fattr->fsid; | ||
1926 | nfs_copy_fh(&server->fh, data->fh); | ||
1962 | sb = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); | 1927 | sb = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); |
1963 | if (!IS_ERR(sb) && sb->s_root == NULL && !(server->flags & NFS_MOUNT_NONLM)) | 1928 | if (!IS_ERR(sb) && sb->s_root == NULL && !(server->flags & NFS_MOUNT_NONLM)) |
1964 | lockd_up(); | 1929 | lockd_up(); |
1965 | return sb; | 1930 | return sb; |
1966 | } | 1931 | } |
1967 | 1932 | ||
1933 | static struct nfs_server *nfs_clone_server(struct super_block *sb, struct nfs_clone_mount *data) | ||
1934 | { | ||
1935 | struct nfs_server *server = NFS_SB(sb); | ||
1936 | struct nfs_server *parent = NFS_SB(data->sb); | ||
1937 | struct inode *root_inode; | ||
1938 | struct nfs_fsinfo fsinfo; | ||
1939 | void *err = ERR_PTR(-ENOMEM); | ||
1940 | |||
1941 | sb->s_op = data->sb->s_op; | ||
1942 | sb->s_blocksize = data->sb->s_blocksize; | ||
1943 | sb->s_blocksize_bits = data->sb->s_blocksize_bits; | ||
1944 | sb->s_maxbytes = data->sb->s_maxbytes; | ||
1945 | |||
1946 | server->client_sys = server->client_acl = ERR_PTR(-EINVAL); | ||
1947 | server->io_stats = nfs_alloc_iostats(); | ||
1948 | if (server->io_stats == NULL) | ||
1949 | goto out; | ||
1950 | |||
1951 | server->client = rpc_clone_client(parent->client); | ||
1952 | if (IS_ERR((err = server->client))) | ||
1953 | goto out; | ||
1954 | |||
1955 | if (!IS_ERR(parent->client_sys)) { | ||
1956 | server->client_sys = rpc_clone_client(parent->client_sys); | ||
1957 | if (IS_ERR((err = server->client_sys))) | ||
1958 | goto out; | ||
1959 | } | ||
1960 | if (!IS_ERR(parent->client_acl)) { | ||
1961 | server->client_acl = rpc_clone_client(parent->client_acl); | ||
1962 | if (IS_ERR((err = server->client_acl))) | ||
1963 | goto out; | ||
1964 | } | ||
1965 | root_inode = nfs_fhget(sb, data->fh, data->fattr); | ||
1966 | if (!root_inode) | ||
1967 | goto out; | ||
1968 | sb->s_root = d_alloc_root(root_inode); | ||
1969 | if (!sb->s_root) | ||
1970 | goto out_put_root; | ||
1971 | fsinfo.fattr = data->fattr; | ||
1972 | if (NFS_PROTO(root_inode)->fsinfo(server, data->fh, &fsinfo) == 0) | ||
1973 | nfs_super_set_maxbytes(sb, fsinfo.maxfilesize); | ||
1974 | sb->s_root->d_op = server->rpc_ops->dentry_ops; | ||
1975 | sb->s_flags |= MS_ACTIVE; | ||
1976 | return server; | ||
1977 | out_put_root: | ||
1978 | iput(root_inode); | ||
1979 | out: | ||
1980 | return err; | ||
1981 | } | ||
1982 | |||
1968 | static struct super_block *nfs_clone_nfs_sb(struct file_system_type *fs_type, | 1983 | static struct super_block *nfs_clone_nfs_sb(struct file_system_type *fs_type, |
1969 | int flags, const char *dev_name, void *raw_data) | 1984 | int flags, const char *dev_name, void *raw_data) |
1970 | { | 1985 | { |
1971 | struct nfs_clone_mount *data = raw_data; | 1986 | struct nfs_clone_mount *data = raw_data; |
1972 | return nfs_clone_generic_sb(data, nfs_clone_client); | 1987 | return nfs_clone_generic_sb(data, nfs_clone_sb, nfs_clone_server); |
1973 | } | 1988 | } |
1974 | 1989 | ||
1975 | static struct file_system_type clone_nfs_fs_type = { | 1990 | static struct file_system_type clone_nfs_fs_type = { |
@@ -2371,12 +2386,14 @@ static inline char *nfs4_dup_path(const struct dentry *dentry) | |||
2371 | return path; | 2386 | return path; |
2372 | } | 2387 | } |
2373 | 2388 | ||
2374 | static struct super_block *nfs4_clone_client(struct nfs_server *server, struct nfs_clone_mount *data) | 2389 | static struct super_block *nfs4_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data) |
2375 | { | 2390 | { |
2376 | const struct dentry *dentry = data->dentry; | 2391 | const struct dentry *dentry = data->dentry; |
2377 | struct nfs4_client *clp = server->nfs4_state; | 2392 | struct nfs4_client *clp = server->nfs4_state; |
2378 | struct super_block *sb; | 2393 | struct super_block *sb; |
2379 | 2394 | ||
2395 | server->fsid = data->fattr->fsid; | ||
2396 | nfs_copy_fh(&server->fh, data->fh); | ||
2380 | server->mnt_path = nfs4_dup_path(dentry); | 2397 | server->mnt_path = nfs4_dup_path(dentry); |
2381 | if (IS_ERR(server->mnt_path)) { | 2398 | if (IS_ERR(server->mnt_path)) { |
2382 | sb = (struct super_block *)server->mnt_path; | 2399 | sb = (struct super_block *)server->mnt_path; |
@@ -2403,12 +2420,12 @@ static struct super_block *nfs_clone_nfs4_sb(struct file_system_type *fs_type, | |||
2403 | int flags, const char *dev_name, void *raw_data) | 2420 | int flags, const char *dev_name, void *raw_data) |
2404 | { | 2421 | { |
2405 | struct nfs_clone_mount *data = raw_data; | 2422 | struct nfs_clone_mount *data = raw_data; |
2406 | return nfs_clone_generic_sb(data, nfs4_clone_client); | 2423 | return nfs_clone_generic_sb(data, nfs4_clone_sb, nfs_clone_server); |
2407 | } | 2424 | } |
2408 | 2425 | ||
2409 | static struct file_system_type clone_nfs4_fs_type = { | 2426 | static struct file_system_type clone_nfs4_fs_type = { |
2410 | .owner = THIS_MODULE, | 2427 | .owner = THIS_MODULE, |
2411 | .name = "nfs", | 2428 | .name = "nfs4", |
2412 | .get_sb = nfs_clone_nfs4_sb, | 2429 | .get_sb = nfs_clone_nfs4_sb, |
2413 | .kill_sb = nfs4_kill_super, | 2430 | .kill_sb = nfs4_kill_super, |
2414 | .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 2431 | .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |