ARM64: dts: rk3328-evb: add support for internal codec sound
[firefly-linux-kernel-4.4.55.git] / fs / attr.c
index 6530ced19697d49a9189fa289c9112187448fee3..11be2265a2d55cb0688231698770b29ee357b0f1 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -187,7 +187,7 @@ EXPORT_SYMBOL(setattr_copy);
  * the file open for write, as there can be no conflicting delegation in
  * that case.
  */
-int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
+int notify_change2(struct vfsmount *mnt, struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
 {
        struct inode *inode = dentry->d_inode;
        umode_t mode = inode->i_mode;
@@ -202,6 +202,21 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
                        return -EPERM;
        }
 
+       /*
+        * If utimes(2) and friends are called with times == NULL (or both
+        * times are UTIME_NOW), then we need to check for write permission
+        */
+       if (ia_valid & ATTR_TOUCH) {
+               if (IS_IMMUTABLE(inode))
+                       return -EPERM;
+
+               if (!inode_owner_or_capable(inode)) {
+                       error = inode_permission(inode, MAY_WRITE);
+                       if (error)
+                               return error;
+               }
+       }
+
        if ((ia_valid & ATTR_MODE)) {
                umode_t amode = attr->ia_mode;
                /* Flag setting protected by i_mutex */
@@ -262,7 +277,9 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
        if (error)
                return error;
 
-       if (inode->i_op->setattr)
+       if (mnt && inode->i_op->setattr2)
+               error = inode->i_op->setattr2(mnt, dentry, attr);
+       else if (inode->i_op->setattr)
                error = inode->i_op->setattr(dentry, attr);
        else
                error = simple_setattr(dentry, attr);
@@ -275,4 +292,10 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
 
        return error;
 }
+EXPORT_SYMBOL(notify_change2);
+
+int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
+{
+       return notify_change2(NULL, dentry, attr, delegated_inode);
+}
 EXPORT_SYMBOL(notify_change);