···29022902 goto retry_lookup;29032903}2904290429052905+static int do_tmpfile(int dfd, struct filename *pathname,29062906+ struct nameidata *nd, int flags,29072907+ const struct open_flags *op,29082908+ struct file *file, int *opened)29092909+{29102910+ static const struct qstr name = QSTR_INIT("/", 1);29112911+ struct dentry *dentry, *child;29122912+ struct inode *dir;29132913+ int error = path_lookupat(dfd, pathname->name,29142914+ flags | LOOKUP_DIRECTORY, nd);29152915+ if (unlikely(error))29162916+ return error;29172917+ error = mnt_want_write(nd->path.mnt);29182918+ if (unlikely(error))29192919+ goto out;29202920+ /* we want directory to be writable */29212921+ error = inode_permission(nd->inode, MAY_WRITE | MAY_EXEC);29222922+ if (error)29232923+ goto out2;29242924+ dentry = nd->path.dentry;29252925+ dir = dentry->d_inode;29262926+ if (!dir->i_op->tmpfile) {29272927+ error = -EOPNOTSUPP;29282928+ goto out2;29292929+ }29302930+ child = d_alloc(dentry, &name);29312931+ if (unlikely(!child)) {29322932+ error = -ENOMEM;29332933+ goto out2;29342934+ }29352935+ nd->flags &= ~LOOKUP_DIRECTORY;29362936+ nd->flags |= op->intent;29372937+ dput(nd->path.dentry);29382938+ nd->path.dentry = child;29392939+ error = dir->i_op->tmpfile(dir, nd->path.dentry, op->mode);29402940+ if (error)29412941+ goto out2;29422942+ audit_inode(pathname, nd->path.dentry, 0);29432943+ error = may_open(&nd->path, op->acc_mode, op->open_flag);29442944+ if (error)29452945+ goto out2;29462946+ file->f_path.mnt = nd->path.mnt;29472947+ error = finish_open(file, nd->path.dentry, NULL, opened);29482948+ if (error)29492949+ goto out2;29502950+ error = open_check_o_direct(file);29512951+ if (error)29522952+ fput(file);29532953+out2:29542954+ mnt_drop_write(nd->path.mnt);29552955+out:29562956+ path_put(&nd->path);29572957+ return error;29582958+}29592959+29052960static struct file *path_openat(int dfd, struct filename *pathname,29062961 struct nameidata *nd, const struct open_flags *op, int flags)29072962{···29712916 return file;2972291729732918 file->f_flags = op->open_flag;29192919+29202920+ if (unlikely(file->f_flags & O_TMPFILE)) {29212921+ error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened);29222922+ goto out;29232923+ }2974292429752925 error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base);29762926 if (unlikely(error))
+9-5
fs/open.c
···840840 if (flags & __O_SYNC)841841 flags |= O_DSYNC;842842843843- /*844844- * If we have O_PATH in the open flag. Then we845845- * cannot have anything other than the below set of flags846846- */847847- if (flags & O_PATH) {843843+ if (flags & O_TMPFILE) {844844+ if (!(flags & O_CREAT))845845+ return -EINVAL;846846+ acc_mode = MAY_OPEN | ACC_MODE(flags);847847+ } else if (flags & O_PATH) {848848+ /*849849+ * If we have O_PATH in the open flag. Then we850850+ * cannot have anything other than the below set of flags851851+ */848852 flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;849853 acc_mode = 0;850854 } else {