]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/nfs/nfs4proc.c
[ARM] 5321/1: Kirkwood: fix typo in Makefile
[linux-2.6-omap-h63xx.git] / fs / nfs / nfs4proc.c
index 1293e0acd82b7ab80604a9077277f0f4f97c333d..83e700a2b0c0096d100c58a31fcf3ad0023f73b6 100644 (file)
@@ -451,9 +451,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
                /* Save the delegation */
                memcpy(stateid.data, delegation->stateid.data, sizeof(stateid.data));
                rcu_read_unlock();
-               lock_kernel();
                ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode);
-               unlock_kernel();
                if (ret != 0)
                        goto out;
                ret = -EAGAIN;
@@ -1139,8 +1137,9 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int
        return res;
 }
 
-static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
-                struct iattr *sattr, struct nfs4_state *state)
+static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
+                           struct nfs_fattr *fattr, struct iattr *sattr,
+                           struct nfs4_state *state)
 {
        struct nfs_server *server = NFS_SERVER(inode);
         struct nfs_setattrargs  arg = {
@@ -1154,9 +1153,10 @@ static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
                .server         = server,
         };
         struct rpc_message msg = {
-                .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
-                .rpc_argp       = &arg,
-                .rpc_resp       = &res,
+               .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
+               .rpc_argp       = &arg,
+               .rpc_resp       = &res,
+               .rpc_cred       = cred,
         };
        unsigned long timestamp = jiffies;
        int status;
@@ -1166,7 +1166,6 @@ static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
        if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) {
                /* Use that stateid */
        } else if (state != NULL) {
-               msg.rpc_cred = state->owner->so_cred;
                nfs4_copy_stateid(&arg.stateid, state, current->files);
        } else
                memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
@@ -1177,15 +1176,16 @@ static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
        return status;
 }
 
-static int nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
-                struct iattr *sattr, struct nfs4_state *state)
+static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
+                          struct nfs_fattr *fattr, struct iattr *sattr,
+                          struct nfs4_state *state)
 {
        struct nfs_server *server = NFS_SERVER(inode);
        struct nfs4_exception exception = { };
        int err;
        do {
                err = nfs4_handle_exception(server,
-                               _nfs4_do_setattr(inode, fattr, sattr, state),
+                               _nfs4_do_setattr(inode, cred, fattr, sattr, state),
                                &exception);
        } while (exception.retry);
        return err;
@@ -1647,29 +1647,27 @@ static int
 nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
                  struct iattr *sattr)
 {
-       struct rpc_cred *cred;
        struct inode *inode = dentry->d_inode;
-       struct nfs_open_context *ctx;
+       struct rpc_cred *cred = NULL;
        struct nfs4_state *state = NULL;
        int status;
 
        nfs_fattr_init(fattr);
        
-       cred = rpc_lookup_cred();
-       if (IS_ERR(cred))
-               return PTR_ERR(cred);
-
        /* Search for an existing open(O_WRITE) file */
-       ctx = nfs_find_open_context(inode, cred, FMODE_WRITE);
-       if (ctx != NULL)
-               state = ctx->state;
+       if (sattr->ia_valid & ATTR_FILE) {
+               struct nfs_open_context *ctx;
 
-       status = nfs4_do_setattr(inode, fattr, sattr, state);
+               ctx = nfs_file_open_context(sattr->ia_file);
+               if (ctx) {
+                       cred = ctx->cred;
+                       state = ctx->state;
+               }
+       }
+
+       status = nfs4_do_setattr(inode, cred, fattr, sattr, state);
        if (status == 0)
                nfs_setattr_update_inode(inode, sattr);
-       if (ctx != NULL)
-               put_nfs_open_context(ctx);
-       put_rpccred(cred);
        return status;
 }
 
@@ -1897,17 +1895,16 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                goto out;
        }
        state = nfs4_do_open(dir, &path, flags, sattr, cred);
-       put_rpccred(cred);
        d_drop(dentry);
        if (IS_ERR(state)) {
                status = PTR_ERR(state);
-               goto out;
+               goto out_putcred;
        }
        d_add(dentry, igrab(state->inode));
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
        if (flags & O_EXCL) {
                struct nfs_fattr fattr;
-               status = nfs4_do_setattr(state->inode, &fattr, sattr, state);
+               status = nfs4_do_setattr(state->inode, cred, &fattr, sattr, state);
                if (status == 0)
                        nfs_setattr_update_inode(state->inode, sattr);
                nfs_post_op_update_inode(state->inode, &fattr);
@@ -1916,6 +1913,8 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                status = nfs4_intent_set_file(nd, &path, state);
        else
                nfs4_close_sync(&path, state, flags);
+out_putcred:
+       put_rpccred(cred);
 out:
        return status;
 }
@@ -2079,47 +2078,81 @@ static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *n
        return err;
 }
 
+struct nfs4_createdata {
+       struct rpc_message msg;
+       struct nfs4_create_arg arg;
+       struct nfs4_create_res res;
+       struct nfs_fh fh;
+       struct nfs_fattr fattr;
+       struct nfs_fattr dir_fattr;
+};
+
+static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
+               struct qstr *name, struct iattr *sattr, u32 ftype)
+{
+       struct nfs4_createdata *data;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (data != NULL) {
+               struct nfs_server *server = NFS_SERVER(dir);
+
+               data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE];
+               data->msg.rpc_argp = &data->arg;
+               data->msg.rpc_resp = &data->res;
+               data->arg.dir_fh = NFS_FH(dir);
+               data->arg.server = server;
+               data->arg.name = name;
+               data->arg.attrs = sattr;
+               data->arg.ftype = ftype;
+               data->arg.bitmask = server->attr_bitmask;
+               data->res.server = server;
+               data->res.fh = &data->fh;
+               data->res.fattr = &data->fattr;
+               data->res.dir_fattr = &data->dir_fattr;
+               nfs_fattr_init(data->res.fattr);
+               nfs_fattr_init(data->res.dir_fattr);
+       }
+       return data;
+}
+
+static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
+{
+       int status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0);
+       if (status == 0) {
+               update_changeattr(dir, &data->res.dir_cinfo);
+               nfs_post_op_update_inode(dir, data->res.dir_fattr);
+               status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
+       }
+       return status;
+}
+
+static void nfs4_free_createdata(struct nfs4_createdata *data)
+{
+       kfree(data);
+}
+
 static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
                struct page *page, unsigned int len, struct iattr *sattr)
 {
-       struct nfs_server *server = NFS_SERVER(dir);
-       struct nfs_fh fhandle;
-       struct nfs_fattr fattr, dir_fattr;
-       struct nfs4_create_arg arg = {
-               .dir_fh = NFS_FH(dir),
-               .server = server,
-               .name = &dentry->d_name,
-               .attrs = sattr,
-               .ftype = NF4LNK,
-               .bitmask = server->attr_bitmask,
-       };
-       struct nfs4_create_res res = {
-               .server = server,
-               .fh = &fhandle,
-               .fattr = &fattr,
-               .dir_fattr = &dir_fattr,
-       };
-       struct rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK],
-               .rpc_argp = &arg,
-               .rpc_resp = &res,
-       };
-       int                     status;
+       struct nfs4_createdata *data;
+       int status = -ENAMETOOLONG;
 
        if (len > NFS4_MAXPATHLEN)
-               return -ENAMETOOLONG;
+               goto out;
 
-       arg.u.symlink.pages = &page;
-       arg.u.symlink.len = len;
-       nfs_fattr_init(&fattr);
-       nfs_fattr_init(&dir_fattr);
+       status = -ENOMEM;
+       data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4LNK);
+       if (data == NULL)
+               goto out;
+
+       data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK];
+       data->arg.u.symlink.pages = &page;
+       data->arg.u.symlink.len = len;
        
-       status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-       if (!status) {
-               update_changeattr(dir, &res.dir_cinfo);
-               nfs_post_op_update_inode(dir, res.dir_fattr);
-               status = nfs_instantiate(dentry, &fhandle, &fattr);
-       }
+       status = nfs4_do_create(dir, dentry, data);
+
+       nfs4_free_createdata(data);
+out:
        return status;
 }
 
@@ -2140,39 +2173,17 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
 static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
                struct iattr *sattr)
 {
-       struct nfs_server *server = NFS_SERVER(dir);
-       struct nfs_fh fhandle;
-       struct nfs_fattr fattr, dir_fattr;
-       struct nfs4_create_arg arg = {
-               .dir_fh = NFS_FH(dir),
-               .server = server,
-               .name = &dentry->d_name,
-               .attrs = sattr,
-               .ftype = NF4DIR,
-               .bitmask = server->attr_bitmask,
-       };
-       struct nfs4_create_res res = {
-               .server = server,
-               .fh = &fhandle,
-               .fattr = &fattr,
-               .dir_fattr = &dir_fattr,
-       };
-       struct rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
-               .rpc_argp = &arg,
-               .rpc_resp = &res,
-       };
-       int                     status;
+       struct nfs4_createdata *data;
+       int status = -ENOMEM;
 
-       nfs_fattr_init(&fattr);
-       nfs_fattr_init(&dir_fattr);
-       
-       status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-       if (!status) {
-               update_changeattr(dir, &res.dir_cinfo);
-               nfs_post_op_update_inode(dir, res.dir_fattr);
-               status = nfs_instantiate(dentry, &fhandle, &fattr);
-       }
+       data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4DIR);
+       if (data == NULL)
+               goto out;
+
+       status = nfs4_do_create(dir, dentry, data);
+
+       nfs4_free_createdata(data);
+out:
        return status;
 }
 
@@ -2242,56 +2253,34 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
                struct iattr *sattr, dev_t rdev)
 {
-       struct nfs_server *server = NFS_SERVER(dir);
-       struct nfs_fh fh;
-       struct nfs_fattr fattr, dir_fattr;
-       struct nfs4_create_arg arg = {
-               .dir_fh = NFS_FH(dir),
-               .server = server,
-               .name = &dentry->d_name,
-               .attrs = sattr,
-               .bitmask = server->attr_bitmask,
-       };
-       struct nfs4_create_res res = {
-               .server = server,
-               .fh = &fh,
-               .fattr = &fattr,
-               .dir_fattr = &dir_fattr,
-       };
-       struct rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
-               .rpc_argp = &arg,
-               .rpc_resp = &res,
-       };
-       int                     status;
-       int                     mode = sattr->ia_mode;
-
-       nfs_fattr_init(&fattr);
-       nfs_fattr_init(&dir_fattr);
+       struct nfs4_createdata *data;
+       int mode = sattr->ia_mode;
+       int status = -ENOMEM;
 
        BUG_ON(!(sattr->ia_valid & ATTR_MODE));
        BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
+
+       data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK);
+       if (data == NULL)
+               goto out;
+
        if (S_ISFIFO(mode))
-               arg.ftype = NF4FIFO;
+               data->arg.ftype = NF4FIFO;
        else if (S_ISBLK(mode)) {
-               arg.ftype = NF4BLK;
-               arg.u.device.specdata1 = MAJOR(rdev);
-               arg.u.device.specdata2 = MINOR(rdev);
+               data->arg.ftype = NF4BLK;
+               data->arg.u.device.specdata1 = MAJOR(rdev);
+               data->arg.u.device.specdata2 = MINOR(rdev);
        }
        else if (S_ISCHR(mode)) {
-               arg.ftype = NF4CHR;
-               arg.u.device.specdata1 = MAJOR(rdev);
-               arg.u.device.specdata2 = MINOR(rdev);
+               data->arg.ftype = NF4CHR;
+               data->arg.u.device.specdata1 = MAJOR(rdev);
+               data->arg.u.device.specdata2 = MINOR(rdev);
        }
-       else
-               arg.ftype = NF4SOCK;
        
-       status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-       if (status == 0) {
-               update_changeattr(dir, &res.dir_cinfo);
-               nfs_post_op_update_inode(dir, res.dir_fattr);
-               status = nfs_instantiate(dentry, &fh, &fattr);
-       }
+       status = nfs4_do_create(dir, dentry, data);
+
+       nfs4_free_createdata(data);
+out:
        return status;
 }
 
@@ -2706,6 +2695,8 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
        ret = nfs_revalidate_inode(server, inode);
        if (ret < 0)
                return ret;
+       if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
+               nfs_zap_acl_cache(inode);
        ret = nfs4_read_cached_acl(inode, buf, buflen);
        if (ret != -ENOENT)
                return ret;
@@ -2733,7 +2724,8 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
        nfs_inode_return_delegation(inode);
        buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
        ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
-       nfs_zap_caches(inode);
+       nfs_access_zap_cache(inode);
+       nfs_zap_acl_cache(inode);
        return ret;
 }
 
@@ -2767,8 +2759,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
                        task->tk_status = 0;
                        return -EAGAIN;
                case -NFS4ERR_DELAY:
-                       nfs_inc_server_stats((struct nfs_server *) server,
-                                               NFSIOS_DELAY);
+                       nfs_inc_server_stats(server, NFSIOS_DELAY);
                case -NFS4ERR_GRACE:
                        rpc_delay(task, NFS4_POLL_RETRY_MAX);
                        task->tk_status = 0;
@@ -2933,7 +2924,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cre
 
 int nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred)
 {
-       long timeout;
+       long timeout = 0;
        int err;
        do {
                err = _nfs4_proc_setclientid_confirm(clp, cred);
@@ -3725,8 +3716,6 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
        .write_done     = nfs4_write_done,
        .commit_setup   = nfs4_proc_commit_setup,
        .commit_done    = nfs4_commit_done,
-       .file_open      = nfs_open,
-       .file_release   = nfs_release,
        .lock           = nfs4_proc_lock,
        .clear_acl_cache = nfs4_zap_acl_attr,
 };