Skip to content

Commit d9b3dbd

Browse files
author
Al Viro
committed
fuse: switch to ->iterate_shared()
Switch dcache pre-seeding on readdir to d_alloc_parallel(); nothing else is needed. Signed-off-by: Al Viro <[email protected]>
1 parent f50752e commit d9b3dbd

File tree

1 file changed

+45
-49
lines changed

1 file changed

+45
-49
lines changed

fs/fuse/dir.c

Lines changed: 45 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,7 +1162,6 @@ static int fuse_direntplus_link(struct file *file,
11621162
struct fuse_direntplus *direntplus,
11631163
u64 attr_version)
11641164
{
1165-
int err;
11661165
struct fuse_entry_out *o = &direntplus->entry_out;
11671166
struct fuse_dirent *dirent = &direntplus->dirent;
11681167
struct dentry *parent = file->f_path.dentry;
@@ -1172,6 +1171,7 @@ static int fuse_direntplus_link(struct file *file,
11721171
struct inode *dir = d_inode(parent);
11731172
struct fuse_conn *fc;
11741173
struct inode *inode;
1174+
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
11751175

11761176
if (!o->nodeid) {
11771177
/*
@@ -1204,65 +1204,61 @@ static int fuse_direntplus_link(struct file *file,
12041204

12051205
name.hash = full_name_hash(name.name, name.len);
12061206
dentry = d_lookup(parent, &name);
1207-
if (dentry) {
1207+
if (!dentry) {
1208+
retry:
1209+
dentry = d_alloc_parallel(parent, &name, &wq);
1210+
if (IS_ERR(dentry))
1211+
return PTR_ERR(dentry);
1212+
}
1213+
if (!d_in_lookup(dentry)) {
1214+
struct fuse_inode *fi;
12081215
inode = d_inode(dentry);
1209-
if (!inode) {
1210-
d_drop(dentry);
1211-
} else if (get_node_id(inode) != o->nodeid ||
1212-
((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
1216+
if (!inode ||
1217+
get_node_id(inode) != o->nodeid ||
1218+
((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
12131219
d_invalidate(dentry);
1214-
} else if (is_bad_inode(inode)) {
1215-
err = -EIO;
1216-
goto out;
1217-
} else {
1218-
struct fuse_inode *fi;
1219-
fi = get_fuse_inode(inode);
1220-
spin_lock(&fc->lock);
1221-
fi->nlookup++;
1222-
spin_unlock(&fc->lock);
1223-
1224-
fuse_change_attributes(inode, &o->attr,
1225-
entry_attr_timeout(o),
1226-
attr_version);
1227-
1228-
/*
1229-
* The other branch to 'found' comes via fuse_iget()
1230-
* which bumps nlookup inside
1231-
*/
1232-
goto found;
1220+
dput(dentry);
1221+
goto retry;
1222+
}
1223+
if (is_bad_inode(inode)) {
1224+
dput(dentry);
1225+
return -EIO;
12331226
}
1234-
dput(dentry);
1235-
}
1236-
1237-
dentry = d_alloc(parent, &name);
1238-
err = -ENOMEM;
1239-
if (!dentry)
1240-
goto out;
12411227

1242-
inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1243-
&o->attr, entry_attr_timeout(o), attr_version);
1244-
if (!inode)
1245-
goto out;
1228+
fi = get_fuse_inode(inode);
1229+
spin_lock(&fc->lock);
1230+
fi->nlookup++;
1231+
spin_unlock(&fc->lock);
12461232

1247-
alias = d_splice_alias(inode, dentry);
1248-
err = PTR_ERR(alias);
1249-
if (IS_ERR(alias))
1250-
goto out;
1233+
fuse_change_attributes(inode, &o->attr,
1234+
entry_attr_timeout(o),
1235+
attr_version);
1236+
/*
1237+
* The other branch comes via fuse_iget()
1238+
* which bumps nlookup inside
1239+
*/
1240+
} else {
1241+
inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
1242+
&o->attr, entry_attr_timeout(o),
1243+
attr_version);
1244+
if (!inode)
1245+
inode = ERR_PTR(-ENOMEM);
12511246

1252-
if (alias) {
1253-
dput(dentry);
1254-
dentry = alias;
1247+
alias = d_splice_alias(inode, dentry);
1248+
d_lookup_done(dentry);
1249+
if (alias) {
1250+
dput(dentry);
1251+
dentry = alias;
1252+
}
1253+
if (IS_ERR(dentry))
1254+
return PTR_ERR(dentry);
12551255
}
1256-
1257-
found:
12581256
if (fc->readdirplus_auto)
12591257
set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
12601258
fuse_change_entry_timeout(dentry, o);
12611259

1262-
err = 0;
1263-
out:
12641260
dput(dentry);
1265-
return err;
1261+
return 0;
12661262
}
12671263

12681264
static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
@@ -1892,7 +1888,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
18921888
static const struct file_operations fuse_dir_operations = {
18931889
.llseek = generic_file_llseek,
18941890
.read = generic_read_dir,
1895-
.iterate = fuse_readdir,
1891+
.iterate_shared = fuse_readdir,
18961892
.open = fuse_dir_open,
18971893
.release = fuse_dir_release,
18981894
.fsync = fuse_dir_fsync,

0 commit comments

Comments
 (0)