solaris-inode-lock-cleanup-20010711
[openafs.git] / src / afs / SOLARIS / osi_inode.c
index 5941a3a..6c24dd8 100644 (file)
@@ -1,4 +1,12 @@
-/* Copyright (C) 1995 Transarc Corporation - All rights reserved. */
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
 /*
  * SOLARIS inode operations
  *
  *
  */
 #include "../afs/param.h"      /* Should be always first */
+#include <afsconfig.h>
+
+RCSID("$Header$");
+
 #include "../afs/sysincludes.h"        /* Standard vendor system headers */
 #include "../afs/afsincludes.h"        /* Afs-based standard headers */
 #include "../afs/osi_inode.h"
 #include "../afs/afs_stats.h" /* statistics stuff */
 
-extern int (*ufs_iputp)(), (*ufs_iallocp)(), (*ufs_iupdatp)(),  (*ufs_igetp)();
+extern int (*ufs_iallocp)(), (*ufs_iupdatp)(), (*ufs_igetp)(),
+           (*ufs_itimes_nolockp)();
+
+#define AFS_ITIMES(ip) { \
+        mutex_enter(&(ip)->i_tlock); \
+        (*ufs_itimes_nolockp)(ip); \
+        mutex_exit(&(ip)->i_tlock); \
+}
+
+#define AFS_ITIMES_NOLOCK(ip) \
+       (*ufs_itimes_nolockp)(ip);
 
 getinode(vfsp, dev, inode, ipp, credp,perror)
      struct vfs *vfsp;
@@ -26,15 +48,32 @@ getinode(vfsp, dev, inode, ipp, credp,perror)
     struct vnode *vp;
     struct fs *fs;
     struct inode *pip;
+    struct ufsvfs *ufsvfsp;
     
     AFS_STATCNT(getinode);
     
     *perror = 0;
     
-    if (!vfsp && !(vfsp = vfs_devsearch(dev))) {
+    if (!vfsp 
+#if !defined(AFS_SUN58_ENV)
+       && !(vfsp = vfs_devsearch(dev))
+#else
+        && !(vfsp = vfs_dev2vfsp(dev))
+#endif
+       ) {
        return (ENODEV);
     }
-    if (code = (*ufs_igetp)(vfsp, inode, &ip, credp)) {
+    ufsvfsp = (struct ufsvfs *)vfsp->vfs_data;
+
+#if defined(AFS_SUN57_ENV)
+    rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
+#endif
+    code = (*ufs_igetp)(vfsp, inode, &ip, credp);
+#if defined(AFS_SUN57_ENV)
+    rw_exit(&ufsvfsp->vfs_dqrwlock);
+#endif
+
+    if (code) {
        *perror = BAD_IGET;
        return code;
     }
@@ -67,14 +106,16 @@ igetinode(vfsp, dev, inode, ipp, credp,perror)
     
     if (ip->i_mode == 0) {
        /* Not an allocated inode */
+       AFS_ITIMES(ip);
        rw_exit(&ip->i_contents);
-       (*ufs_iputp)(ip);
+       VN_RELE(ITOV(ip));
        return (ENOENT);
     }
     
     if (ip->i_nlink == 0 || (ip->i_mode&IFMT) != IFREG) {
+       AFS_ITIMES(ip);
        rw_exit(&ip->i_contents);
-       (*ufs_iputp)(ip);
+       VN_RELE(ITOV(ip));
        return (ENOENT);
     }
     
@@ -108,6 +149,7 @@ afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp, credp)
     struct inode *ip, *newip;
     register int code;
     dev_t newdev;
+    struct ufsvfs *ufsvfsp;
 
     AFS_STATCNT(afs_syscall_icreate);
     
@@ -128,17 +170,28 @@ afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp, credp)
     if (code) {
        return (code);
     }
-    if (code = (*ufs_iallocp)(ip, near_inode, 0, &newip, credp)) {     
-       (*ufs_iputp)(ip);
+
+    ufsvfsp = ip->i_ufsvfs;
+    rw_enter(&ip->i_rwlock, RW_WRITER);
+#if defined(AFS_SUN57_ENV)
+    rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
+#endif
+    rw_enter(&ip->i_contents, RW_WRITER);
+    code = (*ufs_iallocp)(ip, near_inode, 0, &newip, credp);
+    AFS_ITIMES_NOLOCK(ip);
+    rw_exit(&ip->i_contents);
+#if defined(AFS_SUN57_ENV)
+    rw_exit(&ufsvfsp->vfs_dqrwlock);
+#endif
+    rw_exit(&ip->i_rwlock);
+    VN_RELE(ITOV(ip));
+
+    if (code) {
        return (code);
     }
-    (*ufs_iputp)(ip);
     rw_enter(&newip->i_contents, RW_WRITER);
-    mutex_enter(&newip->i_tlock);
     newip->i_flag |= IACC|IUPD|ICHG;
-    mutex_exit(&newip->i_tlock);
-    
-    
+
 #if    defined(AFS_SUN56_ENV)
     newip->i_vicemagic = VICEMAGIC;
 #else
@@ -170,8 +223,9 @@ afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp, credp)
      */
     if (CrSync)
        (*ufs_iupdatp)(newip, 1);
+    AFS_ITIMES_NOLOCK(newip);
     rw_exit(&newip->i_contents);
-    (*ufs_iputp)(newip);
+    VN_RELE(ITOV(newip));
     return (code);
 }
 
@@ -210,7 +264,10 @@ afs_syscall_iopen(dev, inode, usrmod, rvp, credp)
     }
     code = falloc((struct vnode *)NULL, FWRITE|FREAD, &fp, &fd);
     if (code) {
-       (*ufs_iputp)(ip);
+       rw_enter(&ip->i_contents, RW_READER);
+       AFS_ITIMES(ip);
+       rw_exit(&ip->i_contents);
+       VN_RELE(ITOV(ip));
        return (code);
     }
     
@@ -270,9 +327,13 @@ afs_syscall_iincdec(dev, inode, inode_p1, amount, rvp, credp)
     if (code) {
        return (code);
     }
-    if (!IS_VICEMAGIC(ip))
+    if (!IS_VICEMAGIC(ip)) {
        code = EPERM;
-    else {
+       rw_enter(&ip->i_contents, RW_READER);
+       AFS_ITIMES(ip);
+       rw_exit(&ip->i_contents);
+       VN_RELE(ITOV(ip));
+    } else {
        rw_enter(&ip->i_contents, RW_WRITER);
        ip->i_nlink += amount;
        if (ip->i_nlink == 0) {
@@ -280,15 +341,14 @@ afs_syscall_iincdec(dev, inode, inode_p1, amount, rvp, credp)
            dnlc_remove(ITOV(ip), "a");
            CLEAR_VICEMAGIC(ip);
        }
-       mutex_enter(&ip->i_tlock);
        ip->i_flag |= ICHG;
-       mutex_exit(&ip->i_tlock);
        /* We may want to force the inode to the disk in case of crashes, other references, etc. */
        if (IncSync)
            (*ufs_iupdatp)(ip, 1);
+       AFS_ITIMES_NOLOCK(ip);
        rw_exit(&ip->i_contents);
+       VN_RELE(ITOV(ip));
     }
-    (*ufs_iputp)(ip);
     return (code);
 }