• Al Viro's avatar
    Revert "fs: fold open_check_o_direct into do_dentry_open" · af04fadc
    Al Viro authored
    This reverts commit cab64df1.
    
    Having vfs_open() in some cases drop the reference to
    struct file combined with
    
    	error = vfs_open(path, f, cred);
    	if (error) {
    		put_filp(f);
    		return ERR_PTR(error);
    	}
    	return f;
    
    is flat-out wrong.  It used to be
    
    		error = vfs_open(path, f, cred);
    		if (!error) {
    			/* from now on we need fput() to dispose of f */
    			error = open_check_o_direct(f);
    			if (error) {
    				fput(f);
    				f = ERR_PTR(error);
    			}
    		} else {
    			put_filp(f);
    			f = ERR_PTR(error);
    		}
    
    and sure, having that open_check_o_direct() boilerplate gotten rid of is
    nice, but not that way...
    
    Worse, another call chain (via finish_open()) is FUBAR now wrt
    FILE_OPENED handling - in that case we get error returned, with file
    already hit by fput() *AND* FILE_OPENED not set.  Guess what happens in
    path_openat(), when it hits
    
    	if (!(opened & FILE_OPENED)) {
    		BUG_ON(!error);
    		put_filp(file);
    	}
    
    The root cause of all that crap is that the callers of do_dentry_open()
    have no way to tell which way did it fail; while that could be fixed up
    (by passing something like int *opened to do_dentry_open() and have it
    marked if we'd called ->open()), it's probably much too late in the
    cycle to do so right now.
    Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    af04fadc