diff options
author | Joseph Qi <joseph.qi@huawei.com> | 2015-02-16 18:59:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-16 20:56:04 -0500 |
commit | 06ee5c75b57564435933fc0ffa72dc18a2fda0e7 (patch) | |
tree | 2c59e53d305f97f8d1f15bff1e1903d85d251f1d | |
parent | 026749a86ebff68cb2accdcd29872d36ac148920 (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.c | 2 | ||||
-rw-r--r-- | fs/ocfs2/journal.h | 5 | ||||
-rw-r--r-- | fs/ocfs2/namei.c | 247 | ||||
-rw-r--r-- | fs/ocfs2/namei.h | 8 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2_fs.h | 6 |
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 | ||
84 | static int ocfs2_orphan_add(struct ocfs2_super *osb, | 85 | static 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 | ||
92 | static int ocfs2_create_symlink_data(struct ocfs2_super *osb, | 94 | static 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, | |||
104 | static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2); | 106 | static 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 | ||
108 | static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, | 112 | static 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 | ||
2580 | int 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 | |||
2620 | bail_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 | |||
2627 | bail_unlock_inode: | ||
2628 | ocfs2_inode_unlock(inode, 1); | ||
2629 | brelse(di_bh); | ||
2630 | |||
2631 | bail: | ||
2632 | return status; | ||
2633 | } | ||
2634 | |||
2635 | int 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 | |||
2706 | bail_commit: | ||
2707 | ocfs2_commit_trans(osb, handle); | ||
2708 | |||
2709 | bail_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 | |||
2715 | bail_unlock_inode: | ||
2716 | ocfs2_inode_unlock(inode, 1); | ||
2717 | brelse(di_bh); | ||
2718 | |||
2719 | bail: | ||
2720 | return status; | ||
2721 | } | ||
2722 | |||
2530 | int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, | 2723 | int 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); | ||
38 | int ocfs2_create_inode_in_orphan(struct inode *dir, | 39 | int ocfs2_create_inode_in_orphan(struct inode *dir, |
39 | int mode, | 40 | int mode, |
40 | struct inode **new_inode); | 41 | struct inode **new_inode); |
42 | int ocfs2_add_inode_to_orphan(struct ocfs2_super *osb, | ||
43 | struct inode *inode); | ||
44 | int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb, | ||
45 | struct inode *inode, int update_isize, | ||
46 | loff_t end); | ||
41 | int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, | 47 | int 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 */ |