diff options
Diffstat (limited to 'fs/ocfs2/namei.c')
-rw-r--r-- | fs/ocfs2/namei.c | 341 |
1 files changed, 311 insertions, 30 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 8601f934010b..f010b22b1c44 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -69,7 +69,6 @@ | |||
69 | static int ocfs2_mknod_locked(struct ocfs2_super *osb, | 69 | static int ocfs2_mknod_locked(struct ocfs2_super *osb, |
70 | struct inode *dir, | 70 | struct inode *dir, |
71 | struct inode *inode, | 71 | struct inode *inode, |
72 | struct dentry *dentry, | ||
73 | dev_t dev, | 72 | dev_t dev, |
74 | struct buffer_head **new_fe_bh, | 73 | struct buffer_head **new_fe_bh, |
75 | struct buffer_head *parent_fe_bh, | 74 | struct buffer_head *parent_fe_bh, |
@@ -78,7 +77,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
78 | 77 | ||
79 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | 78 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, |
80 | struct inode **ret_orphan_dir, | 79 | struct inode **ret_orphan_dir, |
81 | struct inode *inode, | 80 | u64 blkno, |
82 | char *name, | 81 | char *name, |
83 | struct ocfs2_dir_lookup_result *lookup); | 82 | struct ocfs2_dir_lookup_result *lookup); |
84 | 83 | ||
@@ -358,8 +357,12 @@ static int ocfs2_mknod(struct inode *dir, | |||
358 | } | 357 | } |
359 | did_quota_inode = 1; | 358 | did_quota_inode = 1; |
360 | 359 | ||
360 | mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, | ||
361 | inode->i_mode, (unsigned long)dev, dentry->d_name.len, | ||
362 | dentry->d_name.name); | ||
363 | |||
361 | /* do the real work now. */ | 364 | /* do the real work now. */ |
362 | status = ocfs2_mknod_locked(osb, dir, inode, dentry, dev, | 365 | status = ocfs2_mknod_locked(osb, dir, inode, dev, |
363 | &new_fe_bh, parent_fe_bh, handle, | 366 | &new_fe_bh, parent_fe_bh, handle, |
364 | inode_ac); | 367 | inode_ac); |
365 | if (status < 0) { | 368 | if (status < 0) { |
@@ -375,7 +378,8 @@ static int ocfs2_mknod(struct inode *dir, | |||
375 | goto leave; | 378 | goto leave; |
376 | } | 379 | } |
377 | 380 | ||
378 | status = ocfs2_journal_access_di(handle, dir, parent_fe_bh, | 381 | status = ocfs2_journal_access_di(handle, INODE_CACHE(dir), |
382 | parent_fe_bh, | ||
379 | OCFS2_JOURNAL_ACCESS_WRITE); | 383 | OCFS2_JOURNAL_ACCESS_WRITE); |
380 | if (status < 0) { | 384 | if (status < 0) { |
381 | mlog_errno(status); | 385 | mlog_errno(status); |
@@ -465,7 +469,6 @@ leave: | |||
465 | static int ocfs2_mknod_locked(struct ocfs2_super *osb, | 469 | static int ocfs2_mknod_locked(struct ocfs2_super *osb, |
466 | struct inode *dir, | 470 | struct inode *dir, |
467 | struct inode *inode, | 471 | struct inode *inode, |
468 | struct dentry *dentry, | ||
469 | dev_t dev, | 472 | dev_t dev, |
470 | struct buffer_head **new_fe_bh, | 473 | struct buffer_head **new_fe_bh, |
471 | struct buffer_head *parent_fe_bh, | 474 | struct buffer_head *parent_fe_bh, |
@@ -479,10 +482,6 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
479 | u16 suballoc_bit; | 482 | u16 suballoc_bit; |
480 | u16 feat; | 483 | u16 feat; |
481 | 484 | ||
482 | mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, | ||
483 | inode->i_mode, (unsigned long)dev, dentry->d_name.len, | ||
484 | dentry->d_name.name); | ||
485 | |||
486 | *new_fe_bh = NULL; | 485 | *new_fe_bh = NULL; |
487 | 486 | ||
488 | status = ocfs2_claim_new_inode(osb, handle, dir, parent_fe_bh, | 487 | status = ocfs2_claim_new_inode(osb, handle, dir, parent_fe_bh, |
@@ -507,9 +506,10 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
507 | mlog_errno(status); | 506 | mlog_errno(status); |
508 | goto leave; | 507 | goto leave; |
509 | } | 508 | } |
510 | ocfs2_set_new_buffer_uptodate(inode, *new_fe_bh); | 509 | ocfs2_set_new_buffer_uptodate(INODE_CACHE(inode), *new_fe_bh); |
511 | 510 | ||
512 | status = ocfs2_journal_access_di(handle, inode, *new_fe_bh, | 511 | status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), |
512 | *new_fe_bh, | ||
513 | OCFS2_JOURNAL_ACCESS_CREATE); | 513 | OCFS2_JOURNAL_ACCESS_CREATE); |
514 | if (status < 0) { | 514 | if (status < 0) { |
515 | mlog_errno(status); | 515 | mlog_errno(status); |
@@ -565,7 +565,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
565 | } | 565 | } |
566 | 566 | ||
567 | ocfs2_populate_inode(inode, fe, 1); | 567 | ocfs2_populate_inode(inode, fe, 1); |
568 | ocfs2_inode_set_new(osb, inode); | 568 | ocfs2_ci_set_new(osb, INODE_CACHE(inode)); |
569 | if (!ocfs2_mount_local(osb)) { | 569 | if (!ocfs2_mount_local(osb)) { |
570 | status = ocfs2_create_new_inode_locks(inode); | 570 | status = ocfs2_create_new_inode_locks(inode); |
571 | if (status < 0) | 571 | if (status < 0) |
@@ -682,7 +682,7 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
682 | goto out_unlock_inode; | 682 | goto out_unlock_inode; |
683 | } | 683 | } |
684 | 684 | ||
685 | err = ocfs2_journal_access_di(handle, inode, fe_bh, | 685 | err = ocfs2_journal_access_di(handle, INODE_CACHE(inode), fe_bh, |
686 | OCFS2_JOURNAL_ACCESS_WRITE); | 686 | OCFS2_JOURNAL_ACCESS_WRITE); |
687 | if (err < 0) { | 687 | if (err < 0) { |
688 | mlog_errno(err); | 688 | mlog_errno(err); |
@@ -850,7 +850,8 @@ static int ocfs2_unlink(struct inode *dir, | |||
850 | } | 850 | } |
851 | 851 | ||
852 | if (inode_is_unlinkable(inode)) { | 852 | if (inode_is_unlinkable(inode)) { |
853 | status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, inode, | 853 | status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, |
854 | OCFS2_I(inode)->ip_blkno, | ||
854 | orphan_name, &orphan_insert); | 855 | orphan_name, &orphan_insert); |
855 | if (status < 0) { | 856 | if (status < 0) { |
856 | mlog_errno(status); | 857 | mlog_errno(status); |
@@ -866,7 +867,7 @@ static int ocfs2_unlink(struct inode *dir, | |||
866 | goto leave; | 867 | goto leave; |
867 | } | 868 | } |
868 | 869 | ||
869 | status = ocfs2_journal_access_di(handle, inode, fe_bh, | 870 | status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), fe_bh, |
870 | OCFS2_JOURNAL_ACCESS_WRITE); | 871 | OCFS2_JOURNAL_ACCESS_WRITE); |
871 | if (status < 0) { | 872 | if (status < 0) { |
872 | mlog_errno(status); | 873 | mlog_errno(status); |
@@ -1241,9 +1242,8 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1241 | 1242 | ||
1242 | if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) { | 1243 | if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) { |
1243 | status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, | 1244 | status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, |
1244 | new_inode, | 1245 | OCFS2_I(new_inode)->ip_blkno, |
1245 | orphan_name, | 1246 | orphan_name, &orphan_insert); |
1246 | &orphan_insert); | ||
1247 | if (status < 0) { | 1247 | if (status < 0) { |
1248 | mlog_errno(status); | 1248 | mlog_errno(status); |
1249 | goto bail; | 1249 | goto bail; |
@@ -1284,7 +1284,8 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1284 | goto bail; | 1284 | goto bail; |
1285 | } | 1285 | } |
1286 | } | 1286 | } |
1287 | status = ocfs2_journal_access_di(handle, new_inode, newfe_bh, | 1287 | status = ocfs2_journal_access_di(handle, INODE_CACHE(new_inode), |
1288 | newfe_bh, | ||
1288 | OCFS2_JOURNAL_ACCESS_WRITE); | 1289 | OCFS2_JOURNAL_ACCESS_WRITE); |
1289 | if (status < 0) { | 1290 | if (status < 0) { |
1290 | mlog_errno(status); | 1291 | mlog_errno(status); |
@@ -1331,7 +1332,8 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1331 | old_inode->i_ctime = CURRENT_TIME; | 1332 | old_inode->i_ctime = CURRENT_TIME; |
1332 | mark_inode_dirty(old_inode); | 1333 | mark_inode_dirty(old_inode); |
1333 | 1334 | ||
1334 | status = ocfs2_journal_access_di(handle, old_inode, old_inode_bh, | 1335 | status = ocfs2_journal_access_di(handle, INODE_CACHE(old_inode), |
1336 | old_inode_bh, | ||
1335 | OCFS2_JOURNAL_ACCESS_WRITE); | 1337 | OCFS2_JOURNAL_ACCESS_WRITE); |
1336 | if (status >= 0) { | 1338 | if (status >= 0) { |
1337 | old_di = (struct ocfs2_dinode *) old_inode_bh->b_data; | 1339 | old_di = (struct ocfs2_dinode *) old_inode_bh->b_data; |
@@ -1407,9 +1409,10 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1407 | (int)old_dir_nlink, old_dir->i_nlink); | 1409 | (int)old_dir_nlink, old_dir->i_nlink); |
1408 | } else { | 1410 | } else { |
1409 | struct ocfs2_dinode *fe; | 1411 | struct ocfs2_dinode *fe; |
1410 | status = ocfs2_journal_access_di(handle, old_dir, | 1412 | status = ocfs2_journal_access_di(handle, |
1411 | old_dir_bh, | 1413 | INODE_CACHE(old_dir), |
1412 | OCFS2_JOURNAL_ACCESS_WRITE); | 1414 | old_dir_bh, |
1415 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1413 | fe = (struct ocfs2_dinode *) old_dir_bh->b_data; | 1416 | fe = (struct ocfs2_dinode *) old_dir_bh->b_data; |
1414 | ocfs2_set_links_count(fe, old_dir->i_nlink); | 1417 | ocfs2_set_links_count(fe, old_dir->i_nlink); |
1415 | status = ocfs2_journal_dirty(handle, old_dir_bh); | 1418 | status = ocfs2_journal_dirty(handle, old_dir_bh); |
@@ -1527,9 +1530,11 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb, | |||
1527 | mlog_errno(status); | 1530 | mlog_errno(status); |
1528 | goto bail; | 1531 | goto bail; |
1529 | } | 1532 | } |
1530 | ocfs2_set_new_buffer_uptodate(inode, bhs[virtual]); | 1533 | ocfs2_set_new_buffer_uptodate(INODE_CACHE(inode), |
1534 | bhs[virtual]); | ||
1531 | 1535 | ||
1532 | status = ocfs2_journal_access(handle, inode, bhs[virtual], | 1536 | status = ocfs2_journal_access(handle, INODE_CACHE(inode), |
1537 | bhs[virtual], | ||
1533 | OCFS2_JOURNAL_ACCESS_CREATE); | 1538 | OCFS2_JOURNAL_ACCESS_CREATE); |
1534 | if (status < 0) { | 1539 | if (status < 0) { |
1535 | mlog_errno(status); | 1540 | mlog_errno(status); |
@@ -1692,7 +1697,11 @@ static int ocfs2_symlink(struct inode *dir, | |||
1692 | } | 1697 | } |
1693 | did_quota_inode = 1; | 1698 | did_quota_inode = 1; |
1694 | 1699 | ||
1695 | status = ocfs2_mknod_locked(osb, dir, inode, dentry, | 1700 | mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, |
1701 | inode->i_mode, dentry->d_name.len, | ||
1702 | dentry->d_name.name); | ||
1703 | |||
1704 | status = ocfs2_mknod_locked(osb, dir, inode, | ||
1696 | 0, &new_fe_bh, parent_fe_bh, handle, | 1705 | 0, &new_fe_bh, parent_fe_bh, handle, |
1697 | inode_ac); | 1706 | inode_ac); |
1698 | if (status < 0) { | 1707 | if (status < 0) { |
@@ -1842,7 +1851,7 @@ bail: | |||
1842 | 1851 | ||
1843 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | 1852 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, |
1844 | struct inode **ret_orphan_dir, | 1853 | struct inode **ret_orphan_dir, |
1845 | struct inode *inode, | 1854 | u64 blkno, |
1846 | char *name, | 1855 | char *name, |
1847 | struct ocfs2_dir_lookup_result *lookup) | 1856 | struct ocfs2_dir_lookup_result *lookup) |
1848 | { | 1857 | { |
@@ -1850,7 +1859,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | |||
1850 | struct buffer_head *orphan_dir_bh = NULL; | 1859 | struct buffer_head *orphan_dir_bh = NULL; |
1851 | int status = 0; | 1860 | int status = 0; |
1852 | 1861 | ||
1853 | status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name); | 1862 | status = ocfs2_blkno_stringify(blkno, name); |
1854 | if (status < 0) { | 1863 | if (status < 0) { |
1855 | mlog_errno(status); | 1864 | mlog_errno(status); |
1856 | return status; | 1865 | return status; |
@@ -1917,7 +1926,9 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, | |||
1917 | goto leave; | 1926 | goto leave; |
1918 | } | 1927 | } |
1919 | 1928 | ||
1920 | status = ocfs2_journal_access_di(handle, orphan_dir_inode, orphan_dir_bh, | 1929 | status = ocfs2_journal_access_di(handle, |
1930 | INODE_CACHE(orphan_dir_inode), | ||
1931 | orphan_dir_bh, | ||
1921 | OCFS2_JOURNAL_ACCESS_WRITE); | 1932 | OCFS2_JOURNAL_ACCESS_WRITE); |
1922 | if (status < 0) { | 1933 | if (status < 0) { |
1923 | mlog_errno(status); | 1934 | mlog_errno(status); |
@@ -2002,7 +2013,9 @@ int ocfs2_orphan_del(struct ocfs2_super *osb, | |||
2002 | goto leave; | 2013 | goto leave; |
2003 | } | 2014 | } |
2004 | 2015 | ||
2005 | status = ocfs2_journal_access_di(handle,orphan_dir_inode, orphan_dir_bh, | 2016 | status = ocfs2_journal_access_di(handle, |
2017 | INODE_CACHE(orphan_dir_inode), | ||
2018 | orphan_dir_bh, | ||
2006 | OCFS2_JOURNAL_ACCESS_WRITE); | 2019 | OCFS2_JOURNAL_ACCESS_WRITE); |
2007 | if (status < 0) { | 2020 | if (status < 0) { |
2008 | mlog_errno(status); | 2021 | mlog_errno(status); |
@@ -2028,6 +2041,274 @@ leave: | |||
2028 | return status; | 2041 | return status; |
2029 | } | 2042 | } |
2030 | 2043 | ||
2044 | int ocfs2_create_inode_in_orphan(struct inode *dir, | ||
2045 | int mode, | ||
2046 | struct inode **new_inode) | ||
2047 | { | ||
2048 | int status, did_quota_inode = 0; | ||
2049 | struct inode *inode = NULL; | ||
2050 | struct inode *orphan_dir = NULL; | ||
2051 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | ||
2052 | struct ocfs2_dinode *di = NULL; | ||
2053 | handle_t *handle = NULL; | ||
2054 | char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; | ||
2055 | struct buffer_head *parent_di_bh = NULL; | ||
2056 | struct buffer_head *new_di_bh = NULL; | ||
2057 | struct ocfs2_alloc_context *inode_ac = NULL; | ||
2058 | struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; | ||
2059 | |||
2060 | status = ocfs2_inode_lock(dir, &parent_di_bh, 1); | ||
2061 | if (status < 0) { | ||
2062 | if (status != -ENOENT) | ||
2063 | mlog_errno(status); | ||
2064 | return status; | ||
2065 | } | ||
2066 | |||
2067 | /* | ||
2068 | * We give the orphan dir the root blkno to fake an orphan name, | ||
2069 | * and allocate enough space for our insertion. | ||
2070 | */ | ||
2071 | status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, | ||
2072 | osb->root_blkno, | ||
2073 | orphan_name, &orphan_insert); | ||
2074 | if (status < 0) { | ||
2075 | mlog_errno(status); | ||
2076 | goto leave; | ||
2077 | } | ||
2078 | |||
2079 | /* reserve an inode spot */ | ||
2080 | status = ocfs2_reserve_new_inode(osb, &inode_ac); | ||
2081 | if (status < 0) { | ||
2082 | if (status != -ENOSPC) | ||
2083 | mlog_errno(status); | ||
2084 | goto leave; | ||
2085 | } | ||
2086 | |||
2087 | inode = ocfs2_get_init_inode(dir, mode); | ||
2088 | if (!inode) { | ||
2089 | status = -ENOMEM; | ||
2090 | mlog_errno(status); | ||
2091 | goto leave; | ||
2092 | } | ||
2093 | |||
2094 | handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb, 0, 0)); | ||
2095 | if (IS_ERR(handle)) { | ||
2096 | status = PTR_ERR(handle); | ||
2097 | handle = NULL; | ||
2098 | mlog_errno(status); | ||
2099 | goto leave; | ||
2100 | } | ||
2101 | |||
2102 | /* We don't use standard VFS wrapper because we don't want vfs_dq_init | ||
2103 | * to be called. */ | ||
2104 | if (sb_any_quota_active(osb->sb) && | ||
2105 | osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) { | ||
2106 | status = -EDQUOT; | ||
2107 | goto leave; | ||
2108 | } | ||
2109 | did_quota_inode = 1; | ||
2110 | |||
2111 | /* do the real work now. */ | ||
2112 | status = ocfs2_mknod_locked(osb, dir, inode, | ||
2113 | 0, &new_di_bh, parent_di_bh, handle, | ||
2114 | inode_ac); | ||
2115 | if (status < 0) { | ||
2116 | mlog_errno(status); | ||
2117 | goto leave; | ||
2118 | } | ||
2119 | |||
2120 | status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, orphan_name); | ||
2121 | if (status < 0) { | ||
2122 | mlog_errno(status); | ||
2123 | goto leave; | ||
2124 | } | ||
2125 | |||
2126 | di = (struct ocfs2_dinode *)new_di_bh->b_data; | ||
2127 | status = ocfs2_orphan_add(osb, handle, inode, di, orphan_name, | ||
2128 | &orphan_insert, orphan_dir); | ||
2129 | if (status < 0) { | ||
2130 | mlog_errno(status); | ||
2131 | goto leave; | ||
2132 | } | ||
2133 | |||
2134 | /* get open lock so that only nodes can't remove it from orphan dir. */ | ||
2135 | status = ocfs2_open_lock(inode); | ||
2136 | if (status < 0) | ||
2137 | mlog_errno(status); | ||
2138 | |||
2139 | leave: | ||
2140 | if (status < 0 && did_quota_inode) | ||
2141 | vfs_dq_free_inode(inode); | ||
2142 | if (handle) | ||
2143 | ocfs2_commit_trans(osb, handle); | ||
2144 | |||
2145 | if (orphan_dir) { | ||
2146 | /* This was locked for us in ocfs2_prepare_orphan_dir() */ | ||
2147 | ocfs2_inode_unlock(orphan_dir, 1); | ||
2148 | mutex_unlock(&orphan_dir->i_mutex); | ||
2149 | iput(orphan_dir); | ||
2150 | } | ||
2151 | |||
2152 | if (status == -ENOSPC) | ||
2153 | mlog(0, "Disk is full\n"); | ||
2154 | |||
2155 | if ((status < 0) && inode) { | ||
2156 | clear_nlink(inode); | ||
2157 | iput(inode); | ||
2158 | } | ||
2159 | |||
2160 | if (inode_ac) | ||
2161 | ocfs2_free_alloc_context(inode_ac); | ||
2162 | |||
2163 | brelse(new_di_bh); | ||
2164 | |||
2165 | if (!status) | ||
2166 | *new_inode = inode; | ||
2167 | |||
2168 | ocfs2_free_dir_lookup_result(&orphan_insert); | ||
2169 | |||
2170 | ocfs2_inode_unlock(dir, 1); | ||
2171 | brelse(parent_di_bh); | ||
2172 | return status; | ||
2173 | } | ||
2174 | |||
2175 | int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, | ||
2176 | struct inode *inode, | ||
2177 | struct dentry *dentry) | ||
2178 | { | ||
2179 | int status = 0; | ||
2180 | struct buffer_head *parent_di_bh = NULL; | ||
2181 | handle_t *handle = NULL; | ||
2182 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | ||
2183 | struct ocfs2_dinode *dir_di, *di; | ||
2184 | struct inode *orphan_dir_inode = NULL; | ||
2185 | struct buffer_head *orphan_dir_bh = NULL; | ||
2186 | struct buffer_head *di_bh = NULL; | ||
2187 | struct ocfs2_dir_lookup_result lookup = { NULL, }; | ||
2188 | |||
2189 | mlog_entry("(0x%p, 0x%p, %.*s')\n", dir, dentry, | ||
2190 | dentry->d_name.len, dentry->d_name.name); | ||
2191 | |||
2192 | status = ocfs2_inode_lock(dir, &parent_di_bh, 1); | ||
2193 | if (status < 0) { | ||
2194 | if (status != -ENOENT) | ||
2195 | mlog_errno(status); | ||
2196 | return status; | ||
2197 | } | ||
2198 | |||
2199 | dir_di = (struct ocfs2_dinode *) parent_di_bh->b_data; | ||
2200 | if (!dir_di->i_links_count) { | ||
2201 | /* can't make a file in a deleted directory. */ | ||
2202 | status = -ENOENT; | ||
2203 | goto leave; | ||
2204 | } | ||
2205 | |||
2206 | status = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, | ||
2207 | dentry->d_name.len); | ||
2208 | if (status) | ||
2209 | goto leave; | ||
2210 | |||
2211 | /* get a spot inside the dir. */ | ||
2212 | status = ocfs2_prepare_dir_for_insert(osb, dir, parent_di_bh, | ||
2213 | dentry->d_name.name, | ||
2214 | dentry->d_name.len, &lookup); | ||
2215 | if (status < 0) { | ||
2216 | mlog_errno(status); | ||
2217 | goto leave; | ||
2218 | } | ||
2219 | |||
2220 | orphan_dir_inode = ocfs2_get_system_file_inode(osb, | ||
2221 | ORPHAN_DIR_SYSTEM_INODE, | ||
2222 | osb->slot_num); | ||
2223 | if (!orphan_dir_inode) { | ||
2224 | status = -EEXIST; | ||
2225 | mlog_errno(status); | ||
2226 | goto leave; | ||
2227 | } | ||
2228 | |||
2229 | mutex_lock(&orphan_dir_inode->i_mutex); | ||
2230 | |||
2231 | status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1); | ||
2232 | if (status < 0) { | ||
2233 | mlog_errno(status); | ||
2234 | mutex_unlock(&orphan_dir_inode->i_mutex); | ||
2235 | iput(orphan_dir_inode); | ||
2236 | goto leave; | ||
2237 | } | ||
2238 | |||
2239 | status = ocfs2_read_inode_block(inode, &di_bh); | ||
2240 | if (status < 0) { | ||
2241 | mlog_errno(status); | ||
2242 | goto orphan_unlock; | ||
2243 | } | ||
2244 | |||
2245 | handle = ocfs2_start_trans(osb, ocfs2_rename_credits(osb->sb)); | ||
2246 | if (IS_ERR(handle)) { | ||
2247 | status = PTR_ERR(handle); | ||
2248 | handle = NULL; | ||
2249 | mlog_errno(status); | ||
2250 | goto orphan_unlock; | ||
2251 | } | ||
2252 | |||
2253 | status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), | ||
2254 | di_bh, OCFS2_JOURNAL_ACCESS_WRITE); | ||
2255 | if (status < 0) { | ||
2256 | mlog_errno(status); | ||
2257 | goto out_commit; | ||
2258 | } | ||
2259 | |||
2260 | status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode, | ||
2261 | orphan_dir_bh); | ||
2262 | if (status < 0) { | ||
2263 | mlog_errno(status); | ||
2264 | goto out_commit; | ||
2265 | } | ||
2266 | |||
2267 | di = (struct ocfs2_dinode *)di_bh->b_data; | ||
2268 | le32_add_cpu(&di->i_flags, -OCFS2_ORPHANED_FL); | ||
2269 | di->i_orphaned_slot = 0; | ||
2270 | ocfs2_journal_dirty(handle, di_bh); | ||
2271 | |||
2272 | status = ocfs2_add_entry(handle, dentry, inode, | ||
2273 | OCFS2_I(inode)->ip_blkno, parent_di_bh, | ||
2274 | &lookup); | ||
2275 | if (status < 0) { | ||
2276 | mlog_errno(status); | ||
2277 | goto out_commit; | ||
2278 | } | ||
2279 | |||
2280 | status = ocfs2_dentry_attach_lock(dentry, inode, | ||
2281 | OCFS2_I(dir)->ip_blkno); | ||
2282 | if (status) { | ||
2283 | mlog_errno(status); | ||
2284 | goto out_commit; | ||
2285 | } | ||
2286 | |||
2287 | insert_inode_hash(inode); | ||
2288 | dentry->d_op = &ocfs2_dentry_ops; | ||
2289 | d_instantiate(dentry, inode); | ||
2290 | status = 0; | ||
2291 | out_commit: | ||
2292 | ocfs2_commit_trans(osb, handle); | ||
2293 | orphan_unlock: | ||
2294 | ocfs2_inode_unlock(orphan_dir_inode, 1); | ||
2295 | mutex_unlock(&orphan_dir_inode->i_mutex); | ||
2296 | iput(orphan_dir_inode); | ||
2297 | leave: | ||
2298 | |||
2299 | ocfs2_inode_unlock(dir, 1); | ||
2300 | |||
2301 | brelse(di_bh); | ||
2302 | brelse(parent_di_bh); | ||
2303 | brelse(orphan_dir_bh); | ||
2304 | |||
2305 | ocfs2_free_dir_lookup_result(&lookup); | ||
2306 | |||
2307 | mlog_exit(status); | ||
2308 | |||
2309 | return status; | ||
2310 | } | ||
2311 | |||
2031 | const struct inode_operations ocfs2_dir_iops = { | 2312 | const struct inode_operations ocfs2_dir_iops = { |
2032 | .create = ocfs2_create, | 2313 | .create = ocfs2_create, |
2033 | .lookup = ocfs2_lookup, | 2314 | .lookup = ocfs2_lookup, |