swap: change swap_list_head to plist, add swap_avail_head
[platform/adaptation/renesas_rcar/renesas_kernel.git] / fs / open.c
index d420331..2ed7325 100644 (file)
--- 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,
                newattrs.ia_valid |= ret | ATTR_FORCE;
 
        mutex_lock(&dentry->d_inode->i_mutex);
-       ret = notify_change(dentry, &newattrs);
+       /* Note any delegations or leases have already been broken: */
+       ret = notify_change(dentry, &newattrs, NULL);
        mutex_unlock(&dentry->d_inode->i_mutex);
        return ret;
 }
@@ -464,21 +465,28 @@ out:
 static int chmod_common(struct path *path, umode_t mode)
 {
        struct inode *inode = path->dentry->d_inode;
+       struct inode *delegated_inode = NULL;
        struct iattr newattrs;
        int error;
 
        error = mnt_want_write(path->mnt);
        if (error)
                return error;
+retry_deleg:
        mutex_lock(&inode->i_mutex);
        error = security_path_chmod(path, mode);
        if (error)
                goto out_unlock;
        newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-       error = notify_change(path->dentry, &newattrs);
+       error = notify_change(path->dentry, &newattrs, &delegated_inode);
 out_unlock:
        mutex_unlock(&inode->i_mutex);
+       if (delegated_inode) {
+               error = break_deleg_wait(&delegated_inode);
+               if (!error)
+                       goto retry_deleg;
+       }
        mnt_drop_write(path->mnt);
        return error;
 }
@@ -522,6 +530,7 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
 static int chown_common(struct path *path, uid_t user, gid_t group)
 {
        struct inode *inode = path->dentry->d_inode;
+       struct inode *delegated_inode = NULL;
        int error;
        struct iattr newattrs;
        kuid_t uid;
@@ -546,12 +555,17 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
        if (!S_ISDIR(inode->i_mode))
                newattrs.ia_valid |=
                        ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+retry_deleg:
        mutex_lock(&inode->i_mutex);
        error = security_path_chown(path, uid, gid);
        if (!error)
-               error = notify_change(path->dentry, &newattrs);
+               error = notify_change(path->dentry, &newattrs, &delegated_inode);
        mutex_unlock(&inode->i_mutex);
-
+       if (delegated_inode) {
+               error = break_deleg_wait(&delegated_inode);
+               if (!error)
+                       goto retry_deleg;
+       }
        return error;
 }
 
@@ -627,23 +641,12 @@ out:
 static inline int __get_file_write_access(struct inode *inode,
                                          struct vfsmount *mnt)
 {
-       int error;
-       error = get_write_access(inode);
+       int error = get_write_access(inode);
        if (error)
                return error;
-       /*
-        * Do not take mount writer counts on
-        * special files since no writes to
-        * the mount itself will occur.
-        */
-       if (!special_file(inode->i_mode)) {
-               /*
-                * Balanced in __fput()
-                */
-               error = __mnt_want_write(mnt);
-               if (error)
-                       put_write_access(inode);
-       }
+       error = __mnt_want_write(mnt);
+       if (error)
+               put_write_access(inode);
        return error;
 }
 
@@ -676,23 +679,29 @@ static int do_dentry_open(struct file *f,
 
        path_get(&f->f_path);
        inode = f->f_inode = f->f_path.dentry->d_inode;
-       if (f->f_mode & FMODE_WRITE) {
+       if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) {
                error = __get_file_write_access(inode, f->f_path.mnt);
                if (error)
                        goto cleanup_file;
-               if (!special_file(inode->i_mode))
-                       file_take_write(f);
+               file_take_write(f);
        }
 
        f->f_mapping = inode->i_mapping;
-       file_sb_list_add(f, inode->i_sb);
 
        if (unlikely(f->f_mode & FMODE_PATH)) {
                f->f_op = &empty_fops;
                return 0;
        }
 
+       /* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */
+       if (S_ISREG(inode->i_mode))
+               f->f_mode |= FMODE_ATOMIC_POS;
+
        f->f_op = fops_get(inode->i_fop);
+       if (unlikely(WARN_ON(!f->f_op))) {
+               error = -ENODEV;
+               goto cleanup_all;
+       }
 
        error = security_file_open(f, cred);
        if (error)
@@ -702,7 +711,7 @@ static int do_dentry_open(struct file *f,
        if (error)
                goto cleanup_all;
 
-       if (!open && f->f_op)
+       if (!open)
                open = f->f_op->open;
        if (open) {
                error = open(inode, f);
@@ -720,9 +729,7 @@ static int do_dentry_open(struct file *f,
 
 cleanup_all:
        fops_put(f->f_op);
-       file_sb_list_del(f);
        if (f->f_mode & FMODE_WRITE) {
-               put_write_access(inode);
                if (!special_file(inode->i_mode)) {
                        /*
                         * We don't consider this a real
@@ -730,6 +737,7 @@ cleanup_all:
                         * because it all happenend right
                         * here, so just reset the state.
                         */
+                       put_write_access(inode);
                        file_reset_write(f);
                        __mnt_drop_write(f->f_path.mnt);
                }
@@ -1023,7 +1031,7 @@ int filp_close(struct file *filp, fl_owner_t id)
                return 0;
        }
 
-       if (filp->f_op && filp->f_op->flush)
+       if (filp->f_op->flush)
                retval = filp->f_op->flush(filp, id);
 
        if (likely(!(filp->f_mode & FMODE_PATH))) {