Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'vfs-7.0-rc1.atomic_open' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs atomic_open updates from Christian Brauner:
"Allow knfsd to use atomic_open()

While knfsd offers combined exclusive create and open results to
clients, on some filesystems those results are not atomic. The
separate vfs_create() + vfs_open() sequence in dentry_create() can
produce races and unexpected errors. For example, open O_CREAT with
mode 0 will succeed in creating the file but return -EACCES from
vfs_open(). Additionally, network filesystems benefit from reducing
remote round-trip operations by using a single atomic_open() call.

Teach dentry_create() -- whose sole caller is knfsd -- to use
atomic_open() for filesystems that support it"

* tag 'vfs-7.0-rc1.atomic_open' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
fs/namei: fix kernel-doc markup for dentry_create
VFS/knfsd: Teach dentry_create() to use atomic_open()
VFS: Prepare atomic_open() for dentry_create()
VFS: move dentry_create() from fs/open.c to fs/namei.c

+82 -50
+73 -7
fs/namei.c
··· 4290 4290 * 4291 4291 * Returns an error code otherwise. 4292 4292 */ 4293 - static struct dentry *atomic_open(struct nameidata *nd, struct dentry *dentry, 4293 + static struct dentry *atomic_open(const struct path *path, struct dentry *dentry, 4294 4294 struct file *file, 4295 4295 int open_flag, umode_t mode) 4296 4296 { 4297 4297 struct dentry *const DENTRY_NOT_SET = (void *) -1UL; 4298 - struct inode *dir = nd->path.dentry->d_inode; 4298 + struct inode *dir = path->dentry->d_inode; 4299 4299 int error; 4300 4300 4301 - if (nd->flags & LOOKUP_DIRECTORY) 4302 - open_flag |= O_DIRECTORY; 4303 - 4304 4301 file->__f_path.dentry = DENTRY_NOT_SET; 4305 - file->__f_path.mnt = nd->path.mnt; 4302 + file->__f_path.mnt = path->mnt; 4306 4303 error = dir->i_op->atomic_open(dir, dentry, file, 4307 4304 open_to_namei_flags(open_flag), mode); 4308 4305 d_lookup_done(dentry); ··· 4411 4414 if (create_error) 4412 4415 open_flag &= ~O_CREAT; 4413 4416 if (dir_inode->i_op->atomic_open) { 4414 - dentry = atomic_open(nd, dentry, file, open_flag, mode); 4417 + if (nd->flags & LOOKUP_DIRECTORY) 4418 + open_flag |= O_DIRECTORY; 4419 + dentry = atomic_open(&nd->path, dentry, file, open_flag, mode); 4415 4420 if (unlikely(create_error) && dentry == ERR_PTR(-ENOENT)) 4416 4421 dentry = ERR_PTR(create_error); 4417 4422 return dentry; ··· 4947 4948 } 4948 4949 EXPORT_SYMBOL(start_creating_user_path); 4949 4950 4951 + /** 4952 + * dentry_create - Create and open a file 4953 + * @path: path to create 4954 + * @flags: O\_ flags 4955 + * @mode: mode bits for new file 4956 + * @cred: credentials to use 4957 + * 4958 + * Caller must hold the parent directory's lock, and have prepared 4959 + * a negative dentry, placed in @path->dentry, for the new file. 4960 + * 4961 + * Caller sets @path->mnt to the vfsmount of the filesystem where 4962 + * the new file is to be created. The parent directory and the 4963 + * negative dentry must reside on the same filesystem instance. 4964 + * 4965 + * On success, returns a ``struct file *``. Otherwise an ERR_PTR 4966 + * is returned. 4967 + */ 4968 + struct file *dentry_create(struct path *path, int flags, umode_t mode, 4969 + const struct cred *cred) 4970 + { 4971 + struct file *file __free(fput) = NULL; 4972 + struct dentry *dentry = path->dentry; 4973 + struct dentry *dir = dentry->d_parent; 4974 + struct inode *dir_inode = d_inode(dir); 4975 + struct mnt_idmap *idmap; 4976 + int error, create_error; 4977 + 4978 + file = alloc_empty_file(flags, cred); 4979 + if (IS_ERR(file)) 4980 + return file; 4981 + 4982 + idmap = mnt_idmap(path->mnt); 4983 + 4984 + if (dir_inode->i_op->atomic_open) { 4985 + path->dentry = dir; 4986 + mode = vfs_prepare_mode(idmap, dir_inode, mode, S_IALLUGO, S_IFREG); 4987 + 4988 + create_error = may_o_create(idmap, path, dentry, mode); 4989 + if (create_error) 4990 + flags &= ~O_CREAT; 4991 + 4992 + dentry = atomic_open(path, dentry, file, flags, mode); 4993 + error = PTR_ERR_OR_ZERO(dentry); 4994 + 4995 + if (unlikely(create_error) && error == -ENOENT) 4996 + error = create_error; 4997 + 4998 + if (!error) { 4999 + if (file->f_mode & FMODE_CREATED) 5000 + fsnotify_create(dir->d_inode, dentry); 5001 + if (file->f_mode & FMODE_OPENED) 5002 + fsnotify_open(file); 5003 + } 5004 + 5005 + path->dentry = dentry; 5006 + 5007 + } else { 5008 + error = vfs_create(mnt_idmap(path->mnt), path->dentry, mode, NULL); 5009 + if (!error) 5010 + error = vfs_open(path, file); 5011 + } 5012 + if (unlikely(error)) 5013 + return ERR_PTR(error); 5014 + 5015 + return no_free_ptr(file); 5016 + } 5017 + EXPORT_SYMBOL(dentry_create); 4950 5018 4951 5019 /** 4952 5020 * vfs_mknod - create device node or file
+8 -3
fs/nfsd/nfs4proc.c
··· 194 194 } 195 195 196 196 static __be32 197 - nfsd4_vfs_create(struct svc_fh *fhp, struct dentry *child, 197 + nfsd4_vfs_create(struct svc_fh *fhp, struct dentry **child, 198 198 struct nfsd4_open *open) 199 199 { 200 200 struct file *filp; ··· 202 202 int oflags; 203 203 204 204 oflags = O_CREAT | O_LARGEFILE; 205 + if (nfsd4_create_is_exclusive(open->op_createmode)) 206 + oflags |= O_EXCL; 207 + 205 208 switch (open->op_share_access & NFS4_SHARE_ACCESS_BOTH) { 206 209 case NFS4_SHARE_ACCESS_WRITE: 207 210 oflags |= O_WRONLY; ··· 217 214 } 218 215 219 216 path.mnt = fhp->fh_export->ex_path.mnt; 220 - path.dentry = child; 217 + path.dentry = *child; 221 218 filp = dentry_create(&path, oflags, open->op_iattr.ia_mode, 222 219 current_cred()); 220 + *child = path.dentry; 221 + 223 222 if (IS_ERR(filp)) 224 223 return nfserrno(PTR_ERR(filp)); 225 224 ··· 355 350 status = fh_fill_pre_attrs(fhp); 356 351 if (status != nfs_ok) 357 352 goto out; 358 - status = nfsd4_vfs_create(fhp, child, open); 353 + status = nfsd4_vfs_create(fhp, &child, open); 359 354 if (status != nfs_ok) 360 355 goto out; 361 356 open->op_created = true;
-39
fs/open.c
··· 1142 1142 } 1143 1143 1144 1144 /** 1145 - * dentry_create - Create and open a file 1146 - * @path: path to create 1147 - * @flags: O_ flags 1148 - * @mode: mode bits for new file 1149 - * @cred: credentials to use 1150 - * 1151 - * Caller must hold the parent directory's lock, and have prepared 1152 - * a negative dentry, placed in @path->dentry, for the new file. 1153 - * 1154 - * Caller sets @path->mnt to the vfsmount of the filesystem where 1155 - * the new file is to be created. The parent directory and the 1156 - * negative dentry must reside on the same filesystem instance. 1157 - * 1158 - * On success, returns a "struct file *". Otherwise a ERR_PTR 1159 - * is returned. 1160 - */ 1161 - struct file *dentry_create(const struct path *path, int flags, umode_t mode, 1162 - const struct cred *cred) 1163 - { 1164 - struct file *f; 1165 - int error; 1166 - 1167 - f = alloc_empty_file(flags, cred); 1168 - if (IS_ERR(f)) 1169 - return f; 1170 - 1171 - error = vfs_create(mnt_idmap(path->mnt), path->dentry, mode, NULL); 1172 - if (!error) 1173 - error = vfs_open(path, f); 1174 - 1175 - if (unlikely(error)) { 1176 - fput(f); 1177 - return ERR_PTR(error); 1178 - } 1179 - return f; 1180 - } 1181 - EXPORT_SYMBOL(dentry_create); 1182 - 1183 - /** 1184 1145 * kernel_file_open - open a file for kernel internal use 1185 1146 * @path: path of the file to open 1186 1147 * @flags: open flags
+1 -1
include/linux/fs.h
··· 2467 2467 const struct cred *creds); 2468 2468 struct file *dentry_open_nonotify(const struct path *path, int flags, 2469 2469 const struct cred *cred); 2470 - struct file *dentry_create(const struct path *path, int flags, umode_t mode, 2470 + struct file *dentry_create(struct path *path, int flags, umode_t mode, 2471 2471 const struct cred *cred); 2472 2472 const struct path *backing_file_user_path(const struct file *f); 2473 2473