1
0

052-02-ubifs-Implement-RENAME_WHITEOUT.patch 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. From: Richard Weinberger <richard@nod.at>
  2. Date: Tue, 13 Sep 2016 16:18:56 +0200
  3. Subject: [PATCH] ubifs: Implement RENAME_WHITEOUT
  4. Adds RENAME_WHITEOUT support to UBIFS, we implement
  5. it in the same way as ext4 and xfs do.
  6. For an overview of other ways to implement it please
  7. refere to commit 7dcf5c3e4527 ("xfs: add RENAME_WHITEOUT support").
  8. Signed-off-by: Richard Weinberger <richard@nod.at>
  9. ---
  10. --- a/fs/ubifs/dir.c
  11. +++ b/fs/ubifs/dir.c
  12. @@ -301,8 +301,8 @@ out_budg:
  13. return err;
  14. }
  15. -static int ubifs_tmpfile(struct inode *dir, struct dentry *dentry,
  16. - umode_t mode)
  17. +static int do_tmpfile(struct inode *dir, struct dentry *dentry,
  18. + umode_t mode, struct inode **whiteout)
  19. {
  20. struct inode *inode;
  21. struct ubifs_info *c = dir->i_sb->s_fs_info;
  22. @@ -336,14 +336,27 @@ static int ubifs_tmpfile(struct inode *d
  23. }
  24. ui = ubifs_inode(inode);
  25. + if (whiteout) {
  26. + init_special_inode(inode, inode->i_mode, WHITEOUT_DEV);
  27. + ubifs_assert(inode->i_op == &ubifs_file_inode_operations);
  28. + }
  29. +
  30. err = ubifs_init_security(dir, inode, &dentry->d_name);
  31. if (err)
  32. goto out_inode;
  33. mutex_lock(&ui->ui_mutex);
  34. insert_inode_hash(inode);
  35. - d_tmpfile(dentry, inode);
  36. +
  37. + if (whiteout) {
  38. + mark_inode_dirty(inode);
  39. + drop_nlink(inode);
  40. + *whiteout = inode;
  41. + } else {
  42. + d_tmpfile(dentry, inode);
  43. + }
  44. ubifs_assert(ui->dirty);
  45. +
  46. instantiated = 1;
  47. mutex_unlock(&ui->ui_mutex);
  48. @@ -371,6 +384,12 @@ out_budg:
  49. return err;
  50. }
  51. +static int ubifs_tmpfile(struct inode *dir, struct dentry *dentry,
  52. + umode_t mode)
  53. +{
  54. + return do_tmpfile(dir, dentry, mode, NULL);
  55. +}
  56. +
  57. /**
  58. * vfs_dent_type - get VFS directory entry type.
  59. * @type: UBIFS directory entry type
  60. @@ -1003,37 +1022,43 @@ out_budg:
  61. }
  62. /**
  63. - * lock_3_inodes - a wrapper for locking three UBIFS inodes.
  64. + * lock_4_inodes - a wrapper for locking three UBIFS inodes.
  65. * @inode1: first inode
  66. * @inode2: second inode
  67. * @inode3: third inode
  68. + * @inode4: fouth inode
  69. *
  70. * This function is used for 'ubifs_rename()' and @inode1 may be the same as
  71. - * @inode2 whereas @inode3 may be %NULL.
  72. + * @inode2 whereas @inode3 and @inode4 may be %NULL.
  73. *
  74. * We do not implement any tricks to guarantee strict lock ordering, because
  75. * VFS has already done it for us on the @i_mutex. So this is just a simple
  76. * wrapper function.
  77. */
  78. -static void lock_3_inodes(struct inode *inode1, struct inode *inode2,
  79. - struct inode *inode3)
  80. +static void lock_4_inodes(struct inode *inode1, struct inode *inode2,
  81. + struct inode *inode3, struct inode *inode4)
  82. {
  83. mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
  84. if (inode2 != inode1)
  85. mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
  86. if (inode3)
  87. mutex_lock_nested(&ubifs_inode(inode3)->ui_mutex, WB_MUTEX_3);
  88. + if (inode4)
  89. + mutex_lock_nested(&ubifs_inode(inode4)->ui_mutex, WB_MUTEX_4);
  90. }
  91. /**
  92. - * unlock_3_inodes - a wrapper for unlocking three UBIFS inodes for rename.
  93. + * unlock_4_inodes - a wrapper for unlocking three UBIFS inodes for rename.
  94. * @inode1: first inode
  95. * @inode2: second inode
  96. * @inode3: third inode
  97. + * @inode4: fouth inode
  98. */
  99. -static void unlock_3_inodes(struct inode *inode1, struct inode *inode2,
  100. - struct inode *inode3)
  101. +static void unlock_4_inodes(struct inode *inode1, struct inode *inode2,
  102. + struct inode *inode3, struct inode *inode4)
  103. {
  104. + if (inode4)
  105. + mutex_unlock(&ubifs_inode(inode4)->ui_mutex);
  106. if (inode3)
  107. mutex_unlock(&ubifs_inode(inode3)->ui_mutex);
  108. if (inode1 != inode2)
  109. @@ -1042,12 +1067,15 @@ static void unlock_3_inodes(struct inode
  110. }
  111. static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
  112. - struct inode *new_dir, struct dentry *new_dentry)
  113. + struct inode *new_dir, struct dentry *new_dentry,
  114. + unsigned int flags)
  115. {
  116. struct ubifs_info *c = old_dir->i_sb->s_fs_info;
  117. struct inode *old_inode = d_inode(old_dentry);
  118. struct inode *new_inode = d_inode(new_dentry);
  119. + struct inode *whiteout = NULL;
  120. struct ubifs_inode *old_inode_ui = ubifs_inode(old_inode);
  121. + struct ubifs_inode *whiteout_ui = NULL;
  122. int err, release, sync = 0, move = (new_dir != old_dir);
  123. int is_dir = S_ISDIR(old_inode->i_mode);
  124. int unlink = !!new_inode;
  125. @@ -1069,9 +1097,13 @@ static int ubifs_rename(struct inode *ol
  126. * separately.
  127. */
  128. - dbg_gen("dent '%pd' ino %lu in dir ino %lu to dent '%pd' in dir ino %lu",
  129. + dbg_gen("dent '%pd' ino %lu in dir ino %lu to dent '%pd' in dir ino %lu flags 0x%x",
  130. old_dentry, old_inode->i_ino, old_dir->i_ino,
  131. - new_dentry, new_dir->i_ino);
  132. + new_dentry, new_dir->i_ino, flags);
  133. +
  134. + if (flags & ~(RENAME_NOREPLACE | RENAME_WHITEOUT))
  135. + return -EINVAL;
  136. +
  137. ubifs_assert(mutex_is_locked(&old_dir->i_mutex));
  138. ubifs_assert(mutex_is_locked(&new_dir->i_mutex));
  139. if (unlink)
  140. @@ -1093,7 +1125,32 @@ static int ubifs_rename(struct inode *ol
  141. return err;
  142. }
  143. - lock_3_inodes(old_dir, new_dir, new_inode);
  144. + if (flags & RENAME_WHITEOUT) {
  145. + union ubifs_dev_desc *dev = NULL;
  146. +
  147. + dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);
  148. + if (!dev) {
  149. + ubifs_release_budget(c, &req);
  150. + ubifs_release_budget(c, &ino_req);
  151. + return -ENOMEM;
  152. + }
  153. +
  154. + err = do_tmpfile(old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, &whiteout);
  155. + if (err) {
  156. + ubifs_release_budget(c, &req);
  157. + ubifs_release_budget(c, &ino_req);
  158. + kfree(dev);
  159. + return err;
  160. + }
  161. +
  162. + whiteout->i_state |= I_LINKABLE;
  163. + whiteout_ui = ubifs_inode(whiteout);
  164. + whiteout_ui->data = dev;
  165. + whiteout_ui->data_len = ubifs_encode_dev(dev, MKDEV(0, 0));
  166. + ubifs_assert(!whiteout_ui->dirty);
  167. + }
  168. +
  169. + lock_4_inodes(old_dir, new_dir, new_inode, whiteout);
  170. /*
  171. * Like most other Unix systems, set the @i_ctime for inodes on a
  172. @@ -1163,12 +1220,34 @@ static int ubifs_rename(struct inode *ol
  173. if (unlink && IS_SYNC(new_inode))
  174. sync = 1;
  175. }
  176. - err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry,
  177. +
  178. + if (whiteout) {
  179. + struct ubifs_budget_req wht_req = { .dirtied_ino = 1,
  180. + .dirtied_ino_d = \
  181. + ALIGN(ubifs_inode(whiteout)->data_len, 8) };
  182. +
  183. + err = ubifs_budget_space(c, &wht_req);
  184. + if (err) {
  185. + ubifs_release_budget(c, &req);
  186. + ubifs_release_budget(c, &ino_req);
  187. + kfree(whiteout_ui->data);
  188. + whiteout_ui->data_len = 0;
  189. + iput(whiteout);
  190. + return err;
  191. + }
  192. +
  193. + inc_nlink(whiteout);
  194. + mark_inode_dirty(whiteout);
  195. + whiteout->i_state &= ~I_LINKABLE;
  196. + iput(whiteout);
  197. + }
  198. +
  199. + err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry, whiteout,
  200. sync);
  201. if (err)
  202. goto out_cancel;
  203. - unlock_3_inodes(old_dir, new_dir, new_inode);
  204. + unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
  205. ubifs_release_budget(c, &req);
  206. mutex_lock(&old_inode_ui->ui_mutex);
  207. @@ -1201,7 +1280,11 @@ out_cancel:
  208. inc_nlink(old_dir);
  209. }
  210. }
  211. - unlock_3_inodes(old_dir, new_dir, new_inode);
  212. + if (whiteout) {
  213. + drop_nlink(whiteout);
  214. + iput(whiteout);
  215. + }
  216. + unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
  217. ubifs_release_budget(c, &ino_req);
  218. ubifs_release_budget(c, &req);
  219. return err;
  220. @@ -1255,7 +1338,7 @@ const struct inode_operations ubifs_dir_
  221. .mkdir = ubifs_mkdir,
  222. .rmdir = ubifs_rmdir,
  223. .mknod = ubifs_mknod,
  224. - .rename = ubifs_rename,
  225. + .rename2 = ubifs_rename,
  226. .setattr = ubifs_setattr,
  227. .getattr = ubifs_getattr,
  228. .setxattr = ubifs_setxattr,
  229. --- a/fs/ubifs/journal.c
  230. +++ b/fs/ubifs/journal.c
  231. @@ -917,14 +917,15 @@ int ubifs_jnl_delete_inode(struct ubifs_
  232. * @sync: non-zero if the write-buffer has to be synchronized
  233. *
  234. * This function implements the re-name operation which may involve writing up
  235. - * to 3 inodes and 2 directory entries. It marks the written inodes as clean
  236. + * to 4 inodes and 2 directory entries. It marks the written inodes as clean
  237. * and returns zero on success. In case of failure, a negative error code is
  238. * returned.
  239. */
  240. int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
  241. const struct dentry *old_dentry,
  242. const struct inode *new_dir,
  243. - const struct dentry *new_dentry, int sync)
  244. + const struct dentry *new_dentry,
  245. + const struct inode *whiteout, int sync)
  246. {
  247. void *p;
  248. union ubifs_key key;
  249. @@ -980,13 +981,19 @@ int ubifs_jnl_rename(struct ubifs_info *
  250. zero_dent_node_unused(dent);
  251. ubifs_prep_grp_node(c, dent, dlen1, 0);
  252. - /* Make deletion dent */
  253. dent2 = (void *)dent + aligned_dlen1;
  254. dent2->ch.node_type = UBIFS_DENT_NODE;
  255. dent_key_init_flash(c, &dent2->key, old_dir->i_ino,
  256. &old_dentry->d_name);
  257. - dent2->inum = 0;
  258. - dent2->type = DT_UNKNOWN;
  259. +
  260. + if (whiteout) {
  261. + dent2->inum = cpu_to_le64(whiteout->i_ino);
  262. + dent2->type = get_dent_type(whiteout->i_mode);
  263. + } else {
  264. + /* Make deletion dent */
  265. + dent2->inum = 0;
  266. + dent2->type = DT_UNKNOWN;
  267. + }
  268. dent2->nlen = cpu_to_le16(old_dentry->d_name.len);
  269. memcpy(dent2->name, old_dentry->d_name.name, old_dentry->d_name.len);
  270. dent2->name[old_dentry->d_name.len] = '\0';
  271. @@ -1035,16 +1042,26 @@ int ubifs_jnl_rename(struct ubifs_info *
  272. if (err)
  273. goto out_ro;
  274. - err = ubifs_add_dirt(c, lnum, dlen2);
  275. - if (err)
  276. - goto out_ro;
  277. -
  278. - dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name);
  279. - err = ubifs_tnc_remove_nm(c, &key, &old_dentry->d_name);
  280. - if (err)
  281. - goto out_ro;
  282. + offs += aligned_dlen1;
  283. + if (whiteout) {
  284. + dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name);
  285. + err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen2, &old_dentry->d_name);
  286. + if (err)
  287. + goto out_ro;
  288. +
  289. + ubifs_delete_orphan(c, whiteout->i_ino);
  290. + } else {
  291. + err = ubifs_add_dirt(c, lnum, dlen2);
  292. + if (err)
  293. + goto out_ro;
  294. +
  295. + dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name);
  296. + err = ubifs_tnc_remove_nm(c, &key, &old_dentry->d_name);
  297. + if (err)
  298. + goto out_ro;
  299. + }
  300. - offs += aligned_dlen1 + aligned_dlen2;
  301. + offs += aligned_dlen2;
  302. if (new_inode) {
  303. ino_key_init(c, &key, new_inode->i_ino);
  304. err = ubifs_tnc_add(c, &key, lnum, offs, ilen);
  305. --- a/fs/ubifs/ubifs.h
  306. +++ b/fs/ubifs/ubifs.h
  307. @@ -180,6 +180,7 @@ enum {
  308. WB_MUTEX_1 = 0,
  309. WB_MUTEX_2 = 1,
  310. WB_MUTEX_3 = 2,
  311. + WB_MUTEX_4 = 3,
  312. };
  313. /*
  314. @@ -1546,7 +1547,8 @@ int ubifs_jnl_delete_inode(struct ubifs_
  315. int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
  316. const struct dentry *old_dentry,
  317. const struct inode *new_dir,
  318. - const struct dentry *new_dentry, int sync);
  319. + const struct dentry *new_dentry,
  320. + const struct inode *whiteout, int sync);
  321. int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
  322. loff_t old_size, loff_t new_size);
  323. int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,