diff --git a/fs/hmdfs/inode_cloud_merge.c b/fs/hmdfs/inode_cloud_merge.c index d8cbebe7f972835a26409b806586fa8d9ab843ec..1d1dc7ee39f54622bb2e2eb1d421a8be781d8bb6 100644 --- a/fs/hmdfs/inode_cloud_merge.c +++ b/fs/hmdfs/inode_cloud_merge.c @@ -650,6 +650,11 @@ static int hmdfs_rename_cloud_merge(struct inode *old_dir, ret = -EACCES; goto rename_out; } + if (hmdfs_d(old_dentry)->device_id != hmdfs_d(new_dentry)->device_id) { + ret = -EXDEV; + goto rename_out; + } + rec_op_para = kmalloc(sizeof(*rec_op_para), GFP_KERNEL); if (!rec_op_para) { ret = -ENOMEM; diff --git a/fs/hmdfs/inode_local.c b/fs/hmdfs/inode_local.c index a06e5066ed0653e230bbadd28f041db87a67864f..346309fd94aa5ee063b350800acfdc3e76892f98 100644 --- a/fs/hmdfs/inode_local.c +++ b/fs/hmdfs/inode_local.c @@ -672,6 +672,10 @@ int hmdfs_rename_local(struct inode *old_dir, struct dentry *old_dentry, err = -EACCES; goto rename_out; } + if (hmdfs_d(old_dentry)->device_id != hmdfs_d(new_dentry)->device_id) { + err = -EXDEV; + goto rename_out; + } if (S_ISREG(old_dentry->d_inode->i_mode)) { err = hmdfs_rename_local_dentry(old_dir, old_dentry, new_dir, diff --git a/fs/hmdfs/inode_merge.c b/fs/hmdfs/inode_merge.c index c1014e0f552e143b199e93a3fdb9479c801070b2..0ef8defc2b86017109e932f75a77b79731d8e03a 100644 --- a/fs/hmdfs/inode_merge.c +++ b/fs/hmdfs/inode_merge.c @@ -1173,6 +1173,7 @@ int do_unlink_merge(struct inode *dir, struct dentry *dentry) struct hmdfs_dentry_comrade *comrade = NULL; struct dentry *lo_d = NULL; struct dentry *lo_d_dir = NULL; + struct dentry *lo_d_lookup = NULL; struct inode *lo_i_dir = NULL; wait_event(dim->wait_queue, !has_merge_lookup_work(dim)); @@ -1182,8 +1183,19 @@ int do_unlink_merge(struct inode *dir, struct dentry *dentry) lo_d = comrade->lo_d; dget(lo_d); lo_d_dir = lock_parent(lo_d); + /* lo_d could be unhashed, need to lookup again here */ + lo_d_lookup = lookup_one_len(lo_d->d_name.name, lo_d_dir, + strlen(lo_d->d_name.name)); + if (IS_ERR(lo_d_lookup)) { + ret = PTR_ERR(lo_d_lookup); + hmdfs_err("lookup_one_len failed, err = %d", ret); + unlock_dir(lo_d_dir); + dput(lo_d); + break; + } lo_i_dir = d_inode(lo_d_dir); - ret = vfs_unlink(lo_i_dir, lo_d, NULL); // lo_d GET + ret = vfs_unlink(lo_i_dir, lo_d_lookup, NULL); + dput(lo_d_lookup); unlock_dir(lo_d_dir); dput(lo_d); if (ret) diff --git a/fs/hmdfs/inode_remote.c b/fs/hmdfs/inode_remote.c index 6a19e6e6b135616e4bd3ed1225b559e950d588a8..f906b24104076b7567b0570b019662b385adaf16 100644 --- a/fs/hmdfs/inode_remote.c +++ b/fs/hmdfs/inode_remote.c @@ -809,6 +809,8 @@ int hmdfs_rename_remote(struct inode *old_dir, struct dentry *old_dentry, hmdfs_file_type(new_dentry->d_name.name) != HMDFS_TYPE_COMMON) { return -EACCES; } + if (hmdfs_d(old_dentry)->device_id != hmdfs_d(new_dentry)->device_id) + return -EXDEV; relative_old_dir_path = hmdfs_get_dentry_relative_path(old_dentry->d_parent);