diff options
-rw-r--r-- | include/linux/sunrpc/cache.h | 11 | ||||
-rw-r--r-- | net/sunrpc/cache.c | 319 |
2 files changed, 199 insertions, 131 deletions
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index 23ee25981a0c..8e5bf3036652 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h | |||
@@ -59,6 +59,11 @@ struct cache_head { | |||
59 | 59 | ||
60 | #define CACHE_NEW_EXPIRY 120 /* keep new things pending confirmation for 120 seconds */ | 60 | #define CACHE_NEW_EXPIRY 120 /* keep new things pending confirmation for 120 seconds */ |
61 | 61 | ||
62 | struct cache_detail_procfs { | ||
63 | struct proc_dir_entry *proc_ent; | ||
64 | struct proc_dir_entry *flush_ent, *channel_ent, *content_ent; | ||
65 | }; | ||
66 | |||
62 | struct cache_detail { | 67 | struct cache_detail { |
63 | struct module * owner; | 68 | struct module * owner; |
64 | int hash_size; | 69 | int hash_size; |
@@ -98,12 +103,14 @@ struct cache_detail { | |||
98 | 103 | ||
99 | /* fields for communication over channel */ | 104 | /* fields for communication over channel */ |
100 | struct list_head queue; | 105 | struct list_head queue; |
101 | struct proc_dir_entry *proc_ent; | ||
102 | struct proc_dir_entry *flush_ent, *channel_ent, *content_ent; | ||
103 | 106 | ||
104 | atomic_t readers; /* how many time is /chennel open */ | 107 | atomic_t readers; /* how many time is /chennel open */ |
105 | time_t last_close; /* if no readers, when did last close */ | 108 | time_t last_close; /* if no readers, when did last close */ |
106 | time_t last_warn; /* when we last warned about no readers */ | 109 | time_t last_warn; /* when we last warned about no readers */ |
110 | |||
111 | union { | ||
112 | struct cache_detail_procfs procfs; | ||
113 | } u; | ||
107 | }; | 114 | }; |
108 | 115 | ||
109 | 116 | ||
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index e438352bed7b..1cd82eda56d0 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -291,69 +291,9 @@ static DEFINE_SPINLOCK(cache_list_lock); | |||
291 | static struct cache_detail *current_detail; | 291 | static struct cache_detail *current_detail; |
292 | static int current_index; | 292 | static int current_index; |
293 | 293 | ||
294 | static const struct file_operations cache_file_operations; | ||
295 | static const struct file_operations content_file_operations; | ||
296 | static const struct file_operations cache_flush_operations; | ||
297 | |||
298 | static void do_cache_clean(struct work_struct *work); | 294 | static void do_cache_clean(struct work_struct *work); |
299 | static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean); | 295 | static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean); |
300 | 296 | ||
301 | static void remove_cache_proc_entries(struct cache_detail *cd) | ||
302 | { | ||
303 | if (cd->proc_ent == NULL) | ||
304 | return; | ||
305 | if (cd->flush_ent) | ||
306 | remove_proc_entry("flush", cd->proc_ent); | ||
307 | if (cd->channel_ent) | ||
308 | remove_proc_entry("channel", cd->proc_ent); | ||
309 | if (cd->content_ent) | ||
310 | remove_proc_entry("content", cd->proc_ent); | ||
311 | cd->proc_ent = NULL; | ||
312 | remove_proc_entry(cd->name, proc_net_rpc); | ||
313 | } | ||
314 | |||
315 | #ifdef CONFIG_PROC_FS | ||
316 | static int create_cache_proc_entries(struct cache_detail *cd) | ||
317 | { | ||
318 | struct proc_dir_entry *p; | ||
319 | |||
320 | cd->proc_ent = proc_mkdir(cd->name, proc_net_rpc); | ||
321 | if (cd->proc_ent == NULL) | ||
322 | goto out_nomem; | ||
323 | cd->channel_ent = cd->content_ent = NULL; | ||
324 | |||
325 | p = proc_create_data("flush", S_IFREG|S_IRUSR|S_IWUSR, | ||
326 | cd->proc_ent, &cache_flush_operations, cd); | ||
327 | cd->flush_ent = p; | ||
328 | if (p == NULL) | ||
329 | goto out_nomem; | ||
330 | |||
331 | if (cd->cache_upcall || cd->cache_parse) { | ||
332 | p = proc_create_data("channel", S_IFREG|S_IRUSR|S_IWUSR, | ||
333 | cd->proc_ent, &cache_file_operations, cd); | ||
334 | cd->channel_ent = p; | ||
335 | if (p == NULL) | ||
336 | goto out_nomem; | ||
337 | } | ||
338 | if (cd->cache_show) { | ||
339 | p = proc_create_data("content", S_IFREG|S_IRUSR|S_IWUSR, | ||
340 | cd->proc_ent, &content_file_operations, cd); | ||
341 | cd->content_ent = p; | ||
342 | if (p == NULL) | ||
343 | goto out_nomem; | ||
344 | } | ||
345 | return 0; | ||
346 | out_nomem: | ||
347 | remove_cache_proc_entries(cd); | ||
348 | return -ENOMEM; | ||
349 | } | ||
350 | #else /* CONFIG_PROC_FS */ | ||
351 | static int create_cache_proc_entries(struct cache_detail *cd) | ||
352 | { | ||
353 | return 0; | ||
354 | } | ||
355 | #endif | ||
356 | |||
357 | static void sunrpc_init_cache_detail(struct cache_detail *cd) | 297 | static void sunrpc_init_cache_detail(struct cache_detail *cd) |
358 | { | 298 | { |
359 | rwlock_init(&cd->hash_lock); | 299 | rwlock_init(&cd->hash_lock); |
@@ -395,25 +335,6 @@ out: | |||
395 | printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); | 335 | printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); |
396 | } | 336 | } |
397 | 337 | ||
398 | int cache_register(struct cache_detail *cd) | ||
399 | { | ||
400 | int ret; | ||
401 | |||
402 | sunrpc_init_cache_detail(cd); | ||
403 | ret = create_cache_proc_entries(cd); | ||
404 | if (ret) | ||
405 | sunrpc_destroy_cache_detail(cd); | ||
406 | return ret; | ||
407 | } | ||
408 | EXPORT_SYMBOL_GPL(cache_register); | ||
409 | |||
410 | void cache_unregister(struct cache_detail *cd) | ||
411 | { | ||
412 | remove_cache_proc_entries(cd); | ||
413 | sunrpc_destroy_cache_detail(cd); | ||
414 | } | ||
415 | EXPORT_SYMBOL_GPL(cache_unregister); | ||
416 | |||
417 | /* clean cache tries to find something to clean | 338 | /* clean cache tries to find something to clean |
418 | * and cleans it. | 339 | * and cleans it. |
419 | * It returns 1 if it cleaned something, | 340 | * It returns 1 if it cleaned something, |
@@ -704,13 +625,12 @@ struct cache_reader { | |||
704 | int offset; /* if non-0, we have a refcnt on next request */ | 625 | int offset; /* if non-0, we have a refcnt on next request */ |
705 | }; | 626 | }; |
706 | 627 | ||
707 | static ssize_t | 628 | static ssize_t cache_read(struct file *filp, char __user *buf, size_t count, |
708 | cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) | 629 | loff_t *ppos, struct cache_detail *cd) |
709 | { | 630 | { |
710 | struct cache_reader *rp = filp->private_data; | 631 | struct cache_reader *rp = filp->private_data; |
711 | struct cache_request *rq; | 632 | struct cache_request *rq; |
712 | struct inode *inode = filp->f_path.dentry->d_inode; | 633 | struct inode *inode = filp->f_path.dentry->d_inode; |
713 | struct cache_detail *cd = PDE(inode)->data; | ||
714 | int err; | 634 | int err; |
715 | 635 | ||
716 | if (count == 0) | 636 | if (count == 0) |
@@ -834,13 +754,12 @@ out_slow: | |||
834 | return cache_slow_downcall(buf, count, cd); | 754 | return cache_slow_downcall(buf, count, cd); |
835 | } | 755 | } |
836 | 756 | ||
837 | static ssize_t | 757 | static ssize_t cache_write(struct file *filp, const char __user *buf, |
838 | cache_write(struct file *filp, const char __user *buf, size_t count, | 758 | size_t count, loff_t *ppos, |
839 | loff_t *ppos) | 759 | struct cache_detail *cd) |
840 | { | 760 | { |
841 | struct address_space *mapping = filp->f_mapping; | 761 | struct address_space *mapping = filp->f_mapping; |
842 | struct inode *inode = filp->f_path.dentry->d_inode; | 762 | struct inode *inode = filp->f_path.dentry->d_inode; |
843 | struct cache_detail *cd = PDE(inode)->data; | ||
844 | ssize_t ret = -EINVAL; | 763 | ssize_t ret = -EINVAL; |
845 | 764 | ||
846 | if (!cd->cache_parse) | 765 | if (!cd->cache_parse) |
@@ -855,13 +774,12 @@ out: | |||
855 | 774 | ||
856 | static DECLARE_WAIT_QUEUE_HEAD(queue_wait); | 775 | static DECLARE_WAIT_QUEUE_HEAD(queue_wait); |
857 | 776 | ||
858 | static unsigned int | 777 | static unsigned int cache_poll(struct file *filp, poll_table *wait, |
859 | cache_poll(struct file *filp, poll_table *wait) | 778 | struct cache_detail *cd) |
860 | { | 779 | { |
861 | unsigned int mask; | 780 | unsigned int mask; |
862 | struct cache_reader *rp = filp->private_data; | 781 | struct cache_reader *rp = filp->private_data; |
863 | struct cache_queue *cq; | 782 | struct cache_queue *cq; |
864 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; | ||
865 | 783 | ||
866 | poll_wait(filp, &queue_wait, wait); | 784 | poll_wait(filp, &queue_wait, wait); |
867 | 785 | ||
@@ -883,14 +801,13 @@ cache_poll(struct file *filp, poll_table *wait) | |||
883 | return mask; | 801 | return mask; |
884 | } | 802 | } |
885 | 803 | ||
886 | static int | 804 | static int cache_ioctl(struct inode *ino, struct file *filp, |
887 | cache_ioctl(struct inode *ino, struct file *filp, | 805 | unsigned int cmd, unsigned long arg, |
888 | unsigned int cmd, unsigned long arg) | 806 | struct cache_detail *cd) |
889 | { | 807 | { |
890 | int len = 0; | 808 | int len = 0; |
891 | struct cache_reader *rp = filp->private_data; | 809 | struct cache_reader *rp = filp->private_data; |
892 | struct cache_queue *cq; | 810 | struct cache_queue *cq; |
893 | struct cache_detail *cd = PDE(ino)->data; | ||
894 | 811 | ||
895 | if (cmd != FIONREAD || !rp) | 812 | if (cmd != FIONREAD || !rp) |
896 | return -EINVAL; | 813 | return -EINVAL; |
@@ -913,15 +830,13 @@ cache_ioctl(struct inode *ino, struct file *filp, | |||
913 | return put_user(len, (int __user *)arg); | 830 | return put_user(len, (int __user *)arg); |
914 | } | 831 | } |
915 | 832 | ||
916 | static int | 833 | static int cache_open(struct inode *inode, struct file *filp, |
917 | cache_open(struct inode *inode, struct file *filp) | 834 | struct cache_detail *cd) |
918 | { | 835 | { |
919 | struct cache_reader *rp = NULL; | 836 | struct cache_reader *rp = NULL; |
920 | 837 | ||
921 | nonseekable_open(inode, filp); | 838 | nonseekable_open(inode, filp); |
922 | if (filp->f_mode & FMODE_READ) { | 839 | if (filp->f_mode & FMODE_READ) { |
923 | struct cache_detail *cd = PDE(inode)->data; | ||
924 | |||
925 | rp = kmalloc(sizeof(*rp), GFP_KERNEL); | 840 | rp = kmalloc(sizeof(*rp), GFP_KERNEL); |
926 | if (!rp) | 841 | if (!rp) |
927 | return -ENOMEM; | 842 | return -ENOMEM; |
@@ -936,11 +851,10 @@ cache_open(struct inode *inode, struct file *filp) | |||
936 | return 0; | 851 | return 0; |
937 | } | 852 | } |
938 | 853 | ||
939 | static int | 854 | static int cache_release(struct inode *inode, struct file *filp, |
940 | cache_release(struct inode *inode, struct file *filp) | 855 | struct cache_detail *cd) |
941 | { | 856 | { |
942 | struct cache_reader *rp = filp->private_data; | 857 | struct cache_reader *rp = filp->private_data; |
943 | struct cache_detail *cd = PDE(inode)->data; | ||
944 | 858 | ||
945 | if (rp) { | 859 | if (rp) { |
946 | spin_lock(&queue_lock); | 860 | spin_lock(&queue_lock); |
@@ -969,18 +883,6 @@ cache_release(struct inode *inode, struct file *filp) | |||
969 | 883 | ||
970 | 884 | ||
971 | 885 | ||
972 | static const struct file_operations cache_file_operations = { | ||
973 | .owner = THIS_MODULE, | ||
974 | .llseek = no_llseek, | ||
975 | .read = cache_read, | ||
976 | .write = cache_write, | ||
977 | .poll = cache_poll, | ||
978 | .ioctl = cache_ioctl, /* for FIONREAD */ | ||
979 | .open = cache_open, | ||
980 | .release = cache_release, | ||
981 | }; | ||
982 | |||
983 | |||
984 | static void queue_loose(struct cache_detail *detail, struct cache_head *ch) | 886 | static void queue_loose(struct cache_detail *detail, struct cache_head *ch) |
985 | { | 887 | { |
986 | struct cache_queue *cq; | 888 | struct cache_queue *cq; |
@@ -1307,10 +1209,10 @@ static const struct seq_operations cache_content_op = { | |||
1307 | .show = c_show, | 1209 | .show = c_show, |
1308 | }; | 1210 | }; |
1309 | 1211 | ||
1310 | static int content_open(struct inode *inode, struct file *file) | 1212 | static int content_open(struct inode *inode, struct file *file, |
1213 | struct cache_detail *cd) | ||
1311 | { | 1214 | { |
1312 | struct handle *han; | 1215 | struct handle *han; |
1313 | struct cache_detail *cd = PDE(inode)->data; | ||
1314 | 1216 | ||
1315 | han = __seq_open_private(file, &cache_content_op, sizeof(*han)); | 1217 | han = __seq_open_private(file, &cache_content_op, sizeof(*han)); |
1316 | if (han == NULL) | 1218 | if (han == NULL) |
@@ -1320,17 +1222,10 @@ static int content_open(struct inode *inode, struct file *file) | |||
1320 | return 0; | 1222 | return 0; |
1321 | } | 1223 | } |
1322 | 1224 | ||
1323 | static const struct file_operations content_file_operations = { | ||
1324 | .open = content_open, | ||
1325 | .read = seq_read, | ||
1326 | .llseek = seq_lseek, | ||
1327 | .release = seq_release_private, | ||
1328 | }; | ||
1329 | |||
1330 | static ssize_t read_flush(struct file *file, char __user *buf, | 1225 | static ssize_t read_flush(struct file *file, char __user *buf, |
1331 | size_t count, loff_t *ppos) | 1226 | size_t count, loff_t *ppos, |
1227 | struct cache_detail *cd) | ||
1332 | { | 1228 | { |
1333 | struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data; | ||
1334 | char tbuf[20]; | 1229 | char tbuf[20]; |
1335 | unsigned long p = *ppos; | 1230 | unsigned long p = *ppos; |
1336 | size_t len; | 1231 | size_t len; |
@@ -1348,10 +1243,10 @@ static ssize_t read_flush(struct file *file, char __user *buf, | |||
1348 | return len; | 1243 | return len; |
1349 | } | 1244 | } |
1350 | 1245 | ||
1351 | static ssize_t write_flush(struct file * file, const char __user * buf, | 1246 | static ssize_t write_flush(struct file *file, const char __user *buf, |
1352 | size_t count, loff_t *ppos) | 1247 | size_t count, loff_t *ppos, |
1248 | struct cache_detail *cd) | ||
1353 | { | 1249 | { |
1354 | struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data; | ||
1355 | char tbuf[20]; | 1250 | char tbuf[20]; |
1356 | char *ep; | 1251 | char *ep; |
1357 | long flushtime; | 1252 | long flushtime; |
@@ -1372,8 +1267,174 @@ static ssize_t write_flush(struct file * file, const char __user * buf, | |||
1372 | return count; | 1267 | return count; |
1373 | } | 1268 | } |
1374 | 1269 | ||
1375 | static const struct file_operations cache_flush_operations = { | 1270 | static ssize_t cache_read_procfs(struct file *filp, char __user *buf, |
1271 | size_t count, loff_t *ppos) | ||
1272 | { | ||
1273 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; | ||
1274 | |||
1275 | return cache_read(filp, buf, count, ppos, cd); | ||
1276 | } | ||
1277 | |||
1278 | static ssize_t cache_write_procfs(struct file *filp, const char __user *buf, | ||
1279 | size_t count, loff_t *ppos) | ||
1280 | { | ||
1281 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; | ||
1282 | |||
1283 | return cache_write(filp, buf, count, ppos, cd); | ||
1284 | } | ||
1285 | |||
1286 | static unsigned int cache_poll_procfs(struct file *filp, poll_table *wait) | ||
1287 | { | ||
1288 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; | ||
1289 | |||
1290 | return cache_poll(filp, wait, cd); | ||
1291 | } | ||
1292 | |||
1293 | static int cache_ioctl_procfs(struct inode *inode, struct file *filp, | ||
1294 | unsigned int cmd, unsigned long arg) | ||
1295 | { | ||
1296 | struct cache_detail *cd = PDE(inode)->data; | ||
1297 | |||
1298 | return cache_ioctl(inode, filp, cmd, arg, cd); | ||
1299 | } | ||
1300 | |||
1301 | static int cache_open_procfs(struct inode *inode, struct file *filp) | ||
1302 | { | ||
1303 | struct cache_detail *cd = PDE(inode)->data; | ||
1304 | |||
1305 | return cache_open(inode, filp, cd); | ||
1306 | } | ||
1307 | |||
1308 | static int cache_release_procfs(struct inode *inode, struct file *filp) | ||
1309 | { | ||
1310 | struct cache_detail *cd = PDE(inode)->data; | ||
1311 | |||
1312 | return cache_release(inode, filp, cd); | ||
1313 | } | ||
1314 | |||
1315 | static const struct file_operations cache_file_operations_procfs = { | ||
1316 | .owner = THIS_MODULE, | ||
1317 | .llseek = no_llseek, | ||
1318 | .read = cache_read_procfs, | ||
1319 | .write = cache_write_procfs, | ||
1320 | .poll = cache_poll_procfs, | ||
1321 | .ioctl = cache_ioctl_procfs, /* for FIONREAD */ | ||
1322 | .open = cache_open_procfs, | ||
1323 | .release = cache_release_procfs, | ||
1324 | }; | ||
1325 | |||
1326 | static int content_open_procfs(struct inode *inode, struct file *filp) | ||
1327 | { | ||
1328 | struct cache_detail *cd = PDE(inode)->data; | ||
1329 | |||
1330 | return content_open(inode, filp, cd); | ||
1331 | } | ||
1332 | |||
1333 | static const struct file_operations content_file_operations_procfs = { | ||
1334 | .open = content_open_procfs, | ||
1335 | .read = seq_read, | ||
1336 | .llseek = seq_lseek, | ||
1337 | .release = seq_release_private, | ||
1338 | }; | ||
1339 | |||
1340 | static ssize_t read_flush_procfs(struct file *filp, char __user *buf, | ||
1341 | size_t count, loff_t *ppos) | ||
1342 | { | ||
1343 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; | ||
1344 | |||
1345 | return read_flush(filp, buf, count, ppos, cd); | ||
1346 | } | ||
1347 | |||
1348 | static ssize_t write_flush_procfs(struct file *filp, | ||
1349 | const char __user *buf, | ||
1350 | size_t count, loff_t *ppos) | ||
1351 | { | ||
1352 | struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; | ||
1353 | |||
1354 | return write_flush(filp, buf, count, ppos, cd); | ||
1355 | } | ||
1356 | |||
1357 | static const struct file_operations cache_flush_operations_procfs = { | ||
1376 | .open = nonseekable_open, | 1358 | .open = nonseekable_open, |
1377 | .read = read_flush, | 1359 | .read = read_flush_procfs, |
1378 | .write = write_flush, | 1360 | .write = write_flush_procfs, |
1379 | }; | 1361 | }; |
1362 | |||
1363 | static void remove_cache_proc_entries(struct cache_detail *cd) | ||
1364 | { | ||
1365 | if (cd->u.procfs.proc_ent == NULL) | ||
1366 | return; | ||
1367 | if (cd->u.procfs.flush_ent) | ||
1368 | remove_proc_entry("flush", cd->u.procfs.proc_ent); | ||
1369 | if (cd->u.procfs.channel_ent) | ||
1370 | remove_proc_entry("channel", cd->u.procfs.proc_ent); | ||
1371 | if (cd->u.procfs.content_ent) | ||
1372 | remove_proc_entry("content", cd->u.procfs.proc_ent); | ||
1373 | cd->u.procfs.proc_ent = NULL; | ||
1374 | remove_proc_entry(cd->name, proc_net_rpc); | ||
1375 | } | ||
1376 | |||
1377 | #ifdef CONFIG_PROC_FS | ||
1378 | static int create_cache_proc_entries(struct cache_detail *cd) | ||
1379 | { | ||
1380 | struct proc_dir_entry *p; | ||
1381 | |||
1382 | cd->u.procfs.proc_ent = proc_mkdir(cd->name, proc_net_rpc); | ||
1383 | if (cd->u.procfs.proc_ent == NULL) | ||
1384 | goto out_nomem; | ||
1385 | cd->u.procfs.channel_ent = NULL; | ||
1386 | cd->u.procfs.content_ent = NULL; | ||
1387 | |||
1388 | p = proc_create_data("flush", S_IFREG|S_IRUSR|S_IWUSR, | ||
1389 | cd->u.procfs.proc_ent, | ||
1390 | &cache_flush_operations_procfs, cd); | ||
1391 | cd->u.procfs.flush_ent = p; | ||
1392 | if (p == NULL) | ||
1393 | goto out_nomem; | ||
1394 | |||
1395 | if (cd->cache_upcall || cd->cache_parse) { | ||
1396 | p = proc_create_data("channel", S_IFREG|S_IRUSR|S_IWUSR, | ||
1397 | cd->u.procfs.proc_ent, | ||
1398 | &cache_file_operations_procfs, cd); | ||
1399 | cd->u.procfs.channel_ent = p; | ||
1400 | if (p == NULL) | ||
1401 | goto out_nomem; | ||
1402 | } | ||
1403 | if (cd->cache_show) { | ||
1404 | p = proc_create_data("content", S_IFREG|S_IRUSR|S_IWUSR, | ||
1405 | cd->u.procfs.proc_ent, | ||
1406 | &content_file_operations_procfs, cd); | ||
1407 | cd->u.procfs.content_ent = p; | ||
1408 | if (p == NULL) | ||
1409 | goto out_nomem; | ||
1410 | } | ||
1411 | return 0; | ||
1412 | out_nomem: | ||
1413 | remove_cache_proc_entries(cd); | ||
1414 | return -ENOMEM; | ||
1415 | } | ||
1416 | #else /* CONFIG_PROC_FS */ | ||
1417 | static int create_cache_proc_entries(struct cache_detail *cd) | ||
1418 | { | ||
1419 | return 0; | ||
1420 | } | ||
1421 | #endif | ||
1422 | |||
1423 | int cache_register(struct cache_detail *cd) | ||
1424 | { | ||
1425 | int ret; | ||
1426 | |||
1427 | sunrpc_init_cache_detail(cd); | ||
1428 | ret = create_cache_proc_entries(cd); | ||
1429 | if (ret) | ||
1430 | sunrpc_destroy_cache_detail(cd); | ||
1431 | return ret; | ||
1432 | } | ||
1433 | EXPORT_SYMBOL_GPL(cache_register); | ||
1434 | |||
1435 | void cache_unregister(struct cache_detail *cd) | ||
1436 | { | ||
1437 | remove_cache_proc_entries(cd); | ||
1438 | sunrpc_destroy_cache_detail(cd); | ||
1439 | } | ||
1440 | EXPORT_SYMBOL_GPL(cache_unregister); | ||