aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c122
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
66static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); 66static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
67static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp); 67static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp);
68static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags); 68static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags);
69static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
70static 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 */
71int nfs4_map_errors(int err) 73int 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
557static 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
555static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res) 569static 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
673static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid) 686static 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 */
1556static int nfs4_get_referral(struct inode *dir, struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle) 1573static 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
1671static int _nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, 1688static 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
1718static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name, 1735static 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:
1908static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) 1925static 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
1949struct unlink_desc { 1965static 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
1955static 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
1977static int nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task) 1976static 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
1993static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, 1987static 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
3675int nfs4_proc_fs_locations(struct inode *dir, struct qstr *name, 3669int 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);