diff -urpN linux-2.6.23.8-clean/fs/nfsd/export.c linux-2.6.23.8-patched/fs/nfsd/export.c --- linux-2.6.23.8-clean/fs/nfsd/export.c 2007-10-12 11:43:44.000000000 -0500 +++ linux-2.6.23.8-patched/fs/nfsd/export.c 2007-11-21 11:45:45.000000000 -0600 @@ -923,7 +923,7 @@ exp_readlock(void) down_read(&hash_sem); } -static inline void +void exp_writelock(void) { down_write(&hash_sem); @@ -935,7 +935,7 @@ exp_readunlock(void) up_read(&hash_sem); } -static inline void +void exp_writeunlock(void) { up_write(&hash_sem); @@ -1638,6 +1638,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 -urpN linux-2.6.23.8-clean/fs/nfsd/nfsctl.c linux-2.6.23.8-patched/fs/nfsd/nfsctl.c --- linux-2.6.23.8-clean/fs/nfsd/nfsctl.c 2007-10-12 11:43:44.000000000 -0500 +++ linux-2.6.23.8-patched/fs/nfsd/nfsctl.c 2007-11-21 11:45:45.000000000 -0600 @@ -39,7 +39,7 @@ #include /* - * We have a single directory with 9 nodes in it. + * We have a single directory with several nodes in it. */ enum { NFSD_Root = 1, @@ -57,6 +57,7 @@ enum { NFSD_Versions, NFSD_Ports, NFSD_MaxBlkSize, + 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 @@ -149,6 +150,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) { @@ -652,6 +673,7 @@ static int nfsd_fill_super(struct super_ [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, + [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 -urpN linux-2.6.23.8-clean/include/linux/nfsd/export.h linux-2.6.23.8-patched/include/linux/nfsd/export.h --- linux-2.6.23.8-clean/include/linux/nfsd/export.h 2007-10-12 11:43:44.000000000 -0500 +++ linux-2.6.23.8-patched/include/linux/nfsd/export.h 2007-11-21 11:45:45.000000000 -0600 @@ -125,6 +125,9 @@ __be32 check_nfsd_access(struct svc_expo 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,