* An error code is returned on failure.
*/
static struct dentry *lookup_open(struct nameidata *nd, struct file *file,
- const struct open_flags *op,
- struct delegated_inode *delegated_inode)
+ const struct open_flags *op)
{
+ struct delegated_inode delegated_inode = { };
struct mnt_idmap *idmap;
struct dentry *dir = nd->path.dentry;
struct inode *dir_inode = dir->d_inode;
- int open_flag = op->open_flag;
+ int open_flag;
struct dentry *dentry;
- int error, create_error = 0;
- umode_t mode = op->mode;
- bool got_write = false;
+ int error, create_error;
+ umode_t mode;
+ bool got_write;
+
+retry:
+ open_flag = op->open_flag;
+ got_write = false;
+ mode = op->mode;
+ create_error = 0;
if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) {
got_write = !mnt_want_write(nd->path.mnt);
/* Negative dentry, just create the file */
if (!dentry->d_inode && (open_flag & O_CREAT)) {
/* but break the directory lease first! */
- error = try_break_deleg(dir_inode, LEASE_BREAK_DIR_CREATE, delegated_inode);
+ error = try_break_deleg(dir_inode, LEASE_BREAK_DIR_CREATE, &delegated_inode);
if (error)
goto out_dput;
if (got_write)
mnt_drop_write(nd->path.mnt);
+ if (is_delegated(&delegated_inode)) {
+ /* Must have come through out_dput: dentry is an ERR_PTR() */
+ error = break_deleg_wait(&delegated_inode);
+
+ if (!error)
+ goto retry;
+ dentry = ERR_PTR(error);
+ }
+
return dentry;
out_dput:
static const char *open_last_lookups(struct nameidata *nd,
struct file *file, const struct open_flags *op)
{
- struct delegated_inode delegated_inode = { };
int open_flag = op->open_flag;
struct dentry *dentry;
const char *res;
return ERR_PTR(-ECHILD);
}
}
-retry:
- dentry = lookup_open(nd, file, op, &delegated_inode);
-
- if (IS_ERR(dentry)) {
- if (is_delegated(&delegated_inode)) {
- int error = break_deleg_wait(&delegated_inode);
- if (!error)
- goto retry;
- return ERR_PTR(error);
- }
+ dentry = lookup_open(nd, file, op);
+ if (IS_ERR(dentry))
return ERR_CAST(dentry);
- }
if (file->f_mode & (FMODE_OPENED | FMODE_CREATED)) {
dput(nd->path.dentry);