summaryrefslogtreecommitdiff
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-21 10:42:58 -0700
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-21 10:42:58 -0700
commitab27642b59b68d18df5a9aa5fa81b5ab5735aa77 (patch)
treeafc2f191ef73e6eb1064de6358f44177d691aab0 /fs/nfs
parentba9b543d5bec0a7605952e2ba501fb8b0f3b6407 (diff)
parent654b1536b0927d189526b9063818e0790aa3ea23 (diff)
Merge branch 'master' of ssh://rsync.linux-nfs.org/home/trondmy/www_sites/rsync.linux-nfs.org/pub/linux/nfs-2.6
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4_fs.h4
-rw-r--r--fs/nfs/nfs4proc.c4
-rw-r--r--fs/nfs/nfs4state.c48
-rw-r--r--fs/nfs/nfs4xdr.c3
4 files changed, 34 insertions, 25 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 8a3788199052..78a53f5a9f18 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -110,9 +110,8 @@ struct nfs_seqid_counter {
};
struct nfs_seqid {
- struct list_head list;
struct nfs_seqid_counter *sequence;
- struct rpc_task *task;
+ struct list_head list;
};
static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status)
@@ -127,6 +126,7 @@ static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status
* semantics by allowing the server to identify replayed requests.
*/
struct nfs4_state_owner {
+ spinlock_t so_lock;
struct list_head so_list; /* per-clientid list of state_owners */
struct nfs4_client *so_client;
u32 so_id; /* 32-bit identifier, unique */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ff378126ccd7..9c1da34036aa 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -212,6 +212,7 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid,
open_flags &= (FMODE_READ|FMODE_WRITE);
/* Protect against nfs4_find_state() */
+ spin_lock(&state->owner->so_lock);
spin_lock(&inode->i_lock);
state->state |= open_flags;
/* NB! List reordering - see the reclaim code for why. */
@@ -221,6 +222,7 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid,
state->nreaders++;
memcpy(&state->stateid, stateid, sizeof(state->stateid));
spin_unlock(&inode->i_lock);
+ spin_unlock(&state->owner->so_lock);
}
/*
@@ -2357,7 +2359,7 @@ static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size
return -ENOMEM;
args.acl_pages[0] = localpage;
args.acl_pgbase = 0;
- args.acl_len = PAGE_SIZE;
+ resp_len = args.acl_len = PAGE_SIZE;
} else {
resp_buf = buf;
buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 23834c8fb740..2d5a6a2b9dec 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -267,6 +267,7 @@ nfs4_alloc_state_owner(void)
sp = kzalloc(sizeof(*sp),GFP_KERNEL);
if (!sp)
return NULL;
+ spin_lock_init(&sp->so_lock);
INIT_LIST_HEAD(&sp->so_states);
INIT_LIST_HEAD(&sp->so_delegations);
rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue");
@@ -438,20 +439,23 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
if (state)
goto out;
new = nfs4_alloc_open_state();
+ spin_lock(&owner->so_lock);
spin_lock(&inode->i_lock);
state = __nfs4_find_state_byowner(inode, owner);
if (state == NULL && new != NULL) {
state = new;
- /* Note: The reclaim code dictates that we add stateless
- * and read-only stateids to the end of the list */
- list_add_tail(&state->open_states, &owner->so_states);
state->owner = owner;
atomic_inc(&owner->so_count);
list_add(&state->inode_states, &nfsi->open_states);
state->inode = igrab(inode);
spin_unlock(&inode->i_lock);
+ /* Note: The reclaim code dictates that we add stateless
+ * and read-only stateids to the end of the list */
+ list_add_tail(&state->open_states, &owner->so_states);
+ spin_unlock(&owner->so_lock);
} else {
spin_unlock(&inode->i_lock);
+ spin_unlock(&owner->so_lock);
if (new)
nfs4_free_open_state(new);
}
@@ -468,12 +472,14 @@ void nfs4_put_open_state(struct nfs4_state *state)
struct inode *inode = state->inode;
struct nfs4_state_owner *owner = state->owner;
- if (!atomic_dec_and_lock(&state->count, &inode->i_lock))
+ if (!atomic_dec_and_lock(&state->count, &owner->so_lock))
return;
+ spin_lock(&inode->i_lock);
if (!list_empty(&state->inode_states))
list_del(&state->inode_states);
- spin_unlock(&inode->i_lock);
list_del(&state->open_states);
+ spin_unlock(&inode->i_lock);
+ spin_unlock(&owner->so_lock);
iput(inode);
BUG_ON (state->state != 0);
nfs4_free_open_state(state);
@@ -491,6 +497,7 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
atomic_inc(&owner->so_count);
/* Protect against nfs4_find_state() */
+ spin_lock(&owner->so_lock);
spin_lock(&inode->i_lock);
if (mode & FMODE_READ)
state->nreaders--;
@@ -503,6 +510,7 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
list_move_tail(&state->open_states, &owner->so_states);
}
spin_unlock(&inode->i_lock);
+ spin_unlock(&owner->so_lock);
newstate = 0;
if (state->state != 0) {
if (state->nreaders)
@@ -670,16 +678,12 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f
struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
{
- struct rpc_sequence *sequence = counter->sequence;
struct nfs_seqid *new;
new = kmalloc(sizeof(*new), GFP_KERNEL);
if (new != NULL) {
new->sequence = counter;
- new->task = NULL;
- spin_lock(&sequence->lock);
- list_add_tail(&new->list, &sequence->list);
- spin_unlock(&sequence->lock);
+ INIT_LIST_HEAD(&new->list);
}
return new;
}
@@ -687,16 +691,13 @@ struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
void nfs_free_seqid(struct nfs_seqid *seqid)
{
struct rpc_sequence *sequence = seqid->sequence->sequence;
- struct rpc_task *next = NULL;
- spin_lock(&sequence->lock);
- list_del(&seqid->list);
- if (!list_empty(&sequence->list)) {
- next = list_entry(sequence->list.next, struct nfs_seqid, list)->task;
- if (next)
- rpc_wake_up_task(next);
+ if (!list_empty(&seqid->list)) {
+ spin_lock(&sequence->lock);
+ list_del(&seqid->list);
+ spin_unlock(&sequence->lock);
}
- spin_unlock(&sequence->lock);
+ rpc_wake_up_next(&sequence->wait);
kfree(seqid);
}
@@ -752,13 +753,16 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
struct rpc_sequence *sequence = seqid->sequence->sequence;
int status = 0;
+ if (sequence->list.next == &seqid->list)
+ goto out;
spin_lock(&sequence->lock);
- if (sequence->list.next != &seqid->list) {
- seqid->task = task;
+ if (!list_empty(&sequence->list)) {
rpc_sleep_on(&sequence->wait, task, NULL, NULL);
status = -EAGAIN;
- }
+ } else
+ list_add(&seqid->list, &sequence->list);
spin_unlock(&sequence->lock);
+out:
return status;
}
@@ -903,6 +907,7 @@ static void nfs4_state_mark_reclaim(struct nfs4_client *clp)
list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
sp->so_seqid.counter = 0;
sp->so_seqid.flags = 0;
+ spin_lock(&sp->so_lock);
list_for_each_entry(state, &sp->so_states, open_states) {
list_for_each_entry(lock, &state->lock_states, ls_locks) {
lock->ls_seqid.counter = 0;
@@ -910,6 +915,7 @@ static void nfs4_state_mark_reclaim(struct nfs4_client *clp)
lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
}
}
+ spin_unlock(&sp->so_lock);
}
}
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index c5c75235c5b8..cd762648fa9a 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -3255,7 +3255,8 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
if (attrlen <= *acl_len)
xdr_read_pages(xdr, attrlen);
*acl_len = attrlen;
- }
+ } else
+ status = -EOPNOTSUPP;
out:
return status;