mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-27 15:17:04 -04:00
Merge tag 'vfs-7.3-rc1.lookup' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs lookup updates from Christian Brauner: "This refactors lookup_open() and adds vfs_lookup_open() for nfsd. mnt_want_write() and parent locking are moved into lookup_open() itself. audit_inode_child() is also now called in lookup_open() on failure. That is the calling convention in vfs_create() and vfs_mkdir(), but lookup_open() made no such call when atomic_open() should have created a file and did not. And neither did the regular ->create() path fwiw. This also contains work to remove the unneeded excl argument from the ->create() inode op" * tag 'vfs-7.3-rc1.lookup' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: fs/namei.c: fix coding style in atomic_open() and lookup_open() fs/namei.c: fix kerneldoc of atomic_open() and vfs_lookup_open() fs/namei.c: update stale comments in lookup_open() Remove excl arg to ->create inode_operation fs/namei.c: update kerneldoc of atomic_open() vfs: call audit_inode_child() in lookup_open() on failure vfs: move create error && negative dentry case in lookup_open() up VFS: add vfs_lookup_open() for nfsd VFS: move delegated_inode retry loop into lookup_open() VFS: move mnt_want_write() and locking into lookup_open()
This commit is contained in:
@@ -61,7 +61,7 @@ inode_operations
|
||||
|
||||
prototypes::
|
||||
|
||||
int (*create) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t, bool);
|
||||
int (*create) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t);
|
||||
struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
|
||||
int (*link) (struct dentry *,struct inode *,struct dentry *);
|
||||
int (*unlink) (struct inode *,struct dentry *);
|
||||
|
||||
@@ -1401,3 +1401,11 @@ as with d_dispose_if_unused() these are not trivial; with this variant
|
||||
of API it's more explicit, since grabbing ->d_lock is caller-side, but
|
||||
d_dispose_if_unused() had all the same issues. It's a low-level primitive;
|
||||
use only if you have no alternative.
|
||||
|
||||
---
|
||||
|
||||
**mandatory**
|
||||
|
||||
The .create inode_operation no longer receives the 'excl' arg. It must
|
||||
always assume the file does not already exist. If the filesystem needs
|
||||
to be involved in non-exclusive create, it should provide atomic_open.
|
||||
|
||||
@@ -415,7 +415,7 @@ As of kernel 2.6.22, the following members are defined:
|
||||
.. code-block:: c
|
||||
|
||||
struct inode_operations {
|
||||
int (*create) (struct mnt_idmap *, struct inode *,struct dentry *, umode_t, bool);
|
||||
int (*create) (struct mnt_idmap *, struct inode *,struct dentry *, umode_t);
|
||||
struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
|
||||
int (*link) (struct dentry *,struct inode *,struct dentry *);
|
||||
int (*unlink) (struct inode *,struct dentry *);
|
||||
|
||||
@@ -645,7 +645,6 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
|
||||
* @dir: The parent directory
|
||||
* @dentry: The name of file to be created
|
||||
* @mode: The UNIX file mode to set
|
||||
* @excl: True if the file must not yet exist
|
||||
*
|
||||
* open(.., O_CREAT) is handled in v9fs_vfs_atomic_open(). This is only called
|
||||
* for mknod(2).
|
||||
@@ -654,7 +653,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
|
||||
|
||||
static int
|
||||
v9fs_vfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
|
||||
u32 perm = unixmode2p9mode(v9ses, mode);
|
||||
|
||||
@@ -213,12 +213,11 @@ int v9fs_open_to_dotl_flags(int flags)
|
||||
* @dir: directory inode that is being created
|
||||
* @dentry: dentry that is being deleted
|
||||
* @omode: create permissions
|
||||
* @excl: True if the file must not yet exist
|
||||
*
|
||||
*/
|
||||
static int
|
||||
v9fs_vfs_create_dotl(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t omode, bool excl)
|
||||
struct dentry *dentry, umode_t omode)
|
||||
{
|
||||
return v9fs_vfs_mknod_dotl(idmap, dir, dentry, omode, 0);
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ extern int affs_hash_name(struct super_block *sb, const u8 *name, unsigned int l
|
||||
extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int);
|
||||
extern int affs_unlink(struct inode *dir, struct dentry *dentry);
|
||||
extern int affs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool);
|
||||
struct dentry *dentry, umode_t mode);
|
||||
extern struct dentry *affs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode);
|
||||
extern int affs_rmdir(struct inode *dir, struct dentry *dentry);
|
||||
|
||||
@@ -243,7 +243,7 @@ affs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
|
||||
int
|
||||
affs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct inode *inode;
|
||||
|
||||
@@ -34,7 +34,7 @@ static bool afs_lookup_filldir(struct dir_context *ctx, const char *name, int nl
|
||||
u64 ino, u32 uniquifier);
|
||||
#define AFS_LOOKUP ((filldir_t)0x137UL)
|
||||
static int afs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl);
|
||||
struct dentry *dentry, umode_t mode);
|
||||
static struct dentry *afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode);
|
||||
static int afs_rmdir(struct inode *dir, struct dentry *dentry);
|
||||
@@ -1633,7 +1633,7 @@ static const struct afs_operation_ops afs_create_operation = {
|
||||
* create a regular file on an AFS filesystem
|
||||
*/
|
||||
static int afs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct afs_operation *op;
|
||||
struct afs_vnode *dvnode = AFS_FS_I(dir);
|
||||
|
||||
@@ -29,7 +29,7 @@ static const struct file_operations bad_file_ops =
|
||||
|
||||
static int bad_inode_create(struct mnt_idmap *idmap,
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
umode_t mode, bool excl)
|
||||
umode_t mode)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ const struct file_operations bfs_dir_operations = {
|
||||
};
|
||||
|
||||
static int bfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
int err;
|
||||
struct inode *inode;
|
||||
|
||||
@@ -7007,7 +7007,7 @@ static int btrfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||
}
|
||||
|
||||
static int btrfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
|
||||
|
||||
@@ -983,7 +983,7 @@ static int ceph_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||
}
|
||||
|
||||
static int ceph_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return ceph_mknod(idmap, dir, dentry, mode, 0);
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ static inline void coda_dir_drop_nlink(struct inode *dir)
|
||||
|
||||
/* creation routines: create, mknod, mkdir, link, symlink */
|
||||
static int coda_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *de, umode_t mode, bool excl)
|
||||
struct dentry *de, umode_t mode)
|
||||
{
|
||||
int error;
|
||||
const char *name=de->d_name.name;
|
||||
|
||||
@@ -268,7 +268,7 @@ int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
|
||||
static int
|
||||
ecryptfs_create(struct mnt_idmap *idmap,
|
||||
struct inode *directory_inode, struct dentry *ecryptfs_dentry,
|
||||
umode_t mode, bool excl)
|
||||
umode_t mode)
|
||||
{
|
||||
struct inode *ecryptfs_inode;
|
||||
int rc;
|
||||
|
||||
@@ -75,7 +75,7 @@ static bool efivarfs_valid_name(const char *str, int len)
|
||||
}
|
||||
|
||||
static int efivarfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode = NULL;
|
||||
struct efivar_entry *var;
|
||||
|
||||
@@ -538,7 +538,7 @@ static int exfat_add_entry(struct inode *inode, const char *path,
|
||||
}
|
||||
|
||||
static int exfat_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct inode *inode;
|
||||
|
||||
@@ -99,7 +99,7 @@ struct dentry *ext2_get_parent(struct dentry *child)
|
||||
*/
|
||||
static int ext2_create (struct mnt_idmap * idmap,
|
||||
struct inode * dir, struct dentry * dentry,
|
||||
umode_t mode, bool excl)
|
||||
umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
int err;
|
||||
|
||||
@@ -2811,7 +2811,7 @@ static int ext4_add_nondir(handle_t *handle,
|
||||
* with d_instantiate().
|
||||
*/
|
||||
static int ext4_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
handle_t *handle;
|
||||
struct inode *inode;
|
||||
|
||||
@@ -366,7 +366,7 @@ static struct inode *f2fs_new_inode(struct mnt_idmap *idmap,
|
||||
}
|
||||
|
||||
static int f2fs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
|
||||
struct f2fs_lock_context lc;
|
||||
|
||||
@@ -265,7 +265,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
|
||||
|
||||
/***** Create a file */
|
||||
static int msdos_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct inode *inode = NULL;
|
||||
|
||||
@@ -755,7 +755,7 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
|
||||
}
|
||||
|
||||
static int vfat_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct inode *inode;
|
||||
|
||||
@@ -1084,7 +1084,7 @@ static int fuse_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||
}
|
||||
|
||||
static int fuse_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *entry, umode_t mode, bool excl)
|
||||
struct dentry *entry, umode_t mode)
|
||||
{
|
||||
return fuse_mknod(idmap, dir, entry, mode, 0);
|
||||
}
|
||||
|
||||
@@ -963,15 +963,14 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
||||
* @dir: The directory in which to create the file
|
||||
* @dentry: The dentry of the new file
|
||||
* @mode: The mode of the new file
|
||||
* @excl: Force fail if inode exists
|
||||
*
|
||||
* Returns: errno
|
||||
*/
|
||||
|
||||
static int gfs2_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return gfs2_create_inode(dir, dentry, NULL, S_IFREG | mode, 0, NULL, 0, excl);
|
||||
return gfs2_create_inode(dir, dentry, NULL, S_IFREG | mode, 0, NULL, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -184,7 +184,7 @@ static int hfs_dir_release(struct inode *inode, struct file *file)
|
||||
* the directory and the name (and its length) of the new file.
|
||||
*/
|
||||
static int hfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
int res;
|
||||
|
||||
@@ -562,7 +562,7 @@ static int hfsplus_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||
}
|
||||
|
||||
static int hfsplus_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return hfsplus_mknod(&nop_mnt_idmap, dir, dentry, mode, 0);
|
||||
}
|
||||
|
||||
@@ -593,7 +593,7 @@ static struct inode *hostfs_iget(struct super_block *sb, char *name)
|
||||
}
|
||||
|
||||
static int hostfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
char *name;
|
||||
|
||||
@@ -129,7 +129,7 @@ static struct dentry *hpfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
}
|
||||
|
||||
static int hpfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
const unsigned char *name = dentry->d_name.name;
|
||||
unsigned len = dentry->d_name.len;
|
||||
|
||||
@@ -979,7 +979,7 @@ static struct dentry *hugetlbfs_mkdir(struct mnt_idmap *idmap, struct inode *dir
|
||||
|
||||
static int hugetlbfs_create(struct mnt_idmap *idmap,
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
umode_t mode, bool excl)
|
||||
umode_t mode)
|
||||
{
|
||||
return hugetlbfs_mknod(idmap, dir, dentry, mode | S_IFREG, 0);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
static int jffs2_readdir (struct file *, struct dir_context *);
|
||||
|
||||
static int jffs2_create (struct mnt_idmap *, struct inode *,
|
||||
struct dentry *, umode_t, bool);
|
||||
struct dentry *, umode_t);
|
||||
static struct dentry *jffs2_lookup (struct inode *,struct dentry *,
|
||||
unsigned int);
|
||||
static int jffs2_link (struct dentry *,struct inode *,struct dentry *);
|
||||
@@ -163,7 +163,7 @@ static int jffs2_readdir(struct file *file, struct dir_context *ctx)
|
||||
|
||||
|
||||
static int jffs2_create(struct mnt_idmap *idmap, struct inode *dir_i,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct jffs2_raw_inode *ri;
|
||||
struct jffs2_inode_info *f, *dir_f;
|
||||
|
||||
@@ -61,7 +61,7 @@ static inline void free_ea_wmap(struct inode *inode)
|
||||
*
|
||||
*/
|
||||
static int jfs_create(struct mnt_idmap *idmap, struct inode *dip,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
int rc = 0;
|
||||
tid_t tid; /* transaction id */
|
||||
|
||||
@@ -64,7 +64,7 @@ static int minix_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
|
||||
}
|
||||
|
||||
static int minix_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return minix_mknod(&nop_mnt_idmap, dir, dentry, mode, 0);
|
||||
}
|
||||
|
||||
355
fs/namei.c
355
fs/namei.c
@@ -4199,7 +4199,7 @@ int vfs_create(struct mnt_idmap *idmap, struct dentry *dentry, umode_t mode,
|
||||
error = try_break_deleg(dir, LEASE_BREAK_DIR_CREATE, di);
|
||||
if (error)
|
||||
return error;
|
||||
error = dir->i_op->create(idmap, dir, dentry, mode, true);
|
||||
error = dir->i_op->create(idmap, dir, dentry, mode);
|
||||
if (!error)
|
||||
fsnotify_create(dir, dentry);
|
||||
return error;
|
||||
@@ -4336,50 +4336,83 @@ static int may_o_create(struct mnt_idmap *idmap,
|
||||
return security_inode_create(dir->dentry->d_inode, dentry, mode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to atomically look up, create and open a file from a negative
|
||||
* dentry.
|
||||
/**
|
||||
* atomic_open() - atomically look up, create and open a file
|
||||
* @path: parent directory path
|
||||
* @dentry: child to ->atomic_open()
|
||||
* @file: file to attach child to
|
||||
* @open_flag: open flags
|
||||
* @mode: create mode
|
||||
* @create_error: return value from may_o_create()
|
||||
*
|
||||
* Returns 0 if successful. The file will have been created and attached to
|
||||
* @file by the filesystem calling finish_open().
|
||||
* Attempt to look up, create and open @dentry, which must be negative, in a
|
||||
* single call into the filesystem.
|
||||
*
|
||||
* If the file was looked up only or didn't need creating, FMODE_OPENED won't
|
||||
* be set. The caller will need to perform the open themselves. @path will
|
||||
* have been updated to point to the new dentry. This may be negative.
|
||||
* If a non-error dentry is returned then: when FMODE_OPENED is set,
|
||||
* the file will have been attached to @file by the filesystem calling
|
||||
* finish_open(). If FMODE_OPENED isn't set, the filesystem instead called
|
||||
* finish_no_open() and the caller will need to perform the open themselves.
|
||||
*
|
||||
* Returns an error code otherwise.
|
||||
* FMODE_CREATED is set when the call to ->atomic_open() actually created
|
||||
* the file.
|
||||
*
|
||||
* Returns: the opened or looked-up dentry, or ERR_PTR() on failure. The
|
||||
* reference to @dentry is consumed in either case.
|
||||
*/
|
||||
static struct dentry *atomic_open(const struct path *path, struct dentry *dentry,
|
||||
struct file *file,
|
||||
int open_flag, umode_t mode)
|
||||
int open_flag, umode_t mode, int create_error)
|
||||
{
|
||||
struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
|
||||
struct inode *dir = path->dentry->d_inode;
|
||||
struct inode *dir_inode = path->dentry->d_inode;
|
||||
int error;
|
||||
|
||||
file->__f_path.dentry = DENTRY_NOT_SET;
|
||||
file->__f_path.mnt = path->mnt;
|
||||
error = dir->i_op->atomic_open(dir, dentry, file,
|
||||
error = dir_inode->i_op->atomic_open(dir_inode, dentry, file,
|
||||
open_to_namei_flags(open_flag), mode);
|
||||
d_lookup_done(dentry);
|
||||
|
||||
if (!error) {
|
||||
if (file->f_mode & FMODE_OPENED) {
|
||||
if (unlikely(dentry != file->f_path.dentry)) {
|
||||
/* finish_open() called */
|
||||
struct dentry *opened = file->f_path.dentry;
|
||||
|
||||
if (unlikely(opened != dentry)) {
|
||||
dput(dentry);
|
||||
dentry = dget(file->f_path.dentry);
|
||||
dentry = dget(opened);
|
||||
}
|
||||
} else if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
|
||||
error = -EIO;
|
||||
} else {
|
||||
if (file->f_path.dentry) {
|
||||
} else if (likely(file->f_path.dentry != DENTRY_NOT_SET)) {
|
||||
/* finish_no_open() called */
|
||||
struct dentry *replaced = file->f_path.dentry;
|
||||
|
||||
if (replaced) {
|
||||
dput(dentry);
|
||||
dentry = file->f_path.dentry;
|
||||
dentry = replaced;
|
||||
}
|
||||
if (unlikely(d_is_negative(dentry)))
|
||||
error = -ENOENT;
|
||||
} else {
|
||||
const char *fsname = dentry->d_sb->s_type->name;
|
||||
|
||||
WARN(1, "%s: ->atomic_open() left file->f_path.dentry unset!\n",
|
||||
fsname);
|
||||
error = -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
if (unlikely(create_error) && error == -ENOENT) {
|
||||
/*
|
||||
* Should have done a create, but errored before.
|
||||
* Some filesystems return -ENOENT directly instead of
|
||||
* calling finish_no_open() with a negative dentry;
|
||||
* either way it should only mean the child doesn't exist,
|
||||
* so a refused create is safe to record here.
|
||||
*/
|
||||
audit_inode_child(dir_inode, dentry, AUDIT_TYPE_CHILD_CREATE);
|
||||
error = create_error;
|
||||
}
|
||||
dput(dentry);
|
||||
dentry = ERR_PTR(error);
|
||||
}
|
||||
@@ -4389,32 +4422,52 @@ static struct dentry *atomic_open(const struct path *path, struct dentry *dentry
|
||||
/*
|
||||
* Look up and maybe create and open the last component.
|
||||
*
|
||||
* Must be called with parent locked (exclusive in O_CREAT case).
|
||||
* Takes the parent inode lock itself, exclusive if O_CREAT was requested and
|
||||
* shared otherwise, and drops it again before returning. The caller must not
|
||||
* hold it.
|
||||
*
|
||||
* Returns 0 on success, that is, if
|
||||
* the file was successfully atomically created (if necessary) and opened, or
|
||||
* the file was not completely opened at this time, though lookups and
|
||||
* creations were performed.
|
||||
* These case are distinguished by presence of FMODE_OPENED on file->f_mode.
|
||||
* In the latter case dentry returned in @path might be negative if O_CREAT
|
||||
* hadn't been specified.
|
||||
* On success returns the dentry of the last component. If FMODE_OPENED is set
|
||||
* on file->f_mode the file was also opened and attached to @file; otherwise
|
||||
* only lookup and creation were performed and the caller has to open it. In
|
||||
* the latter case the dentry may be negative if O_CREAT hadn't been specified.
|
||||
*
|
||||
* An error code is returned on failure.
|
||||
* Returns ERR_PTR() on failure.
|
||||
*/
|
||||
static struct dentry *lookup_open(struct nameidata *nd, struct file *file,
|
||||
const struct open_flags *op,
|
||||
bool got_write, struct delegated_inode *delegated_inode)
|
||||
const struct open_flags *op)
|
||||
{
|
||||
struct delegated_inode delegated_inode = { };
|
||||
struct mnt_idmap *idmap;
|
||||
struct dentry *dir = nd->path.dentry;
|
||||
struct inode *dir_inode = dir->d_inode;
|
||||
int open_flag = op->open_flag;
|
||||
int open_flag;
|
||||
struct dentry *dentry;
|
||||
int error, create_error = 0;
|
||||
umode_t mode = op->mode;
|
||||
int error, create_error;
|
||||
umode_t mode;
|
||||
bool got_write;
|
||||
|
||||
if (unlikely(IS_DEADDIR(dir_inode)))
|
||||
return ERR_PTR(-ENOENT);
|
||||
retry:
|
||||
open_flag = op->open_flag;
|
||||
got_write = false;
|
||||
mode = op->mode;
|
||||
create_error = 0;
|
||||
|
||||
if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) {
|
||||
got_write = !mnt_want_write(nd->path.mnt);
|
||||
/*
|
||||
* do _not_ fail yet - we might not need that or fail with
|
||||
* a different error; we'll be dropping this one anyway.
|
||||
*/
|
||||
}
|
||||
if (open_flag & O_CREAT)
|
||||
inode_lock(dir_inode);
|
||||
else
|
||||
inode_lock_shared(dir_inode);
|
||||
|
||||
if (unlikely(IS_DEADDIR(dir_inode))) {
|
||||
dentry = ERR_PTR(-ENOENT);
|
||||
goto out;
|
||||
}
|
||||
|
||||
file->f_mode &= ~FMODE_CREATED;
|
||||
dentry = d_lookup(dir, &nd->last);
|
||||
@@ -4422,7 +4475,7 @@ static struct dentry *lookup_open(struct nameidata *nd, struct file *file,
|
||||
if (!dentry) {
|
||||
dentry = d_alloc_parallel(dir, &nd->last);
|
||||
if (IS_ERR(dentry))
|
||||
return dentry;
|
||||
goto out;
|
||||
}
|
||||
if (d_in_lookup(dentry))
|
||||
break;
|
||||
@@ -4437,8 +4490,8 @@ static struct dentry *lookup_open(struct nameidata *nd, struct file *file,
|
||||
dentry = NULL;
|
||||
}
|
||||
if (dentry->d_inode) {
|
||||
/* Cached positive dentry: will open in f_op->open */
|
||||
return dentry;
|
||||
/* Cached positive dentry: will open in do_open(). */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (open_flag & O_CREAT)
|
||||
@@ -4459,7 +4512,7 @@ static struct dentry *lookup_open(struct nameidata *nd, struct file *file,
|
||||
if (open_flag & O_CREAT) {
|
||||
if (open_flag & O_EXCL)
|
||||
open_flag &= ~O_TRUNC;
|
||||
mode = vfs_prepare_mode(idmap, dir->d_inode, mode, mode, mode);
|
||||
mode = vfs_prepare_mode(idmap, dir_inode, mode, mode, mode);
|
||||
if (likely(got_write))
|
||||
create_error = may_o_create(idmap, &nd->path,
|
||||
dentry, mode);
|
||||
@@ -4471,10 +4524,9 @@ static struct dentry *lookup_open(struct nameidata *nd, struct file *file,
|
||||
if (dir_inode->i_op->atomic_open) {
|
||||
if (nd->flags & LOOKUP_DIRECTORY)
|
||||
open_flag |= O_DIRECTORY;
|
||||
dentry = atomic_open(&nd->path, dentry, file, open_flag, mode);
|
||||
if (unlikely(create_error) && dentry == ERR_PTR(-ENOENT))
|
||||
dentry = ERR_PTR(create_error);
|
||||
return dentry;
|
||||
dentry = atomic_open(&nd->path, dentry, file, open_flag, mode,
|
||||
create_error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (d_in_lookup(dentry)) {
|
||||
@@ -4490,37 +4542,164 @@ static struct dentry *lookup_open(struct nameidata *nd, struct file *file,
|
||||
dentry = res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Negative dentry, just create the file */
|
||||
if (!dentry->d_inode && (open_flag & O_CREAT)) {
|
||||
/* but break the directory lease first! */
|
||||
error = try_break_deleg(dir_inode, LEASE_BREAK_DIR_CREATE, delegated_inode);
|
||||
if (error)
|
||||
goto out_dput;
|
||||
|
||||
file->f_mode |= FMODE_CREATED;
|
||||
audit_inode_child(dir_inode, dentry, AUDIT_TYPE_CHILD_CREATE);
|
||||
if (!dir_inode->i_op->create) {
|
||||
error = -EACCES;
|
||||
goto out_dput;
|
||||
}
|
||||
|
||||
error = dir_inode->i_op->create(idmap, dir_inode, dentry,
|
||||
mode, open_flag & O_EXCL);
|
||||
if (error)
|
||||
goto out_dput;
|
||||
if (dentry->d_inode || !(op->open_flag & O_CREAT)) {
|
||||
/*
|
||||
* No need to create a file. If lookup returned a positive
|
||||
* dentry, the file will be opened in do_open().
|
||||
*/
|
||||
goto out;
|
||||
}
|
||||
if (unlikely(create_error) && !dentry->d_inode) {
|
||||
|
||||
/* Negative dentry with O_CREAT flag set */
|
||||
audit_inode_child(dir_inode, dentry, AUDIT_TYPE_CHILD_CREATE);
|
||||
|
||||
if (unlikely(create_error)) {
|
||||
/* should have done a create, but we already errored */
|
||||
error = create_error;
|
||||
goto out_dput;
|
||||
}
|
||||
|
||||
error = try_break_deleg(dir_inode, LEASE_BREAK_DIR_CREATE, &delegated_inode);
|
||||
if (error)
|
||||
goto out_dput;
|
||||
|
||||
file->f_mode |= FMODE_CREATED;
|
||||
if (!dir_inode->i_op->create) {
|
||||
error = -EACCES;
|
||||
goto out_dput;
|
||||
}
|
||||
|
||||
error = dir_inode->i_op->create(idmap, dir_inode, dentry, mode);
|
||||
if (error)
|
||||
goto out_dput;
|
||||
out:
|
||||
if (!IS_ERR(dentry)) {
|
||||
if (file->f_mode & FMODE_CREATED)
|
||||
fsnotify_create(dir_inode, dentry);
|
||||
if (file->f_mode & FMODE_OPENED)
|
||||
fsnotify_open(file);
|
||||
}
|
||||
if ((open_flag & O_CREAT) || create_error)
|
||||
inode_unlock(dir_inode);
|
||||
else
|
||||
inode_unlock_shared(dir_inode);
|
||||
|
||||
if (got_write)
|
||||
mnt_drop_write(nd->path.mnt);
|
||||
|
||||
if (is_delegated(&delegated_inode)) {
|
||||
/* Must have come through out_dput: dentry is an ERR_PTR() */
|
||||
error = break_deleg_wait(&delegated_inode);
|
||||
|
||||
if (!error)
|
||||
goto retry;
|
||||
dentry = ERR_PTR(error);
|
||||
}
|
||||
|
||||
return dentry;
|
||||
|
||||
out_dput:
|
||||
dput(dentry);
|
||||
return ERR_PTR(error);
|
||||
dentry = ERR_PTR(error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
* vfs_lookup_open - open and possibly create a regular file
|
||||
* @parent: directory to contain file
|
||||
* @last: final component of file name
|
||||
* @open_flag: O_flags
|
||||
* @mode: initial permissions for file
|
||||
*
|
||||
* Open a file after lookup and/or create. This provides similar
|
||||
* functionality to open_last_lookups() for non-VFS users, particularly
|
||||
* nfsd.
|
||||
* It uses ->atomic_open or ->lookup / ->create / ->open as appropriate.
|
||||
*
|
||||
* If the fs object found is not a regular file then an error is returned.
|
||||
* In some cases, related errors are repurposed so that the caller can
|
||||
* determine the type of file found from the error.
|
||||
* -EISDIR : a directory was found
|
||||
* -ELOOP : a symlink was found
|
||||
* -ENODEV : a block or character device special file was found
|
||||
* -EFTYPE : any other non-regular file was found, such as FIFO or SOCK.
|
||||
* or ->atomic_open responded to __O_REGULAR.
|
||||
*
|
||||
* Returns: the opened struct file, or an error.
|
||||
*/
|
||||
struct file *vfs_lookup_open(struct path *parent, struct qstr *last,
|
||||
int open_flag, umode_t mode)
|
||||
{
|
||||
struct file *file __free(fput) = NULL;
|
||||
struct nameidata nd = {};
|
||||
struct open_flags op = {};
|
||||
struct dentry *dentry;
|
||||
int error = 0;
|
||||
|
||||
WARN_ONCE(mode & ~S_IALLUGO, "mode must only have permission bits");
|
||||
WARN_ONCE(open_flag & ~(O_ACCMODE|O_CREAT|O_EXCL|O_TRUNC|__O_REGULAR),
|
||||
"open_flag has unsupported flags");
|
||||
|
||||
mode |= S_IFREG;
|
||||
open_flag |= __O_REGULAR;
|
||||
|
||||
error = lookup_noperm_common(last, parent->dentry);
|
||||
if (error)
|
||||
return ERR_PTR(error);
|
||||
|
||||
file = alloc_empty_file(open_flag, current_cred());
|
||||
if (IS_ERR(file))
|
||||
return file;
|
||||
|
||||
nd.path = *parent;
|
||||
nd.last = *last;
|
||||
nd.flags = LOOKUP_OPEN;
|
||||
if (open_flag & O_CREAT) {
|
||||
nd.flags |= LOOKUP_CREATE;
|
||||
if (open_flag & O_EXCL)
|
||||
nd.flags |= LOOKUP_EXCL;
|
||||
}
|
||||
op.open_flag = open_flag;
|
||||
op.mode = mode;
|
||||
dentry = lookup_open(&nd, file, &op);
|
||||
|
||||
if (IS_ERR(dentry))
|
||||
return ERR_CAST(dentry);
|
||||
|
||||
if (d_really_is_negative(dentry)) {
|
||||
error = -ENOENT;
|
||||
} else if (!(file->f_mode & FMODE_CREATED) && (open_flag & O_EXCL)) {
|
||||
error = -EEXIST;
|
||||
} else if ((dentry->d_inode->i_mode & S_IFMT) != S_IFREG) {
|
||||
switch (dentry->d_inode->i_mode & S_IFMT) {
|
||||
case S_IFDIR:
|
||||
error = -EISDIR;
|
||||
break;
|
||||
case S_IFLNK:
|
||||
error = -ELOOP;
|
||||
break;
|
||||
case S_IFBLK:
|
||||
case S_IFCHR:
|
||||
error = -ENODEV;
|
||||
break;
|
||||
case S_IFIFO:
|
||||
case S_IFSOCK:
|
||||
default:
|
||||
error = -EFTYPE;
|
||||
break;
|
||||
}
|
||||
} else if (!(file->f_mode & FMODE_OPENED)) {
|
||||
nd.path.dentry = dentry;
|
||||
error = vfs_open(&nd.path, file);
|
||||
}
|
||||
dput(dentry);
|
||||
|
||||
if (error)
|
||||
return ERR_PTR(error);
|
||||
return no_free_ptr(file);
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_MODULES(vfs_lookup_open, "nfsd");
|
||||
|
||||
static inline bool trailing_slashes(struct nameidata *nd)
|
||||
{
|
||||
return (bool)nd->last.name[nd->last.len];
|
||||
@@ -4560,10 +4739,7 @@ static struct dentry *lookup_fast_for_open(struct nameidata *nd, int open_flag)
|
||||
static const char *open_last_lookups(struct nameidata *nd,
|
||||
struct file *file, const struct open_flags *op)
|
||||
{
|
||||
struct delegated_inode delegated_inode = { };
|
||||
struct dentry *dir = nd->path.dentry;
|
||||
int open_flag = op->open_flag;
|
||||
bool got_write = false;
|
||||
struct dentry *dentry;
|
||||
const char *res;
|
||||
|
||||
@@ -4592,44 +4768,10 @@ static const char *open_last_lookups(struct nameidata *nd,
|
||||
return ERR_PTR(-ECHILD);
|
||||
}
|
||||
}
|
||||
retry:
|
||||
if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) {
|
||||
got_write = !mnt_want_write(nd->path.mnt);
|
||||
/*
|
||||
* do _not_ fail yet - we might not need that or fail with
|
||||
* a different error; let lookup_open() decide; we'll be
|
||||
* dropping this one anyway.
|
||||
*/
|
||||
}
|
||||
if (open_flag & O_CREAT)
|
||||
inode_lock(dir->d_inode);
|
||||
else
|
||||
inode_lock_shared(dir->d_inode);
|
||||
dentry = lookup_open(nd, file, op, got_write, &delegated_inode);
|
||||
if (!IS_ERR(dentry)) {
|
||||
if (file->f_mode & FMODE_CREATED)
|
||||
fsnotify_create(dir->d_inode, dentry);
|
||||
if (file->f_mode & FMODE_OPENED)
|
||||
fsnotify_open(file);
|
||||
}
|
||||
if (open_flag & O_CREAT)
|
||||
inode_unlock(dir->d_inode);
|
||||
else
|
||||
inode_unlock_shared(dir->d_inode);
|
||||
|
||||
if (got_write)
|
||||
mnt_drop_write(nd->path.mnt);
|
||||
|
||||
if (IS_ERR(dentry)) {
|
||||
if (is_delegated(&delegated_inode)) {
|
||||
int error = break_deleg_wait(&delegated_inode);
|
||||
|
||||
if (!error)
|
||||
goto retry;
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
dentry = lookup_open(nd, file, op);
|
||||
if (IS_ERR(dentry))
|
||||
return ERR_CAST(dentry);
|
||||
}
|
||||
|
||||
if (file->f_mode & (FMODE_OPENED | FMODE_CREATED)) {
|
||||
dput(nd->path.dentry);
|
||||
@@ -5051,7 +5193,7 @@ struct file *dentry_create(struct path *path, int flags, umode_t mode,
|
||||
|
||||
/* atomic_open will dput(dentry) on error */
|
||||
dget(orig_dentry);
|
||||
dentry = atomic_open(path, dentry, file, flags, mode);
|
||||
dentry = atomic_open(path, dentry, file, flags, mode, create_error);
|
||||
error = PTR_ERR_OR_ZERO(dentry);
|
||||
|
||||
if (IS_ERR(dentry))
|
||||
@@ -5061,9 +5203,6 @@ struct file *dentry_create(struct path *path, int flags, umode_t mode,
|
||||
/* Drop the extra reference */
|
||||
dput(orig_dentry);
|
||||
|
||||
if (unlikely(create_error) && error == -ENOENT)
|
||||
error = create_error;
|
||||
|
||||
if (!error) {
|
||||
if (file->f_mode & FMODE_CREATED)
|
||||
fsnotify_create(dir->d_inode, dentry);
|
||||
|
||||
@@ -2427,9 +2427,9 @@ static int nfs_do_create(struct inode *dir, struct dentry *dentry,
|
||||
}
|
||||
|
||||
int nfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return nfs_do_create(dir, dentry, mode, excl ? O_EXCL : 0);
|
||||
return nfs_do_create(dir, dentry, mode, O_EXCL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_create);
|
||||
|
||||
|
||||
@@ -395,7 +395,7 @@ extern unsigned long nfs_access_cache_scan(struct shrinker *shrink,
|
||||
struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int);
|
||||
void nfs_d_prune_case_insensitive_aliases(struct inode *inode);
|
||||
int nfs_create(struct mnt_idmap *, struct inode *, struct dentry *,
|
||||
umode_t, bool);
|
||||
umode_t);
|
||||
struct dentry *nfs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *,
|
||||
umode_t);
|
||||
int nfs_rmdir(struct inode *, struct dentry *);
|
||||
|
||||
@@ -86,7 +86,7 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
|
||||
* with d_instantiate().
|
||||
*/
|
||||
static int nilfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct nilfs_transaction_info ti;
|
||||
|
||||
@@ -737,7 +737,7 @@ static struct ntfs_inode *__ntfs_create(struct mnt_idmap *idmap, struct inode *d
|
||||
}
|
||||
|
||||
static int ntfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct ntfs_volume *vol = NTFS_SB(dir->i_sb);
|
||||
struct ntfs_inode *ni;
|
||||
|
||||
@@ -105,7 +105,7 @@ static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
* ntfs_create - inode_operations::create
|
||||
*/
|
||||
static int ntfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return ntfs_create_inode(idmap, dir, dentry, NULL, S_IFREG | mode, 0,
|
||||
NULL, 0, NULL);
|
||||
|
||||
@@ -453,8 +453,7 @@ static struct dentry *dlmfs_mkdir(struct mnt_idmap * idmap,
|
||||
static int dlmfs_create(struct mnt_idmap *idmap,
|
||||
struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
umode_t mode,
|
||||
bool excl)
|
||||
umode_t mode)
|
||||
{
|
||||
int status = 0;
|
||||
struct inode *inode;
|
||||
|
||||
@@ -667,8 +667,7 @@ static struct dentry *ocfs2_mkdir(struct mnt_idmap *idmap,
|
||||
static int ocfs2_create(struct mnt_idmap *idmap,
|
||||
struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
umode_t mode,
|
||||
bool excl)
|
||||
umode_t mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -286,7 +286,7 @@ static struct dentry *omfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
}
|
||||
|
||||
static int omfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return omfs_add_node(dir, dentry, mode | S_IFREG);
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
static int orangefs_create(struct mnt_idmap *idmap,
|
||||
struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
umode_t mode,
|
||||
bool exclusive)
|
||||
umode_t mode)
|
||||
{
|
||||
struct orangefs_inode_s *parent = ORANGEFS_I(dir);
|
||||
struct orangefs_kernel_op_s *new_op;
|
||||
|
||||
@@ -732,7 +732,7 @@ static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev,
|
||||
}
|
||||
|
||||
static int ovl_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return ovl_create_object(dentry, (mode & 07777) | S_IFREG, 0, NULL);
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ static struct dentry *ramfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
}
|
||||
|
||||
static int ramfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return ramfs_mknod(&nop_mnt_idmap, dir, dentry, mode | S_IFREG, 0);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ void cifs_sb_deactive(struct super_block *sb);
|
||||
extern const struct inode_operations cifs_dir_inode_ops;
|
||||
struct inode *cifs_root_iget(struct super_block *sb);
|
||||
int cifs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *direntry, umode_t mode, bool excl);
|
||||
struct dentry *direntry, umode_t mode);
|
||||
int cifs_atomic_open(struct inode *dir, struct dentry *direntry,
|
||||
struct file *file, unsigned int oflags, umode_t mode);
|
||||
int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
||||
@@ -645,7 +645,7 @@ int cifs_atomic_open(struct inode *dir, struct dentry *direntry,
|
||||
* hashed-positive by calling d_instantiate().
|
||||
*/
|
||||
int cifs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *direntry, umode_t mode, bool excl)
|
||||
struct dentry *direntry, umode_t mode)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(dir);
|
||||
int rc;
|
||||
|
||||
@@ -303,7 +303,7 @@ static int ubifs_prepare_create(struct inode *dir, struct dentry *dentry,
|
||||
}
|
||||
|
||||
static int ubifs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct ubifs_info *c = dir->i_sb->s_fs_info;
|
||||
|
||||
@@ -371,7 +371,7 @@ static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
|
||||
}
|
||||
|
||||
static int udf_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode = udf_new_inode(dir, mode);
|
||||
|
||||
|
||||
@@ -70,8 +70,7 @@ static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, unsi
|
||||
* with d_instantiate().
|
||||
*/
|
||||
static int ufs_create (struct mnt_idmap * idmap,
|
||||
struct inode * dir, struct dentry * dentry, umode_t mode,
|
||||
bool excl)
|
||||
struct inode * dir, struct dentry * dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
|
||||
|
||||
@@ -298,9 +298,9 @@ static int vboxsf_dir_create(struct inode *parent, struct dentry *dentry,
|
||||
|
||||
static int vboxsf_dir_mkfile(struct mnt_idmap *idmap,
|
||||
struct inode *parent, struct dentry *dentry,
|
||||
umode_t mode, bool excl)
|
||||
umode_t mode)
|
||||
{
|
||||
return vboxsf_dir_create(parent, dentry, mode, false, excl, NULL);
|
||||
return vboxsf_dir_create(parent, dentry, mode, false, true, NULL);
|
||||
}
|
||||
|
||||
static struct dentry *vboxsf_dir_mkdir(struct mnt_idmap *idmap,
|
||||
|
||||
@@ -293,8 +293,7 @@ xfs_vn_create(
|
||||
struct mnt_idmap *idmap,
|
||||
struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
umode_t mode,
|
||||
bool flags)
|
||||
umode_t mode)
|
||||
{
|
||||
return xfs_generic_create(idmap, dir, dentry, mode, 0, NULL);
|
||||
}
|
||||
@@ -338,7 +337,7 @@ STATIC struct dentry *
|
||||
xfs_vn_ci_lookup(
|
||||
struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
unsigned int flags)
|
||||
unsigned int flags)
|
||||
{
|
||||
struct xfs_inode *ip;
|
||||
struct xfs_name xname;
|
||||
|
||||
@@ -2002,7 +2002,7 @@ struct inode_operations {
|
||||
int (*readlink) (struct dentry *, char __user *,int);
|
||||
|
||||
int (*create) (struct mnt_idmap *, struct inode *,struct dentry *,
|
||||
umode_t, bool);
|
||||
umode_t);
|
||||
int (*link) (struct dentry *,struct inode *,struct dentry *);
|
||||
int (*unlink) (struct inode *,struct dentry *);
|
||||
int (*symlink) (struct mnt_idmap *, struct inode *,struct dentry *,
|
||||
|
||||
@@ -97,6 +97,9 @@ struct dentry *start_creating_dentry(struct dentry *parent,
|
||||
struct dentry *start_removing_dentry(struct dentry *parent,
|
||||
struct dentry *child);
|
||||
|
||||
struct file *vfs_lookup_open(struct path *parent, struct qstr *last,
|
||||
int open_flag, umode_t mode);
|
||||
|
||||
/* end_creating - finish action started with start_creating
|
||||
* @child: dentry returned by start_creating() or vfs_mkdir()
|
||||
*
|
||||
|
||||
@@ -608,7 +608,7 @@ static int mqueue_create_attr(struct dentry *dentry, umode_t mode, void *arg)
|
||||
}
|
||||
|
||||
static int mqueue_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return mqueue_create_attr(dentry, mode, NULL);
|
||||
}
|
||||
|
||||
@@ -3874,7 +3874,7 @@ static struct dentry *shmem_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
}
|
||||
|
||||
static int shmem_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return shmem_mknod(idmap, dir, dentry, mode | S_IFREG, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user