summaryrefslogtreecommitdiffstats
path: root/fs/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/open.c')
-rw-r--r--fs/open.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/fs/open.c b/fs/open.c
index d420331ca32a..4b3e1edf2fe4 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -57,7 +57,8 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
57 newattrs.ia_valid |= ret | ATTR_FORCE; 57 newattrs.ia_valid |= ret | ATTR_FORCE;
58 58
59 mutex_lock(&dentry->d_inode->i_mutex); 59 mutex_lock(&dentry->d_inode->i_mutex);
60 ret = notify_change(dentry, &newattrs); 60 /* Note any delegations or leases have already been broken: */
61 ret = notify_change(dentry, &newattrs, NULL);
61 mutex_unlock(&dentry->d_inode->i_mutex); 62 mutex_unlock(&dentry->d_inode->i_mutex);
62 return ret; 63 return ret;
63} 64}
@@ -464,21 +465,28 @@ out:
464static int chmod_common(struct path *path, umode_t mode) 465static int chmod_common(struct path *path, umode_t mode)
465{ 466{
466 struct inode *inode = path->dentry->d_inode; 467 struct inode *inode = path->dentry->d_inode;
468 struct inode *delegated_inode = NULL;
467 struct iattr newattrs; 469 struct iattr newattrs;
468 int error; 470 int error;
469 471
470 error = mnt_want_write(path->mnt); 472 error = mnt_want_write(path->mnt);
471 if (error) 473 if (error)
472 return error; 474 return error;
475retry_deleg:
473 mutex_lock(&inode->i_mutex); 476 mutex_lock(&inode->i_mutex);
474 error = security_path_chmod(path, mode); 477 error = security_path_chmod(path, mode);
475 if (error) 478 if (error)
476 goto out_unlock; 479 goto out_unlock;
477 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); 480 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
478 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; 481 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
479 error = notify_change(path->dentry, &newattrs); 482 error = notify_change(path->dentry, &newattrs, &delegated_inode);
480out_unlock: 483out_unlock:
481 mutex_unlock(&inode->i_mutex); 484 mutex_unlock(&inode->i_mutex);
485 if (delegated_inode) {
486 error = break_deleg_wait(&delegated_inode);
487 if (!error)
488 goto retry_deleg;
489 }
482 mnt_drop_write(path->mnt); 490 mnt_drop_write(path->mnt);
483 return error; 491 return error;
484} 492}
@@ -522,6 +530,7 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
522static int chown_common(struct path *path, uid_t user, gid_t group) 530static int chown_common(struct path *path, uid_t user, gid_t group)
523{ 531{
524 struct inode *inode = path->dentry->d_inode; 532 struct inode *inode = path->dentry->d_inode;
533 struct inode *delegated_inode = NULL;
525 int error; 534 int error;
526 struct iattr newattrs; 535 struct iattr newattrs;
527 kuid_t uid; 536 kuid_t uid;
@@ -546,12 +555,17 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
546 if (!S_ISDIR(inode->i_mode)) 555 if (!S_ISDIR(inode->i_mode))
547 newattrs.ia_valid |= 556 newattrs.ia_valid |=
548 ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; 557 ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
558retry_deleg:
549 mutex_lock(&inode->i_mutex); 559 mutex_lock(&inode->i_mutex);
550 error = security_path_chown(path, uid, gid); 560 error = security_path_chown(path, uid, gid);
551 if (!error) 561 if (!error)
552 error = notify_change(path->dentry, &newattrs); 562 error = notify_change(path->dentry, &newattrs, &delegated_inode);
553 mutex_unlock(&inode->i_mutex); 563 mutex_unlock(&inode->i_mutex);
554 564 if (delegated_inode) {
565 error = break_deleg_wait(&delegated_inode);
566 if (!error)
567 goto retry_deleg;
568 }
555 return error; 569 return error;
556} 570}
557 571
@@ -685,7 +699,6 @@ static int do_dentry_open(struct file *f,
685 } 699 }
686 700
687 f->f_mapping = inode->i_mapping; 701 f->f_mapping = inode->i_mapping;
688 file_sb_list_add(f, inode->i_sb);
689 702
690 if (unlikely(f->f_mode & FMODE_PATH)) { 703 if (unlikely(f->f_mode & FMODE_PATH)) {
691 f->f_op = &empty_fops; 704 f->f_op = &empty_fops;
@@ -693,6 +706,10 @@ static int do_dentry_open(struct file *f,
693 } 706 }
694 707
695 f->f_op = fops_get(inode->i_fop); 708 f->f_op = fops_get(inode->i_fop);
709 if (unlikely(WARN_ON(!f->f_op))) {
710 error = -ENODEV;
711 goto cleanup_all;
712 }
696 713
697 error = security_file_open(f, cred); 714 error = security_file_open(f, cred);
698 if (error) 715 if (error)
@@ -702,7 +719,7 @@ static int do_dentry_open(struct file *f,
702 if (error) 719 if (error)
703 goto cleanup_all; 720 goto cleanup_all;
704 721
705 if (!open && f->f_op) 722 if (!open)
706 open = f->f_op->open; 723 open = f->f_op->open;
707 if (open) { 724 if (open) {
708 error = open(inode, f); 725 error = open(inode, f);
@@ -720,7 +737,6 @@ static int do_dentry_open(struct file *f,
720 737
721cleanup_all: 738cleanup_all:
722 fops_put(f->f_op); 739 fops_put(f->f_op);
723 file_sb_list_del(f);
724 if (f->f_mode & FMODE_WRITE) { 740 if (f->f_mode & FMODE_WRITE) {
725 put_write_access(inode); 741 put_write_access(inode);
726 if (!special_file(inode->i_mode)) { 742 if (!special_file(inode->i_mode)) {
@@ -1023,7 +1039,7 @@ int filp_close(struct file *filp, fl_owner_t id)
1023 return 0; 1039 return 0;
1024 } 1040 }
1025 1041
1026 if (filp->f_op && filp->f_op->flush) 1042 if (filp->f_op->flush)
1027 retval = filp->f_op->flush(filp, id); 1043 retval = filp->f_op->flush(filp, id);
1028 1044
1029 if (likely(!(filp->f_mode & FMODE_PATH))) { 1045 if (likely(!(filp->f_mode & FMODE_PATH))) {