• Zhihao Cheng's avatar
    ubifs: Rename whiteout atomically · 278d9a24
    Zhihao Cheng authored
    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: 9e0a1fff ("ubifs: Implement RENAME_WHITEOUT")
    Signed-off-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
    Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
    278d9a24
dir.c 43.7 KB