patch-2.3.99-pre4 linux/fs/lockd/clntproc.c
Next file: linux/fs/lockd/host.c
Previous file: linux/fs/lockd/clntlock.c
Back to the patch index
Back to the overall index
- Lines: 233
- Date:
Mon Apr 3 13:24:05 2000
- Orig file:
v2.3.99-pre3/linux/fs/lockd/clntproc.c
- Orig date:
Mon Mar 27 08:08:29 2000
diff -u --recursive --new-file v2.3.99-pre3/linux/fs/lockd/clntproc.c linux/fs/lockd/clntproc.c
@@ -106,10 +106,18 @@
struct nlm_rqst reqst, *call = &reqst;
sigset_t oldset;
unsigned long flags;
- int status;
+ int status, proto, vers;
- /* Always use NLM version 1 over UDP for now... */
- if (!(host = nlmclnt_lookup_host(NFS_ADDR(inode), IPPROTO_UDP, 1)))
+ vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1;
+ if (NFS_PROTO(inode)->version > 3) {
+ printk(KERN_NOTICE "NFSv4 file locking not implemented!\n");
+ return -ENOLCK;
+ }
+
+ /* Retrieve transport protocol from NFS client */
+ proto = NFS_CLIENT(inode)->cl_xprt->prot;
+
+ if (!(host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers)))
return -ENOLCK;
/* Create RPC client handle if not there, and copy soft
@@ -142,6 +150,10 @@
spin_unlock_irqrestore(¤t->sigmask_lock, flags);
call = nlmclnt_alloc_call();
+ if (!call) {
+ status = -ENOMEM;
+ goto out_restore;
+ }
call->a_flags = RPC_TASK_ASYNC;
} else {
spin_unlock_irqrestore(¤t->sigmask_lock, flags);
@@ -165,8 +177,9 @@
}
if (status < 0 && (call->a_flags & RPC_TASK_ASYNC))
- rpc_free(call);
+ kfree(call);
+ out_restore:
spin_lock_irqsave(¤t->sigmask_lock, flags);
current->blocked = oldset;
recalc_sigpending(current);
@@ -200,8 +213,7 @@
struct nlm_rqst *call;
while (!signalled()) {
- call = (struct nlm_rqst *) rpc_allocate(RPC_TASK_ASYNC,
- sizeof(struct nlm_rqst));
+ call = (struct nlm_rqst *) kmalloc(sizeof(struct nlm_rqst), GFP_KERNEL);
if (call)
return call;
printk("nlmclnt_alloc_call: failed, waiting for memory\n");
@@ -246,6 +258,7 @@
case -ECONNREFUSED:
case -ETIMEDOUT:
case -ENOTCONN:
+ nlm_rebind_host(host);
status = -EAGAIN;
break;
case -ERESTARTSYS:
@@ -253,10 +266,7 @@
default:
break;
}
- if (req->a_args.block)
- nlm_rebind_host(host);
- else
- break;
+ break;
} else
if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) {
dprintk("lockd: server in grace period\n");
@@ -290,7 +300,7 @@
* Generic NLM call, async version.
*/
int
-nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
+nlmsvc_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
{
struct nlm_host *host = req->a_host;
struct rpc_clnt *clnt;
@@ -313,9 +323,20 @@
msg.rpc_cred = NULL;
status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req);
- /* If the async call is proceeding, increment host refcount */
- if (status >= 0 && (req->a_flags & RPC_TASK_ASYNC))
- host->h_count++;
+ return status;
+}
+
+int
+nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
+{
+ struct nlm_host *host = req->a_host;
+ int status;
+
+ /* Increment host refcount */
+ nlm_get_host(host);
+ status = nlmsvc_async_call(req, proc, callback);
+ if (status < 0)
+ nlm_release_host(host);
return status;
}
@@ -347,6 +368,20 @@
return 0;
}
+static
+void nlmclnt_insert_lock_callback(struct file_lock *fl)
+{
+ nlm_get_host(fl->fl_u.nfs_fl.host);
+}
+static
+void nlmclnt_remove_lock_callback(struct file_lock *fl)
+{
+ if (fl->fl_u.nfs_fl.host) {
+ nlm_release_host(fl->fl_u.nfs_fl.host);
+ fl->fl_u.nfs_fl.host = NULL;
+ }
+}
+
/*
* LOCK: Try to create a lock
*
@@ -380,7 +415,7 @@
return -ENOLCK;
}
- while (1) {
+ do {
if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0) {
if (resp->status != NLM_LCK_BLOCKED)
break;
@@ -388,11 +423,14 @@
}
if (status < 0)
return status;
- }
+ } while (resp->status == NLM_LCK_BLOCKED);
if (resp->status == NLM_LCK_GRANTED) {
fl->fl_u.nfs_fl.state = host->h_state;
fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
+ fl->fl_u.nfs_fl.host = host;
+ fl->fl_insert = nlmclnt_insert_lock_callback;
+ fl->fl_remove = nlmclnt_remove_lock_callback;
}
return nlm_stat_to_errno(resp->status);
@@ -444,15 +482,9 @@
static int
nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
{
- struct nlm_host *host = req->a_host;
struct nlm_res *resp = &req->a_res;
int status;
- /* No monitor, no lock: see nlmclnt_lock().
- * Since this is an UNLOCK, don't try to setup monitoring here. */
- if (!host->h_monitored)
- return -ENOLCK;
-
/* Clean the GRANTED flag now so the lock doesn't get
* reclaimed while we're stuck in the unlock call. */
fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED;
@@ -487,9 +519,7 @@
if (task->tk_status < 0) {
dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status);
- nlm_rebind_host(req->a_host);
- rpc_restart_call(task);
- return;
+ goto retry_unlock;
}
if (status != NLM_LCK_GRANTED
&& status != NLM_LCK_DENIED_GRACE_PERIOD) {
@@ -497,7 +527,12 @@
}
die:
- rpc_release_task(task);
+ nlm_release_host(req->a_host);
+ kfree(req);
+ return;
+ retry_unlock:
+ nlm_rebind_host(req->a_host);
+ rpc_restart_call(task);
}
/*
@@ -520,10 +555,9 @@
recalc_sigpending(current);
spin_unlock_irqrestore(¤t->sigmask_lock, flags);
- do {
- req = (struct nlm_rqst *) rpc_allocate(RPC_TASK_ASYNC,
- sizeof(*req));
- } while (req == NULL);
+ req = nlmclnt_alloc_call();
+ if (!req)
+ return -ENOMEM;
req->a_host = host;
req->a_flags = RPC_TASK_ASYNC;
@@ -532,7 +566,7 @@
status = nlmclnt_async_call(req, NLMPROC_CANCEL,
nlmclnt_cancel_callback);
if (status < 0)
- rpc_free(req);
+ kfree(req);
spin_lock_irqsave(¤t->sigmask_lock, flags);
current->blocked = oldset;
@@ -573,7 +607,6 @@
}
die:
- rpc_release_task(task);
nlm_release_host(req->a_host);
kfree(req);
return;
@@ -582,7 +615,6 @@
nlm_rebind_host(req->a_host);
rpc_restart_call(task);
rpc_delay(task, 30 * HZ);
- return;
}
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)