*/
#include <linux/types.h>
+#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b)
{
- if(a->len != b->len)
+ if (a->len != b->len)
return 0;
- if(memcmp(a->data,b->data,a->len))
+ if (memcmp(a->data, b->data, a->len))
return 0;
return 1;
}
struct nlm_block *block;
struct nlm_rqst *call = NULL;
+ nlm_get_host(host);
call = nlm_alloc_call(host);
if (call == NULL)
return NULL;
{
if (call->a_args.lock.oh.data != call->a_owner)
kfree(call->a_args.lock.oh.data);
+
+ locks_release_private(&call->a_args.lock.fl);
}
/*
__be32
nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
struct nlm_host *host, struct nlm_lock *lock, int wait,
- struct nlm_cookie *cookie)
+ struct nlm_cookie *cookie, int reclaim)
{
struct nlm_block *block = NULL;
int error;
*/
block = nlmsvc_lookup_block(file, lock);
if (block == NULL) {
- block = nlmsvc_create_block(rqstp, nlm_get_host(host), file,
- lock, cookie);
+ block = nlmsvc_create_block(rqstp, host, file, lock, cookie);
ret = nlm_lck_denied_nolocks;
if (block == NULL)
goto out;
goto out;
}
+ if (locks_in_grace() && !reclaim) {
+ ret = nlm_lck_denied_grace_period;
+ goto out;
+ }
+ if (reclaim && !locks_in_grace()) {
+ ret = nlm_lck_denied_grace_period;
+ goto out;
+ }
+
if (!wait)
lock->fl.fl_flags &= ~FL_SLEEP;
error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
lock->fl.fl_flags &= ~FL_SLEEP;
dprintk("lockd: vfs_lock_file returned %d\n", error);
- switch(error) {
+ switch (error) {
case 0:
ret = nlm_granted;
goto out;
case -EAGAIN:
+ /*
+ * If this is a blocking request for an
+ * already pending lock request then we need
+ * to put it back on lockd's block list
+ */
+ if (wait)
+ break;
ret = nlm_lck_denied;
- break;
- case -EINPROGRESS:
+ goto out;
+ case FILE_LOCK_DEFERRED:
if (wait)
break;
/* Filesystem lock operation is in progress
goto out;
}
- ret = nlm_lck_denied;
- if (!wait)
- goto out;
-
ret = nlm_lck_blocked;
/* Append to list of blocked */
if (conf == NULL)
return nlm_granted;
- nlm_get_host(host);
block = nlmsvc_create_block(rqstp, host, file, lock, cookie);
if (block == NULL) {
kfree(conf);
goto out;
}
+ if (locks_in_grace()) {
+ ret = nlm_lck_denied_grace_period;
+ goto out;
+ }
error = vfs_test_lock(file->f_file, &lock->fl);
- if (error == -EINPROGRESS) {
+ if (error == FILE_LOCK_DEFERRED) {
ret = nlmsvc_defer_lock_rqst(rqstp, block);
goto out;
}
(long long)lock->fl.fl_start,
(long long)lock->fl.fl_end);
+ if (locks_in_grace())
+ return nlm_lck_denied_grace_period;
+
mutex_lock(&file->f_mutex);
block = nlmsvc_lookup_block(file, lock);
mutex_unlock(&file->f_mutex);
return fl1->fl_owner == fl2->fl_owner && fl1->fl_pid == fl2->fl_pid;
}
-struct lock_manager_operations nlmsvc_lock_operations = {
+const struct lock_manager_operations nlmsvc_lock_operations = {
.fl_compare_owner = nlmsvc_same_owner,
.fl_notify = nlmsvc_notify_blocked,
.fl_grant = nlmsvc_grant_deferred,
switch (error) {
case 0:
break;
- case -EAGAIN:
- case -EINPROGRESS:
+ case FILE_LOCK_DEFERRED:
dprintk("lockd: lock still blocked error %d\n", error);
nlmsvc_insert_block(block, NLM_NEVER);
nlmsvc_release_block(block);
dprintk("lockd: GRANT_MSG RPC callback\n");
+ lock_kernel();
/* if the block is not on a list at this point then it has
* been invalidated. Don't try to requeue it.
*
* for nlm_blocked?
*/
if (list_empty(&block->b_list))
- return;
+ goto out;
/* Technically, we should down the file semaphore here. Since we
* move the block towards the head of the queue only, no harm
}
nlmsvc_insert_block(block, timeout);
svc_wake_up(block->b_daemon);
+out:
+ unlock_kernel();
}
static void nlmsvc_grant_release(void *data)
{
struct nlm_rqst *call = data;
+ lock_kernel();
nlmsvc_release_block(call->a_block);
+ unlock_kernel();
}
static const struct rpc_call_ops nlmsvc_grant_ops = {
if (block->b_when == NLM_NEVER)
break;
- if (time_after(block->b_when,jiffies)) {
+ if (time_after(block->b_when, jiffies)) {
timeout = block->b_when - jiffies;
break;
}