From 6b6dc4034314fb11d22b39cc2b4af27bc57a439d Mon Sep 17 00:00:00 2001 From: Derrick Brashear Date: Thu, 15 May 2003 18:00:20 +0000 Subject: [PATCH] STABLE12-linux-busy-cache-partition-while-afs-running-and-dont-allow-afsd-shutdown-while-afs-mounted-20030515 FIXES 1454 to preclude superblock corruption and stramge oopses (cherry picked from commit 6c4bb9b335a3e5464007c61b6c4e4f286281ef0b) --- src/afs/LINUX/osi_file.c | 8 ++++-- src/afs/LINUX/osi_misc.c | 52 +++++++++++++++++++++++++------------- src/afs/LINUX/osi_vfsops.c | 8 +++--- src/afs/afs_call.c | 9 ++++--- 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/src/afs/LINUX/osi_file.c b/src/afs/LINUX/osi_file.c index 3eef98f5e..f11d94c60 100644 --- a/src/afs/LINUX/osi_file.c +++ b/src/afs/LINUX/osi_file.c @@ -211,8 +211,12 @@ afs_osi_Write(afile, offset, aptr, asize) size_t resid; register afs_int32 code; AFS_STATCNT(osi_Write); - if ( !afile ) - osi_Panic("afs_osi_Write called with null param"); + if ( !afile ) { + if ( !afs_shuttingdown ) + osi_Panic("afs_osi_Write called with null param"); + else + return EIO; + } if (offset != -1) afile->offset = offset; AFS_GUNLOCK(); code = osi_rdwr(UIO_WRITE, afile, (caddr_t)aptr, asize, &resid); diff --git a/src/afs/LINUX/osi_misc.c b/src/afs/LINUX/osi_misc.c index a3ac7dd39..02cdfe7a1 100644 --- a/src/afs/LINUX/osi_misc.c +++ b/src/afs/LINUX/osi_misc.c @@ -25,37 +25,53 @@ RCSID("$Header$"); char *crash_addr = 0; /* Induce an oops by writing here. */ +#if defined(AFS_LINUX24_ENV) /* Lookup name and return vnode for same. */ -int osi_lookupname(char *aname, uio_seg_t seg, int followlink, - vnode_t **dirvpp, struct dentry **dpp) +int osi_lookupname_internal(char *aname, uio_seg_t seg, int followlink, + vnode_t **dirvpp, struct dentry **dpp, + struct nameidata *nd) { -#if defined(AFS_LINUX24_ENV) - struct nameidata nd; -#else - struct dentry *dp = NULL; -#endif int code; code = ENOENT; -#if defined(AFS_LINUX24_ENV) if (seg == AFS_UIOUSER) { code = followlink ? - user_path_walk(aname, &nd) : user_path_walk_link(aname, &nd); + user_path_walk(aname, nd) : user_path_walk_link(aname, nd); } else { - if (path_init(aname, followlink ? LOOKUP_FOLLOW : 0, &nd)) - code = path_walk(aname, &nd); + if (path_init(aname, followlink ? LOOKUP_FOLLOW : 0, nd)) + code = path_walk(aname, nd); } if (!code) { - if (nd.dentry->d_inode) { - *dpp = dget(nd.dentry); + if (nd->dentry->d_inode) { + *dpp = dget(nd->dentry); code = 0; - } else + } else { code = ENOENT; - path_release(&nd); + path_release(nd); + } } + return code; +} +#endif + +int osi_lookupname(char *aname, uio_seg_t seg, int followlink, + vnode_t **dirvpp, struct dentry **dpp) +{ +#if defined(AFS_LINUX24_ENV) + struct nameidata nd; + int code = osi_lookupname_internal(aname, seg, followlink, dirvpp, dpp, + &nd); + if (!code) + path_release(&nd); + + return (code); #else + struct dentry *dp = NULL; + int code; + + code = ENOENT; if (seg == AFS_UIOUSER) { dp = followlink ? namei(aname) : lnamei(aname); } @@ -71,9 +87,9 @@ int osi_lookupname(char *aname, uio_seg_t seg, int followlink, else dput(dp); } -#endif return code; +#endif } /* Intialize cache device info and fragment size for disk cache partition. */ @@ -85,8 +101,10 @@ int osi_InitCacheInfo(char *aname) extern struct osi_dev cacheDev; extern afs_int32 afs_fsfragsize; extern struct super_block *afs_cacheSBp; + extern struct nameidata afs_cacheNd; - code = osi_lookupname(aname, AFS_UIOSYS, 1, NULL, &dp); + code = osi_lookupname_internal(aname, AFS_UIOSYS, 1, NULL, &dp, + &afs_cacheNd); if (code) return ENOENT; cacheInode = dp->d_inode->i_ino; diff --git a/src/afs/LINUX/osi_vfsops.c b/src/afs/LINUX/osi_vfsops.c index fd200623e..6dc3a1380 100644 --- a/src/afs/LINUX/osi_vfsops.c +++ b/src/afs/LINUX/osi_vfsops.c @@ -31,6 +31,7 @@ RCSID("$Header$"); struct vcache *afs_globalVp = 0; struct vfs *afs_globalVFS = 0; +struct nameidata afs_cacheNd; int afs_was_mounted = 0; /* Used to force reload if mount/unmount/mount */ extern struct super_operations afs_sops; @@ -269,6 +270,7 @@ void afs_put_super(struct super_block *sbp) afs_globalVFS = 0; afs_globalVp = 0; afs_shutdown(); + path_release(&afs_cacheNd); osi_linux_verify_alloced_memory(); done: @@ -336,9 +338,7 @@ int afs_statfs(struct super_block *sbp, struct statfs *statp, int size) void afs_umount_begin(struct super_block *sbp) { - afs_put_super(sbp); afs_shuttingdown=1; - afs_was_mounted=0; } #if defined(AFS_LINUX24_ENV) @@ -348,7 +348,7 @@ struct super_operations afs_sops = { delete_inode: afs_delete_inode, put_super: afs_put_super, statfs: afs_statfs, - umount_begin: NULL /* afs_umount_begin */ + umount_begin: afs_umount_begin }; #else struct super_operations afs_sops = { @@ -362,7 +362,7 @@ struct super_operations afs_sops = { afs_statfs, NULL, /* afs_remount_fs - see doc above */ NULL, /* afs_clear_inode */ - NULL /* afs_umount_begin */ + afs_umount_begin }; #endif diff --git a/src/afs/afs_call.c b/src/afs/afs_call.c index b2d8a9c2b..86bfb36e4 100644 --- a/src/afs/afs_call.c +++ b/src/afs/afs_call.c @@ -732,11 +732,12 @@ long parm, parm2, parm3, parm4, parm5, parm6; afs_cold_shutdown = 0; if (parm == 1) afs_cold_shutdown = 1; #ifndef AFS_DARWIN_ENV - if (afs_globalVFS != 0) - afs_warn("AFS isn't unmounted yet!\n"); + if (afs_globalVFS != 0) { + afs_warn("AFS isn't unmounted yet! Call aborted\n"); + code = EACCES; + } else #endif - - afs_shutdown(); + afs_shutdown(); } #if ! defined(AFS_HPUX90_ENV) || defined(AFS_HPUX100_ENV) -- 2.39.5