|
14 | 14 | #include <linux/types.h>
|
15 | 15 | #include <linux/version.h>
|
16 | 16 |
|
17 |
| -#include "vvsfs.h" |
18 | 17 | #include "logging.h"
|
| 18 | +#include "vvsfs.h" |
19 | 19 |
|
20 | 20 | struct inode *vvsfs_iget(struct super_block *sb, unsigned long ino);
|
21 | 21 |
|
@@ -215,9 +215,9 @@ static int vvsfs_find_entry_indirect(struct vvsfs_inode_info *vi,
|
215 | 215 | * otherwise and error
|
216 | 216 | */
|
217 | 217 | int vvsfs_find_entry(struct inode *dir,
|
218 |
| - struct dentry *dentry, |
219 |
| - unsigned flags, |
220 |
| - struct bufloc_t *out_loc) { |
| 218 | + struct dentry *dentry, |
| 219 | + unsigned flags, |
| 220 | + struct bufloc_t *out_loc) { |
221 | 221 | struct vvsfs_inode_info *vi;
|
222 | 222 | struct super_block *sb;
|
223 | 223 | int result;
|
@@ -670,6 +670,13 @@ int vvsfs_free_inode_blocks(struct inode *inode) {
|
670 | 670 |
|
671 | 671 | DEBUG_LOG("vvsfs - free inode blocks - %lu", inode->i_ino);
|
672 | 672 |
|
| 673 | + if (inode->i_nlink != 0) { |
| 674 | + DEBUG_LOG( |
| 675 | + "vvsfs - free inode blocks called on allocated inode (links %u)", |
| 676 | + inode->i_nlink); |
| 677 | + return -EIO; |
| 678 | + } |
| 679 | + |
673 | 680 | vi = VVSFS_I(inode);
|
674 | 681 | sb = inode->i_sb;
|
675 | 682 | i_sb = sb->s_fs_info;
|
@@ -699,6 +706,21 @@ int vvsfs_free_inode_blocks(struct inode *inode) {
|
699 | 706 | return 0;
|
700 | 707 | }
|
701 | 708 |
|
| 709 | +/* Drops the link count of a given inode and frees the resources if applicable |
| 710 | + * |
| 711 | + * @inode: Target inode to drop link count of |
| 712 | + * |
| 713 | + * @return: (int) 0 if successful, error otherwise |
| 714 | + */ |
| 715 | +int vvsfs_drop_inode_link(struct inode *inode) { |
| 716 | + DEBUG_LOG("vvsfs - drop inode link"); |
| 717 | + inode_dec_link_count(inode); |
| 718 | + if (inode->i_nlink == 0) { |
| 719 | + return vvsfs_free_inode_blocks(inode); |
| 720 | + } |
| 721 | + return 0; |
| 722 | +} |
| 723 | + |
702 | 724 | /* Calculate the data block map index for a given position
|
703 | 725 | * within the given inode data blocks.
|
704 | 726 | *
|
@@ -1079,7 +1101,7 @@ vvsfs_create(struct mnt_idmap *namespace,
|
1079 | 1101 | if (ret != 0) {
|
1080 | 1102 | DEBUG_LOG("vvsfs - create - failed to create new entry for intial data "
|
1081 | 1103 | "block\n");
|
1082 |
| - vvsfs_free_inode_blocks(inode); |
| 1104 | + vvsfs_drop_inode_link(inode); |
1083 | 1105 | discard_new_inode(inode);
|
1084 | 1106 | return ret;
|
1085 | 1107 | }
|
@@ -1360,16 +1382,15 @@ static int vvsfs_unlink(struct inode *dir, struct dentry *dentry) {
|
1360 | 1382 | "entry\n");
|
1361 | 1383 | return err;
|
1362 | 1384 | }
|
1363 |
| - err = vvsfs_free_inode_blocks(inode); |
| 1385 | + |
| 1386 | + inode->i_ctime = dir->i_ctime; |
| 1387 | + |
| 1388 | + err = vvsfs_drop_inode_link(inode); |
1364 | 1389 | if (err) {
|
1365 | 1390 | DEBUG_LOG("vvsfs - unlink - failed to free inode blocks\n");
|
1366 | 1391 | return err;
|
1367 | 1392 | }
|
1368 |
| - inode->i_ctime = dir->i_ctime; |
1369 |
| - DEBUG_LOG("vvsfs - unlink - link count before: %u\n", inode->i_nlink); |
1370 |
| - inode_dec_link_count(inode); |
1371 |
| - DEBUG_LOG("vvsfs - unlink - link count after: %u\n", inode->i_nlink); |
1372 |
| - mark_inode_dirty(inode); |
| 1393 | + |
1373 | 1394 | DEBUG_LOG("vvsfs - unlink - done\n");
|
1374 | 1395 | return err;
|
1375 | 1396 | }
|
@@ -1508,7 +1529,6 @@ vvsfs_symlink(struct mnt_idmap *namespace,
|
1508 | 1529 | struct dentry *dentry,
|
1509 | 1530 | const char *symname) {
|
1510 | 1531 | struct vvsfs_inode_info *dir_info;
|
1511 |
| - int ret; |
1512 | 1532 | int err;
|
1513 | 1533 | struct buffer_head *bh;
|
1514 | 1534 | struct inode *inode;
|
@@ -1536,18 +1556,18 @@ vvsfs_symlink(struct mnt_idmap *namespace,
|
1536 | 1556 |
|
1537 | 1557 | err = page_symlink(inode, symname, strlen(symname) + 1);
|
1538 | 1558 | if (err) {
|
1539 |
| - vvsfs_free_inode_blocks(inode); |
| 1559 | + vvsfs_drop_inode_link(inode); |
1540 | 1560 | discard_new_inode(inode);
|
1541 | 1561 | return err;
|
1542 | 1562 | }
|
1543 | 1563 |
|
1544 | 1564 | // add the file/directory to the parent directory's list
|
1545 | 1565 | // of entries -- on disk.
|
1546 |
| - ret = vvsfs_add_new_entry(dir, dentry, inode); |
1547 |
| - if (ret != 0) { |
1548 |
| - vvsfs_free_inode_blocks(inode); |
| 1566 | + err = vvsfs_add_new_entry(dir, dentry, inode); |
| 1567 | + if (err != 0) { |
| 1568 | + vvsfs_drop_inode_link(inode); |
1549 | 1569 | discard_new_inode(inode);
|
1550 |
| - return ret; |
| 1570 | + return err; |
1551 | 1571 | }
|
1552 | 1572 |
|
1553 | 1573 | d_instantiate(dentry, inode);
|
@@ -1599,7 +1619,7 @@ static int vvsfs_mknod(struct user_namespace *mnt_userns,
|
1599 | 1619 | // of entries -- on disk.
|
1600 | 1620 | ret = vvsfs_add_new_entry(dir, dentry, inode);
|
1601 | 1621 | if (ret != 0) {
|
1602 |
| - vvsfs_free_inode_blocks(inode); |
| 1622 | + vvsfs_drop_inode_link(inode); |
1603 | 1623 | discard_new_inode(inode);
|
1604 | 1624 | return ret;
|
1605 | 1625 | }
|
@@ -1650,15 +1670,13 @@ static int vvsfs_dentry_exchange_inode(struct inode *dir,
|
1650 | 1670 | dir->i_mtime = dir->i_ctime = current_time(dir);
|
1651 | 1671 | mark_inode_dirty(dir);
|
1652 | 1672 |
|
1653 |
| - // Drop the link count of the inode that was originally pointed to by this |
1654 |
| - // dentry, so that it can possibly be deleted |
| 1673 | + // Update inode create time |
1655 | 1674 | existing_inode->i_ctime = current_time(existing_inode);
|
1656 |
| - DEBUG_LOG("vvsfs - rename - new_inode link count before: %u\n", |
1657 |
| - existing_inode->i_nlink); |
1658 |
| - inode_dec_link_count(existing_inode); |
1659 |
| - DEBUG_LOG("vvsfs - rename - new_inode link count after: %u\n", |
1660 |
| - existing_inode->i_nlink); |
1661 |
| - mark_inode_dirty(existing_inode); |
| 1675 | + |
| 1676 | + // Drop the link count of the inode that was originally pointed to by this |
| 1677 | + // dentry |
| 1678 | + vvsfs_drop_inode_link(existing_inode); |
| 1679 | + |
1662 | 1680 | return 0;
|
1663 | 1681 | }
|
1664 | 1682 |
|
|
0 commit comments