diff options
Diffstat (limited to 'fs/ubifs/journal.c')
| -rw-r--r-- | fs/ubifs/journal.c | 110 |
1 files changed, 82 insertions, 28 deletions
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 283155abe5f5..22993f867d19 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c | |||
| @@ -447,13 +447,11 @@ static int get_dent_type(int mode) | |||
| 447 | * @ino: buffer in which to pack inode node | 447 | * @ino: buffer in which to pack inode node |
| 448 | * @inode: inode to pack | 448 | * @inode: inode to pack |
| 449 | * @last: indicates the last node of the group | 449 | * @last: indicates the last node of the group |
| 450 | * @last_reference: non-zero if this is a deletion inode | ||
| 451 | */ | 450 | */ |
| 452 | static void pack_inode(struct ubifs_info *c, struct ubifs_ino_node *ino, | 451 | static void pack_inode(struct ubifs_info *c, struct ubifs_ino_node *ino, |
| 453 | const struct inode *inode, int last, | 452 | const struct inode *inode, int last) |
| 454 | int last_reference) | ||
| 455 | { | 453 | { |
| 456 | int data_len = 0; | 454 | int data_len = 0, last_reference = !inode->i_nlink; |
| 457 | struct ubifs_inode *ui = ubifs_inode(inode); | 455 | struct ubifs_inode *ui = ubifs_inode(inode); |
| 458 | 456 | ||
| 459 | ino->ch.node_type = UBIFS_INO_NODE; | 457 | ino->ch.node_type = UBIFS_INO_NODE; |
| @@ -596,9 +594,9 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, | |||
| 596 | ubifs_prep_grp_node(c, dent, dlen, 0); | 594 | ubifs_prep_grp_node(c, dent, dlen, 0); |
| 597 | 595 | ||
| 598 | ino = (void *)dent + aligned_dlen; | 596 | ino = (void *)dent + aligned_dlen; |
| 599 | pack_inode(c, ino, inode, 0, last_reference); | 597 | pack_inode(c, ino, inode, 0); |
| 600 | ino = (void *)ino + aligned_ilen; | 598 | ino = (void *)ino + aligned_ilen; |
| 601 | pack_inode(c, ino, dir, 1, 0); | 599 | pack_inode(c, ino, dir, 1); |
| 602 | 600 | ||
| 603 | if (last_reference) { | 601 | if (last_reference) { |
| 604 | err = ubifs_add_orphan(c, inode->i_ino); | 602 | err = ubifs_add_orphan(c, inode->i_ino); |
| @@ -606,6 +604,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, | |||
| 606 | release_head(c, BASEHD); | 604 | release_head(c, BASEHD); |
| 607 | goto out_finish; | 605 | goto out_finish; |
| 608 | } | 606 | } |
| 607 | ui->del_cmtno = c->cmt_no; | ||
| 609 | } | 608 | } |
| 610 | 609 | ||
| 611 | err = write_head(c, BASEHD, dent, len, &lnum, &dent_offs, sync); | 610 | err = write_head(c, BASEHD, dent, len, &lnum, &dent_offs, sync); |
| @@ -750,30 +749,25 @@ out_free: | |||
| 750 | * ubifs_jnl_write_inode - flush inode to the journal. | 749 | * ubifs_jnl_write_inode - flush inode to the journal. |
| 751 | * @c: UBIFS file-system description object | 750 | * @c: UBIFS file-system description object |
| 752 | * @inode: inode to flush | 751 | * @inode: inode to flush |
| 753 | * @deletion: inode has been deleted | ||
| 754 | * | 752 | * |
| 755 | * This function writes inode @inode to the journal. If the inode is | 753 | * This function writes inode @inode to the journal. If the inode is |
| 756 | * synchronous, it also synchronizes the write-buffer. Returns zero in case of | 754 | * synchronous, it also synchronizes the write-buffer. Returns zero in case of |
| 757 | * success and a negative error code in case of failure. | 755 | * success and a negative error code in case of failure. |
| 758 | */ | 756 | */ |
| 759 | int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode, | 757 | int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode) |
| 760 | int deletion) | ||
| 761 | { | 758 | { |
| 762 | int err, len, lnum, offs, sync = 0; | 759 | int err, lnum, offs; |
| 763 | struct ubifs_ino_node *ino; | 760 | struct ubifs_ino_node *ino; |
| 764 | struct ubifs_inode *ui = ubifs_inode(inode); | 761 | struct ubifs_inode *ui = ubifs_inode(inode); |
| 762 | int sync = 0, len = UBIFS_INO_NODE_SZ, last_reference = !inode->i_nlink; | ||
| 765 | 763 | ||
| 766 | dbg_jnl("ino %lu%s", inode->i_ino, | 764 | dbg_jnl("ino %lu, nlink %u", inode->i_ino, inode->i_nlink); |
| 767 | deletion ? " (last reference)" : ""); | ||
| 768 | if (deletion) | ||
| 769 | ubifs_assert(inode->i_nlink == 0); | ||
| 770 | 765 | ||
| 771 | len = UBIFS_INO_NODE_SZ; | ||
| 772 | /* | 766 | /* |
| 773 | * If the inode is being deleted, do not write the attached data. No | 767 | * If the inode is being deleted, do not write the attached data. No |
| 774 | * need to synchronize the write-buffer either. | 768 | * need to synchronize the write-buffer either. |
| 775 | */ | 769 | */ |
| 776 | if (!deletion) { | 770 | if (!last_reference) { |
| 777 | len += ui->data_len; | 771 | len += ui->data_len; |
| 778 | sync = IS_SYNC(inode); | 772 | sync = IS_SYNC(inode); |
| 779 | } | 773 | } |
| @@ -786,7 +780,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode, | |||
| 786 | if (err) | 780 | if (err) |
| 787 | goto out_free; | 781 | goto out_free; |
| 788 | 782 | ||
| 789 | pack_inode(c, ino, inode, 1, deletion); | 783 | pack_inode(c, ino, inode, 1); |
| 790 | err = write_head(c, BASEHD, ino, len, &lnum, &offs, sync); | 784 | err = write_head(c, BASEHD, ino, len, &lnum, &offs, sync); |
| 791 | if (err) | 785 | if (err) |
| 792 | goto out_release; | 786 | goto out_release; |
| @@ -795,7 +789,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode, | |||
| 795 | inode->i_ino); | 789 | inode->i_ino); |
| 796 | release_head(c, BASEHD); | 790 | release_head(c, BASEHD); |
| 797 | 791 | ||
| 798 | if (deletion) { | 792 | if (last_reference) { |
| 799 | err = ubifs_tnc_remove_ino(c, inode->i_ino); | 793 | err = ubifs_tnc_remove_ino(c, inode->i_ino); |
| 800 | if (err) | 794 | if (err) |
| 801 | goto out_ro; | 795 | goto out_ro; |
| @@ -828,6 +822,65 @@ out_free: | |||
| 828 | } | 822 | } |
| 829 | 823 | ||
| 830 | /** | 824 | /** |
| 825 | * ubifs_jnl_delete_inode - delete an inode. | ||
| 826 | * @c: UBIFS file-system description object | ||
| 827 | * @inode: inode to delete | ||
| 828 | * | ||
| 829 | * This function deletes inode @inode which includes removing it from orphans, | ||
| 830 | * deleting it from TNC and, in some cases, writing a deletion inode to the | ||
| 831 | * journal. | ||
| 832 | * | ||
| 833 | * When regular file inodes are unlinked or a directory inode is removed, the | ||
| 834 | * 'ubifs_jnl_update()' function writes a corresponding deletion inode and | ||
| 835 | * direntry to the media, and adds the inode to orphans. After this, when the | ||
| 836 | * last reference to this inode has been dropped, this function is called. In | ||
| 837 | * general, it has to write one more deletion inode to the media, because if | ||
| 838 | * a commit happened between 'ubifs_jnl_update()' and | ||
| 839 | * 'ubifs_jnl_delete_inode()', the deletion inode is not in the journal | ||
| 840 | * anymore, and in fact it might not be on the flash anymore, because it might | ||
| 841 | * have been garbage-collected already. And for optimization reasons UBIFS does | ||
| 842 | * not read the orphan area if it has been unmounted cleanly, so it would have | ||
| 843 | * no indication in the journal that there is a deleted inode which has to be | ||
| 844 | * removed from TNC. | ||
| 845 | * | ||
| 846 | * However, if there was no commit between 'ubifs_jnl_update()' and | ||
| 847 | * 'ubifs_jnl_delete_inode()', then there is no need to write the deletion | ||
| 848 | * inode to the media for the second time. And this is quite a typical case. | ||
| 849 | * | ||
| 850 | * This function returns zero in case of success and a negative error code in | ||
| 851 | * case of failure. | ||
| 852 | */ | ||
| 853 | int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode) | ||
| 854 | { | ||
| 855 | int err; | ||
| 856 | struct ubifs_inode *ui = ubifs_inode(inode); | ||
| 857 | |||
| 858 | ubifs_assert(inode->i_nlink == 0); | ||
| 859 | |||
| 860 | if (ui->del_cmtno != c->cmt_no) | ||
| 861 | /* A commit happened for sure */ | ||
| 862 | return ubifs_jnl_write_inode(c, inode); | ||
| 863 | |||
| 864 | down_read(&c->commit_sem); | ||
| 865 | /* | ||
| 866 | * Check commit number again, because the first test has been done | ||
| 867 | * without @c->commit_sem, so a commit might have happened. | ||
| 868 | */ | ||
| 869 | if (ui->del_cmtno != c->cmt_no) { | ||
| 870 | up_read(&c->commit_sem); | ||
| 871 | return ubifs_jnl_write_inode(c, inode); | ||
| 872 | } | ||
| 873 | |||
| 874 | err = ubifs_tnc_remove_ino(c, inode->i_ino); | ||
| 875 | if (err) | ||
| 876 | ubifs_ro_mode(c, err); | ||
| 877 | else | ||
| 878 | ubifs_delete_orphan(c, inode->i_ino); | ||
| 879 | up_read(&c->commit_sem); | ||
| 880 | return err; | ||
| 881 | } | ||
| 882 | |||
| 883 | /** | ||
| 831 | * ubifs_jnl_rename - rename a directory entry. | 884 | * ubifs_jnl_rename - rename a directory entry. |
| 832 | * @c: UBIFS file-system description object | 885 | * @c: UBIFS file-system description object |
| 833 | * @old_dir: parent inode of directory entry to rename | 886 | * @old_dir: parent inode of directory entry to rename |
| @@ -917,16 +970,16 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, | |||
| 917 | 970 | ||
| 918 | p = (void *)dent2 + aligned_dlen2; | 971 | p = (void *)dent2 + aligned_dlen2; |
| 919 | if (new_inode) { | 972 | if (new_inode) { |
| 920 | pack_inode(c, p, new_inode, 0, last_reference); | 973 | pack_inode(c, p, new_inode, 0); |
| 921 | p += ALIGN(ilen, 8); | 974 | p += ALIGN(ilen, 8); |
| 922 | } | 975 | } |
| 923 | 976 | ||
| 924 | if (!move) | 977 | if (!move) |
| 925 | pack_inode(c, p, old_dir, 1, 0); | 978 | pack_inode(c, p, old_dir, 1); |
| 926 | else { | 979 | else { |
| 927 | pack_inode(c, p, old_dir, 0, 0); | 980 | pack_inode(c, p, old_dir, 0); |
| 928 | p += ALIGN(plen, 8); | 981 | p += ALIGN(plen, 8); |
| 929 | pack_inode(c, p, new_dir, 1, 0); | 982 | pack_inode(c, p, new_dir, 1); |
| 930 | } | 983 | } |
| 931 | 984 | ||
| 932 | if (last_reference) { | 985 | if (last_reference) { |
| @@ -935,6 +988,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, | |||
| 935 | release_head(c, BASEHD); | 988 | release_head(c, BASEHD); |
| 936 | goto out_finish; | 989 | goto out_finish; |
| 937 | } | 990 | } |
| 991 | new_ui->del_cmtno = c->cmt_no; | ||
| 938 | } | 992 | } |
| 939 | 993 | ||
| 940 | err = write_head(c, BASEHD, dent, len, &lnum, &offs, sync); | 994 | err = write_head(c, BASEHD, dent, len, &lnum, &offs, sync); |
| @@ -1131,7 +1185,7 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode, | |||
| 1131 | if (err) | 1185 | if (err) |
| 1132 | goto out_free; | 1186 | goto out_free; |
| 1133 | 1187 | ||
| 1134 | pack_inode(c, ino, inode, 0, 0); | 1188 | pack_inode(c, ino, inode, 0); |
| 1135 | ubifs_prep_grp_node(c, trun, UBIFS_TRUN_NODE_SZ, dlen ? 0 : 1); | 1189 | ubifs_prep_grp_node(c, trun, UBIFS_TRUN_NODE_SZ, dlen ? 0 : 1); |
| 1136 | if (dlen) | 1190 | if (dlen) |
| 1137 | ubifs_prep_grp_node(c, dn, dlen, 1); | 1191 | ubifs_prep_grp_node(c, dn, dlen, 1); |
| @@ -1251,9 +1305,9 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host, | |||
| 1251 | ubifs_prep_grp_node(c, xent, xlen, 0); | 1305 | ubifs_prep_grp_node(c, xent, xlen, 0); |
| 1252 | 1306 | ||
| 1253 | ino = (void *)xent + aligned_xlen; | 1307 | ino = (void *)xent + aligned_xlen; |
| 1254 | pack_inode(c, ino, inode, 0, 1); | 1308 | pack_inode(c, ino, inode, 0); |
| 1255 | ino = (void *)ino + UBIFS_INO_NODE_SZ; | 1309 | ino = (void *)ino + UBIFS_INO_NODE_SZ; |
| 1256 | pack_inode(c, ino, host, 1, 0); | 1310 | pack_inode(c, ino, host, 1); |
| 1257 | 1311 | ||
| 1258 | err = write_head(c, BASEHD, xent, len, &lnum, &xent_offs, sync); | 1312 | err = write_head(c, BASEHD, xent, len, &lnum, &xent_offs, sync); |
| 1259 | if (!sync && !err) | 1313 | if (!sync && !err) |
| @@ -1320,7 +1374,7 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode, | |||
| 1320 | const struct inode *host) | 1374 | const struct inode *host) |
| 1321 | { | 1375 | { |
| 1322 | int err, len1, len2, aligned_len, aligned_len1, lnum, offs; | 1376 | int err, len1, len2, aligned_len, aligned_len1, lnum, offs; |
| 1323 | struct ubifs_inode *host_ui = ubifs_inode(inode); | 1377 | struct ubifs_inode *host_ui = ubifs_inode(host); |
| 1324 | struct ubifs_ino_node *ino; | 1378 | struct ubifs_ino_node *ino; |
| 1325 | union ubifs_key key; | 1379 | union ubifs_key key; |
| 1326 | int sync = IS_DIRSYNC(host); | 1380 | int sync = IS_DIRSYNC(host); |
| @@ -1344,8 +1398,8 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode, | |||
| 1344 | if (err) | 1398 | if (err) |
| 1345 | goto out_free; | 1399 | goto out_free; |
| 1346 | 1400 | ||
| 1347 | pack_inode(c, ino, host, 0, 0); | 1401 | pack_inode(c, ino, host, 0); |
| 1348 | pack_inode(c, (void *)ino + aligned_len1, inode, 1, 0); | 1402 | pack_inode(c, (void *)ino + aligned_len1, inode, 1); |
| 1349 | 1403 | ||
| 1350 | err = write_head(c, BASEHD, ino, aligned_len, &lnum, &offs, 0); | 1404 | err = write_head(c, BASEHD, ino, aligned_len, &lnum, &offs, 0); |
| 1351 | if (!sync && !err) { | 1405 | if (!sync && !err) { |
