summaryrefslogtreecommitdiffstats
path: root/fs/ubifs
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2016-09-14 16:28:50 -0400
committerRichard Weinberger <richard@nod.at>2016-10-02 16:55:02 -0400
commit9e0a1fff8db56eaaebb74b4a3ef65f86811c4798 (patch)
tree5aacb28779d5befeb285a7334c4ebaa4617d81be /fs/ubifs
parent474b93704f32163af4bfa728fddc570eba357353 (diff)
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 <richard@nod.at>
Diffstat (limited to 'fs/ubifs')
-rw-r--r--fs/ubifs/dir.c120
-rw-r--r--fs/ubifs/journal.c43
-rw-r--r--fs/ubifs/ubifs.h4
3 files changed, 134 insertions, 33 deletions
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 8460f481eeb9..e0282534f170 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -301,8 +301,8 @@ out_budg:
301 return err; 301 return err;
302} 302}
303 303
304static int ubifs_tmpfile(struct inode *dir, struct dentry *dentry, 304static int do_tmpfile(struct inode *dir, struct dentry *dentry,
305 umode_t mode) 305 umode_t mode, struct inode **whiteout)
306{ 306{
307 struct inode *inode; 307 struct inode *inode;
308 struct ubifs_info *c = dir->i_sb->s_fs_info; 308 struct ubifs_info *c = dir->i_sb->s_fs_info;
@@ -336,14 +336,27 @@ static int ubifs_tmpfile(struct inode *dir, struct dentry *dentry,
336 } 336 }
337 ui = ubifs_inode(inode); 337 ui = ubifs_inode(inode);
338 338
339 if (whiteout) {
340 init_special_inode(inode, inode->i_mode, WHITEOUT_DEV);
341 ubifs_assert(inode->i_op == &ubifs_file_inode_operations);
342 }
343
339 err = ubifs_init_security(dir, inode, &dentry->d_name); 344 err = ubifs_init_security(dir, inode, &dentry->d_name);
340 if (err) 345 if (err)
341 goto out_inode; 346 goto out_inode;
342 347
343 mutex_lock(&ui->ui_mutex); 348 mutex_lock(&ui->ui_mutex);
344 insert_inode_hash(inode); 349 insert_inode_hash(inode);
345 d_tmpfile(dentry, inode); 350
351 if (whiteout) {
352 mark_inode_dirty(inode);
353 drop_nlink(inode);
354 *whiteout = inode;
355 } else {
356 d_tmpfile(dentry, inode);
357 }
346 ubifs_assert(ui->dirty); 358 ubifs_assert(ui->dirty);
359
347 instantiated = 1; 360 instantiated = 1;
348 mutex_unlock(&ui->ui_mutex); 361 mutex_unlock(&ui->ui_mutex);
349 362
@@ -371,6 +384,12 @@ out_budg:
371 return err; 384 return err;
372} 385}
373 386
387static int ubifs_tmpfile(struct inode *dir, struct dentry *dentry,
388 umode_t mode)
389{
390 return do_tmpfile(dir, dentry, mode, NULL);
391}
392
374/** 393/**
375 * vfs_dent_type - get VFS directory entry type. 394 * vfs_dent_type - get VFS directory entry type.
376 * @type: UBIFS directory entry type 395 * @type: UBIFS directory entry type
@@ -997,37 +1016,43 @@ out_budg:
997} 1016}
998 1017
999/** 1018/**
1000 * lock_3_inodes - a wrapper for locking three UBIFS inodes. 1019 * lock_4_inodes - a wrapper for locking three UBIFS inodes.
1001 * @inode1: first inode 1020 * @inode1: first inode
1002 * @inode2: second inode 1021 * @inode2: second inode
1003 * @inode3: third inode 1022 * @inode3: third inode
1023 * @inode4: fouth inode
1004 * 1024 *
1005 * This function is used for 'ubifs_rename()' and @inode1 may be the same as 1025 * This function is used for 'ubifs_rename()' and @inode1 may be the same as
1006 * @inode2 whereas @inode3 may be %NULL. 1026 * @inode2 whereas @inode3 and @inode4 may be %NULL.
1007 * 1027 *
1008 * We do not implement any tricks to guarantee strict lock ordering, because 1028 * We do not implement any tricks to guarantee strict lock ordering, because
1009 * VFS has already done it for us on the @i_mutex. So this is just a simple 1029 * VFS has already done it for us on the @i_mutex. So this is just a simple
1010 * wrapper function. 1030 * wrapper function.
1011 */ 1031 */
1012static void lock_3_inodes(struct inode *inode1, struct inode *inode2, 1032static void lock_4_inodes(struct inode *inode1, struct inode *inode2,
1013 struct inode *inode3) 1033 struct inode *inode3, struct inode *inode4)
1014{ 1034{
1015 mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1); 1035 mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
1016 if (inode2 != inode1) 1036 if (inode2 != inode1)
1017 mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2); 1037 mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
1018 if (inode3) 1038 if (inode3)
1019 mutex_lock_nested(&ubifs_inode(inode3)->ui_mutex, WB_MUTEX_3); 1039 mutex_lock_nested(&ubifs_inode(inode3)->ui_mutex, WB_MUTEX_3);
1040 if (inode4)
1041 mutex_lock_nested(&ubifs_inode(inode4)->ui_mutex, WB_MUTEX_4);
1020} 1042}
1021 1043
1022/** 1044/**
1023 * unlock_3_inodes - a wrapper for unlocking three UBIFS inodes for rename. 1045 * unlock_4_inodes - a wrapper for unlocking three UBIFS inodes for rename.
1024 * @inode1: first inode 1046 * @inode1: first inode
1025 * @inode2: second inode 1047 * @inode2: second inode
1026 * @inode3: third inode 1048 * @inode3: third inode
1049 * @inode4: fouth inode
1027 */ 1050 */
1028static void unlock_3_inodes(struct inode *inode1, struct inode *inode2, 1051static void unlock_4_inodes(struct inode *inode1, struct inode *inode2,
1029 struct inode *inode3) 1052 struct inode *inode3, struct inode *inode4)
1030{ 1053{
1054 if (inode4)
1055 mutex_unlock(&ubifs_inode(inode4)->ui_mutex);
1031 if (inode3) 1056 if (inode3)
1032 mutex_unlock(&ubifs_inode(inode3)->ui_mutex); 1057 mutex_unlock(&ubifs_inode(inode3)->ui_mutex);
1033 if (inode1 != inode2) 1058 if (inode1 != inode2)
@@ -1036,12 +1061,15 @@ static void unlock_3_inodes(struct inode *inode1, struct inode *inode2,
1036} 1061}
1037 1062
1038static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, 1063static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
1039 struct inode *new_dir, struct dentry *new_dentry) 1064 struct inode *new_dir, struct dentry *new_dentry,
1065 unsigned int flags)
1040{ 1066{
1041 struct ubifs_info *c = old_dir->i_sb->s_fs_info; 1067 struct ubifs_info *c = old_dir->i_sb->s_fs_info;
1042 struct inode *old_inode = d_inode(old_dentry); 1068 struct inode *old_inode = d_inode(old_dentry);
1043 struct inode *new_inode = d_inode(new_dentry); 1069 struct inode *new_inode = d_inode(new_dentry);
1070 struct inode *whiteout = NULL;
1044 struct ubifs_inode *old_inode_ui = ubifs_inode(old_inode); 1071 struct ubifs_inode *old_inode_ui = ubifs_inode(old_inode);
1072 struct ubifs_inode *whiteout_ui = NULL;
1045 int err, release, sync = 0, move = (new_dir != old_dir); 1073 int err, release, sync = 0, move = (new_dir != old_dir);
1046 int is_dir = S_ISDIR(old_inode->i_mode); 1074 int is_dir = S_ISDIR(old_inode->i_mode);
1047 int unlink = !!new_inode; 1075 int unlink = !!new_inode;
@@ -1063,15 +1091,18 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
1063 * separately. 1091 * separately.
1064 */ 1092 */
1065 1093
1066 dbg_gen("dent '%pd' ino %lu in dir ino %lu to dent '%pd' in dir ino %lu", 1094 dbg_gen("dent '%pd' ino %lu in dir ino %lu to dent '%pd' in dir ino %lu flags 0x%x",
1067 old_dentry, old_inode->i_ino, old_dir->i_ino, 1095 old_dentry, old_inode->i_ino, old_dir->i_ino,
1068 new_dentry, new_dir->i_ino); 1096 new_dentry, new_dir->i_ino, flags);
1097
1098 if (flags & ~(RENAME_NOREPLACE | RENAME_WHITEOUT))
1099 return -EINVAL;
1100
1069 ubifs_assert(inode_is_locked(old_dir)); 1101 ubifs_assert(inode_is_locked(old_dir));
1070 ubifs_assert(inode_is_locked(new_dir)); 1102 ubifs_assert(inode_is_locked(new_dir));
1071 if (unlink) 1103 if (unlink)
1072 ubifs_assert(inode_is_locked(new_inode)); 1104 ubifs_assert(inode_is_locked(new_inode));
1073 1105
1074
1075 if (unlink && is_dir) { 1106 if (unlink && is_dir) {
1076 err = check_dir_empty(c, new_inode); 1107 err = check_dir_empty(c, new_inode);
1077 if (err) 1108 if (err)
@@ -1087,7 +1118,32 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
1087 return err; 1118 return err;
1088 } 1119 }
1089 1120
1090 lock_3_inodes(old_dir, new_dir, new_inode); 1121 if (flags & RENAME_WHITEOUT) {
1122 union ubifs_dev_desc *dev = NULL;
1123
1124 dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);
1125 if (!dev) {
1126 ubifs_release_budget(c, &req);
1127 ubifs_release_budget(c, &ino_req);
1128 return -ENOMEM;
1129 }
1130
1131 err = do_tmpfile(old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, &whiteout);
1132 if (err) {
1133 ubifs_release_budget(c, &req);
1134 ubifs_release_budget(c, &ino_req);
1135 kfree(dev);
1136 return err;
1137 }
1138
1139 whiteout->i_state |= I_LINKABLE;
1140 whiteout_ui = ubifs_inode(whiteout);
1141 whiteout_ui->data = dev;
1142 whiteout_ui->data_len = ubifs_encode_dev(dev, MKDEV(0, 0));
1143 ubifs_assert(!whiteout_ui->dirty);
1144 }
1145
1146 lock_4_inodes(old_dir, new_dir, new_inode, whiteout);
1091 1147
1092 /* 1148 /*
1093 * Like most other Unix systems, set the @i_ctime for inodes on a 1149 * Like most other Unix systems, set the @i_ctime for inodes on a
@@ -1157,12 +1213,34 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
1157 if (unlink && IS_SYNC(new_inode)) 1213 if (unlink && IS_SYNC(new_inode))
1158 sync = 1; 1214 sync = 1;
1159 } 1215 }
1160 err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry, 1216
1217 if (whiteout) {
1218 struct ubifs_budget_req wht_req = { .dirtied_ino = 1,
1219 .dirtied_ino_d = \
1220 ALIGN(ubifs_inode(whiteout)->data_len, 8) };
1221
1222 err = ubifs_budget_space(c, &wht_req);
1223 if (err) {
1224 ubifs_release_budget(c, &req);
1225 ubifs_release_budget(c, &ino_req);
1226 kfree(whiteout_ui->data);
1227 whiteout_ui->data_len = 0;
1228 iput(whiteout);
1229 return err;
1230 }
1231
1232 inc_nlink(whiteout);
1233 mark_inode_dirty(whiteout);
1234 whiteout->i_state &= ~I_LINKABLE;
1235 iput(whiteout);
1236 }
1237
1238 err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry, whiteout,
1161 sync); 1239 sync);
1162 if (err) 1240 if (err)
1163 goto out_cancel; 1241 goto out_cancel;
1164 1242
1165 unlock_3_inodes(old_dir, new_dir, new_inode); 1243 unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
1166 ubifs_release_budget(c, &req); 1244 ubifs_release_budget(c, &req);
1167 1245
1168 mutex_lock(&old_inode_ui->ui_mutex); 1246 mutex_lock(&old_inode_ui->ui_mutex);
@@ -1195,7 +1273,11 @@ out_cancel:
1195 inc_nlink(old_dir); 1273 inc_nlink(old_dir);
1196 } 1274 }
1197 } 1275 }
1198 unlock_3_inodes(old_dir, new_dir, new_inode); 1276 if (whiteout) {
1277 drop_nlink(whiteout);
1278 iput(whiteout);
1279 }
1280 unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
1199 ubifs_release_budget(c, &ino_req); 1281 ubifs_release_budget(c, &ino_req);
1200 ubifs_release_budget(c, &req); 1282 ubifs_release_budget(c, &req);
1201 return err; 1283 return err;
@@ -1249,7 +1331,7 @@ const struct inode_operations ubifs_dir_inode_operations = {
1249 .mkdir = ubifs_mkdir, 1331 .mkdir = ubifs_mkdir,
1250 .rmdir = ubifs_rmdir, 1332 .rmdir = ubifs_rmdir,
1251 .mknod = ubifs_mknod, 1333 .mknod = ubifs_mknod,
1252 .rename = ubifs_rename, 1334 .rename2 = ubifs_rename,
1253 .setattr = ubifs_setattr, 1335 .setattr = ubifs_setattr,
1254 .getattr = ubifs_getattr, 1336 .getattr = ubifs_getattr,
1255 .setxattr = generic_setxattr, 1337 .setxattr = generic_setxattr,
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index 0b9da5b6e0f9..6b27ddd2c484 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -917,14 +917,15 @@ int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode)
917 * @sync: non-zero if the write-buffer has to be synchronized 917 * @sync: non-zero if the write-buffer has to be synchronized
918 * 918 *
919 * This function implements the re-name operation which may involve writing up 919 * This function implements the re-name operation which may involve writing up
920 * to 3 inodes and 2 directory entries. It marks the written inodes as clean 920 * to 4 inodes and 2 directory entries. It marks the written inodes as clean
921 * and returns zero on success. In case of failure, a negative error code is 921 * and returns zero on success. In case of failure, a negative error code is
922 * returned. 922 * returned.
923 */ 923 */
924int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, 924int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
925 const struct dentry *old_dentry, 925 const struct dentry *old_dentry,
926 const struct inode *new_dir, 926 const struct inode *new_dir,
927 const struct dentry *new_dentry, int sync) 927 const struct dentry *new_dentry,
928 const struct inode *whiteout, int sync)
928{ 929{
929 void *p; 930 void *p;
930 union ubifs_key key; 931 union ubifs_key key;
@@ -980,13 +981,19 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
980 zero_dent_node_unused(dent); 981 zero_dent_node_unused(dent);
981 ubifs_prep_grp_node(c, dent, dlen1, 0); 982 ubifs_prep_grp_node(c, dent, dlen1, 0);
982 983
983 /* Make deletion dent */
984 dent2 = (void *)dent + aligned_dlen1; 984 dent2 = (void *)dent + aligned_dlen1;
985 dent2->ch.node_type = UBIFS_DENT_NODE; 985 dent2->ch.node_type = UBIFS_DENT_NODE;
986 dent_key_init_flash(c, &dent2->key, old_dir->i_ino, 986 dent_key_init_flash(c, &dent2->key, old_dir->i_ino,
987 &old_dentry->d_name); 987 &old_dentry->d_name);
988 dent2->inum = 0; 988
989 dent2->type = DT_UNKNOWN; 989 if (whiteout) {
990 dent2->inum = cpu_to_le64(whiteout->i_ino);
991 dent2->type = get_dent_type(whiteout->i_mode);
992 } else {
993 /* Make deletion dent */
994 dent2->inum = 0;
995 dent2->type = DT_UNKNOWN;
996 }
990 dent2->nlen = cpu_to_le16(old_dentry->d_name.len); 997 dent2->nlen = cpu_to_le16(old_dentry->d_name.len);
991 memcpy(dent2->name, old_dentry->d_name.name, old_dentry->d_name.len); 998 memcpy(dent2->name, old_dentry->d_name.name, old_dentry->d_name.len);
992 dent2->name[old_dentry->d_name.len] = '\0'; 999 dent2->name[old_dentry->d_name.len] = '\0';
@@ -1035,16 +1042,26 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
1035 if (err) 1042 if (err)
1036 goto out_ro; 1043 goto out_ro;
1037 1044
1038 err = ubifs_add_dirt(c, lnum, dlen2); 1045 offs += aligned_dlen1;
1039 if (err) 1046 if (whiteout) {
1040 goto out_ro; 1047 dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name);
1048 err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen2, &old_dentry->d_name);
1049 if (err)
1050 goto out_ro;
1041 1051
1042 dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name); 1052 ubifs_delete_orphan(c, whiteout->i_ino);
1043 err = ubifs_tnc_remove_nm(c, &key, &old_dentry->d_name); 1053 } else {
1044 if (err) 1054 err = ubifs_add_dirt(c, lnum, dlen2);
1045 goto out_ro; 1055 if (err)
1056 goto out_ro;
1057
1058 dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name);
1059 err = ubifs_tnc_remove_nm(c, &key, &old_dentry->d_name);
1060 if (err)
1061 goto out_ro;
1062 }
1046 1063
1047 offs += aligned_dlen1 + aligned_dlen2; 1064 offs += aligned_dlen2;
1048 if (new_inode) { 1065 if (new_inode) {
1049 ino_key_init(c, &key, new_inode->i_ino); 1066 ino_key_init(c, &key, new_inode->i_ino);
1050 err = ubifs_tnc_add(c, &key, lnum, offs, ilen); 1067 err = ubifs_tnc_add(c, &key, lnum, offs, ilen);
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 4617d459022a..ca86c9386674 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -157,6 +157,7 @@ enum {
157 WB_MUTEX_1 = 0, 157 WB_MUTEX_1 = 0,
158 WB_MUTEX_2 = 1, 158 WB_MUTEX_2 = 1,
159 WB_MUTEX_3 = 2, 159 WB_MUTEX_3 = 2,
160 WB_MUTEX_4 = 3,
160}; 161};
161 162
162/* 163/*
@@ -1523,7 +1524,8 @@ int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode);
1523int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, 1524int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
1524 const struct dentry *old_dentry, 1525 const struct dentry *old_dentry,
1525 const struct inode *new_dir, 1526 const struct inode *new_dir,
1526 const struct dentry *new_dentry, int sync); 1527 const struct dentry *new_dentry,
1528 const struct inode *whiteout, int sync);
1527int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode, 1529int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
1528 loff_t old_size, loff_t new_size); 1530 loff_t old_size, loff_t new_size);
1529int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host, 1531int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,