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 | ||