diff options
author | J. Bruce Fields <bfields@citi.umich.edu> | 2009-08-21 11:27:29 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-08-21 11:27:29 -0400 |
commit | e9dc122166b8d863d3057a66ada04838e5548e52 (patch) | |
tree | 749e15bf719b64bf9113db7acd8e043d9742cb26 /net/sunrpc/cache.c | |
parent | 560ab42ef923aaf2e4347315bdfcc74b2708972c (diff) | |
parent | 405d8f8b1d936414da2093d4149ff790ff3f84a5 (diff) |
Merge branch 'nfs-for-2.6.32' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6 into for-2.6.32-incoming
Conflicts:
net/sunrpc/cache.c
Diffstat (limited to 'net/sunrpc/cache.c')
-rw-r--r-- | net/sunrpc/cache.c | 622 |
1 files changed, 473 insertions, 149 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index bbd31f1215e7..ade8a7e99cd3 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -27,10 +27,12 @@ | |||
27 | #include <linux/net.h> | 27 | #include <linux/net.h> |
28 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
29 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
30 | #include <linux/pagemap.h> | ||
30 | #include <asm/ioctls.h> | 31 | #include <asm/ioctls.h> |
31 | #include <linux/sunrpc/types.h> | 32 | #include <linux/sunrpc/types.h> |
32 | #include <linux/sunrpc/cache.h> | 33 | #include <linux/sunrpc/cache.h> |
33 | #include <linux/sunrpc/stats.h> | 34 | #include <linux/sunrpc/stats.h> |
35 | #include <linux/sunrpc/rpc_pipe_fs.h> | ||
34 | 36 | ||
35 | #define RPCDBG_FACILITY RPCDBG_CACHE | 37 | #define RPCDBG_FACILITY RPCDBG_CACHE |
36 | 38 | ||
@@ -175,7 +177,12 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail, | |||
175 | } | 177 | } |
176 | EXPORT_SYMBOL_GPL(sunrpc_cache_update); | 178 | EXPORT_SYMBOL_GPL(sunrpc_cache_update); |
177 | 179 | ||
178 | static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h); | 180 | static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h) |
181 | { | ||
182 | if (!cd->cache_upcall) | ||
183 | return -EINVAL; | ||
184 | return cd->cache_upcall(cd, h); | ||
185 | } | ||
179 | 186 | ||
180 | static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) | 187 | static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) |
181 | { | 188 | { |
@@ -192,6 +199,7 @@ static inline int cache_is_valid(struct cache_detail *detail, struct cache_head | |||
192 | return 0; | 199 | return 0; |
193 | } | 200 | } |
194 | } | 201 | } |
202 | |||
195 | /* | 203 | /* |
196 | * This is the generic cache management routine for all | 204 | * This is the generic cache management routine for all |
197 | * the authentication caches. | 205 | * the authentication caches. |
@@ -297,76 +305,11 @@ static DEFINE_SPINLOCK(cache_list_lock); | |||
297 | static struct cache_detail *current_detail; | 305 | static struct cache_detail *current_detail; |
298 | static int current_index; | 306 | static int current_index; |
299 | 307 | ||
300 | static const struct file_operations cache_file_operations; | ||
301 | static const struct file_operations content_file_operations; | ||
302 | static const struct file_operations cache_flush_operations; | ||
303 | |||
304 | static void do_cache_clean(struct work_struct *work); | 308 | static void do_cache_clean(struct work_struct *work); |
305 | static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean); | 309 | static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean); |
306 | 310 | ||
307 | static void remove_cache_proc_entries(struct cache_detail *cd) | 311 | static void sunrpc_init_cache_detail(struct cache_detail *cd) |
308 | { | ||
309 | if (cd->proc_ent == NULL) | ||
310 | return; | ||
311 | if (cd->flush_ent) | ||
312 | remove_proc_entry("flush", cd->proc_ent); | ||
313 | if (cd->channel_ent) | ||
314 | remove_proc_entry("channel", cd->proc_ent); | ||
315 | if (cd->content_ent) | ||
316 | remove_proc_entry("content", cd->proc_ent); | ||
317 | cd->proc_ent = NULL; | ||
318 | remove_proc_entry(cd->name, proc_net_rpc); | ||
319 | } | ||
320 | |||
321 | #ifdef CONFIG_PROC_FS | ||
322 | static int create_cache_proc_entries(struct cache_detail *cd) | ||
323 | { | ||
324 | struct proc_dir_entry *p; | ||
325 | |||
326 | cd->proc_ent = proc_mkdir(cd->name, proc_net_rpc); | ||
327 | if (cd->proc_ent == NULL) | ||
328 | goto out_nomem; | ||
329 | cd->channel_ent = cd->content_ent = NULL; | ||
330 | |||
331 | p = proc_create_data("flush", S_IFREG|S_IRUSR|S_IWUSR, | ||
332 | cd->proc_ent, &cache_flush_operations, cd); | ||
333 | cd->flush_ent = p; | ||
334 | if (p == NULL) | ||
335 | goto out_nomem; | ||
336 | |||
337 | if (cd->cache_request || cd->cache_parse) { | ||
338 | p = proc_create_data("channel", S_IFREG|S_IRUSR|S_IWUSR, | ||
339 | cd->proc_ent, &cache_file_operations, cd); | ||
340 | cd->channel_ent = p; | ||
341 | if (p == NULL) | ||
342 | goto out_nomem; | ||
343 | } | ||
344 | if (cd->cache_show) { | ||
345 | p = proc_create_data("content", S_IFREG|S_IRUSR|S_IWUSR, | ||
346 | cd->proc_ent, &content_file_operations, cd); | ||
347 | cd->content_ent = p; | ||
348 | if (p == NULL) | ||
349 | goto out_nomem; | ||
350 | } | ||
351 | return 0; | ||
352 | out_nomem: | ||
353 | remove_cache_proc_entries(cd); | ||
354 | return -ENOMEM; | ||
355 | } | ||
356 | #else /* CONFIG_PROC_FS */ | ||
357 | static int create_cache_proc_entries(struct cache_detail *cd) | ||
358 | { | ||
359 | return 0; | ||
360 | } | ||
361 | #endif | ||
362 | |||
363 | int cache_register(struct cache_detail *cd) | ||
364 | { | 312 | { |
365 | int ret; | ||
366 | |||
367 | ret = create_cache_proc_entries(cd); | ||
368 | if (ret) | ||
369 | return ret; | ||
370 | rwlock_init(&cd->hash_lock); | 313 | rwlock_init(&cd->hash_lock); |
371 | INIT_LIST_HEAD(&cd->queue); | 314 | INIT_LIST_HEAD(&cd->queue); |
372 | spin_lock(&cache_list_lock); | 315 | spin_lock(&cache_list_lock); |
@@ -380,11 +323,9 @@ int cache_register(struct cache_detail *cd) | |||
380 | 323 | ||
381 | /* start the cleaning process */ | 324 | /* start the cleaning process */ |
382 | schedule_delayed_work(&cache_cleaner, 0); | 325 | schedule_delayed_work(&cache_cleaner, 0); |
383 | return 0; | ||
384 | } | 326 | } |
385 | EXPORT_SYMBOL_GPL(cache_register); | ||
386 | 327 | ||
387 | void cache_unregister(struct cache_detail *cd) | 328 | static void sunrpc_destroy_cache_detail(struct cache_detail *cd) |
388 | { | 329 | { |
389 | cache_purge(cd); | 330 | cache_purge(cd); |
390 | spin_lock(&cache_list_lock); | 331 | spin_lock(&cache_list_lock); |
@@ -399,7 +340,6 @@ void cache_unregister(struct cache_detail *cd) | |||
399 | list_del_init(&cd->others); | 340 | list_del_init(&cd->others); |
400 | write_unlock(&cd->hash_lock); | 341 | write_unlock(&cd->hash_lock); |
401 | spin_unlock(&cache_list_lock); | 342 | spin_unlock(&cache_list_lock); |
402 | remove_cache_proc_entries(cd); | ||
403 | if (list_empty(&cache_list)) { | 343 | if (list_empty(&cache_list)) { |
404 | /* module must be being unloaded so its safe to kill the worker */ | 344 | /* module must be being unloaded so its safe to kill the worker */ |
405 | cancel_delayed_work_sync(&cache_cleaner); | 345 | cancel_delayed_work_sync(&cache_cleaner); |
@@ -408,7 +348,6 @@ void cache_unregister(struct cache_detail *cd) | |||
408 | out: | 348 | out: |
409 | printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); | 349 | printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); |
410 | } | 350 | } |
411 | EXPORT_SYMBOL_GPL(cache_unregister); | ||
412 | 351 | ||
413 | /* clean cache tries to find something to clean | 352 | /* clean cache tries to find something to clean |
414 | * and cleans it. | 353 | * and cleans it. |
@@ -703,18 +642,18 @@ struct cache_reader { | |||
703 | int offset; /* if non-0, we have a refcnt on next request */ | 642 | int offset; /* if non-0, we have a refcnt on next request */ |
704 | }; | 643 | }; |
705 | 644 | ||
706 | static ssize_t | 645 | static ssize_t cache_read(struct file *filp, char __user *buf, size_t count, |
707 | cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) | 646 | loff_t *ppos, struct cache_detail *cd) |
708 | { | 647 | { |
709 | struct cache_reader *rp = filp->private_data; | 648 | struct cache_reader *rp = filp->private_data; |
710 | struct cache_request *rq; | 649 | struct cache_request *rq; |
711 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; | 650 | struct inode *inode = filp->f_path.dentry->d_inode; |
712 | int err; | 651 | int err; |
713 | 652 | ||
714 | if (count == 0) | 653 | if (count == 0) |
715 | return 0; | 654 | return 0; |
716 | 655 | ||
717 | mutex_lock(&queue_io_mutex); /* protect against multiple concurrent | 656 | mutex_lock(&inode->i_mutex); /* protect against multiple concurrent |
718 | * readers on this file */ | 657 | * readers on this file */ |
719 | again: | 658 | again: |
720 | spin_lock(&queue_lock); | 659 | spin_lock(&queue_lock); |
@@ -727,7 +666,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) | |||
727 | } | 666 | } |
728 | if (rp->q.list.next == &cd->queue) { | 667 | if (rp->q.list.next == &cd->queue) { |
729 | spin_unlock(&queue_lock); | 668 | spin_unlock(&queue_lock); |
730 | mutex_unlock(&queue_io_mutex); | 669 | mutex_unlock(&inode->i_mutex); |
731 | BUG_ON(rp->offset); | 670 | BUG_ON(rp->offset); |
732 | return 0; | 671 | return 0; |
733 | } | 672 | } |
@@ -774,49 +713,90 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) | |||
774 | } | 713 | } |
775 | if (err == -EAGAIN) | 714 | if (err == -EAGAIN) |
776 | goto again; | 715 | goto again; |
777 | mutex_unlock(&queue_io_mutex); | 716 | mutex_unlock(&inode->i_mutex); |
778 | return err ? err : count; | 717 | return err ? err : count; |
779 | } | 718 | } |
780 | 719 | ||
781 | static char write_buf[8192]; /* protected by queue_io_mutex */ | 720 | static ssize_t cache_do_downcall(char *kaddr, const char __user *buf, |
721 | size_t count, struct cache_detail *cd) | ||
722 | { | ||
723 | ssize_t ret; | ||
782 | 724 | ||
783 | static ssize_t | 725 | if (copy_from_user(kaddr, buf, count)) |
784 | cache_write(struct file *filp, const char __user *buf, size_t count, | 726 | return -EFAULT; |
785 | loff_t *ppos) | 727 | kaddr[count] = '\0'; |
728 | ret = cd->cache_parse(cd, kaddr, count); | ||
729 | if (!ret) | ||
730 | ret = count; | ||
731 | return ret; | ||
732 | } | ||
733 | |||
734 | static ssize_t cache_slow_downcall(const char __user *buf, | ||
735 | size_t count, struct cache_detail *cd) | ||
786 | { | 736 | { |
787 | int err; | 737 | static char write_buf[8192]; /* protected by queue_io_mutex */ |
788 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; | 738 | ssize_t ret = -EINVAL; |
789 | 739 | ||
790 | if (count == 0) | ||
791 | return 0; | ||
792 | if (count >= sizeof(write_buf)) | 740 | if (count >= sizeof(write_buf)) |
793 | return -EINVAL; | 741 | goto out; |
794 | |||
795 | mutex_lock(&queue_io_mutex); | 742 | mutex_lock(&queue_io_mutex); |
743 | ret = cache_do_downcall(write_buf, buf, count, cd); | ||
744 | mutex_unlock(&queue_io_mutex); | ||
745 | out: | ||
746 | return ret; | ||
747 | } | ||
796 | 748 | ||
797 | if (copy_from_user(write_buf, buf, count)) { | 749 | static ssize_t cache_downcall(struct address_space *mapping, |
798 | mutex_unlock(&queue_io_mutex); | 750 | const char __user *buf, |
799 | return -EFAULT; | 751 | size_t count, struct cache_detail *cd) |
800 | } | 752 | { |
801 | write_buf[count] = '\0'; | 753 | struct page *page; |
802 | if (cd->cache_parse) | 754 | char *kaddr; |
803 | err = cd->cache_parse(cd, write_buf, count); | 755 | ssize_t ret = -ENOMEM; |
804 | else | 756 | |
805 | err = -EINVAL; | 757 | if (count >= PAGE_CACHE_SIZE) |
758 | goto out_slow; | ||
759 | |||
760 | page = find_or_create_page(mapping, 0, GFP_KERNEL); | ||
761 | if (!page) | ||
762 | goto out_slow; | ||
763 | |||
764 | kaddr = kmap(page); | ||
765 | ret = cache_do_downcall(kaddr, buf, count, cd); | ||
766 | kunmap(page); | ||
767 | unlock_page(page); | ||
768 | page_cache_release(page); | ||
769 | return ret; | ||
770 | out_slow: | ||
771 | return cache_slow_downcall(buf, count, cd); | ||
772 | } | ||
806 | 773 | ||
807 | mutex_unlock(&queue_io_mutex); | 774 | static ssize_t cache_write(struct file *filp, const char __user *buf, |
808 | return err ? err : count; | 775 | size_t count, loff_t *ppos, |
776 | struct cache_detail *cd) | ||
777 | { | ||
778 | struct address_space *mapping = filp->f_mapping; | ||
779 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
780 | ssize_t ret = -EINVAL; | ||
781 | |||
782 | if (!cd->cache_parse) | ||
783 | goto out; | ||
784 | |||
785 | mutex_lock(&inode->i_mutex); | ||
786 | ret = cache_downcall(mapping, buf, count, cd); | ||
787 | mutex_unlock(&inode->i_mutex); | ||
788 | out: | ||
789 | return ret; | ||
809 | } | 790 | } |
810 | 791 | ||
811 | static DECLARE_WAIT_QUEUE_HEAD(queue_wait); | 792 | static DECLARE_WAIT_QUEUE_HEAD(queue_wait); |
812 | 793 | ||
813 | static unsigned int | 794 | static unsigned int cache_poll(struct file *filp, poll_table *wait, |
814 | cache_poll(struct file *filp, poll_table *wait) | 795 | struct cache_detail *cd) |
815 | { | 796 | { |
816 | unsigned int mask; | 797 | unsigned int mask; |
817 | struct cache_reader *rp = filp->private_data; | 798 | struct cache_reader *rp = filp->private_data; |
818 | struct cache_queue *cq; | 799 | struct cache_queue *cq; |
819 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; | ||
820 | 800 | ||
821 | poll_wait(filp, &queue_wait, wait); | 801 | poll_wait(filp, &queue_wait, wait); |
822 | 802 | ||
@@ -838,14 +818,13 @@ cache_poll(struct file *filp, poll_table *wait) | |||
838 | return mask; | 818 | return mask; |
839 | } | 819 | } |
840 | 820 | ||
841 | static int | 821 | static int cache_ioctl(struct inode *ino, struct file *filp, |
842 | cache_ioctl(struct inode *ino, struct file *filp, | 822 | unsigned int cmd, unsigned long arg, |
843 | unsigned int cmd, unsigned long arg) | 823 | struct cache_detail *cd) |
844 | { | 824 | { |
845 | int len = 0; | 825 | int len = 0; |
846 | struct cache_reader *rp = filp->private_data; | 826 | struct cache_reader *rp = filp->private_data; |
847 | struct cache_queue *cq; | 827 | struct cache_queue *cq; |
848 | struct cache_detail *cd = PDE(ino)->data; | ||
849 | 828 | ||
850 | if (cmd != FIONREAD || !rp) | 829 | if (cmd != FIONREAD || !rp) |
851 | return -EINVAL; | 830 | return -EINVAL; |
@@ -868,15 +847,15 @@ cache_ioctl(struct inode *ino, struct file *filp, | |||
868 | return put_user(len, (int __user *)arg); | 847 | return put_user(len, (int __user *)arg); |
869 | } | 848 | } |
870 | 849 | ||
871 | static int | 850 | static int cache_open(struct inode *inode, struct file *filp, |
872 | cache_open(struct inode *inode, struct file *filp) | 851 | struct cache_detail *cd) |
873 | { | 852 | { |
874 | struct cache_reader *rp = NULL; | 853 | struct cache_reader *rp = NULL; |
875 | 854 | ||
855 | if (!cd || !try_module_get(cd->owner)) | ||
856 | return -EACCES; | ||
876 | nonseekable_open(inode, filp); | 857 | nonseekable_open(inode, filp); |
877 | if (filp->f_mode & FMODE_READ) { | 858 | if (filp->f_mode & FMODE_READ) { |
878 | struct cache_detail *cd = PDE(inode)->data; | ||
879 | |||
880 | rp = kmalloc(sizeof(*rp), GFP_KERNEL); | 859 | rp = kmalloc(sizeof(*rp), GFP_KERNEL); |
881 | if (!rp) | 860 | if (!rp) |
882 | return -ENOMEM; | 861 | return -ENOMEM; |
@@ -891,11 +870,10 @@ cache_open(struct inode *inode, struct file *filp) | |||
891 | return 0; | 870 | return 0; |
892 | } | 871 | } |
893 | 872 | ||
894 | static int | 873 | static int cache_release(struct inode *inode, struct file *filp, |
895 | cache_release(struct inode *inode, struct file *filp) | 874 | struct cache_detail *cd) |
896 | { | 875 | { |
897 | struct cache_reader *rp = filp->private_data; | 876 | struct cache_reader *rp = filp->private_data; |
898 | struct cache_detail *cd = PDE(inode)->data; | ||
899 | 877 | ||
900 | if (rp) { | 878 | if (rp) { |
901 | spin_lock(&queue_lock); | 879 | spin_lock(&queue_lock); |
@@ -919,23 +897,12 @@ cache_release(struct inode *inode, struct file *filp) | |||
919 | cd->last_close = get_seconds(); | 897 | cd->last_close = get_seconds(); |
920 | atomic_dec(&cd->readers); | 898 | atomic_dec(&cd->readers); |
921 | } | 899 | } |
900 | module_put(cd->owner); | ||
922 | return 0; | 901 | return 0; |
923 | } | 902 | } |
924 | 903 | ||
925 | 904 | ||
926 | 905 | ||
927 | static const struct file_operations cache_file_operations = { | ||
928 | .owner = THIS_MODULE, | ||
929 | .llseek = no_llseek, | ||
930 | .read = cache_read, | ||
931 | .write = cache_write, | ||
932 | .poll = cache_poll, | ||
933 | .ioctl = cache_ioctl, /* for FIONREAD */ | ||
934 | .open = cache_open, | ||
935 | .release = cache_release, | ||
936 | }; | ||
937 | |||
938 | |||
939 | static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch) | 906 | static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch) |
940 | { | 907 | { |
941 | struct cache_queue *cq; | 908 | struct cache_queue *cq; |
@@ -1036,15 +1003,21 @@ static void warn_no_listener(struct cache_detail *detail) | |||
1036 | if (detail->last_warn != detail->last_close) { | 1003 | if (detail->last_warn != detail->last_close) { |
1037 | detail->last_warn = detail->last_close; | 1004 | detail->last_warn = detail->last_close; |
1038 | if (detail->warn_no_listener) | 1005 | if (detail->warn_no_listener) |
1039 | detail->warn_no_listener(detail); | 1006 | detail->warn_no_listener(detail, detail->last_close != 0); |
1040 | } | 1007 | } |
1041 | } | 1008 | } |
1042 | 1009 | ||
1043 | /* | 1010 | /* |
1044 | * register an upcall request to user-space. | 1011 | * register an upcall request to user-space and queue it up for read() by the |
1012 | * upcall daemon. | ||
1013 | * | ||
1045 | * Each request is at most one page long. | 1014 | * Each request is at most one page long. |
1046 | */ | 1015 | */ |
1047 | static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h) | 1016 | int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h, |
1017 | void (*cache_request)(struct cache_detail *, | ||
1018 | struct cache_head *, | ||
1019 | char **, | ||
1020 | int *)) | ||
1048 | { | 1021 | { |
1049 | 1022 | ||
1050 | char *buf; | 1023 | char *buf; |
@@ -1052,9 +1025,6 @@ static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h) | |||
1052 | char *bp; | 1025 | char *bp; |
1053 | int len; | 1026 | int len; |
1054 | 1027 | ||
1055 | if (detail->cache_request == NULL) | ||
1056 | return -EINVAL; | ||
1057 | |||
1058 | if (atomic_read(&detail->readers) == 0 && | 1028 | if (atomic_read(&detail->readers) == 0 && |
1059 | detail->last_close < get_seconds() - 30) { | 1029 | detail->last_close < get_seconds() - 30) { |
1060 | warn_no_listener(detail); | 1030 | warn_no_listener(detail); |
@@ -1073,7 +1043,7 @@ static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h) | |||
1073 | 1043 | ||
1074 | bp = buf; len = PAGE_SIZE; | 1044 | bp = buf; len = PAGE_SIZE; |
1075 | 1045 | ||
1076 | detail->cache_request(detail, h, &bp, &len); | 1046 | cache_request(detail, h, &bp, &len); |
1077 | 1047 | ||
1078 | if (len < 0) { | 1048 | if (len < 0) { |
1079 | kfree(buf); | 1049 | kfree(buf); |
@@ -1091,6 +1061,7 @@ static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h) | |||
1091 | wake_up(&queue_wait); | 1061 | wake_up(&queue_wait); |
1092 | return 0; | 1062 | return 0; |
1093 | } | 1063 | } |
1064 | EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall); | ||
1094 | 1065 | ||
1095 | /* | 1066 | /* |
1096 | * parse a message from user-space and pass it | 1067 | * parse a message from user-space and pass it |
@@ -1258,11 +1229,13 @@ static const struct seq_operations cache_content_op = { | |||
1258 | .show = c_show, | 1229 | .show = c_show, |
1259 | }; | 1230 | }; |
1260 | 1231 | ||
1261 | static int content_open(struct inode *inode, struct file *file) | 1232 | static int content_open(struct inode *inode, struct file *file, |
1233 | struct cache_detail *cd) | ||
1262 | { | 1234 | { |
1263 | struct handle *han; | 1235 | struct handle *han; |
1264 | struct cache_detail *cd = PDE(inode)->data; | ||
1265 | 1236 | ||
1237 | if (!cd || !try_module_get(cd->owner)) | ||
1238 | return -EACCES; | ||
1266 | han = __seq_open_private(file, &cache_content_op, sizeof(*han)); | 1239 | han = __seq_open_private(file, &cache_content_op, sizeof(*han)); |
1267 | if (han == NULL) | 1240 | if (han == NULL) |
1268 | return -ENOMEM; | 1241 | return -ENOMEM; |
@@ -1271,17 +1244,33 @@ static int content_open(struct inode *inode, struct file *file) | |||
1271 | return 0; | 1244 | return 0; |
1272 | } | 1245 | } |
1273 | 1246 | ||
1274 | static const struct file_operations content_file_operations = { | 1247 | static int content_release(struct inode *inode, struct file *file, |
1275 | .open = content_open, | 1248 | struct cache_detail *cd) |
1276 | .read = seq_read, | 1249 | { |
1277 | .llseek = seq_lseek, | 1250 | int ret = seq_release_private(inode, file); |
1278 | .release = seq_release_private, | 1251 | module_put(cd->owner); |
1279 | }; | 1252 | return ret; |
1253 | } | ||
1254 | |||
1255 | static int open_flush(struct inode *inode, struct file *file, | ||
1256 | struct cache_detail *cd) | ||
1257 | { | ||
1258 | if (!cd || !try_module_get(cd->owner)) | ||
1259 | return -EACCES; | ||
1260 | return nonseekable_open(inode, file); | ||
1261 | } | ||
1262 | |||
1263 | static int release_flush(struct inode *inode, struct file *file, | ||
1264 | struct cache_detail *cd) | ||
1265 | { | ||
1266 | module_put(cd->owner); | ||
1267 | return 0; | ||
1268 | } | ||
1280 | 1269 | ||
1281 | static ssize_t read_flush(struct file *file, char __user *buf, | 1270 | static ssize_t read_flush(struct file *file, char __user *buf, |
1282 | size_t count, loff_t *ppos) | 1271 | size_t count, loff_t *ppos, |
1272 | struct cache_detail *cd) | ||
1283 | { | 1273 | { |
1284 | struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data; | ||
1285 | char tbuf[20]; | 1274 | char tbuf[20]; |
1286 | unsigned long p = *ppos; | 1275 | unsigned long p = *ppos; |
1287 | size_t len; | 1276 | size_t len; |
@@ -1299,10 +1288,10 @@ static ssize_t read_flush(struct file *file, char __user *buf, | |||
1299 | return len; | 1288 | return len; |
1300 | } | 1289 | } |
1301 | 1290 | ||
1302 | static ssize_t write_flush(struct file * file, const char __user * buf, | 1291 | static ssize_t write_flush(struct file *file, const char __user *buf, |
1303 | size_t count, loff_t *ppos) | 1292 | size_t count, loff_t *ppos, |
1293 | struct cache_detail *cd) | ||
1304 | { | 1294 | { |
1305 | struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data; | ||
1306 | char tbuf[20]; | 1295 | char tbuf[20]; |
1307 | char *ep; | 1296 | char *ep; |
1308 | long flushtime; | 1297 | long flushtime; |
@@ -1323,8 +1312,343 @@ static ssize_t write_flush(struct file * file, const char __user * buf, | |||
1323 | return count; | 1312 | return count; |
1324 | } | 1313 | } |
1325 | 1314 | ||
1326 | static const struct file_operations cache_flush_operations = { | 1315 | static ssize_t cache_read_procfs(struct file *filp, char __user *buf, |
1327 | .open = nonseekable_open, | 1316 | size_t count, loff_t *ppos) |
1328 | .read = read_flush, | 1317 | { |
1329 | .write = write_flush, | 1318 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; |
1319 | |||
1320 | return cache_read(filp, buf, count, ppos, cd); | ||
1321 | } | ||
1322 | |||
1323 | static ssize_t cache_write_procfs(struct file *filp, const char __user *buf, | ||
1324 | size_t count, loff_t *ppos) | ||
1325 | { | ||
1326 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; | ||
1327 | |||
1328 | return cache_write(filp, buf, count, ppos, cd); | ||
1329 | } | ||
1330 | |||
1331 | static unsigned int cache_poll_procfs(struct file *filp, poll_table *wait) | ||
1332 | { | ||
1333 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; | ||
1334 | |||
1335 | return cache_poll(filp, wait, cd); | ||
1336 | } | ||
1337 | |||
1338 | static int cache_ioctl_procfs(struct inode *inode, struct file *filp, | ||
1339 | unsigned int cmd, unsigned long arg) | ||
1340 | { | ||
1341 | struct cache_detail *cd = PDE(inode)->data; | ||
1342 | |||
1343 | return cache_ioctl(inode, filp, cmd, arg, cd); | ||
1344 | } | ||
1345 | |||
1346 | static int cache_open_procfs(struct inode *inode, struct file *filp) | ||
1347 | { | ||
1348 | struct cache_detail *cd = PDE(inode)->data; | ||
1349 | |||
1350 | return cache_open(inode, filp, cd); | ||
1351 | } | ||
1352 | |||
1353 | static int cache_release_procfs(struct inode *inode, struct file *filp) | ||
1354 | { | ||
1355 | struct cache_detail *cd = PDE(inode)->data; | ||
1356 | |||
1357 | return cache_release(inode, filp, cd); | ||
1358 | } | ||
1359 | |||
1360 | static const struct file_operations cache_file_operations_procfs = { | ||
1361 | .owner = THIS_MODULE, | ||
1362 | .llseek = no_llseek, | ||
1363 | .read = cache_read_procfs, | ||
1364 | .write = cache_write_procfs, | ||
1365 | .poll = cache_poll_procfs, | ||
1366 | .ioctl = cache_ioctl_procfs, /* for FIONREAD */ | ||
1367 | .open = cache_open_procfs, | ||
1368 | .release = cache_release_procfs, | ||
1330 | }; | 1369 | }; |
1370 | |||
1371 | static int content_open_procfs(struct inode *inode, struct file *filp) | ||
1372 | { | ||
1373 | struct cache_detail *cd = PDE(inode)->data; | ||
1374 | |||
1375 | return content_open(inode, filp, cd); | ||
1376 | } | ||
1377 | |||
1378 | static int content_release_procfs(struct inode *inode, struct file *filp) | ||
1379 | { | ||
1380 | struct cache_detail *cd = PDE(inode)->data; | ||
1381 | |||
1382 | return content_release(inode, filp, cd); | ||
1383 | } | ||
1384 | |||
1385 | static const struct file_operations content_file_operations_procfs = { | ||
1386 | .open = content_open_procfs, | ||
1387 | .read = seq_read, | ||
1388 | .llseek = seq_lseek, | ||
1389 | .release = content_release_procfs, | ||
1390 | }; | ||
1391 | |||
1392 | static int open_flush_procfs(struct inode *inode, struct file *filp) | ||
1393 | { | ||
1394 | struct cache_detail *cd = PDE(inode)->data; | ||
1395 | |||
1396 | return open_flush(inode, filp, cd); | ||
1397 | } | ||
1398 | |||
1399 | static int release_flush_procfs(struct inode *inode, struct file *filp) | ||
1400 | { | ||
1401 | struct cache_detail *cd = PDE(inode)->data; | ||
1402 | |||
1403 | return release_flush(inode, filp, cd); | ||
1404 | } | ||
1405 | |||
1406 | static ssize_t read_flush_procfs(struct file *filp, char __user *buf, | ||
1407 | size_t count, loff_t *ppos) | ||
1408 | { | ||
1409 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; | ||
1410 | |||
1411 | return read_flush(filp, buf, count, ppos, cd); | ||
1412 | } | ||
1413 | |||
1414 | static ssize_t write_flush_procfs(struct file *filp, | ||
1415 | const char __user *buf, | ||
1416 | size_t count, loff_t *ppos) | ||
1417 | { | ||
1418 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; | ||
1419 | |||
1420 | return write_flush(filp, buf, count, ppos, cd); | ||
1421 | } | ||
1422 | |||
1423 | static const struct file_operations cache_flush_operations_procfs = { | ||
1424 | .open = open_flush_procfs, | ||
1425 | .read = read_flush_procfs, | ||
1426 | .write = write_flush_procfs, | ||
1427 | .release = release_flush_procfs, | ||
1428 | }; | ||
1429 | |||
1430 | static void remove_cache_proc_entries(struct cache_detail *cd) | ||
1431 | { | ||
1432 | if (cd->u.procfs.proc_ent == NULL) | ||
1433 | return; | ||
1434 | if (cd->u.procfs.flush_ent) | ||
1435 | remove_proc_entry("flush", cd->u.procfs.proc_ent); | ||
1436 | if (cd->u.procfs.channel_ent) | ||
1437 | remove_proc_entry("channel", cd->u.procfs.proc_ent); | ||
1438 | if (cd->u.procfs.content_ent) | ||
1439 | remove_proc_entry("content", cd->u.procfs.proc_ent); | ||
1440 | cd->u.procfs.proc_ent = NULL; | ||
1441 | remove_proc_entry(cd->name, proc_net_rpc); | ||
1442 | } | ||
1443 | |||
1444 | #ifdef CONFIG_PROC_FS | ||
1445 | static int create_cache_proc_entries(struct cache_detail *cd) | ||
1446 | { | ||
1447 | struct proc_dir_entry *p; | ||
1448 | |||
1449 | cd->u.procfs.proc_ent = proc_mkdir(cd->name, proc_net_rpc); | ||
1450 | if (cd->u.procfs.proc_ent == NULL) | ||
1451 | goto out_nomem; | ||
1452 | cd->u.procfs.channel_ent = NULL; | ||
1453 | cd->u.procfs.content_ent = NULL; | ||
1454 | |||
1455 | p = proc_create_data("flush", S_IFREG|S_IRUSR|S_IWUSR, | ||
1456 | cd->u.procfs.proc_ent, | ||
1457 | &cache_flush_operations_procfs, cd); | ||
1458 | cd->u.procfs.flush_ent = p; | ||
1459 | if (p == NULL) | ||
1460 | goto out_nomem; | ||
1461 | |||
1462 | if (cd->cache_upcall || cd->cache_parse) { | ||
1463 | p = proc_create_data("channel", S_IFREG|S_IRUSR|S_IWUSR, | ||
1464 | cd->u.procfs.proc_ent, | ||
1465 | &cache_file_operations_procfs, cd); | ||
1466 | cd->u.procfs.channel_ent = p; | ||
1467 | if (p == NULL) | ||
1468 | goto out_nomem; | ||
1469 | } | ||
1470 | if (cd->cache_show) { | ||
1471 | p = proc_create_data("content", S_IFREG|S_IRUSR|S_IWUSR, | ||
1472 | cd->u.procfs.proc_ent, | ||
1473 | &content_file_operations_procfs, cd); | ||
1474 | cd->u.procfs.content_ent = p; | ||
1475 | if (p == NULL) | ||
1476 | goto out_nomem; | ||
1477 | } | ||
1478 | return 0; | ||
1479 | out_nomem: | ||
1480 | remove_cache_proc_entries(cd); | ||
1481 | return -ENOMEM; | ||
1482 | } | ||
1483 | #else /* CONFIG_PROC_FS */ | ||
1484 | static int create_cache_proc_entries(struct cache_detail *cd) | ||
1485 | { | ||
1486 | return 0; | ||
1487 | } | ||
1488 | #endif | ||
1489 | |||
1490 | int cache_register(struct cache_detail *cd) | ||
1491 | { | ||
1492 | int ret; | ||
1493 | |||
1494 | sunrpc_init_cache_detail(cd); | ||
1495 | ret = create_cache_proc_entries(cd); | ||
1496 | if (ret) | ||
1497 | sunrpc_destroy_cache_detail(cd); | ||
1498 | return ret; | ||
1499 | } | ||
1500 | EXPORT_SYMBOL_GPL(cache_register); | ||
1501 | |||
1502 | void cache_unregister(struct cache_detail *cd) | ||
1503 | { | ||
1504 | remove_cache_proc_entries(cd); | ||
1505 | sunrpc_destroy_cache_detail(cd); | ||
1506 | } | ||
1507 | EXPORT_SYMBOL_GPL(cache_unregister); | ||
1508 | |||
1509 | static ssize_t cache_read_pipefs(struct file *filp, char __user *buf, | ||
1510 | size_t count, loff_t *ppos) | ||
1511 | { | ||
1512 | struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private; | ||
1513 | |||
1514 | return cache_read(filp, buf, count, ppos, cd); | ||
1515 | } | ||
1516 | |||
1517 | static ssize_t cache_write_pipefs(struct file *filp, const char __user *buf, | ||
1518 | size_t count, loff_t *ppos) | ||
1519 | { | ||
1520 | struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private; | ||
1521 | |||
1522 | return cache_write(filp, buf, count, ppos, cd); | ||
1523 | } | ||
1524 | |||
1525 | static unsigned int cache_poll_pipefs(struct file *filp, poll_table *wait) | ||
1526 | { | ||
1527 | struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private; | ||
1528 | |||
1529 | return cache_poll(filp, wait, cd); | ||
1530 | } | ||
1531 | |||
1532 | static int cache_ioctl_pipefs(struct inode *inode, struct file *filp, | ||
1533 | unsigned int cmd, unsigned long arg) | ||
1534 | { | ||
1535 | struct cache_detail *cd = RPC_I(inode)->private; | ||
1536 | |||
1537 | return cache_ioctl(inode, filp, cmd, arg, cd); | ||
1538 | } | ||
1539 | |||
1540 | static int cache_open_pipefs(struct inode *inode, struct file *filp) | ||
1541 | { | ||
1542 | struct cache_detail *cd = RPC_I(inode)->private; | ||
1543 | |||
1544 | return cache_open(inode, filp, cd); | ||
1545 | } | ||
1546 | |||
1547 | static int cache_release_pipefs(struct inode *inode, struct file *filp) | ||
1548 | { | ||
1549 | struct cache_detail *cd = RPC_I(inode)->private; | ||
1550 | |||
1551 | return cache_release(inode, filp, cd); | ||
1552 | } | ||
1553 | |||
1554 | const struct file_operations cache_file_operations_pipefs = { | ||
1555 | .owner = THIS_MODULE, | ||
1556 | .llseek = no_llseek, | ||
1557 | .read = cache_read_pipefs, | ||
1558 | .write = cache_write_pipefs, | ||
1559 | .poll = cache_poll_pipefs, | ||
1560 | .ioctl = cache_ioctl_pipefs, /* for FIONREAD */ | ||
1561 | .open = cache_open_pipefs, | ||
1562 | .release = cache_release_pipefs, | ||
1563 | }; | ||
1564 | |||
1565 | static int content_open_pipefs(struct inode *inode, struct file *filp) | ||
1566 | { | ||
1567 | struct cache_detail *cd = RPC_I(inode)->private; | ||
1568 | |||
1569 | return content_open(inode, filp, cd); | ||
1570 | } | ||
1571 | |||
1572 | static int content_release_pipefs(struct inode *inode, struct file *filp) | ||
1573 | { | ||
1574 | struct cache_detail *cd = RPC_I(inode)->private; | ||
1575 | |||
1576 | return content_release(inode, filp, cd); | ||
1577 | } | ||
1578 | |||
1579 | const struct file_operations content_file_operations_pipefs = { | ||
1580 | .open = content_open_pipefs, | ||
1581 | .read = seq_read, | ||
1582 | .llseek = seq_lseek, | ||
1583 | .release = content_release_pipefs, | ||
1584 | }; | ||
1585 | |||
1586 | static int open_flush_pipefs(struct inode *inode, struct file *filp) | ||
1587 | { | ||
1588 | struct cache_detail *cd = RPC_I(inode)->private; | ||
1589 | |||
1590 | return open_flush(inode, filp, cd); | ||
1591 | } | ||
1592 | |||
1593 | static int release_flush_pipefs(struct inode *inode, struct file *filp) | ||
1594 | { | ||
1595 | struct cache_detail *cd = RPC_I(inode)->private; | ||
1596 | |||
1597 | return release_flush(inode, filp, cd); | ||
1598 | } | ||
1599 | |||
1600 | static ssize_t read_flush_pipefs(struct file *filp, char __user *buf, | ||
1601 | size_t count, loff_t *ppos) | ||
1602 | { | ||
1603 | struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private; | ||
1604 | |||
1605 | return read_flush(filp, buf, count, ppos, cd); | ||
1606 | } | ||
1607 | |||
1608 | static ssize_t write_flush_pipefs(struct file *filp, | ||
1609 | const char __user *buf, | ||
1610 | size_t count, loff_t *ppos) | ||
1611 | { | ||
1612 | struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private; | ||
1613 | |||
1614 | return write_flush(filp, buf, count, ppos, cd); | ||
1615 | } | ||
1616 | |||
1617 | const struct file_operations cache_flush_operations_pipefs = { | ||
1618 | .open = open_flush_pipefs, | ||
1619 | .read = read_flush_pipefs, | ||
1620 | .write = write_flush_pipefs, | ||
1621 | .release = release_flush_pipefs, | ||
1622 | }; | ||
1623 | |||
1624 | int sunrpc_cache_register_pipefs(struct dentry *parent, | ||
1625 | const char *name, mode_t umode, | ||
1626 | struct cache_detail *cd) | ||
1627 | { | ||
1628 | struct qstr q; | ||
1629 | struct dentry *dir; | ||
1630 | int ret = 0; | ||
1631 | |||
1632 | sunrpc_init_cache_detail(cd); | ||
1633 | q.name = name; | ||
1634 | q.len = strlen(name); | ||
1635 | q.hash = full_name_hash(q.name, q.len); | ||
1636 | dir = rpc_create_cache_dir(parent, &q, umode, cd); | ||
1637 | if (!IS_ERR(dir)) | ||
1638 | cd->u.pipefs.dir = dir; | ||
1639 | else { | ||
1640 | sunrpc_destroy_cache_detail(cd); | ||
1641 | ret = PTR_ERR(dir); | ||
1642 | } | ||
1643 | return ret; | ||
1644 | } | ||
1645 | EXPORT_SYMBOL_GPL(sunrpc_cache_register_pipefs); | ||
1646 | |||
1647 | void sunrpc_cache_unregister_pipefs(struct cache_detail *cd) | ||
1648 | { | ||
1649 | rpc_remove_cache_dir(cd->u.pipefs.dir); | ||
1650 | cd->u.pipefs.dir = NULL; | ||
1651 | sunrpc_destroy_cache_detail(cd); | ||
1652 | } | ||
1653 | EXPORT_SYMBOL_GPL(sunrpc_cache_unregister_pipefs); | ||
1654 | |||