return err;
}
+struct sdcardfs_name_data {
+ struct dir_context ctx;
+ const struct qstr *to_find;
+ char *name;
+ bool found;
+};
+
+static int sdcardfs_name_match(void *__buf, const char *name, int namelen,
+ loff_t offset, u64 ino, unsigned int d_type)
+{
+ struct sdcardfs_name_data *buf = (struct sdcardfs_name_data *) __buf;
+ struct qstr candidate = QSTR_INIT(name, namelen);
+
+ if (qstr_case_eq(buf->to_find, &candidate)) {
+ memcpy(buf->name, name, namelen);
+ buf->name[namelen] = 0;
+ buf->found = true;
+ return 1;
+ }
+ return 0;
+}
+
/*
* Main driver function for sdcardfs's lookup.
*
&lower_path);
/* check for other cases */
if (err == -ENOENT) {
- struct dentry *child;
- struct dentry *match = NULL;
- mutex_lock(&lower_dir_dentry->d_inode->i_mutex);
- spin_lock(&lower_dir_dentry->d_lock);
- list_for_each_entry(child, &lower_dir_dentry->d_subdirs, d_u.d_child) {
- if (child && child->d_inode) {
- if (qstr_case_eq(&child->d_name, name)) {
- match = dget(child);
- break;
- }
- }
+ struct file *file;
+ const struct cred *cred = current_cred();
+
+ struct sdcardfs_name_data buffer = {
+ .ctx.actor = sdcardfs_name_match,
+ .to_find = name,
+ .name = __getname(),
+ .found = false,
+ };
+
+ if (!buffer.name) {
+ err = -ENOMEM;
+ goto out;
+ }
+ file = dentry_open(lower_parent_path, O_RDONLY, cred);
+ if (IS_ERR(file)) {
+ err = PTR_ERR(file);
+ goto put_name;
}
- spin_unlock(&lower_dir_dentry->d_lock);
- mutex_unlock(&lower_dir_dentry->d_inode->i_mutex);
- if (match) {
+ err = iterate_dir(file, &buffer.ctx);
+ fput(file);
+ if (err)
+ goto put_name;
+
+ if (buffer.found)
err = vfs_path_lookup(lower_dir_dentry,
lower_dir_mnt,
- match->d_name.name, 0,
+ buffer.name, 0,
&lower_path);
- dput(match);
- }
+ else
+ err = -ENOENT;
+put_name:
+ __putname(buffer.name);
}
/* no error: handle positive dentries */