Untangling ima mess, part 2: deal with counters

* do ima_get_count() in __dentry_open()
* stop doing that in followups
* move ima_path_check() to right after nameidata_to_filp()
* don't bump counters on it

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
index a6c8c6f..1d83325 100644
--- a/fs/cachefiles/rdwr.c
+++ b/fs/cachefiles/rdwr.c
@@ -11,7 +11,6 @@
 
 #include <linux/mount.h>
 #include <linux/file.h>
-#include <linux/ima.h>
 #include "internal.h"
 
 /*
@@ -923,7 +922,6 @@
 	if (IS_ERR(file)) {
 		ret = PTR_ERR(file);
 	} else {
-		ima_counts_get(file);
 		ret = -EIO;
 		if (file->f_op->write) {
 			pos = (loff_t) page->index << PAGE_SHIFT;
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index c6ac85d..101fe4c 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -35,7 +35,6 @@
 #include <linux/key.h>
 #include <linux/parser.h>
 #include <linux/fs_stack.h>
-#include <linux/ima.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -119,7 +118,6 @@
 	const struct cred *cred = current_cred();
 	struct ecryptfs_inode_info *inode_info =
 		ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
-	int opened_lower_file = 0;
 	int rc = 0;
 
 	mutex_lock(&inode_info->lower_file_mutex);
@@ -136,12 +134,9 @@
 			       "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
 			       "rc = [%d]\n", lower_dentry, lower_mnt, rc);
 			inode_info->lower_file = NULL;
-		} else
-			opened_lower_file = 1;
+		}
 	}
 	mutex_unlock(&inode_info->lower_file_mutex);
-	if (opened_lower_file)
-		ima_counts_get(inode_info->lower_file);
 	return rc;
 }
 
diff --git a/fs/namei.c b/fs/namei.c
index 0f0fccc..c530e5d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1461,14 +1461,7 @@
 	/*
 	 * Ensure there are no outstanding leases on the file.
 	 */
-	error = break_lease(inode, flag);
-	if (error)
-		return error;
-
-	return ima_path_check(path, acc_mode ?
-			       acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) :
-			       ACC_MODE(flag) & (MAY_READ | MAY_WRITE),
-			       IMA_COUNT_UPDATE);
+	return break_lease(inode, flag);
 }
 
 static int handle_truncate(struct path *path)
@@ -1688,13 +1681,17 @@
 			goto exit;
 		}
 		filp = nameidata_to_filp(&nd, open_flag);
-		if (IS_ERR(filp))
-			ima_counts_put(&nd.path,
-				       acc_mode & (MAY_READ | MAY_WRITE |
-						   MAY_EXEC));
 		mnt_drop_write(nd.path.mnt);
 		if (nd.root.mnt)
 			path_put(&nd.root);
+		if (!IS_ERR(filp)) {
+			error = ima_path_check(&filp->f_path, filp->f_mode &
+				       (MAY_READ | MAY_WRITE | MAY_EXEC), 0);
+			if (error) {
+				fput(filp);
+				filp = ERR_PTR(error);
+			}
+		}
 		return filp;
 	}
 
@@ -1748,27 +1745,24 @@
 		goto exit;
 	}
 	filp = nameidata_to_filp(&nd, open_flag);
-	if (IS_ERR(filp)) {
-		ima_counts_put(&nd.path,
-			       acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC));
-		if (will_truncate)
-			mnt_drop_write(nd.path.mnt);
-		if (nd.root.mnt)
-			path_put(&nd.root);
-		return filp;
-	}
-
-	if (acc_mode & MAY_WRITE)
-		vfs_dq_init(nd.path.dentry->d_inode);
-
-	if (will_truncate) {
-		error = handle_truncate(&nd.path);
+	if (!IS_ERR(filp)) {
+		error = ima_path_check(&filp->f_path, filp->f_mode &
+			       (MAY_READ | MAY_WRITE | MAY_EXEC), 0);
 		if (error) {
-			mnt_drop_write(nd.path.mnt);
 			fput(filp);
-			if (nd.root.mnt)
-				path_put(&nd.root);
-			return ERR_PTR(error);
+			filp = ERR_PTR(error);
+		}
+	}
+	if (!IS_ERR(filp)) {
+		if (acc_mode & MAY_WRITE)
+			vfs_dq_init(nd.path.dentry->d_inode);
+
+		if (will_truncate) {
+			error = handle_truncate(&nd.path);
+			if (error) {
+				fput(filp);
+				filp = ERR_PTR(error);
+			}
 		}
 	}
 	/*
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index a293f02..c9942b3 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -744,8 +744,6 @@
 			    flags, current_cred());
 	if (IS_ERR(*filp))
 		host_err = PTR_ERR(*filp);
-	else
-		ima_counts_get(*filp);
 out_nfserr:
 	err = nfserrno(host_err);
 out:
diff --git a/fs/open.c b/fs/open.c
index d95651e..ca69241 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -30,6 +30,7 @@
 #include <linux/audit.h>
 #include <linux/falloc.h>
 #include <linux/fs_struct.h>
+#include <linux/ima.h>
 
 #include "internal.h"
 
@@ -857,6 +858,7 @@
 		if (error)
 			goto cleanup_all;
 	}
+	ima_counts_get(f);
 
 	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index ee9d697..c79bd57 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -32,7 +32,6 @@
 #include <linux/nsproxy.h>
 #include <linux/pid.h>
 #include <linux/ipc_namespace.h>
-#include <linux/ima.h>
 
 #include <net/sock.h>
 #include "util.h"
@@ -734,7 +733,6 @@
 		error = PTR_ERR(filp);
 		goto out_putfd;
 	}
-	ima_counts_get(filp);
 
 	fd_install(fd, filp);
 	goto out_upsem;