diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:50:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:50:52 -0400 |
commit | 3f6f7e6d57b8a0ae2810ae7aac70c51b6f2a6304 (patch) | |
tree | ed4460a8f072cd088e225163bdeeafc5ce9fecb6 /fs | |
parent | 8f627a8a881481598c2591c3acc122fb9be7bac4 (diff) | |
parent | 31be83aeaee22fa165862ad449c7131ceaf1cf91 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/bcopeland/omfs
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/bcopeland/omfs:
omfs: make readdir stop when filldir says so
omfs: merge unlink() and rmdir(), close leak in rename()
omfs: stop playing silly buggers with omfs_unlink() in ->rename()
omfs: rename() needs to mark old_inode dirty after ctime update
Diffstat (limited to 'fs')
-rw-r--r-- | fs/omfs/dir.c | 66 |
1 files changed, 20 insertions, 46 deletions
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c index 393f3f659da7..de4ff29f1e05 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 | ||
238 | static int omfs_unlink(struct inode *dir, struct dentry *dentry) | 238 | static 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; | |
250 | end_unlink: | ||
251 | return ret; | ||
252 | } | ||
253 | |||
254 | static 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 | ||
267 | static int omfs_add_node(struct inode *dir, struct dentry *dentry, int mode) | 256 | static int omfs_add_node(struct inode *dir, struct dentry *dentry, int mode) |
@@ -372,9 +361,10 @@ static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir, | |||
372 | 361 | ||
373 | res = filldir(dirent, oi->i_name, strnlen(oi->i_name, | 362 | res = filldir(dirent, oi->i_name, strnlen(oi->i_name, |
374 | OMFS_NAMELEN), filp->f_pos, self, d_type); | 363 | OMFS_NAMELEN), filp->f_pos, self, d_type); |
375 | if (res == 0) | ||
376 | filp->f_pos++; | ||
377 | brelse(bh); | 364 | brelse(bh); |
365 | if (res < 0) | ||
366 | break; | ||
367 | filp->f_pos++; | ||
378 | } | 368 | } |
379 | out: | 369 | out: |
380 | return res; | 370 | return res; |
@@ -385,44 +375,28 @@ static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
385 | { | 375 | { |
386 | struct inode *new_inode = new_dentry->d_inode; | 376 | struct inode *new_inode = new_dentry->d_inode; |
387 | struct inode *old_inode = old_dentry->d_inode; | 377 | struct inode *old_inode = old_dentry->d_inode; |
388 | struct buffer_head *bh; | ||
389 | int is_dir; | ||
390 | int err; | 378 | int err; |
391 | 379 | ||
392 | is_dir = S_ISDIR(old_inode->i_mode); | ||
393 | |||
394 | if (new_inode) { | 380 | if (new_inode) { |
395 | /* overwriting existing file/dir */ | 381 | /* overwriting existing file/dir */ |
396 | err = -ENOTEMPTY; | 382 | 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) | 383 | if (err) |
409 | goto out; | 384 | goto out; |
410 | } | 385 | } |
411 | 386 | ||
412 | /* since omfs locates files by name, we need to unlink _before_ | 387 | /* since omfs locates files by name, we need to unlink _before_ |
413 | * adding the new link or we won't find the old one */ | 388 | * adding the new link or we won't find the old one */ |
414 | inode_inc_link_count(old_inode); | 389 | err = omfs_delete_entry(old_dentry); |
415 | err = omfs_unlink(old_dir, old_dentry); | 390 | if (err) |
416 | if (err) { | ||
417 | inode_dec_link_count(old_inode); | ||
418 | goto out; | 391 | goto out; |
419 | } | ||
420 | 392 | ||
393 | mark_inode_dirty(old_dir); | ||
421 | err = omfs_add_link(new_dentry, old_inode); | 394 | err = omfs_add_link(new_dentry, old_inode); |
422 | if (err) | 395 | if (err) |
423 | goto out; | 396 | goto out; |
424 | 397 | ||
425 | old_inode->i_ctime = CURRENT_TIME_SEC; | 398 | old_inode->i_ctime = CURRENT_TIME_SEC; |
399 | mark_inode_dirty(old_inode); | ||
426 | out: | 400 | out: |
427 | return err; | 401 | return err; |
428 | } | 402 | } |
@@ -488,8 +462,8 @@ const struct inode_operations omfs_dir_inops = { | |||
488 | .mkdir = omfs_mkdir, | 462 | .mkdir = omfs_mkdir, |
489 | .rename = omfs_rename, | 463 | .rename = omfs_rename, |
490 | .create = omfs_create, | 464 | .create = omfs_create, |
491 | .unlink = omfs_unlink, | 465 | .unlink = omfs_remove, |
492 | .rmdir = omfs_rmdir, | 466 | .rmdir = omfs_remove, |
493 | }; | 467 | }; |
494 | 468 | ||
495 | const struct file_operations omfs_dir_operations = { | 469 | const struct file_operations omfs_dir_operations = { |