/* Globals */
static time_t lease_time = 90; /* default lease time */
-static time_t old_lease_time = 90; /* past incarnation lease time */
-static u32 nfs4_reclaim_init = 0;
+static time_t user_lease_time = 90;
time_t boot_time;
static time_t grace_end = 0;
static u32 current_clientid = 1;
*/
/* recall_lock protects the del_recall_lru */
-spinlock_t recall_lock;
+spinlock_t recall_lock = SPIN_LOCK_UNLOCKED;
static struct list_head del_recall_lru;
static void
int status, flag = 0;
flag = NFS4_OPEN_DELEGATE_NONE;
- if (open->op_claim_type != NFS4_OPEN_CLAIM_NULL
- || !atomic_read(&cb->cb_set) || !sop->so_confirmed)
- goto out;
-
- if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
- flag = NFS4_OPEN_DELEGATE_WRITE;
- else
- flag = NFS4_OPEN_DELEGATE_READ;
+ open->op_recall = 0;
+ switch (open->op_claim_type) {
+ case NFS4_OPEN_CLAIM_PREVIOUS:
+ if (!atomic_read(&cb->cb_set))
+ open->op_recall = 1;
+ flag = open->op_delegate_type;
+ if (flag == NFS4_OPEN_DELEGATE_NONE)
+ goto out;
+ break;
+ 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())
+ goto out;
+ if (!atomic_read(&cb->cb_set) || !sop->so_confirmed)
+ goto out;
+ if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
+ flag = NFS4_OPEN_DELEGATE_WRITE;
+ else
+ flag = NFS4_OPEN_DELEGATE_READ;
+ break;
+ default:
+ goto out;
+ }
dp = alloc_init_deleg(sop->so_client, stp, fh, flag);
if (dp == NULL) {
dp->dl_stateid.si_fileid,
dp->dl_stateid.si_generation);
out:
+ if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
+ && flag == NFS4_OPEN_DELEGATE_NONE
+ && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
+ printk("NFSD: WARNING: refusing delegation reclaim\n");
open->op_delegate_type = flag;
}
return status;
}
+static struct workqueue_struct *laundry_wq;
static struct work_struct laundromat_work;
static void laundromat_main(void *);
static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
t = nfs4_laundromat();
dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
- schedule_delayed_work(&laundromat_work, t*HZ);
+ queue_delayed_work(laundry_wq, &laundromat_work, t*HZ);
}
/* search ownerid_hashtbl[] and close_lru for stateid owner
struct nfs4_client_reclaim *crp = NULL;
int i;
- BUG_ON(!nfs4_reclaim_init);
for (i = 0; i < CLIENT_HASH_SIZE; i++) {
while (!list_empty(&reclaim_str_hashtbl[i])) {
crp = list_entry(reclaim_str_hashtbl[i].next,
return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad;
}
+/* initialization to perform at module load time: */
-/*
- * Start and stop routines
- */
-
-static void
-__nfs4_state_init(void)
+void
+nfs4_state_init(void)
{
int i;
- time_t grace_time;
- if (!nfs4_reclaim_init) {
- for (i = 0; i < CLIENT_HASH_SIZE; i++)
- INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
- reclaim_str_hashtbl_size = 0;
- nfs4_reclaim_init = 1;
- }
for (i = 0; i < CLIENT_HASH_SIZE; i++) {
INIT_LIST_HEAD(&conf_id_hashtbl[i]);
INIT_LIST_HEAD(&conf_str_hashtbl[i]);
INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]);
INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]);
}
- memset(&zerostateid, 0, sizeof(stateid_t));
memset(&onestateid, ~0, sizeof(stateid_t));
-
INIT_LIST_HEAD(&close_lru);
INIT_LIST_HEAD(&client_lru);
INIT_LIST_HEAD(&del_recall_lru);
- spin_lock_init(&recall_lock);
+ for (i = 0; i < CLIENT_HASH_SIZE; i++)
+ INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
+ reclaim_str_hashtbl_size = 0;
+}
+
+/* initialization to perform when the nfsd service is started: */
+
+static void
+__nfs4_state_start(void)
+{
+ time_t grace_time;
+
boot_time = get_seconds();
- grace_time = max(old_lease_time, lease_time);
- if (reclaim_str_hashtbl_size == 0)
- grace_time = 0;
- if (grace_time)
- printk("NFSD: starting %ld-second grace period\n", grace_time);
+ grace_time = max(user_lease_time, lease_time);
+ lease_time = user_lease_time;
+ printk("NFSD: starting %ld-second grace period\n", grace_time);
grace_end = boot_time + grace_time;
- INIT_WORK(&laundromat_work,laundromat_main, NULL);
- schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ);
+ laundry_wq = create_singlethread_workqueue("nfsd4");
+ queue_delayed_work(laundry_wq, &laundromat_work, NFSD_LEASE_TIME*HZ);
}
int
-nfs4_state_init(void)
+nfs4_state_start(void)
{
int status;
status = nfsd4_init_slabs();
if (status)
return status;
- __nfs4_state_init();
+ __nfs4_state_start();
nfs4_init = 1;
return 0;
}
}
cancel_delayed_work(&laundromat_work);
- flush_scheduled_work();
+ flush_workqueue(laundry_wq);
+ destroy_workqueue(laundry_wq);
nfs4_init = 0;
}
/*
* Called when leasetime is changed.
*
- * if nfsd is not started, simply set the global lease.
- *
- * if nfsd(s) are running, lease change requires nfsv4 state to be reset.
- * e.g: boot_time is reset, existing nfs4_client structs are
- * used to fill reclaim_str_hashtbl, then all state (except for the
- * reclaim_str_hashtbl) is re-initialized.
- *
- * if the old lease time is greater than the new lease time, the grace
- * period needs to be set to the old lease time to allow clients to reclaim
- * their state. XXX - we may want to set the grace period == lease time
- * after an initial grace period == old lease time
- *
- * if an error occurs in this process, the new lease is set, but the server
- * will not honor OPEN or LOCK reclaims, and will return nfserr_no_grace
- * which means OPEN/LOCK/READ/WRITE will fail during grace period.
- *
- * clients will attempt to reset all state with SETCLIENTID/CONFIRM, and
- * OPEN and LOCK reclaims.
+ * The only way the protocol gives us to handle on-the-fly lease changes is to
+ * simulate a reboot. Instead of doing that, we just wait till the next time
+ * we start to register any changes in lease time. If the administrator
+ * really wants to change the lease time *now*, they can go ahead and bring
+ * nfsd down and then back up again after changing the lease time.
*/
void
nfs4_reset_lease(time_t leasetime)
{
- struct nfs4_client *clp;
- int i;
-
- printk("NFSD: New leasetime %ld\n",leasetime);
- if (!nfs4_init)
- return;
- nfs4_lock_state();
- old_lease_time = lease_time;
- lease_time = leasetime;
-
- nfs4_release_reclaim();
-
- /* populate reclaim_str_hashtbl with current confirmed nfs4_clientid */
- for (i = 0; i < CLIENT_HASH_SIZE; i++) {
- list_for_each_entry(clp, &conf_id_hashtbl[i], cl_idhash) {
- if (!nfs4_client_to_reclaim(clp->cl_name.data,
- clp->cl_name.len)) {
- nfs4_release_reclaim();
- goto init_state;
- }
- }
- }
-init_state:
- __nfs4_state_shutdown();
- __nfs4_state_init();
- nfs4_unlock_state();
+ lock_kernel();
+ user_lease_time = leasetime;
+ unlock_kernel();
}
-