diff -ru linux-2.6.24.2/fs/nfsd/export.c linux-2.6.24.2-nfs.suspend/fs/nfsd/export.c --- linux-2.6.24.2/fs/nfsd/export.c 2008-02-10 21:51:11.000000000 -0800 +++ linux-2.6.24.2-nfs.suspend/fs/nfsd/export.c 2008-02-13 12:55:17.000000000 -0800 @@ -921,7 +921,7 @@ down_read(&hash_sem); } -static inline void +void exp_writelock(void) { down_write(&hash_sem); @@ -933,7 +933,7 @@ up_read(&hash_sem); } -static inline void +void exp_writeunlock(void) { up_write(&hash_sem); @@ -1635,6 +1635,17 @@ } /* + * 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 Only in linux-2.6.24.2-nfs.suspend/fs/nfsd: export.c.orig diff -ru linux-2.6.24.2/fs/nfsd/nfsctl.c linux-2.6.24.2-nfs.suspend/fs/nfsd/nfsctl.c --- linux-2.6.24.2/fs/nfsd/nfsctl.c 2008-02-10 21:51:11.000000000 -0800 +++ linux-2.6.24.2-nfs.suspend/fs/nfsd/nfsctl.c 2008-02-13 12:55:17.000000000 -0800 @@ -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 @@ 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 @@ .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 @@ [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 -ru linux-2.6.24.2/include/linux/nfsd/export.h linux-2.6.24.2-nfs.suspend/include/linux/nfsd/export.h --- linux-2.6.24.2/include/linux/nfsd/export.h 2008-02-10 21:51:11.000000000 -0800 +++ linux-2.6.24.2-nfs.suspend/include/linux/nfsd/export.h 2008-02-13 12:55:17.000000000 -0800 @@ -125,6 +125,9 @@ 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 * rqst_exp_get_by_name(struct svc_rqst *, Only in linux-2.6.24.2-nfs.suspend/include/linux/nfsd: export.h.orig