obj-$(CONFIG_LOCKD) += lockd.o
lockd-objs-y := clntlock.o clntproc.o host.o svc.o svclock.o svcshare.o \
- svcproc.o svcsubs.o mon.o xdr.o
+ svcproc.o svcsubs.o mon.o xdr.o grace.o
lockd-objs-$(CONFIG_LOCKD_V4) += xdr4.o svc4proc.o
lockd-objs := $(lockd-objs-y)
--- /dev/null
+/*
+ * Common code for control of lockd and nfsv4 grace periods.
+ */
+
+#include <linux/module.h>
+#include <linux/lockd/bind.h>
+
+static LIST_HEAD(grace_list);
+static DEFINE_SPINLOCK(grace_lock);
+
+/**
+ * locks_start_grace
+ * @lm: who this grace period is for
+ *
+ * A grace period is a period during which locks should not be given
+ * out. Currently grace periods are only enforced by the two lock
+ * managers (lockd and nfsd), using the locks_in_grace() function to
+ * check when they are in a grace period.
+ *
+ * This function is called to start a grace period.
+ */
+void locks_start_grace(struct lock_manager *lm)
+{
+ spin_lock(&grace_lock);
+ list_add(&lm->list, &grace_list);
+ spin_unlock(&grace_lock);
+}
+EXPORT_SYMBOL_GPL(locks_start_grace);
+
+/**
+ * locks_end_grace
+ * @lm: who this grace period is for
+ *
+ * Call this function to state that the given lock manager is ready to
+ * resume regular locking. The grace period will not end until all lock
+ * managers that called locks_start_grace() also call locks_end_grace().
+ * Note that callers count on it being safe to call this more than once,
+ * and the second call should be a no-op.
+ */
+void locks_end_grace(struct lock_manager *lm)
+{
+ spin_lock(&grace_lock);
+ list_del_init(&lm->list);
+ spin_unlock(&grace_lock);
+}
+EXPORT_SYMBOL_GPL(locks_end_grace);
+
+/**
+ * locks_in_grace
+ *
+ * Lock managers call this function to determine when it is OK for them
+ * to answer ordinary lock requests, and when they should accept only
+ * lock reclaims.
+ */
+int locks_in_grace(void)
+{
+ return !list_empty(&grace_list);
+}
+EXPORT_SYMBOL_GPL(locks_in_grace);
static unsigned int nlmsvc_users;
static struct task_struct *nlmsvc_task;
static struct svc_rqst *nlmsvc_rqst;
-int nlmsvc_grace_period;
unsigned long nlmsvc_timeout;
/*
return nlm_timeout * 5 * HZ;
}
-unsigned long get_nfs_grace_period(void)
-{
- unsigned long lockdgrace = get_lockd_grace_period();
- unsigned long nfsdgrace = 0;
-
- if (nlmsvc_ops)
- nfsdgrace = nlmsvc_ops->get_grace_period();
-
- return max(lockdgrace, nfsdgrace);
-}
-EXPORT_SYMBOL(get_nfs_grace_period);
+static struct lock_manager lockd_manager = {
+};
static void grace_ender(struct work_struct *not_used)
{
- nlmsvc_grace_period = 0;
+ locks_end_grace(&lockd_manager);
}
static DECLARE_DELAYED_WORK(grace_period_end, grace_ender);
static void set_grace_period(void)
{
- unsigned long grace_period = get_nfs_grace_period() + jiffies;
+ unsigned long grace_period = get_lockd_grace_period();
- nlmsvc_grace_period = 1;
+ locks_start_grace(&lockd_manager);
cancel_delayed_work_sync(&grace_period_end);
schedule_delayed_work(&grace_period_end, grace_period);
}
resp->cookie = argp->cookie;
/* Don't accept test requests during grace period */
- if (nlmsvc_grace_period) {
+ if (locks_in_grace()) {
resp->status = nlm_lck_denied_grace_period;
return rc;
}
resp->cookie = argp->cookie;
/* Don't accept new lock requests during grace period */
- if (nlmsvc_grace_period && !argp->reclaim) {
+ if (locks_in_grace() && !argp->reclaim) {
resp->status = nlm_lck_denied_grace_period;
return rc;
}
resp->cookie = argp->cookie;
/* Don't accept requests during grace period */
- if (nlmsvc_grace_period) {
+ if (locks_in_grace()) {
resp->status = nlm_lck_denied_grace_period;
return rpc_success;
}
resp->cookie = argp->cookie;
/* Don't accept new lock requests during grace period */
- if (nlmsvc_grace_period) {
+ if (locks_in_grace()) {
resp->status = nlm_lck_denied_grace_period;
return rpc_success;
}
resp->cookie = argp->cookie;
/* Don't accept new lock requests during grace period */
- if (nlmsvc_grace_period && !argp->reclaim) {
+ if (locks_in_grace() && !argp->reclaim) {
resp->status = nlm_lck_denied_grace_period;
return rpc_success;
}
resp->cookie = argp->cookie;
/* Don't accept requests during grace period */
- if (nlmsvc_grace_period) {
+ if (locks_in_grace()) {
resp->status = nlm_lck_denied_grace_period;
return rpc_success;
}
resp->cookie = argp->cookie;
/* Don't accept test requests during grace period */
- if (nlmsvc_grace_period) {
+ if (locks_in_grace()) {
resp->status = nlm_lck_denied_grace_period;
return rc;
}
resp->cookie = argp->cookie;
/* Don't accept new lock requests during grace period */
- if (nlmsvc_grace_period && !argp->reclaim) {
+ if (locks_in_grace() && !argp->reclaim) {
resp->status = nlm_lck_denied_grace_period;
return rc;
}
resp->cookie = argp->cookie;
/* Don't accept requests during grace period */
- if (nlmsvc_grace_period) {
+ if (locks_in_grace()) {
resp->status = nlm_lck_denied_grace_period;
return rpc_success;
}
resp->cookie = argp->cookie;
/* Don't accept new lock requests during grace period */
- if (nlmsvc_grace_period) {
+ if (locks_in_grace()) {
resp->status = nlm_lck_denied_grace_period;
return rpc_success;
}
resp->cookie = argp->cookie;
/* Don't accept new lock requests during grace period */
- if (nlmsvc_grace_period && !argp->reclaim) {
+ if (locks_in_grace() && !argp->reclaim) {
resp->status = nlm_lck_denied_grace_period;
return rpc_success;
}
resp->cookie = argp->cookie;
/* Don't accept requests during grace period */
- if (nlmsvc_grace_period) {
+ if (locks_in_grace()) {
resp->status = nlm_lck_denied_grace_period;
return rpc_success;
}
static struct nlmsvc_binding nfsd_nlm_ops = {
.fopen = nlm_fopen, /* open file for locking */
.fclose = nlm_fclose, /* close file */
- .get_grace_period = get_nfs4_grace_period,
};
void
/* Openowner is now set, so sequence id will get bumped. Now we need
* these checks before we do any creates: */
status = nfserr_grace;
- if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+ if (locks_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
goto out;
status = nfserr_no_grace;
- if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+ if (!locks_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
goto out;
switch (open->op_claim_type) {
{
__be32 status;
- if (nfs4_in_grace())
+ if (locks_in_grace())
return nfserr_grace;
status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
remove->rm_name, remove->rm_namelen);
if (!cstate->save_fh.fh_dentry)
return status;
- if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags
+ if (locks_in_grace() && !(cstate->save_fh.fh_export->ex_flags
& NFSEXP_NOSUBTREECHECK))
return nfserr_grace;
status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
static time_t lease_time = 90; /* default lease time */
static time_t user_lease_time = 90;
static time_t boot_time;
-static int in_grace = 1;
static u32 current_ownerid = 1;
static u32 current_fileid = 1;
static u32 current_delegid = 1;
case NFS4_OPEN_CLAIM_NULL:
/* Let's not give out any delegations till everyone's
* had the chance to reclaim theirs.... */
- if (nfs4_in_grace())
+ if (locks_in_grace())
goto out;
if (!atomic_read(&cb->cb_set) || !sop->so_confirmed)
goto out;
return status;
}
+struct lock_manager nfsd4_manager = {
+};
+
static void
-end_grace(void)
+nfsd4_end_grace(void)
{
dprintk("NFSD: end of grace period\n");
nfsd4_recdir_purge_old();
- in_grace = 0;
+ locks_end_grace(&nfsd4_manager);
}
static time_t
nfs4_lock_state();
dprintk("NFSD: laundromat service - starting\n");
- if (in_grace)
- end_grace();
+ if (locks_in_grace())
+ nfsd4_end_grace();
list_for_each_safe(pos, next, &client_lru) {
clp = list_entry(pos, struct nfs4_client, cl_lru);
if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
return nfserr_bad_stateid;
else if (ONE_STATEID(stateid) && (flags & RD_STATE))
return nfs_ok;
- else if (nfs4_in_grace()) {
+ else if (locks_in_grace()) {
/* Answer in remaining cases depends on existance of
* conflicting state; so we must wait out the grace period. */
return nfserr_grace;
static inline int
io_during_grace_disallowed(struct inode *inode, int flags)
{
- return nfs4_in_grace() && (flags & (RD_STATE | WR_STATE))
+ return locks_in_grace() && (flags & (RD_STATE | WR_STATE))
&& mandatory_lock(inode);
}
filp = lock_stp->st_vfs_file;
status = nfserr_grace;
- if (nfs4_in_grace() && !lock->lk_reclaim)
+ if (locks_in_grace() && !lock->lk_reclaim)
goto out;
status = nfserr_no_grace;
- if (!nfs4_in_grace() && lock->lk_reclaim)
+ if (!locks_in_grace() && lock->lk_reclaim)
goto out;
locks_init_lock(&file_lock);
int error;
__be32 status;
- if (nfs4_in_grace())
+ if (locks_in_grace())
return nfserr_grace;
if (check_lock_length(lockt->lt_offset, lockt->lt_length))
unsigned long grace_time;
boot_time = get_seconds();
- grace_time = get_nfs_grace_period();
+ grace_time = get_nfs4_grace_period();
lease_time = user_lease_time;
- in_grace = 1;
+ locks_start_grace(&nfsd4_manager);
printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
grace_time/HZ);
laundry_wq = create_singlethread_workqueue("nfsd4");
return;
}
-int
-nfs4_in_grace(void)
-{
- return in_grace;
-}
-
time_t
nfs4_lease_time(void)
{
int (*fl_change)(struct file_lock **, int);
};
+struct lock_manager {
+ struct list_head list;
+};
+
+void locks_start_grace(struct lock_manager *);
+void locks_end_grace(struct lock_manager *);
+int locks_in_grace(void);
+
/* that will die - we need it for nfs_lock_info */
#include <linux/nfs_fs_i.h>
struct nfs_fh *,
struct file **);
void (*fclose)(struct file *);
- unsigned long (*get_grace_period)(void);
};
extern struct nlmsvc_binding * nlmsvc_ops;
extern int lockd_up(int proto);
extern void lockd_down(void);
-unsigned long get_nfs_grace_period(void);
-
-#ifdef CONFIG_NFSD_V4
-unsigned long get_nfs4_grace_period(void);
-#else
-static inline unsigned long get_nfs4_grace_period(void) {return 0;}
-#endif
-
#endif /* LINUX_LOCKD_BIND_H */