X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fnfsd%2Fnfs4idmap.c;h=4ba540841cf6f7c8866e52ade9de62186d8c403a;hb=4e4f43fe003969bdaa246374b90e16708a22ef79;hp=97d430bf2bb1fba302dab025250f7349330aa016;hpb=86090fcac5e27b630656fe3d963a6b80e26dac44;p=linux-2.6.git diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 97d430bf2..4ba540841 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -175,6 +175,14 @@ idtoname_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h) 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); @@ -186,6 +194,7 @@ struct cache_detail idtoname_cache = { .cache_request = idtoname_request, .cache_parse = idtoname_parse, .cache_show = idtoname_show, + .warn_no_listener = warn_no_idmapd, }; int @@ -318,6 +327,7 @@ struct cache_detail nametoid_cache = { .cache_request = nametoid_request, .cache_parse = nametoid_parse, .cache_show = nametoid_show, + .warn_no_listener = warn_no_idmapd, }; int @@ -409,13 +419,19 @@ struct idmap_defer_req { 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) { @@ -433,31 +449,44 @@ idmap_defer(struct cache_req *req) 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; } @@ -467,36 +496,22 @@ idmap_lookup(struct svc_rqst *rqstp, 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; } @@ -515,6 +530,8 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen 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; @@ -533,6 +550,8 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) 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);