Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

knfsd: allow cache_register to return error on failure

Newer server features such as nfsv4 and gss depend on proc to work, so a
failure to initialize the proc files they need should be treated as
fatal.

Thanks to Andrew Morton for style fix and compile fix in case where
CONFIG_NFSD_V4 is undefined.

Cc: Andrew Morton <akpm@linux-foundation.org>
Acked-by: NeilBrown <neilb@suse.de>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>

+75 -26
+9 -3
fs/nfsd/export.c
··· 1637 1637 /* 1638 1638 * Initialize the exports module. 1639 1639 */ 1640 - void 1640 + int 1641 1641 nfsd_export_init(void) 1642 1642 { 1643 + int rv; 1643 1644 dprintk("nfsd: initializing export module.\n"); 1644 1645 1645 - cache_register(&svc_export_cache); 1646 - cache_register(&svc_expkey_cache); 1646 + rv = cache_register(&svc_export_cache); 1647 + if (rv) 1648 + return rv; 1649 + rv = cache_register(&svc_expkey_cache); 1650 + if (rv) 1651 + cache_unregister(&svc_export_cache); 1652 + return rv; 1647 1653 1648 1654 } 1649 1655
+10 -3
fs/nfsd/nfs4idmap.c
··· 464 464 * Exported API 465 465 */ 466 466 467 - void 467 + int 468 468 nfsd_idmap_init(void) 469 469 { 470 - cache_register(&idtoname_cache); 471 - cache_register(&nametoid_cache); 470 + int rv; 471 + 472 + rv = cache_register(&idtoname_cache); 473 + if (rv) 474 + return rv; 475 + rv = cache_register(&nametoid_cache); 476 + if (rv) 477 + cache_unregister(&idtoname_cache); 478 + return rv; 472 479 } 473 480 474 481 void
+9 -3
fs/nfsd/nfsctl.c
··· 707 707 retval = nfsd_reply_cache_init(); 708 708 if (retval) 709 709 goto out_free_stat; 710 - nfsd_export_init(); /* Exports table */ 710 + retval = nfsd_export_init(); 711 + if (retval) 712 + goto out_free_cache; 711 713 nfsd_lockd_init(); /* lockd->nfsd callbacks */ 712 - nfsd_idmap_init(); /* Name to ID mapping */ 714 + retval = nfsd_idmap_init(); 715 + if (retval) 716 + goto out_free_lockd; 713 717 retval = create_proc_exports_entry(); 714 718 if (retval) 715 719 goto out_free_idmap; ··· 724 720 out_free_all: 725 721 remove_proc_entry("fs/nfs/exports", NULL); 726 722 remove_proc_entry("fs/nfs", NULL); 727 - nfsd_idmap_shutdown(); 728 723 out_free_idmap: 724 + nfsd_idmap_shutdown(); 725 + out_free_lockd: 729 726 nfsd_lockd_shutdown(); 730 727 nfsd_export_shutdown(); 728 + out_free_cache: 731 729 nfsd_reply_cache_shutdown(); 732 730 out_free_stat: 733 731 nfsd_stat_shutdown();
+1 -1
include/linux/nfsd/export.h
··· 122 122 /* 123 123 * Function declarations 124 124 */ 125 - void nfsd_export_init(void); 125 + int nfsd_export_init(void); 126 126 void nfsd_export_shutdown(void); 127 127 void nfsd_export_flush(void); 128 128 void exp_readlock(void);
+8 -3
include/linux/nfsd_idmap.h
··· 44 44 #define IDMAP_NAMESZ 128 45 45 46 46 #ifdef CONFIG_NFSD_V4 47 - void nfsd_idmap_init(void); 47 + int nfsd_idmap_init(void); 48 48 void nfsd_idmap_shutdown(void); 49 49 #else 50 - static inline void nfsd_idmap_init(void) {}; 51 - static inline void nfsd_idmap_shutdown(void) {}; 50 + static inline int nfsd_idmap_init(void) 51 + { 52 + return 0; 53 + } 54 + static inline void nfsd_idmap_shutdown(void) 55 + { 56 + } 52 57 #endif 53 58 54 59 int nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, __u32 *);
+1 -1
include/linux/sunrpc/cache.h
··· 169 169 extern void cache_flush(void); 170 170 extern void cache_purge(struct cache_detail *detail); 171 171 #define NEVER (0x7FFFFFFF) 172 - extern void cache_register(struct cache_detail *cd); 172 + extern int cache_register(struct cache_detail *cd); 173 173 extern void cache_unregister(struct cache_detail *cd); 174 174 175 175 extern void qword_add(char **bpp, int *lp, char *str);
+13 -4
net/sunrpc/auth_gss/svcauth_gss.c
··· 1386 1386 gss_svc_init(void) 1387 1387 { 1388 1388 int rv = svc_auth_register(RPC_AUTH_GSS, &svcauthops_gss); 1389 - if (rv == 0) { 1390 - cache_register(&rsc_cache); 1391 - cache_register(&rsi_cache); 1392 - } 1389 + if (rv) 1390 + return rv; 1391 + rv = cache_register(&rsc_cache); 1392 + if (rv) 1393 + goto out1; 1394 + rv = cache_register(&rsi_cache); 1395 + if (rv) 1396 + goto out2; 1397 + return 0; 1398 + out2: 1399 + cache_unregister(&rsc_cache); 1400 + out1: 1401 + svc_auth_unregister(RPC_AUTH_GSS); 1393 1402 return rv; 1394 1403 } 1395 1404
+24 -8
net/sunrpc/cache.c
··· 304 304 remove_proc_entry(cd->name, proc_net_rpc); 305 305 } 306 306 307 - static void create_cache_proc_entries(struct cache_detail *cd) 307 + #ifdef CONFIG_PROC_FS 308 + static int create_cache_proc_entries(struct cache_detail *cd) 308 309 { 309 310 struct proc_dir_entry *p; 310 311 311 312 cd->proc_ent = proc_mkdir(cd->name, proc_net_rpc); 312 313 if (cd->proc_ent == NULL) 313 - return; 314 + goto out_nomem; 314 315 cd->proc_ent->owner = cd->owner; 315 316 cd->channel_ent = cd->content_ent = NULL; 316 317 317 318 p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR, cd->proc_ent); 318 319 cd->flush_ent = p; 319 320 if (p == NULL) 320 - return; 321 + goto out_nomem; 321 322 p->proc_fops = &cache_flush_operations; 322 323 p->owner = cd->owner; 323 324 p->data = cd; ··· 328 327 cd->proc_ent); 329 328 cd->channel_ent = p; 330 329 if (p == NULL) 331 - return; 330 + goto out_nomem; 332 331 p->proc_fops = &cache_file_operations; 333 332 p->owner = cd->owner; 334 333 p->data = cd; ··· 338 337 cd->proc_ent); 339 338 cd->content_ent = p; 340 339 if (p == NULL) 341 - return; 340 + goto out_nomem; 342 341 p->proc_fops = &content_file_operations; 343 342 p->owner = cd->owner; 344 343 p->data = cd; 345 344 } 345 + return 0; 346 + out_nomem: 347 + remove_cache_proc_entries(cd); 348 + return -ENOMEM; 346 349 } 347 - 348 - void cache_register(struct cache_detail *cd) 350 + #else /* CONFIG_PROC_FS */ 351 + static int create_cache_proc_entries(struct cache_detail *cd) 349 352 { 350 - create_cache_proc_entries(cd); 353 + return 0; 354 + } 355 + #endif 356 + 357 + int cache_register(struct cache_detail *cd) 358 + { 359 + int ret; 360 + 361 + ret = create_cache_proc_entries(cd); 362 + if (ret) 363 + return ret; 351 364 rwlock_init(&cd->hash_lock); 352 365 INIT_LIST_HEAD(&cd->queue); 353 366 spin_lock(&cache_list_lock); ··· 375 360 376 361 /* start the cleaning process */ 377 362 schedule_delayed_work(&cache_cleaner, 0); 363 + return 0; 378 364 } 379 365 380 366 void cache_unregister(struct cache_detail *cd)