ubifs: Rename whiteout atomically
authorZhihao Cheng <chengzhihao1@huawei.com>
Mon, 27 Dec 2021 03:22:36 +0000 (11:22 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 8 Apr 2022 12:24:08 +0000 (14:24 +0200)
commitc67bc98d1f0853bb196e9c48eab38b6f2ddab795
tree154f2ed8729ad7e26457db7fc065ce7b79e49ebe
parentff846f2c5d1de96f0af036eb9e3a7ecfeb1f1cd5
ubifs: Rename whiteout atomically

commit 278d9a243635f26c05ad95dcf9c5a593b9e04dc6 upstream.

Currently, rename whiteout has 3 steps:
  1. create tmpfile(which associates old dentry to tmpfile inode) for
     whiteout, and store tmpfile to disk
  2. link whiteout, associate whiteout inode to old dentry agagin and
     store old dentry, old inode, new dentry on disk
  3. writeback dirty whiteout inode to disk

Suddenly power-cut or error occurring(eg. ENOSPC returned by budget,
memory allocation failure) during above steps may cause kinds of problems:
  Problem 1: ENOSPC returned by whiteout space budget (before step 2),
     old dentry will disappear after rename syscall, whiteout file
     cannot be found either.

     ls dir  // we get file, whiteout
     rename(dir/file, dir/whiteout, REANME_WHITEOUT)
     ENOSPC = ubifs_budget_space(&wht_req) // return
     ls dir  // empty (no file, no whiteout)
  Problem 2: Power-cut happens before step 3, whiteout inode with 'nlink=1'
     is not stored on disk, whiteout dentry(old dentry) is written
     on disk, whiteout file is lost on next mount (We get "dead
     directory entry" after executing 'ls -l' on whiteout file).

Now, we use following 3 steps to finish rename whiteout:
  1. create an in-mem inode with 'nlink = 1' as whiteout
  2. ubifs_jnl_rename (Write on disk to finish associating old dentry to
     whiteout inode, associating new dentry with old inode)
  3. iput(whiteout)

Rely writing in-mem inode on disk by ubifs_jnl_rename() to finish rename
whiteout, which avoids middle disk state caused by suddenly power-cut
and error occurring.

Fixes: 9e0a1fff8db56ea ("ubifs: Implement RENAME_WHITEOUT")
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/ubifs/dir.c
fs/ubifs/journal.c