Merge branch 'for-linus' of git://neil.brown.name/md
[pandora-kernel.git] / fs / gfs2 / super.c
index b7beadd..71e4209 100644 (file)
@@ -752,51 +752,77 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc)
        struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct address_space *metamapping = gfs2_glock2aspace(ip->i_gl);
        struct backing_dev_info *bdi = metamapping->backing_dev_info;
-       struct gfs2_holder gh;
+       int ret = 0;
+
+       if (wbc->sync_mode == WB_SYNC_ALL)
+               gfs2_log_flush(GFS2_SB(inode), ip->i_gl);
+       if (bdi->dirty_exceeded)
+               gfs2_ail1_flush(sdp, wbc);
+       else
+               filemap_fdatawrite(metamapping);
+       if (wbc->sync_mode == WB_SYNC_ALL)
+               ret = filemap_fdatawait(metamapping);
+       if (ret)
+               mark_inode_dirty_sync(inode);
+       return ret;
+}
+
+/**
+ * gfs2_dirty_inode - check for atime updates
+ * @inode: The inode in question
+ * @flags: The type of dirty
+ *
+ * Unfortunately it can be called under any combination of inode
+ * glock and transaction lock, so we have to check carefully.
+ *
+ * At the moment this deals only with atime - it should be possible
+ * to expand that role in future, once a review of the locking has
+ * been carried out.
+ */
+
+static void gfs2_dirty_inode(struct inode *inode, int flags)
+{
+       struct gfs2_inode *ip = GFS2_I(inode);
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct buffer_head *bh;
-       struct timespec atime;
-       struct gfs2_dinode *di;
-       int ret = -EAGAIN;
-       int unlock_required = 0;
-
-       /* Skip timestamp update, if this is from a memalloc */
-       if (current->flags & PF_MEMALLOC)
-               goto do_flush;
+       struct gfs2_holder gh;
+       int need_unlock = 0;
+       int need_endtrans = 0;
+       int ret;
+
+       if (!(flags & (I_DIRTY_DATASYNC|I_DIRTY_SYNC)))
+               return;
+
        if (!gfs2_glock_is_locked_by_me(ip->i_gl)) {
                ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
-               if (ret)
-                       goto do_flush;
-               unlock_required = 1;
+               if (ret) {
+                       fs_err(sdp, "dirty_inode: glock %d\n", ret);
+                       return;
+               }
+               need_unlock = 1;
        }
-       ret = gfs2_trans_begin(sdp, RES_DINODE, 0);
-       if (ret)
-               goto do_unlock;
+
+       if (current->journal_info == NULL) {
+               ret = gfs2_trans_begin(sdp, RES_DINODE, 0);
+               if (ret) {
+                       fs_err(sdp, "dirty_inode: gfs2_trans_begin %d\n", ret);
+                       goto out;
+               }
+               need_endtrans = 1;
+       }
+
        ret = gfs2_meta_inode_buffer(ip, &bh);
        if (ret == 0) {
-               di = (struct gfs2_dinode *)bh->b_data;
-               atime.tv_sec = be64_to_cpu(di->di_atime);
-               atime.tv_nsec = be32_to_cpu(di->di_atime_nsec);
-               if (timespec_compare(&inode->i_atime, &atime) > 0) {
-                       gfs2_trans_add_bh(ip->i_gl, bh, 1);
-                       gfs2_dinode_out(ip, bh->b_data);
-               }
+               gfs2_trans_add_bh(ip->i_gl, bh, 1);
+               gfs2_dinode_out(ip, bh->b_data);
                brelse(bh);
        }
-       gfs2_trans_end(sdp);
-do_unlock:
-       if (unlock_required)
+
+       if (need_endtrans)
+               gfs2_trans_end(sdp);
+out:
+       if (need_unlock)
                gfs2_glock_dq_uninit(&gh);
-do_flush:
-       if (wbc->sync_mode == WB_SYNC_ALL)
-               gfs2_log_flush(GFS2_SB(inode), ip->i_gl);
-       filemap_fdatawrite(metamapping);
-       if (bdi->dirty_exceeded)
-               gfs2_ail1_flush(sdp, wbc);
-       if (!ret && (wbc->sync_mode == WB_SYNC_ALL))
-               ret = filemap_fdatawait(metamapping);
-       if (ret)
-               mark_inode_dirty_sync(inode);
-       return ret;
 }
 
 /**
@@ -1011,7 +1037,6 @@ static int statfs_slow_fill(struct gfs2_rgrpd *rgd,
 
 static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc)
 {
-       struct gfs2_holder ri_gh;
        struct gfs2_rgrpd *rgd_next;
        struct gfs2_holder *gha, *gh;
        unsigned int slots = 64;
@@ -1024,10 +1049,6 @@ static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host
        if (!gha)
                return -ENOMEM;
 
-       error = gfs2_rindex_hold(sdp, &ri_gh);
-       if (error)
-               goto out;
-
        rgd_next = gfs2_rgrpd_get_first(sdp);
 
        for (;;) {
@@ -1070,9 +1091,6 @@ static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host
                yield();
        }
 
-       gfs2_glock_dq_uninit(&ri_gh);
-
-out:
        kfree(gha);
        return error;
 }
@@ -1124,6 +1142,10 @@ static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf)
        struct gfs2_statfs_change_host sc;
        int error;
 
+       error = gfs2_rindex_update(sdp);
+       if (error)
+               return error;
+
        if (gfs2_tune_get(sdp, gt_statfs_slow))
                error = gfs2_statfs_slow(sdp, &sc);
        else
@@ -1394,21 +1416,17 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip)
        if (error)
                goto out;
 
-       error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
-       if (error)
-               goto out_qs;
-
        rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
        if (!rgd) {
                gfs2_consist_inode(ip);
                error = -EIO;
-               goto out_rindex_relse;
+               goto out_qs;
        }
 
        error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0,
                                   &al->al_rgd_gh);
        if (error)
-               goto out_rindex_relse;
+               goto out_qs;
 
        error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS + RES_QUOTA,
                                 sdp->sd_jdesc->jd_blocks);
@@ -1423,8 +1441,6 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip)
 
 out_rg_gunlock:
        gfs2_glock_dq_uninit(&al->al_rgd_gh);
-out_rindex_relse:
-       gfs2_glock_dq_uninit(&al->al_ri_gh);
 out_qs:
        gfs2_quota_unhold(ip);
 out:
@@ -1471,9 +1487,11 @@ static void gfs2_evict_inode(struct inode *inode)
                goto out;
        }
 
-       error = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED);
-       if (error)
-               goto out_truncate;
+       if (!test_bit(GIF_ALLOC_FAILED, &ip->i_flags)) {
+               error = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED);
+               if (error)
+                       goto out_truncate;
+       }
 
        if (test_bit(GIF_INVALID, &ip->i_flags)) {
                error = gfs2_inode_refresh(ip);
@@ -1513,6 +1531,10 @@ static void gfs2_evict_inode(struct inode *inode)
        goto out_unlock;
 
 out_truncate:
+       gfs2_log_flush(sdp, ip->i_gl);
+       write_inode_now(inode, 1);
+       gfs2_ail_flush(ip->i_gl, 0);
+
        /* Case 2 starts here */
        error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
        if (error)
@@ -1552,6 +1574,7 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb)
        if (ip) {
                ip->i_flags = 0;
                ip->i_gl = NULL;
+               ip->i_rgd = NULL;
        }
        return &ip->i_inode;
 }
@@ -1572,6 +1595,7 @@ const struct super_operations gfs2_super_ops = {
        .alloc_inode            = gfs2_alloc_inode,
        .destroy_inode          = gfs2_destroy_inode,
        .write_inode            = gfs2_write_inode,
+       .dirty_inode            = gfs2_dirty_inode,
        .evict_inode            = gfs2_evict_inode,
        .put_super              = gfs2_put_super,
        .sync_fs                = gfs2_sync_fs,