Merge branch 'akpm' (patches from Andrew Morton)
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 30 Jan 2014 00:22:54 +0000 (16:22 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 30 Jan 2014 00:22:54 +0000 (16:22 -0800)
Merge random fixes from Andrew Morton:
 "Random fixes.

  I have one batch remaining for -rc1, mainly zram changes which await a
  merge of Jens's trees"

* emailed patches fron Andrew Morton akpm@linux-foundation.org>:
  MAINTAINERS: ADI Linux development mailing lists: change to the new server
  Documentation: fix multiple typo occurences s/KenelVersion/KernelVersion/
  dma-debug: fix overlap detection
  memblock: add limit checking to memblock_virt_alloc
  mm/readahead.c: fix do_readahead() for no readpage(s)
  mm/slub.c: do not VM_BUG_ON_PAGE() for temporary on-stack pages
  slab: fix wrong retval on kmem_cache_create_memcg error path
  s390/compat: change parameter types from unsigned long to compat_ulong_t
  fs/compat: fix lookup_dcookie() parameter handling
  fs/compat: fix parameter handling for compat readv/writev syscalls
  mm/mempolicy.c: convert to pr_foo()
  mm: numa: initialise numa balancing after jump label initialisation
  mm/page-writeback.c: do not count anon pages as dirtyable memory
  mm/page-writeback.c: fix dirty_balance_reserve subtraction from dirtyable memory
  mm: document improved handling of swappiness==0
  lib/genalloc.c: add check gen_pool_dma_alloc() if dma pointer is not NULL

fs/ceph/acl.c
fs/ceph/dir.c
fs/ceph/inode.c
fs/ceph/super.h
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify.h
fs/notify/fanotify/fanotify_user.c
fs/notify/inotify/inotify_fsnotify.c
fs/notify/notification.c
include/linux/fsnotify_backend.h

index f691128..66d377a 100644 (file)
@@ -107,14 +107,14 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type)
        return acl;
 }
 
-static int ceph_set_acl(struct dentry *dentry, struct inode *inode,
-                               struct posix_acl *acl, int type)
+int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
        int ret = 0, size = 0;
        const char *name = NULL;
        char *value = NULL;
        struct iattr newattrs;
        umode_t new_mode = inode->i_mode, old_mode = inode->i_mode;
+       struct dentry *dentry = d_find_alias(inode);
 
        if (acl) {
                ret = posix_acl_valid(acl);
@@ -208,8 +208,7 @@ int ceph_init_acl(struct dentry *dentry, struct inode *inode, struct inode *dir)
 
        if (IS_POSIXACL(dir) && acl) {
                if (S_ISDIR(inode->i_mode)) {
-                       ret = ceph_set_acl(dentry, inode, acl,
-                                               ACL_TYPE_DEFAULT);
+                       ret = ceph_set_acl(inode, acl, ACL_TYPE_DEFAULT);
                        if (ret)
                                goto out_release;
                }
@@ -217,7 +216,7 @@ int ceph_init_acl(struct dentry *dentry, struct inode *inode, struct inode *dir)
                if (ret < 0)
                        goto out;
                else if (ret > 0)
-                       ret = ceph_set_acl(dentry, inode, acl, ACL_TYPE_ACCESS);
+                       ret = ceph_set_acl(inode, acl, ACL_TYPE_ACCESS);
                else
                        cache_no_acl(inode);
        } else {
index 619616d..6da4df8 100644 (file)
@@ -1303,6 +1303,7 @@ const struct inode_operations ceph_dir_iops = {
        .listxattr = ceph_listxattr,
        .removexattr = ceph_removexattr,
        .get_acl = ceph_get_acl,
+       .set_acl = ceph_set_acl,
        .mknod = ceph_mknod,
        .symlink = ceph_symlink,
        .mkdir = ceph_mkdir,
index 8b8b506..32d519d 100644 (file)
@@ -97,6 +97,7 @@ const struct inode_operations ceph_file_iops = {
        .listxattr = ceph_listxattr,
        .removexattr = ceph_removexattr,
        .get_acl = ceph_get_acl,
+       .set_acl = ceph_set_acl,
 };
 
 
@@ -1616,6 +1617,7 @@ static const struct inode_operations ceph_symlink_iops = {
        .listxattr = ceph_listxattr,
        .removexattr = ceph_removexattr,
        .get_acl = ceph_get_acl,
+       .set_acl = ceph_set_acl,
 };
 
 /*
index 3459339..aa26059 100644 (file)
@@ -718,6 +718,7 @@ extern void ceph_queue_writeback(struct inode *inode);
 extern int ceph_do_getattr(struct inode *inode, int mask);
 extern int ceph_permission(struct inode *inode, int mask);
 extern int ceph_setattr(struct dentry *dentry, struct iattr *attr);
+extern int ceph_setattr(struct dentry *dentry, struct iattr *attr);
 extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry,
                        struct kstat *stat);
 
@@ -741,12 +742,14 @@ extern const struct xattr_handler *ceph_xattr_handlers[];
 #ifdef CONFIG_CEPH_FS_POSIX_ACL
 
 struct posix_acl *ceph_get_acl(struct inode *, int);
+int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 int ceph_init_acl(struct dentry *, struct inode *, struct inode *);
 void ceph_forget_all_cached_acls(struct inode *inode);
 
 #else
 
 #define ceph_get_acl NULL
+#define ceph_set_acl NULL
 
 static inline int ceph_init_acl(struct dentry *dentry, struct inode *inode,
                                struct inode *dir)
index 5877262..0e792f5 100644 (file)
@@ -16,12 +16,6 @@ static bool should_merge(struct fsnotify_event *old_fsn,
 {
        struct fanotify_event_info *old, *new;
 
-#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
-       /* dont merge two permission events */
-       if ((old_fsn->mask & FAN_ALL_PERM_EVENTS) &&
-           (new_fsn->mask & FAN_ALL_PERM_EVENTS))
-               return false;
-#endif
        pr_debug("%s: old=%p new=%p\n", __func__, old_fsn, new_fsn);
        old = FANOTIFY_E(old_fsn);
        new = FANOTIFY_E(new_fsn);
@@ -34,14 +28,23 @@ static bool should_merge(struct fsnotify_event *old_fsn,
 }
 
 /* and the list better be locked by something too! */
-static struct fsnotify_event *fanotify_merge(struct list_head *list,
-                                            struct fsnotify_event *event)
+static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
 {
        struct fsnotify_event *test_event;
        bool do_merge = false;
 
        pr_debug("%s: list=%p event=%p\n", __func__, list, event);
 
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+       /*
+        * Don't merge a permission event with any other event so that we know
+        * the event structure we have created in fanotify_handle_event() is the
+        * one we should check for permission response.
+        */
+       if (event->mask & FAN_ALL_PERM_EVENTS)
+               return 0;
+#endif
+
        list_for_each_entry_reverse(test_event, list, list) {
                if (should_merge(test_event, event)) {
                        do_merge = true;
@@ -50,10 +53,10 @@ static struct fsnotify_event *fanotify_merge(struct list_head *list,
        }
 
        if (!do_merge)
-               return NULL;
+               return 0;
 
        test_event->mask |= event->mask;
-       return test_event;
+       return 1;
 }
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
@@ -149,7 +152,6 @@ static int fanotify_handle_event(struct fsnotify_group *group,
        int ret = 0;
        struct fanotify_event_info *event;
        struct fsnotify_event *fsn_event;
-       struct fsnotify_event *notify_fsn_event;
 
        BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
        BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
@@ -188,21 +190,19 @@ static int fanotify_handle_event(struct fsnotify_group *group,
        event->response = 0;
 #endif
 
-       notify_fsn_event = fsnotify_add_notify_event(group, fsn_event,
-                                                    fanotify_merge);
-       if (notify_fsn_event) {
+       ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge);
+       if (ret) {
+               BUG_ON(mask & FAN_ALL_PERM_EVENTS);
                /* Our event wasn't used in the end. Free it. */
                fsnotify_destroy_event(group, fsn_event);
-               if (IS_ERR(notify_fsn_event))
-                       return PTR_ERR(notify_fsn_event);
-               /* We need to ask about a different events after a merge... */
-               event = FANOTIFY_E(notify_fsn_event);
-               fsn_event = notify_fsn_event;
+               ret = 0;
        }
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
-       if (fsn_event->mask & FAN_ALL_PERM_EVENTS)
+       if (mask & FAN_ALL_PERM_EVENTS) {
                ret = fanotify_get_response_from_access(group, event);
+               fsnotify_destroy_event(group, fsn_event);
+       }
 #endif
        return ret;
 }
index 0e90174..32a2f03 100644 (file)
@@ -4,6 +4,13 @@
 
 extern struct kmem_cache *fanotify_event_cachep;
 
+/*
+ * Lifetime of the structure differs for normal and permission events. In both
+ * cases the structure is allocated in fanotify_handle_event(). For normal
+ * events the structure is freed immediately after reporting it to userspace.
+ * For permission events we free it only after we receive response from
+ * userspace.
+ */
 struct fanotify_event_info {
        struct fsnotify_event fse;
        /*
index 1fd66ab..b6175fa 100644 (file)
@@ -319,7 +319,12 @@ static ssize_t fanotify_read(struct file *file, char __user *buf,
                        if (IS_ERR(kevent))
                                break;
                        ret = copy_event_to_user(group, kevent, buf);
-                       fsnotify_destroy_event(group, kevent);
+                       /*
+                        * Permission events get destroyed after we
+                        * receive response
+                        */
+                       if (!(kevent->mask & FAN_ALL_PERM_EVENTS))
+                               fsnotify_destroy_event(group, kevent);
                        if (ret < 0)
                                break;
                        buf += ret;
index aad1a35..d5ee563 100644 (file)
@@ -53,15 +53,13 @@ static bool event_compare(struct fsnotify_event *old_fsn,
        return false;
 }
 
-static struct fsnotify_event *inotify_merge(struct list_head *list,
-                                           struct fsnotify_event *event)
+static int inotify_merge(struct list_head *list,
+                         struct fsnotify_event *event)
 {
        struct fsnotify_event *last_event;
 
        last_event = list_entry(list->prev, struct fsnotify_event, list);
-       if (!event_compare(last_event, event))
-               return NULL;
-       return last_event;
+       return event_compare(last_event, event);
 }
 
 int inotify_handle_event(struct fsnotify_group *group,
@@ -73,9 +71,8 @@ int inotify_handle_event(struct fsnotify_group *group,
 {
        struct inotify_inode_mark *i_mark;
        struct inotify_event_info *event;
-       struct fsnotify_event *added_event;
        struct fsnotify_event *fsn_event;
-       int ret = 0;
+       int ret;
        int len = 0;
        int alloc_len = sizeof(struct inotify_event_info);
 
@@ -110,18 +107,16 @@ int inotify_handle_event(struct fsnotify_group *group,
        if (len)
                strcpy(event->name, file_name);
 
-       added_event = fsnotify_add_notify_event(group, fsn_event, inotify_merge);
-       if (added_event) {
+       ret = fsnotify_add_notify_event(group, fsn_event, inotify_merge);
+       if (ret) {
                /* Our event wasn't used in the end. Free it. */
                fsnotify_destroy_event(group, fsn_event);
-               if (IS_ERR(added_event))
-                       ret = PTR_ERR(added_event);
        }
 
        if (inode_mark->mask & IN_ONESHOT)
                fsnotify_destroy_mark(inode_mark, group);
 
-       return ret;
+       return 0;
 }
 
 static void inotify_freeing_mark(struct fsnotify_mark *fsn_mark, struct fsnotify_group *group)
index 952237b..18b3c44 100644 (file)
@@ -79,15 +79,15 @@ void fsnotify_destroy_event(struct fsnotify_group *group,
 
 /*
  * Add an event to the group notification queue.  The group can later pull this
- * event off the queue to deal with.  If the event is successfully added to the
- * group's notification queue, a reference is taken on event.
+ * event off the queue to deal with.  The function returns 0 if the event was
+ * added to the queue, 1 if the event was merged with some other queued event.
  */
-struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group,
-                                                struct fsnotify_event *event,
-                                                struct fsnotify_event *(*merge)(struct list_head *,
-                                                                                struct fsnotify_event *))
+int fsnotify_add_notify_event(struct fsnotify_group *group,
+                             struct fsnotify_event *event,
+                             int (*merge)(struct list_head *,
+                                          struct fsnotify_event *))
 {
-       struct fsnotify_event *return_event = NULL;
+       int ret = 0;
        struct list_head *list = &group->notification_list;
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
@@ -98,14 +98,14 @@ struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group,
                /* Queue overflow event only if it isn't already queued */
                if (list_empty(&group->overflow_event.list))
                        event = &group->overflow_event;
-               return_event = event;
+               ret = 1;
        }
 
        if (!list_empty(list) && merge) {
-               return_event = merge(list, event);
-               if (return_event) {
+               ret = merge(list, event);
+               if (ret) {
                        mutex_unlock(&group->notification_mutex);
-                       return return_event;
+                       return ret;
                }
        }
 
@@ -115,7 +115,7 @@ struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group,
 
        wake_up(&group->notification_waitq);
        kill_fasync(&group->fsn_fa, SIGIO, POLL_IN);
-       return return_event;
+       return ret;
 }
 
 /*
index 7d8d5e6..3d286ff 100644 (file)
@@ -322,10 +322,10 @@ extern int fsnotify_fasync(int fd, struct file *file, int on);
 extern void fsnotify_destroy_event(struct fsnotify_group *group,
                                   struct fsnotify_event *event);
 /* attach the event to the group notification queue */
-extern struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group,
-                                                       struct fsnotify_event *event,
-                                                       struct fsnotify_event *(*merge)(struct list_head *,
-                                                                                       struct fsnotify_event *));
+extern int fsnotify_add_notify_event(struct fsnotify_group *group,
+                                    struct fsnotify_event *event,
+                                    int (*merge)(struct list_head *,
+                                                 struct fsnotify_event *));
 /* true if the group notification queue is empty */
 extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group);
 /* return, but do not dequeue the first event on the notification queue */