diff options
Diffstat (limited to 'net/sunrpc/cache.c')
| -rw-r--r-- | net/sunrpc/cache.c | 319 |
1 files changed, 190 insertions, 129 deletions
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); | ||
