]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - fs/gfs2/ops_super.c
[GFS2] Clean up journaled data writing
[mirror_ubuntu-bionic-kernel.git] / fs / gfs2 / ops_super.c
index b89999d3a7679cb0c17c30dfd78a750df826cea4..950f31460e8b756d64967e22abca0c51709d4f03 100644 (file)
@@ -92,7 +92,6 @@ static void gfs2_put_super(struct super_block *sb)
        kthread_stop(sdp->sd_recoverd_process);
        while (sdp->sd_glockd_num--)
                kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]);
-       kthread_stop(sdp->sd_scand_process);
 
        if (!(sb->s_flags & MS_RDONLY)) {
                error = gfs2_make_fs_ro(sdp);
@@ -283,6 +282,31 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
        return error;
 }
 
+/**
+ * gfs2_drop_inode - Drop an inode (test for remote unlink)
+ * @inode: The inode to drop
+ *
+ * If we've received a callback on an iopen lock then its because a
+ * remote node tried to deallocate the inode but failed due to this node
+ * still having the inode open. Here we mark the link count zero
+ * since we know that it must have reached zero if the GLF_DEMOTE flag
+ * is set on the iopen glock. If we didn't do a disk read since the
+ * remote node removed the final link then we might otherwise miss
+ * this event. This check ensures that this node will deallocate the
+ * inode's blocks, or alternatively pass the baton on to another
+ * node for later deallocation.
+ */
+static void gfs2_drop_inode(struct inode *inode)
+{
+       if (inode->i_private && inode->i_nlink) {
+               struct gfs2_inode *ip = GFS2_I(inode);
+               struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
+               if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags))
+                       clear_nlink(inode);
+       }
+       generic_drop_inode(inode);
+}
+
 /**
  * gfs2_clear_inode - Deallocate an inode when VFS is done with it
  * @inode: The VFS inode
@@ -301,8 +325,10 @@ static void gfs2_clear_inode(struct inode *inode)
                gfs2_glock_schedule_for_reclaim(ip->i_gl);
                gfs2_glock_put(ip->i_gl);
                ip->i_gl = NULL;
-               if (ip->i_iopen_gh.gh_gl)
+               if (ip->i_iopen_gh.gh_gl) {
+                       ip->i_iopen_gh.gh_gl->gl_object = NULL;
                        gfs2_glock_dq_uninit(&ip->i_iopen_gh);
+               }
        }
 }
 
@@ -397,13 +423,13 @@ static void gfs2_delete_inode(struct inode *inode)
        if (!inode->i_private)
                goto out;
 
-       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB, &gh);
+       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        if (unlikely(error)) {
                gfs2_glock_dq_uninit(&ip->i_iopen_gh);
                goto out;
        }
 
-       gfs2_glock_dq(&ip->i_iopen_gh);
+       gfs2_glock_dq_wait(&ip->i_iopen_gh);
        gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh);
        error = gfs2_glock_nq(&ip->i_iopen_gh);
        if (error)
@@ -429,19 +455,22 @@ static void gfs2_delete_inode(struct inode *inode)
        }
 
        error = gfs2_dinode_dealloc(ip);
-       /*
-        * Must do this before unlock to avoid trying to write back
-        * potentially dirty data now that inode no longer exists
-        * on disk.
-        */
+       if (error)
+               goto out_unlock;
+
+       error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
+       if (error)
+               goto out_unlock;
+       /* Needs to be done before glock release & also in a transaction */
        truncate_inode_pages(&inode->i_data, 0);
+       gfs2_trans_end(sdp);
 
 out_unlock:
        gfs2_glock_dq(&ip->i_iopen_gh);
 out_uninit:
        gfs2_holder_uninit(&ip->i_iopen_gh);
        gfs2_glock_dq_uninit(&gh);
-       if (error)
+       if (error && error != GLR_TRYFAILED)
                fs_warn(sdp, "gfs2_delete_inode: %d\n", error);
 out:
        truncate_inode_pages(&inode->i_data, 0);
@@ -481,6 +510,7 @@ const struct super_operations gfs2_super_ops = {
        .statfs                 = gfs2_statfs,
        .remount_fs             = gfs2_remount_fs,
        .clear_inode            = gfs2_clear_inode,
+       .drop_inode             = gfs2_drop_inode,
        .show_options           = gfs2_show_options,
 };