diff options
Diffstat (limited to 'net/sunrpc/cache.c')
| -rw-r--r-- | net/sunrpc/cache.c | 152 |
1 files changed, 93 insertions, 59 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 73f053d0cc7a..636c8e04e0be 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
| @@ -245,6 +245,7 @@ int cache_check(struct cache_detail *detail, | |||
| 245 | cache_put(h, detail); | 245 | cache_put(h, detail); |
| 246 | return rv; | 246 | return rv; |
| 247 | } | 247 | } |
| 248 | EXPORT_SYMBOL(cache_check); | ||
| 248 | 249 | ||
| 249 | /* | 250 | /* |
| 250 | * caches need to be periodically cleaned. | 251 | * caches need to be periodically cleaned. |
| @@ -290,44 +291,78 @@ static const struct file_operations cache_flush_operations; | |||
| 290 | static void do_cache_clean(struct work_struct *work); | 291 | static void do_cache_clean(struct work_struct *work); |
| 291 | static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean); | 292 | static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean); |
| 292 | 293 | ||
| 293 | void cache_register(struct cache_detail *cd) | 294 | static void remove_cache_proc_entries(struct cache_detail *cd) |
| 294 | { | 295 | { |
| 295 | cd->proc_ent = proc_mkdir(cd->name, proc_net_rpc); | 296 | if (cd->proc_ent == NULL) |
| 296 | if (cd->proc_ent) { | 297 | return; |
| 297 | struct proc_dir_entry *p; | 298 | if (cd->flush_ent) |
| 298 | cd->proc_ent->owner = cd->owner; | 299 | remove_proc_entry("flush", cd->proc_ent); |
| 299 | cd->channel_ent = cd->content_ent = NULL; | 300 | if (cd->channel_ent) |
| 301 | remove_proc_entry("channel", cd->proc_ent); | ||
| 302 | if (cd->content_ent) | ||
| 303 | remove_proc_entry("content", cd->proc_ent); | ||
| 304 | cd->proc_ent = NULL; | ||
| 305 | remove_proc_entry(cd->name, proc_net_rpc); | ||
| 306 | } | ||
| 300 | 307 | ||
| 301 | p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR, | 308 | #ifdef CONFIG_PROC_FS |
| 302 | cd->proc_ent); | 309 | static int create_cache_proc_entries(struct cache_detail *cd) |
| 303 | cd->flush_ent = p; | 310 | { |
| 304 | if (p) { | 311 | struct proc_dir_entry *p; |
| 305 | p->proc_fops = &cache_flush_operations; | ||
| 306 | p->owner = cd->owner; | ||
| 307 | p->data = cd; | ||
| 308 | } | ||
| 309 | 312 | ||
| 310 | if (cd->cache_request || cd->cache_parse) { | 313 | cd->proc_ent = proc_mkdir(cd->name, proc_net_rpc); |
| 311 | p = create_proc_entry("channel", S_IFREG|S_IRUSR|S_IWUSR, | 314 | if (cd->proc_ent == NULL) |
| 312 | cd->proc_ent); | 315 | goto out_nomem; |
| 313 | cd->channel_ent = p; | 316 | cd->proc_ent->owner = cd->owner; |
| 314 | if (p) { | 317 | cd->channel_ent = cd->content_ent = NULL; |
| 315 | p->proc_fops = &cache_file_operations; | 318 | |
| 316 | p->owner = cd->owner; | 319 | p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR, cd->proc_ent); |
| 317 | p->data = cd; | 320 | cd->flush_ent = p; |
| 318 | } | 321 | if (p == NULL) |
| 319 | } | 322 | goto out_nomem; |
| 320 | if (cd->cache_show) { | 323 | p->proc_fops = &cache_flush_operations; |
| 321 | p = create_proc_entry("content", S_IFREG|S_IRUSR|S_IWUSR, | 324 | p->owner = cd->owner; |
| 322 | cd->proc_ent); | 325 | p->data = cd; |
| 323 | cd->content_ent = p; | 326 | |
| 324 | if (p) { | 327 | if (cd->cache_request || cd->cache_parse) { |
| 325 | p->proc_fops = &content_file_operations; | 328 | p = create_proc_entry("channel", S_IFREG|S_IRUSR|S_IWUSR, |
| 326 | p->owner = cd->owner; | 329 | cd->proc_ent); |
| 327 | p->data = cd; | 330 | cd->channel_ent = p; |
| 328 | } | 331 | if (p == NULL) |
| 329 | } | 332 | goto out_nomem; |
| 333 | p->proc_fops = &cache_file_operations; | ||
| 334 | p->owner = cd->owner; | ||
| 335 | p->data = cd; | ||
| 330 | } | 336 | } |
| 337 | if (cd->cache_show) { | ||
| 338 | p = create_proc_entry("content", S_IFREG|S_IRUSR|S_IWUSR, | ||
| 339 | cd->proc_ent); | ||
| 340 | cd->content_ent = p; | ||
| 341 | if (p == NULL) | ||
| 342 | goto out_nomem; | ||
| 343 | p->proc_fops = &content_file_operations; | ||
| 344 | p->owner = cd->owner; | ||
| 345 | p->data = cd; | ||
| 346 | } | ||
| 347 | return 0; | ||
| 348 | out_nomem: | ||
| 349 | remove_cache_proc_entries(cd); | ||
| 350 | return -ENOMEM; | ||
| 351 | } | ||
| 352 | #else /* CONFIG_PROC_FS */ | ||
| 353 | static int create_cache_proc_entries(struct cache_detail *cd) | ||
| 354 | { | ||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | #endif | ||
| 358 | |||
| 359 | int cache_register(struct cache_detail *cd) | ||
| 360 | { | ||
| 361 | int ret; | ||
| 362 | |||
| 363 | ret = create_cache_proc_entries(cd); | ||
| 364 | if (ret) | ||
| 365 | return ret; | ||
| 331 | rwlock_init(&cd->hash_lock); | 366 | rwlock_init(&cd->hash_lock); |
| 332 | INIT_LIST_HEAD(&cd->queue); | 367 | INIT_LIST_HEAD(&cd->queue); |
| 333 | spin_lock(&cache_list_lock); | 368 | spin_lock(&cache_list_lock); |
| @@ -341,9 +376,11 @@ void cache_register(struct cache_detail *cd) | |||
| 341 | 376 | ||
| 342 | /* start the cleaning process */ | 377 | /* start the cleaning process */ |
| 343 | schedule_delayed_work(&cache_cleaner, 0); | 378 | schedule_delayed_work(&cache_cleaner, 0); |
| 379 | return 0; | ||
| 344 | } | 380 | } |
| 381 | EXPORT_SYMBOL(cache_register); | ||
| 345 | 382 | ||
| 346 | int cache_unregister(struct cache_detail *cd) | 383 | void cache_unregister(struct cache_detail *cd) |
| 347 | { | 384 | { |
| 348 | cache_purge(cd); | 385 | cache_purge(cd); |
| 349 | spin_lock(&cache_list_lock); | 386 | spin_lock(&cache_list_lock); |
| @@ -351,30 +388,23 @@ int cache_unregister(struct cache_detail *cd) | |||
| 351 | if (cd->entries || atomic_read(&cd->inuse)) { | 388 | if (cd->entries || atomic_read(&cd->inuse)) { |
| 352 | write_unlock(&cd->hash_lock); | 389 | write_unlock(&cd->hash_lock); |
| 353 | spin_unlock(&cache_list_lock); | 390 | spin_unlock(&cache_list_lock); |
| 354 | return -EBUSY; | 391 | goto out; |
| 355 | } | 392 | } |
| 356 | if (current_detail == cd) | 393 | if (current_detail == cd) |
| 357 | current_detail = NULL; | 394 | current_detail = NULL; |
| 358 | list_del_init(&cd->others); | 395 | list_del_init(&cd->others); |
| 359 | write_unlock(&cd->hash_lock); | 396 | write_unlock(&cd->hash_lock); |
| 360 | spin_unlock(&cache_list_lock); | 397 | spin_unlock(&cache_list_lock); |
| 361 | if (cd->proc_ent) { | 398 | remove_cache_proc_entries(cd); |
| 362 | if (cd->flush_ent) | ||
| 363 | remove_proc_entry("flush", cd->proc_ent); | ||
| 364 | if (cd->channel_ent) | ||
| 365 | remove_proc_entry("channel", cd->proc_ent); | ||
| 366 | if (cd->content_ent) | ||
| 367 | remove_proc_entry("content", cd->proc_ent); | ||
| 368 | |||
| 369 | cd->proc_ent = NULL; | ||
| 370 | remove_proc_entry(cd->name, proc_net_rpc); | ||
| 371 | } | ||
| 372 | if (list_empty(&cache_list)) { | 399 | if (list_empty(&cache_list)) { |
| 373 | /* module must be being unloaded so its safe to kill the worker */ | 400 | /* module must be being unloaded so its safe to kill the worker */ |
| 374 | cancel_delayed_work_sync(&cache_cleaner); | 401 | cancel_delayed_work_sync(&cache_cleaner); |
| 375 | } | 402 | } |
| 376 | return 0; | 403 | return; |
| 404 | out: | ||
| 405 | printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); | ||
| 377 | } | 406 | } |
| 407 | EXPORT_SYMBOL(cache_unregister); | ||
| 378 | 408 | ||
| 379 | /* clean cache tries to find something to clean | 409 | /* clean cache tries to find something to clean |
| 380 | * and cleans it. | 410 | * and cleans it. |
| @@ -489,6 +519,7 @@ void cache_flush(void) | |||
| 489 | while (cache_clean() != -1) | 519 | while (cache_clean() != -1) |
| 490 | cond_resched(); | 520 | cond_resched(); |
| 491 | } | 521 | } |
| 522 | EXPORT_SYMBOL(cache_flush); | ||
| 492 | 523 | ||
| 493 | void cache_purge(struct cache_detail *detail) | 524 | void cache_purge(struct cache_detail *detail) |
| 494 | { | 525 | { |
| @@ -497,7 +528,7 @@ void cache_purge(struct cache_detail *detail) | |||
| 497 | cache_flush(); | 528 | cache_flush(); |
| 498 | detail->flush_time = 1; | 529 | detail->flush_time = 1; |
| 499 | } | 530 | } |
| 500 | 531 | EXPORT_SYMBOL(cache_purge); | |
| 501 | 532 | ||
| 502 | 533 | ||
| 503 | /* | 534 | /* |
| @@ -634,13 +665,13 @@ void cache_clean_deferred(void *owner) | |||
| 634 | /* | 665 | /* |
| 635 | * communicate with user-space | 666 | * communicate with user-space |
| 636 | * | 667 | * |
| 637 | * We have a magic /proc file - /proc/sunrpc/cache | 668 | * We have a magic /proc file - /proc/sunrpc/<cachename>/channel. |
| 638 | * On read, you get a full request, or block | 669 | * On read, you get a full request, or block. |
| 639 | * On write, an update request is processed | 670 | * On write, an update request is processed. |
| 640 | * Poll works if anything to read, and always allows write | 671 | * Poll works if anything to read, and always allows write. |
| 641 | * | 672 | * |
| 642 | * Implemented by linked list of requests. Each open file has | 673 | * Implemented by linked list of requests. Each open file has |
| 643 | * a ->private that also exists in this list. New request are added | 674 | * a ->private that also exists in this list. New requests are added |
| 644 | * to the end and may wakeup and preceding readers. | 675 | * to the end and may wakeup and preceding readers. |
| 645 | * New readers are added to the head. If, on read, an item is found with | 676 | * New readers are added to the head. If, on read, an item is found with |
| 646 | * CACHE_UPCALLING clear, we free it from the list. | 677 | * CACHE_UPCALLING clear, we free it from the list. |
| @@ -963,6 +994,7 @@ void qword_add(char **bpp, int *lp, char *str) | |||
| 963 | *bpp = bp; | 994 | *bpp = bp; |
| 964 | *lp = len; | 995 | *lp = len; |
| 965 | } | 996 | } |
| 997 | EXPORT_SYMBOL(qword_add); | ||
| 966 | 998 | ||
| 967 | void qword_addhex(char **bpp, int *lp, char *buf, int blen) | 999 | void qword_addhex(char **bpp, int *lp, char *buf, int blen) |
| 968 | { | 1000 | { |
| @@ -991,6 +1023,7 @@ void qword_addhex(char **bpp, int *lp, char *buf, int blen) | |||
| 991 | *bpp = bp; | 1023 | *bpp = bp; |
| 992 | *lp = len; | 1024 | *lp = len; |
| 993 | } | 1025 | } |
| 1026 | EXPORT_SYMBOL(qword_addhex); | ||
| 994 | 1027 | ||
| 995 | static void warn_no_listener(struct cache_detail *detail) | 1028 | static void warn_no_listener(struct cache_detail *detail) |
| 996 | { | 1029 | { |
| @@ -1113,6 +1146,7 @@ int qword_get(char **bpp, char *dest, int bufsize) | |||
| 1113 | *dest = '\0'; | 1146 | *dest = '\0'; |
| 1114 | return len; | 1147 | return len; |
| 1115 | } | 1148 | } |
| 1149 | EXPORT_SYMBOL(qword_get); | ||
| 1116 | 1150 | ||
| 1117 | 1151 | ||
| 1118 | /* | 1152 | /* |
| @@ -1244,18 +1278,18 @@ static ssize_t read_flush(struct file *file, char __user *buf, | |||
| 1244 | struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data; | 1278 | struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data; |
| 1245 | char tbuf[20]; | 1279 | char tbuf[20]; |
| 1246 | unsigned long p = *ppos; | 1280 | unsigned long p = *ppos; |
| 1247 | int len; | 1281 | size_t len; |
| 1248 | 1282 | ||
| 1249 | sprintf(tbuf, "%lu\n", cd->flush_time); | 1283 | sprintf(tbuf, "%lu\n", cd->flush_time); |
| 1250 | len = strlen(tbuf); | 1284 | len = strlen(tbuf); |
| 1251 | if (p >= len) | 1285 | if (p >= len) |
| 1252 | return 0; | 1286 | return 0; |
| 1253 | len -= p; | 1287 | len -= p; |
| 1254 | if (len > count) len = count; | 1288 | if (len > count) |
| 1289 | len = count; | ||
| 1255 | if (copy_to_user(buf, (void*)(tbuf+p), len)) | 1290 | if (copy_to_user(buf, (void*)(tbuf+p), len)) |
| 1256 | len = -EFAULT; | 1291 | return -EFAULT; |
| 1257 | else | 1292 | *ppos += len; |
| 1258 | *ppos += len; | ||
| 1259 | return len; | 1293 | return len; |
| 1260 | } | 1294 | } |
| 1261 | 1295 | ||
