X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=target%2Flinux%2Fgeneric%2Fpatches-4.4%2F052-02-ubifs-Implement-RENAME_WHITEOUT.patch;h=c2ec904939872a55d875bcfc41c1252d8991f902;hb=HEAD;hp=9abb923932fc6186bbe69af56d6789ef119549c7;hpb=413eb04e1eeff0ea140b0dd5365ae04fb0dabd46;p=openwrt%2Fopenwrt.git diff --git a/target/linux/generic/patches-4.4/052-02-ubifs-Implement-RENAME_WHITEOUT.patch b/target/linux/generic/patches-4.4/052-02-ubifs-Implement-RENAME_WHITEOUT.patch deleted file mode 100644 index 9abb923932..0000000000 --- a/target/linux/generic/patches-4.4/052-02-ubifs-Implement-RENAME_WHITEOUT.patch +++ /dev/null @@ -1,342 +0,0 @@ -From: Richard Weinberger -Date: Tue, 13 Sep 2016 16:18:56 +0200 -Subject: [PATCH] ubifs: Implement RENAME_WHITEOUT - -Adds RENAME_WHITEOUT support to UBIFS, we implement -it in the same way as ext4 and xfs do. -For an overview of other ways to implement it please -refere to commit 7dcf5c3e4527 ("xfs: add RENAME_WHITEOUT support"). - -Signed-off-by: Richard Weinberger ---- - ---- a/fs/ubifs/dir.c -+++ b/fs/ubifs/dir.c -@@ -301,8 +301,8 @@ out_budg: - return err; - } - --static int ubifs_tmpfile(struct inode *dir, struct dentry *dentry, -- umode_t mode) -+static int do_tmpfile(struct inode *dir, struct dentry *dentry, -+ umode_t mode, struct inode **whiteout) - { - struct inode *inode; - struct ubifs_info *c = dir->i_sb->s_fs_info; -@@ -336,14 +336,27 @@ static int ubifs_tmpfile(struct inode *d - } - ui = ubifs_inode(inode); - -+ if (whiteout) { -+ init_special_inode(inode, inode->i_mode, WHITEOUT_DEV); -+ ubifs_assert(inode->i_op == &ubifs_file_inode_operations); -+ } -+ - err = ubifs_init_security(dir, inode, &dentry->d_name); - if (err) - goto out_inode; - - mutex_lock(&ui->ui_mutex); - insert_inode_hash(inode); -- d_tmpfile(dentry, inode); -+ -+ if (whiteout) { -+ mark_inode_dirty(inode); -+ drop_nlink(inode); -+ *whiteout = inode; -+ } else { -+ d_tmpfile(dentry, inode); -+ } - ubifs_assert(ui->dirty); -+ - instantiated = 1; - mutex_unlock(&ui->ui_mutex); - -@@ -371,6 +384,12 @@ out_budg: - return err; - } - -+static int ubifs_tmpfile(struct inode *dir, struct dentry *dentry, -+ umode_t mode) -+{ -+ return do_tmpfile(dir, dentry, mode, NULL); -+} -+ - /** - * vfs_dent_type - get VFS directory entry type. - * @type: UBIFS directory entry type -@@ -997,37 +1016,43 @@ out_budg: - } - - /** -- * lock_3_inodes - a wrapper for locking three UBIFS inodes. -+ * lock_4_inodes - a wrapper for locking three UBIFS inodes. - * @inode1: first inode - * @inode2: second inode - * @inode3: third inode -+ * @inode4: fouth inode - * - * This function is used for 'ubifs_rename()' and @inode1 may be the same as -- * @inode2 whereas @inode3 may be %NULL. -+ * @inode2 whereas @inode3 and @inode4 may be %NULL. - * - * We do not implement any tricks to guarantee strict lock ordering, because - * VFS has already done it for us on the @i_mutex. So this is just a simple - * wrapper function. - */ --static void lock_3_inodes(struct inode *inode1, struct inode *inode2, -- struct inode *inode3) -+static void lock_4_inodes(struct inode *inode1, struct inode *inode2, -+ struct inode *inode3, struct inode *inode4) - { - mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1); - if (inode2 != inode1) - mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2); - if (inode3) - mutex_lock_nested(&ubifs_inode(inode3)->ui_mutex, WB_MUTEX_3); -+ if (inode4) -+ mutex_lock_nested(&ubifs_inode(inode4)->ui_mutex, WB_MUTEX_4); - } - - /** -- * unlock_3_inodes - a wrapper for unlocking three UBIFS inodes for rename. -+ * unlock_4_inodes - a wrapper for unlocking three UBIFS inodes for rename. - * @inode1: first inode - * @inode2: second inode - * @inode3: third inode -+ * @inode4: fouth inode - */ --static void unlock_3_inodes(struct inode *inode1, struct inode *inode2, -- struct inode *inode3) -+static void unlock_4_inodes(struct inode *inode1, struct inode *inode2, -+ struct inode *inode3, struct inode *inode4) - { -+ if (inode4) -+ mutex_unlock(&ubifs_inode(inode4)->ui_mutex); - if (inode3) - mutex_unlock(&ubifs_inode(inode3)->ui_mutex); - if (inode1 != inode2) -@@ -1036,12 +1061,15 @@ static void unlock_3_inodes(struct inode - } - - static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, -- struct inode *new_dir, struct dentry *new_dentry) -+ struct inode *new_dir, struct dentry *new_dentry, -+ unsigned int flags) - { - struct ubifs_info *c = old_dir->i_sb->s_fs_info; - struct inode *old_inode = d_inode(old_dentry); - struct inode *new_inode = d_inode(new_dentry); -+ struct inode *whiteout = NULL; - struct ubifs_inode *old_inode_ui = ubifs_inode(old_inode); -+ struct ubifs_inode *whiteout_ui = NULL; - int err, release, sync = 0, move = (new_dir != old_dir); - int is_dir = S_ISDIR(old_inode->i_mode); - int unlink = !!new_inode; -@@ -1063,9 +1091,13 @@ static int ubifs_rename(struct inode *ol - * separately. - */ - -- dbg_gen("dent '%pd' ino %lu in dir ino %lu to dent '%pd' in dir ino %lu", -+ dbg_gen("dent '%pd' ino %lu in dir ino %lu to dent '%pd' in dir ino %lu flags 0x%x", - old_dentry, old_inode->i_ino, old_dir->i_ino, -- new_dentry, new_dir->i_ino); -+ new_dentry, new_dir->i_ino, flags); -+ -+ if (flags & ~(RENAME_NOREPLACE | RENAME_WHITEOUT)) -+ return -EINVAL; -+ - ubifs_assert(mutex_is_locked(&old_dir->i_mutex)); - ubifs_assert(mutex_is_locked(&new_dir->i_mutex)); - if (unlink) -@@ -1087,7 +1119,32 @@ static int ubifs_rename(struct inode *ol - return err; - } - -- lock_3_inodes(old_dir, new_dir, new_inode); -+ if (flags & RENAME_WHITEOUT) { -+ union ubifs_dev_desc *dev = NULL; -+ -+ dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS); -+ if (!dev) { -+ ubifs_release_budget(c, &req); -+ ubifs_release_budget(c, &ino_req); -+ return -ENOMEM; -+ } -+ -+ err = do_tmpfile(old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, &whiteout); -+ if (err) { -+ ubifs_release_budget(c, &req); -+ ubifs_release_budget(c, &ino_req); -+ kfree(dev); -+ return err; -+ } -+ -+ whiteout->i_state |= I_LINKABLE; -+ whiteout_ui = ubifs_inode(whiteout); -+ whiteout_ui->data = dev; -+ whiteout_ui->data_len = ubifs_encode_dev(dev, MKDEV(0, 0)); -+ ubifs_assert(!whiteout_ui->dirty); -+ } -+ -+ lock_4_inodes(old_dir, new_dir, new_inode, whiteout); - - /* - * Like most other Unix systems, set the @i_ctime for inodes on a -@@ -1157,12 +1214,34 @@ static int ubifs_rename(struct inode *ol - if (unlink && IS_SYNC(new_inode)) - sync = 1; - } -- err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry, -+ -+ if (whiteout) { -+ struct ubifs_budget_req wht_req = { .dirtied_ino = 1, -+ .dirtied_ino_d = \ -+ ALIGN(ubifs_inode(whiteout)->data_len, 8) }; -+ -+ err = ubifs_budget_space(c, &wht_req); -+ if (err) { -+ ubifs_release_budget(c, &req); -+ ubifs_release_budget(c, &ino_req); -+ kfree(whiteout_ui->data); -+ whiteout_ui->data_len = 0; -+ iput(whiteout); -+ return err; -+ } -+ -+ inc_nlink(whiteout); -+ mark_inode_dirty(whiteout); -+ whiteout->i_state &= ~I_LINKABLE; -+ iput(whiteout); -+ } -+ -+ err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry, whiteout, - sync); - if (err) - goto out_cancel; - -- unlock_3_inodes(old_dir, new_dir, new_inode); -+ unlock_4_inodes(old_dir, new_dir, new_inode, whiteout); - ubifs_release_budget(c, &req); - - mutex_lock(&old_inode_ui->ui_mutex); -@@ -1195,7 +1274,11 @@ out_cancel: - inc_nlink(old_dir); - } - } -- unlock_3_inodes(old_dir, new_dir, new_inode); -+ if (whiteout) { -+ drop_nlink(whiteout); -+ iput(whiteout); -+ } -+ unlock_4_inodes(old_dir, new_dir, new_inode, whiteout); - ubifs_release_budget(c, &ino_req); - ubifs_release_budget(c, &req); - return err; -@@ -1249,7 +1332,7 @@ const struct inode_operations ubifs_dir_ - .mkdir = ubifs_mkdir, - .rmdir = ubifs_rmdir, - .mknod = ubifs_mknod, -- .rename = ubifs_rename, -+ .rename2 = ubifs_rename, - .setattr = ubifs_setattr, - .getattr = ubifs_getattr, - .setxattr = ubifs_setxattr, ---- a/fs/ubifs/journal.c -+++ b/fs/ubifs/journal.c -@@ -917,14 +917,15 @@ int ubifs_jnl_delete_inode(struct ubifs_ - * @sync: non-zero if the write-buffer has to be synchronized - * - * This function implements the re-name operation which may involve writing up -- * to 3 inodes and 2 directory entries. It marks the written inodes as clean -+ * to 4 inodes and 2 directory entries. It marks the written inodes as clean - * and returns zero on success. In case of failure, a negative error code is - * returned. - */ - int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, - const struct dentry *old_dentry, - const struct inode *new_dir, -- const struct dentry *new_dentry, int sync) -+ const struct dentry *new_dentry, -+ const struct inode *whiteout, int sync) - { - void *p; - union ubifs_key key; -@@ -980,13 +981,19 @@ int ubifs_jnl_rename(struct ubifs_info * - zero_dent_node_unused(dent); - ubifs_prep_grp_node(c, dent, dlen1, 0); - -- /* Make deletion dent */ - dent2 = (void *)dent + aligned_dlen1; - dent2->ch.node_type = UBIFS_DENT_NODE; - dent_key_init_flash(c, &dent2->key, old_dir->i_ino, - &old_dentry->d_name); -- dent2->inum = 0; -- dent2->type = DT_UNKNOWN; -+ -+ if (whiteout) { -+ dent2->inum = cpu_to_le64(whiteout->i_ino); -+ dent2->type = get_dent_type(whiteout->i_mode); -+ } else { -+ /* Make deletion dent */ -+ dent2->inum = 0; -+ dent2->type = DT_UNKNOWN; -+ } - dent2->nlen = cpu_to_le16(old_dentry->d_name.len); - memcpy(dent2->name, old_dentry->d_name.name, old_dentry->d_name.len); - dent2->name[old_dentry->d_name.len] = '\0'; -@@ -1035,16 +1042,26 @@ int ubifs_jnl_rename(struct ubifs_info * - if (err) - goto out_ro; - -- err = ubifs_add_dirt(c, lnum, dlen2); -- if (err) -- goto out_ro; -+ offs += aligned_dlen1; -+ if (whiteout) { -+ dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name); -+ err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen2, &old_dentry->d_name); -+ if (err) -+ goto out_ro; - -- dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name); -- err = ubifs_tnc_remove_nm(c, &key, &old_dentry->d_name); -- if (err) -- goto out_ro; -+ ubifs_delete_orphan(c, whiteout->i_ino); -+ } else { -+ err = ubifs_add_dirt(c, lnum, dlen2); -+ if (err) -+ goto out_ro; - -- offs += aligned_dlen1 + aligned_dlen2; -+ dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name); -+ err = ubifs_tnc_remove_nm(c, &key, &old_dentry->d_name); -+ if (err) -+ goto out_ro; -+ } -+ -+ offs += aligned_dlen2; - if (new_inode) { - ino_key_init(c, &key, new_inode->i_ino); - err = ubifs_tnc_add(c, &key, lnum, offs, ilen); ---- a/fs/ubifs/ubifs.h -+++ b/fs/ubifs/ubifs.h -@@ -180,6 +180,7 @@ enum { - WB_MUTEX_1 = 0, - WB_MUTEX_2 = 1, - WB_MUTEX_3 = 2, -+ WB_MUTEX_4 = 3, - }; - - /* -@@ -1546,7 +1547,8 @@ int ubifs_jnl_delete_inode(struct ubifs_ - int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, - const struct dentry *old_dentry, - const struct inode *new_dir, -- const struct dentry *new_dentry, int sync); -+ const struct dentry *new_dentry, -+ const struct inode *whiteout, int sync); - int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode, - loff_t old_size, loff_t new_size); - int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,