Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3fe03deb authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull vfs fixes from Al Viro:
 "atomic_open-related fixes (Miklos' series, with EEXIST-related parts
  replaced with fix in fs/namei.c:atomic_open() instead of messing with
  the instances) + race fix in autofs + leak on failure exit in 9p"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  9p: don't forget to destroy inode cache if fscache registration fails
  atomic_open: take care of EEXIST in no-open case with O_CREAT|O_EXCL in fs/namei.c
  vfs: don't set FILE_CREATED before calling ->atomic_open()
  nfs: set FILE_CREATED
  gfs2: set FILE_CREATED
  cifs: fix filp leak in cifs_atomic_open()
  vfs: improve i_op->atomic_open() documentation
  autofs4: close the races around autofs4_notify_daemon()
parents 9baa5059 8061a6fa
Loading
Loading
Loading
Loading
+7 −7
Original line number Original line Diff line number Diff line
@@ -359,11 +359,9 @@ struct inode_operations {
	ssize_t (*listxattr) (struct dentry *, char *, size_t);
	ssize_t (*listxattr) (struct dentry *, char *, size_t);
	int (*removexattr) (struct dentry *, const char *);
	int (*removexattr) (struct dentry *, const char *);
	void (*update_time)(struct inode *, struct timespec *, int);
	void (*update_time)(struct inode *, struct timespec *, int);
	int (*atomic_open)(struct inode *, struct dentry *,
	int (*atomic_open)(struct inode *, struct dentry *, struct file *,
			unsigned open_flag, umode_t create_mode, int *opened);
	int (*tmpfile) (struct inode *, struct dentry *, umode_t);
	int (*tmpfile) (struct inode *, struct dentry *, umode_t);
} ____cacheline_aligned;
				struct file *, unsigned open_flag,
				umode_t create_mode, int *opened);
};
};


Again, all methods are called without any locks being held, unless
Again, all methods are called without any locks being held, unless
@@ -470,9 +468,11 @@ otherwise noted.
  	method the filesystem can look up, possibly create and open the file in
  	method the filesystem can look up, possibly create and open the file in
  	one atomic operation.  If it cannot perform this (e.g. the file type
  	one atomic operation.  If it cannot perform this (e.g. the file type
  	turned out to be wrong) it may signal this by returning 1 instead of
  	turned out to be wrong) it may signal this by returning 1 instead of
  	usual 0 or -ve .  This method is only called if the last
	usual 0 or -ve .  This method is only called if the last component is
  	component is negative or needs lookup.  Cached positive dentries are
	negative or needs lookup.  Cached positive dentries are still handled by
  	still handled by f_op->open().
	f_op->open().  If the file was created, the FILE_CREATED flag should be
	set in "opened".  In case of O_EXCL the method must only succeed if the
	file didn't exist and hence FILE_CREATED shall always be set on success.


  tmpfile: called in the end of O_TMPFILE open().  Optional, equivalent to
  tmpfile: called in the end of O_TMPFILE open().  Optional, equivalent to
	atomically creating, opening and unlinking a file in given directory.
	atomically creating, opening and unlinking a file in given directory.
+4 −3
Original line number Original line Diff line number Diff line
@@ -603,10 +603,11 @@ static int v9fs_cache_register(void)
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;
#ifdef CONFIG_9P_FSCACHE
#ifdef CONFIG_9P_FSCACHE
	return fscache_register_netfs(&v9fs_cache_netfs);
	ret = fscache_register_netfs(&v9fs_cache_netfs);
#else
	if (ret < 0)
	return ret;
		v9fs_destroy_inode_cache();
#endif
#endif
	return ret;
}
}


static void v9fs_cache_unregister(void)
static void v9fs_cache_unregister(void)
+1 −7
Original line number Original line Diff line number Diff line
@@ -267,14 +267,8 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
	}
	}


	/* Only creates */
	/* Only creates */
	if (!(flags & O_CREAT))
	if (!(flags & O_CREAT) || dentry->d_inode)
		return	finish_no_open(file, res);
		return	finish_no_open(file, res);
	else if (dentry->d_inode) {
		if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
			return -EEXIST;
		else
			return finish_no_open(file, res);
	}


	v9ses = v9fs_inode2v9ses(dir);
	v9ses = v9fs_inode2v9ses(dir);


+3 −10
Original line number Original line Diff line number Diff line
@@ -109,13 +109,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,


	pkt.hdr.proto_version = sbi->version;
	pkt.hdr.proto_version = sbi->version;
	pkt.hdr.type = type;
	pkt.hdr.type = type;
	mutex_lock(&sbi->wq_mutex);


	/* Check if we have become catatonic */
	if (sbi->catatonic) {
		mutex_unlock(&sbi->wq_mutex);
		return;
	}
	switch (type) {
	switch (type) {
	/* Kernel protocol v4 missing and expire packets */
	/* Kernel protocol v4 missing and expire packets */
	case autofs_ptype_missing:
	case autofs_ptype_missing:
@@ -427,7 +421,6 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
		wq->tgid = current->tgid;
		wq->tgid = current->tgid;
		wq->status = -EINTR; /* Status return if interrupted */
		wq->status = -EINTR; /* Status return if interrupted */
		wq->wait_ctr = 2;
		wq->wait_ctr = 2;
		mutex_unlock(&sbi->wq_mutex);


		if (sbi->version < 5) {
		if (sbi->version < 5) {
			if (notify == NFY_MOUNT)
			if (notify == NFY_MOUNT)
@@ -449,15 +442,15 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
			(unsigned long) wq->wait_queue_token, wq->name.len,
			(unsigned long) wq->wait_queue_token, wq->name.len,
			wq->name.name, notify);
			wq->name.name, notify);


		/* autofs4_notify_daemon() may block */
		/* autofs4_notify_daemon() may block; it will unlock ->wq_mutex */
		autofs4_notify_daemon(sbi, wq, type);
		autofs4_notify_daemon(sbi, wq, type);
	} else {
	} else {
		wq->wait_ctr++;
		wq->wait_ctr++;
		mutex_unlock(&sbi->wq_mutex);
		kfree(qstr.name);
		DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
		DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
			(unsigned long) wq->wait_queue_token, wq->name.len,
			(unsigned long) wq->wait_queue_token, wq->name.len,
			wq->name.name, notify);
			wq->name.name, notify);
		mutex_unlock(&sbi->wq_mutex);
		kfree(qstr.name);
	}
	}


	/*
	/*
+1 −0
Original line number Original line Diff line number Diff line
@@ -500,6 +500,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
		if (server->ops->close)
		if (server->ops->close)
			server->ops->close(xid, tcon, &fid);
			server->ops->close(xid, tcon, &fid);
		cifs_del_pending_open(&open);
		cifs_del_pending_open(&open);
		fput(file);
		rc = -ENOMEM;
		rc = -ENOMEM;
	}
	}


Loading