]> err.no Git - linux-2.6/blobdiff - fs/ocfs2/dlmglue.c
ocfs2: Fix up i_blocks calculation to know about holes
[linux-2.6] / fs / ocfs2 / dlmglue.c
index 31d519a6dbd29680587b5e92a761b575c4d8e054..43267eea3538dbb5c0ca183f8828152712aacab2 100644 (file)
@@ -225,11 +225,17 @@ static struct ocfs2_lock_res_ops ocfs2_dentry_lops = {
        .flags          = 0,
 };
 
+static struct ocfs2_lock_res_ops ocfs2_inode_open_lops = {
+       .get_osb        = ocfs2_get_inode_osb,
+       .flags          = 0,
+};
+
 static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres)
 {
        return lockres->l_type == OCFS2_LOCK_TYPE_META ||
                lockres->l_type == OCFS2_LOCK_TYPE_DATA ||
-               lockres->l_type == OCFS2_LOCK_TYPE_RW;
+               lockres->l_type == OCFS2_LOCK_TYPE_RW ||
+               lockres->l_type == OCFS2_LOCK_TYPE_OPEN;
 }
 
 static inline struct inode *ocfs2_lock_res_inode(struct ocfs2_lock_res *lockres)
@@ -373,6 +379,9 @@ void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res,
                case OCFS2_LOCK_TYPE_DATA:
                        ops = &ocfs2_inode_data_lops;
                        break;
+               case OCFS2_LOCK_TYPE_OPEN:
+                       ops = &ocfs2_inode_open_lops;
+                       break;
                default:
                        mlog_bug_on_msg(1, "type: %d\n", type);
                        ops = NULL; /* thanks, gcc */
@@ -1129,6 +1138,12 @@ int ocfs2_create_new_inode_locks(struct inode *inode)
                goto bail;
        }
 
+       ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_open_lockres, 0, 0);
+       if (ret) {
+               mlog_errno(ret);
+               goto bail;
+       }
+
 bail:
        mlog_exit(ret);
        return ret;
@@ -1182,6 +1197,99 @@ void ocfs2_rw_unlock(struct inode *inode, int write)
        mlog_exit_void();
 }
 
+/*
+ * ocfs2_open_lock always get PR mode lock.
+ */
+int ocfs2_open_lock(struct inode *inode)
+{
+       int status = 0;
+       struct ocfs2_lock_res *lockres;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       BUG_ON(!inode);
+
+       mlog_entry_void();
+
+       mlog(0, "inode %llu take PRMODE open lock\n",
+            (unsigned long long)OCFS2_I(inode)->ip_blkno);
+
+       if (ocfs2_mount_local(osb))
+               goto out;
+
+       lockres = &OCFS2_I(inode)->ip_open_lockres;
+
+       status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres,
+                                   LKM_PRMODE, 0, 0);
+       if (status < 0)
+               mlog_errno(status);
+
+out:
+       mlog_exit(status);
+       return status;
+}
+
+int ocfs2_try_open_lock(struct inode *inode, int write)
+{
+       int status = 0, level;
+       struct ocfs2_lock_res *lockres;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       BUG_ON(!inode);
+
+       mlog_entry_void();
+
+       mlog(0, "inode %llu try to take %s open lock\n",
+            (unsigned long long)OCFS2_I(inode)->ip_blkno,
+            write ? "EXMODE" : "PRMODE");
+
+       if (ocfs2_mount_local(osb))
+               goto out;
+
+       lockres = &OCFS2_I(inode)->ip_open_lockres;
+
+       level = write ? LKM_EXMODE : LKM_PRMODE;
+
+       /*
+        * The file system may already holding a PRMODE/EXMODE open lock.
+        * Since we pass LKM_NOQUEUE, the request won't block waiting on
+        * other nodes and the -EAGAIN will indicate to the caller that
+        * this inode is still in use.
+        */
+       status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres,
+                                   level, LKM_NOQUEUE, 0);
+
+out:
+       mlog_exit(status);
+       return status;
+}
+
+/*
+ * ocfs2_open_unlock unlock PR and EX mode open locks.
+ */
+void ocfs2_open_unlock(struct inode *inode)
+{
+       struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_open_lockres;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       mlog_entry_void();
+
+       mlog(0, "inode %llu drop open lock\n",
+            (unsigned long long)OCFS2_I(inode)->ip_blkno);
+
+       if (ocfs2_mount_local(osb))
+               goto out;
+
+       if(lockres->l_ro_holders)
+               ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres,
+                                    LKM_PRMODE);
+       if(lockres->l_ex_holders)
+               ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres,
+                                    LKM_EXMODE);
+
+out:
+       mlog_exit_void();
+}
+
 int ocfs2_data_lock_full(struct inode *inode,
                         int write,
                         int arg_flags)
@@ -1387,8 +1495,7 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
        if (S_ISLNK(inode->i_mode) && !oi->ip_clusters)
                inode->i_blocks = 0;
        else
-               inode->i_blocks =
-                       ocfs2_align_bytes_to_sectors(i_size_read(inode));
+               inode->i_blocks = ocfs2_inode_sector_count(inode);
 
        inode->i_uid     = be32_to_cpu(lvb->lvb_iuid);
        inode->i_gid     = be32_to_cpu(lvb->lvb_igid);
@@ -1506,10 +1613,6 @@ static int ocfs2_meta_lock_update(struct inode *inode,
         * for the inode metadata. */
        ocfs2_metadata_cache_purge(inode);
 
-       /* will do nothing for inode types that don't use the extent
-        * map (bitmap files, etc) */
-       ocfs2_extent_map_trunc(inode, 0);
-
        if (ocfs2_meta_lvb_is_trustable(inode, lockres)) {
                mlog(0, "Trusting LVB on inode %llu\n",
                     (unsigned long long)oi->ip_blkno);
@@ -2455,12 +2558,19 @@ int ocfs2_drop_inode_locks(struct inode *inode)
         * ocfs2_clear_inode has done it for us. */
 
        err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb),
-                             &OCFS2_I(inode)->ip_data_lockres);
+                             &OCFS2_I(inode)->ip_open_lockres);
        if (err < 0)
                mlog_errno(err);
 
        status = err;
 
+       err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb),
+                             &OCFS2_I(inode)->ip_data_lockres);
+       if (err < 0)
+               mlog_errno(err);
+       if (err < 0 && !status)
+               status = err;
+
        err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb),
                              &OCFS2_I(inode)->ip_meta_lockres);
        if (err < 0)