diff --git a/fs/hmdfs/inode.c b/fs/hmdfs/inode.c index 33cc8c7419d5c89ee3292df056f6164907b65972..90997cd88f7d74d58e1b33900d3efcf0f7aacbba 100644 --- a/fs/hmdfs/inode.c +++ b/fs/hmdfs/inode.c @@ -354,4 +354,41 @@ void hmdfs_update_upper_file(struct file *upper_file, struct file *lower_file) i_size_write(upper_file->f_inode, lower_size); truncate_inode_pages(upper_file->f_inode->i_mapping, 0); } +} + +struct dentry *lookup_multi_dir(struct dentry *root_dentry, + const char *name, + unsigned int flags) +{ + struct dentry *current_dentry = root_dentry; + struct dentry *ret_dentry = NULL; + const char *start = name; + const char *end = NULL; + if (*start) { + dget(root_dentry); + } + + while (*start) { + end = strchr(start, '/'); + if (!end) { + end = start + strlen(start); + } + hmdfs_err("flt :: goto lookup_one_len name = %s, len = %d\n", start, end - start); + ret_dentry = lookup_one_len(start, current_dentry, end - start); + if (IS_ERR(ret_dentry)) { + dput(current_dentry); + hmdfs_err("flt :: lookup_one_len failed!"); + return ret_dentry; + } + dput(current_dentry); + current_dentry = ret_dentry; + while (*end == '/') { + end = end + 1; + } + start = end; + } + if (ret_dentry == NULL) { + ret_dentry = ERR_PTR(ENOENT); + } + return ret_dentry; } \ No newline at end of file diff --git a/fs/hmdfs/inode.h b/fs/hmdfs/inode.h index fb9bd2929d581e6e48dee17bd369962869440e02..aace1392678424fa9f125a9659d10b0733601386 100644 --- a/fs/hmdfs/inode.h +++ b/fs/hmdfs/inode.h @@ -261,4 +261,7 @@ struct inode *hmdfs_iget5_locked_cloud(struct super_block *sb, void hmdfs_update_upper_file(struct file *upper_file, struct file *lower_file); uint32_t make_ino_raw_cloud(uint8_t *cloud_id); +struct dentry *lookup_multi_dir(struct dentry *root_dentry, + const char *name, + unsigned int flags); #endif // INODE_H diff --git a/fs/hmdfs/inode_cloud_merge.c b/fs/hmdfs/inode_cloud_merge.c index a6f0b150fcfcf229326ea210af8899556d25088d..ef9088547919486048f36a2de5996b90fed8b629 100644 --- a/fs/hmdfs/inode_cloud_merge.c +++ b/fs/hmdfs/inode_cloud_merge.c @@ -94,28 +94,16 @@ cloud_merge_lookup_comrade(struct hmdfs_sb_info *sbi, int devid, unsigned int flags) { - int err; - struct path root, path; + struct dentry *dentry = NULL; struct hmdfs_dentry_comrade *comrade = NULL; - err = kern_path(sbi->real_dst, LOOKUP_DIRECTORY, &root); - if (err) { - comrade = ERR_PTR(err); - goto out; - } - - err = vfs_path_lookup(root.dentry, root.mnt, name, flags, &path); - if (err) { - comrade = ERR_PTR(err); - goto root_put; + dentry = lookup_multi_dir(sbi->sb->s_root, name, flags); + if (dentry == NULL || IS_ERR(dentry)) { + return ERR_PTR(PTR_ERR(dentry)); } - comrade = alloc_comrade(path.dentry, devid); - - path_put(&path); -root_put: - path_put(&root); -out: + comrade = alloc_comrade(dentry, devid); + dput(dentry); return comrade; } @@ -202,7 +190,7 @@ static int lookup_merge_normal(struct dentry *dentry, unsigned int flags) * It's common for a network filesystem to incur various of faults, so we * intent to show mercy for faults here, except faults reported by the local. */ -static int do_lookup_cloud_merge_root(struct path path_dev, +static int do_lookup_cloud_merge_root(struct dentry *dentry_dev, struct dentry *child_dentry, unsigned int flags) { struct hmdfs_dentry_comrade *comrade; @@ -217,7 +205,7 @@ static int do_lookup_cloud_merge_root(struct path path_dev, // lookup real_dst/device_view/local memcpy(buf, DEVICE_VIEW_LOCAL, sizeof(DEVICE_VIEW_LOCAL)); - comrade = lookup_comrade(path_dev, buf, HMDFS_DEVID_LOCAL, flags); + comrade = lookup_comrade(dentry_dev, buf, HMDFS_DEVID_LOCAL, flags); if (IS_ERR(comrade)) { ret = PTR_ERR(comrade); goto out; @@ -226,7 +214,7 @@ static int do_lookup_cloud_merge_root(struct path path_dev, memcpy(buf, CLOUD_CID, 6); buf[5] = '\0'; - comrade = lookup_comrade(path_dev, buf, CLOUD_DEVICE, flags); + comrade = lookup_comrade(dentry_dev, buf, CLOUD_DEVICE, flags); if (IS_ERR(comrade)) { ret = 0; goto out; @@ -246,33 +234,21 @@ static int lookup_cloud_merge_root(struct inode *root_inode, struct dentry *child_dentry, unsigned int flags) { struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); - struct path path_dev; + struct dentry *dentry_dev = NULL; int ret = -ENOENT; - int buf_len; - char *buf = NULL; bool locked, down; - // consider additional one slash and one '\0' - buf_len = strlen(sbi->real_dst) + 1 + sizeof(DEVICE_VIEW_ROOT); - if (buf_len > PATH_MAX) - return -ENAMETOOLONG; - - buf = kmalloc(buf_len, GFP_KERNEL); - if (unlikely(!buf)) - return -ENOMEM; - - sprintf(buf, "%s/%s", sbi->real_dst, DEVICE_VIEW_ROOT); lock_root_inode_shared(root_inode, &locked, &down); - ret = hmdfs_get_path_in_sb(child_dentry->d_sb, buf, LOOKUP_DIRECTORY, - &path_dev); - if (ret) - goto free_buf; + dentry_dev = lookup_multi_dir(sbi->sb->s_root, DEVICE_VIEW_ROOT, flags); + if (dentry_dev == NULL || IS_ERR(dentry_dev)) { + ret = PTR_ERR(dentry_dev); + goto out; + } - ret = do_lookup_cloud_merge_root(path_dev, child_dentry, flags); - path_put(&path_dev); + ret = do_lookup_cloud_merge_root(dentry_dev, child_dentry, flags); + dput(dentry_dev); -free_buf: - kfree(buf); +out: restore_root_inode_sem(root_inode, locked, down); return ret; } diff --git a/fs/hmdfs/inode_merge.c b/fs/hmdfs/inode_merge.c index 7c1e1e4f8539adf339c4633ddbf0b0dc8f54833a..e653a821010d139d316d97df505a06a24ecfd9e7 100644 --- a/fs/hmdfs/inode_merge.c +++ b/fs/hmdfs/inode_merge.c @@ -217,22 +217,21 @@ void assign_comrades_unlocked(struct dentry *child_dentry, mutex_unlock(&cdi->comrade_list_lock); } -struct hmdfs_dentry_comrade *lookup_comrade(struct path lower_path, +struct hmdfs_dentry_comrade *lookup_comrade(struct dentry *lower_dentry, const char *d_name, int dev_id, unsigned int flags) { - struct path path; + struct dentry *dentry = NULL; struct hmdfs_dentry_comrade *comrade = NULL; - int err; - err = vfs_path_lookup(lower_path.dentry, lower_path.mnt, d_name, flags, - &path); - if (err) - return ERR_PTR(err); + dentry = lookup_multi_dir(lower_dentry, d_name, flags); + if (dentry == NULL || IS_ERR(dentry)) { + return ERR_PTR(PTR_ERR(dentry)); + } - comrade = alloc_comrade(path.dentry, dev_id); - path_put(&path); + comrade = alloc_comrade(dentry, dev_id); + dput(dentry); return comrade; } @@ -346,28 +345,24 @@ static struct hmdfs_dentry_comrade *merge_lookup_comrade( struct hmdfs_sb_info *sbi, const char *name, int devid, unsigned int flags) { - int err; - struct path root, path; + struct dentry *dentry = NULL; struct hmdfs_dentry_comrade *comrade = NULL; const struct cred *old_cred = hmdfs_override_creds(sbi->cred); - err = kern_path(sbi->real_dst, LOOKUP_DIRECTORY, &root); - if (err) { - comrade = ERR_PTR(err); + dentry = lookup_multi_dir(sbi->sb->s_root, name, flags); + if (dentry == NULL || IS_ERR(dentry)) { + if (dentry == NULL) { + hmdfs_err("flt :: dentry == NULL"); + } else { + hmdfs_err("flt :: dentry_err = %d", PTR_ERR(dentry)); + } + comrade = ERR_PTR(PTR_ERR(dentry)); goto out; } - err = vfs_path_lookup(root.dentry, root.mnt, name, flags, &path); - if (err) { - comrade = ERR_PTR(err); - goto root_put; - } + comrade = alloc_comrade(dentry, devid); + dput(dentry); - comrade = alloc_comrade(path.dentry, devid); - - path_put(&path); -root_put: - path_put(&root); out: hmdfs_revert_creds(old_cred); return comrade; @@ -550,7 +545,7 @@ static int lookup_merge_normal(struct dentry *dentry, unsigned int flags) * It's common for a network filesystem to incur various of faults, so we * intent to show mercy for faults here, except faults reported by the local. */ -static int do_lookup_merge_root(struct path path_dev, +static int do_lookup_merge_root(struct dentry *dentry_dev, struct dentry *child_dentry, unsigned int flags) { struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); @@ -567,7 +562,7 @@ static int do_lookup_merge_root(struct path path_dev, // lookup real_dst/device_view/local memcpy(buf, DEVICE_VIEW_LOCAL, sizeof(DEVICE_VIEW_LOCAL)); - comrade = lookup_comrade(path_dev, buf, HMDFS_DEVID_LOCAL, flags); + comrade = lookup_comrade(dentry_dev, buf, HMDFS_DEVID_LOCAL, flags); if (IS_ERR(comrade)) { ret = PTR_ERR(comrade); goto out; @@ -579,7 +574,7 @@ static int do_lookup_merge_root(struct path path_dev, list_for_each_entry(peer, &sbi->connections.node_list, list) { mutex_unlock(&sbi->connections.node_lock); memcpy(buf, peer->cid, HMDFS_CID_SIZE); - comrade = lookup_comrade(path_dev, buf, peer->device_id, flags); + comrade = lookup_comrade(dentry_dev, buf, peer->device_id, flags); if (IS_ERR(comrade)) continue; @@ -641,33 +636,21 @@ static int lookup_merge_root(struct inode *root_inode, struct dentry *child_dentry, unsigned int flags) { struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); - struct path path_dev; + struct dentry *dentry_dev = NULL; int ret = -ENOENT; - int buf_len; - char *buf = NULL; bool locked, down; - // consider additional one slash and one '\0' - buf_len = strlen(sbi->real_dst) + 1 + sizeof(DEVICE_VIEW_ROOT); - if (buf_len > PATH_MAX) - return -ENAMETOOLONG; - - buf = kmalloc(buf_len, GFP_KERNEL); - if (unlikely(!buf)) - return -ENOMEM; - - sprintf(buf, "%s/%s", sbi->real_dst, DEVICE_VIEW_ROOT); lock_root_inode_shared(root_inode, &locked, &down); - ret = hmdfs_get_path_in_sb(child_dentry->d_sb, buf, LOOKUP_DIRECTORY, - &path_dev); - if (ret) - goto free_buf; + dentry_dev = lookup_multi_dir(sbi->sb->s_root, DEVICE_VIEW_ROOT, flags); + if (dentry_dev == NULL || IS_ERR(dentry_dev)) { + ret = PTR_ERR(dentry_dev); + goto out; + } - ret = do_lookup_merge_root(path_dev, child_dentry, flags); - path_put(&path_dev); + ret = do_lookup_merge_root(dentry_dev, child_dentry, flags); + dput(dentry_dev); -free_buf: - kfree(buf); +out: restore_root_inode_sem(root_inode, locked, down); return ret; }