aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/cache.c')
-rw-r--r--net/sunrpc/cache.c288
1 files changed, 201 insertions, 87 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 7dce81a926c5..e433e7580e27 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -33,15 +33,16 @@
33#include <linux/sunrpc/cache.h> 33#include <linux/sunrpc/cache.h>
34#include <linux/sunrpc/stats.h> 34#include <linux/sunrpc/stats.h>
35#include <linux/sunrpc/rpc_pipe_fs.h> 35#include <linux/sunrpc/rpc_pipe_fs.h>
36#include "netns.h"
36 37
37#define RPCDBG_FACILITY RPCDBG_CACHE 38#define RPCDBG_FACILITY RPCDBG_CACHE
38 39
39static int cache_defer_req(struct cache_req *req, struct cache_head *item); 40static void cache_defer_req(struct cache_req *req, struct cache_head *item);
40static void cache_revisit_request(struct cache_head *item); 41static void cache_revisit_request(struct cache_head *item);
41 42
42static void cache_init(struct cache_head *h) 43static void cache_init(struct cache_head *h)
43{ 44{
44 time_t now = get_seconds(); 45 time_t now = seconds_since_boot();
45 h->next = NULL; 46 h->next = NULL;
46 h->flags = 0; 47 h->flags = 0;
47 kref_init(&h->ref); 48 kref_init(&h->ref);
@@ -51,7 +52,7 @@ static void cache_init(struct cache_head *h)
51 52
52static inline int cache_is_expired(struct cache_detail *detail, struct cache_head *h) 53static inline int cache_is_expired(struct cache_detail *detail, struct cache_head *h)
53{ 54{
54 return (h->expiry_time < get_seconds()) || 55 return (h->expiry_time < seconds_since_boot()) ||
55 (detail->flush_time > h->last_refresh); 56 (detail->flush_time > h->last_refresh);
56} 57}
57 58
@@ -126,7 +127,7 @@ static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch);
126static void cache_fresh_locked(struct cache_head *head, time_t expiry) 127static void cache_fresh_locked(struct cache_head *head, time_t expiry)
127{ 128{
128 head->expiry_time = expiry; 129 head->expiry_time = expiry;
129 head->last_refresh = get_seconds(); 130 head->last_refresh = seconds_since_boot();
130 set_bit(CACHE_VALID, &head->flags); 131 set_bit(CACHE_VALID, &head->flags);
131} 132}
132 133
@@ -237,7 +238,7 @@ int cache_check(struct cache_detail *detail,
237 238
238 /* now see if we want to start an upcall */ 239 /* now see if we want to start an upcall */
239 refresh_age = (h->expiry_time - h->last_refresh); 240 refresh_age = (h->expiry_time - h->last_refresh);
240 age = get_seconds() - h->last_refresh; 241 age = seconds_since_boot() - h->last_refresh;
241 242
242 if (rqstp == NULL) { 243 if (rqstp == NULL) {
243 if (rv == -EAGAIN) 244 if (rv == -EAGAIN)
@@ -252,7 +253,7 @@ int cache_check(struct cache_detail *detail,
252 cache_revisit_request(h); 253 cache_revisit_request(h);
253 if (rv == -EAGAIN) { 254 if (rv == -EAGAIN) {
254 set_bit(CACHE_NEGATIVE, &h->flags); 255 set_bit(CACHE_NEGATIVE, &h->flags);
255 cache_fresh_locked(h, get_seconds()+CACHE_NEW_EXPIRY); 256 cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY);
256 cache_fresh_unlocked(h, detail); 257 cache_fresh_unlocked(h, detail);
257 rv = -ENOENT; 258 rv = -ENOENT;
258 } 259 }
@@ -267,7 +268,8 @@ int cache_check(struct cache_detail *detail,
267 } 268 }
268 269
269 if (rv == -EAGAIN) { 270 if (rv == -EAGAIN) {
270 if (cache_defer_req(rqstp, h) < 0) { 271 cache_defer_req(rqstp, h);
272 if (!test_bit(CACHE_PENDING, &h->flags)) {
271 /* Request is not deferred */ 273 /* Request is not deferred */
272 rv = cache_is_valid(detail, h); 274 rv = cache_is_valid(detail, h);
273 if (rv == -EAGAIN) 275 if (rv == -EAGAIN)
@@ -387,11 +389,11 @@ static int cache_clean(void)
387 return -1; 389 return -1;
388 } 390 }
389 current_detail = list_entry(next, struct cache_detail, others); 391 current_detail = list_entry(next, struct cache_detail, others);
390 if (current_detail->nextcheck > get_seconds()) 392 if (current_detail->nextcheck > seconds_since_boot())
391 current_index = current_detail->hash_size; 393 current_index = current_detail->hash_size;
392 else { 394 else {
393 current_index = 0; 395 current_index = 0;
394 current_detail->nextcheck = get_seconds()+30*60; 396 current_detail->nextcheck = seconds_since_boot()+30*60;
395 } 397 }
396 } 398 }
397 399
@@ -476,7 +478,7 @@ EXPORT_SYMBOL_GPL(cache_flush);
476void cache_purge(struct cache_detail *detail) 478void cache_purge(struct cache_detail *detail)
477{ 479{
478 detail->flush_time = LONG_MAX; 480 detail->flush_time = LONG_MAX;
479 detail->nextcheck = get_seconds(); 481 detail->nextcheck = seconds_since_boot();
480 cache_flush(); 482 cache_flush();
481 detail->flush_time = 1; 483 detail->flush_time = 1;
482} 484}
@@ -505,81 +507,155 @@ EXPORT_SYMBOL_GPL(cache_purge);
505 507
506static DEFINE_SPINLOCK(cache_defer_lock); 508static DEFINE_SPINLOCK(cache_defer_lock);
507static LIST_HEAD(cache_defer_list); 509static LIST_HEAD(cache_defer_list);
508static struct list_head cache_defer_hash[DFR_HASHSIZE]; 510static struct hlist_head cache_defer_hash[DFR_HASHSIZE];
509static int cache_defer_cnt; 511static int cache_defer_cnt;
510 512
511static int cache_defer_req(struct cache_req *req, struct cache_head *item) 513static void __unhash_deferred_req(struct cache_deferred_req *dreq)
514{
515 hlist_del_init(&dreq->hash);
516 if (!list_empty(&dreq->recent)) {
517 list_del_init(&dreq->recent);
518 cache_defer_cnt--;
519 }
520}
521
522static void __hash_deferred_req(struct cache_deferred_req *dreq, struct cache_head *item)
512{ 523{
513 struct cache_deferred_req *dreq, *discard;
514 int hash = DFR_HASH(item); 524 int hash = DFR_HASH(item);
515 525
516 if (cache_defer_cnt >= DFR_MAX) { 526 INIT_LIST_HEAD(&dreq->recent);
517 /* too much in the cache, randomly drop this one, 527 hlist_add_head(&dreq->hash, &cache_defer_hash[hash]);
518 * or continue and drop the oldest below 528}
519 */ 529
520 if (net_random()&1) 530static void setup_deferral(struct cache_deferred_req *dreq,
521 return -ENOMEM; 531 struct cache_head *item,
522 } 532 int count_me)
523 dreq = req->defer(req); 533{
524 if (dreq == NULL)
525 return -ENOMEM;
526 534
527 dreq->item = item; 535 dreq->item = item;
528 536
529 spin_lock(&cache_defer_lock); 537 spin_lock(&cache_defer_lock);
530 538
531 list_add(&dreq->recent, &cache_defer_list); 539 __hash_deferred_req(dreq, item);
532
533 if (cache_defer_hash[hash].next == NULL)
534 INIT_LIST_HEAD(&cache_defer_hash[hash]);
535 list_add(&dreq->hash, &cache_defer_hash[hash]);
536 540
537 /* it is in, now maybe clean up */ 541 if (count_me) {
538 discard = NULL; 542 cache_defer_cnt++;
539 if (++cache_defer_cnt > DFR_MAX) { 543 list_add(&dreq->recent, &cache_defer_list);
540 discard = list_entry(cache_defer_list.prev,
541 struct cache_deferred_req, recent);
542 list_del_init(&discard->recent);
543 list_del_init(&discard->hash);
544 cache_defer_cnt--;
545 } 544 }
545
546 spin_unlock(&cache_defer_lock); 546 spin_unlock(&cache_defer_lock);
547 547
548}
549
550struct thread_deferred_req {
551 struct cache_deferred_req handle;
552 struct completion completion;
553};
554
555static void cache_restart_thread(struct cache_deferred_req *dreq, int too_many)
556{
557 struct thread_deferred_req *dr =
558 container_of(dreq, struct thread_deferred_req, handle);
559 complete(&dr->completion);
560}
561
562static void cache_wait_req(struct cache_req *req, struct cache_head *item)
563{
564 struct thread_deferred_req sleeper;
565 struct cache_deferred_req *dreq = &sleeper.handle;
566
567 sleeper.completion = COMPLETION_INITIALIZER_ONSTACK(sleeper.completion);
568 dreq->revisit = cache_restart_thread;
569
570 setup_deferral(dreq, item, 0);
571
572 if (!test_bit(CACHE_PENDING, &item->flags) ||
573 wait_for_completion_interruptible_timeout(
574 &sleeper.completion, req->thread_wait) <= 0) {
575 /* The completion wasn't completed, so we need
576 * to clean up
577 */
578 spin_lock(&cache_defer_lock);
579 if (!hlist_unhashed(&sleeper.handle.hash)) {
580 __unhash_deferred_req(&sleeper.handle);
581 spin_unlock(&cache_defer_lock);
582 } else {
583 /* cache_revisit_request already removed
584 * this from the hash table, but hasn't
585 * called ->revisit yet. It will very soon
586 * and we need to wait for it.
587 */
588 spin_unlock(&cache_defer_lock);
589 wait_for_completion(&sleeper.completion);
590 }
591 }
592}
593
594static void cache_limit_defers(void)
595{
596 /* Make sure we haven't exceed the limit of allowed deferred
597 * requests.
598 */
599 struct cache_deferred_req *discard = NULL;
600
601 if (cache_defer_cnt <= DFR_MAX)
602 return;
603
604 spin_lock(&cache_defer_lock);
605
606 /* Consider removing either the first or the last */
607 if (cache_defer_cnt > DFR_MAX) {
608 if (net_random() & 1)
609 discard = list_entry(cache_defer_list.next,
610 struct cache_deferred_req, recent);
611 else
612 discard = list_entry(cache_defer_list.prev,
613 struct cache_deferred_req, recent);
614 __unhash_deferred_req(discard);
615 }
616 spin_unlock(&cache_defer_lock);
548 if (discard) 617 if (discard)
549 /* there was one too many */
550 discard->revisit(discard, 1); 618 discard->revisit(discard, 1);
619}
551 620
552 if (!test_bit(CACHE_PENDING, &item->flags)) { 621static void cache_defer_req(struct cache_req *req, struct cache_head *item)
553 /* must have just been validated... */ 622{
554 cache_revisit_request(item); 623 struct cache_deferred_req *dreq;
555 return -EAGAIN; 624
625 if (req->thread_wait) {
626 cache_wait_req(req, item);
627 if (!test_bit(CACHE_PENDING, &item->flags))
628 return;
556 } 629 }
557 return 0; 630 dreq = req->defer(req);
631 if (dreq == NULL)
632 return;
633 setup_deferral(dreq, item, 1);
634 if (!test_bit(CACHE_PENDING, &item->flags))
635 /* Bit could have been cleared before we managed to
636 * set up the deferral, so need to revisit just in case
637 */
638 cache_revisit_request(item);
639
640 cache_limit_defers();
558} 641}
559 642
560static void cache_revisit_request(struct cache_head *item) 643static void cache_revisit_request(struct cache_head *item)
561{ 644{
562 struct cache_deferred_req *dreq; 645 struct cache_deferred_req *dreq;
563 struct list_head pending; 646 struct list_head pending;
564 647 struct hlist_node *lp, *tmp;
565 struct list_head *lp;
566 int hash = DFR_HASH(item); 648 int hash = DFR_HASH(item);
567 649
568 INIT_LIST_HEAD(&pending); 650 INIT_LIST_HEAD(&pending);
569 spin_lock(&cache_defer_lock); 651 spin_lock(&cache_defer_lock);
570 652
571 lp = cache_defer_hash[hash].next; 653 hlist_for_each_entry_safe(dreq, lp, tmp, &cache_defer_hash[hash], hash)
572 if (lp) { 654 if (dreq->item == item) {
573 while (lp != &cache_defer_hash[hash]) { 655 __unhash_deferred_req(dreq);
574 dreq = list_entry(lp, struct cache_deferred_req, hash); 656 list_add(&dreq->recent, &pending);
575 lp = lp->next;
576 if (dreq->item == item) {
577 list_del_init(&dreq->hash);
578 list_move(&dreq->recent, &pending);
579 cache_defer_cnt--;
580 }
581 } 657 }
582 } 658
583 spin_unlock(&cache_defer_lock); 659 spin_unlock(&cache_defer_lock);
584 660
585 while (!list_empty(&pending)) { 661 while (!list_empty(&pending)) {
@@ -600,9 +676,8 @@ void cache_clean_deferred(void *owner)
600 676
601 list_for_each_entry_safe(dreq, tmp, &cache_defer_list, recent) { 677 list_for_each_entry_safe(dreq, tmp, &cache_defer_list, recent) {
602 if (dreq->owner == owner) { 678 if (dreq->owner == owner) {
603 list_del_init(&dreq->hash); 679 __unhash_deferred_req(dreq);
604 list_move(&dreq->recent, &pending); 680 list_add(&dreq->recent, &pending);
605 cache_defer_cnt--;
606 } 681 }
607 } 682 }
608 spin_unlock(&cache_defer_lock); 683 spin_unlock(&cache_defer_lock);
@@ -901,7 +976,7 @@ static int cache_release(struct inode *inode, struct file *filp,
901 filp->private_data = NULL; 976 filp->private_data = NULL;
902 kfree(rp); 977 kfree(rp);
903 978
904 cd->last_close = get_seconds(); 979 cd->last_close = seconds_since_boot();
905 atomic_dec(&cd->readers); 980 atomic_dec(&cd->readers);
906 } 981 }
907 module_put(cd->owner); 982 module_put(cd->owner);
@@ -1014,6 +1089,23 @@ static void warn_no_listener(struct cache_detail *detail)
1014 } 1089 }
1015} 1090}
1016 1091
1092static bool cache_listeners_exist(struct cache_detail *detail)
1093{
1094 if (atomic_read(&detail->readers))
1095 return true;
1096 if (detail->last_close == 0)
1097 /* This cache was never opened */
1098 return false;
1099 if (detail->last_close < seconds_since_boot() - 30)
1100 /*
1101 * We allow for the possibility that someone might
1102 * restart a userspace daemon without restarting the
1103 * server; but after 30 seconds, we give up.
1104 */
1105 return false;
1106 return true;
1107}
1108
1017/* 1109/*
1018 * register an upcall request to user-space and queue it up for read() by the 1110 * register an upcall request to user-space and queue it up for read() by the
1019 * upcall daemon. 1111 * upcall daemon.
@@ -1032,10 +1124,9 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h,
1032 char *bp; 1124 char *bp;
1033 int len; 1125 int len;
1034 1126
1035 if (atomic_read(&detail->readers) == 0 && 1127 if (!cache_listeners_exist(detail)) {
1036 detail->last_close < get_seconds() - 30) { 1128 warn_no_listener(detail);
1037 warn_no_listener(detail); 1129 return -EINVAL;
1038 return -EINVAL;
1039 } 1130 }
1040 1131
1041 buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 1132 buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
@@ -1094,13 +1185,19 @@ int qword_get(char **bpp, char *dest, int bufsize)
1094 if (bp[0] == '\\' && bp[1] == 'x') { 1185 if (bp[0] == '\\' && bp[1] == 'x') {
1095 /* HEX STRING */ 1186 /* HEX STRING */
1096 bp += 2; 1187 bp += 2;
1097 while (isxdigit(bp[0]) && isxdigit(bp[1]) && len < bufsize) { 1188 while (len < bufsize) {
1098 int byte = isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10; 1189 int h, l;
1099 bp++; 1190
1100 byte <<= 4; 1191 h = hex_to_bin(bp[0]);
1101 byte |= isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10; 1192 if (h < 0)
1102 *dest++ = byte; 1193 break;
1103 bp++; 1194
1195 l = hex_to_bin(bp[1]);
1196 if (l < 0)
1197 break;
1198
1199 *dest++ = (h << 4) | l;
1200 bp += 2;
1104 len++; 1201 len++;
1105 } 1202 }
1106 } else { 1203 } else {
@@ -1218,7 +1315,8 @@ static int c_show(struct seq_file *m, void *p)
1218 1315
1219 ifdebug(CACHE) 1316 ifdebug(CACHE)
1220 seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n", 1317 seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n",
1221 cp->expiry_time, atomic_read(&cp->ref.refcount), cp->flags); 1318 convert_to_wallclock(cp->expiry_time),
1319 atomic_read(&cp->ref.refcount), cp->flags);
1222 cache_get(cp); 1320 cache_get(cp);
1223 if (cache_check(cd, cp, NULL)) 1321 if (cache_check(cd, cp, NULL))
1224 /* cache_check does a cache_put on failure */ 1322 /* cache_check does a cache_put on failure */
@@ -1284,7 +1382,7 @@ static ssize_t read_flush(struct file *file, char __user *buf,
1284 unsigned long p = *ppos; 1382 unsigned long p = *ppos;
1285 size_t len; 1383 size_t len;
1286 1384
1287 sprintf(tbuf, "%lu\n", cd->flush_time); 1385 sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time));
1288 len = strlen(tbuf); 1386 len = strlen(tbuf);
1289 if (p >= len) 1387 if (p >= len)
1290 return 0; 1388 return 0;
@@ -1302,19 +1400,20 @@ static ssize_t write_flush(struct file *file, const char __user *buf,
1302 struct cache_detail *cd) 1400 struct cache_detail *cd)
1303{ 1401{
1304 char tbuf[20]; 1402 char tbuf[20];
1305 char *ep; 1403 char *bp, *ep;
1306 long flushtime; 1404
1307 if (*ppos || count > sizeof(tbuf)-1) 1405 if (*ppos || count > sizeof(tbuf)-1)
1308 return -EINVAL; 1406 return -EINVAL;
1309 if (copy_from_user(tbuf, buf, count)) 1407 if (copy_from_user(tbuf, buf, count))
1310 return -EFAULT; 1408 return -EFAULT;
1311 tbuf[count] = 0; 1409 tbuf[count] = 0;
1312 flushtime = simple_strtoul(tbuf, &ep, 0); 1410 simple_strtoul(tbuf, &ep, 0);
1313 if (*ep && *ep != '\n') 1411 if (*ep && *ep != '\n')
1314 return -EINVAL; 1412 return -EINVAL;
1315 1413
1316 cd->flush_time = flushtime; 1414 bp = tbuf;
1317 cd->nextcheck = get_seconds(); 1415 cd->flush_time = get_expiry(&bp);
1416 cd->nextcheck = seconds_since_boot();
1318 cache_flush(); 1417 cache_flush();
1319 1418
1320 *ppos += count; 1419 *ppos += count;
@@ -1438,8 +1537,10 @@ static const struct file_operations cache_flush_operations_procfs = {
1438 .llseek = no_llseek, 1537 .llseek = no_llseek,
1439}; 1538};
1440 1539
1441static void remove_cache_proc_entries(struct cache_detail *cd) 1540static void remove_cache_proc_entries(struct cache_detail *cd, struct net *net)
1442{ 1541{
1542 struct sunrpc_net *sn;
1543
1443 if (cd->u.procfs.proc_ent == NULL) 1544 if (cd->u.procfs.proc_ent == NULL)
1444 return; 1545 return;
1445 if (cd->u.procfs.flush_ent) 1546 if (cd->u.procfs.flush_ent)
@@ -1449,15 +1550,18 @@ static void remove_cache_proc_entries(struct cache_detail *cd)
1449 if (cd->u.procfs.content_ent) 1550 if (cd->u.procfs.content_ent)
1450 remove_proc_entry("content", cd->u.procfs.proc_ent); 1551 remove_proc_entry("content", cd->u.procfs.proc_ent);
1451 cd->u.procfs.proc_ent = NULL; 1552 cd->u.procfs.proc_ent = NULL;
1452 remove_proc_entry(cd->name, proc_net_rpc); 1553 sn = net_generic(net, sunrpc_net_id);
1554 remove_proc_entry(cd->name, sn->proc_net_rpc);
1453} 1555}
1454 1556
1455#ifdef CONFIG_PROC_FS 1557#ifdef CONFIG_PROC_FS
1456static int create_cache_proc_entries(struct cache_detail *cd) 1558static int create_cache_proc_entries(struct cache_detail *cd, struct net *net)
1457{ 1559{
1458 struct proc_dir_entry *p; 1560 struct proc_dir_entry *p;
1561 struct sunrpc_net *sn;
1459 1562
1460 cd->u.procfs.proc_ent = proc_mkdir(cd->name, proc_net_rpc); 1563 sn = net_generic(net, sunrpc_net_id);
1564 cd->u.procfs.proc_ent = proc_mkdir(cd->name, sn->proc_net_rpc);
1461 if (cd->u.procfs.proc_ent == NULL) 1565 if (cd->u.procfs.proc_ent == NULL)
1462 goto out_nomem; 1566 goto out_nomem;
1463 cd->u.procfs.channel_ent = NULL; 1567 cd->u.procfs.channel_ent = NULL;
@@ -1488,11 +1592,11 @@ static int create_cache_proc_entries(struct cache_detail *cd)
1488 } 1592 }
1489 return 0; 1593 return 0;
1490out_nomem: 1594out_nomem:
1491 remove_cache_proc_entries(cd); 1595 remove_cache_proc_entries(cd, net);
1492 return -ENOMEM; 1596 return -ENOMEM;
1493} 1597}
1494#else /* CONFIG_PROC_FS */ 1598#else /* CONFIG_PROC_FS */
1495static int create_cache_proc_entries(struct cache_detail *cd) 1599static int create_cache_proc_entries(struct cache_detail *cd, struct net *net)
1496{ 1600{
1497 return 0; 1601 return 0;
1498} 1602}
@@ -1503,23 +1607,33 @@ void __init cache_initialize(void)
1503 INIT_DELAYED_WORK_DEFERRABLE(&cache_cleaner, do_cache_clean); 1607 INIT_DELAYED_WORK_DEFERRABLE(&cache_cleaner, do_cache_clean);
1504} 1608}
1505 1609
1506int cache_register(struct cache_detail *cd) 1610int cache_register_net(struct cache_detail *cd, struct net *net)
1507{ 1611{
1508 int ret; 1612 int ret;
1509 1613
1510 sunrpc_init_cache_detail(cd); 1614 sunrpc_init_cache_detail(cd);
1511 ret = create_cache_proc_entries(cd); 1615 ret = create_cache_proc_entries(cd, net);
1512 if (ret) 1616 if (ret)
1513 sunrpc_destroy_cache_detail(cd); 1617 sunrpc_destroy_cache_detail(cd);
1514 return ret; 1618 return ret;
1515} 1619}
1620
1621int cache_register(struct cache_detail *cd)
1622{
1623 return cache_register_net(cd, &init_net);
1624}
1516EXPORT_SYMBOL_GPL(cache_register); 1625EXPORT_SYMBOL_GPL(cache_register);
1517 1626
1518void cache_unregister(struct cache_detail *cd) 1627void cache_unregister_net(struct cache_detail *cd, struct net *net)
1519{ 1628{
1520 remove_cache_proc_entries(cd); 1629 remove_cache_proc_entries(cd, net);
1521 sunrpc_destroy_cache_detail(cd); 1630 sunrpc_destroy_cache_detail(cd);
1522} 1631}
1632
1633void cache_unregister(struct cache_detail *cd)
1634{
1635 cache_unregister_net(cd, &init_net);
1636}
1523EXPORT_SYMBOL_GPL(cache_unregister); 1637EXPORT_SYMBOL_GPL(cache_unregister);
1524 1638
1525static ssize_t cache_read_pipefs(struct file *filp, char __user *buf, 1639static ssize_t cache_read_pipefs(struct file *filp, char __user *buf,