Merge master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6
[pandora-kernel.git] / fs / nfs / nfs4proc.c
index 850f085..47c7e6e 100644 (file)
@@ -55,7 +55,7 @@
 
 #define NFSDBG_FACILITY                NFSDBG_PROC
 
-#define NFS4_POLL_RETRY_MIN    (1*HZ)
+#define NFS4_POLL_RETRY_MIN    (HZ/10)
 #define NFS4_POLL_RETRY_MAX    (15*HZ)
 
 struct nfs4_opendata;
@@ -758,7 +758,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
        }
        nfs_confirm_seqid(&data->owner->so_seqid, 0);
        if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
-               return server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
+               return server->nfs_client->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
        return 0;
 }
 
@@ -793,10 +793,17 @@ out:
 int nfs4_recover_expired_lease(struct nfs_server *server)
 {
        struct nfs_client *clp = server->nfs_client;
+       int ret;
 
-       if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
+       for (;;) {
+               ret = nfs4_wait_clnt_recover(server->client, clp);
+               if (ret != 0)
+                       return ret;
+               if (!test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
+                       break;
                nfs4_schedule_state_recovery(clp);
-       return nfs4_wait_clnt_recover(server->client, clp);
+       }
+       return 0;
 }
 
 /*
@@ -1268,7 +1275,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
                BUG_ON(nd->intent.open.flags & O_CREAT);
        }
 
-       cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+       cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
        if (IS_ERR(cred))
                return (struct dentry *)cred;
        state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
@@ -1291,7 +1298,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
        struct rpc_cred *cred;
        struct nfs4_state *state;
 
-       cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+       cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
        if (IS_ERR(cred))
                return PTR_ERR(cred);
        state = nfs4_open_delegated(dentry->d_inode, openflags, cred);
@@ -1393,70 +1400,19 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
        return err;
 }
 
+/*
+ * get the file handle for the "/" directory on the server
+ */
 static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
-               struct nfs_fsinfo *info)
+                             struct nfs_fsinfo *info)
 {
-       struct nfs_fattr *      fattr = info->fattr;
-       unsigned char *         p;
-       struct qstr             q;
-       struct nfs4_lookup_arg args = {
-               .dir_fh = fhandle,
-               .name = &q,
-               .bitmask = nfs4_fattr_bitmap,
-       };
-       struct nfs4_lookup_res res = {
-               .server = server,
-               .fattr = fattr,
-               .fh = fhandle,
-       };
-       struct rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
-               .rpc_argp = &args,
-               .rpc_resp = &res,
-       };
        int status;
 
-       /*
-        * Now we do a separate LOOKUP for each component of the mount path.
-        * The LOOKUPs are done separately so that we can conveniently
-        * catch an ERR_WRONGSEC if it occurs along the way...
-        */
        status = nfs4_lookup_root(server, fhandle, info);
-       if (status)
-               goto out;
-
-       p = server->mnt_path;
-       for (;;) {
-               struct nfs4_exception exception = { };
-
-               while (*p == '/')
-                       p++;
-               if (!*p)
-                       break;
-               q.name = p;
-               while (*p && (*p != '/'))
-                       p++;
-               q.len = p - q.name;
-
-               do {
-                       nfs_fattr_init(fattr);
-                       status = nfs4_handle_exception(server,
-                                       rpc_call_sync(server->client, &msg, 0),
-                                       &exception);
-               } while (exception.retry);
-               if (status == 0)
-                       continue;
-               if (status == -ENOENT) {
-                       printk(KERN_NOTICE "NFS: mount path %s does not exist!\n", server->mnt_path);
-                       printk(KERN_NOTICE "NFS: suggestion: try mounting '/' instead.\n");
-               }
-               break;
-       }
        if (status == 0)
                status = nfs4_server_capabilities(server, fhandle);
        if (status == 0)
                status = nfs4_do_fsinfo(server, fhandle, info);
-out:
        return nfs4_map_errors(status);
 }
 
@@ -1565,7 +1521,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
        nfs_fattr_init(fattr);
        
-       cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
+       cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
        if (IS_ERR(cred))
                return PTR_ERR(cred);
 
@@ -1927,7 +1883,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
        struct rpc_cred *cred;
        int status = 0;
 
-       cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+       cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
        if (IS_ERR(cred)) {
                status = PTR_ERR(cred);
                goto out;
@@ -2135,24 +2091,24 @@ static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *n
        return err;
 }
 
-static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name,
-               struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle,
-               struct nfs_fattr *fattr)
+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_fattr dir_fattr;
+       struct nfs_fh fhandle;
+       struct nfs_fattr fattr, dir_fattr;
        struct nfs4_create_arg arg = {
                .dir_fh = NFS_FH(dir),
                .server = server,
-               .name = name,
+               .name = &dentry->d_name,
                .attrs = sattr,
                .ftype = NF4LNK,
                .bitmask = server->attr_bitmask,
        };
        struct nfs4_create_res res = {
                .server = server,
-               .fh = fhandle,
-               .fattr = fattr,
+               .fh = &fhandle,
+               .fattr = &fattr,
                .dir_fattr = &dir_fattr,
        };
        struct rpc_message msg = {
@@ -2162,29 +2118,32 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name,
        };
        int                     status;
 
-       if (path->len > NFS4_MAXPATHLEN)
+       if (len > NFS4_MAXPATHLEN)
                return -ENAMETOOLONG;
-       arg.u.symlink = path;
-       nfs_fattr_init(fattr);
+
+       arg.u.symlink.pages = &page;
+       arg.u.symlink.len = len;
+       nfs_fattr_init(&fattr);
        nfs_fattr_init(&dir_fattr);
        
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-       if (!status)
+       if (!status) {
                update_changeattr(dir, &res.dir_cinfo);
-       nfs_post_op_update_inode(dir, res.dir_fattr);
+               nfs_post_op_update_inode(dir, res.dir_fattr);
+               status = nfs_instantiate(dentry, &fhandle, &fattr);
+       }
        return status;
 }
 
-static int nfs4_proc_symlink(struct inode *dir, struct qstr *name,
-               struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle,
-               struct nfs_fattr *fattr)
+static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
+               struct page *page, unsigned int len, struct iattr *sattr)
 {
        struct nfs4_exception exception = { };
        int err;
        do {
                err = nfs4_handle_exception(NFS_SERVER(dir),
-                               _nfs4_proc_symlink(dir, name, path, sattr,
-                                       fhandle, fattr),
+                               _nfs4_proc_symlink(dir, dentry, page,
+                                                       len, sattr),
                                &exception);
        } while (exception.retry);
        return err;
@@ -2816,7 +2775,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
                return -EOPNOTSUPP;
        nfs_inode_return_delegation(inode);
        buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
-       ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
+       ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
        if (ret == 0)
                nfs4_write_cached_acl(inode, buf, buflen);
        return ret;
@@ -2932,6 +2891,7 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct
                        if (ret == 0)
                                exception->retry = 1;
                        break;
+               case -NFS4ERR_FILE_OPEN:
                case -NFS4ERR_GRACE:
                case -NFS4ERR_DELAY:
                        ret = nfs4_delay(server->client, &exception->timeout);
@@ -2968,7 +2928,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po
        for(;;) {
                setclientid.sc_name_len = scnprintf(setclientid.sc_name,
                                sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u",
-                               clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr),
+                               clp->cl_ipaddr, NIPQUAD(clp->cl_addr.sin_addr),
                                cred->cr_ops->cr_name,
                                clp->cl_id_uniquifier);
                setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
@@ -3761,7 +3721,7 @@ static struct inode_operations nfs4_file_inode_operations = {
        .listxattr      = nfs4_listxattr,
 };
 
-struct nfs_rpc_ops     nfs_v4_clientops = {
+const struct nfs_rpc_ops nfs_v4_clientops = {
        .version        = 4,                    /* protocol version */
        .dentry_ops     = &nfs4_dentry_operations,
        .dir_inode_ops  = &nfs4_dir_inode_operations,