mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/
synced 2025-04-19 20:58:31 +09:00
vfs-6.15-rc1.async.dir
-----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCZ90rNwAKCRCRxhvAZXjc onBJAP9Z8Ywmlb5KQ1E3HvDmkwyY6yOSyZ9/CmbzrkCJ8ywYkQD/d9/xt0EP/O/q N8YtzXArHWt7u0YbcVpy9WK3F72BdwU= =VJgY -----END PGP SIGNATURE----- Merge tag 'vfs-6.15-rc1.async.dir' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs async dir updates from Christian Brauner: "This contains cleanups that fell out of the work from async directory handling: - Change kern_path_locked() and user_path_locked_at() to never return a negative dentry. This simplifies the usability of these helpers in various places - Drop d_exact_alias() from the remaining place in NFS where it is still used. This also allows us to drop the d_exact_alias() helper completely - Drop an unnecessary call to fh_update() from nfsd_create_locked() - Change i_op->mkdir() to return a struct dentry Change vfs_mkdir() to return a dentry provided by the filesystems which is hashed and positive. This allows us to reduce the number of cases where the resulting dentry is not positive to very few cases. The code in these places becomes simpler and easier to understand. - Repack DENTRY_* and LOOKUP_* flags" * tag 'vfs-6.15-rc1.async.dir' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: doc: fix inline emphasis warning VFS: Change vfs_mkdir() to return the dentry. nfs: change mkdir inode_operation to return alternate dentry if needed. fuse: return correct dentry for ->mkdir ceph: return the correct dentry on mkdir hostfs: store inode in dentry after mkdir if possible. Change inode_operations.mkdir to return struct dentry * nfsd: drop fh_update() from S_IFDIR branch of nfsd_create_locked() nfs/vfs: discard d_exact_alias() VFS: add common error checks to lookup_one_qstr_excl() VFS: change kern_path_locked() and user_path_locked_at() to never return negative dentry VFS: repack LOOKUP_ bit flags. VFS: repack DENTRY_ flags.
This commit is contained in:
commit
26d8e43079
@ -66,7 +66,7 @@ prototypes::
|
||||
int (*link) (struct dentry *,struct inode *,struct dentry *);
|
||||
int (*unlink) (struct inode *,struct dentry *);
|
||||
int (*symlink) (struct mnt_idmap *, struct inode *,struct dentry *,const char *);
|
||||
int (*mkdir) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t);
|
||||
struct dentry *(*mkdir) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t);
|
||||
int (*rmdir) (struct inode *,struct dentry *);
|
||||
int (*mknod) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t,dev_t);
|
||||
int (*rename) (struct mnt_idmap *, struct inode *, struct dentry *,
|
||||
|
@ -1144,7 +1144,7 @@ and it *must* be opened exclusive.
|
||||
|
||||
---
|
||||
|
||||
** mandatory**
|
||||
**mandatory**
|
||||
|
||||
->d_revalidate() gets two extra arguments - inode of parent directory and
|
||||
name our dentry is expected to have. Both are stable (dir is pinned in
|
||||
@ -1160,5 +1160,46 @@ magic.
|
||||
|
||||
---
|
||||
|
||||
** mandatory **
|
||||
**recommended**
|
||||
|
||||
kern_path_locked() and user_path_locked() no longer return a negative
|
||||
dentry so this doesn't need to be checked. If the name cannot be found,
|
||||
ERR_PTR(-ENOENT) is returned.
|
||||
|
||||
---
|
||||
|
||||
**recommended**
|
||||
|
||||
lookup_one_qstr_excl() is changed to return errors in more cases, so
|
||||
these conditions don't require explicit checks:
|
||||
|
||||
- if LOOKUP_CREATE is NOT given, then the dentry won't be negative,
|
||||
ERR_PTR(-ENOENT) is returned instead
|
||||
- if LOOKUP_EXCL IS given, then the dentry won't be positive,
|
||||
ERR_PTR(-EEXIST) is rreturned instread
|
||||
|
||||
LOOKUP_EXCL now means "target must not exist". It can be combined with
|
||||
LOOK_CREATE or LOOKUP_RENAME_TARGET.
|
||||
|
||||
---
|
||||
|
||||
**mandatory**
|
||||
invalidate_inodes() is gone use evict_inodes() instead.
|
||||
|
||||
---
|
||||
|
||||
**mandatory**
|
||||
|
||||
->mkdir() now returns a dentry. If the created inode is found to
|
||||
already be in cache and have a dentry (often IS_ROOT()), it will need to
|
||||
be spliced into the given name in place of the given dentry. That dentry
|
||||
now needs to be returned. If the original dentry is used, NULL should
|
||||
be returned. Any error should be returned with ERR_PTR().
|
||||
|
||||
In general, filesystems which use d_instantiate_new() to install the new
|
||||
inode can safely return NULL. Filesystems which may not have an I_NEW inode
|
||||
should use d_drop();d_splice_alias() and return the result of the latter.
|
||||
|
||||
If a positive dentry cannot be returned for some reason, in-kernel
|
||||
clients such as cachefiles, nfsd, smb/server may not perform ideally but
|
||||
will fail-safe.
|
||||
|
@ -495,7 +495,7 @@ As of kernel 2.6.22, the following members are defined:
|
||||
int (*link) (struct dentry *,struct inode *,struct dentry *);
|
||||
int (*unlink) (struct inode *,struct dentry *);
|
||||
int (*symlink) (struct mnt_idmap *, struct inode *,struct dentry *,const char *);
|
||||
int (*mkdir) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t);
|
||||
struct dentry *(*mkdir) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t);
|
||||
int (*rmdir) (struct inode *,struct dentry *);
|
||||
int (*mknod) (struct mnt_idmap *, struct inode *,struct dentry *,umode_t,dev_t);
|
||||
int (*rename) (struct mnt_idmap *, struct inode *, struct dentry *,
|
||||
@ -562,7 +562,26 @@ otherwise noted.
|
||||
``mkdir``
|
||||
called by the mkdir(2) system call. Only required if you want
|
||||
to support creating subdirectories. You will probably need to
|
||||
call d_instantiate() just as you would in the create() method
|
||||
call d_instantiate_new() just as you would in the create() method.
|
||||
|
||||
If d_instantiate_new() is not used and if the fh_to_dentry()
|
||||
export operation is provided, or if the storage might be
|
||||
accessible by another path (e.g. with a network filesystem)
|
||||
then more care may be needed. Importantly d_instantate()
|
||||
should not be used with an inode that is no longer I_NEW if there
|
||||
any chance that the inode could already be attached to a dentry.
|
||||
This is because of a hard rule in the VFS that a directory must
|
||||
only ever have one dentry.
|
||||
|
||||
For example, if an NFS filesystem is mounted twice the new directory
|
||||
could be visible on the other mount before it is on the original
|
||||
mount, and a pair of name_to_handle_at(), open_by_handle_at()
|
||||
calls could instantiate the directory inode with an IS_ROOT()
|
||||
dentry before the first mkdir returns.
|
||||
|
||||
If there is any chance this could happen, then the new inode
|
||||
should be d_drop()ed and attached with d_splice_alias(). The
|
||||
returned dentry (if any) should be returned by ->mkdir().
|
||||
|
||||
``rmdir``
|
||||
called by the rmdir(2) system call. Only required if you want
|
||||
|
@ -175,18 +175,17 @@ static int dev_mkdir(const char *name, umode_t mode)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
struct path path;
|
||||
int err;
|
||||
|
||||
dentry = kern_path_create(AT_FDCWD, name, &path, LOOKUP_DIRECTORY);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
err = vfs_mkdir(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode);
|
||||
if (!err)
|
||||
dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode);
|
||||
if (!IS_ERR(dentry))
|
||||
/* mark as kernel-created inode */
|
||||
d_inode(dentry)->i_private = &thread;
|
||||
done_path_create(&path, dentry);
|
||||
return err;
|
||||
return PTR_ERR_OR_ZERO(dentry);
|
||||
}
|
||||
|
||||
static int create_path(const char *nodepath)
|
||||
@ -260,15 +259,12 @@ static int dev_rmdir(const char *name)
|
||||
dentry = kern_path_locked(name, &parent);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
if (d_really_is_positive(dentry)) {
|
||||
if (d_inode(dentry)->i_private == &thread)
|
||||
err = vfs_rmdir(&nop_mnt_idmap, d_inode(parent.dentry),
|
||||
dentry);
|
||||
else
|
||||
err = -EPERM;
|
||||
} else {
|
||||
err = -ENOENT;
|
||||
}
|
||||
if (d_inode(dentry)->i_private == &thread)
|
||||
err = vfs_rmdir(&nop_mnt_idmap, d_inode(parent.dentry),
|
||||
dentry);
|
||||
else
|
||||
err = -EPERM;
|
||||
|
||||
dput(dentry);
|
||||
inode_unlock(d_inode(parent.dentry));
|
||||
path_put(&parent);
|
||||
@ -325,6 +321,8 @@ static int handle_remove(const char *nodename, struct device *dev)
|
||||
{
|
||||
struct path parent;
|
||||
struct dentry *dentry;
|
||||
struct kstat stat;
|
||||
struct path p;
|
||||
int deleted = 0;
|
||||
int err;
|
||||
|
||||
@ -332,32 +330,28 @@ static int handle_remove(const char *nodename, struct device *dev)
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
if (d_really_is_positive(dentry)) {
|
||||
struct kstat stat;
|
||||
struct path p = {.mnt = parent.mnt, .dentry = dentry};
|
||||
err = vfs_getattr(&p, &stat, STATX_TYPE | STATX_MODE,
|
||||
AT_STATX_SYNC_AS_STAT);
|
||||
if (!err && dev_mynode(dev, d_inode(dentry), &stat)) {
|
||||
struct iattr newattrs;
|
||||
/*
|
||||
* before unlinking this node, reset permissions
|
||||
* of possible references like hardlinks
|
||||
*/
|
||||
newattrs.ia_uid = GLOBAL_ROOT_UID;
|
||||
newattrs.ia_gid = GLOBAL_ROOT_GID;
|
||||
newattrs.ia_mode = stat.mode & ~0777;
|
||||
newattrs.ia_valid =
|
||||
ATTR_UID|ATTR_GID|ATTR_MODE;
|
||||
inode_lock(d_inode(dentry));
|
||||
notify_change(&nop_mnt_idmap, dentry, &newattrs, NULL);
|
||||
inode_unlock(d_inode(dentry));
|
||||
err = vfs_unlink(&nop_mnt_idmap, d_inode(parent.dentry),
|
||||
dentry, NULL);
|
||||
if (!err || err == -ENOENT)
|
||||
deleted = 1;
|
||||
}
|
||||
} else {
|
||||
err = -ENOENT;
|
||||
p.mnt = parent.mnt;
|
||||
p.dentry = dentry;
|
||||
err = vfs_getattr(&p, &stat, STATX_TYPE | STATX_MODE,
|
||||
AT_STATX_SYNC_AS_STAT);
|
||||
if (!err && dev_mynode(dev, d_inode(dentry), &stat)) {
|
||||
struct iattr newattrs;
|
||||
/*
|
||||
* before unlinking this node, reset permissions
|
||||
* of possible references like hardlinks
|
||||
*/
|
||||
newattrs.ia_uid = GLOBAL_ROOT_UID;
|
||||
newattrs.ia_gid = GLOBAL_ROOT_GID;
|
||||
newattrs.ia_mode = stat.mode & ~0777;
|
||||
newattrs.ia_valid =
|
||||
ATTR_UID|ATTR_GID|ATTR_MODE;
|
||||
inode_lock(d_inode(dentry));
|
||||
notify_change(&nop_mnt_idmap, dentry, &newattrs, NULL);
|
||||
inode_unlock(d_inode(dentry));
|
||||
err = vfs_unlink(&nop_mnt_idmap, d_inode(parent.dentry),
|
||||
dentry, NULL);
|
||||
if (!err || err == -ENOENT)
|
||||
deleted = 1;
|
||||
}
|
||||
dput(dentry);
|
||||
inode_unlock(d_inode(parent.dentry));
|
||||
|
@ -669,8 +669,8 @@ v9fs_vfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
*
|
||||
*/
|
||||
|
||||
static int v9fs_vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *v9fs_vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
int err;
|
||||
u32 perm;
|
||||
@ -692,8 +692,7 @@ static int v9fs_vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
||||
if (fid)
|
||||
p9_fid_put(fid);
|
||||
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -350,9 +350,9 @@ out:
|
||||
*
|
||||
*/
|
||||
|
||||
static int v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap,
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
umode_t omode)
|
||||
static struct dentry *v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap,
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
umode_t omode)
|
||||
{
|
||||
int err;
|
||||
struct v9fs_session_info *v9ses;
|
||||
@ -417,7 +417,7 @@ error:
|
||||
p9_fid_put(fid);
|
||||
v9fs_put_acl(dacl, pacl);
|
||||
p9_fid_put(dfid);
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -168,7 +168,7 @@ extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, unsi
|
||||
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);
|
||||
extern int affs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
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);
|
||||
extern int affs_link(struct dentry *olddentry, struct inode *dir,
|
||||
|
@ -273,7 +273,7 @@ affs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
struct dentry *
|
||||
affs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
@ -285,7 +285,7 @@ affs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
||||
inode = affs_new_inode(dir);
|
||||
if (!inode)
|
||||
return -ENOSPC;
|
||||
return ERR_PTR(-ENOSPC);
|
||||
|
||||
inode->i_mode = S_IFDIR | mode;
|
||||
affs_mode_to_prot(inode);
|
||||
@ -298,9 +298,9 @@ affs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
clear_nlink(inode);
|
||||
mark_inode_dirty(inode);
|
||||
iput(inode);
|
||||
return error;
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
|
12
fs/afs/dir.c
12
fs/afs/dir.c
@ -33,8 +33,8 @@ static bool afs_lookup_filldir(struct dir_context *ctx, const char *name, int nl
|
||||
loff_t fpos, u64 ino, unsigned dtype);
|
||||
static int afs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl);
|
||||
static int afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
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);
|
||||
static int afs_unlink(struct inode *dir, struct dentry *dentry);
|
||||
static int afs_link(struct dentry *from, struct inode *dir,
|
||||
@ -1315,8 +1315,8 @@ static const struct afs_operation_ops afs_mkdir_operation = {
|
||||
/*
|
||||
* create a directory on an AFS filesystem
|
||||
*/
|
||||
static int afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct afs_operation *op;
|
||||
struct afs_vnode *dvnode = AFS_FS_I(dir);
|
||||
@ -1328,7 +1328,7 @@ static int afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
op = afs_alloc_operation(NULL, dvnode->volume);
|
||||
if (IS_ERR(op)) {
|
||||
d_drop(dentry);
|
||||
return PTR_ERR(op);
|
||||
return ERR_CAST(op);
|
||||
}
|
||||
|
||||
fscache_use_cookie(afs_vnode_cache(dvnode), true);
|
||||
@ -1344,7 +1344,7 @@ static int afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
op->ops = &afs_mkdir_operation;
|
||||
ret = afs_do_sync_operation(op);
|
||||
afs_dir_unuse_cookie(dvnode, ret);
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -15,8 +15,8 @@ static int autofs_dir_symlink(struct mnt_idmap *, struct inode *,
|
||||
struct dentry *, const char *);
|
||||
static int autofs_dir_unlink(struct inode *, struct dentry *);
|
||||
static int autofs_dir_rmdir(struct inode *, struct dentry *);
|
||||
static int autofs_dir_mkdir(struct mnt_idmap *, struct inode *,
|
||||
struct dentry *, umode_t);
|
||||
static struct dentry *autofs_dir_mkdir(struct mnt_idmap *, struct inode *,
|
||||
struct dentry *, umode_t);
|
||||
static long autofs_root_ioctl(struct file *, unsigned int, unsigned long);
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long autofs_root_compat_ioctl(struct file *,
|
||||
@ -720,9 +720,9 @@ static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int autofs_dir_mkdir(struct mnt_idmap *idmap,
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
umode_t mode)
|
||||
static struct dentry *autofs_dir_mkdir(struct mnt_idmap *idmap,
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
umode_t mode)
|
||||
{
|
||||
struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
|
||||
struct autofs_info *ino = autofs_dentry_ino(dentry);
|
||||
@ -739,7 +739,7 @@ static int autofs_dir_mkdir(struct mnt_idmap *idmap,
|
||||
|
||||
inode = autofs_get_inode(dir->i_sb, S_IFDIR | mode);
|
||||
if (!inode)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
d_add(dentry, inode);
|
||||
|
||||
if (sbi->version < 5)
|
||||
@ -751,7 +751,7 @@ static int autofs_dir_mkdir(struct mnt_idmap *idmap,
|
||||
inc_nlink(dir);
|
||||
inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get/set timeout ioctl() operation */
|
||||
|
@ -58,10 +58,10 @@ static int bad_inode_symlink(struct mnt_idmap *idmap,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int bad_inode_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *bad_inode_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return -EIO;
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
|
||||
static int bad_inode_rmdir (struct inode *dir, struct dentry *dentry)
|
||||
|
@ -511,10 +511,6 @@ static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
|
||||
ret = -EXDEV;
|
||||
goto err;
|
||||
}
|
||||
if (!d_is_positive(victim)) {
|
||||
ret = -ENOENT;
|
||||
goto err;
|
||||
}
|
||||
ret = __bch2_unlink(dir, victim, true);
|
||||
if (!ret) {
|
||||
fsnotify_rmdir(dir, victim);
|
||||
|
@ -858,10 +858,10 @@ err:
|
||||
return bch2_err_class(ret);
|
||||
}
|
||||
|
||||
static int bch2_mkdir(struct mnt_idmap *idmap,
|
||||
struct inode *vdir, struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *bch2_mkdir(struct mnt_idmap *idmap,
|
||||
struct inode *vdir, struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return bch2_mknod(idmap, vdir, dentry, mode|S_IFDIR, 0);
|
||||
return ERR_PTR(bch2_mknod(idmap, vdir, dentry, mode|S_IFDIR, 0));
|
||||
}
|
||||
|
||||
static int bch2_rename2(struct mnt_idmap *idmap,
|
||||
|
@ -6744,18 +6744,18 @@ fail:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int btrfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *btrfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
|
||||
inode = new_inode(dir->i_sb);
|
||||
if (!inode)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
inode_init_owner(idmap, inode, dir, S_IFDIR | mode);
|
||||
inode->i_op = &btrfs_dir_inode_operations;
|
||||
inode->i_fop = &btrfs_dir_file_operations;
|
||||
return btrfs_create_common(dir, dentry, inode);
|
||||
return ERR_PTR(btrfs_create_common(dir, dentry, inode));
|
||||
}
|
||||
|
||||
static noinline int uncompress_inline(struct btrfs_path *path,
|
||||
|
@ -128,18 +128,19 @@ retry:
|
||||
ret = security_path_mkdir(&path, subdir, 0700);
|
||||
if (ret < 0)
|
||||
goto mkdir_error;
|
||||
ret = cachefiles_inject_write_error();
|
||||
if (ret == 0)
|
||||
ret = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700);
|
||||
if (ret < 0) {
|
||||
subdir = ERR_PTR(cachefiles_inject_write_error());
|
||||
if (!IS_ERR(subdir))
|
||||
subdir = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700);
|
||||
ret = PTR_ERR(subdir);
|
||||
if (IS_ERR(subdir)) {
|
||||
trace_cachefiles_vfs_error(NULL, d_inode(dir), ret,
|
||||
cachefiles_trace_mkdir_error);
|
||||
goto mkdir_error;
|
||||
}
|
||||
trace_cachefiles_mkdir(dir, subdir);
|
||||
|
||||
if (unlikely(d_unhashed(subdir))) {
|
||||
cachefiles_put_directory(subdir);
|
||||
if (unlikely(d_unhashed(subdir) || d_is_negative(subdir))) {
|
||||
dput(subdir);
|
||||
goto retry;
|
||||
}
|
||||
ASSERT(d_backing_inode(subdir));
|
||||
@ -195,7 +196,8 @@ mark_error:
|
||||
|
||||
mkdir_error:
|
||||
inode_unlock(d_inode(dir));
|
||||
dput(subdir);
|
||||
if (!IS_ERR(subdir))
|
||||
dput(subdir);
|
||||
pr_err("mkdir %s failed with error %d\n", dirname, ret);
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
@ -1092,19 +1092,20 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ceph_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *ceph_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
|
||||
struct ceph_client *cl = mdsc->fsc->client;
|
||||
struct ceph_mds_request *req;
|
||||
struct ceph_acl_sec_ctx as_ctx = {};
|
||||
struct dentry *ret;
|
||||
int err;
|
||||
int op;
|
||||
|
||||
err = ceph_wait_on_conflict_unlink(dentry);
|
||||
if (err)
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
|
||||
if (ceph_snap(dir) == CEPH_SNAPDIR) {
|
||||
/* mkdir .snap/foo is a MKSNAP */
|
||||
@ -1116,32 +1117,32 @@ static int ceph_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
ceph_vinop(dir), dentry, dentry, mode);
|
||||
op = CEPH_MDS_OP_MKDIR;
|
||||
} else {
|
||||
err = -EROFS;
|
||||
ret = ERR_PTR(-EROFS);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (op == CEPH_MDS_OP_MKDIR &&
|
||||
ceph_quota_is_max_files_exceeded(dir)) {
|
||||
err = -EDQUOT;
|
||||
ret = ERR_PTR(-EDQUOT);
|
||||
goto out;
|
||||
}
|
||||
if ((op == CEPH_MDS_OP_MKSNAP) && IS_ENCRYPTED(dir) &&
|
||||
!fscrypt_has_encryption_key(dir)) {
|
||||
err = -ENOKEY;
|
||||
ret = ERR_PTR(-ENOKEY);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
|
||||
if (IS_ERR(req)) {
|
||||
err = PTR_ERR(req);
|
||||
ret = ERR_CAST(req);
|
||||
goto out;
|
||||
}
|
||||
|
||||
mode |= S_IFDIR;
|
||||
req->r_new_inode = ceph_new_inode(dir, dentry, &mode, &as_ctx);
|
||||
if (IS_ERR(req->r_new_inode)) {
|
||||
err = PTR_ERR(req->r_new_inode);
|
||||
ret = ERR_CAST(req->r_new_inode);
|
||||
req->r_new_inode = NULL;
|
||||
goto out_req;
|
||||
}
|
||||
@ -1165,15 +1166,22 @@ static int ceph_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
!req->r_reply_info.head->is_target &&
|
||||
!req->r_reply_info.head->is_dentry)
|
||||
err = ceph_handle_notrace_create(dir, dentry);
|
||||
ret = ERR_PTR(err);
|
||||
out_req:
|
||||
if (!IS_ERR(ret) && req->r_dentry != dentry)
|
||||
/* Some other dentry was spliced in */
|
||||
ret = dget(req->r_dentry);
|
||||
ceph_mdsc_put_request(req);
|
||||
out:
|
||||
if (!err)
|
||||
if (!IS_ERR(ret)) {
|
||||
if (ret)
|
||||
dentry = ret;
|
||||
ceph_init_inode_acls(d_inode(dentry), &as_ctx);
|
||||
else
|
||||
} else {
|
||||
d_drop(dentry);
|
||||
}
|
||||
ceph_release_acl_sec_ctx(&as_ctx);
|
||||
return err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ceph_link(struct dentry *old_dentry, struct inode *dir,
|
||||
|
@ -166,8 +166,8 @@ err_out:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int coda_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *de, umode_t mode)
|
||||
static struct dentry *coda_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *de, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct coda_vattr attrs;
|
||||
@ -177,14 +177,14 @@ static int coda_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct CodaFid newfid;
|
||||
|
||||
if (is_root_inode(dir) && coda_iscontrol(name, len))
|
||||
return -EPERM;
|
||||
return ERR_PTR(-EPERM);
|
||||
|
||||
attrs.va_mode = mode;
|
||||
error = venus_mkdir(dir->i_sb, coda_i2f(dir),
|
||||
error = venus_mkdir(dir->i_sb, coda_i2f(dir),
|
||||
name, len, &newfid, &attrs);
|
||||
if (error)
|
||||
goto err_out;
|
||||
|
||||
|
||||
inode = coda_iget(dir->i_sb, &newfid, &attrs);
|
||||
if (IS_ERR(inode)) {
|
||||
error = PTR_ERR(inode);
|
||||
@ -195,10 +195,10 @@ static int coda_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
coda_dir_inc_nlink(dir);
|
||||
coda_dir_update_mtime(dir);
|
||||
d_instantiate(de, inode);
|
||||
return 0;
|
||||
return NULL;
|
||||
err_out:
|
||||
d_drop(de);
|
||||
return error;
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
/* try to make de an entry in dir_inodde linked to source_de */
|
||||
|
@ -1280,8 +1280,8 @@ out_root_unlock:
|
||||
}
|
||||
EXPORT_SYMBOL(configfs_depend_item_unlocked);
|
||||
|
||||
static int configfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *configfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
int ret = 0;
|
||||
int module_got = 0;
|
||||
@ -1461,7 +1461,7 @@ out_put:
|
||||
put_fragment(frag);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
|
46
fs/dcache.c
46
fs/dcache.c
@ -2688,52 +2688,6 @@ void d_add(struct dentry *entry, struct inode *inode)
|
||||
}
|
||||
EXPORT_SYMBOL(d_add);
|
||||
|
||||
/**
|
||||
* d_exact_alias - find and hash an exact unhashed alias
|
||||
* @entry: dentry to add
|
||||
* @inode: The inode to go with this dentry
|
||||
*
|
||||
* If an unhashed dentry with the same name/parent and desired
|
||||
* inode already exists, hash and return it. Otherwise, return
|
||||
* NULL.
|
||||
*
|
||||
* Parent directory should be locked.
|
||||
*/
|
||||
struct dentry *d_exact_alias(struct dentry *entry, struct inode *inode)
|
||||
{
|
||||
struct dentry *alias;
|
||||
unsigned int hash = entry->d_name.hash;
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
|
||||
/*
|
||||
* Don't need alias->d_lock here, because aliases with
|
||||
* d_parent == entry->d_parent are not subject to name or
|
||||
* parent changes, because the parent inode i_mutex is held.
|
||||
*/
|
||||
if (alias->d_name.hash != hash)
|
||||
continue;
|
||||
if (alias->d_parent != entry->d_parent)
|
||||
continue;
|
||||
if (!d_same_name(alias, entry->d_parent, &entry->d_name))
|
||||
continue;
|
||||
spin_lock(&alias->d_lock);
|
||||
if (!d_unhashed(alias)) {
|
||||
spin_unlock(&alias->d_lock);
|
||||
alias = NULL;
|
||||
} else {
|
||||
dget_dlock(alias);
|
||||
__d_rehash(alias);
|
||||
spin_unlock(&alias->d_lock);
|
||||
}
|
||||
spin_unlock(&inode->i_lock);
|
||||
return alias;
|
||||
}
|
||||
spin_unlock(&inode->i_lock);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(d_exact_alias);
|
||||
|
||||
static void swap_names(struct dentry *dentry, struct dentry *target)
|
||||
{
|
||||
if (unlikely(dname_external(target))) {
|
||||
|
@ -503,18 +503,24 @@ out_lock:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ecryptfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *ecryptfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
int rc;
|
||||
struct dentry *lower_dentry;
|
||||
struct inode *lower_dir;
|
||||
|
||||
rc = lock_parent(dentry, &lower_dentry, &lower_dir);
|
||||
if (!rc)
|
||||
rc = vfs_mkdir(&nop_mnt_idmap, lower_dir,
|
||||
lower_dentry, mode);
|
||||
if (rc || d_really_is_negative(lower_dentry))
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
lower_dentry = vfs_mkdir(&nop_mnt_idmap, lower_dir,
|
||||
lower_dentry, mode);
|
||||
rc = PTR_ERR(lower_dentry);
|
||||
if (IS_ERR(lower_dentry))
|
||||
goto out;
|
||||
rc = 0;
|
||||
if (d_unhashed(lower_dentry))
|
||||
goto out;
|
||||
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
|
||||
if (rc)
|
||||
@ -526,7 +532,7 @@ out:
|
||||
inode_unlock(lower_dir);
|
||||
if (d_really_is_negative(dentry))
|
||||
d_drop(dentry);
|
||||
return rc;
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
|
@ -840,8 +840,8 @@ unlock:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int exfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *exfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct inode *inode;
|
||||
@ -851,7 +851,7 @@ static int exfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
loff_t size = i_size_read(dir);
|
||||
|
||||
if (unlikely(exfat_forced_shutdown(sb)))
|
||||
return -EIO;
|
||||
return ERR_PTR(-EIO);
|
||||
|
||||
mutex_lock(&EXFAT_SB(sb)->s_lock);
|
||||
exfat_set_volume_dirty(sb);
|
||||
@ -882,7 +882,7 @@ static int exfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&EXFAT_SB(sb)->s_lock);
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static int exfat_check_dir_empty(struct super_block *sb,
|
||||
|
@ -225,15 +225,16 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ext2_mkdir(struct mnt_idmap * idmap,
|
||||
struct inode * dir, struct dentry * dentry, umode_t mode)
|
||||
static struct dentry *ext2_mkdir(struct mnt_idmap * idmap,
|
||||
struct inode * dir, struct dentry * dentry,
|
||||
umode_t mode)
|
||||
{
|
||||
struct inode * inode;
|
||||
int err;
|
||||
|
||||
err = dquot_initialize(dir);
|
||||
if (err)
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
|
||||
inode_inc_link_count(dir);
|
||||
|
||||
@ -258,7 +259,7 @@ static int ext2_mkdir(struct mnt_idmap * idmap,
|
||||
|
||||
d_instantiate_new(dentry, inode);
|
||||
out:
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
|
||||
out_fail:
|
||||
inode_dec_link_count(inode);
|
||||
|
@ -3004,19 +3004,19 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ext4_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *ext4_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
handle_t *handle;
|
||||
struct inode *inode;
|
||||
int err, err2 = 0, credits, retries = 0;
|
||||
|
||||
if (EXT4_DIR_LINK_MAX(dir))
|
||||
return -EMLINK;
|
||||
return ERR_PTR(-EMLINK);
|
||||
|
||||
err = dquot_initialize(dir);
|
||||
if (err)
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
|
||||
credits = (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
|
||||
EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3);
|
||||
@ -3066,7 +3066,7 @@ out_stop:
|
||||
out_retry:
|
||||
if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
|
||||
goto retry;
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -684,23 +684,23 @@ out_free_encrypted_link:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int f2fs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *f2fs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
|
||||
struct inode *inode;
|
||||
int err;
|
||||
|
||||
if (unlikely(f2fs_cp_error(sbi)))
|
||||
return -EIO;
|
||||
return ERR_PTR(-EIO);
|
||||
|
||||
err = f2fs_dquot_initialize(dir);
|
||||
if (err)
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
|
||||
inode = f2fs_new_inode(idmap, dir, S_IFDIR | mode, NULL);
|
||||
if (IS_ERR(inode))
|
||||
return PTR_ERR(inode);
|
||||
return ERR_CAST(inode);
|
||||
|
||||
inode->i_op = &f2fs_dir_inode_operations;
|
||||
inode->i_fop = &f2fs_dir_operations;
|
||||
@ -722,12 +722,12 @@ static int f2fs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
f2fs_sync_fs(sbi->sb, 1);
|
||||
|
||||
f2fs_balance_fs(sbi, true);
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
out_fail:
|
||||
clear_inode_flag(inode, FI_INC_LINK);
|
||||
f2fs_handle_failed_inode(inode);
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static int f2fs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
|
@ -339,8 +339,8 @@ out:
|
||||
}
|
||||
|
||||
/***** Make a directory */
|
||||
static int msdos_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *msdos_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct fat_slot_info sinfo;
|
||||
@ -389,13 +389,13 @@ static int msdos_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
||||
mutex_unlock(&MSDOS_SB(sb)->s_lock);
|
||||
fat_flush_inodes(sb, dir, inode);
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
out_free:
|
||||
fat_free_clusters(dir, cluster);
|
||||
out:
|
||||
mutex_unlock(&MSDOS_SB(sb)->s_lock);
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
/***** Unlink a file */
|
||||
|
@ -841,8 +841,8 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int vfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *vfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct inode *inode;
|
||||
@ -877,13 +877,13 @@ static int vfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
d_instantiate(dentry, inode);
|
||||
|
||||
mutex_unlock(&MSDOS_SB(sb)->s_lock);
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
out_free:
|
||||
fat_free_clusters(dir, cluster);
|
||||
out:
|
||||
mutex_unlock(&MSDOS_SB(sb)->s_lock);
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static int vfat_get_dotdot_de(struct inode *inode, struct buffer_head **bh,
|
||||
|
@ -781,9 +781,9 @@ no_open:
|
||||
/*
|
||||
* Code shared between mknod, mkdir, symlink and link
|
||||
*/
|
||||
static int create_new_entry(struct mnt_idmap *idmap, struct fuse_mount *fm,
|
||||
struct fuse_args *args, struct inode *dir,
|
||||
struct dentry *entry, umode_t mode)
|
||||
static struct dentry *create_new_entry(struct mnt_idmap *idmap, struct fuse_mount *fm,
|
||||
struct fuse_args *args, struct inode *dir,
|
||||
struct dentry *entry, umode_t mode)
|
||||
{
|
||||
struct fuse_entry_out outarg;
|
||||
struct inode *inode;
|
||||
@ -792,11 +792,11 @@ static int create_new_entry(struct mnt_idmap *idmap, struct fuse_mount *fm,
|
||||
struct fuse_forget_link *forget;
|
||||
|
||||
if (fuse_is_bad(dir))
|
||||
return -EIO;
|
||||
return ERR_PTR(-EIO);
|
||||
|
||||
forget = fuse_alloc_forget();
|
||||
if (!forget)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memset(&outarg, 0, sizeof(outarg));
|
||||
args->nodeid = get_node_id(dir);
|
||||
@ -826,29 +826,43 @@ static int create_new_entry(struct mnt_idmap *idmap, struct fuse_mount *fm,
|
||||
&outarg.attr, ATTR_TIMEOUT(&outarg), 0, 0);
|
||||
if (!inode) {
|
||||
fuse_queue_forget(fm->fc, forget, outarg.nodeid, 1);
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
kfree(forget);
|
||||
|
||||
d_drop(entry);
|
||||
d = d_splice_alias(inode, entry);
|
||||
if (IS_ERR(d))
|
||||
return PTR_ERR(d);
|
||||
return d;
|
||||
|
||||
if (d) {
|
||||
if (d)
|
||||
fuse_change_entry_timeout(d, &outarg);
|
||||
dput(d);
|
||||
} else {
|
||||
else
|
||||
fuse_change_entry_timeout(entry, &outarg);
|
||||
}
|
||||
fuse_dir_changed(dir);
|
||||
return 0;
|
||||
return d;
|
||||
|
||||
out_put_forget_req:
|
||||
if (err == -EEXIST)
|
||||
fuse_invalidate_entry(entry);
|
||||
kfree(forget);
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static int create_new_nondir(struct mnt_idmap *idmap, struct fuse_mount *fm,
|
||||
struct fuse_args *args, struct inode *dir,
|
||||
struct dentry *entry, umode_t mode)
|
||||
{
|
||||
/*
|
||||
* Note that when creating anything other than a directory we
|
||||
* can be sure create_new_entry() will NOT return an alternate
|
||||
* dentry as d_splice_alias() only returns an alternate dentry
|
||||
* for directories. So we don't need to check for that case
|
||||
* when passing back the result.
|
||||
*/
|
||||
WARN_ON_ONCE(S_ISDIR(mode));
|
||||
|
||||
return PTR_ERR(create_new_entry(idmap, fm, args, dir, entry, mode));
|
||||
}
|
||||
|
||||
static int fuse_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||
@ -871,7 +885,7 @@ static int fuse_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||
args.in_args[0].value = &inarg;
|
||||
args.in_args[1].size = entry->d_name.len + 1;
|
||||
args.in_args[1].value = entry->d_name.name;
|
||||
return create_new_entry(idmap, fm, &args, dir, entry, mode);
|
||||
return create_new_nondir(idmap, fm, &args, dir, entry, mode);
|
||||
}
|
||||
|
||||
static int fuse_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
@ -898,8 +912,8 @@ static int fuse_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int fuse_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *entry, umode_t mode)
|
||||
static struct dentry *fuse_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *entry, umode_t mode)
|
||||
{
|
||||
struct fuse_mkdir_in inarg;
|
||||
struct fuse_mount *fm = get_fuse_mount(dir);
|
||||
@ -934,7 +948,7 @@ static int fuse_symlink(struct mnt_idmap *idmap, struct inode *dir,
|
||||
args.in_args[1].value = entry->d_name.name;
|
||||
args.in_args[2].size = len;
|
||||
args.in_args[2].value = link;
|
||||
return create_new_entry(idmap, fm, &args, dir, entry, S_IFLNK);
|
||||
return create_new_nondir(idmap, fm, &args, dir, entry, S_IFLNK);
|
||||
}
|
||||
|
||||
void fuse_flush_time_update(struct inode *inode)
|
||||
@ -1131,7 +1145,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
|
||||
args.in_args[0].value = &inarg;
|
||||
args.in_args[1].size = newent->d_name.len + 1;
|
||||
args.in_args[1].value = newent->d_name.name;
|
||||
err = create_new_entry(&invalid_mnt_idmap, fm, &args, newdir, newent, inode->i_mode);
|
||||
err = create_new_nondir(&invalid_mnt_idmap, fm, &args, newdir, newent, inode->i_mode);
|
||||
if (!err)
|
||||
fuse_update_ctime_in_cache(inode);
|
||||
else if (err == -EINTR)
|
||||
|
@ -1248,14 +1248,15 @@ static int gfs2_symlink(struct mnt_idmap *idmap, struct inode *dir,
|
||||
* @dentry: The dentry of the new directory
|
||||
* @mode: The mode of the new directory
|
||||
*
|
||||
* Returns: errno
|
||||
* Returns: the dentry, or ERR_PTR(errno)
|
||||
*/
|
||||
|
||||
static int gfs2_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *gfs2_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
unsigned dsize = gfs2_max_stuffed_size(GFS2_I(dir));
|
||||
return gfs2_create_inode(dir, dentry, NULL, S_IFDIR | mode, 0, NULL, dsize, 0);
|
||||
|
||||
return ERR_PTR(gfs2_create_inode(dir, dentry, NULL, S_IFDIR | mode, 0, NULL, dsize, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
10
fs/hfs/dir.c
10
fs/hfs/dir.c
@ -219,26 +219,26 @@ static int hfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
* in a directory, given the inode for the parent directory and the
|
||||
* name (and its length) of the new directory.
|
||||
*/
|
||||
static int hfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *hfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
int res;
|
||||
|
||||
inode = hfs_new_inode(dir, &dentry->d_name, S_IFDIR | mode);
|
||||
if (!inode)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
|
||||
if (res) {
|
||||
clear_nlink(inode);
|
||||
hfs_delete_inode(inode);
|
||||
iput(inode);
|
||||
return res;
|
||||
return ERR_PTR(res);
|
||||
}
|
||||
d_instantiate(dentry, inode);
|
||||
mark_inode_dirty(inode);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -523,10 +523,10 @@ static int hfsplus_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
return hfsplus_mknod(&nop_mnt_idmap, dir, dentry, mode, 0);
|
||||
}
|
||||
|
||||
static int hfsplus_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *hfsplus_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return hfsplus_mknod(&nop_mnt_idmap, dir, dentry, mode | S_IFDIR, 0);
|
||||
return ERR_PTR(hfsplus_mknod(&nop_mnt_idmap, dir, dentry, mode | S_IFDIR, 0));
|
||||
}
|
||||
|
||||
static int hfsplus_rename(struct mnt_idmap *idmap,
|
||||
|
@ -679,17 +679,25 @@ static int hostfs_symlink(struct mnt_idmap *idmap, struct inode *ino,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int hostfs_mkdir(struct mnt_idmap *idmap, struct inode *ino,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *hostfs_mkdir(struct mnt_idmap *idmap, struct inode *ino,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
char *file;
|
||||
int err;
|
||||
|
||||
if ((file = dentry_name(dentry)) == NULL)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
err = do_mkdir(file, mode);
|
||||
if (err) {
|
||||
dentry = ERR_PTR(err);
|
||||
} else {
|
||||
inode = hostfs_iget(dentry->d_sb, file);
|
||||
d_drop(dentry);
|
||||
dentry = d_splice_alias(inode, dentry);
|
||||
}
|
||||
__putname(file);
|
||||
return err;
|
||||
return dentry;
|
||||
}
|
||||
|
||||
static int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
|
||||
|
@ -19,8 +19,8 @@ static void hpfs_update_directory_times(struct inode *dir)
|
||||
hpfs_write_inode_nolock(dir);
|
||||
}
|
||||
|
||||
static int hpfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *hpfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
const unsigned char *name = dentry->d_name.name;
|
||||
unsigned len = dentry->d_name.len;
|
||||
@ -35,7 +35,7 @@ static int hpfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
int r;
|
||||
struct hpfs_dirent dee;
|
||||
int err;
|
||||
if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
|
||||
if ((err = hpfs_chk_name(name, &len))) return ERR_PTR(err==-ENOENT ? -EINVAL : err);
|
||||
hpfs_lock(dir->i_sb);
|
||||
err = -ENOSPC;
|
||||
fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
|
||||
@ -112,7 +112,7 @@ static int hpfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
hpfs_update_directory_times(dir);
|
||||
d_instantiate(dentry, result);
|
||||
hpfs_unlock(dir->i_sb);
|
||||
return 0;
|
||||
return NULL;
|
||||
bail3:
|
||||
iput(result);
|
||||
bail2:
|
||||
@ -123,7 +123,7 @@ bail1:
|
||||
hpfs_free_sectors(dir->i_sb, fno, 1);
|
||||
bail:
|
||||
hpfs_unlock(dir->i_sb);
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static int hpfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
@ -991,14 +991,14 @@ static int hugetlbfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hugetlbfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *hugetlbfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
int retval = hugetlbfs_mknod(idmap, dir, dentry,
|
||||
mode | S_IFDIR, 0);
|
||||
if (!retval)
|
||||
inc_nlink(dir);
|
||||
return retval;
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
|
||||
static int hugetlbfs_create(struct mnt_idmap *idmap,
|
||||
|
@ -230,9 +230,12 @@ int __init init_mkdir(const char *pathname, umode_t mode)
|
||||
return PTR_ERR(dentry);
|
||||
mode = mode_strip_umask(d_inode(path.dentry), mode);
|
||||
error = security_path_mkdir(&path, dentry, mode);
|
||||
if (!error)
|
||||
error = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode,
|
||||
if (!error) {
|
||||
dentry = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode,
|
||||
dentry, mode);
|
||||
if (IS_ERR(dentry))
|
||||
error = PTR_ERR(dentry);
|
||||
}
|
||||
done_path_create(&path, dentry);
|
||||
return error;
|
||||
}
|
||||
|
@ -32,8 +32,8 @@ static int jffs2_link (struct dentry *,struct inode *,struct dentry *);
|
||||
static int jffs2_unlink (struct inode *,struct dentry *);
|
||||
static int jffs2_symlink (struct mnt_idmap *, struct inode *,
|
||||
struct dentry *, const char *);
|
||||
static int jffs2_mkdir (struct mnt_idmap *, struct inode *,struct dentry *,
|
||||
umode_t);
|
||||
static struct dentry *jffs2_mkdir (struct mnt_idmap *, struct inode *,struct dentry *,
|
||||
umode_t);
|
||||
static int jffs2_rmdir (struct inode *,struct dentry *);
|
||||
static int jffs2_mknod (struct mnt_idmap *, struct inode *,struct dentry *,
|
||||
umode_t,dev_t);
|
||||
@ -446,8 +446,8 @@ static int jffs2_symlink (struct mnt_idmap *idmap, struct inode *dir_i,
|
||||
}
|
||||
|
||||
|
||||
static int jffs2_mkdir (struct mnt_idmap *idmap, struct inode *dir_i,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *jffs2_mkdir (struct mnt_idmap *idmap, struct inode *dir_i,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct jffs2_inode_info *f, *dir_f;
|
||||
struct jffs2_sb_info *c;
|
||||
@ -464,7 +464,7 @@ static int jffs2_mkdir (struct mnt_idmap *idmap, struct inode *dir_i,
|
||||
|
||||
ri = jffs2_alloc_raw_inode();
|
||||
if (!ri)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
c = JFFS2_SB_INFO(dir_i->i_sb);
|
||||
|
||||
@ -477,7 +477,7 @@ static int jffs2_mkdir (struct mnt_idmap *idmap, struct inode *dir_i,
|
||||
|
||||
if (ret) {
|
||||
jffs2_free_raw_inode(ri);
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
inode = jffs2_new_inode(dir_i, mode, ri);
|
||||
@ -485,7 +485,7 @@ static int jffs2_mkdir (struct mnt_idmap *idmap, struct inode *dir_i,
|
||||
if (IS_ERR(inode)) {
|
||||
jffs2_free_raw_inode(ri);
|
||||
jffs2_complete_reservation(c);
|
||||
return PTR_ERR(inode);
|
||||
return ERR_CAST(inode);
|
||||
}
|
||||
|
||||
inode->i_op = &jffs2_dir_inode_operations;
|
||||
@ -584,11 +584,11 @@ static int jffs2_mkdir (struct mnt_idmap *idmap, struct inode *dir_i,
|
||||
jffs2_complete_reservation(c);
|
||||
|
||||
d_instantiate_new(dentry, inode);
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
fail:
|
||||
iget_failed(inode);
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
|
||||
|
@ -187,13 +187,13 @@ static int jfs_create(struct mnt_idmap *idmap, struct inode *dip,
|
||||
* dentry - dentry of child directory
|
||||
* mode - create mode (rwxrwxrwx).
|
||||
*
|
||||
* RETURN: Errors from subroutines
|
||||
* RETURN: ERR_PTR() of errors from subroutines.
|
||||
*
|
||||
* note:
|
||||
* EACCES: user needs search+write permission on the parent directory
|
||||
*/
|
||||
static int jfs_mkdir(struct mnt_idmap *idmap, struct inode *dip,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *jfs_mkdir(struct mnt_idmap *idmap, struct inode *dip,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
int rc = 0;
|
||||
tid_t tid; /* transaction id */
|
||||
@ -308,7 +308,7 @@ static int jfs_mkdir(struct mnt_idmap *idmap, struct inode *dip,
|
||||
out1:
|
||||
|
||||
jfs_info("jfs_mkdir: rc:%d", rc);
|
||||
return rc;
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1230,24 +1230,24 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir,
|
||||
return d_splice_alias(inode, dentry);
|
||||
}
|
||||
|
||||
static int kernfs_iop_mkdir(struct mnt_idmap *idmap,
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
umode_t mode)
|
||||
static struct dentry *kernfs_iop_mkdir(struct mnt_idmap *idmap,
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
umode_t mode)
|
||||
{
|
||||
struct kernfs_node *parent = dir->i_private;
|
||||
struct kernfs_syscall_ops *scops = kernfs_root(parent)->syscall_ops;
|
||||
int ret;
|
||||
|
||||
if (!scops || !scops->mkdir)
|
||||
return -EPERM;
|
||||
return ERR_PTR(-EPERM);
|
||||
|
||||
if (!kernfs_get_active(parent))
|
||||
return -ENODEV;
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
ret = scops->mkdir(parent, dentry->d_name.name, mode);
|
||||
|
||||
kernfs_put_active(parent);
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int kernfs_iop_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
|
@ -104,15 +104,15 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir,
|
||||
return add_nondir(dentry, inode);
|
||||
}
|
||||
|
||||
static int minix_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *minix_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode * inode;
|
||||
int err;
|
||||
|
||||
inode = minix_new_inode(dir, S_IFDIR | mode);
|
||||
if (IS_ERR(inode))
|
||||
return PTR_ERR(inode);
|
||||
return ERR_CAST(inode);
|
||||
|
||||
inode_inc_link_count(dir);
|
||||
minix_set_inode(inode, 0);
|
||||
@ -128,7 +128,7 @@ static int minix_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
||||
d_instantiate(dentry, inode);
|
||||
out:
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
|
||||
out_fail:
|
||||
inode_dec_link_count(inode);
|
||||
|
105
fs/namei.c
105
fs/namei.c
@ -1671,6 +1671,8 @@ static struct dentry *lookup_dcache(const struct qstr *name,
|
||||
* dentries - as the matter of fact, this only gets called
|
||||
* when directory is guaranteed to have no in-lookup children
|
||||
* at all.
|
||||
* Will return -ENOENT if name isn't found and LOOKUP_CREATE wasn't passed.
|
||||
* Will return -EEXIST if name is found and LOOKUP_EXCL was passed.
|
||||
*/
|
||||
struct dentry *lookup_one_qstr_excl(const struct qstr *name,
|
||||
struct dentry *base,
|
||||
@ -1681,7 +1683,7 @@ struct dentry *lookup_one_qstr_excl(const struct qstr *name,
|
||||
struct inode *dir = base->d_inode;
|
||||
|
||||
if (dentry)
|
||||
return dentry;
|
||||
goto found;
|
||||
|
||||
/* Don't create child dentry for a dead directory. */
|
||||
if (unlikely(IS_DEADDIR(dir)))
|
||||
@ -1696,6 +1698,17 @@ struct dentry *lookup_one_qstr_excl(const struct qstr *name,
|
||||
dput(dentry);
|
||||
dentry = old;
|
||||
}
|
||||
found:
|
||||
if (IS_ERR(dentry))
|
||||
return dentry;
|
||||
if (d_is_negative(dentry) && !(flags & LOOKUP_CREATE)) {
|
||||
dput(dentry);
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
if (d_is_positive(dentry) && (flags & LOOKUP_EXCL)) {
|
||||
dput(dentry);
|
||||
return ERR_PTR(-EEXIST);
|
||||
}
|
||||
return dentry;
|
||||
}
|
||||
EXPORT_SYMBOL(lookup_one_qstr_excl);
|
||||
@ -4080,27 +4093,13 @@ static struct dentry *filename_create(int dfd, struct filename *name,
|
||||
* '/', and a directory wasn't requested.
|
||||
*/
|
||||
if (last.name[last.len] && !want_dir)
|
||||
create_flags = 0;
|
||||
create_flags &= ~LOOKUP_CREATE;
|
||||
inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
|
||||
dentry = lookup_one_qstr_excl(&last, path->dentry,
|
||||
reval_flag | create_flags);
|
||||
if (IS_ERR(dentry))
|
||||
goto unlock;
|
||||
|
||||
error = -EEXIST;
|
||||
if (d_is_positive(dentry))
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Special case - lookup gave negative, but... we had foo/bar/
|
||||
* From the vfs_mknod() POV we just have a negative dentry -
|
||||
* all is fine. Let's be bastards - you had / on the end, you've
|
||||
* been asking for (non-existent) directory. -ENOENT for you.
|
||||
*/
|
||||
if (unlikely(!create_flags)) {
|
||||
error = -ENOENT;
|
||||
goto fail;
|
||||
}
|
||||
if (unlikely(err2)) {
|
||||
error = err2;
|
||||
goto fail;
|
||||
@ -4131,7 +4130,8 @@ EXPORT_SYMBOL(kern_path_create);
|
||||
|
||||
void done_path_create(struct path *path, struct dentry *dentry)
|
||||
{
|
||||
dput(dentry);
|
||||
if (!IS_ERR(dentry))
|
||||
dput(dentry);
|
||||
inode_unlock(path->dentry->d_inode);
|
||||
mnt_drop_write(path->mnt);
|
||||
path_put(path);
|
||||
@ -4277,7 +4277,7 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d
|
||||
}
|
||||
|
||||
/**
|
||||
* vfs_mkdir - create directory
|
||||
* vfs_mkdir - create directory returning correct dentry if possible
|
||||
* @idmap: idmap of the mount the inode was found from
|
||||
* @dir: inode of the parent directory
|
||||
* @dentry: dentry of the child directory
|
||||
@ -4290,32 +4290,51 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d
|
||||
* care to map the inode according to @idmap before checking permissions.
|
||||
* On non-idmapped mounts or if permission checking is to be performed on the
|
||||
* raw inode simply pass @nop_mnt_idmap.
|
||||
*
|
||||
* In the event that the filesystem does not use the *@dentry but leaves it
|
||||
* negative or unhashes it and possibly splices a different one returning it,
|
||||
* the original dentry is dput() and the alternate is returned.
|
||||
*
|
||||
* In case of an error the dentry is dput() and an ERR_PTR() is returned.
|
||||
*/
|
||||
int vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
struct dentry *vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
int error;
|
||||
unsigned max_links = dir->i_sb->s_max_links;
|
||||
struct dentry *de;
|
||||
|
||||
error = may_create(idmap, dir, dentry);
|
||||
if (error)
|
||||
return error;
|
||||
goto err;
|
||||
|
||||
error = -EPERM;
|
||||
if (!dir->i_op->mkdir)
|
||||
return -EPERM;
|
||||
goto err;
|
||||
|
||||
mode = vfs_prepare_mode(idmap, dir, mode, S_IRWXUGO | S_ISVTX, 0);
|
||||
error = security_inode_mkdir(dir, dentry, mode);
|
||||
if (error)
|
||||
return error;
|
||||
goto err;
|
||||
|
||||
error = -EMLINK;
|
||||
if (max_links && dir->i_nlink >= max_links)
|
||||
return -EMLINK;
|
||||
goto err;
|
||||
|
||||
error = dir->i_op->mkdir(idmap, dir, dentry, mode);
|
||||
if (!error)
|
||||
fsnotify_mkdir(dir, dentry);
|
||||
return error;
|
||||
de = dir->i_op->mkdir(idmap, dir, dentry, mode);
|
||||
error = PTR_ERR(de);
|
||||
if (IS_ERR(de))
|
||||
goto err;
|
||||
if (de) {
|
||||
dput(dentry);
|
||||
dentry = de;
|
||||
}
|
||||
fsnotify_mkdir(dir, dentry);
|
||||
return dentry;
|
||||
|
||||
err:
|
||||
dput(dentry);
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
EXPORT_SYMBOL(vfs_mkdir);
|
||||
|
||||
@ -4335,8 +4354,10 @@ retry:
|
||||
error = security_path_mkdir(&path, dentry,
|
||||
mode_strip_umask(path.dentry->d_inode, mode));
|
||||
if (!error) {
|
||||
error = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode,
|
||||
dentry = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode,
|
||||
dentry, mode);
|
||||
if (IS_ERR(dentry))
|
||||
error = PTR_ERR(dentry);
|
||||
}
|
||||
done_path_create(&path, dentry);
|
||||
if (retry_estale(error, lookup_flags)) {
|
||||
@ -4447,10 +4468,6 @@ retry:
|
||||
error = PTR_ERR(dentry);
|
||||
if (IS_ERR(dentry))
|
||||
goto exit3;
|
||||
if (!dentry->d_inode) {
|
||||
error = -ENOENT;
|
||||
goto exit4;
|
||||
}
|
||||
error = security_path_rmdir(&path, dentry);
|
||||
if (error)
|
||||
goto exit4;
|
||||
@ -4581,7 +4598,7 @@ retry_deleg:
|
||||
if (!IS_ERR(dentry)) {
|
||||
|
||||
/* Why not before? Because we want correct error value */
|
||||
if (last.name[last.len] || d_is_negative(dentry))
|
||||
if (last.name[last.len])
|
||||
goto slashes;
|
||||
inode = dentry->d_inode;
|
||||
ihold(inode);
|
||||
@ -4615,9 +4632,7 @@ exit1:
|
||||
return error;
|
||||
|
||||
slashes:
|
||||
if (d_is_negative(dentry))
|
||||
error = -ENOENT;
|
||||
else if (d_is_dir(dentry))
|
||||
if (d_is_dir(dentry))
|
||||
error = -EISDIR;
|
||||
else
|
||||
error = -ENOTDIR;
|
||||
@ -5117,7 +5132,8 @@ int do_renameat2(int olddfd, struct filename *from, int newdfd,
|
||||
struct qstr old_last, new_last;
|
||||
int old_type, new_type;
|
||||
struct inode *delegated_inode = NULL;
|
||||
unsigned int lookup_flags = 0, target_flags = LOOKUP_RENAME_TARGET;
|
||||
unsigned int lookup_flags = 0, target_flags =
|
||||
LOOKUP_RENAME_TARGET | LOOKUP_CREATE;
|
||||
bool should_retry = false;
|
||||
int error = -EINVAL;
|
||||
|
||||
@ -5130,6 +5146,8 @@ int do_renameat2(int olddfd, struct filename *from, int newdfd,
|
||||
|
||||
if (flags & RENAME_EXCHANGE)
|
||||
target_flags = 0;
|
||||
if (flags & RENAME_NOREPLACE)
|
||||
target_flags |= LOOKUP_EXCL;
|
||||
|
||||
retry:
|
||||
error = filename_parentat(olddfd, from, lookup_flags, &old_path,
|
||||
@ -5171,23 +5189,12 @@ retry_deleg:
|
||||
error = PTR_ERR(old_dentry);
|
||||
if (IS_ERR(old_dentry))
|
||||
goto exit3;
|
||||
/* source must exist */
|
||||
error = -ENOENT;
|
||||
if (d_is_negative(old_dentry))
|
||||
goto exit4;
|
||||
new_dentry = lookup_one_qstr_excl(&new_last, new_path.dentry,
|
||||
lookup_flags | target_flags);
|
||||
error = PTR_ERR(new_dentry);
|
||||
if (IS_ERR(new_dentry))
|
||||
goto exit4;
|
||||
error = -EEXIST;
|
||||
if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry))
|
||||
goto exit5;
|
||||
if (flags & RENAME_EXCHANGE) {
|
||||
error = -ENOENT;
|
||||
if (d_is_negative(new_dentry))
|
||||
goto exit5;
|
||||
|
||||
if (!d_is_dir(new_dentry)) {
|
||||
error = -ENOTDIR;
|
||||
if (new_last.name[new_last.len])
|
||||
|
20
fs/nfs/dir.c
20
fs/nfs/dir.c
@ -1532,7 +1532,8 @@ static int nfs_is_exclusive_create(struct inode *dir, unsigned int flags)
|
||||
{
|
||||
if (NFS_PROTO(dir)->version == 2)
|
||||
return 0;
|
||||
return flags & LOOKUP_EXCL;
|
||||
return (flags & (LOOKUP_CREATE | LOOKUP_EXCL)) ==
|
||||
(LOOKUP_CREATE | LOOKUP_EXCL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2421,11 +2422,11 @@ EXPORT_SYMBOL_GPL(nfs_mknod);
|
||||
/*
|
||||
* See comments for nfs_proc_create regarding failed operations.
|
||||
*/
|
||||
int nfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
struct dentry *nfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct iattr attr;
|
||||
int error;
|
||||
struct dentry *ret;
|
||||
|
||||
dfprintk(VFS, "NFS: mkdir(%s/%lu), %pd\n",
|
||||
dir->i_sb->s_id, dir->i_ino, dentry);
|
||||
@ -2434,14 +2435,9 @@ int nfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
attr.ia_mode = mode | S_IFDIR;
|
||||
|
||||
trace_nfs_mkdir_enter(dir, dentry);
|
||||
error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr);
|
||||
trace_nfs_mkdir_exit(dir, dentry, error);
|
||||
if (error != 0)
|
||||
goto out_err;
|
||||
return 0;
|
||||
out_err:
|
||||
d_drop(dentry);
|
||||
return error;
|
||||
ret = NFS_PROTO(dir)->mkdir(dir, dentry, &attr);
|
||||
trace_nfs_mkdir_exit(dir, dentry, PTR_ERR_OR_ZERO(ret));
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_mkdir);
|
||||
|
||||
|
@ -400,8 +400,8 @@ 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);
|
||||
int nfs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *,
|
||||
umode_t);
|
||||
struct dentry *nfs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *,
|
||||
umode_t);
|
||||
int nfs_rmdir(struct inode *, struct dentry *);
|
||||
int nfs_unlink(struct inode *, struct dentry *);
|
||||
int nfs_symlink(struct mnt_idmap *, struct inode *, struct dentry *,
|
||||
|
@ -578,13 +578,13 @@ out:
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
static struct dentry *
|
||||
nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
|
||||
{
|
||||
struct posix_acl *default_acl, *acl;
|
||||
struct nfs3_createdata *data;
|
||||
struct dentry *d_alias;
|
||||
int status = -ENOMEM;
|
||||
struct dentry *ret = ERR_PTR(-ENOMEM);
|
||||
int status;
|
||||
|
||||
dprintk("NFS call mkdir %pd\n", dentry);
|
||||
|
||||
@ -592,8 +592,9 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
|
||||
if (data == NULL)
|
||||
goto out;
|
||||
|
||||
status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
|
||||
if (status)
|
||||
ret = ERR_PTR(posix_acl_create(dir, &sattr->ia_mode,
|
||||
&default_acl, &acl));
|
||||
if (IS_ERR(ret))
|
||||
goto out;
|
||||
|
||||
data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR];
|
||||
@ -602,25 +603,27 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
|
||||
data->arg.mkdir.len = dentry->d_name.len;
|
||||
data->arg.mkdir.sattr = sattr;
|
||||
|
||||
d_alias = nfs3_do_create(dir, dentry, data);
|
||||
status = PTR_ERR_OR_ZERO(d_alias);
|
||||
ret = nfs3_do_create(dir, dentry, data);
|
||||
|
||||
if (status != 0)
|
||||
if (IS_ERR(ret))
|
||||
goto out_release_acls;
|
||||
|
||||
if (d_alias)
|
||||
dentry = d_alias;
|
||||
if (ret)
|
||||
dentry = ret;
|
||||
|
||||
status = nfs3_proc_setacls(d_inode(dentry), acl, default_acl);
|
||||
if (status) {
|
||||
dput(ret);
|
||||
ret = ERR_PTR(status);
|
||||
}
|
||||
|
||||
dput(d_alias);
|
||||
out_release_acls:
|
||||
posix_acl_release(acl);
|
||||
posix_acl_release(default_acl);
|
||||
out:
|
||||
nfs3_free_createdata(data);
|
||||
dprintk("NFS reply mkdir: %d\n", status);
|
||||
return status;
|
||||
dprintk("NFS reply mkdir: %d\n", PTR_ERR_OR_ZERO(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -3154,9 +3154,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
|
||||
if (d_really_is_negative(dentry)) {
|
||||
struct dentry *alias;
|
||||
d_drop(dentry);
|
||||
alias = d_exact_alias(dentry, state->inode);
|
||||
if (!alias)
|
||||
alias = d_splice_alias(igrab(state->inode), dentry);
|
||||
alias = d_splice_alias(igrab(state->inode), dentry);
|
||||
/* d_splice_alias() can't fail here - it's a non-directory */
|
||||
if (alias) {
|
||||
dput(ctx->dentry);
|
||||
@ -5139,9 +5137,6 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_
|
||||
&data->arg.seq_args, &data->res.seq_res, 1);
|
||||
if (status == 0) {
|
||||
spin_lock(&dir->i_lock);
|
||||
/* Creating a directory bumps nlink in the parent */
|
||||
if (data->arg.ftype == NF4DIR)
|
||||
nfs4_inc_nlink_locked(dir);
|
||||
nfs4_update_changeattr_locked(dir, &data->res.dir_cinfo,
|
||||
data->res.fattr->time_start,
|
||||
NFS_INO_INVALID_DATA);
|
||||
@ -5151,6 +5146,25 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_
|
||||
return status;
|
||||
}
|
||||
|
||||
static struct dentry *nfs4_do_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
struct nfs4_createdata *data)
|
||||
{
|
||||
int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg,
|
||||
&data->arg.seq_args, &data->res.seq_res, 1);
|
||||
|
||||
if (status)
|
||||
return ERR_PTR(status);
|
||||
|
||||
spin_lock(&dir->i_lock);
|
||||
/* Creating a directory bumps nlink in the parent */
|
||||
nfs4_inc_nlink_locked(dir);
|
||||
nfs4_update_changeattr_locked(dir, &data->res.dir_cinfo,
|
||||
data->res.fattr->time_start,
|
||||
NFS_INO_INVALID_DATA);
|
||||
spin_unlock(&dir->i_lock);
|
||||
return nfs_add_or_obtain(dentry, data->res.fh, data->res.fattr);
|
||||
}
|
||||
|
||||
static void nfs4_free_createdata(struct nfs4_createdata *data)
|
||||
{
|
||||
nfs4_label_free(data->fattr.label);
|
||||
@ -5207,32 +5221,34 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
struct iattr *sattr, struct nfs4_label *label)
|
||||
static struct dentry *_nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
struct iattr *sattr,
|
||||
struct nfs4_label *label)
|
||||
{
|
||||
struct nfs4_createdata *data;
|
||||
int status = -ENOMEM;
|
||||
struct dentry *ret = ERR_PTR(-ENOMEM);
|
||||
|
||||
data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4DIR);
|
||||
if (data == NULL)
|
||||
goto out;
|
||||
|
||||
data->arg.label = label;
|
||||
status = nfs4_do_create(dir, dentry, data);
|
||||
ret = nfs4_do_mkdir(dir, dentry, data);
|
||||
|
||||
nfs4_free_createdata(data);
|
||||
out:
|
||||
return status;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
struct iattr *sattr)
|
||||
static struct dentry *nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
struct iattr *sattr)
|
||||
{
|
||||
struct nfs_server *server = NFS_SERVER(dir);
|
||||
struct nfs4_exception exception = {
|
||||
.interruptible = true,
|
||||
};
|
||||
struct nfs4_label l, *label;
|
||||
struct dentry *alias;
|
||||
int err;
|
||||
|
||||
label = nfs4_label_init_security(dir, dentry, sattr, &l);
|
||||
@ -5240,14 +5256,15 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
|
||||
sattr->ia_mode &= ~current_umask();
|
||||
do {
|
||||
err = _nfs4_proc_mkdir(dir, dentry, sattr, label);
|
||||
alias = _nfs4_proc_mkdir(dir, dentry, sattr, label);
|
||||
err = PTR_ERR_OR_ZERO(alias);
|
||||
trace_nfs4_mkdir(dir, &dentry->d_name, err);
|
||||
err = nfs4_handle_exception(NFS_SERVER(dir), err,
|
||||
&exception);
|
||||
} while (exception.retry);
|
||||
nfs4_label_release_security(label);
|
||||
|
||||
return err;
|
||||
return alias;
|
||||
}
|
||||
|
||||
static int _nfs4_proc_readdir(struct nfs_readdir_arg *nr_arg,
|
||||
|
@ -446,13 +446,14 @@ out:
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
static struct dentry *
|
||||
nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
|
||||
{
|
||||
struct nfs_createdata *data;
|
||||
struct rpc_message msg = {
|
||||
.rpc_proc = &nfs_procedures[NFSPROC_MKDIR],
|
||||
};
|
||||
struct dentry *alias = NULL;
|
||||
int status = -ENOMEM;
|
||||
|
||||
dprintk("NFS call mkdir %pd\n", dentry);
|
||||
@ -464,12 +465,15 @@ nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
|
||||
|
||||
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
|
||||
nfs_mark_for_revalidate(dir);
|
||||
if (status == 0)
|
||||
status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
|
||||
if (status == 0) {
|
||||
alias = nfs_add_or_obtain(dentry, data->res.fh, data->res.fattr);
|
||||
status = PTR_ERR_OR_ZERO(alias);
|
||||
} else
|
||||
alias = ERR_PTR(status);
|
||||
nfs_free_createdata(data);
|
||||
out:
|
||||
dprintk("NFS reply mkdir: %d\n", status);
|
||||
return status;
|
||||
return alias;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -233,9 +233,12 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
|
||||
* as well be forgiving and just succeed silently.
|
||||
*/
|
||||
goto out_put;
|
||||
status = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), dentry, S_IRWXU);
|
||||
dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), dentry, S_IRWXU);
|
||||
if (IS_ERR(dentry))
|
||||
status = PTR_ERR(dentry);
|
||||
out_put:
|
||||
dput(dentry);
|
||||
if (!status)
|
||||
dput(dentry);
|
||||
out_unlock:
|
||||
inode_unlock(d_inode(dir));
|
||||
if (status == 0) {
|
||||
|
@ -1461,7 +1461,7 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||
struct inode *dirp;
|
||||
struct iattr *iap = attrs->na_iattr;
|
||||
__be32 err;
|
||||
int host_err;
|
||||
int host_err = 0;
|
||||
|
||||
dentry = fhp->fh_dentry;
|
||||
dirp = d_inode(dentry);
|
||||
@ -1488,28 +1488,15 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||
nfsd_check_ignore_resizing(iap);
|
||||
break;
|
||||
case S_IFDIR:
|
||||
host_err = vfs_mkdir(&nop_mnt_idmap, dirp, dchild, iap->ia_mode);
|
||||
if (!host_err && unlikely(d_unhashed(dchild))) {
|
||||
struct dentry *d;
|
||||
d = lookup_one_len(dchild->d_name.name,
|
||||
dchild->d_parent,
|
||||
dchild->d_name.len);
|
||||
if (IS_ERR(d)) {
|
||||
host_err = PTR_ERR(d);
|
||||
break;
|
||||
}
|
||||
if (unlikely(d_is_negative(d))) {
|
||||
dput(d);
|
||||
err = nfserr_serverfault;
|
||||
goto out;
|
||||
}
|
||||
dchild = vfs_mkdir(&nop_mnt_idmap, dirp, dchild, iap->ia_mode);
|
||||
if (IS_ERR(dchild)) {
|
||||
host_err = PTR_ERR(dchild);
|
||||
} else if (d_is_negative(dchild)) {
|
||||
err = nfserr_serverfault;
|
||||
goto out;
|
||||
} else if (unlikely(dchild != resfhp->fh_dentry)) {
|
||||
dput(resfhp->fh_dentry);
|
||||
resfhp->fh_dentry = dget(d);
|
||||
err = fh_update(resfhp);
|
||||
dput(dchild);
|
||||
dchild = d;
|
||||
if (err)
|
||||
goto out;
|
||||
resfhp->fh_dentry = dget(dchild);
|
||||
}
|
||||
break;
|
||||
case S_IFCHR:
|
||||
@ -1530,7 +1517,8 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||
err = nfsd_create_setattr(rqstp, fhp, resfhp, attrs);
|
||||
|
||||
out:
|
||||
dput(dchild);
|
||||
if (!IS_ERR(dchild))
|
||||
dput(dchild);
|
||||
return err;
|
||||
|
||||
out_nfserr:
|
||||
|
@ -218,8 +218,8 @@ static int nilfs_link(struct dentry *old_dentry, struct inode *dir,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nilfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *nilfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct nilfs_transaction_info ti;
|
||||
@ -227,7 +227,7 @@ static int nilfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
||||
err = nilfs_transaction_begin(dir->i_sb, &ti, 1);
|
||||
if (err)
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
|
||||
inc_nlink(dir);
|
||||
|
||||
@ -258,7 +258,7 @@ out:
|
||||
else
|
||||
nilfs_transaction_abort(dir->i_sb);
|
||||
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
|
||||
out_fail:
|
||||
drop_nlink(inode);
|
||||
|
@ -201,11 +201,11 @@ static int ntfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
|
||||
/*
|
||||
* ntfs_mkdir- inode_operations::mkdir
|
||||
*/
|
||||
static int ntfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *ntfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return ntfs_create_inode(idmap, dir, dentry, NULL, S_IFDIR | mode, 0,
|
||||
NULL, 0, NULL);
|
||||
return ERR_PTR(ntfs_create_inode(idmap, dir, dentry, NULL, S_IFDIR | mode, 0,
|
||||
NULL, 0, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -402,10 +402,10 @@ static struct inode *dlmfs_get_inode(struct inode *parent,
|
||||
* File creation. Allocate an inode, and we're done..
|
||||
*/
|
||||
/* SMP-safe */
|
||||
static int dlmfs_mkdir(struct mnt_idmap * idmap,
|
||||
struct inode * dir,
|
||||
struct dentry * dentry,
|
||||
umode_t mode)
|
||||
static struct dentry *dlmfs_mkdir(struct mnt_idmap * idmap,
|
||||
struct inode * dir,
|
||||
struct dentry * dentry,
|
||||
umode_t mode)
|
||||
{
|
||||
int status;
|
||||
struct inode *inode = NULL;
|
||||
@ -448,7 +448,7 @@ static int dlmfs_mkdir(struct mnt_idmap * idmap,
|
||||
bail:
|
||||
if (status < 0)
|
||||
iput(inode);
|
||||
return status;
|
||||
return ERR_PTR(status);
|
||||
}
|
||||
|
||||
static int dlmfs_create(struct mnt_idmap *idmap,
|
||||
|
@ -644,10 +644,10 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
|
||||
suballoc_loc, suballoc_bit);
|
||||
}
|
||||
|
||||
static int ocfs2_mkdir(struct mnt_idmap *idmap,
|
||||
struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
umode_t mode)
|
||||
static struct dentry *ocfs2_mkdir(struct mnt_idmap *idmap,
|
||||
struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
umode_t mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -657,7 +657,7 @@ static int ocfs2_mkdir(struct mnt_idmap *idmap,
|
||||
if (ret)
|
||||
mlog_errno(ret);
|
||||
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int ocfs2_create(struct mnt_idmap *idmap,
|
||||
|
@ -279,10 +279,10 @@ out_free_inode:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int omfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *omfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return omfs_add_node(dir, dentry, mode | S_IFDIR);
|
||||
return ERR_PTR(omfs_add_node(dir, dentry, mode | S_IFDIR));
|
||||
}
|
||||
|
||||
static int omfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
@ -300,8 +300,8 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int orangefs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *orangefs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct orangefs_inode_s *parent = ORANGEFS_I(dir);
|
||||
struct orangefs_kernel_op_s *new_op;
|
||||
@ -312,7 +312,7 @@ static int orangefs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
||||
new_op = op_alloc(ORANGEFS_VFS_OP_MKDIR);
|
||||
if (!new_op)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
new_op->upcall.req.mkdir.parent_refn = parent->refn;
|
||||
|
||||
@ -366,7 +366,7 @@ static int orangefs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
__orangefs_setattr(dir, &iattr);
|
||||
out:
|
||||
op_release(new_op);
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int orangefs_rename(struct mnt_idmap *idmap,
|
||||
|
@ -138,37 +138,6 @@ kill_whiteout:
|
||||
goto out;
|
||||
}
|
||||
|
||||
int ovl_mkdir_real(struct ovl_fs *ofs, struct inode *dir,
|
||||
struct dentry **newdentry, umode_t mode)
|
||||
{
|
||||
int err;
|
||||
struct dentry *d, *dentry = *newdentry;
|
||||
|
||||
err = ovl_do_mkdir(ofs, dir, dentry, mode);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (likely(!d_unhashed(dentry)))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* vfs_mkdir() may succeed and leave the dentry passed
|
||||
* to it unhashed and negative. If that happens, try to
|
||||
* lookup a new hashed and positive dentry.
|
||||
*/
|
||||
d = ovl_lookup_upper(ofs, dentry->d_name.name, dentry->d_parent,
|
||||
dentry->d_name.len);
|
||||
if (IS_ERR(d)) {
|
||||
pr_warn("failed lookup after mkdir (%pd2, err=%i).\n",
|
||||
dentry, err);
|
||||
return PTR_ERR(d);
|
||||
}
|
||||
dput(dentry);
|
||||
*newdentry = d;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dentry *ovl_create_real(struct ovl_fs *ofs, struct inode *dir,
|
||||
struct dentry *newdentry, struct ovl_cattr *attr)
|
||||
{
|
||||
@ -191,7 +160,8 @@ struct dentry *ovl_create_real(struct ovl_fs *ofs, struct inode *dir,
|
||||
|
||||
case S_IFDIR:
|
||||
/* mkdir is special... */
|
||||
err = ovl_mkdir_real(ofs, dir, &newdentry, attr->mode);
|
||||
newdentry = ovl_do_mkdir(ofs, dir, newdentry, attr->mode);
|
||||
err = PTR_ERR_OR_ZERO(newdentry);
|
||||
break;
|
||||
|
||||
case S_IFCHR:
|
||||
@ -219,7 +189,8 @@ struct dentry *ovl_create_real(struct ovl_fs *ofs, struct inode *dir,
|
||||
}
|
||||
out:
|
||||
if (err) {
|
||||
dput(newdentry);
|
||||
if (!IS_ERR(newdentry))
|
||||
dput(newdentry);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
return newdentry;
|
||||
@ -282,7 +253,8 @@ static int ovl_instantiate(struct dentry *dentry, struct inode *inode,
|
||||
* XXX: if we ever use ovl_obtain_alias() to decode directory
|
||||
* file handles, need to use ovl_get_inode_locked() and
|
||||
* d_instantiate_new() here to prevent from creating two
|
||||
* hashed directory inode aliases.
|
||||
* hashed directory inode aliases. We then need to return
|
||||
* the obtained alias to ovl_mkdir().
|
||||
*/
|
||||
inode = ovl_get_inode(dentry->d_sb, &oip);
|
||||
if (IS_ERR(inode))
|
||||
@ -687,10 +659,10 @@ static int ovl_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
return ovl_create_object(dentry, (mode & 07777) | S_IFREG, 0, NULL);
|
||||
}
|
||||
|
||||
static int ovl_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *ovl_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return ovl_create_object(dentry, (mode & 07777) | S_IFDIR, 0, NULL);
|
||||
return ERR_PTR(ovl_create_object(dentry, (mode & 07777) | S_IFDIR, 0, NULL));
|
||||
}
|
||||
|
||||
static int ovl_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
@ -241,13 +241,14 @@ static inline int ovl_do_create(struct ovl_fs *ofs,
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline int ovl_do_mkdir(struct ovl_fs *ofs,
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
umode_t mode)
|
||||
static inline struct dentry *ovl_do_mkdir(struct ovl_fs *ofs,
|
||||
struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
umode_t mode)
|
||||
{
|
||||
int err = vfs_mkdir(ovl_upper_mnt_idmap(ofs), dir, dentry, mode);
|
||||
pr_debug("mkdir(%pd2, 0%o) = %i\n", dentry, mode, err);
|
||||
return err;
|
||||
dentry = vfs_mkdir(ovl_upper_mnt_idmap(ofs), dir, dentry, mode);
|
||||
pr_debug("mkdir(%pd2, 0%o) = %i\n", dentry, mode, PTR_ERR_OR_ZERO(dentry));
|
||||
return dentry;
|
||||
}
|
||||
|
||||
static inline int ovl_do_mknod(struct ovl_fs *ofs,
|
||||
@ -838,8 +839,6 @@ struct ovl_cattr {
|
||||
|
||||
#define OVL_CATTR(m) (&(struct ovl_cattr) { .mode = (m) })
|
||||
|
||||
int ovl_mkdir_real(struct ovl_fs *ofs, struct inode *dir,
|
||||
struct dentry **newdentry, umode_t mode);
|
||||
struct dentry *ovl_create_real(struct ovl_fs *ofs,
|
||||
struct inode *dir, struct dentry *newdentry,
|
||||
struct ovl_cattr *attr);
|
||||
|
@ -327,9 +327,10 @@ retry:
|
||||
goto retry;
|
||||
}
|
||||
|
||||
err = ovl_mkdir_real(ofs, dir, &work, attr.ia_mode);
|
||||
if (err)
|
||||
goto out_dput;
|
||||
work = ovl_do_mkdir(ofs, dir, work, attr.ia_mode);
|
||||
err = PTR_ERR(work);
|
||||
if (IS_ERR(work))
|
||||
goto out_err;
|
||||
|
||||
/* Weird filesystem returning with hashed negative (kernfs)? */
|
||||
err = -EINVAL;
|
||||
|
@ -119,13 +119,13 @@ out:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int ramfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *ramfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
int retval = ramfs_mknod(&nop_mnt_idmap, dir, dentry, mode | S_IFDIR, 0);
|
||||
if (!retval)
|
||||
inc_nlink(dir);
|
||||
return retval;
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
|
||||
static int ramfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
@ -59,8 +59,8 @@ extern int cifs_unlink(struct inode *dir, struct dentry *dentry);
|
||||
extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
|
||||
extern int cifs_mknod(struct mnt_idmap *, struct inode *, struct dentry *,
|
||||
umode_t, dev_t);
|
||||
extern int cifs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *,
|
||||
umode_t);
|
||||
extern struct dentry *cifs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *,
|
||||
umode_t);
|
||||
extern int cifs_rmdir(struct inode *, struct dentry *);
|
||||
extern int cifs_rename2(struct mnt_idmap *, struct inode *,
|
||||
struct dentry *, struct inode *, struct dentry *,
|
||||
|
@ -2207,8 +2207,8 @@ posix_mkdir_get_info:
|
||||
}
|
||||
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
|
||||
|
||||
int cifs_mkdir(struct mnt_idmap *idmap, struct inode *inode,
|
||||
struct dentry *direntry, umode_t mode)
|
||||
struct dentry *cifs_mkdir(struct mnt_idmap *idmap, struct inode *inode,
|
||||
struct dentry *direntry, umode_t mode)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned int xid;
|
||||
@ -2224,10 +2224,10 @@ int cifs_mkdir(struct mnt_idmap *idmap, struct inode *inode,
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
if (unlikely(cifs_forced_shutdown(cifs_sb)))
|
||||
return -EIO;
|
||||
return ERR_PTR(-EIO);
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
return ERR_CAST(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
xid = get_xid();
|
||||
@ -2283,7 +2283,7 @@ mkdir_out:
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||
|
@ -113,11 +113,6 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
|
||||
if (IS_ERR(d))
|
||||
goto err_out;
|
||||
|
||||
if (d_is_negative(d)) {
|
||||
dput(d);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
path->dentry = d;
|
||||
path->mnt = mntget(parent_path->mnt);
|
||||
|
||||
@ -211,8 +206,8 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
|
||||
{
|
||||
struct mnt_idmap *idmap;
|
||||
struct path path;
|
||||
struct dentry *dentry;
|
||||
int err;
|
||||
struct dentry *dentry, *d;
|
||||
int err = 0;
|
||||
|
||||
dentry = ksmbd_vfs_kern_path_create(work, name,
|
||||
LOOKUP_NO_SYMLINKS | LOOKUP_DIRECTORY,
|
||||
@ -227,27 +222,15 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
|
||||
|
||||
idmap = mnt_idmap(path.mnt);
|
||||
mode |= S_IFDIR;
|
||||
err = vfs_mkdir(idmap, d_inode(path.dentry), dentry, mode);
|
||||
if (!err && d_unhashed(dentry)) {
|
||||
struct dentry *d;
|
||||
d = dentry;
|
||||
dentry = vfs_mkdir(idmap, d_inode(path.dentry), dentry, mode);
|
||||
if (IS_ERR(dentry))
|
||||
err = PTR_ERR(dentry);
|
||||
else if (d_is_negative(dentry))
|
||||
err = -ENOENT;
|
||||
if (!err && dentry != d)
|
||||
ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), d_inode(dentry));
|
||||
|
||||
d = lookup_one(idmap, dentry->d_name.name, dentry->d_parent,
|
||||
dentry->d_name.len);
|
||||
if (IS_ERR(d)) {
|
||||
err = PTR_ERR(d);
|
||||
goto out_err;
|
||||
}
|
||||
if (unlikely(d_is_negative(d))) {
|
||||
dput(d);
|
||||
err = -ENOENT;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), d_inode(d));
|
||||
dput(d);
|
||||
}
|
||||
|
||||
out_err:
|
||||
done_path_create(&path, dentry);
|
||||
if (err)
|
||||
pr_err("mkdir(%s): creation failed (err:%d)\n", name, err);
|
||||
@ -693,6 +676,7 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
|
||||
struct ksmbd_file *parent_fp;
|
||||
int new_type;
|
||||
int err, lookup_flags = LOOKUP_NO_SYMLINKS;
|
||||
int target_lookup_flags = LOOKUP_RENAME_TARGET;
|
||||
|
||||
if (ksmbd_override_fsids(work))
|
||||
return -ENOMEM;
|
||||
@ -703,6 +687,14 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
|
||||
goto revert_fsids;
|
||||
}
|
||||
|
||||
/*
|
||||
* explicitly handle file overwrite case, for compatibility with
|
||||
* filesystems that may not support rename flags (e.g: fuse)
|
||||
*/
|
||||
if (flags & RENAME_NOREPLACE)
|
||||
target_lookup_flags |= LOOKUP_EXCL;
|
||||
flags &= ~(RENAME_NOREPLACE);
|
||||
|
||||
retry:
|
||||
err = vfs_path_parent_lookup(to, lookup_flags | LOOKUP_BENEATH,
|
||||
&new_path, &new_last, &new_type,
|
||||
@ -743,7 +735,7 @@ retry:
|
||||
}
|
||||
|
||||
new_dentry = lookup_one_qstr_excl(&new_last, new_path.dentry,
|
||||
lookup_flags | LOOKUP_RENAME_TARGET);
|
||||
lookup_flags | target_lookup_flags);
|
||||
if (IS_ERR(new_dentry)) {
|
||||
err = PTR_ERR(new_dentry);
|
||||
goto out3;
|
||||
@ -754,16 +746,6 @@ retry:
|
||||
goto out4;
|
||||
}
|
||||
|
||||
/*
|
||||
* explicitly handle file overwrite case, for compatibility with
|
||||
* filesystems that may not support rename flags (e.g: fuse)
|
||||
*/
|
||||
if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry)) {
|
||||
err = -EEXIST;
|
||||
goto out4;
|
||||
}
|
||||
flags &= ~(RENAME_NOREPLACE);
|
||||
|
||||
if (old_child == trap) {
|
||||
err = -EINVAL;
|
||||
goto out4;
|
||||
|
@ -110,8 +110,8 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir,
|
||||
return add_nondir(dentry, inode);
|
||||
}
|
||||
|
||||
static int sysv_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *sysv_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode * inode;
|
||||
int err;
|
||||
@ -137,7 +137,7 @@ static int sysv_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
||||
d_instantiate(dentry, inode);
|
||||
out:
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
|
||||
out_fail:
|
||||
inode_dec_link_count(inode);
|
||||
|
@ -109,9 +109,9 @@ static char *get_dname(struct dentry *dentry)
|
||||
return name;
|
||||
}
|
||||
|
||||
static int tracefs_syscall_mkdir(struct mnt_idmap *idmap,
|
||||
struct inode *inode, struct dentry *dentry,
|
||||
umode_t mode)
|
||||
static struct dentry *tracefs_syscall_mkdir(struct mnt_idmap *idmap,
|
||||
struct inode *inode, struct dentry *dentry,
|
||||
umode_t mode)
|
||||
{
|
||||
struct tracefs_inode *ti;
|
||||
char *name;
|
||||
@ -119,7 +119,7 @@ static int tracefs_syscall_mkdir(struct mnt_idmap *idmap,
|
||||
|
||||
name = get_dname(dentry);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/*
|
||||
* This is a new directory that does not take the default of
|
||||
@ -141,7 +141,7 @@ static int tracefs_syscall_mkdir(struct mnt_idmap *idmap,
|
||||
|
||||
kfree(name);
|
||||
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int tracefs_syscall_rmdir(struct inode *inode, struct dentry *dentry)
|
||||
|
@ -1002,8 +1002,8 @@ out_fname:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct ubifs_inode *dir_ui = ubifs_inode(dir);
|
||||
@ -1023,7 +1023,7 @@ static int ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
||||
err = ubifs_budget_space(c, &req);
|
||||
if (err)
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
|
||||
err = ubifs_prepare_create(dir, dentry, &nm);
|
||||
if (err)
|
||||
@ -1060,7 +1060,7 @@ static int ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
ubifs_release_budget(c, &req);
|
||||
d_instantiate(dentry, inode);
|
||||
fscrypt_free_filename(&nm);
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
out_cancel:
|
||||
dir->i_size -= sz_change;
|
||||
@ -1074,7 +1074,7 @@ out_fname:
|
||||
fscrypt_free_filename(&nm);
|
||||
out_budg:
|
||||
ubifs_release_budget(c, &req);
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static int ubifs_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
@ -419,8 +419,8 @@ static int udf_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||
return udf_add_nondir(dentry, inode);
|
||||
}
|
||||
|
||||
static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct udf_fileident_iter iter;
|
||||
@ -430,7 +430,7 @@ static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
||||
inode = udf_new_inode(dir, S_IFDIR | mode);
|
||||
if (IS_ERR(inode))
|
||||
return PTR_ERR(inode);
|
||||
return ERR_CAST(inode);
|
||||
|
||||
iinfo = UDF_I(inode);
|
||||
inode->i_op = &udf_dir_inode_operations;
|
||||
@ -439,7 +439,7 @@ static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
if (err) {
|
||||
clear_nlink(inode);
|
||||
discard_new_inode(inode);
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
set_nlink(inode, 2);
|
||||
iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
|
||||
@ -456,7 +456,7 @@ static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
if (err) {
|
||||
clear_nlink(inode);
|
||||
discard_new_inode(inode);
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
|
||||
iter.fi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
|
||||
@ -471,7 +471,7 @@ static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
mark_inode_dirty(dir);
|
||||
d_instantiate_new(dentry, inode);
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int empty_dir(struct inode *dir)
|
||||
|
@ -166,8 +166,8 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
|
||||
return error;
|
||||
}
|
||||
|
||||
static int ufs_mkdir(struct mnt_idmap * idmap, struct inode * dir,
|
||||
struct dentry * dentry, umode_t mode)
|
||||
static struct dentry *ufs_mkdir(struct mnt_idmap * idmap, struct inode * dir,
|
||||
struct dentry * dentry, umode_t mode)
|
||||
{
|
||||
struct inode * inode;
|
||||
int err;
|
||||
@ -194,7 +194,7 @@ static int ufs_mkdir(struct mnt_idmap * idmap, struct inode * dir,
|
||||
goto out_fail;
|
||||
|
||||
d_instantiate_new(dentry, inode);
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
out_fail:
|
||||
inode_dec_link_count(inode);
|
||||
@ -202,7 +202,7 @@ out_fail:
|
||||
discard_new_inode(inode);
|
||||
out_dir:
|
||||
inode_dec_link_count(dir);
|
||||
return err;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static int ufs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
|
@ -303,11 +303,11 @@ static int vboxsf_dir_mkfile(struct mnt_idmap *idmap,
|
||||
return vboxsf_dir_create(parent, dentry, mode, false, excl, NULL);
|
||||
}
|
||||
|
||||
static int vboxsf_dir_mkdir(struct mnt_idmap *idmap,
|
||||
struct inode *parent, struct dentry *dentry,
|
||||
umode_t mode)
|
||||
static struct dentry *vboxsf_dir_mkdir(struct mnt_idmap *idmap,
|
||||
struct inode *parent, struct dentry *dentry,
|
||||
umode_t mode)
|
||||
{
|
||||
return vboxsf_dir_create(parent, dentry, mode, true, true, NULL);
|
||||
return ERR_PTR(vboxsf_dir_create(parent, dentry, mode, true, true, NULL));
|
||||
}
|
||||
|
||||
static int vboxsf_dir_atomic_open(struct inode *parent, struct dentry *dentry,
|
||||
|
@ -167,10 +167,11 @@ xrep_orphanage_create(
|
||||
* directory to control access to a file we put in here.
|
||||
*/
|
||||
if (d_really_is_negative(orphanage_dentry)) {
|
||||
error = vfs_mkdir(&nop_mnt_idmap, root_inode, orphanage_dentry,
|
||||
0750);
|
||||
if (error)
|
||||
goto out_dput_orphanage;
|
||||
orphanage_dentry = vfs_mkdir(&nop_mnt_idmap, root_inode,
|
||||
orphanage_dentry, 0750);
|
||||
error = PTR_ERR(orphanage_dentry);
|
||||
if (IS_ERR(orphanage_dentry))
|
||||
goto out_unlock_root;
|
||||
}
|
||||
|
||||
/* Not a directory? Bail out. */
|
||||
|
@ -298,14 +298,14 @@ xfs_vn_create(
|
||||
return xfs_generic_create(idmap, dir, dentry, mode, 0, NULL);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
STATIC struct dentry *
|
||||
xfs_vn_mkdir(
|
||||
struct mnt_idmap *idmap,
|
||||
struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
umode_t mode)
|
||||
{
|
||||
return xfs_generic_create(idmap, dir, dentry, mode | S_IFDIR, 0, NULL);
|
||||
return ERR_PTR(xfs_generic_create(idmap, dir, dentry, mode | S_IFDIR, 0, NULL));
|
||||
}
|
||||
|
||||
STATIC struct dentry *
|
||||
|
@ -203,34 +203,34 @@ struct dentry_operations {
|
||||
#define DCACHE_NFSFS_RENAMED BIT(12)
|
||||
/* this dentry has been "silly renamed" and has to be deleted on the last
|
||||
* dput() */
|
||||
#define DCACHE_FSNOTIFY_PARENT_WATCHED BIT(14)
|
||||
#define DCACHE_FSNOTIFY_PARENT_WATCHED BIT(13)
|
||||
/* Parent inode is watched by some fsnotify listener */
|
||||
|
||||
#define DCACHE_DENTRY_KILLED BIT(15)
|
||||
#define DCACHE_DENTRY_KILLED BIT(14)
|
||||
|
||||
#define DCACHE_MOUNTED BIT(16) /* is a mountpoint */
|
||||
#define DCACHE_NEED_AUTOMOUNT BIT(17) /* handle automount on this dir */
|
||||
#define DCACHE_MANAGE_TRANSIT BIT(18) /* manage transit from this dirent */
|
||||
#define DCACHE_MOUNTED BIT(15) /* is a mountpoint */
|
||||
#define DCACHE_NEED_AUTOMOUNT BIT(16) /* handle automount on this dir */
|
||||
#define DCACHE_MANAGE_TRANSIT BIT(17) /* manage transit from this dirent */
|
||||
#define DCACHE_MANAGED_DENTRY \
|
||||
(DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
|
||||
|
||||
#define DCACHE_LRU_LIST BIT(19)
|
||||
#define DCACHE_LRU_LIST BIT(18)
|
||||
|
||||
#define DCACHE_ENTRY_TYPE (7 << 20) /* bits 20..22 are for storing type: */
|
||||
#define DCACHE_MISS_TYPE (0 << 20) /* Negative dentry */
|
||||
#define DCACHE_WHITEOUT_TYPE (1 << 20) /* Whiteout dentry (stop pathwalk) */
|
||||
#define DCACHE_DIRECTORY_TYPE (2 << 20) /* Normal directory */
|
||||
#define DCACHE_AUTODIR_TYPE (3 << 20) /* Lookupless directory (presumed automount) */
|
||||
#define DCACHE_REGULAR_TYPE (4 << 20) /* Regular file type */
|
||||
#define DCACHE_SPECIAL_TYPE (5 << 20) /* Other file type */
|
||||
#define DCACHE_SYMLINK_TYPE (6 << 20) /* Symlink */
|
||||
#define DCACHE_ENTRY_TYPE (7 << 19) /* bits 19..21 are for storing type: */
|
||||
#define DCACHE_MISS_TYPE (0 << 19) /* Negative dentry */
|
||||
#define DCACHE_WHITEOUT_TYPE (1 << 19) /* Whiteout dentry (stop pathwalk) */
|
||||
#define DCACHE_DIRECTORY_TYPE (2 << 19) /* Normal directory */
|
||||
#define DCACHE_AUTODIR_TYPE (3 << 19) /* Lookupless directory (presumed automount) */
|
||||
#define DCACHE_REGULAR_TYPE (4 << 19) /* Regular file type */
|
||||
#define DCACHE_SPECIAL_TYPE (5 << 19) /* Other file type */
|
||||
#define DCACHE_SYMLINK_TYPE (6 << 19) /* Symlink */
|
||||
|
||||
#define DCACHE_NOKEY_NAME BIT(25) /* Encrypted name encoded without key */
|
||||
#define DCACHE_OP_REAL BIT(26)
|
||||
#define DCACHE_NOKEY_NAME BIT(22) /* Encrypted name encoded without key */
|
||||
#define DCACHE_OP_REAL BIT(23)
|
||||
|
||||
#define DCACHE_PAR_LOOKUP BIT(28) /* being looked up (with parent locked shared) */
|
||||
#define DCACHE_DENTRY_CURSOR BIT(29)
|
||||
#define DCACHE_NORCU BIT(30) /* No RCU delay for freeing */
|
||||
#define DCACHE_PAR_LOOKUP BIT(24) /* being looked up (with parent locked shared) */
|
||||
#define DCACHE_DENTRY_CURSOR BIT(25)
|
||||
#define DCACHE_NORCU BIT(26) /* No RCU delay for freeing */
|
||||
|
||||
extern seqlock_t rename_lock;
|
||||
|
||||
@ -253,7 +253,6 @@ extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
|
||||
extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *);
|
||||
extern bool d_same_name(const struct dentry *dentry, const struct dentry *parent,
|
||||
const struct qstr *name);
|
||||
extern struct dentry * d_exact_alias(struct dentry *, struct inode *);
|
||||
extern struct dentry *d_find_any_alias(struct inode *inode);
|
||||
extern struct dentry * d_obtain_alias(struct inode *);
|
||||
extern struct dentry * d_obtain_root(struct inode *);
|
||||
|
@ -1971,8 +1971,8 @@ bool inode_owner_or_capable(struct mnt_idmap *idmap,
|
||||
*/
|
||||
int vfs_create(struct mnt_idmap *, struct inode *,
|
||||
struct dentry *, umode_t, bool);
|
||||
int vfs_mkdir(struct mnt_idmap *, struct inode *,
|
||||
struct dentry *, umode_t);
|
||||
struct dentry *vfs_mkdir(struct mnt_idmap *, struct inode *,
|
||||
struct dentry *, umode_t);
|
||||
int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *,
|
||||
umode_t, dev_t);
|
||||
int vfs_symlink(struct mnt_idmap *, struct inode *,
|
||||
@ -2201,8 +2201,8 @@ struct inode_operations {
|
||||
int (*unlink) (struct inode *,struct dentry *);
|
||||
int (*symlink) (struct mnt_idmap *, struct inode *,struct dentry *,
|
||||
const char *);
|
||||
int (*mkdir) (struct mnt_idmap *, struct inode *,struct dentry *,
|
||||
umode_t);
|
||||
struct dentry *(*mkdir) (struct mnt_idmap *, struct inode *,
|
||||
struct dentry *, umode_t);
|
||||
int (*rmdir) (struct inode *,struct dentry *);
|
||||
int (*mknod) (struct mnt_idmap *, struct inode *,struct dentry *,
|
||||
umode_t,dev_t);
|
||||
|
@ -18,35 +18,36 @@ enum { MAX_NESTED_LINKS = 8 };
|
||||
enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT};
|
||||
|
||||
/* pathwalk mode */
|
||||
#define LOOKUP_FOLLOW 0x0001 /* follow links at the end */
|
||||
#define LOOKUP_DIRECTORY 0x0002 /* require a directory */
|
||||
#define LOOKUP_AUTOMOUNT 0x0004 /* force terminal automount */
|
||||
#define LOOKUP_EMPTY 0x4000 /* accept empty path [user_... only] */
|
||||
#define LOOKUP_DOWN 0x8000 /* follow mounts in the starting point */
|
||||
#define LOOKUP_MOUNTPOINT 0x0080 /* follow mounts in the end */
|
||||
|
||||
#define LOOKUP_REVAL 0x0020 /* tell ->d_revalidate() to trust no cache */
|
||||
#define LOOKUP_RCU 0x0040 /* RCU pathwalk mode; semi-internal */
|
||||
#define LOOKUP_FOLLOW BIT(0) /* follow links at the end */
|
||||
#define LOOKUP_DIRECTORY BIT(1) /* require a directory */
|
||||
#define LOOKUP_AUTOMOUNT BIT(2) /* force terminal automount */
|
||||
#define LOOKUP_EMPTY BIT(3) /* accept empty path [user_... only] */
|
||||
#define LOOKUP_LINKAT_EMPTY BIT(4) /* Linkat request with empty path. */
|
||||
#define LOOKUP_DOWN BIT(5) /* follow mounts in the starting point */
|
||||
#define LOOKUP_MOUNTPOINT BIT(6) /* follow mounts in the end */
|
||||
#define LOOKUP_REVAL BIT(7) /* tell ->d_revalidate() to trust no cache */
|
||||
#define LOOKUP_RCU BIT(8) /* RCU pathwalk mode; semi-internal */
|
||||
#define LOOKUP_CACHED BIT(9) /* Only do cached lookup */
|
||||
#define LOOKUP_PARENT BIT(10) /* Looking up final parent in path */
|
||||
/* 5 spare bits for pathwalk */
|
||||
|
||||
/* These tell filesystem methods that we are dealing with the final component... */
|
||||
#define LOOKUP_OPEN 0x0100 /* ... in open */
|
||||
#define LOOKUP_CREATE 0x0200 /* ... in object creation */
|
||||
#define LOOKUP_EXCL 0x0400 /* ... in exclusive creation */
|
||||
#define LOOKUP_RENAME_TARGET 0x0800 /* ... in destination of rename() */
|
||||
#define LOOKUP_OPEN BIT(16) /* ... in open */
|
||||
#define LOOKUP_CREATE BIT(17) /* ... in object creation */
|
||||
#define LOOKUP_EXCL BIT(18) /* ... in target must not exist */
|
||||
#define LOOKUP_RENAME_TARGET BIT(19) /* ... in destination of rename() */
|
||||
|
||||
/* internal use only */
|
||||
#define LOOKUP_PARENT 0x0010
|
||||
/* 4 spare bits for intent */
|
||||
|
||||
/* Scoping flags for lookup. */
|
||||
#define LOOKUP_NO_SYMLINKS 0x010000 /* No symlink crossing. */
|
||||
#define LOOKUP_NO_MAGICLINKS 0x020000 /* No nd_jump_link() crossing. */
|
||||
#define LOOKUP_NO_XDEV 0x040000 /* No mountpoint crossing. */
|
||||
#define LOOKUP_BENEATH 0x080000 /* No escaping from starting point. */
|
||||
#define LOOKUP_IN_ROOT 0x100000 /* Treat dirfd as fs root. */
|
||||
#define LOOKUP_CACHED 0x200000 /* Only do cached lookup */
|
||||
#define LOOKUP_LINKAT_EMPTY 0x400000 /* Linkat request with empty path. */
|
||||
#define LOOKUP_NO_SYMLINKS BIT(24) /* No symlink crossing. */
|
||||
#define LOOKUP_NO_MAGICLINKS BIT(25) /* No nd_jump_link() crossing. */
|
||||
#define LOOKUP_NO_XDEV BIT(26) /* No mountpoint crossing. */
|
||||
#define LOOKUP_BENEATH BIT(27) /* No escaping from starting point. */
|
||||
#define LOOKUP_IN_ROOT BIT(28) /* Treat dirfd as fs root. */
|
||||
/* LOOKUP_* flags which do scope-related checks based on the dirfd. */
|
||||
#define LOOKUP_IS_SCOPED (LOOKUP_BENEATH | LOOKUP_IN_ROOT)
|
||||
/* 3 spare bits for scoping */
|
||||
|
||||
extern int path_pts(struct path *path);
|
||||
|
||||
|
@ -1802,7 +1802,7 @@ struct nfs_rpc_ops {
|
||||
int (*link) (struct inode *, struct inode *, const struct qstr *);
|
||||
int (*symlink) (struct inode *, struct dentry *, struct folio *,
|
||||
unsigned int, struct iattr *);
|
||||
int (*mkdir) (struct inode *, struct dentry *, struct iattr *);
|
||||
struct dentry *(*mkdir) (struct inode *, struct dentry *, struct iattr *);
|
||||
int (*rmdir) (struct inode *, const struct qstr *);
|
||||
int (*readdir) (struct nfs_readdir_arg *, struct nfs_readdir_res *);
|
||||
int (*mknod) (struct inode *, struct dentry *, struct iattr *,
|
||||
|
@ -350,11 +350,10 @@ static int audit_get_nd(struct audit_watch *watch, struct path *parent)
|
||||
struct dentry *d = kern_path_locked(watch->path, parent);
|
||||
if (IS_ERR(d))
|
||||
return PTR_ERR(d);
|
||||
if (d_is_positive(d)) {
|
||||
/* update watch filter fields */
|
||||
watch->dev = d->d_sb->s_dev;
|
||||
watch->ino = d_backing_inode(d)->i_ino;
|
||||
}
|
||||
/* update watch filter fields */
|
||||
watch->dev = d->d_sb->s_dev;
|
||||
watch->ino = d_backing_inode(d)->i_ino;
|
||||
|
||||
inode_unlock(d_backing_inode(parent->dentry));
|
||||
dput(d);
|
||||
return 0;
|
||||
@ -419,10 +418,11 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
|
||||
/* caller expects mutex locked */
|
||||
mutex_lock(&audit_filter_mutex);
|
||||
|
||||
if (ret) {
|
||||
if (ret && ret != -ENOENT) {
|
||||
audit_put_watch(watch);
|
||||
return ret;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
/* either find an old parent or attach a new one */
|
||||
parent = audit_find_parent(d_backing_inode(parent_path.dentry));
|
||||
|
@ -150,14 +150,14 @@ static void bpf_dentry_finalize(struct dentry *dentry, struct inode *inode,
|
||||
inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
|
||||
}
|
||||
|
||||
static int bpf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *bpf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
|
||||
inode = bpf_get_inode(dir->i_sb, dir, mode | S_IFDIR);
|
||||
if (IS_ERR(inode))
|
||||
return PTR_ERR(inode);
|
||||
return ERR_CAST(inode);
|
||||
|
||||
inode->i_op = &bpf_dir_iops;
|
||||
inode->i_fop = &simple_dir_operations;
|
||||
@ -166,7 +166,7 @@ static int bpf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
inc_nlink(dir);
|
||||
|
||||
bpf_dentry_finalize(dentry, inode, dir);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct map_iter {
|
||||
|
@ -3912,16 +3912,16 @@ out_iput:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int shmem_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *shmem_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = shmem_mknod(idmap, dir, dentry, mode | S_IFDIR, 0);
|
||||
if (error)
|
||||
return error;
|
||||
return ERR_PTR(error);
|
||||
inc_nlink(dir);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int shmem_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
@ -1795,8 +1795,8 @@ fail2:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int ns_mkdir_op(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
static struct dentry *ns_mkdir_op(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct aa_ns *ns, *parent;
|
||||
/* TODO: improve permission check */
|
||||
@ -1808,7 +1808,7 @@ static int ns_mkdir_op(struct mnt_idmap *idmap, struct inode *dir,
|
||||
AA_MAY_LOAD_POLICY);
|
||||
end_current_label_crit_section(label);
|
||||
if (error)
|
||||
return error;
|
||||
return ERR_PTR(error);
|
||||
|
||||
parent = aa_get_ns(dir->i_private);
|
||||
AA_BUG(d_inode(ns_subns_dir(parent)) != dir);
|
||||
@ -1843,7 +1843,7 @@ out:
|
||||
mutex_unlock(&parent->lock);
|
||||
aa_put_ns(parent);
|
||||
|
||||
return error;
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
static int ns_rmdir_op(struct inode *dir, struct dentry *dentry)
|
||||
|
Loading…
x
Reference in New Issue
Block a user