aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-03-04 01:31:03 -0500
committerBob Copeland <me@bobcopeland.com>2011-03-05 16:24:01 -0500
commitd932805b3dc8c6d80d8948f7d7d0d8336d53b2ed (patch)
tree5024d697f1b3b6c8fcfe627718ece4020102df1b
parentcdb26496dba00d5c4375261be6518b3e94260444 (diff)
omfs: merge unlink() and rmdir(), close leak in rename()
In case of directory-overwriting rename(), omfs forgot to mark the victim doomed, so omfs_evict_inode() didn't free it. We could fix that by calling omfs_rmdir() for directory victims instead of doing omfs_unlink(), but it's easier to merge omfs_unlink() and omfs_rmdir() instead. Note that we have no hardlinks here. It also makes the checks in omfs_rename() go away - they fold into what omfs_remove() does when it runs into a directory. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Bob Copeland <me@bobcopeland.com>
-rw-r--r--fs/omfs/dir.c53
1 files changed, 13 insertions, 40 deletions
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c
index a4c2d31b785e..fd91f629ceb8 100644
--- a/fs/omfs/dir.c
+++ b/fs/omfs/dir.c
@@ -235,33 +235,22 @@ static int omfs_dir_is_empty(struct inode *inode)
235 return *ptr != ~0; 235 return *ptr != ~0;
236} 236}
237 237
238static int omfs_unlink(struct inode *dir, struct dentry *dentry) 238static int omfs_remove(struct inode *dir, struct dentry *dentry)
239{ 239{
240 int ret;
241 struct inode *inode = dentry->d_inode; 240 struct inode *inode = dentry->d_inode;
241 int ret;
242
243 if (S_ISDIR(inode->i_mode) && !omfs_dir_is_empty(inode))
244 return -ENOTEMPTY;
242 245
243 ret = omfs_delete_entry(dentry); 246 ret = omfs_delete_entry(dentry);
244 if (ret) 247 if (ret)
245 goto end_unlink; 248 return ret;
246 249
247 inode_dec_link_count(inode); 250 clear_nlink(inode);
251 mark_inode_dirty(inode);
248 mark_inode_dirty(dir); 252 mark_inode_dirty(dir);
249 253 return 0;
250end_unlink:
251 return ret;
252}
253
254static int omfs_rmdir(struct inode *dir, struct dentry *dentry)
255{
256 int err = -ENOTEMPTY;
257 struct inode *inode = dentry->d_inode;
258
259 if (omfs_dir_is_empty(inode)) {
260 err = omfs_unlink(dir, dentry);
261 if (!err)
262 inode_dec_link_count(inode);
263 }
264 return err;
265} 254}
266 255
267static int omfs_add_node(struct inode *dir, struct dentry *dentry, int mode) 256static int omfs_add_node(struct inode *dir, struct dentry *dentry, int mode)
@@ -385,33 +374,17 @@ static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry,
385{ 374{
386 struct inode *new_inode = new_dentry->d_inode; 375 struct inode *new_inode = new_dentry->d_inode;
387 struct inode *old_inode = old_dentry->d_inode; 376 struct inode *old_inode = old_dentry->d_inode;
388 struct buffer_head *bh;
389 int is_dir;
390 int err; 377 int err;
391 378
392 is_dir = S_ISDIR(old_inode->i_mode);
393
394 if (new_inode) { 379 if (new_inode) {
395 /* overwriting existing file/dir */ 380 /* overwriting existing file/dir */
396 err = -ENOTEMPTY; 381 err = omfs_remove(new_dir, new_dentry);
397 if (is_dir && !omfs_dir_is_empty(new_inode))
398 goto out;
399
400 err = -ENOENT;
401 bh = omfs_find_entry(new_dir, new_dentry->d_name.name,
402 new_dentry->d_name.len);
403 if (IS_ERR(bh))
404 goto out;
405 brelse(bh);
406
407 err = omfs_unlink(new_dir, new_dentry);
408 if (err) 382 if (err)
409 goto out; 383 goto out;
410 } 384 }
411 385
412 /* since omfs locates files by name, we need to unlink _before_ 386 /* since omfs locates files by name, we need to unlink _before_
413 * adding the new link or we won't find the old one */ 387 * adding the new link or we won't find the old one */
414 inode_inc_link_count(old_inode);
415 err = omfs_delete_entry(old_dentry); 388 err = omfs_delete_entry(old_dentry);
416 if (err) 389 if (err)
417 goto out; 390 goto out;
@@ -488,8 +461,8 @@ const struct inode_operations omfs_dir_inops = {
488 .mkdir = omfs_mkdir, 461 .mkdir = omfs_mkdir,
489 .rename = omfs_rename, 462 .rename = omfs_rename,
490 .create = omfs_create, 463 .create = omfs_create,
491 .unlink = omfs_unlink, 464 .unlink = omfs_remove,
492 .rmdir = omfs_rmdir, 465 .rmdir = omfs_remove,
493}; 466};
494 467
495const struct file_operations omfs_dir_operations = { 468const struct file_operations omfs_dir_operations = {