fs/nfs: fix new compiler warning about boolean in switch
[cascardo/linux.git] / fs / nfs / nfs4proc.c
index 2e7c9f7..addf17d 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/module.h>
-#include <linux/nfs_idmap.h>
 #include <linux/xattr.h>
 #include <linux/utsname.h>
 #include <linux/freezer.h>
@@ -63,6 +62,7 @@
 #include "callback.h"
 #include "pnfs.h"
 #include "netns.h"
+#include "nfs4idmap.h"
 #include "nfs4session.h"
 #include "fscache.h"
 
@@ -185,7 +185,8 @@ const u32 nfs4_fattr_bitmap[3] = {
        | FATTR4_WORD1_SPACE_USED
        | FATTR4_WORD1_TIME_ACCESS
        | FATTR4_WORD1_TIME_METADATA
-       | FATTR4_WORD1_TIME_MODIFY,
+       | FATTR4_WORD1_TIME_MODIFY
+       | FATTR4_WORD1_MOUNTED_ON_FILEID,
 #ifdef CONFIG_NFS_V4_SECURITY_LABEL
        FATTR4_WORD2_SECURITY_LABEL
 #endif
@@ -901,6 +902,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
        if (!cinfo->atomic || cinfo->before != dir->i_version)
                nfs_force_lookup_revalidate(dir);
        dir->i_version = cinfo->after;
+       nfsi->attr_gencount = nfs_inc_attr_generation_counter();
        nfs_fscache_invalidate(dir);
        spin_unlock(&dir->i_lock);
 }
@@ -1552,6 +1554,9 @@ static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmod
 
        opendata->o_arg.open_flags = 0;
        opendata->o_arg.fmode = fmode;
+       opendata->o_arg.share_access = nfs4_map_atomic_open_share(
+                       NFS_SB(opendata->dentry->d_sb),
+                       fmode, 0);
        memset(&opendata->o_res, 0, sizeof(opendata->o_res));
        memset(&opendata->c_res, 0, sizeof(opendata->c_res));
        nfs4_init_opendata_res(opendata);
@@ -2413,8 +2418,8 @@ static int _nfs4_do_open(struct inode *dir,
                                opendata->o_res.f_attr, sattr,
                                state, label, olabel);
                if (status == 0) {
-                       nfs_setattr_update_inode(state->inode, sattr);
-                       nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr);
+                       nfs_setattr_update_inode(state->inode, sattr,
+                                       opendata->o_res.f_attr);
                        nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel);
                }
        }
@@ -2651,7 +2656,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                case -NFS4ERR_BAD_STATEID:
                case -NFS4ERR_EXPIRED:
                        if (!nfs4_stateid_match(&calldata->arg.stateid,
-                                               &state->stateid)) {
+                                               &state->open_stateid)) {
                                rpc_restart_call_prepare(task);
                                goto out_release;
                        }
@@ -2687,7 +2692,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
        is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags);
        is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags);
        is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags);
-       nfs4_stateid_copy(&calldata->arg.stateid, &state->stateid);
+       nfs4_stateid_copy(&calldata->arg.stateid, &state->open_stateid);
        /* Calculate the change in open mode */
        calldata->arg.fmode = 0;
        if (state->n_rdwr == 0) {
@@ -3091,16 +3096,13 @@ int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle,
                         struct nfs_fsinfo *info,
                         bool auth_probe)
 {
-       int status;
+       int status = 0;
 
-       switch (auth_probe) {
-       case false:
+       if (!auth_probe)
                status = nfs4_lookup_root(server, fhandle, info);
-               if (status != -NFS4ERR_WRONGSEC)
-                       break;
-       default:
+
+       if (auth_probe || status == NFS4ERR_WRONGSEC)
                status = nfs4_do_find_root_sec(server, fhandle, info);
-       }
 
        if (status == 0)
                status = nfs4_server_capabilities(server, fhandle);
@@ -3288,7 +3290,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
        status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, label);
        if (status == 0) {
-               nfs_setattr_update_inode(inode, sattr);
+               nfs_setattr_update_inode(inode, sattr, fattr);
                nfs_setsecurity(inode, fattr, label);
        }
        nfs4_label_free(label);
@@ -4234,7 +4236,7 @@ static int nfs4_write_done_cb(struct rpc_task *task,
        }
        if (task->tk_status >= 0) {
                renew_lease(NFS_SERVER(inode), hdr->timestamp);
-               nfs_post_op_update_inode_force_wcc(inode, &hdr->fattr);
+               nfs_writeback_update_inode(hdr);
        }
        return 0;
 }
@@ -6648,47 +6650,47 @@ nfs41_same_server_scope(struct nfs41_server_scope *a,
 int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred)
 {
        int status;
+       struct nfs41_bind_conn_to_session_args args = {
+               .client = clp,
+               .dir = NFS4_CDFC4_FORE_OR_BOTH,
+       };
        struct nfs41_bind_conn_to_session_res res;
        struct rpc_message msg = {
                .rpc_proc =
                        &nfs4_procedures[NFSPROC4_CLNT_BIND_CONN_TO_SESSION],
-               .rpc_argp = clp,
+               .rpc_argp = &args,
                .rpc_resp = &res,
                .rpc_cred = cred,
        };
 
        dprintk("--> %s\n", __func__);
 
-       res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS);
-       if (unlikely(res.session == NULL)) {
-               status = -ENOMEM;
-               goto out;
-       }
+       nfs4_copy_sessionid(&args.sessionid, &clp->cl_session->sess_id);
+       if (!(clp->cl_session->flags & SESSION4_BACK_CHAN))
+               args.dir = NFS4_CDFC4_FORE;
 
        status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
        trace_nfs4_bind_conn_to_session(clp, status);
        if (status == 0) {
-               if (memcmp(res.session->sess_id.data,
+               if (memcmp(res.sessionid.data,
                    clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) {
                        dprintk("NFS: %s: Session ID mismatch\n", __func__);
                        status = -EIO;
-                       goto out_session;
+                       goto out;
                }
-               if (res.dir != NFS4_CDFS4_BOTH) {
+               if ((res.dir & args.dir) != res.dir || res.dir == 0) {
                        dprintk("NFS: %s: Unexpected direction from server\n",
                                __func__);
                        status = -EIO;
-                       goto out_session;
+                       goto out;
                }
-               if (res.use_conn_in_rdma_mode) {
+               if (res.use_conn_in_rdma_mode != args.use_conn_in_rdma_mode) {
                        dprintk("NFS: %s: Server returned RDMA mode = true\n",
                                __func__);
                        status = -EIO;
-                       goto out_session;
+                       goto out;
                }
        }
-out_session:
-       kfree(res.session);
 out:
        dprintk("<-- %s status= %d\n", __func__, status);
        return status;
@@ -6893,9 +6895,13 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
 
        if (status == 0) {
                clp->cl_clientid = res.clientid;
-               clp->cl_exchange_flags = (res.flags & ~EXCHGID4_FLAG_CONFIRMED_R);
-               if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R))
+               clp->cl_exchange_flags = res.flags;
+               /* Client ID is not confirmed */
+               if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R)) {
+                       clear_bit(NFS4_SESSION_ESTABLISHED,
+                                       &clp->cl_session->session_state);
                        clp->cl_seqid = res.seqid;
+               }
 
                kfree(clp->cl_serverowner);
                clp->cl_serverowner = res.server_owner;
@@ -7166,10 +7172,11 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
                args->bc_attrs.max_reqs);
 }
 
-static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session)
+static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args,
+               struct nfs41_create_session_res *res)
 {
        struct nfs4_channel_attrs *sent = &args->fc_attrs;
-       struct nfs4_channel_attrs *rcvd = &session->fc_attrs;
+       struct nfs4_channel_attrs *rcvd = &res->fc_attrs;
 
        if (rcvd->max_resp_sz > sent->max_resp_sz)
                return -EINVAL;
@@ -7188,11 +7195,14 @@ static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args
        return 0;
 }
 
-static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session)
+static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args,
+               struct nfs41_create_session_res *res)
 {
        struct nfs4_channel_attrs *sent = &args->bc_attrs;
-       struct nfs4_channel_attrs *rcvd = &session->bc_attrs;
+       struct nfs4_channel_attrs *rcvd = &res->bc_attrs;
 
+       if (!(res->flags & SESSION4_BACK_CHAN))
+               goto out;
        if (rcvd->max_rqst_sz > sent->max_rqst_sz)
                return -EINVAL;
        if (rcvd->max_resp_sz < sent->max_resp_sz)
@@ -7204,18 +7214,33 @@ static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args
                return -EINVAL;
        if (rcvd->max_reqs != sent->max_reqs)
                return -EINVAL;
+out:
        return 0;
 }
 
 static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args,
-                                    struct nfs4_session *session)
+                                    struct nfs41_create_session_res *res)
 {
        int ret;
 
-       ret = nfs4_verify_fore_channel_attrs(args, session);
+       ret = nfs4_verify_fore_channel_attrs(args, res);
        if (ret)
                return ret;
-       return nfs4_verify_back_channel_attrs(args, session);
+       return nfs4_verify_back_channel_attrs(args, res);
+}
+
+static void nfs4_update_session(struct nfs4_session *session,
+               struct nfs41_create_session_res *res)
+{
+       nfs4_copy_sessionid(&session->sess_id, &res->sessionid);
+       /* Mark client id and session as being confirmed */
+       session->clp->cl_exchange_flags |= EXCHGID4_FLAG_CONFIRMED_R;
+       set_bit(NFS4_SESSION_ESTABLISHED, &session->session_state);
+       session->flags = res->flags;
+       memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs));
+       if (res->flags & SESSION4_BACK_CHAN)
+               memcpy(&session->bc_attrs, &res->bc_attrs,
+                               sizeof(session->bc_attrs));
 }
 
 static int _nfs4_proc_create_session(struct nfs_client *clp,
@@ -7224,11 +7249,12 @@ static int _nfs4_proc_create_session(struct nfs_client *clp,
        struct nfs4_session *session = clp->cl_session;
        struct nfs41_create_session_args args = {
                .client = clp,
+               .clientid = clp->cl_clientid,
+               .seqid = clp->cl_seqid,
                .cb_program = NFS4_CALLBACK,
        };
-       struct nfs41_create_session_res res = {
-               .client = clp,
-       };
+       struct nfs41_create_session_res res;
+
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION],
                .rpc_argp = &args,
@@ -7245,11 +7271,15 @@ static int _nfs4_proc_create_session(struct nfs_client *clp,
 
        if (!status) {
                /* Verify the session's negotiated channel_attrs values */
-               status = nfs4_verify_channel_attrs(&args, session);
+               status = nfs4_verify_channel_attrs(&args, &res);
                /* Increment the clientid slot sequence id */
-               clp->cl_seqid++;
+               if (clp->cl_seqid == res.seqid)
+                       clp->cl_seqid++;
+               if (status)
+                       goto out;
+               nfs4_update_session(session, &res);
        }
-
+out:
        return status;
 }
 
@@ -7301,8 +7331,8 @@ int nfs4_proc_destroy_session(struct nfs4_session *session,
        dprintk("--> nfs4_proc_destroy_session\n");
 
        /* session is still being setup */
-       if (session->clp->cl_cons_state != NFS_CS_READY)
-               return status;
+       if (!test_and_clear_bit(NFS4_SESSION_ESTABLISHED, &session->session_state))
+               return 0;
 
        status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
        trace_nfs4_destroy_session(session->clp, status);
@@ -7912,6 +7942,8 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server,
 {
        struct nfs4_getdeviceinfo_args args = {
                .pdev = pdev,
+               .notify_types = NOTIFY_DEVICEID4_CHANGE |
+                       NOTIFY_DEVICEID4_DELETE,
        };
        struct nfs4_getdeviceinfo_res res = {
                .pdev = pdev,
@@ -7926,6 +7958,11 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server,
 
        dprintk("--> %s\n", __func__);
        status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
+       if (res.notification & ~args.notify_types)
+               dprintk("%s: unsupported notification\n", __func__);
+       if (res.notification != args.notify_types)
+               pdev->nocache = 1;
+
        dprintk("<-- %s status=%d\n", __func__, status);
 
        return status;