diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 122 |
1 files changed, 58 insertions, 64 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index fee2da856c95..6ca2795ccd9c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -66,6 +66,8 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
66 | static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); | 66 | static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); |
67 | static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp); | 67 | static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp); |
68 | static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags); | 68 | static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags); |
69 | static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | ||
70 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | ||
69 | 71 | ||
70 | /* Prevent leaks of NFSv4 errors into userland */ | 72 | /* Prevent leaks of NFSv4 errors into userland */ |
71 | int nfs4_map_errors(int err) | 73 | int nfs4_map_errors(int err) |
@@ -552,6 +554,18 @@ static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state * | |||
552 | return ERR_PTR(-ENOENT); | 554 | return ERR_PTR(-ENOENT); |
553 | } | 555 | } |
554 | 556 | ||
557 | static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context *ctx, struct nfs4_state *state) | ||
558 | { | ||
559 | struct nfs4_opendata *opendata; | ||
560 | |||
561 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); | ||
562 | if (opendata == NULL) | ||
563 | return ERR_PTR(-ENOMEM); | ||
564 | opendata->state = state; | ||
565 | atomic_inc(&state->count); | ||
566 | return opendata; | ||
567 | } | ||
568 | |||
555 | static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res) | 569 | static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res) |
556 | { | 570 | { |
557 | struct nfs4_state *newstate; | 571 | struct nfs4_state *newstate; |
@@ -626,12 +640,11 @@ static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state | |||
626 | int delegation_type = 0; | 640 | int delegation_type = 0; |
627 | int status; | 641 | int status; |
628 | 642 | ||
629 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); | 643 | opendata = nfs4_open_recoverdata_alloc(ctx, state); |
630 | if (opendata == NULL) | 644 | if (IS_ERR(opendata)) |
631 | return -ENOMEM; | 645 | return PTR_ERR(opendata); |
632 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS; | 646 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS; |
633 | opendata->o_arg.fh = NFS_FH(state->inode); | 647 | opendata->o_arg.fh = NFS_FH(state->inode); |
634 | nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh); | ||
635 | rcu_read_lock(); | 648 | rcu_read_lock(); |
636 | delegation = rcu_dereference(NFS_I(state->inode)->delegation); | 649 | delegation = rcu_dereference(NFS_I(state->inode)->delegation); |
637 | if (delegation != NULL && (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) != 0) | 650 | if (delegation != NULL && (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) != 0) |
@@ -672,13 +685,12 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta | |||
672 | 685 | ||
673 | static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid) | 686 | static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid) |
674 | { | 687 | { |
675 | struct nfs4_state_owner *sp = state->owner; | ||
676 | struct nfs4_opendata *opendata; | 688 | struct nfs4_opendata *opendata; |
677 | int ret; | 689 | int ret; |
678 | 690 | ||
679 | opendata = nfs4_opendata_alloc(&ctx->path, sp, 0, NULL); | 691 | opendata = nfs4_open_recoverdata_alloc(ctx, state); |
680 | if (opendata == NULL) | 692 | if (IS_ERR(opendata)) |
681 | return -ENOMEM; | 693 | return PTR_ERR(opendata); |
682 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR; | 694 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR; |
683 | memcpy(opendata->o_arg.u.delegation.data, stateid->data, | 695 | memcpy(opendata->o_arg.u.delegation.data, stateid->data, |
684 | sizeof(opendata->o_arg.u.delegation.data)); | 696 | sizeof(opendata->o_arg.u.delegation.data)); |
@@ -823,8 +835,10 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
823 | /* Update sequence id. */ | 835 | /* Update sequence id. */ |
824 | data->o_arg.id = sp->so_owner_id.id; | 836 | data->o_arg.id = sp->so_owner_id.id; |
825 | data->o_arg.clientid = sp->so_client->cl_clientid; | 837 | data->o_arg.clientid = sp->so_client->cl_clientid; |
826 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) | 838 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { |
827 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; | 839 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; |
840 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); | ||
841 | } | ||
828 | data->timestamp = jiffies; | 842 | data->timestamp = jiffies; |
829 | rpc_call_setup(task, &msg, 0); | 843 | rpc_call_setup(task, &msg, 0); |
830 | return; | 844 | return; |
@@ -918,6 +932,9 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
918 | if (status != 0 || !data->rpc_done) | 932 | if (status != 0 || !data->rpc_done) |
919 | return status; | 933 | return status; |
920 | 934 | ||
935 | if (o_res->fh.size == 0) | ||
936 | _nfs4_proc_lookup(dir, o_arg->name, &o_res->fh, o_res->f_attr); | ||
937 | |||
921 | if (o_arg->open_flags & O_CREAT) { | 938 | if (o_arg->open_flags & O_CREAT) { |
922 | update_changeattr(dir, &o_res->cinfo); | 939 | update_changeattr(dir, &o_res->cinfo); |
923 | nfs_post_op_update_inode(dir, o_res->dir_attr); | 940 | nfs_post_op_update_inode(dir, o_res->dir_attr); |
@@ -929,7 +946,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
929 | return status; | 946 | return status; |
930 | } | 947 | } |
931 | if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) | 948 | if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) |
932 | return server->nfs_client->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); | 949 | _nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr); |
933 | return 0; | 950 | return 0; |
934 | } | 951 | } |
935 | 952 | ||
@@ -989,9 +1006,9 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s | |||
989 | struct nfs4_opendata *opendata; | 1006 | struct nfs4_opendata *opendata; |
990 | int ret; | 1007 | int ret; |
991 | 1008 | ||
992 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); | 1009 | opendata = nfs4_open_recoverdata_alloc(ctx, state); |
993 | if (opendata == NULL) | 1010 | if (IS_ERR(opendata)) |
994 | return -ENOMEM; | 1011 | return PTR_ERR(opendata); |
995 | ret = nfs4_open_recover(opendata, state); | 1012 | ret = nfs4_open_recover(opendata, state); |
996 | if (ret == -ESTALE) { | 1013 | if (ret == -ESTALE) { |
997 | /* Invalidate the state owner so we don't ever use it again */ | 1014 | /* Invalidate the state owner so we don't ever use it again */ |
@@ -1553,7 +1570,7 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
1553 | * Note that we'll actually follow the referral later when | 1570 | * Note that we'll actually follow the referral later when |
1554 | * we detect fsid mismatch in inode revalidation | 1571 | * we detect fsid mismatch in inode revalidation |
1555 | */ | 1572 | */ |
1556 | static int nfs4_get_referral(struct inode *dir, struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle) | 1573 | static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle) |
1557 | { | 1574 | { |
1558 | int status = -ENOMEM; | 1575 | int status = -ENOMEM; |
1559 | struct page *page = NULL; | 1576 | struct page *page = NULL; |
@@ -1668,8 +1685,8 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
1668 | return status; | 1685 | return status; |
1669 | } | 1686 | } |
1670 | 1687 | ||
1671 | static int _nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, | 1688 | static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *dirfh, |
1672 | struct qstr *name, struct nfs_fh *fhandle, | 1689 | const struct qstr *name, struct nfs_fh *fhandle, |
1673 | struct nfs_fattr *fattr) | 1690 | struct nfs_fattr *fattr) |
1674 | { | 1691 | { |
1675 | int status; | 1692 | int status; |
@@ -1715,7 +1732,7 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, | |||
1715 | return err; | 1732 | return err; |
1716 | } | 1733 | } |
1717 | 1734 | ||
1718 | static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name, | 1735 | static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, |
1719 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 1736 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
1720 | { | 1737 | { |
1721 | int status; | 1738 | int status; |
@@ -1908,28 +1925,27 @@ out: | |||
1908 | static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) | 1925 | static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) |
1909 | { | 1926 | { |
1910 | struct nfs_server *server = NFS_SERVER(dir); | 1927 | struct nfs_server *server = NFS_SERVER(dir); |
1911 | struct nfs4_remove_arg args = { | 1928 | struct nfs_removeargs args = { |
1912 | .fh = NFS_FH(dir), | 1929 | .fh = NFS_FH(dir), |
1913 | .name = name, | 1930 | .name.len = name->len, |
1931 | .name.name = name->name, | ||
1914 | .bitmask = server->attr_bitmask, | 1932 | .bitmask = server->attr_bitmask, |
1915 | }; | 1933 | }; |
1916 | struct nfs_fattr dir_attr; | 1934 | struct nfs_removeres res = { |
1917 | struct nfs4_remove_res res = { | ||
1918 | .server = server, | 1935 | .server = server, |
1919 | .dir_attr = &dir_attr, | ||
1920 | }; | 1936 | }; |
1921 | struct rpc_message msg = { | 1937 | struct rpc_message msg = { |
1922 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE], | 1938 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE], |
1923 | .rpc_argp = &args, | 1939 | .rpc_argp = &args, |
1924 | .rpc_resp = &res, | 1940 | .rpc_resp = &res, |
1925 | }; | 1941 | }; |
1926 | int status; | 1942 | int status; |
1927 | 1943 | ||
1928 | nfs_fattr_init(res.dir_attr); | 1944 | nfs_fattr_init(&res.dir_attr); |
1929 | status = rpc_call_sync(server->client, &msg, 0); | 1945 | status = rpc_call_sync(server->client, &msg, 0); |
1930 | if (status == 0) { | 1946 | if (status == 0) { |
1931 | update_changeattr(dir, &res.cinfo); | 1947 | update_changeattr(dir, &res.cinfo); |
1932 | nfs_post_op_update_inode(dir, res.dir_attr); | 1948 | nfs_post_op_update_inode(dir, &res.dir_attr); |
1933 | } | 1949 | } |
1934 | return status; | 1950 | return status; |
1935 | } | 1951 | } |
@@ -1946,48 +1962,26 @@ static int nfs4_proc_remove(struct inode *dir, struct qstr *name) | |||
1946 | return err; | 1962 | return err; |
1947 | } | 1963 | } |
1948 | 1964 | ||
1949 | struct unlink_desc { | 1965 | static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) |
1950 | struct nfs4_remove_arg args; | ||
1951 | struct nfs4_remove_res res; | ||
1952 | struct nfs_fattr dir_attr; | ||
1953 | }; | ||
1954 | |||
1955 | static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, | ||
1956 | struct qstr *name) | ||
1957 | { | 1966 | { |
1958 | struct nfs_server *server = NFS_SERVER(dir->d_inode); | 1967 | struct nfs_server *server = NFS_SERVER(dir); |
1959 | struct unlink_desc *up; | 1968 | struct nfs_removeargs *args = msg->rpc_argp; |
1969 | struct nfs_removeres *res = msg->rpc_resp; | ||
1960 | 1970 | ||
1961 | up = kmalloc(sizeof(*up), GFP_KERNEL); | 1971 | args->bitmask = server->attr_bitmask; |
1962 | if (!up) | 1972 | res->server = server; |
1963 | return -ENOMEM; | ||
1964 | |||
1965 | up->args.fh = NFS_FH(dir->d_inode); | ||
1966 | up->args.name = name; | ||
1967 | up->args.bitmask = server->attr_bitmask; | ||
1968 | up->res.server = server; | ||
1969 | up->res.dir_attr = &up->dir_attr; | ||
1970 | |||
1971 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; | 1973 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; |
1972 | msg->rpc_argp = &up->args; | ||
1973 | msg->rpc_resp = &up->res; | ||
1974 | return 0; | ||
1975 | } | 1974 | } |
1976 | 1975 | ||
1977 | static int nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task) | 1976 | static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) |
1978 | { | 1977 | { |
1979 | struct rpc_message *msg = &task->tk_msg; | 1978 | struct nfs_removeres *res = task->tk_msg.rpc_resp; |
1980 | struct unlink_desc *up; | 1979 | |
1981 | 1980 | if (nfs4_async_handle_error(task, res->server) == -EAGAIN) | |
1982 | if (msg->rpc_resp != NULL) { | 1981 | return 0; |
1983 | up = container_of(msg->rpc_resp, struct unlink_desc, res); | 1982 | update_changeattr(dir, &res->cinfo); |
1984 | update_changeattr(dir->d_inode, &up->res.cinfo); | 1983 | nfs_post_op_update_inode(dir, &res->dir_attr); |
1985 | nfs_post_op_update_inode(dir->d_inode, up->res.dir_attr); | 1984 | return 1; |
1986 | kfree(up); | ||
1987 | msg->rpc_resp = NULL; | ||
1988 | msg->rpc_argp = NULL; | ||
1989 | } | ||
1990 | return 0; | ||
1991 | } | 1985 | } |
1992 | 1986 | ||
1993 | static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | 1987 | static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, |
@@ -3672,7 +3666,7 @@ ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen) | |||
3672 | return len; | 3666 | return len; |
3673 | } | 3667 | } |
3674 | 3668 | ||
3675 | int nfs4_proc_fs_locations(struct inode *dir, struct qstr *name, | 3669 | int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, |
3676 | struct nfs4_fs_locations *fs_locations, struct page *page) | 3670 | struct nfs4_fs_locations *fs_locations, struct page *page) |
3677 | { | 3671 | { |
3678 | struct nfs_server *server = NFS_SERVER(dir); | 3672 | struct nfs_server *server = NFS_SERVER(dir); |