* [PATCH] kNFSdv4 - 2 of 10 - better handling of failed idmap lookups
2004-04-08 1:18 [PATCH] kNFSdv4 - 0 of 10 - Introduction NeilBrown
` (4 preceding siblings ...)
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 6 of 10 - Keep state to allow replays for 'close' to work NeilBrown
@ 2004-04-08 1:18 ` NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 5 of 10 - Fix bad error returm from svcauth_gss_accept NeilBrown
` (3 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: NeilBrown @ 2004-04-08 1:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: nfs, J. Bruce Fields
From: "J. Bruce Fields" <bfields@fieldses.org>
Slightly better behavior on failed mapping (which may happen either because
idmapd is not running, or because there it has told us it doesn't know the
mapping.):
on name->id (setattr), return BADNAME. (I used ESRCH to
communicate BADNAME, just because it was the first error in
include/asm-generic/errno-base.h that had something to
do with nonexistance of something, and that we weren't
already using.)
id->name (getattr), return a string representation of the numerical
id. This is probably useless to the client, especially
since we're unlikely to accept such a string on a setattr,
but perhaps some client will find it mildly helpful.
----------- Diffstat output ------------
./fs/nfsd/nfs4idmap.c | 4 ++++
./fs/nfsd/nfsproc.c | 1 +
./include/linux/nfsd/nfsd.h | 1 +
3 files changed, 6 insertions(+)
diff ./fs/nfsd/nfs4idmap.c~current~ ./fs/nfsd/nfs4idmap.c
--- ./fs/nfsd/nfs4idmap.c~current~ 2004-04-08 10:50:09.000000000 +1000
+++ ./fs/nfsd/nfs4idmap.c 2004-04-08 10:50:13.000000000 +1000
@@ -545,6 +545,8 @@ idmap_name_to_id(struct svc_rqst *rqstp,
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;
@@ -563,6 +565,8 @@ idmap_id_to_name(struct svc_rqst *rqstp,
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);
diff ./fs/nfsd/nfsproc.c~current~ ./fs/nfsd/nfsproc.c
--- ./fs/nfsd/nfsproc.c~current~ 2004-04-06 10:57:05.000000000 +1000
+++ ./fs/nfsd/nfsproc.c 2004-04-08 10:50:13.000000000 +1000
@@ -588,6 +588,7 @@ nfserrno (int errno)
{ nfserr_jukebox, -ETIMEDOUT },
{ nfserr_dropit, -EAGAIN },
{ nfserr_dropit, -ENOMEM },
+ { nfserr_badname, -ESRCH },
{ -1, -EIO }
};
int i;
diff ./include/linux/nfsd/nfsd.h~current~ ./include/linux/nfsd/nfsd.h
--- ./include/linux/nfsd/nfsd.h~current~ 2004-04-06 10:57:05.000000000 +1000
+++ ./include/linux/nfsd/nfsd.h 2004-04-08 10:50:13.000000000 +1000
@@ -196,6 +196,7 @@ void nfsd_lockd_shutdown(void);
#define nfserr_openmode __constant_htonl(NFSERR_OPENMODE)
#define nfserr_locks_held __constant_htonl(NFSERR_LOCKS_HELD)
#define nfserr_op_illegal __constant_htonl(NFSERR_OP_ILLEGAL)
+#define nfserr_badname __constant_htonl(NFSERR_BADNAME)
/* error codes for internal use */
/* if a request fails due to kmalloc failure, it gets dropped.
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH] kNFSdv4 - 10 of 10 - Implement server-side reboot recovery (mostly)
2004-04-08 1:18 [PATCH] kNFSdv4 - 0 of 10 - Introduction NeilBrown
` (6 preceding siblings ...)
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 5 of 10 - Fix bad error returm from svcauth_gss_accept NeilBrown
@ 2004-04-08 1:18 ` NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 1 of 10 - idmap bugfixes and cleanup NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 4 of 10 - nfsd4_readdir fixes NeilBrown
9 siblings, 0 replies; 16+ messages in thread
From: NeilBrown @ 2004-04-08 1:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: nfs, J. Bruce Fields
From: "J. Bruce Fields" <bfields@fieldses.org>
>From Andros: Implement server-side reboot recovery (server now handles open and
lock reclaims). Not completely to spec: we don't yet store the state in stable
storage that would be required to recover correctly in certain situations.
----------- Diffstat output ------------
./fs/nfsd/nfs4proc.c | 102 +++++++++++++++++++++++++++++++++++++------
./fs/nfsd/nfs4state.c | 53 +++++++++++++++++++---
./include/linux/nfsd/nfsd.h | 3 +
./include/linux/nfsd/state.h | 2
4 files changed, 140 insertions(+), 20 deletions(-)
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
--- ./fs/nfsd/nfs4proc.c~current~ 2004-04-08 10:57:10.000000000 +1000
+++ ./fs/nfsd/nfs4proc.c 2004-04-08 10:57:18.000000000 +1000
@@ -66,10 +66,31 @@ fh_dup2(struct svc_fh *dst, struct svc_f
}
static int
+do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
+{
+ int accmode, status;
+
+ if (open->op_truncate &&
+ !(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
+ return nfserr_inval;
+
+ accmode = MAY_NOP;
+ if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
+ accmode = MAY_READ;
+ if (open->op_share_deny & NFS4_SHARE_ACCESS_WRITE)
+ accmode |= (MAY_WRITE | MAY_TRUNC);
+ accmode |= MAY_OWNER_OVERRIDE;
+
+ status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
+
+ return status;
+}
+
+static int
do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
{
struct svc_fh resfh;
- int accmode, status;
+ int status;
fh_init(&resfh, NFS4_FHSIZE);
open->op_truncate = 0;
@@ -92,6 +113,8 @@ do_open_lookup(struct svc_rqst *rqstp, s
if (!status) {
set_change_info(&open->op_cinfo, current_fh);
+
+ /* set reply cache */
fh_dup2(current_fh, &resfh);
/* XXXJBF: keep a saved svc_fh struct instead?? */
open->op_stateowner->so_replay.rp_openfh_len =
@@ -100,19 +123,41 @@ do_open_lookup(struct svc_rqst *rqstp, s
&resfh.fh_handle.fh_base,
resfh.fh_handle.fh_size);
- accmode = MAY_NOP;
- if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
- accmode = MAY_READ;
- if (open->op_share_deny & NFS4_SHARE_ACCESS_WRITE)
- accmode |= (MAY_WRITE | MAY_TRUNC);
- accmode |= MAY_OWNER_OVERRIDE;
- status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
+ status = do_open_permission(rqstp, current_fh, open);
}
fh_put(&resfh);
return status;
}
+static int
+do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
+{
+ int status;
+
+ dprintk("NFSD: do_open_fhandle\n");
+
+ /* we don't know the target directory, and therefore can not
+ * set the change info
+ */
+
+ memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info));
+
+ /* set replay cache */
+ open->op_stateowner->so_replay.rp_openfh_len = current_fh->fh_handle.fh_size;
+ memcpy(open->op_stateowner->so_replay.rp_openfh,
+ ¤t_fh->fh_handle.fh_base,
+ current_fh->fh_handle.fh_size);
+
+ open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
+ !open->op_iattr.ia_size;
+
+ status = do_open_permission(rqstp, current_fh, open);
+
+ return status;
+}
+
+
/*
* nfs4_unlock_state() called in encode
*/
@@ -124,6 +169,13 @@ nfsd4_open(struct svc_rqst *rqstp, struc
(int)open->op_fname.len, open->op_fname.data,
open->op_stateowner);
+ if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+ return nfserr_grace;
+
+ if (nfs4_in_no_grace() &&
+ open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+ return nfserr_no_grace;
+
/* This check required by spec. */
if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
return nfserr_inval;
@@ -148,16 +200,30 @@ nfsd4_open(struct svc_rqst *rqstp, struc
}
if (status)
return status;
+ if (open->op_claim_type == NFS4_OPEN_CLAIM_NULL) {
/*
* This block of code will (1) set CURRENT_FH to the file being opened,
* creating it if necessary, (2) set open->op_cinfo,
* (3) set open->op_truncate if the file is to be truncated
* after opening, (4) do permission checking.
*/
- status = do_open_lookup(rqstp, current_fh, open);
- if (status)
- return status;
-
+ status = do_open_lookup(rqstp, current_fh, open);
+ if (status)
+ return status;
+ } else if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) {
+ /*
+ * The CURRENT_FH is already set to the file being opened. This
+ * block of code will (1) set open->op_cinfo, (2) set
+ * open->op_truncate if the file is to be truncated after opening,
+ * (3) do permission checking.
+ */
+ status = do_open_fhandle(rqstp, current_fh, open);
+ if (status)
+ return status;
+ } else {
+ printk("NFSD: unsupported OPEN claim type\n");
+ return nfserr_inval;
+ }
/*
* nfsd4_process_open2() does the actual opening of the file. If
* successful, it (1) truncates the file if open->op_truncate was
@@ -414,6 +480,8 @@ nfsd4_read(struct svc_rqst *rqstp, struc
int status;
/* no need to check permission - this will be done in nfsd_read() */
+ if (nfs4_in_grace())
+ return nfserr_grace;
if (read->rd_offset >= OFFSET_MAX)
return nfserr_inval;
@@ -539,10 +607,13 @@ static inline int
nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr)
{
struct nfs4_stateid *stp;
- int status = nfserr_nofilehandle;
+ int status = nfs_ok;
+
+ if (nfs4_in_grace())
+ return nfserr_grace;
if (!current_fh->fh_dentry)
- goto out;
+ return nfserr_nofilehandle;
status = nfs_ok;
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
@@ -581,6 +652,9 @@ nfsd4_write(struct svc_rqst *rqstp, stru
u32 *p;
int status = nfs_ok;
+ if (nfs4_in_grace())
+ return nfserr_grace;
+
/* no need to check permission - this will be done in nfsd_write() */
if (write->wr_offset >= OFFSET_MAX)
diff ./fs/nfsd/nfs4state.c~current~ ./fs/nfsd/nfs4state.c
--- ./fs/nfsd/nfs4state.c~current~ 2004-04-08 10:57:00.000000000 +1000
+++ ./fs/nfsd/nfs4state.c 2004-04-08 10:57:18.000000000 +1000
@@ -52,6 +52,7 @@
/* Globals */
time_t boot_time;
+static time_t grace_end = 0;
static u32 current_clientid = 1;
static u32 current_ownerid;
static u32 current_fileid;
@@ -1104,7 +1105,7 @@ nfsd4_process_open1(struct nfsd4_open *o
status = nfserr_stale_clientid;
if (STALE_CLIENTID(&open->op_clientid))
- goto out;
+ return status;
strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
if (find_openstateowner_str(strhashval, open, &sop)) {
@@ -1125,7 +1126,7 @@ nfsd4_process_open1(struct nfsd4_open *o
}
/* replay: indicate to calling function */
status = NFSERR_REPLAY_ME;
- goto out;
+ return status;
}
if (sop->so_confirmed) {
if (open->op_seqid == sop->so_seqid + 1) {
@@ -1163,6 +1164,8 @@ instantiate_new_owner:
renew:
renew_client(sop->so_client);
out:
+ if (status && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+ status = nfserr_reclaim_bad;
return status;
}
/*
@@ -1173,7 +1176,7 @@ nfsd4_process_open2(struct svc_rqst *rqs
{
struct iattr iattr;
struct nfs4_stateowner *sop = open->op_stateowner;
- struct nfs4_file *fp;
+ struct nfs4_file *fp = NULL;
struct inode *ino;
unsigned int fi_hashval;
struct list_head *pos, *next;
@@ -1182,7 +1185,7 @@ nfsd4_process_open2(struct svc_rqst *rqs
status = nfserr_resource;
if (!sop)
- goto out;
+ return status;
ino = current_fh->fh_dentry->d_inode;
@@ -1274,6 +1277,17 @@ out:
if (fp && list_empty(&fp->fi_perfile))
release_file(fp);
+ if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) {
+ if (status)
+ status = nfserr_reclaim_bad;
+ else {
+ /* successful reclaim. so_seqid is decremented because
+ * it will be bumped in encode_open
+ */
+ open->op_stateowner->so_confirmed = 1;
+ open->op_stateowner->so_seqid--;
+ }
+ }
/*
* To finish the open response, we just need to set the rflags.
*/
@@ -1286,6 +1300,7 @@ out_free:
kfree(stp);
goto out;
}
+
static struct work_struct laundromat_work;
static void laundromat_main(void *);
static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
@@ -1983,6 +1998,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
(long long) lock->lk_offset,
(long long) lock->lk_length);
+ if (nfs4_in_grace() && !lock->lk_reclaim)
+ return nfserr_grace;
+ if (nfs4_in_no_grace() && lock->lk_reclaim)
+ return nfserr_no_grace;
+
if (check_lock_length(lock->lk_offset, lock->lk_length))
return nfserr_inval;
@@ -2012,8 +2032,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
CHECK_FH | OPEN_STATE,
&open_sop, &open_stp,
&lock->v.new.clientid);
- if (status)
+ if (status) {
+ if (lock->lk_reclaim)
+ status = nfserr_reclaim_bad;
goto out;
+ }
/* create lockowner and lock stateid */
fp = open_stp->st_file;
strhashval = lock_ownerstr_hashval(fp->fi_inode,
@@ -2148,6 +2171,9 @@ nfsd4_lockt(struct svc_rqst *rqstp, stru
unsigned int strhashval;
int status;
+ if (nfs4_in_grace())
+ return nfserr_grace;
+
if (check_lock_length(lockt->lt_offset, lockt->lt_length))
return nfserr_inval;
@@ -2377,6 +2403,7 @@ void
nfs4_state_init(void)
{
int i;
+ time_t start = get_seconds();
if (nfs4_init)
return;
@@ -2407,13 +2434,27 @@ nfs4_state_init(void)
INIT_LIST_HEAD(&close_lru);
INIT_LIST_HEAD(&client_lru);
init_MUTEX(&client_sema);
- boot_time = get_seconds();
+ boot_time = start;
+ grace_end = start + NFSD_LEASE_TIME;
INIT_WORK(&laundromat_work,laundromat_main, NULL);
schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ);
nfs4_init = 1;
}
+int
+nfs4_in_grace(void)
+{
+ return time_before(get_seconds(), (unsigned long)grace_end);
+}
+
+int
+nfs4_in_no_grace(void)
+{
+ return (grace_end < get_seconds());
+}
+
+
static void
__nfs4_state_shutdown(void)
{
diff ./include/linux/nfsd/nfsd.h~current~ ./include/linux/nfsd/nfsd.h
--- ./include/linux/nfsd/nfsd.h~current~ 2004-04-08 10:50:13.000000000 +1000
+++ ./include/linux/nfsd/nfsd.h 2004-04-08 10:57:18.000000000 +1000
@@ -197,6 +197,9 @@ void nfsd_lockd_shutdown(void);
#define nfserr_locks_held __constant_htonl(NFSERR_LOCKS_HELD)
#define nfserr_op_illegal __constant_htonl(NFSERR_OP_ILLEGAL)
#define nfserr_badname __constant_htonl(NFSERR_BADNAME)
+#define nfserr_grace __constant_htonl(NFSERR_GRACE)
+#define nfserr_no_grace __constant_htonl(NFSERR_NO_GRACE)
+#define nfserr_reclaim_bad __constant_htonl(NFSERR_RECLAIM_BAD)
/* error codes for internal use */
/* if a request fails due to kmalloc failure, it gets dropped.
diff ./include/linux/nfsd/state.h~current~ ./include/linux/nfsd/state.h
--- ./include/linux/nfsd/state.h~current~ 2004-04-08 10:56:23.000000000 +1000
+++ ./include/linux/nfsd/state.h 2004-04-08 10:57:18.000000000 +1000
@@ -215,4 +215,6 @@ extern int nfs4_share_conflict(struct sv
unsigned int deny_type);
extern void nfs4_lock_state(void);
extern void nfs4_unlock_state(void);
+extern int nfs4_in_grace(void);
+extern int nfs4_in_no_grace(void);
#endif /* NFSD4_STATE_H */
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH] kNFSdv4 - 1 of 10 - idmap bugfixes and cleanup
2004-04-08 1:18 [PATCH] kNFSdv4 - 0 of 10 - Introduction NeilBrown
` (7 preceding siblings ...)
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 10 of 10 - Implement server-side reboot recovery (mostly) NeilBrown
@ 2004-04-08 1:18 ` NeilBrown
[not found] ` <20040407233608.6414089a.akpm@osdl.org>
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 4 of 10 - nfsd4_readdir fixes NeilBrown
9 siblings, 1 reply; 16+ messages in thread
From: NeilBrown @ 2004-04-08 1:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: nfs, J. Bruce Fields
From: "J. Bruce Fields" <bfields@fieldses.org>
Fix race conditions and leaks on error; split up code a bit to make it
easier to verify correctness.
----------- Diffstat output ------------
./fs/nfsd/nfs4idmap.c | 100 ++++++++++++++++++++++++++++++++------------------
1 files changed, 65 insertions(+), 35 deletions(-)
diff ./fs/nfsd/nfs4idmap.c~current~ ./fs/nfsd/nfs4idmap.c
--- ./fs/nfsd/nfs4idmap.c~current~ 2004-04-06 10:57:05.000000000 +1000
+++ ./fs/nfsd/nfs4idmap.c 2004-04-08 10:50:09.000000000 +1000
@@ -412,8 +412,12 @@ struct idmap_defer_req {
static void
put_mdr(struct idmap_defer_req *mdr)
{
+ wait_queue_head_t *waitq = &mdr->waitq;
+
if (atomic_dec_and_test(&mdr->count))
kfree(mdr);
+ else
+ wake_up(waitq);
}
static void
@@ -422,7 +426,6 @@ idmap_revisit(struct cache_deferred_req
struct idmap_defer_req *mdr =
container_of(dreq, struct idmap_defer_req, deferred_req);
- wake_up(&mdr->waitq);
put_mdr(mdr);
}
@@ -438,65 +441,92 @@ idmap_defer(struct cache_req *req)
static int threads_waiting = 0;
-static inline int
-idmap_lookup_wait(struct idmap_defer_req *mdr, wait_queue_t waitq, struct
- svc_rqst *rqstp) {
- int ret = -ETIMEDOUT;
+static inline void
+idmap_wait(struct idmap_defer_req *mdr, struct svc_rqst *rqstp) {
- set_task_state(current, TASK_INTERRUPTIBLE);
+ /* Note: BKL prevents races with nfsd_svc and other lookups */
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);
+}
+
+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
+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;
}
+static inline void
+init_mdr(struct idmap_defer_req *mdr, wait_queue_t *waitq)
+{
+
+ memset(mdr, 0, sizeof(*mdr));
+ init_waitqueue_head(&mdr->waitq);
+ add_wait_queue(&mdr->waitq, waitq);
+ atomic_set(&mdr->count, 2);
+ mdr->req.defer = idmap_defer;
+}
+
static int
idmap_lookup(struct svc_rqst *rqstp,
struct ent *(*lookup_fn)(struct ent *, int), struct ent *key,
struct cache_detail *detail, struct ent **item)
{
- struct idmap_defer_req *mdr;
DECLARE_WAITQUEUE(waitq, current);
+ struct idmap_defer_req *mdr;
int ret;
- *item = lookup_fn(key, 0);
- if (!*item)
- return -ENOMEM;
mdr = kmalloc(sizeof(*mdr), GFP_KERNEL);
- memset(mdr, 0, sizeof(*mdr));
- 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);
+ if (!mdr)
+ return -ENOMEM;
+ init_mdr(mdr, &waitq);
+ set_task_state(current, TASK_INTERRUPTIBLE);
+ 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);
+ idmap_wait(mdr, rqstp);
+ ret = do_idmap_lookup_nowait(lookup_fn, key, detail, item);
+ } else {
+ put_mdr(mdr);
+ put_mdr(mdr);
}
-out:
return ret;
}
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH] kNFSdv4 - 3 of 10 - complain if idmapd doesn't have channel open
2004-04-08 1:18 [PATCH] kNFSdv4 - 0 of 10 - Introduction NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 9 of 10 - Set credentials properly when puutrootfh is used NeilBrown
@ 2004-04-08 1:18 ` NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 7 of 10 - Allow locku replays aswell NeilBrown
` (7 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: NeilBrown @ 2004-04-08 1:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: nfs, J. Bruce Fields
From: "J. Bruce Fields" <bfields@fieldses.org>
Currently if a user mounts a server that doesn't have idmapd running, the
mount may block for 10 seconds to a minute, and there's no useful errors on
the client or server side.
Help out by:
1) Failing lookups immediately whenever no process has opened the
files in idmapd that are used to do idmapping upcalls.
2) Doing a printk() in this situation so they know idmapd needs to
be run.
----------- Diffstat output ------------
./fs/nfsd/nfs4idmap.c | 15 +++++++++++++++
1 files changed, 15 insertions(+)
diff ./fs/nfsd/nfs4idmap.c~current~ ./fs/nfsd/nfs4idmap.c
--- ./fs/nfsd/nfs4idmap.c~current~ 2004-04-08 10:50:13.000000000 +1000
+++ ./fs/nfsd/nfs4idmap.c 2004-04-08 10:50:15.000000000 +1000
@@ -505,6 +505,17 @@ init_mdr(struct idmap_defer_req *mdr, wa
mdr->req.defer = idmap_defer;
}
+static inline void
+warn_no_idmapd(void) {
+ static time_t last_warning = 0;
+
+ if (last_warning < get_seconds() - 60) {
+ last_warning = get_seconds();
+ printk(KERN_WARNING "nfsd: idmap failing; check if idmapd"
+ " is running?\n");
+ }
+}
+
static int
idmap_lookup(struct svc_rqst *rqstp,
struct ent *(*lookup_fn)(struct ent *, int), struct ent *key,
@@ -514,6 +525,10 @@ idmap_lookup(struct svc_rqst *rqstp,
struct idmap_defer_req *mdr;
int ret;
+ if (atomic_read(&detail->readers) == 0) {
+ warn_no_idmapd();
+ return -ENOENT;
+ }
mdr = kmalloc(sizeof(*mdr), GFP_KERNEL);
if (!mdr)
return -ENOMEM;
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH] kNFSdv4 - 8 of 10 - Improve how locking copes with replays
2004-04-08 1:18 [PATCH] kNFSdv4 - 0 of 10 - Introduction NeilBrown
` (2 preceding siblings ...)
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 7 of 10 - Allow locku replays aswell NeilBrown
@ 2004-04-08 1:18 ` NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 6 of 10 - Keep state to allow replays for 'close' to work NeilBrown
` (5 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: NeilBrown @ 2004-04-08 1:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: nfs, J. Bruce Fields
From: "J. Bruce Fields" <bfields@fieldses.org>
>From Andros: Hold state_lock longer so the stateowner doesn't diseappear out
from under us before we get the chance to encode the replay. Don't attempt to
save replay if we failed to find a stateowner.
----------- Diffstat output ------------
./fs/nfsd/nfs4proc.c | 35 +++++++++++++++++++++++++++--------
./fs/nfsd/nfs4state.c | 35 ++++++++++++++++++++++++-----------
./fs/nfsd/nfs4xdr.c | 33 +++++++++++++++++++++------------
3 files changed, 72 insertions(+), 31 deletions(-)
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
--- ./fs/nfsd/nfs4proc.c~current~ 2004-04-08 10:56:52.000000000 +1000
+++ ./fs/nfsd/nfs4proc.c 2004-04-08 10:57:00.000000000 +1000
@@ -113,17 +113,24 @@ do_open_lookup(struct svc_rqst *rqstp, s
return status;
}
+/*
+ * nfs4_unlock_state() called in encode
+ */
static inline int
nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
{
int status;
- dprintk("NFSD: nfsd4_open filename %.*s\n",
- (int)open->op_fname.len, open->op_fname.data);
+ dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
+ (int)open->op_fname.len, open->op_fname.data,
+ open->op_stateowner);
/* This check required by spec. */
if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
return nfserr_inval;
+ open->op_stateowner = NULL;
+ nfs4_lock_state();
+
/* check seqid for replay. set nfs4_owner */
status = nfsd4_process_open1(open);
if (status == NFSERR_REPLAY_ME) {
@@ -763,7 +770,9 @@ nfsd4_proc_compound(struct svc_rqst *rqs
break;
case OP_CLOSE:
op->status = nfsd4_close(rqstp, ¤t_fh, &op->u.close);
- op->replay = &op->u.close.cl_stateowner->so_replay;
+ if (op->u.close.cl_stateowner)
+ op->replay =
+ &op->u.close.cl_stateowner->so_replay;
break;
case OP_COMMIT:
op->status = nfsd4_commit(rqstp, ¤t_fh, &op->u.commit);
@@ -782,14 +791,18 @@ nfsd4_proc_compound(struct svc_rqst *rqs
break;
case OP_LOCK:
op->status = nfsd4_lock(rqstp, ¤t_fh, &op->u.lock);
- op->replay = &op->u.lock.lk_stateowner->so_replay;
+ if (op->u.lock.lk_stateowner)
+ op->replay =
+ &op->u.lock.lk_stateowner->so_replay;
break;
case OP_LOCKT:
op->status = nfsd4_lockt(rqstp, ¤t_fh, &op->u.lockt);
break;
case OP_LOCKU:
op->status = nfsd4_locku(rqstp, ¤t_fh, &op->u.locku);
- op->replay = &op->u.locku.lu_stateowner->so_replay;
+ if (op->u.locku.lu_stateowner)
+ op->replay =
+ &op->u.locku.lu_stateowner->so_replay;
break;
case OP_LOOKUP:
op->status = nfsd4_lookup(rqstp, ¤t_fh, &op->u.lookup);
@@ -804,15 +817,21 @@ nfsd4_proc_compound(struct svc_rqst *rqs
break;
case OP_OPEN:
op->status = nfsd4_open(rqstp, ¤t_fh, &op->u.open);
- op->replay = &op->u.open.op_stateowner->so_replay;
+ if (op->u.open.op_stateowner)
+ op->replay =
+ &op->u.open.op_stateowner->so_replay;
break;
case OP_OPEN_CONFIRM:
op->status = nfsd4_open_confirm(rqstp, ¤t_fh, &op->u.open_confirm);
- op->replay = &op->u.open_confirm.oc_stateowner->so_replay;
+ if (op->u.open_confirm.oc_stateowner)
+ op->replay =
+ &op->u.open_confirm.oc_stateowner->so_replay;
break;
case OP_OPEN_DOWNGRADE:
op->status = nfsd4_open_downgrade(rqstp, ¤t_fh, &op->u.open_downgrade);
- op->replay = &op->u.open_downgrade.od_stateowner->so_replay;
+ if (op->u.open_downgrade.od_stateowner)
+ op->replay =
+ &op->u.open_downgrade.od_stateowner->so_replay;
break;
case OP_PUTFH:
op->status = nfsd4_putfh(rqstp, ¤t_fh, &op->u.putfh);
diff ./fs/nfsd/nfs4state.c~current~ ./fs/nfsd/nfs4state.c
--- ./fs/nfsd/nfs4state.c~current~ 2004-04-08 10:56:23.000000000 +1000
+++ ./fs/nfsd/nfs4state.c 2004-04-08 10:57:00.000000000 +1000
@@ -89,6 +89,9 @@ nfs4_lock_state(void)
down(&client_sema);
}
+/*
+ * nfs4_unlock_state(); called in encode
+ */
void
nfs4_unlock_state(void)
{
@@ -1083,6 +1086,8 @@ nfs4_file_downgrade(struct file *filp, u
* notfound:
* verify clientid
* create new owner
+ *
+ * called with nfs4_lock_state() held.
*/
int
nfsd4_process_open1(struct nfsd4_open *open)
@@ -1101,7 +1106,6 @@ nfsd4_process_open1(struct nfsd4_open *o
if (STALE_CLIENTID(&open->op_clientid))
goto out;
- nfs4_lock_state();
strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
if (find_openstateowner_str(strhashval, open, &sop)) {
open->op_stateowner = sop;
@@ -1159,10 +1163,11 @@ instantiate_new_owner:
renew:
renew_client(sop->so_client);
out:
- nfs4_unlock_state();
return status;
}
-
+/*
+ * called with nfs4_lock_state() held.
+ */
int
nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
{
@@ -1185,7 +1190,6 @@ nfsd4_process_open2(struct svc_rqst *rqs
if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
goto out;
- nfs4_lock_state();
fi_hashval = file_hashval(ino);
if (find_file(fi_hashval, ino, &fp)) {
/* Search for conflicting share reservations */
@@ -1277,7 +1281,6 @@ out:
if (!open->op_stateowner->so_confirmed)
open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM;
- nfs4_unlock_state();
return status;
out_free:
kfree(stp);
@@ -1598,11 +1601,15 @@ check_replay:
} else {
printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d\n", sop->so_seqid +1, seqid);
+ *sopp = NULL;
status = nfserr_bad_seqid;
}
goto out;
}
+/*
+ * nfs4_unlock_state(); called in encode
+ */
int
nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc)
{
@@ -1638,7 +1645,6 @@ nfsd4_open_confirm(struct svc_rqst *rqst
stp->st_stateid.si_generation);
status = nfs_ok;
out:
- nfs4_unlock_state();
return status;
}
@@ -1667,6 +1673,9 @@ reset_union_bmap_deny(unsigned long deny
}
}
+/*
+ * nfs4_unlock_state(); called in encode
+ */
int
nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od)
@@ -1679,6 +1688,7 @@ nfsd4_open_downgrade(struct svc_rqst *rq
(int)current_fh->fh_dentry->d_name.len,
current_fh->fh_dentry->d_name.name);
+ od->od_stateowner = NULL;
status = nfserr_inval;
if (!TEST_ACCESS(od->od_share_access) || !TEST_DENY(od->od_share_deny))
goto out;
@@ -1712,10 +1722,12 @@ nfsd4_open_downgrade(struct svc_rqst *rq
memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t));
status = nfs_ok;
out:
- nfs4_unlock_state();
return status;
}
+/*
+ * nfs4_unlock_state() called after encode
+ */
int
nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close)
{
@@ -1726,6 +1738,7 @@ nfsd4_close(struct svc_rqst *rqstp, stru
(int)current_fh->fh_dentry->d_name.len,
current_fh->fh_dentry->d_name.name);
+ close->cl_stateowner = NULL;
nfs4_lock_state();
/* check close_lru for replay */
if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid,
@@ -1743,7 +1756,6 @@ nfsd4_close(struct svc_rqst *rqstp, stru
/* release_state_owner() calls nfsd_close() if needed */
release_state_owner(stp, &close->cl_stateowner, OPEN_STATE);
out:
- nfs4_unlock_state();
return status;
}
@@ -1953,6 +1965,8 @@ check_lock_length(u64 offset, u64 length
/*
* LOCK operation
+ *
+ * nfs4_unlock_state(); called in encode
*/
int
nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock)
@@ -2117,7 +2131,6 @@ out_destroy_new_stateid:
release_state_owner(lock_stp, &lock->lk_stateowner, LOCK_STATE);
}
out:
- nfs4_unlock_state();
return status;
}
@@ -2212,7 +2225,7 @@ out:
nfs4_unlock_state();
return status;
}
-
+
int
nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku)
{
@@ -2228,6 +2241,7 @@ nfsd4_locku(struct svc_rqst *rqstp, stru
if (check_lock_length(locku->lu_offset, locku->lu_length))
return nfserr_inval;
+ locku->lu_stateowner = NULL;
nfs4_lock_state();
if ((status = nfs4_preprocess_seqid_op(current_fh,
@@ -2270,7 +2284,6 @@ nfsd4_locku(struct svc_rqst *rqstp, stru
memcpy(&locku->lu_stateid, &stp->st_stateid, sizeof(stateid_t));
out:
- nfs4_unlock_state();
return status;
out_nfserr:
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
--- ./fs/nfsd/nfs4xdr.c~current~ 2004-04-08 10:56:00.000000000 +1000
+++ ./fs/nfsd/nfs4xdr.c 2004-04-08 10:57:00.000000000 +1000
@@ -484,11 +484,14 @@ nfsd4_decode_access(struct nfsd4_compoun
DECODE_TAIL;
}
+#define NFS4_STATE_NOT_LOCKED ((void *)-1)
+
static int
nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
{
DECODE_HEAD;
+ close->cl_stateowner = NFS4_STATE_NOT_LOCKED;
READ_BUF(4 + sizeof(stateid_t));
READ32(close->cl_seqid);
READ32(close->cl_stateid.si_generation);
@@ -579,6 +582,7 @@ nfsd4_decode_lock(struct nfsd4_compounda
{
DECODE_HEAD;
+ lock->lk_stateowner = NFS4_STATE_NOT_LOCKED;
/*
* type, reclaim(boolean), offset, length, new_lock_owner(boolean)
*/
@@ -636,6 +640,7 @@ nfsd4_decode_locku(struct nfsd4_compound
{
DECODE_HEAD;
+ locku->lu_stateowner = NFS4_STATE_NOT_LOCKED;
READ_BUF(24 + sizeof(stateid_t));
READ32(locku->lu_type);
if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
@@ -671,6 +676,7 @@ nfsd4_decode_open(struct nfsd4_compounda
memset(open->op_bmval, 0, sizeof(open->op_bmval));
open->op_iattr.ia_valid = 0;
+ open->op_stateowner = NFS4_STATE_NOT_LOCKED;
/* seqid, share_access, share_deny, clientid, ownerlen */
READ_BUF(16 + sizeof(clientid_t));
@@ -746,6 +752,7 @@ nfsd4_decode_open_confirm(struct nfsd4_c
{
DECODE_HEAD;
+ open_conf->oc_stateowner = NFS4_STATE_NOT_LOCKED;
READ_BUF(4 + sizeof(stateid_t));
READ32(open_conf->oc_req_stateid.si_generation);
COPYMEM(&open_conf->oc_req_stateid.si_opaque, sizeof(stateid_opaque_t));
@@ -759,6 +766,7 @@ nfsd4_decode_open_downgrade(struct nfsd4
{
DECODE_HEAD;
+ open_down->od_stateowner = NFS4_STATE_NOT_LOCKED;
READ_BUF(4 + sizeof(stateid_t));
READ32(open_down->od_stateid.si_generation);
COPYMEM(&open_down->od_stateid.si_opaque, sizeof(stateid_opaque_t));
@@ -1259,7 +1267,8 @@ nfsd4_decode_compound(struct nfsd4_compo
*/
#define ENCODE_SEQID_OP_TAIL(stateowner) do { \
- if (seqid_mutating_err(nfserr) && stateowner) { \
+ if (seqid_mutating_err(nfserr) && stateowner \
+ && (stateowner != NFS4_STATE_NOT_LOCKED)) { \
if (stateowner->so_confirmed) \
stateowner->so_seqid++; \
stateowner->so_replay.rp_status = nfserr; \
@@ -1267,7 +1276,10 @@ nfsd4_decode_compound(struct nfsd4_compo
(((char *)(resp)->p - (char *)save)); \
memcpy(stateowner->so_replay.rp_buf, save, \
stateowner->so_replay.rp_buflen); \
- } } while(0)
+ } \
+ if (stateowner != NFS4_STATE_NOT_LOCKED) \
+ nfs4_unlock_state(); \
+ } while (0);
static u32 nfs4_ftypes[16] = {
@@ -1917,7 +1929,7 @@ nfsd4_encode_open(struct nfsd4_compoundr
ENCODE_SEQID_OP_HEAD;
if (nfserr)
- return;
+ goto out;
RESERVE_SPACE(36 + sizeof(stateid_t));
WRITE32(open->op_stateid.si_generation);
@@ -1972,7 +1984,7 @@ nfsd4_encode_open(struct nfsd4_compoundr
BUG();
}
/* XXX save filehandle here */
-
+out:
ENCODE_SEQID_OP_TAIL(open->op_stateowner);
}
@@ -2297,14 +2309,8 @@ nfsd4_encode_operation(struct nfsd4_comp
RESERVE_SPACE(8);
WRITE32(op->opnum);
- if ((op->opnum != OP_SETATTR) && (op->opnum != OP_LOCK) && (op->opnum != OP_LOCKT) && (op->opnum != OP_SETCLIENTID) && (op->status)) {
- *p++ = op->status;
- ADJUST_ARGS();
- return;
- } else {
- statp = p++; /* to be backfilled at the end */
- ADJUST_ARGS();
- }
+ statp = p++; /* to be backfilled at the end */
+ ADJUST_ARGS();
switch (op->opnum) {
case OP_ACCESS:
@@ -2408,6 +2414,8 @@ nfsd4_encode_operation(struct nfsd4_comp
*
* XDR note: do not encode rp->rp_buflen: the buffer contains the
* previously sent already encoded operation.
+ *
+ * called with nfs4_lock_state() held
*/
void
nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
@@ -2425,6 +2433,7 @@ nfsd4_encode_replay(struct nfsd4_compoun
RESERVE_SPACE(rp->rp_buflen);
WRITEMEM(rp->rp_buf, rp->rp_buflen);
ADJUST_ARGS();
+ nfs4_unlock_state();
}
/*
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH] kNFSdv4 - 4 of 10 - nfsd4_readdir fixes
2004-04-08 1:18 [PATCH] kNFSdv4 - 0 of 10 - Introduction NeilBrown
` (8 preceding siblings ...)
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 1 of 10 - idmap bugfixes and cleanup NeilBrown
@ 2004-04-08 1:18 ` NeilBrown
9 siblings, 0 replies; 16+ messages in thread
From: NeilBrown @ 2004-04-08 1:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: nfs, J. Bruce Fields
From: "J. Bruce Fields" <bfields@fieldses.org>
Fix out-of-spec errors in nfs4 readdir. Add checks for bad cookie values.
----------- Diffstat output ------------
./fs/nfsd/nfs4proc.c | 8 +++++++-
./fs/nfsd/nfs4xdr.c | 2 ++
2 files changed, 9 insertions(+), 1 deletion(-)
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
--- ./fs/nfsd/nfs4proc.c~current~ 2004-04-08 10:56:00.000000000 +1000
+++ ./fs/nfsd/nfs4proc.c 2004-04-08 10:56:00.000000000 +1000
@@ -448,6 +448,11 @@ out:
static inline int
nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir)
{
+ u64 cookie = readdir->rd_cookie;
+ static const nfs4_verifier zeroverf = {
+ .data[0] = 0,
+ };
+
/* no need to check permission - this will be done in nfsd_readdir() */
if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
@@ -456,7 +461,8 @@ nfsd4_readdir(struct svc_rqst *rqstp, st
readdir->rd_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
readdir->rd_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
- if (readdir->rd_cookie > ~(u32)0)
+ if ((cookie > ~(u32)0) || (cookie == 1) || (cookie == 2) ||
+ (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE)))
return nfserr_bad_cookie;
readdir->rd_rqstp = rqstp;
diff ./fs/nfsd/nfs4xdr.c~current~ ./fs/nfsd/nfs4xdr.c
--- ./fs/nfsd/nfs4xdr.c~current~ 2004-04-08 10:56:00.000000000 +1000
+++ ./fs/nfsd/nfs4xdr.c 2004-04-08 10:56:00.000000000 +1000
@@ -2179,6 +2179,8 @@ nfsd4_encode_readdir(struct nfsd4_compou
readdir->common.err == nfserr_toosmall &&
readdir->buffer == page)
nfserr = nfserr_toosmall;
+ if (nfserr == nfserr_symlink)
+ nfserr = nfserr_notdir;
if (nfserr)
goto err_no_verf;
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH] kNFSdv4 - 5 of 10 - Fix bad error returm from svcauth_gss_accept
2004-04-08 1:18 [PATCH] kNFSdv4 - 0 of 10 - Introduction NeilBrown
` (5 preceding siblings ...)
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 2 of 10 - better handling of failed idmap lookups NeilBrown
@ 2004-04-08 1:18 ` NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 10 of 10 - Implement server-side reboot recovery (mostly) NeilBrown
` (2 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: NeilBrown @ 2004-04-08 1:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: nfs, J. Bruce Fields
From: "J. Bruce Fields" <bfields@fieldses.org>
Error return when the client supplies a bad service should be badcred.
----------- Diffstat output ------------
./net/sunrpc/auth_gss/svcauth_gss.c | 1 +
1 files changed, 1 insertion(+)
diff ./net/sunrpc/auth_gss/svcauth_gss.c~current~ ./net/sunrpc/auth_gss/svcauth_gss.c
--- ./net/sunrpc/auth_gss/svcauth_gss.c~current~ 2004-04-08 10:56:10.000000000 +1000
+++ ./net/sunrpc/auth_gss/svcauth_gss.c 2004-04-08 10:56:10.000000000 +1000
@@ -895,6 +895,7 @@ svcauth_gss_accept(struct svc_rqst *rqst
svc_putu32(resv, rpc_success);
goto complete;
case RPC_GSS_PROC_DATA:
+ *authp = rpc_autherr_badcred;
rqstp->rq_client =
find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
if (rqstp->rq_client == NULL)
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH] kNFSdv4 - 9 of 10 - Set credentials properly when puutrootfh is used
2004-04-08 1:18 [PATCH] kNFSdv4 - 0 of 10 - Introduction NeilBrown
@ 2004-04-08 1:18 ` NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 3 of 10 - complain if idmapd doesn't have channel open NeilBrown
` (8 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: NeilBrown @ 2004-04-08 1:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: nfs, J. Bruce Fields
The credentials (uid/gid) of a process are set when a filehandle
is verified. Nfsv4 allows requests without an explicit filehandle
(instead, an implicit 'root' filehandle) so we much make sure the
credentials are set for these requests too.
From: "J. Bruce Fields" <bfields@fieldses.org>
>From Andros: added a call to nfsd_setuser in nfsd4_putrootfh so that nfsd runs
as the rpc->cred user.
----------- Diffstat output ------------
./fs/nfsd/nfs4proc.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletion(-)
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
--- ./fs/nfsd/nfs4proc.c~current~ 2004-04-08 10:57:00.000000000 +1000
+++ ./fs/nfsd/nfs4proc.c 2004-04-08 10:57:10.000000000 +1000
@@ -194,9 +194,14 @@ nfsd4_putfh(struct svc_rqst *rqstp, stru
static inline int
nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh)
{
+ int status;
+
fh_put(current_fh);
- return exp_pseudoroot(rqstp->rq_client, current_fh,
+ status = exp_pseudoroot(rqstp->rq_client, current_fh,
&rqstp->rq_chandle);
+ if (!status)
+ status = nfsd_setuser(rqstp, current_fh->fh_export);
+ return status;
}
static inline int
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH] kNFSdv4 - 6 of 10 - Keep state to allow replays for 'close' to work.
2004-04-08 1:18 [PATCH] kNFSdv4 - 0 of 10 - Introduction NeilBrown
` (3 preceding siblings ...)
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 8 of 10 - Improve how locking copes with replays NeilBrown
@ 2004-04-08 1:18 ` NeilBrown
[not found] ` <20040407234541.7f2bb6d3.akpm@osdl.org>
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 2 of 10 - better handling of failed idmap lookups NeilBrown
` (4 subsequent siblings)
9 siblings, 1 reply; 16+ messages in thread
From: NeilBrown @ 2004-04-08 1:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: nfs, J. Bruce Fields
From: "J. Bruce Fields" <bfields@fieldses.org>
>From Andros: Idea is to keep around a list of openowners recently released by
closes, and make sure they stay around long enough so that replays still work.
----------- Diffstat output ------------
./fs/nfsd/nfs4state.c | 85 +++++++++++++++++++++++++++++++------------
./include/linux/nfsd/state.h | 6 +++
2 files changed, 69 insertions(+), 22 deletions(-)
diff ./fs/nfsd/nfs4state.c~current~ ./fs/nfsd/nfs4state.c
--- ./fs/nfsd/nfs4state.c~current~ 2004-04-08 10:56:23.000000000 +1000
+++ ./fs/nfsd/nfs4state.c 2004-04-08 10:56:23.000000000 +1000
@@ -136,12 +136,16 @@ static void release_file(struct nfs4_fil
*
* client_lru holds client queue ordered by nfs4_client.cl_time
* for lease renewal.
+ *
+ * close_lru holds (open) stateowner queue ordered by nfs4_stateowner.so_time
+ * for last close replay.
*/
static struct list_head conf_id_hashtbl[CLIENT_HASH_SIZE];
static struct list_head conf_str_hashtbl[CLIENT_HASH_SIZE];
static struct list_head unconf_str_hashtbl[CLIENT_HASH_SIZE];
static struct list_head unconf_id_hashtbl[CLIENT_HASH_SIZE];
static struct list_head client_lru;
+static struct list_head close_lru;
static inline void
renew_client(struct nfs4_client *clp)
@@ -774,6 +778,8 @@ alloc_init_open_stateowner(unsigned int
INIT_LIST_HEAD(&sop->so_perclient);
INIT_LIST_HEAD(&sop->so_perfilestate);
INIT_LIST_HEAD(&sop->so_perlockowner); /* not used */
+ INIT_LIST_HEAD(&sop->so_close_lru);
+ sop->so_time = 0;
list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
list_add(&sop->so_perclient, &clp->cl_perclient);
@@ -814,6 +820,7 @@ release_stateowner(struct nfs4_stateowne
list_del(&sop->so_strhash);
list_del(&sop->so_perclient);
list_del(&sop->so_perlockowner);
+ list_del(&sop->so_close_lru);
del_perclient++;
while (!list_empty(&sop->so_perfilestate)) {
stp = list_entry(sop->so_perfilestate.next,
@@ -882,6 +889,19 @@ release_file(struct nfs4_file *fp)
}
void
+move_to_close_lru(struct nfs4_stateowner *sop)
+{
+ dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
+ /* remove stateowner from all other hash lists except perclient */
+ list_del_init(&sop->so_idhash);
+ list_del_init(&sop->so_strhash);
+ list_del_init(&sop->so_perlockowner);
+
+ list_add_tail(&sop->so_close_lru, &close_lru);
+ sop->so_time = get_seconds();
+}
+
+void
release_state_owner(struct nfs4_stateid *stp, struct nfs4_stateowner **sopp,
int flag)
{
@@ -890,16 +910,13 @@ release_state_owner(struct nfs4_stateid
dprintk("NFSD: release_state_owner\n");
release_stateid(stp, flag);
- /*
- * release unused nfs4_stateowners.
- * XXX will need to be placed on an open_stateid_lru list to be
+
+ /* place unused nfs4_stateowners on so_close_lru list to be
* released by the laundromat service after the lease period
* to enable us to handle CLOSE replay
*/
- if (sop->so_confirmed && list_empty(&sop->so_perfilestate)) {
- release_stateowner(sop);
- *sopp = NULL;
- }
+ if (sop->so_confirmed && list_empty(&sop->so_perfilestate))
+ move_to_close_lru(sop);
/* unused nfs4_file's are releseed. XXX slab cache? */
if (list_empty(&fp->fi_perfile)) {
release_file(fp);
@@ -1316,9 +1333,11 @@ time_t
nfs4_laundromat(void)
{
struct nfs4_client *clp;
+ struct nfs4_stateowner *sop;
struct list_head *pos, *next;
time_t cutoff = get_seconds() - NFSD_LEASE_TIME;
- time_t t, return_val = NFSD_LEASE_TIME;
+ time_t t, clientid_val = NFSD_LEASE_TIME;
+ time_t u, close_val = NFSD_LEASE_TIME;
nfs4_lock_state();
@@ -1327,18 +1346,30 @@ nfs4_laundromat(void)
clp = list_entry(pos, struct nfs4_client, cl_lru);
if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
t = clp->cl_time - cutoff;
- if (return_val > t)
- return_val = t;
+ if (clientid_val > t)
+ clientid_val = t;
break;
}
dprintk("NFSD: purging unused client (clientid %08x)\n",
clp->cl_clientid.cl_id);
expire_client(clp);
}
- if (return_val < NFSD_LAUNDROMAT_MINTIMEOUT)
- return_val = NFSD_LAUNDROMAT_MINTIMEOUT;
+ list_for_each_safe(pos, next, &close_lru) {
+ sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
+ if (time_after((unsigned long)sop->so_time, (unsigned long)cutoff)) {
+ u = sop->so_time - cutoff;
+ if (close_val > u)
+ close_val = u;
+ break;
+ }
+ dprintk("NFSD: purging unused open stateowner (so_id %d)\n",
+ sop->so_id);
+ release_stateowner(sop);
+ }
+ if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT)
+ clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT;
nfs4_unlock_state();
- return return_val;
+ return clientid_val;
}
void
@@ -1351,17 +1382,22 @@ laundromat_main(void *not_used)
schedule_delayed_work(&laundromat_work, t*HZ);
}
-/* search ownerid_hashtbl[] for stateid owner (stateid->si_stateownerid) */
+/* search ownerid_hashtbl[] and close_lru for stateid owner
+ * (stateid->si_stateownerid)
+ */
struct nfs4_stateowner *
-find_openstateowner_id(u32 st_id) {
+find_openstateowner_id(u32 st_id, int flags) {
struct list_head *pos, *next;
struct nfs4_stateowner *local = NULL;
- unsigned int hashval = ownerid_hashval(st_id);
- list_for_each_safe(pos, next, &ownerid_hashtbl[hashval]) {
- local = list_entry(pos, struct nfs4_stateowner, so_idhash);
- if(local->so_id == st_id)
- return local;
+ dprintk("NFSD: find_openstateowner_id %d\n", st_id);
+ if (flags & CLOSE_STATE) {
+ list_for_each_safe(pos, next, &close_lru) {
+ local = list_entry(pos, struct nfs4_stateowner,
+ so_close_lru);
+ if(local->so_id == st_id)
+ return local;
+ }
}
return NULL;
}
@@ -1547,11 +1583,12 @@ no_nfs4_stateid:
* starting by trying to look up the stateowner.
* If stateowner is not found - stateid is bad.
*/
- if (!(sop = find_openstateowner_id(stateid->si_stateownerid))) {
+ if (!(sop = find_openstateowner_id(stateid->si_stateownerid, flags))) {
printk("NFSD: preprocess_seqid_op: no stateowner or nfs4_stateid!\n");
status = nfserr_bad_stateid;
goto out;
}
+ *sopp = sop;
check_replay:
if (seqid == sop->so_seqid) {
@@ -1690,9 +1727,10 @@ nfsd4_close(struct svc_rqst *rqstp, stru
current_fh->fh_dentry->d_name.name);
nfs4_lock_state();
+ /* check close_lru for replay */
if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid,
&close->cl_stateid,
- CHECK_FH | OPEN_STATE,
+ CHECK_FH | OPEN_STATE | CLOSE_STATE,
&close->cl_stateowner, &stp, NULL)))
goto out;
/*
@@ -1854,6 +1892,8 @@ alloc_init_lock_stateowner(unsigned int
INIT_LIST_HEAD(&sop->so_perclient);
INIT_LIST_HEAD(&sop->so_perfilestate);
INIT_LIST_HEAD(&sop->so_perlockowner);
+ INIT_LIST_HEAD(&sop->so_close_lru); /* not used */
+ sop->so_time = 0;
list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
list_add(&sop->so_perclient, &clp->cl_perclient);
@@ -2351,6 +2391,7 @@ nfs4_state_init(void)
memset(&zerostateid, 0, sizeof(stateid_t));
memset(&onestateid, ~0, sizeof(stateid_t));
+ INIT_LIST_HEAD(&close_lru);
INIT_LIST_HEAD(&client_lru);
init_MUTEX(&client_sema);
boot_time = get_seconds();
diff ./include/linux/nfsd/state.h~current~ ./include/linux/nfsd/state.h
--- ./include/linux/nfsd/state.h~current~ 2004-04-08 10:56:23.000000000 +1000
+++ ./include/linux/nfsd/state.h 2004-04-08 10:56:23.000000000 +1000
@@ -132,6 +132,9 @@ struct nfs4_replay {
* release a stateowner.
* so_perlockowner: (open) nfs4_stateid->st_perlockowner entry - used when
* close is called to reap associated byte-range locks
+* so_close_lru: (open) stateowner is placed on this list instead of being
+* reaped (when so_perfilestate is empty) to hold the last close replay.
+* reaped by laundramat thread after lease period.
*/
struct nfs4_stateowner {
struct list_head so_idhash; /* hash by so_id */
@@ -139,6 +142,8 @@ struct nfs4_stateowner {
struct list_head so_perclient; /* nfs4_client->cl_perclient */
struct list_head so_perfilestate; /* list: nfs4_stateid */
struct list_head so_perlockowner; /* nfs4_stateid->st_perlockowner */
+ struct list_head so_close_lru; /* tail queue */
+ time_t so_time; /* time of placement on so_close_lru */
int so_is_open_owner; /* 1=openowner,0=lockowner */
u32 so_id;
struct nfs4_client * so_client;
@@ -194,6 +199,7 @@ struct nfs4_stateid {
#define OPEN_STATE 0x00000004
#define LOCK_STATE 0x00000008
#define RDWR_STATE 0x00000010
+#define CLOSE_STATE 0x00000020
#define seqid_mutating_err(err) \
(((err) != nfserr_stale_clientid) && \
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH] kNFSdv4 - 7 of 10 - Allow locku replays aswell
2004-04-08 1:18 [PATCH] kNFSdv4 - 0 of 10 - Introduction NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 9 of 10 - Set credentials properly when puutrootfh is used NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 3 of 10 - complain if idmapd doesn't have channel open NeilBrown
@ 2004-04-08 1:18 ` NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 8 of 10 - Improve how locking copes with replays NeilBrown
` (6 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: NeilBrown @ 2004-04-08 1:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: nfs, J. Bruce Fields
From: "J. Bruce Fields" <bfields@fieldses.org>
>From Andros: locku replies should be saved for possible replay as well.
----------- Diffstat output ------------
./fs/nfsd/nfs4proc.c | 1 +
1 files changed, 1 insertion(+)
diff ./fs/nfsd/nfs4proc.c~current~ ./fs/nfsd/nfs4proc.c
--- ./fs/nfsd/nfs4proc.c~current~ 2004-04-08 10:56:00.000000000 +1000
+++ ./fs/nfsd/nfs4proc.c 2004-04-08 10:56:52.000000000 +1000
@@ -789,6 +789,7 @@ nfsd4_proc_compound(struct svc_rqst *rqs
break;
case OP_LOCKU:
op->status = nfsd4_locku(rqstp, ¤t_fh, &op->u.locku);
+ op->replay = &op->u.locku.lu_stateowner->so_replay;
break;
case OP_LOOKUP:
op->status = nfsd4_lookup(rqstp, ¤t_fh, &op->u.lookup);
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH] kNFSdv4 - 0 of 10 - Introduction
@ 2004-04-08 1:18 NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 9 of 10 - Set credentials properly when puutrootfh is used NeilBrown
` (9 more replies)
0 siblings, 10 replies; 16+ messages in thread
From: NeilBrown @ 2004-04-08 1:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: nfs, J. Bruce Fields
Hi Andrew,
here are 10 patches for the NFSv4 server in 2.6-latested.
Some relate to the "idmapper" which is used to map between textual
identities (used by the protocol) and numerical identitied (i.e. uids).
Others relate to better handling of replayed requests.
All are purely nfsv4 which is still "Experimental" and should be as safe
as the rest of the nfsv4 server code.
Thanks,
NeilBrown
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] kNFSdv4 - 1 of 10 - idmap bugfixes and cleanup
[not found] ` <20040407233608.6414089a.akpm@osdl.org>
@ 2004-04-08 19:18 ` J. Bruce Fields
2004-04-08 19:28 ` J. Bruce Fields
1 sibling, 0 replies; 16+ messages in thread
From: J. Bruce Fields @ 2004-04-08 19:18 UTC (permalink / raw)
To: Andrew Morton; +Cc: NeilBrown, nfs
On Wed, Apr 07, 2004 at 11:36:08PM -0700, Andrew Morton wrote:
>
> Random observations which may be wrong:
>
> - If two CPUs run put_mdr() at the same time, one of them can do
> wake_up() of a now-kfreed pointer. This function requires higher-level
> locking of some form.
Argh, there isn't any, so you're right of course, thanks.
So I just use a spinlock. That also makes the atomic_t superfluous.
Here's an incremental patch.
--b.
fs/nfsd/nfs4idmap.c | 15 +++++++++------
1 files changed, 9 insertions(+), 6 deletions(-)
diff -puN fs/nfsd/nfs4idmap.c~nfsd_idmap_mdr_put_fix fs/nfsd/nfs4idmap.c
--- linux-2.6.5-rc2/fs/nfsd/nfs4idmap.c~nfsd_idmap_mdr_put_fix 2004-04-08 14:14:28.000000000 -0400
+++ linux-2.6.5-rc2-bfields/fs/nfsd/nfs4idmap.c 2004-04-08 14:14:28.000000000 -0400
@@ -406,18 +406,21 @@ struct idmap_defer_req {
struct cache_req req;
struct cache_deferred_req deferred_req;
wait_queue_head_t waitq;
- atomic_t count;
+ int count;
};
+static spinlock_t mdr_lock = SPIN_LOCK_UNLOCKED;
+
static void
put_mdr(struct idmap_defer_req *mdr)
{
- wait_queue_head_t *waitq = &mdr->waitq;
-
- if (atomic_dec_and_test(&mdr->count))
+ spin_lock(&mdr_lock);
+ mdr->count--;
+ if (mdr->count == 0)
kfree(mdr);
else
- wake_up(waitq);
+ wake_up(&mdr->waitq);
+ spin_unlock(&mdr_lock);
}
static void
@@ -501,7 +504,7 @@ init_mdr(struct idmap_defer_req *mdr, wa
memset(mdr, 0, sizeof(*mdr));
init_waitqueue_head(&mdr->waitq);
add_wait_queue(&mdr->waitq, waitq);
- atomic_set(&mdr->count, 2);
+ mdr->count = 2;
mdr->req.defer = idmap_defer;
}
_
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] kNFSdv4 - 1 of 10 - idmap bugfixes and cleanup
[not found] ` <20040407233608.6414089a.akpm@osdl.org>
2004-04-08 19:18 ` J. Bruce Fields
@ 2004-04-08 19:28 ` J. Bruce Fields
[not found] ` <20040408125528.5362c910.akpm@osdl.org>
1 sibling, 1 reply; 16+ messages in thread
From: J. Bruce Fields @ 2004-04-08 19:28 UTC (permalink / raw)
To: Andrew Morton; +Cc: NeilBrown, nfs
On Wed, Apr 07, 2004 at 11:36:08PM -0700, Andrew Morton wrote:
>
> - Cannot idmap_lookup() return in state TASK_UNINTERRUPTIBLE?
I assume you meant TASK_INTERRUPTIBLE.
After the
set_task_state(current, TASK_INTERRUPTIBLE);
either put_mdr, or idmap_wait (which always calls put_mdr) is called,
and put_mdr does a wake_up. So I believe this is correct, though I do
wish it was clearer.
--b.
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] kNFSdv4 - 6 of 10 - Keep state to allow replays for 'close' to work.
[not found] ` <20040407234541.7f2bb6d3.akpm@osdl.org>
@ 2004-04-08 21:23 ` J. Bruce Fields
0 siblings, 0 replies; 16+ messages in thread
From: J. Bruce Fields @ 2004-04-08 21:23 UTC (permalink / raw)
To: Andrew Morton; +Cc: NeilBrown, nfs
On Wed, Apr 07, 2004 at 11:45:41PM -0700, Andrew Morton wrote:
> NeilBrown <neilb@cse.unsw.edu.au> wrote:
> >
> > + dprintk("NFSD: find_openstateowner_id %d\n", st_id);
> > + if (flags & CLOSE_STATE) {
> > + list_for_each_safe(pos, next, &close_lru) {
> > + local = list_entry(pos, struct nfs4_stateowner,
> > + so_close_lru);
> > + if(local->so_id == st_id)
> > + return local;
> > + }
> > }
>
> list_for_each() is adequate here. list_for_each_safe() is only needed if
> you're removing things from the list inside the body of the loop.
Someone was very fond of list_for_each_safe(). The following (applies
on top of the above) removes all the list_for_each_safe()'s in
nfs4state.c except for the two that were actually needed.
> The locking in here is, err, a little coarse-grained?
Yeah, everything on the server that deals with nfsv4 open and locking
state takes a single big semaphore. We should fix that some day.
--b.
fs/nfsd/nfs4state.c | 70 +++++++++++++---------------------------------------
1 files changed, 18 insertions(+), 52 deletions(-)
diff -puN fs/nfs/nfs4state.c~nfsd_list_cleanup fs/nfs/nfs4state.c
diff -puN fs/nfsd/nfs4state.c~nfsd_list_cleanup fs/nfsd/nfs4state.c
--- linux-2.6.5-rc2/fs/nfsd/nfs4state.c~nfsd_list_cleanup 2004-04-08 16:37:53.000000000 -0400
+++ linux-2.6.5-rc2-bfields/fs/nfsd/nfs4state.c 2004-04-08 16:38:30.000000000 -0400
@@ -380,7 +380,6 @@ nfsd4_setclientid(struct svc_rqst *rqstp
unsigned int strhashval;
struct nfs4_client * conf, * unconf, * new, * clp;
int status;
- struct list_head *pos, *next;
status = nfserr_inval;
if (!check_name(clname))
@@ -395,8 +394,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp
conf = NULL;
nfs4_lock_state();
- list_for_each_safe(pos, next, &conf_str_hashtbl[strhashval]) {
- clp = list_entry(pos, struct nfs4_client, cl_strhash);
+ list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) {
if (!cmp_name(&clp->cl_name, &clname))
continue;
/*
@@ -426,8 +424,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp
break;
}
unconf = NULL;
- list_for_each_safe(pos, next, &unconf_str_hashtbl[strhashval]) {
- clp = list_entry(pos, struct nfs4_client, cl_strhash);
+ list_for_each_entry(clp, &unconf_str_hashtbl[strhashval], cl_strhash) {
if (!cmp_name(&clp->cl_name, &clname))
continue;
/* cl_name match from a previous SETCLIENTID operation */
@@ -553,7 +550,6 @@ nfsd4_setclientid_confirm(struct svc_rqs
struct nfs4_client *clp, *conf = NULL, *unconf = NULL;
nfs4_verifier confirm = setclientid_confirm->sc_confirm;
clientid_t * clid = &setclientid_confirm->sc_clientid;
- struct list_head *pos, *next;
int status;
status = nfserr_stale_clientid;
@@ -566,8 +562,7 @@ nfsd4_setclientid_confirm(struct svc_rqs
idhashval = clientid_hashval(clid->cl_id);
nfs4_lock_state();
- list_for_each_safe(pos, next, &conf_id_hashtbl[idhashval]) {
- clp = list_entry(pos, struct nfs4_client, cl_idhash);
+ list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
if (!cmp_clid(&clp->cl_clientid, clid))
continue;
@@ -586,8 +581,7 @@ nfsd4_setclientid_confirm(struct svc_rqs
conf = clp;
break;
}
- list_for_each_safe(pos, next, &unconf_id_hashtbl[idhashval]) {
- clp = list_entry(pos, struct nfs4_client, cl_idhash);
+ list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
if (!cmp_clid(&clp->cl_clientid, clid))
continue;
status = nfserr_inval;
@@ -933,11 +927,9 @@ cmp_owner_str(struct nfs4_stateowner *so
/* search ownerstr_hashtbl[] for owner */
static int
find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, struct nfs4_stateowner **op) {
- struct list_head *pos, *next;
struct nfs4_stateowner *local = NULL;
- list_for_each_safe(pos, next, &ownerstr_hashtbl[hashval]) {
- local = list_entry(pos, struct nfs4_stateowner, so_strhash);
+ list_for_each_entry(local, &ownerstr_hashtbl[hashval], so_strhash) {
if(!cmp_owner_str(local, &open->op_owner, &open->op_clientid))
continue;
*op = local;
@@ -950,12 +942,10 @@ find_openstateowner_str(unsigned int has
static int
verify_clientid(struct nfs4_client **client, clientid_t *clid) {
- struct list_head *pos, *next;
struct nfs4_client *clp;
unsigned int idhashval = clientid_hashval(clid->cl_id);
- list_for_each_safe(pos, next, &conf_id_hashtbl[idhashval]) {
- clp = list_entry(pos, struct nfs4_client, cl_idhash);
+ list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
if (!cmp_clid(&clp->cl_clientid, clid))
continue;
*client = clp;
@@ -968,11 +958,9 @@ verify_clientid(struct nfs4_client **cli
/* search file_hashtbl[] for file */
static int
find_file(unsigned int hashval, struct inode *ino, struct nfs4_file **fp) {
- struct list_head *pos, *next;
struct nfs4_file *local = NULL;
- list_for_each_safe(pos, next, &file_hashtbl[hashval]) {
- local = list_entry(pos, struct nfs4_file, fi_hash);
+ list_for_each_entry(local, &file_hashtbl[hashval], fi_hash) {
if (local->fi_inode == ino) {
*fp = local;
return(1);
@@ -1028,15 +1016,13 @@ nfs4_share_conflict(struct svc_fh *curre
unsigned int fi_hashval;
struct nfs4_file *fp;
struct nfs4_stateid *stp;
- struct list_head *pos, *next;
dprintk("NFSD: nfs4_share_conflict\n");
fi_hashval = file_hashval(ino);
if (find_file(fi_hashval, ino, &fp)) {
/* Search for conflicting share reservations */
- list_for_each_safe(pos, next, &fp->fi_perfile) {
- stp = list_entry(pos, struct nfs4_stateid, st_perfile);
+ list_for_each_entry(stp, &fp->fi_perfile, st_perfile) {
if (test_bit(deny_type, &stp->st_deny_bmap) ||
test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
return nfserr_share_denied;
@@ -1171,7 +1157,6 @@ nfsd4_process_open2(struct svc_rqst *rqs
struct nfs4_file *fp;
struct inode *ino;
unsigned int fi_hashval;
- struct list_head *pos, *next;
struct nfs4_stateid *stq, *stp = NULL;
int status;
@@ -1190,8 +1175,7 @@ nfsd4_process_open2(struct svc_rqst *rqs
if (find_file(fi_hashval, ino, &fp)) {
/* Search for conflicting share reservations */
status = nfserr_share_denied;
- list_for_each_safe(pos, next, &fp->fi_perfile) {
- stq = list_entry(pos, struct nfs4_stateid, st_perfile);
+ list_for_each_entry(stq, &fp->fi_perfile, st_perfile) {
if(stq->st_stateowner == sop) {
stp = stq;
continue;
@@ -1291,7 +1275,6 @@ int
nfsd4_renew(clientid_t *clid)
{
struct nfs4_client *clp;
- struct list_head *pos, *next;
unsigned int idhashval;
int status;
@@ -1303,15 +1286,13 @@ nfsd4_renew(clientid_t *clid)
goto out;
status = nfs_ok;
idhashval = clientid_hashval(clid->cl_id);
- list_for_each_safe(pos, next, &conf_id_hashtbl[idhashval]) {
- clp = list_entry(pos, struct nfs4_client, cl_idhash);
+ list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
if (!cmp_clid(&clp->cl_clientid, clid))
continue;
renew_client(clp);
goto out;
}
- list_for_each_safe(pos, next, &unconf_id_hashtbl[idhashval]) {
- clp = list_entry(pos, struct nfs4_client, cl_idhash);
+ list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
if (!cmp_clid(&clp->cl_clientid, clid))
continue;
renew_client(clp);
@@ -1387,14 +1368,11 @@ laundromat_main(void *not_used)
*/
struct nfs4_stateowner *
find_openstateowner_id(u32 st_id, int flags) {
- struct list_head *pos, *next;
struct nfs4_stateowner *local = NULL;
dprintk("NFSD: find_openstateowner_id %d\n", st_id);
if (flags & CLOSE_STATE) {
- list_for_each_safe(pos, next, &close_lru) {
- local = list_entry(pos, struct nfs4_stateowner,
- so_close_lru);
+ list_for_each_entry(local, &close_lru, so_close_lru) {
if(local->so_id == st_id)
return local;
}
@@ -1767,7 +1745,6 @@ static struct list_head lockstateid_hash
struct nfs4_stateid *
find_stateid(stateid_t *stid, int flags)
{
- struct list_head *pos, *next;
struct nfs4_stateid *local = NULL;
u32 st_id = stid->si_stateownerid;
u32 f_id = stid->si_fileid;
@@ -1776,8 +1753,7 @@ find_stateid(stateid_t *stid, int flags)
dprintk("NFSD: find_stateid flags 0x%x\n",flags);
if ((flags & LOCK_STATE) || (flags & RDWR_STATE)) {
hashval = stateid_hashval(st_id, f_id);
- list_for_each_safe(pos, next, &lockstateid_hashtbl[hashval]) {
- local = list_entry(pos, struct nfs4_stateid, st_hash);
+ list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) {
if((local->st_stateid.si_stateownerid == st_id) &&
(local->st_stateid.si_fileid == f_id))
return local;
@@ -1785,8 +1761,7 @@ find_stateid(stateid_t *stid, int flags)
}
if ((flags & OPEN_STATE) || (flags & RDWR_STATE)) {
hashval = stateid_hashval(st_id, f_id);
- list_for_each_safe(pos, next, &stateid_hashtbl[hashval]) {
- local = list_entry(pos, struct nfs4_stateid, st_hash);
+ list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) {
if((local->st_stateid.si_stateownerid == st_id) &&
(local->st_stateid.si_fileid == f_id))
return local;
@@ -1817,14 +1792,12 @@ nfs4_transform_lock_offset(struct file_l
int
nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval)
{
- struct list_head *pos, *next;
struct nfs4_stateowner *local = NULL;
int status = 0;
if (hashval >= LOCK_HASH_SIZE)
goto out;
- list_for_each_safe(pos, next, &lock_ownerid_hashtbl[hashval]) {
- local = list_entry(pos, struct nfs4_stateowner, so_idhash);
+ list_for_each_entry(local, &lock_ownerid_hashtbl[hashval], so_idhash) {
if (local == sop) {
status = 1;
goto out;
@@ -1855,11 +1828,9 @@ nfs4_set_lock_denied(struct file_lock *f
static int
find_lockstateowner_str(unsigned int hashval, struct xdr_netobj *owner, clientid_t *clid, struct nfs4_stateowner **op) {
- struct list_head *pos, *next;
struct nfs4_stateowner *local = NULL;
- list_for_each_safe(pos, next, &lock_ownerstr_hashtbl[hashval]) {
- local = list_entry(pos, struct nfs4_stateowner, so_strhash);
+ list_for_each_entry(local, &lock_ownerstr_hashtbl[hashval], so_strhash) {
if(!cmp_owner_str(local, owner, clid))
continue;
*op = local;
@@ -2305,7 +2276,6 @@ int
nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
{
clientid_t *clid = &rlockowner->rl_clientid;
- struct list_head *pos, *next;
struct nfs4_stateowner *local = NULL;
struct xdr_netobj *owner = &rlockowner->rl_owner;
int status, i;
@@ -2326,9 +2296,7 @@ nfsd4_release_lockowner(struct svc_rqst
/* find the lockowner */
status = nfs_ok;
for (i=0; i < LOCK_HASH_SIZE; i++) {
- list_for_each_safe(pos, next, &lock_ownerstr_hashtbl[i]) {
- local = list_entry(pos, struct nfs4_stateowner,
- so_strhash);
+ list_for_each_entry(local, &lock_ownerstr_hashtbl[i], so_strhash) {
if(cmp_owner_str(local, owner, clid))
break;
}
@@ -2339,9 +2307,7 @@ nfsd4_release_lockowner(struct svc_rqst
/* check for any locks held by any stateid associated with the
* (lock) stateowner */
status = nfserr_locks_held;
- list_for_each_safe(pos, next, &local->so_perfilestate) {
- stp = list_entry(pos, struct nfs4_stateid,
- st_perfilestate);
+ list_for_each_entry(stp, &local->so_perfilestate, st_perfilestate) {
if(stp->st_vfs_set) {
if (check_for_locks(&stp->st_vfs_file, local))
goto out;
_
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] kNFSdv4 - 1 of 10 - idmap bugfixes and cleanup
[not found] ` <20040408125528.5362c910.akpm@osdl.org>
@ 2004-04-08 22:05 ` J. Bruce Fields
[not found] ` <20040408153438.41e2c494.akpm@osdl.org>
0 siblings, 1 reply; 16+ messages in thread
From: J. Bruce Fields @ 2004-04-08 22:05 UTC (permalink / raw)
To: Andrew Morton; +Cc: neilb, nfs
On Thu, Apr 08, 2004 at 12:55:28PM -0700, Andrew Morton wrote:
> "J. Bruce Fields" <bfields@fieldses.org> wrote:
> > After the
> >
> > set_task_state(current, TASK_INTERRUPTIBLE);
> >
> > either put_mdr, or idmap_wait (which always calls put_mdr) is called,
> > and put_mdr does a wake_up. So I believe this is correct, though I do
> > wish it was clearer.
>
> wake_up() doesn't alter the caller's task->state.
The caller is on the waitqueue in this case.
But now that I look at it more carefully, there's more serious problems;
it'll take another day for me to get this right, sorry; drop the idmap
patches or not, and that particular code is in almost equally bad
shape....
--b.
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] kNFSdv4 - 1 of 10 - idmap bugfixes and cleanup
[not found] ` <20040408153438.41e2c494.akpm@osdl.org>
@ 2004-04-08 22:39 ` J. Bruce Fields
0 siblings, 0 replies; 16+ messages in thread
From: J. Bruce Fields @ 2004-04-08 22:39 UTC (permalink / raw)
To: Andrew Morton; +Cc: neilb, nfs
On Thu, Apr 08, 2004 at 03:34:38PM -0700, Andrew Morton wrote:
> What do you want me to do?
Could you just drop the first 4 for now? Thanks.
> kNFSdv4-1-of-10-idmap-bugfixes-and-cleanup.patch
> nfsd_idmap_mdr_put_fix.patch
> kNFSdv4-2-of-10-better-handling-of-failed-idmap-lookups.patch
> kNFSdv4-3-of-10-complain-if-idmapd-doesnt-have-channel-open.patch
And then I'll just resubmit those through Neil when they're fixed.
Sorry about that.--b.
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2004-04-08 22:39 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-04-08 1:18 [PATCH] kNFSdv4 - 0 of 10 - Introduction NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 9 of 10 - Set credentials properly when puutrootfh is used NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 3 of 10 - complain if idmapd doesn't have channel open NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 7 of 10 - Allow locku replays aswell NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 8 of 10 - Improve how locking copes with replays NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 6 of 10 - Keep state to allow replays for 'close' to work NeilBrown
[not found] ` <20040407234541.7f2bb6d3.akpm@osdl.org>
2004-04-08 21:23 ` J. Bruce Fields
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 2 of 10 - better handling of failed idmap lookups NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 5 of 10 - Fix bad error returm from svcauth_gss_accept NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 10 of 10 - Implement server-side reboot recovery (mostly) NeilBrown
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 1 of 10 - idmap bugfixes and cleanup NeilBrown
[not found] ` <20040407233608.6414089a.akpm@osdl.org>
2004-04-08 19:18 ` J. Bruce Fields
2004-04-08 19:28 ` J. Bruce Fields
[not found] ` <20040408125528.5362c910.akpm@osdl.org>
2004-04-08 22:05 ` J. Bruce Fields
[not found] ` <20040408153438.41e2c494.akpm@osdl.org>
2004-04-08 22:39 ` J. Bruce Fields
2004-04-08 1:18 ` [PATCH] kNFSdv4 - 4 of 10 - nfsd4_readdir fixes NeilBrown
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.