Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm...
[cascardo/linux.git] / fs / nfsd / nfs4state.c
index ab45cdd..9e7103b 100644 (file)
@@ -151,7 +151,7 @@ get_nfs4_file(struct nfs4_file *fi)
 }
 
 static int num_delegations;
-unsigned int max_delegations;
+unsigned long max_delegations;
 
 /*
  * Open owner state (share locks)
@@ -700,8 +700,8 @@ static int nfsd4_get_drc_mem(int slotsize, u32 num)
        num = min_t(u32, num, NFSD_MAX_SLOTS_PER_SESSION);
 
        spin_lock(&nfsd_drc_lock);
-       avail = min_t(int, NFSD_MAX_MEM_PER_SESSION,
-                       nfsd_drc_max_mem - nfsd_drc_mem_used);
+       avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION,
+                   nfsd_drc_max_mem - nfsd_drc_mem_used);
        num = min_t(int, num, avail / slotsize);
        nfsd_drc_mem_used += num * slotsize;
        spin_unlock(&nfsd_drc_lock);
@@ -743,9 +743,12 @@ out_free:
        return NULL;
 }
 
-static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4_channel_attrs *req, int numslots, int slotsize)
+static void init_forechannel_attrs(struct nfsd4_channel_attrs *new,
+                                  struct nfsd4_channel_attrs *req,
+                                  int numslots, int slotsize,
+                                  struct nfsd_net *nn)
 {
-       u32 maxrpc = nfsd_serv->sv_max_mesg;
+       u32 maxrpc = nn->nfsd_serv->sv_max_mesg;
 
        new->maxreqs = numslots;
        new->maxresp_cached = min_t(u32, req->maxresp_cached,
@@ -883,7 +886,8 @@ void nfsd4_put_session(struct nfsd4_session *ses)
        spin_unlock(&nn->client_lock);
 }
 
-static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
+static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan,
+                                          struct nfsd_net *nn)
 {
        struct nfsd4_session *new;
        int numslots, slotsize;
@@ -904,7 +908,7 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
                nfsd4_put_drc_mem(slotsize, fchan->maxreqs);
                return NULL;
        }
-       init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize);
+       init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize, nn);
        return new;
 }
 
@@ -1198,7 +1202,7 @@ static bool groups_equal(struct group_info *g1, struct group_info *g2)
        if (g1->ngroups != g2->ngroups)
                return false;
        for (i=0; i<g1->ngroups; i++)
-               if (GROUP_AT(g1, i) != GROUP_AT(g2, i))
+               if (!gid_eq(GROUP_AT(g1, i), GROUP_AT(g2, i)))
                        return false;
        return true;
 }
@@ -1223,8 +1227,8 @@ static bool
 same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
 {
        if ((is_gss_cred(cr1) != is_gss_cred(cr2))
-               || (cr1->cr_uid != cr2->cr_uid)
-               || (cr1->cr_gid != cr2->cr_gid)
+               || (!uid_eq(cr1->cr_uid, cr2->cr_uid))
+               || (!gid_eq(cr1->cr_gid, cr2->cr_gid))
                || !groups_equal(cr1->cr_group_info, cr2->cr_group_info))
                return false;
        if (cr1->cr_principal == cr2->cr_principal)
@@ -1776,7 +1780,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
                return nfserr_inval;
        if (check_forechannel_attrs(cr_ses->fore_channel))
                return nfserr_toosmall;
-       new = alloc_session(&cr_ses->fore_channel);
+       new = alloc_session(&cr_ses->fore_channel, nn);
        if (!new)
                return nfserr_jukebox;
        status = nfserr_jukebox;
@@ -1851,14 +1855,6 @@ out_free_session:
        goto out;
 }
 
-static bool nfsd4_last_compound_op(struct svc_rqst *rqstp)
-{
-       struct nfsd4_compoundres *resp = rqstp->rq_resp;
-       struct nfsd4_compoundargs *argp = rqstp->rq_argp;
-
-       return argp->opcnt == resp->opcnt;
-}
-
 static __be32 nfsd4_map_bcts_dir(u32 *dir)
 {
        switch (*dir) {
@@ -2987,6 +2983,7 @@ out:
        }
        return;
 out_free:
+       unhash_stid(&dp->dl_stid);
        nfs4_put_delegation(dp);
 out_no_deleg:
        flag = NFS4_OPEN_DELEGATE_NONE;
@@ -3132,6 +3129,18 @@ void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status)
                free_generic_stateid(open->op_stp);
 }
 
+static __be32 lookup_clientid(clientid_t *clid, bool session, struct nfsd_net *nn, struct nfs4_client **clp)
+{
+       struct nfs4_client *found;
+
+       if (STALE_CLIENTID(clid, nn))
+               return nfserr_stale_clientid;
+       found = find_confirmed_client(clid, session, nn);
+       if (clp)
+               *clp = found;
+       return found ? nfs_ok : nfserr_expired;
+}
+
 __be32
 nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
            clientid_t *clid)
@@ -3143,16 +3152,9 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        nfs4_lock_state();
        dprintk("process_renew(%08x/%08x): starting\n", 
                        clid->cl_boot, clid->cl_id);
-       status = nfserr_stale_clientid;
-       if (STALE_CLIENTID(clid, nn))
-               goto out;
-       clp = find_confirmed_client(clid, cstate->minorversion, nn);
-       status = nfserr_expired;
-       if (clp == NULL) {
-               /* We assume the client took too long to RENEW. */
-               dprintk("nfsd4_renew: clientid not found!\n");
+       status = lookup_clientid(clid, cstate->minorversion, nn, &clp);
+       if (status)
                goto out;
-       }
        status = nfserr_cb_path_down;
        if (!list_empty(&clp->cl_delegations)
                        && clp->cl_cb_state != NFSD4_CB_UP)
@@ -4293,9 +4295,11 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        nfs4_lock_state();
 
-       status = nfserr_stale_clientid;
-       if (!nfsd4_has_session(cstate) && STALE_CLIENTID(&lockt->lt_clientid, nn))
-               goto out;
+       if (!nfsd4_has_session(cstate)) {
+               status = lookup_clientid(&lockt->lt_clientid, false, nn, NULL);
+               if (status)
+                       goto out;
+       }
 
        if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
                goto out;
@@ -4466,14 +4470,12 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
        dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
                clid->cl_boot, clid->cl_id);
 
-       /* XXX check for lease expiration */
-
-       status = nfserr_stale_clientid;
-       if (STALE_CLIENTID(clid, nn))
-               return status;
-
        nfs4_lock_state();
 
+       status = lookup_clientid(clid, cstate->minorversion, nn, NULL);
+       if (status)
+               goto out;
+
        status = nfserr_locks_held;
        INIT_LIST_HEAD(&matches);
 
@@ -4611,6 +4613,22 @@ u64 nfsd_forget_client(struct nfs4_client *clp, u64 max)
        return 1;
 }
 
+u64 nfsd_print_client(struct nfs4_client *clp, u64 num)
+{
+       char buf[INET6_ADDRSTRLEN];
+       rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
+       printk(KERN_INFO "NFS Client: %s\n", buf);
+       return 1;
+}
+
+static void nfsd_print_count(struct nfs4_client *clp, unsigned int count,
+                            const char *type)
+{
+       char buf[INET6_ADDRSTRLEN];
+       rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
+       printk(KERN_INFO "NFS Client: %s has %u %s\n", buf, count, type);
+}
+
 static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max, void (*func)(struct nfs4_lockowner *))
 {
        struct nfs4_openowner *oop;
@@ -4637,6 +4655,13 @@ u64 nfsd_forget_client_locks(struct nfs4_client *clp, u64 max)
        return nfsd_foreach_client_lock(clp, max, release_lockowner);
 }
 
+u64 nfsd_print_client_locks(struct nfs4_client *clp, u64 max)
+{
+       u64 count = nfsd_foreach_client_lock(clp, max, NULL);
+       nfsd_print_count(clp, count, "locked files");
+       return count;
+}
+
 static u64 nfsd_foreach_client_open(struct nfs4_client *clp, u64 max, void (*func)(struct nfs4_openowner *))
 {
        struct nfs4_openowner *oop, *next;
@@ -4657,6 +4682,13 @@ u64 nfsd_forget_client_openowners(struct nfs4_client *clp, u64 max)
        return nfsd_foreach_client_open(clp, max, release_openowner);
 }
 
+u64 nfsd_print_client_openowners(struct nfs4_client *clp, u64 max)
+{
+       u64 count = nfsd_foreach_client_open(clp, max, NULL);
+       nfsd_print_count(clp, count, "open files");
+       return count;
+}
+
 static u64 nfsd_find_all_delegations(struct nfs4_client *clp, u64 max,
                                     struct list_head *victims)
 {
@@ -4703,6 +4735,18 @@ u64 nfsd_recall_client_delegations(struct nfs4_client *clp, u64 max)
        return count;
 }
 
+u64 nfsd_print_client_delegations(struct nfs4_client *clp, u64 max)
+{
+       u64 count = 0;
+
+       spin_lock(&recall_lock);
+       count = nfsd_find_all_delegations(clp, max, NULL);
+       spin_unlock(&recall_lock);
+
+       nfsd_print_count(clp, count, "delegations");
+       return count;
+}
+
 u64 nfsd_for_n_state(u64 max, u64 (*func)(struct nfs4_client *, u64))
 {
        struct nfs4_client *clp, *next;
@@ -4721,6 +4765,21 @@ u64 nfsd_for_n_state(u64 max, u64 (*func)(struct nfs4_client *, u64))
        return count;
 }
 
+struct nfs4_client *nfsd_find_client(struct sockaddr_storage *addr, size_t addr_size)
+{
+       struct nfs4_client *clp;
+       struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, nfsd_net_id);
+
+       if (!nfsd_netns_ready(nn))
+               return NULL;
+
+       list_for_each_entry(clp, &nn->client_lru, cl_lru) {
+               if (memcmp(&clp->cl_addr, addr, addr_size) == 0)
+                       return clp;
+       }
+       return NULL;
+}
+
 #endif /* CONFIG_NFSD_FAULT_INJECTION */
 
 /* initialization to perform at module load time: */