return 0;
}
+static void
+warn_no_idmapd(struct cache_detail *detail)
+{
+ printk("nfsd: nfsv4 idmapping failing: has idmapd %s?\n",
+ detail->last_close? "died" : "not been started");
+}
+
+
static int idtoname_parse(struct cache_detail *, char *, int);
static struct ent *idtoname_lookup(struct ent *, int);
.cache_request = idtoname_request,
.cache_parse = idtoname_parse,
.cache_show = idtoname_show,
+ .warn_no_listener = warn_no_idmapd,
};
int
.cache_request = nametoid_request,
.cache_parse = nametoid_parse,
.cache_show = nametoid_show,
+ .warn_no_listener = warn_no_idmapd,
};
int
atomic_t count;
};
-static void
+static inline void
put_mdr(struct idmap_defer_req *mdr)
{
if (atomic_dec_and_test(&mdr->count))
kfree(mdr);
}
+static inline void
+get_mdr(struct idmap_defer_req *mdr)
+{
+ atomic_inc(&mdr->count);
+}
+
static void
idmap_revisit(struct cache_deferred_req *dreq, int toomany)
{
container_of(req, struct idmap_defer_req, req);
mdr->deferred_req.revisit = idmap_revisit;
+ get_mdr(mdr);
return (&mdr->deferred_req);
}
-static int threads_waiting = 0;
+static inline int
+do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *, int), struct ent *key,
+ struct cache_detail *detail, struct ent **item,
+ struct idmap_defer_req *mdr)
+{
+ *item = lookup_fn(key, 0);
+ if (!*item)
+ return -ENOMEM;
+ return cache_check(detail, &(*item)->h, &mdr->req);
+}
static inline int
-idmap_lookup_wait(struct idmap_defer_req *mdr, wait_queue_t waitq, struct
- svc_rqst *rqstp) {
- int ret = -ETIMEDOUT;
-
- set_task_state(current, TASK_INTERRUPTIBLE);
- lock_kernel();
- /* XXX: Does it matter that threads_waiting isn't per-server? */
- /* Note: BKL prevents races with nfsd_svc and other lookups */
- if (2 * threads_waiting > rqstp->rq_server->sv_nrthreads)
- goto out;
- threads_waiting++;
- schedule_timeout(10 * HZ);
- threads_waiting--;
- ret = 0;
-out:
- unlock_kernel();
- remove_wait_queue(&mdr->waitq, &waitq);
- set_task_state(current, TASK_RUNNING);
- put_mdr(mdr);
+do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int),
+ struct ent *key, struct cache_detail *detail,
+ struct ent **item)
+{
+ int ret = -ENOMEM;
+
+ *item = lookup_fn(key, 0);
+ if (!*item)
+ goto out_err;
+ ret = -ETIMEDOUT;
+ if (!test_bit(CACHE_VALID, &(*item)->h.flags)
+ || (*item)->h.expiry_time < get_seconds()
+ || detail->flush_time > (*item)->h.last_refresh)
+ goto out_put;
+ ret = -ENOENT;
+ if (test_bit(CACHE_NEGATIVE, &(*item)->h.flags))
+ goto out_put;
+ return 0;
+out_put:
+ ent_put(&(*item)->h, detail);
+out_err:
+ *item = NULL;
return ret;
}
struct cache_detail *detail, struct ent **item)
{
struct idmap_defer_req *mdr;
- DECLARE_WAITQUEUE(waitq, current);
int ret;
- *item = lookup_fn(key, 0);
- if (!*item)
- return -ENOMEM;
mdr = kmalloc(sizeof(*mdr), GFP_KERNEL);
+ if (!mdr)
+ return -ENOMEM;
memset(mdr, 0, sizeof(*mdr));
+ atomic_set(&mdr->count, 1);
init_waitqueue_head(&mdr->waitq);
- add_wait_queue(&mdr->waitq, &waitq);
- atomic_set(&mdr->count, 2);
mdr->req.defer = idmap_defer;
- ret = cache_check(detail, &(*item)->h, &mdr->req);
+ ret = do_idmap_lookup(lookup_fn, key, detail, item, mdr);
if (ret == -EAGAIN) {
- ret = idmap_lookup_wait(mdr, waitq, rqstp);
- if (ret)
- goto out;
- /* Try again, but don't wait. */
- *item = lookup_fn(key, 0);
- ret = -ENOMEM;
- if (!*item)
- goto out;
- ret = -ETIMEDOUT;
- if (!test_bit(CACHE_VALID, &(*item)->h.flags)) {
- ent_put(&(*item)->h, detail);
- goto out;
- }
- ret = cache_check(detail, &(*item)->h, NULL);
+ wait_event_interruptible_timeout(mdr->waitq,
+ test_bit(CACHE_VALID, &(*item)->h.flags), 1 * HZ);
+ ret = do_idmap_lookup_nowait(lookup_fn, key, detail, item);
}
-out:
+ put_mdr(mdr);
return ret;
}
key.name[namelen] = '\0';
strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item);
+ if (ret == -ENOENT)
+ ret = -ESRCH; /* nfserr_badname */
if (ret)
return ret;
*id = item->id;
strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item);
+ if (ret == -ENOENT)
+ return sprintf(name, "%u", id);
if (ret)
return ret;
ret = strlen(item->name);