diff -rup 2.6.17-rc6-dd.nfsclean/fs/nfsd/export.c 2.6.17-rc6-dd/fs/nfsd/export.c --- 2.6.17-rc6-dd.nfsclean/fs/nfsd/export.c 2006-11-20 13:01:00.000000000 -0800 +++ 2.6.17-rc6-dd/fs/nfsd/export.c 2006-11-20 13:41:55.000000000 -0800 @@ -820,7 +820,7 @@ exp_readlock(void) down_read(&hash_sem); } -static inline void +void exp_writelock(void) { down_write(&hash_sem); @@ -832,7 +832,7 @@ exp_readunlock(void) up_read(&hash_sem); } -static inline void +void exp_writeunlock(void) { up_write(&hash_sem); @@ -1375,6 +1375,17 @@ exp_verify_string(char *cp, int max) } /* + * Flush exports table without calling RW semaphore. + * The caller is required to lock and unlock the export table. + */ +void +export_purge(void) +{ + cache_purge(&svc_expkey_cache); + cache_purge(&svc_export_cache); +} + +/* * Initialize the exports module. */ void diff -rup 2.6.17-rc6-dd.nfsclean/fs/nfsd/nfsctl.c 2.6.17-rc6-dd/fs/nfsd/nfsctl.c --- 2.6.17-rc6-dd.nfsclean/fs/nfsd/nfsctl.c 2006-11-20 13:01:00.000000000 -0800 +++ 2.6.17-rc6-dd/fs/nfsd/nfsctl.c 2006-11-20 18:29:07.000000000 -0800 @@ -39,7 +39,7 @@ unsigned int nfsd_versbits = ~0; /* - * We have a single directory with 9 nodes in it. + * We have a single directory with several nodes in it. */ enum { NFSD_Root = 1, @@ -54,6 +54,7 @@ enum { NFSD_Fh, NFSD_Threads, NFSD_Versions, + NFSD_Suspend, /* * The below MUST come last. Otherwise we leave a hole in nfsd_files[] * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops @@ -140,6 +141,26 @@ static const struct file_operations tran .release = simple_transaction_release, }; +static ssize_t nfsctl_suspend_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) +{ + printk("Suspending NFS transactions!\n"); + exp_writelock(); + export_purge(); + return size; +} + +static ssize_t nfsctl_suspend_read(struct file *file, char __user *buf, size_t size, loff_t *pos) +{ + printk("Resuming NFS transactions!\n"); + exp_writeunlock(); + return 0; +} + +static struct file_operations suspend_ops = { + .write = nfsctl_suspend_write, + .read = nfsctl_suspend_read, +}; + extern struct seq_operations nfs_exports_op; static int exports_open(struct inode *inode, struct file *file) { @@ -485,6 +506,7 @@ static int nfsd_fill_super(struct super_ [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, + [NFSD_Suspend] = {"suspend", &suspend_ops, S_IWUSR|S_IRUSR}, #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, diff -rup 2.6.17-rc6-dd.nfsclean/include/linux/nfsd/export.h 2.6.17-rc6-dd/include/linux/nfsd/export.h --- 2.6.17-rc6-dd.nfsclean/include/linux/nfsd/export.h 2006-11-20 13:01:13.000000000 -0800 +++ 2.6.17-rc6-dd/include/linux/nfsd/export.h 2006-11-20 13:38:13.000000000 -0800 @@ -87,6 +87,9 @@ struct svc_expkey { void nfsd_export_init(void); void nfsd_export_shutdown(void); void nfsd_export_flush(void); +void export_purge(void); +void exp_writelock(void); +void exp_writeunlock(void); void exp_readlock(void); void exp_readunlock(void); struct svc_export * exp_get_by_name(struct auth_domain *clp,