summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoseph Qi <joseph.qi@huawei.com>2015-02-16 18:59:54 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-16 20:56:04 -0500
commit06ee5c75b57564435933fc0ffa72dc18a2fda0e7 (patch)
tree2c59e53d305f97f8d1f15bff1e1903d85d251f1d
parent026749a86ebff68cb2accdcd29872d36ac148920 (diff)
ocfs2: add functions to add and remove inode in orphan dir
Add functions to add inode to orphan dir and remove inode in orphan dir. Here we do not call ocfs2_prepare_orphan_dir and ocfs2_orphan_add directly. Because append O_DIRECT will add inode to orphan two and may result in more than one orphan entry for the same inode. [akpm@linux-foundation.org: avoid dynamic stack allocation] Signed-off-by: Joseph Qi <joseph.qi@huawei.com> Cc: Weiwei Wang <wangww631@huawei.com> Cc: Junxiao Bi <junxiao.bi@oracle.com> Cc: Joel Becker <jlbec@evilplan.org> Cc: Mark Fasheh <mfasheh@suse.com> Cc: Xuejiufei <xuejiufei@huawei.com> Cc: alex chen <alex.chen@huawei.com> Cc: Fengguang Wu <fengguang.wu@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/ocfs2/inode.c2
-rw-r--r--fs/ocfs2/journal.h5
-rw-r--r--fs/ocfs2/namei.c247
-rw-r--r--fs/ocfs2/namei.h8
-rw-r--r--fs/ocfs2/ocfs2_fs.h6
5 files changed, 238 insertions, 30 deletions
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index c8b25de9efbb..3025c0da6b8a 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -648,7 +648,7 @@ static int ocfs2_remove_inode(struct inode *inode,
648 648
649 if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) { 649 if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) {
650 status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode, 650 status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode,
651 orphan_dir_bh); 651 orphan_dir_bh, false);
652 if (status < 0) { 652 if (status < 0) {
653 mlog_errno(status); 653 mlog_errno(status);
654 goto bail_commit; 654 goto bail_commit;
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index 7f8cde94abfe..f4cd3c3e9fb7 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -472,6 +472,11 @@ static inline int ocfs2_unlink_credits(struct super_block *sb)
472 * orphan dir index leaf */ 472 * orphan dir index leaf */
473#define OCFS2_DELETE_INODE_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 4) 473#define OCFS2_DELETE_INODE_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 4)
474 474
475/* dinode + orphan dir dinode + extent tree leaf block + orphan dir entry +
476 * orphan dir index root + orphan dir index leaf */
477#define OCFS2_INODE_ADD_TO_ORPHAN_CREDITS (2 * OCFS2_INODE_UPDATE_CREDITS + 4)
478#define OCFS2_INODE_DEL_FROM_ORPHAN_CREDITS OCFS2_INODE_ADD_TO_ORPHAN_CREDITS
479
475/* dinode update, old dir dinode update, new dir dinode update, old 480/* dinode update, old dir dinode update, new dir dinode update, old
476 * dir dir entry, new dir dir entry, dir entry update for renaming 481 * dir dir entry, new dir dir entry, dir entry update for renaming
477 * directory + target unlink + 3 x dir index leaves */ 482 * directory + target unlink + 3 x dir index leaves */
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 914c121ec890..7eec45d0d85f 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -79,7 +79,8 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
79 struct inode **ret_orphan_dir, 79 struct inode **ret_orphan_dir,
80 u64 blkno, 80 u64 blkno,
81 char *name, 81 char *name,
82 struct ocfs2_dir_lookup_result *lookup); 82 struct ocfs2_dir_lookup_result *lookup,
83 bool dio);
83 84
84static int ocfs2_orphan_add(struct ocfs2_super *osb, 85static int ocfs2_orphan_add(struct ocfs2_super *osb,
85 handle_t *handle, 86 handle_t *handle,
@@ -87,7 +88,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
87 struct buffer_head *fe_bh, 88 struct buffer_head *fe_bh,
88 char *name, 89 char *name,
89 struct ocfs2_dir_lookup_result *lookup, 90 struct ocfs2_dir_lookup_result *lookup,
90 struct inode *orphan_dir_inode); 91 struct inode *orphan_dir_inode,
92 bool dio);
91 93
92static int ocfs2_create_symlink_data(struct ocfs2_super *osb, 94static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
93 handle_t *handle, 95 handle_t *handle,
@@ -104,6 +106,8 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
104static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2); 106static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2);
105/* An orphan dir name is an 8 byte value, printed as a hex string */ 107/* An orphan dir name is an 8 byte value, printed as a hex string */
106#define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) 108#define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64)))
109#define OCFS2_DIO_ORPHAN_PREFIX "dio-"
110#define OCFS2_DIO_ORPHAN_PREFIX_LEN 4
107 111
108static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, 112static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
109 unsigned int flags) 113 unsigned int flags)
@@ -952,7 +956,8 @@ static int ocfs2_unlink(struct inode *dir,
952 if (ocfs2_inode_is_unlinkable(inode)) { 956 if (ocfs2_inode_is_unlinkable(inode)) {
953 status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, 957 status = ocfs2_prepare_orphan_dir(osb, &orphan_dir,
954 OCFS2_I(inode)->ip_blkno, 958 OCFS2_I(inode)->ip_blkno,
955 orphan_name, &orphan_insert); 959 orphan_name, &orphan_insert,
960 false);
956 if (status < 0) { 961 if (status < 0) {
957 mlog_errno(status); 962 mlog_errno(status);
958 goto leave; 963 goto leave;
@@ -1004,7 +1009,7 @@ static int ocfs2_unlink(struct inode *dir,
1004 1009
1005 if (is_unlinkable) { 1010 if (is_unlinkable) {
1006 status = ocfs2_orphan_add(osb, handle, inode, fe_bh, 1011 status = ocfs2_orphan_add(osb, handle, inode, fe_bh,
1007 orphan_name, &orphan_insert, orphan_dir); 1012 orphan_name, &orphan_insert, orphan_dir, false);
1008 if (status < 0) 1013 if (status < 0)
1009 mlog_errno(status); 1014 mlog_errno(status);
1010 } 1015 }
@@ -1440,7 +1445,8 @@ static int ocfs2_rename(struct inode *old_dir,
1440 if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) { 1445 if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) {
1441 status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, 1446 status = ocfs2_prepare_orphan_dir(osb, &orphan_dir,
1442 OCFS2_I(new_inode)->ip_blkno, 1447 OCFS2_I(new_inode)->ip_blkno,
1443 orphan_name, &orphan_insert); 1448 orphan_name, &orphan_insert,
1449 false);
1444 if (status < 0) { 1450 if (status < 0) {
1445 mlog_errno(status); 1451 mlog_errno(status);
1446 goto bail; 1452 goto bail;
@@ -1507,7 +1513,7 @@ static int ocfs2_rename(struct inode *old_dir,
1507 if (should_add_orphan) { 1513 if (should_add_orphan) {
1508 status = ocfs2_orphan_add(osb, handle, new_inode, 1514 status = ocfs2_orphan_add(osb, handle, new_inode,
1509 newfe_bh, orphan_name, 1515 newfe_bh, orphan_name,
1510 &orphan_insert, orphan_dir); 1516 &orphan_insert, orphan_dir, false);
1511 if (status < 0) { 1517 if (status < 0) {
1512 mlog_errno(status); 1518 mlog_errno(status);
1513 goto bail; 1519 goto bail;
@@ -2088,12 +2094,28 @@ static int __ocfs2_prepare_orphan_dir(struct inode *orphan_dir_inode,
2088 struct buffer_head *orphan_dir_bh, 2094 struct buffer_head *orphan_dir_bh,
2089 u64 blkno, 2095 u64 blkno,
2090 char *name, 2096 char *name,
2091 struct ocfs2_dir_lookup_result *lookup) 2097 struct ocfs2_dir_lookup_result *lookup,
2098 bool dio)
2092{ 2099{
2093 int ret; 2100 int ret;
2094 struct ocfs2_super *osb = OCFS2_SB(orphan_dir_inode->i_sb); 2101 struct ocfs2_super *osb = OCFS2_SB(orphan_dir_inode->i_sb);
2102 int namelen = dio ?
2103 (OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN) :
2104 OCFS2_ORPHAN_NAMELEN;
2105
2106 if (dio) {
2107 ret = snprintf(name, OCFS2_DIO_ORPHAN_PREFIX_LEN + 1, "%s",
2108 OCFS2_DIO_ORPHAN_PREFIX);
2109 if (ret != OCFS2_DIO_ORPHAN_PREFIX_LEN) {
2110 ret = -EINVAL;
2111 mlog_errno(ret);
2112 return ret;
2113 }
2095 2114
2096 ret = ocfs2_blkno_stringify(blkno, name); 2115 ret = ocfs2_blkno_stringify(blkno,
2116 name + OCFS2_DIO_ORPHAN_PREFIX_LEN);
2117 } else
2118 ret = ocfs2_blkno_stringify(blkno, name);
2097 if (ret < 0) { 2119 if (ret < 0) {
2098 mlog_errno(ret); 2120 mlog_errno(ret);
2099 return ret; 2121 return ret;
@@ -2101,7 +2123,7 @@ static int __ocfs2_prepare_orphan_dir(struct inode *orphan_dir_inode,
2101 2123
2102 ret = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode, 2124 ret = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode,
2103 orphan_dir_bh, name, 2125 orphan_dir_bh, name,
2104 OCFS2_ORPHAN_NAMELEN, lookup); 2126 namelen, lookup);
2105 if (ret < 0) { 2127 if (ret < 0) {
2106 mlog_errno(ret); 2128 mlog_errno(ret);
2107 return ret; 2129 return ret;
@@ -2128,7 +2150,8 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
2128 struct inode **ret_orphan_dir, 2150 struct inode **ret_orphan_dir,
2129 u64 blkno, 2151 u64 blkno,
2130 char *name, 2152 char *name,
2131 struct ocfs2_dir_lookup_result *lookup) 2153 struct ocfs2_dir_lookup_result *lookup,
2154 bool dio)
2132{ 2155{
2133 struct inode *orphan_dir_inode = NULL; 2156 struct inode *orphan_dir_inode = NULL;
2134 struct buffer_head *orphan_dir_bh = NULL; 2157 struct buffer_head *orphan_dir_bh = NULL;
@@ -2142,7 +2165,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
2142 } 2165 }
2143 2166
2144 ret = __ocfs2_prepare_orphan_dir(orphan_dir_inode, orphan_dir_bh, 2167 ret = __ocfs2_prepare_orphan_dir(orphan_dir_inode, orphan_dir_bh,
2145 blkno, name, lookup); 2168 blkno, name, lookup, dio);
2146 if (ret < 0) { 2169 if (ret < 0) {
2147 mlog_errno(ret); 2170 mlog_errno(ret);
2148 goto out; 2171 goto out;
@@ -2170,12 +2193,16 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
2170 struct buffer_head *fe_bh, 2193 struct buffer_head *fe_bh,
2171 char *name, 2194 char *name,
2172 struct ocfs2_dir_lookup_result *lookup, 2195 struct ocfs2_dir_lookup_result *lookup,
2173 struct inode *orphan_dir_inode) 2196 struct inode *orphan_dir_inode,
2197 bool dio)
2174{ 2198{
2175 struct buffer_head *orphan_dir_bh = NULL; 2199 struct buffer_head *orphan_dir_bh = NULL;
2176 int status = 0; 2200 int status = 0;
2177 struct ocfs2_dinode *orphan_fe; 2201 struct ocfs2_dinode *orphan_fe;
2178 struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; 2202 struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data;
2203 int namelen = dio ?
2204 (OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN) :
2205 OCFS2_ORPHAN_NAMELEN;
2179 2206
2180 trace_ocfs2_orphan_add_begin( 2207 trace_ocfs2_orphan_add_begin(
2181 (unsigned long long)OCFS2_I(inode)->ip_blkno); 2208 (unsigned long long)OCFS2_I(inode)->ip_blkno);
@@ -2219,7 +2246,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
2219 ocfs2_journal_dirty(handle, orphan_dir_bh); 2246 ocfs2_journal_dirty(handle, orphan_dir_bh);
2220 2247
2221 status = __ocfs2_add_entry(handle, orphan_dir_inode, name, 2248 status = __ocfs2_add_entry(handle, orphan_dir_inode, name,
2222 OCFS2_ORPHAN_NAMELEN, inode, 2249 namelen, inode,
2223 OCFS2_I(inode)->ip_blkno, 2250 OCFS2_I(inode)->ip_blkno,
2224 orphan_dir_bh, lookup); 2251 orphan_dir_bh, lookup);
2225 if (status < 0) { 2252 if (status < 0) {
@@ -2227,13 +2254,21 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
2227 goto rollback; 2254 goto rollback;
2228 } 2255 }
2229 2256
2230 fe->i_flags |= cpu_to_le32(OCFS2_ORPHANED_FL); 2257 if (dio) {
2231 OCFS2_I(inode)->ip_flags &= ~OCFS2_INODE_SKIP_ORPHAN_DIR; 2258 /* Update flag OCFS2_DIO_ORPHANED_FL and record the orphan
2259 * slot.
2260 */
2261 fe->i_flags |= cpu_to_le32(OCFS2_DIO_ORPHANED_FL);
2262 fe->i_dio_orphaned_slot = cpu_to_le16(osb->slot_num);
2263 } else {
2264 fe->i_flags |= cpu_to_le32(OCFS2_ORPHANED_FL);
2265 OCFS2_I(inode)->ip_flags &= ~OCFS2_INODE_SKIP_ORPHAN_DIR;
2232 2266
2233 /* Record which orphan dir our inode now resides 2267 /* Record which orphan dir our inode now resides
2234 * in. delete_inode will use this to determine which orphan 2268 * in. delete_inode will use this to determine which orphan
2235 * dir to lock. */ 2269 * dir to lock. */
2236 fe->i_orphaned_slot = cpu_to_le16(osb->slot_num); 2270 fe->i_orphaned_slot = cpu_to_le16(osb->slot_num);
2271 }
2237 2272
2238 ocfs2_journal_dirty(handle, fe_bh); 2273 ocfs2_journal_dirty(handle, fe_bh);
2239 2274
@@ -2258,14 +2293,28 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
2258 handle_t *handle, 2293 handle_t *handle,
2259 struct inode *orphan_dir_inode, 2294 struct inode *orphan_dir_inode,
2260 struct inode *inode, 2295 struct inode *inode,
2261 struct buffer_head *orphan_dir_bh) 2296 struct buffer_head *orphan_dir_bh,
2297 bool dio)
2262{ 2298{
2263 char name[OCFS2_ORPHAN_NAMELEN + 1]; 2299 const int namelen = OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN;
2300 char name[namelen + 1];
2264 struct ocfs2_dinode *orphan_fe; 2301 struct ocfs2_dinode *orphan_fe;
2265 int status = 0; 2302 int status = 0;
2266 struct ocfs2_dir_lookup_result lookup = { NULL, }; 2303 struct ocfs2_dir_lookup_result lookup = { NULL, };
2267 2304
2268 status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name); 2305 if (dio) {
2306 status = snprintf(name, OCFS2_DIO_ORPHAN_PREFIX_LEN + 1, "%s",
2307 OCFS2_DIO_ORPHAN_PREFIX);
2308 if (status != OCFS2_DIO_ORPHAN_PREFIX_LEN) {
2309 status = -EINVAL;
2310 mlog_errno(status);
2311 return status;
2312 }
2313
2314 status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno,
2315 name + OCFS2_DIO_ORPHAN_PREFIX_LEN);
2316 } else
2317 status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name);
2269 if (status < 0) { 2318 if (status < 0) {
2270 mlog_errno(status); 2319 mlog_errno(status);
2271 goto leave; 2320 goto leave;
@@ -2273,10 +2322,10 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
2273 2322
2274 trace_ocfs2_orphan_del( 2323 trace_ocfs2_orphan_del(
2275 (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno, 2324 (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno,
2276 name, OCFS2_ORPHAN_NAMELEN); 2325 name, namelen);
2277 2326
2278 /* find it's spot in the orphan directory */ 2327 /* find it's spot in the orphan directory */
2279 status = ocfs2_find_entry(name, OCFS2_ORPHAN_NAMELEN, orphan_dir_inode, 2328 status = ocfs2_find_entry(name, namelen, orphan_dir_inode,
2280 &lookup); 2329 &lookup);
2281 if (status) { 2330 if (status) {
2282 mlog_errno(status); 2331 mlog_errno(status);
@@ -2376,7 +2425,8 @@ static int ocfs2_prep_new_orphaned_file(struct inode *dir,
2376 } 2425 }
2377 2426
2378 ret = __ocfs2_prepare_orphan_dir(orphan_dir, orphan_dir_bh, 2427 ret = __ocfs2_prepare_orphan_dir(orphan_dir, orphan_dir_bh,
2379 di_blkno, orphan_name, orphan_insert); 2428 di_blkno, orphan_name, orphan_insert,
2429 false);
2380 if (ret < 0) { 2430 if (ret < 0) {
2381 mlog_errno(ret); 2431 mlog_errno(ret);
2382 goto out; 2432 goto out;
@@ -2482,7 +2532,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
2482 2532
2483 di = (struct ocfs2_dinode *)new_di_bh->b_data; 2533 di = (struct ocfs2_dinode *)new_di_bh->b_data;
2484 status = ocfs2_orphan_add(osb, handle, inode, new_di_bh, orphan_name, 2534 status = ocfs2_orphan_add(osb, handle, inode, new_di_bh, orphan_name,
2485 &orphan_insert, orphan_dir); 2535 &orphan_insert, orphan_dir, false);
2486 if (status < 0) { 2536 if (status < 0) {
2487 mlog_errno(status); 2537 mlog_errno(status);
2488 goto leave; 2538 goto leave;
@@ -2527,6 +2577,149 @@ leave:
2527 return status; 2577 return status;
2528} 2578}
2529 2579
2580int ocfs2_add_inode_to_orphan(struct ocfs2_super *osb,
2581 struct inode *inode)
2582{
2583 char orphan_name[OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN + 1];
2584 struct inode *orphan_dir_inode = NULL;
2585 struct ocfs2_dir_lookup_result orphan_insert = { NULL, };
2586 struct buffer_head *di_bh = NULL;
2587 int status = 0;
2588 handle_t *handle = NULL;
2589
2590 status = ocfs2_inode_lock(inode, &di_bh, 1);
2591 if (status < 0) {
2592 mlog_errno(status);
2593 goto bail;
2594 }
2595
2596 status = ocfs2_prepare_orphan_dir(osb, &orphan_dir_inode,
2597 OCFS2_I(inode)->ip_blkno,
2598 orphan_name,
2599 &orphan_insert,
2600 true);
2601 if (status < 0) {
2602 mlog_errno(status);
2603 goto bail_unlock_inode;
2604 }
2605
2606 handle = ocfs2_start_trans(osb,
2607 OCFS2_INODE_ADD_TO_ORPHAN_CREDITS);
2608 if (IS_ERR(handle)) {
2609 status = PTR_ERR(handle);
2610 goto bail_unlock_orphan;
2611 }
2612
2613 status = ocfs2_orphan_add(osb, handle, inode, di_bh, orphan_name,
2614 &orphan_insert, orphan_dir_inode, true);
2615 if (status)
2616 mlog_errno(status);
2617
2618 ocfs2_commit_trans(osb, handle);
2619
2620bail_unlock_orphan:
2621 ocfs2_inode_unlock(orphan_dir_inode, 1);
2622 mutex_unlock(&orphan_dir_inode->i_mutex);
2623 iput(orphan_dir_inode);
2624
2625 ocfs2_free_dir_lookup_result(&orphan_insert);
2626
2627bail_unlock_inode:
2628 ocfs2_inode_unlock(inode, 1);
2629 brelse(di_bh);
2630
2631bail:
2632 return status;
2633}
2634
2635int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb,
2636 struct inode *inode, int update_isize,
2637 loff_t end)
2638{
2639 struct inode *orphan_dir_inode = NULL;
2640 struct buffer_head *orphan_dir_bh = NULL;
2641 struct buffer_head *di_bh = NULL;
2642 struct ocfs2_dinode *di = NULL;
2643 handle_t *handle = NULL;
2644 int status = 0;
2645
2646 status = ocfs2_inode_lock(inode, &di_bh, 1);
2647 if (status < 0) {
2648 mlog_errno(status);
2649 goto bail;
2650 }
2651 di = (struct ocfs2_dinode *) di_bh->b_data;
2652
2653 orphan_dir_inode = ocfs2_get_system_file_inode(osb,
2654 ORPHAN_DIR_SYSTEM_INODE,
2655 le16_to_cpu(di->i_dio_orphaned_slot));
2656 if (!orphan_dir_inode) {
2657 status = -ENOENT;
2658 mlog_errno(status);
2659 goto bail_unlock_inode;
2660 }
2661
2662 mutex_lock(&orphan_dir_inode->i_mutex);
2663 status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1);
2664 if (status < 0) {
2665 mutex_unlock(&orphan_dir_inode->i_mutex);
2666 iput(orphan_dir_inode);
2667 mlog_errno(status);
2668 goto bail_unlock_inode;
2669 }
2670
2671 handle = ocfs2_start_trans(osb,
2672 OCFS2_INODE_DEL_FROM_ORPHAN_CREDITS);
2673 if (IS_ERR(handle)) {
2674 status = PTR_ERR(handle);
2675 goto bail_unlock_orphan;
2676 }
2677
2678 BUG_ON(!(di->i_flags & cpu_to_le32(OCFS2_DIO_ORPHANED_FL)));
2679
2680 status = ocfs2_orphan_del(osb, handle, orphan_dir_inode,
2681 inode, orphan_dir_bh, true);
2682 if (status < 0) {
2683 mlog_errno(status);
2684 goto bail_commit;
2685 }
2686
2687 status = ocfs2_journal_access_di(handle,
2688 INODE_CACHE(inode),
2689 di_bh,
2690 OCFS2_JOURNAL_ACCESS_WRITE);
2691 if (status < 0) {
2692 mlog_errno(status);
2693 goto bail_commit;
2694 }
2695
2696 di->i_flags &= ~cpu_to_le32(OCFS2_DIO_ORPHANED_FL);
2697 di->i_dio_orphaned_slot = 0;
2698
2699 if (update_isize) {
2700 status = ocfs2_set_inode_size(handle, inode, di_bh, end);
2701 if (status)
2702 mlog_errno(status);
2703 } else
2704 ocfs2_journal_dirty(handle, di_bh);
2705
2706bail_commit:
2707 ocfs2_commit_trans(osb, handle);
2708
2709bail_unlock_orphan:
2710 ocfs2_inode_unlock(orphan_dir_inode, 1);
2711 mutex_unlock(&orphan_dir_inode->i_mutex);
2712 brelse(orphan_dir_bh);
2713 iput(orphan_dir_inode);
2714
2715bail_unlock_inode:
2716 ocfs2_inode_unlock(inode, 1);
2717 brelse(di_bh);
2718
2719bail:
2720 return status;
2721}
2722
2530int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, 2723int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
2531 struct inode *inode, 2724 struct inode *inode,
2532 struct dentry *dentry) 2725 struct dentry *dentry)
@@ -2615,7 +2808,7 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
2615 } 2808 }
2616 2809
2617 status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode, 2810 status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode,
2618 orphan_dir_bh); 2811 orphan_dir_bh, false);
2619 if (status < 0) { 2812 if (status < 0) {
2620 mlog_errno(status); 2813 mlog_errno(status);
2621 goto out_commit; 2814 goto out_commit;
diff --git a/fs/ocfs2/namei.h b/fs/ocfs2/namei.h
index e5d059d4f115..5ddecce172fa 100644
--- a/fs/ocfs2/namei.h
+++ b/fs/ocfs2/namei.h
@@ -34,10 +34,16 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
34 handle_t *handle, 34 handle_t *handle,
35 struct inode *orphan_dir_inode, 35 struct inode *orphan_dir_inode,
36 struct inode *inode, 36 struct inode *inode,
37 struct buffer_head *orphan_dir_bh); 37 struct buffer_head *orphan_dir_bh,
38 bool dio);
38int ocfs2_create_inode_in_orphan(struct inode *dir, 39int ocfs2_create_inode_in_orphan(struct inode *dir,
39 int mode, 40 int mode,
40 struct inode **new_inode); 41 struct inode **new_inode);
42int ocfs2_add_inode_to_orphan(struct ocfs2_super *osb,
43 struct inode *inode);
44int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb,
45 struct inode *inode, int update_isize,
46 loff_t end);
41int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, 47int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
42 struct inode *new_inode, 48 struct inode *new_inode,
43 struct dentry *new_dentry); 49 struct dentry *new_dentry);
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index 938387a10d5d..cf4fa43af78e 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -229,6 +229,8 @@
229#define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ 229#define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */
230#define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ 230#define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */
231#define OCFS2_QUOTA_FL (0x00001000) /* Quota file */ 231#define OCFS2_QUOTA_FL (0x00001000) /* Quota file */
232#define OCFS2_DIO_ORPHANED_FL (0X00002000) /* On the orphan list especially
233 * for dio */
232 234
233/* 235/*
234 * Flags on ocfs2_dinode.i_dyn_features 236 * Flags on ocfs2_dinode.i_dyn_features
@@ -729,7 +731,9 @@ struct ocfs2_dinode {
729 inode belongs to. Only valid 731 inode belongs to. Only valid
730 if allocated from a 732 if allocated from a
731 discontiguous block group */ 733 discontiguous block group */
732/*A0*/ __le64 i_reserved2[3]; 734/*A0*/ __le16 i_dio_orphaned_slot; /* only used for append dio write */
735 __le16 i_reserved1[3];
736 __le64 i_reserved2[2];
733/*B8*/ union { 737/*B8*/ union {
734 __le64 i_pad1; /* Generic way to refer to this 738 __le64 i_pad1; /* Generic way to refer to this
735 64bit union */ 739 64bit union */