Skip to content

Commit 60545d0

Browse files
author
Al Viro
committed
[O_TMPFILE] it's still short a few helpers, but infrastructure should be OK now...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent f9652e1 commit 60545d0

File tree

12 files changed

+164
-5
lines changed

12 files changed

+164
-5
lines changed

arch/alpha/include/uapi/asm/fcntl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#define O_SYNC (__O_SYNC|O_DSYNC)
3333

3434
#define O_PATH 040000000
35+
#define O_TMPFILE 0100000000
3536

3637
#define F_GETLK 7
3738
#define F_SETLK 8

arch/parisc/include/uapi/asm/fcntl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define O_INVISIBLE 004000000 /* invisible I/O, for DMAPI/XDSM */
2121

2222
#define O_PATH 020000000
23+
#define O_TMPFILE 040000000
2324

2425
#define F_GETLK64 8
2526
#define F_SETLK64 9

arch/sparc/include/uapi/asm/fcntl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#define O_SYNC (__O_SYNC|O_DSYNC)
3636

3737
#define O_PATH 0x1000000
38+
#define O_TMPFILE 0x2000000
3839

3940
#define F_GETOWN 5 /* for sockets. */
4041
#define F_SETOWN 6 /* for sockets. */

fs/dcache.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2968,6 +2968,22 @@ void d_genocide(struct dentry *root)
29682968
goto again;
29692969
}
29702970

2971+
void d_tmpfile(struct dentry *dentry, struct inode *inode)
2972+
{
2973+
inode_dec_link_count(inode);
2974+
BUG_ON(dentry->d_name.name != dentry->d_iname ||
2975+
!hlist_unhashed(&dentry->d_alias) ||
2976+
!d_unlinked(dentry));
2977+
spin_lock(&dentry->d_parent->d_lock);
2978+
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
2979+
dentry->d_name.len = sprintf(dentry->d_iname, "#%llu",
2980+
(unsigned long long)inode->i_ino);
2981+
spin_unlock(&dentry->d_lock);
2982+
spin_unlock(&dentry->d_parent->d_lock);
2983+
d_instantiate(dentry, inode);
2984+
}
2985+
EXPORT_SYMBOL(d_tmpfile);
2986+
29712987
/**
29722988
* find_inode_number - check for dentry with name
29732989
* @dir: directory to check

fs/ext2/namei.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,29 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, umode_t mode
119119
return ext2_add_nondir(dentry, inode);
120120
}
121121

122+
static int ext2_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
123+
{
124+
struct inode *inode = ext2_new_inode(dir, mode, NULL);
125+
if (IS_ERR(inode))
126+
return PTR_ERR(inode);
127+
128+
inode->i_op = &ext2_file_inode_operations;
129+
if (ext2_use_xip(inode->i_sb)) {
130+
inode->i_mapping->a_ops = &ext2_aops_xip;
131+
inode->i_fop = &ext2_xip_file_operations;
132+
} else if (test_opt(inode->i_sb, NOBH)) {
133+
inode->i_mapping->a_ops = &ext2_nobh_aops;
134+
inode->i_fop = &ext2_file_operations;
135+
} else {
136+
inode->i_mapping->a_ops = &ext2_aops;
137+
inode->i_fop = &ext2_file_operations;
138+
}
139+
mark_inode_dirty(inode);
140+
d_tmpfile(dentry, inode);
141+
unlock_new_inode(inode);
142+
return 0;
143+
}
144+
122145
static int ext2_mknod (struct inode * dir, struct dentry *dentry, umode_t mode, dev_t rdev)
123146
{
124147
struct inode * inode;
@@ -398,6 +421,7 @@ const struct inode_operations ext2_dir_inode_operations = {
398421
#endif
399422
.setattr = ext2_setattr,
400423
.get_acl = ext2_get_acl,
424+
.tmpfile = ext2_tmpfile,
401425
};
402426

403427
const struct inode_operations ext2_special_inode_operations = {

fs/minix/namei.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@ static int minix_mknod(struct inode * dir, struct dentry *dentry, umode_t mode,
5454
return error;
5555
}
5656

57+
static int minix_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
58+
{
59+
int error;
60+
struct inode *inode = minix_new_inode(dir, mode, &error);
61+
if (inode) {
62+
minix_set_inode(inode, 0);
63+
mark_inode_dirty(inode);
64+
d_tmpfile(dentry, inode);
65+
}
66+
return error;
67+
}
68+
5769
static int minix_create(struct inode *dir, struct dentry *dentry, umode_t mode,
5870
bool excl)
5971
{
@@ -254,4 +266,5 @@ const struct inode_operations minix_dir_inode_operations = {
254266
.mknod = minix_mknod,
255267
.rename = minix_rename,
256268
.getattr = minix_getattr,
269+
.tmpfile = minix_tmpfile,
257270
};

fs/namei.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2902,6 +2902,61 @@ static int do_last(struct nameidata *nd, struct path *path,
29022902
goto retry_lookup;
29032903
}
29042904

2905+
static int do_tmpfile(int dfd, struct filename *pathname,
2906+
struct nameidata *nd, int flags,
2907+
const struct open_flags *op,
2908+
struct file *file, int *opened)
2909+
{
2910+
static const struct qstr name = QSTR_INIT("/", 1);
2911+
struct dentry *dentry, *child;
2912+
struct inode *dir;
2913+
int error = path_lookupat(dfd, pathname->name,
2914+
flags | LOOKUP_DIRECTORY, nd);
2915+
if (unlikely(error))
2916+
return error;
2917+
error = mnt_want_write(nd->path.mnt);
2918+
if (unlikely(error))
2919+
goto out;
2920+
/* we want directory to be writable */
2921+
error = inode_permission(nd->inode, MAY_WRITE | MAY_EXEC);
2922+
if (error)
2923+
goto out2;
2924+
dentry = nd->path.dentry;
2925+
dir = dentry->d_inode;
2926+
if (!dir->i_op->tmpfile) {
2927+
error = -EOPNOTSUPP;
2928+
goto out2;
2929+
}
2930+
child = d_alloc(dentry, &name);
2931+
if (unlikely(!child)) {
2932+
error = -ENOMEM;
2933+
goto out2;
2934+
}
2935+
nd->flags &= ~LOOKUP_DIRECTORY;
2936+
nd->flags |= op->intent;
2937+
dput(nd->path.dentry);
2938+
nd->path.dentry = child;
2939+
error = dir->i_op->tmpfile(dir, nd->path.dentry, op->mode);
2940+
if (error)
2941+
goto out2;
2942+
audit_inode(pathname, nd->path.dentry, 0);
2943+
error = may_open(&nd->path, op->acc_mode, op->open_flag);
2944+
if (error)
2945+
goto out2;
2946+
file->f_path.mnt = nd->path.mnt;
2947+
error = finish_open(file, nd->path.dentry, NULL, opened);
2948+
if (error)
2949+
goto out2;
2950+
error = open_check_o_direct(file);
2951+
if (error)
2952+
fput(file);
2953+
out2:
2954+
mnt_drop_write(nd->path.mnt);
2955+
out:
2956+
path_put(&nd->path);
2957+
return error;
2958+
}
2959+
29052960
static struct file *path_openat(int dfd, struct filename *pathname,
29062961
struct nameidata *nd, const struct open_flags *op, int flags)
29072962
{
@@ -2917,6 +2972,11 @@ static struct file *path_openat(int dfd, struct filename *pathname,
29172972

29182973
file->f_flags = op->open_flag;
29192974

2975+
if (unlikely(file->f_flags & O_TMPFILE)) {
2976+
error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened);
2977+
goto out;
2978+
}
2979+
29202980
error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base);
29212981
if (unlikely(error))
29222982
goto out;

fs/open.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -840,11 +840,15 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
840840
if (flags & __O_SYNC)
841841
flags |= O_DSYNC;
842842

843-
/*
844-
* If we have O_PATH in the open flag. Then we
845-
* cannot have anything other than the below set of flags
846-
*/
847-
if (flags & O_PATH) {
843+
if (flags & O_TMPFILE) {
844+
if (!(flags & O_CREAT))
845+
return -EINVAL;
846+
acc_mode = MAY_OPEN | ACC_MODE(flags);
847+
} else if (flags & O_PATH) {
848+
/*
849+
* If we have O_PATH in the open flag. Then we
850+
* cannot have anything other than the below set of flags
851+
*/
848852
flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;
849853
acc_mode = 0;
850854
} else {

include/linux/dcache.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ extern struct dentry * d_make_root(struct inode *);
246246
/* <clickety>-<click> the ramfs-type tree */
247247
extern void d_genocide(struct dentry *);
248248

249+
extern void d_tmpfile(struct dentry *, struct inode *);
250+
249251
extern struct dentry *d_find_alias(struct inode *);
250252
extern void d_prune_aliases(struct inode *);
251253

include/linux/fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,6 +1580,7 @@ struct inode_operations {
15801580
int (*atomic_open)(struct inode *, struct dentry *,
15811581
struct file *, unsigned open_flag,
15821582
umode_t create_mode, int *opened);
1583+
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
15831584
} ____cacheline_aligned;
15841585

15851586
ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,

include/uapi/asm-generic/fcntl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@
8484
#define O_PATH 010000000
8585
#endif
8686

87+
#ifndef O_TMPFILE
88+
#define O_TMPFILE 020000000
89+
#endif
90+
8791
#ifndef O_NDELAY
8892
#define O_NDELAY O_NONBLOCK
8993
#endif

mm/shmem.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,6 +1965,37 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
19651965
return error;
19661966
}
19671967

1968+
static int
1969+
shmem_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
1970+
{
1971+
struct inode *inode;
1972+
int error = -ENOSPC;
1973+
1974+
inode = shmem_get_inode(dir->i_sb, dir, mode, 0, VM_NORESERVE);
1975+
if (inode) {
1976+
error = security_inode_init_security(inode, dir,
1977+
NULL,
1978+
shmem_initxattrs, NULL);
1979+
if (error) {
1980+
if (error != -EOPNOTSUPP) {
1981+
iput(inode);
1982+
return error;
1983+
}
1984+
}
1985+
#ifdef CONFIG_TMPFS_POSIX_ACL
1986+
error = generic_acl_init(inode, dir);
1987+
if (error) {
1988+
iput(inode);
1989+
return error;
1990+
}
1991+
#else
1992+
error = 0;
1993+
#endif
1994+
d_tmpfile(dentry, inode);
1995+
}
1996+
return error;
1997+
}
1998+
19681999
static int shmem_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
19692000
{
19702001
int error;
@@ -2723,6 +2754,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
27232754
.rmdir = shmem_rmdir,
27242755
.mknod = shmem_mknod,
27252756
.rename = shmem_rename,
2757+
.tmpfile = shmem_tmpfile,
27262758
#endif
27272759
#ifdef CONFIG_TMPFS_XATTR
27282760
.setxattr = shmem_setxattr,

0 commit comments

Comments
 (0)