On Thu, 2011-03-10 at 12:30 -0500, Chuck Lever wrote: > diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c > index e6742b5..a788ec9 100644 > --- a/fs/nfs/nfs4state.c > +++ b/fs/nfs/nfs4state.c > @@ -56,6 +56,8 @@ > #include "internal.h" > #include "pnfs.h" > > +#define NFSDBG_FACILITY NFSDBG_CLIENT > + > #define OPENOWNER_POOL_SIZE 8 > > const nfs4_stateid zero_stateid; > @@ -1013,9 +1015,33 @@ void nfs4_schedule_state_recovery(struct nfs_client *clp) > { > if (!clp) > return; > + dprintk("--> %s: \"%s\" (client ID %llx)\n", > + __func__, clp->cl_hostname, clp->cl_clientid); > if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) > set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); > nfs4_schedule_state_manager(clp); > + dprintk("<-- %s\n", __func__); > +} > + > +/** > + * nfs4_schedule_migration_recovery - start background migration recovery > + * > + * @server: nfs_server representing remote file system that is migrating > + * > + */ > +void nfs4_schedule_migration_recovery(struct nfs_server *server) > +{ > + struct nfs_client *clp = server->nfs_client; > + > + dprintk("--> %s(%llx:%llx)\n", __func__, > + (unsigned long long)server->fsid.major, > + (unsigned long long)server->fsid.minor); > + if (test_and_set_bit(NFS4CLNT_MOVED, &clp->cl_state) == 0) { > + set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); Hmm... Why do we need to reset the NFSv4.1 session here? > + clp->cl_moved_server = server; > + nfs4_schedule_state_manager(clp); > + } > + dprintk("<-- %s\n", __func__); > } > > int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) > @@ -1435,6 +1461,64 @@ static int nfs4_reclaim_lease(struct nfs_client *clp) > return status; > } > > +/* > + * Try remote migration of one FSID from a source server to a > + * destination server. The source server provides a list of > + * potential destinations. > + */ > +static void nfs4_try_migration(struct nfs_server *server) > +{ > + struct nfs_client *clp = server->nfs_client; > + struct nfs4_fs_locations *locations = NULL; > + struct page *page; > + int status; > + > + dprintk("--> %s: FSID %llx:%llx on \"%s\"\n", __func__, > + (unsigned long long)server->fsid.major, > + (unsigned long long)server->fsid.minor, > + clp->cl_hostname); > + > + status = -ENOMEM; > + page = alloc_page(GFP_KERNEL); > + locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL); > + if (page == NULL || locations == NULL) { > + dprintk("<-- %s: no memory\n", __func__); > + goto out; > + } > + > + status = nfs4_proc_get_mig_status(server, locations, page); > + if (status != 0) { > + dprintk("<-- %s: get migration status: %d\n", > + __func__, status); > + goto out; > + } > + if (!(locations->fattr.valid & NFS_ATTR_FATTR_V4_LOCATIONS)) { > + dprintk("<-- %s: No fs_locations data available, " > + "migration skipped\n", __func__); > + goto out; > + } > + > + status = nfs4_replace_transport(server, locations); > + if (status != 0) { > + dprintk("<-- %s: failed to replace transport: %d\n", > + __func__, status); > + goto out; > + } > + > + /* Force an update of our callback info on the destination server */ > + set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); I wonder if this should be made into a separate flag. That would enable us to reuse it for the NFS4ERR_CB_PATH_DOWN handling... > + > + /* XXX: would like to update /proc/mounts, but that's entirely > + * optional. */ > + > + dprintk("<-- %s: migration succeeded\n", __func__); > + > +out: > + if (page != NULL) > + __free_page(page); > + kfree(locations); > +} > + > #ifdef CONFIG_NFS_V4_1 > void nfs41_handle_recall_slot(struct nfs_client *clp) > { > @@ -1664,6 +1748,10 @@ static void nfs4_state_manager(struct nfs_client *clp) -- Trond Myklebust Linux NFS client maintainer NetApp Trond.Myklebust@xxxxxxxxxx www.netapp.com -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html