diff options
Diffstat (limited to 'fs/ext3/namei.c')
-rw-r--r-- | fs/ext3/namei.c | 80 |
1 files changed, 67 insertions, 13 deletions
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 32f3b8695859..34b6d9bfc48a 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -1416,10 +1416,19 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1416 | frame->at = entries; | 1416 | frame->at = entries; |
1417 | frame->bh = bh; | 1417 | frame->bh = bh; |
1418 | bh = bh2; | 1418 | bh = bh2; |
1419 | /* | ||
1420 | * Mark buffers dirty here so that if do_split() fails we write a | ||
1421 | * consistent set of buffers to disk. | ||
1422 | */ | ||
1423 | ext3_journal_dirty_metadata(handle, frame->bh); | ||
1424 | ext3_journal_dirty_metadata(handle, bh); | ||
1419 | de = do_split(handle,dir, &bh, frame, &hinfo, &retval); | 1425 | de = do_split(handle,dir, &bh, frame, &hinfo, &retval); |
1420 | dx_release (frames); | 1426 | if (!de) { |
1421 | if (!(de)) | 1427 | ext3_mark_inode_dirty(handle, dir); |
1428 | dx_release(frames); | ||
1422 | return retval; | 1429 | return retval; |
1430 | } | ||
1431 | dx_release(frames); | ||
1423 | 1432 | ||
1424 | return add_dirent_to_buf(handle, dentry, inode, de, bh); | 1433 | return add_dirent_to_buf(handle, dentry, inode, de, bh); |
1425 | } | 1434 | } |
@@ -2189,6 +2198,7 @@ static int ext3_symlink (struct inode * dir, | |||
2189 | handle_t *handle; | 2198 | handle_t *handle; |
2190 | struct inode * inode; | 2199 | struct inode * inode; |
2191 | int l, err, retries = 0; | 2200 | int l, err, retries = 0; |
2201 | int credits; | ||
2192 | 2202 | ||
2193 | l = strlen(symname)+1; | 2203 | l = strlen(symname)+1; |
2194 | if (l > dir->i_sb->s_blocksize) | 2204 | if (l > dir->i_sb->s_blocksize) |
@@ -2196,10 +2206,26 @@ static int ext3_symlink (struct inode * dir, | |||
2196 | 2206 | ||
2197 | dquot_initialize(dir); | 2207 | dquot_initialize(dir); |
2198 | 2208 | ||
2209 | if (l > EXT3_N_BLOCKS * 4) { | ||
2210 | /* | ||
2211 | * For non-fast symlinks, we just allocate inode and put it on | ||
2212 | * orphan list in the first transaction => we need bitmap, | ||
2213 | * group descriptor, sb, inode block, quota blocks. | ||
2214 | */ | ||
2215 | credits = 4 + EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb); | ||
2216 | } else { | ||
2217 | /* | ||
2218 | * Fast symlink. We have to add entry to directory | ||
2219 | * (EXT3_DATA_TRANS_BLOCKS + EXT3_INDEX_EXTRA_TRANS_BLOCKS), | ||
2220 | * allocate new inode (bitmap, group descriptor, inode block, | ||
2221 | * quota blocks, sb is already counted in previous macros). | ||
2222 | */ | ||
2223 | credits = EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + | ||
2224 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + | ||
2225 | EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb); | ||
2226 | } | ||
2199 | retry: | 2227 | retry: |
2200 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + | 2228 | handle = ext3_journal_start(dir, credits); |
2201 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 + | ||
2202 | EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)); | ||
2203 | if (IS_ERR(handle)) | 2229 | if (IS_ERR(handle)) |
2204 | return PTR_ERR(handle); | 2230 | return PTR_ERR(handle); |
2205 | 2231 | ||
@@ -2211,21 +2237,45 @@ retry: | |||
2211 | if (IS_ERR(inode)) | 2237 | if (IS_ERR(inode)) |
2212 | goto out_stop; | 2238 | goto out_stop; |
2213 | 2239 | ||
2214 | if (l > sizeof (EXT3_I(inode)->i_data)) { | 2240 | if (l > EXT3_N_BLOCKS * 4) { |
2215 | inode->i_op = &ext3_symlink_inode_operations; | 2241 | inode->i_op = &ext3_symlink_inode_operations; |
2216 | ext3_set_aops(inode); | 2242 | ext3_set_aops(inode); |
2217 | /* | 2243 | /* |
2218 | * page_symlink() calls into ext3_prepare/commit_write. | 2244 | * We cannot call page_symlink() with transaction started |
2219 | * We have a transaction open. All is sweetness. It also sets | 2245 | * because it calls into ext3_write_begin() which acquires page |
2220 | * i_size in generic_commit_write(). | 2246 | * lock which ranks below transaction start (and it can also |
2247 | * wait for journal commit if we are running out of space). So | ||
2248 | * we have to stop transaction now and restart it when symlink | ||
2249 | * contents is written. | ||
2250 | * | ||
2251 | * To keep fs consistent in case of crash, we have to put inode | ||
2252 | * to orphan list in the mean time. | ||
2221 | */ | 2253 | */ |
2254 | drop_nlink(inode); | ||
2255 | err = ext3_orphan_add(handle, inode); | ||
2256 | ext3_journal_stop(handle); | ||
2257 | if (err) | ||
2258 | goto err_drop_inode; | ||
2222 | err = __page_symlink(inode, symname, l, 1); | 2259 | err = __page_symlink(inode, symname, l, 1); |
2260 | if (err) | ||
2261 | goto err_drop_inode; | ||
2262 | /* | ||
2263 | * Now inode is being linked into dir (EXT3_DATA_TRANS_BLOCKS | ||
2264 | * + EXT3_INDEX_EXTRA_TRANS_BLOCKS), inode is also modified | ||
2265 | */ | ||
2266 | handle = ext3_journal_start(dir, | ||
2267 | EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + | ||
2268 | EXT3_INDEX_EXTRA_TRANS_BLOCKS + 1); | ||
2269 | if (IS_ERR(handle)) { | ||
2270 | err = PTR_ERR(handle); | ||
2271 | goto err_drop_inode; | ||
2272 | } | ||
2273 | inc_nlink(inode); | ||
2274 | err = ext3_orphan_del(handle, inode); | ||
2223 | if (err) { | 2275 | if (err) { |
2276 | ext3_journal_stop(handle); | ||
2224 | drop_nlink(inode); | 2277 | drop_nlink(inode); |
2225 | unlock_new_inode(inode); | 2278 | goto err_drop_inode; |
2226 | ext3_mark_inode_dirty(handle, inode); | ||
2227 | iput (inode); | ||
2228 | goto out_stop; | ||
2229 | } | 2279 | } |
2230 | } else { | 2280 | } else { |
2231 | inode->i_op = &ext3_fast_symlink_inode_operations; | 2281 | inode->i_op = &ext3_fast_symlink_inode_operations; |
@@ -2239,6 +2289,10 @@ out_stop: | |||
2239 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) | 2289 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) |
2240 | goto retry; | 2290 | goto retry; |
2241 | return err; | 2291 | return err; |
2292 | err_drop_inode: | ||
2293 | unlock_new_inode(inode); | ||
2294 | iput(inode); | ||
2295 | return err; | ||
2242 | } | 2296 | } |
2243 | 2297 | ||
2244 | static int ext3_link (struct dentry * old_dentry, | 2298 | static int ext3_link (struct dentry * old_dentry, |