aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/include/uapi/asm/fcntl.h1
-rw-r--r--arch/parisc/include/uapi/asm/fcntl.h1
-rw-r--r--arch/sparc/include/uapi/asm/fcntl.h1
-rw-r--r--fs/dcache.c16
-rw-r--r--fs/ext2/namei.c24
-rw-r--r--fs/minix/namei.c13
-rw-r--r--fs/namei.c60
-rw-r--r--fs/open.c14
-rw-r--r--include/linux/dcache.h2
-rw-r--r--include/linux/fs.h1
-rw-r--r--include/uapi/asm-generic/fcntl.h4
-rw-r--r--mm/shmem.c32
12 files changed, 164 insertions, 5 deletions
diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
index 6d9e805f18a7..dfdadb0b4bef 100644
--- a/arch/alpha/include/uapi/asm/fcntl.h
+++ b/arch/alpha/include/uapi/asm/fcntl.h
@@ -32,6 +32,7 @@
32#define O_SYNC (__O_SYNC|O_DSYNC) 32#define O_SYNC (__O_SYNC|O_DSYNC)
33 33
34#define O_PATH 040000000 34#define O_PATH 040000000
35#define O_TMPFILE 0100000000
35 36
36#define F_GETLK 7 37#define F_GETLK 7
37#define F_SETLK 8 38#define F_SETLK 8
diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h
index 0304b92ccfea..cc61c475f277 100644
--- a/arch/parisc/include/uapi/asm/fcntl.h
+++ b/arch/parisc/include/uapi/asm/fcntl.h
@@ -20,6 +20,7 @@
20#define O_INVISIBLE 004000000 /* invisible I/O, for DMAPI/XDSM */ 20#define O_INVISIBLE 004000000 /* invisible I/O, for DMAPI/XDSM */
21 21
22#define O_PATH 020000000 22#define O_PATH 020000000
23#define O_TMPFILE 040000000
23 24
24#define F_GETLK64 8 25#define F_GETLK64 8
25#define F_SETLK64 9 26#define F_SETLK64 9
diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h
index d0b83f66f356..d73e5e008b0d 100644
--- a/arch/sparc/include/uapi/asm/fcntl.h
+++ b/arch/sparc/include/uapi/asm/fcntl.h
@@ -35,6 +35,7 @@
35#define O_SYNC (__O_SYNC|O_DSYNC) 35#define O_SYNC (__O_SYNC|O_DSYNC)
36 36
37#define O_PATH 0x1000000 37#define O_PATH 0x1000000
38#define O_TMPFILE 0x2000000
38 39
39#define F_GETOWN 5 /* for sockets. */ 40#define F_GETOWN 5 /* for sockets. */
40#define F_SETOWN 6 /* for sockets. */ 41#define F_SETOWN 6 /* for sockets. */
diff --git a/fs/dcache.c b/fs/dcache.c
index f09b9085f7d8..b7f049c31526 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2968,6 +2968,22 @@ rename_retry:
2968 goto again; 2968 goto again;
2969} 2969}
2970 2970
2971void 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}
2985EXPORT_SYMBOL(d_tmpfile);
2986
2971/** 2987/**
2972 * find_inode_number - check for dentry with name 2988 * find_inode_number - check for dentry with name
2973 * @dir: directory to check 2989 * @dir: directory to check
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 73b0d9519836..256dd5f4c1c4 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -119,6 +119,29 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, umode_t mode
119 return ext2_add_nondir(dentry, inode); 119 return ext2_add_nondir(dentry, inode);
120} 120}
121 121
122static 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
122static int ext2_mknod (struct inode * dir, struct dentry *dentry, umode_t mode, dev_t rdev) 145static int ext2_mknod (struct inode * dir, struct dentry *dentry, umode_t mode, dev_t rdev)
123{ 146{
124 struct inode * inode; 147 struct inode * inode;
@@ -398,6 +421,7 @@ const struct inode_operations ext2_dir_inode_operations = {
398#endif 421#endif
399 .setattr = ext2_setattr, 422 .setattr = ext2_setattr,
400 .get_acl = ext2_get_acl, 423 .get_acl = ext2_get_acl,
424 .tmpfile = ext2_tmpfile,
401}; 425};
402 426
403const struct inode_operations ext2_special_inode_operations = { 427const struct inode_operations ext2_special_inode_operations = {
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 0db73d9dd668..cd950e2331b6 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -54,6 +54,18 @@ static int minix_mknod(struct inode * dir, struct dentry *dentry, umode_t mode,
54 return error; 54 return error;
55} 55}
56 56
57static 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
57static int minix_create(struct inode *dir, struct dentry *dentry, umode_t mode, 69static int minix_create(struct inode *dir, struct dentry *dentry, umode_t mode,
58 bool excl) 70 bool excl)
59{ 71{
@@ -254,4 +266,5 @@ const struct inode_operations minix_dir_inode_operations = {
254 .mknod = minix_mknod, 266 .mknod = minix_mknod,
255 .rename = minix_rename, 267 .rename = minix_rename,
256 .getattr = minix_getattr, 268 .getattr = minix_getattr,
269 .tmpfile = minix_tmpfile,
257}; 270};
diff --git a/fs/namei.c b/fs/namei.c
index 402eda351d07..778e253e3d48 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2902,6 +2902,61 @@ stale_open:
2902 goto retry_lookup; 2902 goto retry_lookup;
2903} 2903}
2904 2904
2905static 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);
2953out2:
2954 mnt_drop_write(nd->path.mnt);
2955out:
2956 path_put(&nd->path);
2957 return error;
2958}
2959
2905static struct file *path_openat(int dfd, struct filename *pathname, 2960static struct file *path_openat(int dfd, struct filename *pathname,
2906 struct nameidata *nd, const struct open_flags *op, int flags) 2961 struct nameidata *nd, const struct open_flags *op, int flags)
2907{ 2962{
@@ -2917,6 +2972,11 @@ static struct file *path_openat(int dfd, struct filename *pathname,
2917 2972
2918 file->f_flags = op->open_flag; 2973 file->f_flags = op->open_flag;
2919 2974
2975 if (unlikely(file->f_flags & O_TMPFILE)) {
2976 error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened);
2977 goto out;
2978 }
2979
2920 error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base); 2980 error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base);
2921 if (unlikely(error)) 2981 if (unlikely(error))
2922 goto out; 2982 goto out;
diff --git a/fs/open.c b/fs/open.c
index 5a40a4a51757..fca72c4d3f17 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -840,11 +840,15 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
840 if (flags & __O_SYNC) 840 if (flags & __O_SYNC)
841 flags |= O_DSYNC; 841 flags |= O_DSYNC;
842 842
843 /* 843 if (flags & O_TMPFILE) {
844 * If we have O_PATH in the open flag. Then we 844 if (!(flags & O_CREAT))
845 * cannot have anything other than the below set of flags 845 return -EINVAL;
846 */ 846 acc_mode = MAY_OPEN | ACC_MODE(flags);
847 if (flags & O_PATH) { 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 */
848 flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH; 852 flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;
849 acc_mode = 0; 853 acc_mode = 0;
850 } else { 854 } else {
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 1a6bb81f0fe5..86da7595ba31 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -246,6 +246,8 @@ extern struct dentry * d_make_root(struct inode *);
246/* <clickety>-<click> the ramfs-type tree */ 246/* <clickety>-<click> the ramfs-type tree */
247extern void d_genocide(struct dentry *); 247extern void d_genocide(struct dentry *);
248 248
249extern void d_tmpfile(struct dentry *, struct inode *);
250
249extern struct dentry *d_find_alias(struct inode *); 251extern struct dentry *d_find_alias(struct inode *);
250extern void d_prune_aliases(struct inode *); 252extern void d_prune_aliases(struct inode *);
251 253
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7c30e3a62baf..dd6615f0fd13 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1580,6 +1580,7 @@ struct inode_operations {
1580 int (*atomic_open)(struct inode *, struct dentry *, 1580 int (*atomic_open)(struct inode *, struct dentry *,
1581 struct file *, unsigned open_flag, 1581 struct file *, unsigned open_flag,
1582 umode_t create_mode, int *opened); 1582 umode_t create_mode, int *opened);
1583 int (*tmpfile) (struct inode *, struct dentry *, umode_t);
1583} ____cacheline_aligned; 1584} ____cacheline_aligned;
1584 1585
1585ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, 1586ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h
index a48937d4a5ea..06632beaa6d5 100644
--- a/include/uapi/asm-generic/fcntl.h
+++ b/include/uapi/asm-generic/fcntl.h
@@ -84,6 +84,10 @@
84#define O_PATH 010000000 84#define O_PATH 010000000
85#endif 85#endif
86 86
87#ifndef O_TMPFILE
88#define O_TMPFILE 020000000
89#endif
90
87#ifndef O_NDELAY 91#ifndef O_NDELAY
88#define O_NDELAY O_NONBLOCK 92#define O_NDELAY O_NONBLOCK
89#endif 93#endif
diff --git a/mm/shmem.c b/mm/shmem.c
index 5e6a8422658b..f887358dabc5 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1965,6 +1965,37 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
1965 return error; 1965 return error;
1966} 1966}
1967 1967
1968static int
1969shmem_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
1968static int shmem_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 1999static int shmem_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1969{ 2000{
1970 int error; 2001 int error;
@@ -2723,6 +2754,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
2723 .rmdir = shmem_rmdir, 2754 .rmdir = shmem_rmdir,
2724 .mknod = shmem_mknod, 2755 .mknod = shmem_mknod,
2725 .rename = shmem_rename, 2756 .rename = shmem_rename,
2757 .tmpfile = shmem_tmpfile,
2726#endif 2758#endif
2727#ifdef CONFIG_TMPFS_XATTR 2759#ifdef CONFIG_TMPFS_XATTR
2728 .setxattr = shmem_setxattr, 2760 .setxattr = shmem_setxattr,