Skip to content

Commit 23cdd0e

Browse files
chuckleverbrauner
authored andcommitted
libfs: Fix simple_offset_rename_exchange()
User space expects the replacement (old) directory entry to have the same directory offset after the rename. Suggested-by: Christian Brauner <brauner@kernel.org> Fixes: a2e4595 ("shmem: stable directory offsets") Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Link: https://lore.kernel.org/r/20240415152057.4605-2-cel@kernel.org Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 4cece76 commit 23cdd0e

1 file changed

Lines changed: 19 additions & 6 deletions

File tree

fs/libfs.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,18 @@ int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry)
295295
return 0;
296296
}
297297

298+
static int simple_offset_replace(struct offset_ctx *octx, struct dentry *dentry,
299+
long offset)
300+
{
301+
int ret;
302+
303+
ret = mtree_store(&octx->mt, offset, dentry, GFP_KERNEL);
304+
if (ret)
305+
return ret;
306+
offset_set(dentry, offset);
307+
return 0;
308+
}
309+
298310
/**
299311
* simple_offset_remove - Remove an entry to a directory's offset map
300312
* @octx: directory offset ctx to be updated
@@ -352,6 +364,9 @@ int simple_offset_empty(struct dentry *dentry)
352364
* @new_dir: destination parent
353365
* @new_dentry: destination dentry
354366
*
367+
* This API preserves the directory offset values. Caller provides
368+
* appropriate serialization.
369+
*
355370
* Returns zero on success. Otherwise a negative errno is returned and the
356371
* rename is rolled back.
357372
*/
@@ -369,11 +384,11 @@ int simple_offset_rename_exchange(struct inode *old_dir,
369384
simple_offset_remove(old_ctx, old_dentry);
370385
simple_offset_remove(new_ctx, new_dentry);
371386

372-
ret = simple_offset_add(new_ctx, old_dentry);
387+
ret = simple_offset_replace(new_ctx, old_dentry, new_index);
373388
if (ret)
374389
goto out_restore;
375390

376-
ret = simple_offset_add(old_ctx, new_dentry);
391+
ret = simple_offset_replace(old_ctx, new_dentry, old_index);
377392
if (ret) {
378393
simple_offset_remove(new_ctx, old_dentry);
379394
goto out_restore;
@@ -388,10 +403,8 @@ int simple_offset_rename_exchange(struct inode *old_dir,
388403
return 0;
389404

390405
out_restore:
391-
offset_set(old_dentry, old_index);
392-
mtree_store(&old_ctx->mt, old_index, old_dentry, GFP_KERNEL);
393-
offset_set(new_dentry, new_index);
394-
mtree_store(&new_ctx->mt, new_index, new_dentry, GFP_KERNEL);
406+
(void)simple_offset_replace(old_ctx, old_dentry, old_index);
407+
(void)simple_offset_replace(new_ctx, new_dentry, new_index);
395408
return ret;
396409
}
397410

0 commit comments

Comments
 (0)