diff options
Diffstat (limited to 'fs/affs/namei.c')
-rw-r--r-- | fs/affs/namei.c | 87 |
1 files changed, 73 insertions, 14 deletions
diff --git a/fs/affs/namei.c b/fs/affs/namei.c index 96dd1d09a273..46d3ace6761d 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c | |||
@@ -365,6 +365,7 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
365 | symname++; | 365 | symname++; |
366 | } | 366 | } |
367 | *p = 0; | 367 | *p = 0; |
368 | inode->i_size = i + 1; | ||
368 | mark_buffer_dirty_inode(bh, inode); | 369 | mark_buffer_dirty_inode(bh, inode); |
369 | affs_brelse(bh); | 370 | affs_brelse(bh); |
370 | mark_inode_dirty(inode); | 371 | mark_inode_dirty(inode); |
@@ -393,21 +394,14 @@ affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |||
393 | return affs_add_entry(dir, inode, dentry, ST_LINKFILE); | 394 | return affs_add_entry(dir, inode, dentry, ST_LINKFILE); |
394 | } | 395 | } |
395 | 396 | ||
396 | int | 397 | static int |
397 | affs_rename(struct inode *old_dir, struct dentry *old_dentry, | 398 | affs_rename(struct inode *old_dir, struct dentry *old_dentry, |
398 | struct inode *new_dir, struct dentry *new_dentry, | 399 | struct inode *new_dir, struct dentry *new_dentry) |
399 | unsigned int flags) | ||
400 | { | 400 | { |
401 | struct super_block *sb = old_dir->i_sb; | 401 | struct super_block *sb = old_dir->i_sb; |
402 | struct buffer_head *bh = NULL; | 402 | struct buffer_head *bh = NULL; |
403 | int retval; | 403 | int retval; |
404 | 404 | ||
405 | if (flags & ~RENAME_NOREPLACE) | ||
406 | return -EINVAL; | ||
407 | |||
408 | pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__, | ||
409 | old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry); | ||
410 | |||
411 | retval = affs_check_name(new_dentry->d_name.name, | 405 | retval = affs_check_name(new_dentry->d_name.name, |
412 | new_dentry->d_name.len, | 406 | new_dentry->d_name.len, |
413 | affs_nofilenametruncate(old_dentry)); | 407 | affs_nofilenametruncate(old_dentry)); |
@@ -447,6 +441,76 @@ done: | |||
447 | return retval; | 441 | return retval; |
448 | } | 442 | } |
449 | 443 | ||
444 | static int | ||
445 | affs_xrename(struct inode *old_dir, struct dentry *old_dentry, | ||
446 | struct inode *new_dir, struct dentry *new_dentry) | ||
447 | { | ||
448 | |||
449 | struct super_block *sb = old_dir->i_sb; | ||
450 | struct buffer_head *bh_old = NULL; | ||
451 | struct buffer_head *bh_new = NULL; | ||
452 | int retval; | ||
453 | |||
454 | bh_old = affs_bread(sb, d_inode(old_dentry)->i_ino); | ||
455 | if (!bh_old) | ||
456 | return -EIO; | ||
457 | |||
458 | bh_new = affs_bread(sb, d_inode(new_dentry)->i_ino); | ||
459 | if (!bh_new) | ||
460 | return -EIO; | ||
461 | |||
462 | /* Remove old header from its parent directory. */ | ||
463 | affs_lock_dir(old_dir); | ||
464 | retval = affs_remove_hash(old_dir, bh_old); | ||
465 | affs_unlock_dir(old_dir); | ||
466 | if (retval) | ||
467 | goto done; | ||
468 | |||
469 | /* Remove new header from its parent directory. */ | ||
470 | affs_lock_dir(new_dir); | ||
471 | retval = affs_remove_hash(new_dir, bh_new); | ||
472 | affs_unlock_dir(new_dir); | ||
473 | if (retval) | ||
474 | goto done; | ||
475 | |||
476 | /* Insert old into the new directory with the new name. */ | ||
477 | affs_copy_name(AFFS_TAIL(sb, bh_old)->name, new_dentry); | ||
478 | affs_fix_checksum(sb, bh_old); | ||
479 | affs_lock_dir(new_dir); | ||
480 | retval = affs_insert_hash(new_dir, bh_old); | ||
481 | affs_unlock_dir(new_dir); | ||
482 | |||
483 | /* Insert new into the old directory with the old name. */ | ||
484 | affs_copy_name(AFFS_TAIL(sb, bh_new)->name, old_dentry); | ||
485 | affs_fix_checksum(sb, bh_new); | ||
486 | affs_lock_dir(old_dir); | ||
487 | retval = affs_insert_hash(old_dir, bh_new); | ||
488 | affs_unlock_dir(old_dir); | ||
489 | done: | ||
490 | mark_buffer_dirty_inode(bh_old, new_dir); | ||
491 | mark_buffer_dirty_inode(bh_new, old_dir); | ||
492 | affs_brelse(bh_old); | ||
493 | affs_brelse(bh_new); | ||
494 | return retval; | ||
495 | } | ||
496 | |||
497 | int affs_rename2(struct inode *old_dir, struct dentry *old_dentry, | ||
498 | struct inode *new_dir, struct dentry *new_dentry, | ||
499 | unsigned int flags) | ||
500 | { | ||
501 | |||
502 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) | ||
503 | return -EINVAL; | ||
504 | |||
505 | pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__, | ||
506 | old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry); | ||
507 | |||
508 | if (flags & RENAME_EXCHANGE) | ||
509 | return affs_xrename(old_dir, old_dentry, new_dir, new_dentry); | ||
510 | |||
511 | return affs_rename(old_dir, old_dentry, new_dir, new_dentry); | ||
512 | } | ||
513 | |||
450 | static struct dentry *affs_get_parent(struct dentry *child) | 514 | static struct dentry *affs_get_parent(struct dentry *child) |
451 | { | 515 | { |
452 | struct inode *parent; | 516 | struct inode *parent; |
@@ -477,11 +541,6 @@ static struct inode *affs_nfs_get_inode(struct super_block *sb, u64 ino, | |||
477 | if (IS_ERR(inode)) | 541 | if (IS_ERR(inode)) |
478 | return ERR_CAST(inode); | 542 | return ERR_CAST(inode); |
479 | 543 | ||
480 | if (generation && inode->i_generation != generation) { | ||
481 | iput(inode); | ||
482 | return ERR_PTR(-ESTALE); | ||
483 | } | ||
484 | |||
485 | return inode; | 544 | return inode; |
486 | } | 545 | } |
487 | 546 | ||