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) { |