NFSv4: Add nfs4_state_recovery_ops We want to reuse the same code to recover the NFSv4 state after a server reboot, a network partition, or a failover situation. Add a structure to contain those operations will that depend on the recovery scenario under consideration. Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 9 +++++++-- fs/nfs/nfs4state.c | 14 ++++++++------ include/linux/nfs_fs.h | 9 +++++++-- 3 files changed, 22 insertions(+), 10 deletions(-) Index: linux-2.6.11/fs/nfs/nfs4proc.c =================================================================== --- linux-2.6.11.orig/fs/nfs/nfs4proc.c +++ linux-2.6.11/fs/nfs/nfs4proc.c @@ -263,7 +263,7 @@ static int _nfs4_open_reclaim(struct nfs return status; } -int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state) +static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state) { struct nfs_server *server = NFS_SERVER(state->inode); struct nfs4_exception exception = { }; @@ -2558,7 +2558,7 @@ static int _nfs4_do_setlk(struct nfs4_st return status; } -int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request) +static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request) { return _nfs4_do_setlk(state, F_SETLK, request, 1); } @@ -2632,6 +2632,11 @@ nfs4_proc_lock(struct file *filp, int cm return status; } +struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { + .recover_open = nfs4_open_reclaim, + .recover_lock = nfs4_lock_reclaim, +}; + struct nfs_rpc_ops nfs_v4_clientops = { .version = 4, /* protocol version */ .dentry_ops = &nfs4_dentry_operations, Index: linux-2.6.11/include/linux/nfs_fs.h =================================================================== --- linux-2.6.11.orig/include/linux/nfs_fs.h +++ linux-2.6.11/include/linux/nfs_fs.h @@ -673,6 +673,11 @@ struct nfs4_exception { int retry; }; +struct nfs4_state_recovery_ops { + int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *); + int (*recover_lock)(struct nfs4_state *, struct file_lock *); +}; + extern struct dentry_operations nfs4_dentry_operations; extern struct inode_operations nfs4_dir_inode_operations; @@ -680,13 +685,13 @@ extern struct inode_operations nfs4_dir_ extern int nfs4_map_errors(int err); extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short); extern int nfs4_proc_setclientid_confirm(struct nfs4_client *); -extern int nfs4_open_reclaim(struct nfs4_state_owner *, struct nfs4_state *); extern int nfs4_proc_async_renew(struct nfs4_client *); extern int nfs4_proc_renew(struct nfs4_client *); extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode); extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); extern int nfs4_open_revalidate(struct inode *, struct dentry *, int); -extern int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request); + +extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; /* nfs4renewd.c */ extern void nfs4_schedule_state_renewal(struct nfs4_client *); Index: linux-2.6.11/fs/nfs/nfs4state.c =================================================================== --- linux-2.6.11.orig/fs/nfs/nfs4state.c +++ linux-2.6.11/fs/nfs/nfs4state.c @@ -765,7 +765,7 @@ nfs4_schedule_state_recovery(struct nfs4 schedule_work(&clp->cl_recoverd); } -static int nfs4_reclaim_locks(struct nfs4_state *state) +static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_state *state) { struct inode *inode = state->inode; struct file_lock *fl; @@ -776,7 +776,7 @@ static int nfs4_reclaim_locks(struct nfs continue; if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state) continue; - status = nfs4_lock_reclaim(state, fl); + status = ops->recover_lock(state, fl); if (status >= 0) continue; switch (status) { @@ -798,7 +798,7 @@ out_err: return status; } -static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp) +static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct nfs4_state_owner *sp) { struct nfs4_state *state; struct nfs4_lock_state *lock; @@ -815,11 +815,11 @@ static int nfs4_reclaim_open_state(struc list_for_each_entry(state, &sp->so_states, open_states) { if (state->state == 0) continue; - status = nfs4_open_reclaim(sp, state); + status = ops->recover_open(sp, state); list_for_each_entry(lock, &state->lock_states, ls_locks) lock->ls_flags &= ~NFS_LOCK_INITIALIZED; if (status >= 0) { - status = nfs4_reclaim_locks(state); + status = nfs4_reclaim_locks(ops, state); if (status < 0) goto out_err; list_for_each_entry(lock, &state->lock_states, ls_locks) { @@ -860,6 +860,7 @@ static int reclaimer(void *ptr) struct reclaimer_args *args = (struct reclaimer_args *)ptr; struct nfs4_client *clp = args->clp; struct nfs4_state_owner *sp; + struct nfs4_state_recovery_ops *ops; int status = 0; daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr)); @@ -878,6 +879,7 @@ restart_loop: status = nfs4_proc_renew(clp); if (status == 0 || status == -NFS4ERR_CB_PATH_DOWN) goto out; + ops = &nfs4_reboot_recovery_ops; status = __nfs4_init_client(clp); if (status) goto out_error; @@ -885,7 +887,7 @@ restart_loop: nfs_delegation_mark_reclaim(clp); /* Note: list is protected by exclusive lock on cl->cl_sem */ list_for_each_entry(sp, &clp->cl_state_owners, so_list) { - status = nfs4_reclaim_open_state(sp); + status = nfs4_reclaim_open_state(ops, sp); if (status < 0) { if (status == -NFS4ERR_STALE_CLIENTID) goto restart_loop;