Merge tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/steve...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 4 Apr 2014 21:49:16 +0000 (14:49 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 4 Apr 2014 21:49:16 +0000 (14:49 -0700)
Pull GFS2 updates from Steven Whitehouse:
 "One of the main highlights this time, is not the patches themselves
  but instead the widening contributor base.  It is good to see that
  interest is increasing in GFS2, and I'd like to thank all the
  contributors to this patch set.

  In addition to the usual set of bug fixes and clean ups, there are
  patches to improve inode creation performance when xattrs are required
  and some improvements to the transaction code which is intended to
  help improve scalability after further changes in due course.

  Journal extent mapping is also updated to make it more efficient and
  again, this is a foundation for future work in this area.

  The maximum number of ACLs has been increased to 300 (for a 4k block
  size) which means that even with a few additional xattrs from selinux,
  everything should fit within a single fs block.

  There is also a patch to bring GFS2's own copy of the writepages code
  up to the same level as the core VFS.  Eventually we may be able to
  merge some of this code, since it is fairly similar.

  The other major change this time, is bringing consistency to the
  printing of messages via fs_<level>, pr_<level> macros"

* tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw: (29 commits)
  GFS2: Fix address space from page function
  GFS2: Fix uninitialized VFS inode in gfs2_create_inode
  GFS2: Fix return value in slot_get()
  GFS2: inline function gfs2_set_mode
  GFS2: Remove extraneous function gfs2_security_init
  GFS2: Increase the max number of ACLs
  GFS2: Re-add a call to log_flush_wait when flushing the journal
  GFS2: Ensure workqueue is scheduled after noexp request
  GFS2: check NULL return value in gfs2_ok_to_move
  GFS2: Convert gfs2_lm_withdraw to use fs_err
  GFS2: Use fs_<level> more often
  GFS2: Use pr_<level> more consistently
  GFS2: Move recovery variables to journal structure in memory
  GFS2: global conversion to pr_foo()
  GFS2: return -E2BIG if hit the maximum limits of ACLs
  GFS2: Clean up journal extent mapping
  GFS2: replace kmalloc - __vmalloc / memset 0
  GFS2: Remove extra "if" in gfs2_log_flush()
  fs: NULL dereference in posix_acl_to_xattr()
  GFS2: Move log buffer accounting to transaction
  ...

1  2 
fs/fs-writeback.c
fs/gfs2/super.c
fs/posix_acl.c

diff --combined fs/fs-writeback.c
  struct wb_writeback_work {
        long nr_pages;
        struct super_block *sb;
 -      /*
 -       * Write only inodes dirtied before this time. Don't forget to set
 -       * older_than_this_is_set when you set this.
 -       */
 -      unsigned long older_than_this;
 +      unsigned long *older_than_this;
        enum writeback_sync_modes sync_mode;
        unsigned int tagged_writepages:1;
        unsigned int for_kupdate:1;
        unsigned int range_cyclic:1;
        unsigned int for_background:1;
        unsigned int for_sync:1;        /* sync(2) WB_SYNC_ALL writeback */
 -      unsigned int older_than_this_is_set:1;
        enum wb_reason reason;          /* why was writeback initiated? */
  
        struct list_head list;          /* pending work list */
@@@ -89,29 -94,18 +89,31 @@@ static inline struct inode *wb_inode(st
  #define CREATE_TRACE_POINTS
  #include <trace/events/writeback.h>
  
+ EXPORT_TRACEPOINT_SYMBOL_GPL(wbc_writepage);
 +static void bdi_wakeup_thread(struct backing_dev_info *bdi)
 +{
 +      spin_lock_bh(&bdi->wb_lock);
 +      if (test_bit(BDI_registered, &bdi->state))
 +              mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0);
 +      spin_unlock_bh(&bdi->wb_lock);
 +}
 +
  static void bdi_queue_work(struct backing_dev_info *bdi,
                           struct wb_writeback_work *work)
  {
        trace_writeback_queue(bdi, work);
  
        spin_lock_bh(&bdi->wb_lock);
 +      if (!test_bit(BDI_registered, &bdi->state)) {
 +              if (work->done)
 +                      complete(work->done);
 +              goto out_unlock;
 +      }
        list_add_tail(&work->list, &bdi->work_list);
 -      spin_unlock_bh(&bdi->wb_lock);
 -
        mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0);
 +out_unlock:
 +      spin_unlock_bh(&bdi->wb_lock);
  }
  
  static void
@@@ -127,7 -121,7 +129,7 @@@ __bdi_start_writeback(struct backing_de
        work = kzalloc(sizeof(*work), GFP_ATOMIC);
        if (!work) {
                trace_writeback_nowork(bdi);
 -              mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0);
 +              bdi_wakeup_thread(bdi);
                return;
        }
  
@@@ -174,7 -168,7 +176,7 @@@ void bdi_start_background_writeback(str
         * writeback as soon as there is no other work to do.
         */
        trace_writeback_wake_background(bdi);
 -      mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0);
 +      bdi_wakeup_thread(bdi);
  }
  
  /*
@@@ -260,10 -254,10 +262,10 @@@ static int move_expired_inodes(struct l
        int do_sb_sort = 0;
        int moved = 0;
  
 -      WARN_ON_ONCE(!work->older_than_this_is_set);
        while (!list_empty(delaying_queue)) {
                inode = wb_inode(delaying_queue->prev);
 -              if (inode_dirtied_after(inode, work->older_than_this))
 +              if (work->older_than_this &&
 +                  inode_dirtied_after(inode, *work->older_than_this))
                        break;
                list_move(&inode->i_wb_list, &tmp);
                moved++;
@@@ -750,6 -744,8 +752,6 @@@ static long writeback_inodes_wb(struct 
                .sync_mode      = WB_SYNC_NONE,
                .range_cyclic   = 1,
                .reason         = reason,
 -              .older_than_this = jiffies,
 -              .older_than_this_is_set = 1,
        };
  
        spin_lock(&wb->list_lock);
@@@ -808,12 -804,13 +810,12 @@@ static long wb_writeback(struct bdi_wri
  {
        unsigned long wb_start = jiffies;
        long nr_pages = work->nr_pages;
 +      unsigned long oldest_jif;
        struct inode *inode;
        long progress;
  
 -      if (!work->older_than_this_is_set) {
 -              work->older_than_this = jiffies;
 -              work->older_than_this_is_set = 1;
 -      }
 +      oldest_jif = jiffies;
 +      work->older_than_this = &oldest_jif;
  
        spin_lock(&wb->list_lock);
        for (;;) {
                 * safe.
                 */
                if (work->for_kupdate) {
 -                      work->older_than_this = jiffies -
 +                      oldest_jif = jiffies -
                                msecs_to_jiffies(dirty_expire_interval * 10);
                } else if (work->for_background)
 -                      work->older_than_this = jiffies;
 +                      oldest_jif = jiffies;
  
                trace_writeback_start(wb->bdi, work);
                if (list_empty(&wb->b_io))
@@@ -1030,7 -1027,7 +1032,7 @@@ void bdi_writeback_workfn(struct work_s
        current->flags |= PF_SWAPWRITE;
  
        if (likely(!current_is_workqueue_rescuer() ||
 -                 list_empty(&bdi->bdi_list))) {
 +                 !test_bit(BDI_registered, &bdi->state))) {
                /*
                 * The normal path.  Keep writing back @bdi until its
                 * work_list is empty.  Note that this path is also taken
                trace_writeback_pages_written(pages_written);
        }
  
 -      if (!list_empty(&bdi->work_list) ||
 -          (wb_has_dirty_io(wb) && dirty_writeback_interval))
 -              queue_delayed_work(bdi_wq, &wb->dwork,
 -                      msecs_to_jiffies(dirty_writeback_interval * 10));
 +      if (!list_empty(&bdi->work_list))
 +              mod_delayed_work(bdi_wq, &wb->dwork, 0);
 +      else if (wb_has_dirty_io(wb) && dirty_writeback_interval)
 +              bdi_wakeup_thread_delayed(bdi);
  
        current->flags &= ~PF_SWAPWRITE;
  }
@@@ -1362,18 -1359,21 +1364,18 @@@ EXPORT_SYMBOL(try_to_writeback_inodes_s
  
  /**
   * sync_inodes_sb     -       sync sb inode pages
 - * @sb:                       the superblock
 - * @older_than_this:  timestamp
 + * @sb: the superblock
   *
   * This function writes and waits on any dirty inode belonging to this
 - * superblock that has been dirtied before given timestamp.
 + * super_block.
   */
 -void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this)
 +void sync_inodes_sb(struct super_block *sb)
  {
        DECLARE_COMPLETION_ONSTACK(done);
        struct wb_writeback_work work = {
                .sb             = sb,
                .sync_mode      = WB_SYNC_ALL,
                .nr_pages       = LONG_MAX,
 -              .older_than_this = older_than_this,
 -              .older_than_this_is_set = 1,
                .range_cyclic   = 0,
                .done           = &done,
                .reason         = WB_REASON_SYNC,
diff --combined fs/gfs2/super.c
@@@ -7,6 -7,8 +7,8 @@@
   * of the GNU General Public License version 2.
   */
  
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  #include <linux/bio.h>
  #include <linux/sched.h>
  #include <linux/slab.h>
@@@ -175,8 -177,7 +177,7 @@@ int gfs2_mount_args(struct gfs2_args *a
                        break;
                case Opt_debug:
                        if (args->ar_errors == GFS2_ERRORS_PANIC) {
-                               printk(KERN_WARNING "GFS2: -o debug and -o errors=panic "
-                                      "are mutually exclusive.\n");
+                               pr_warn("-o debug and -o errors=panic are mutually exclusive\n");
                                return -EINVAL;
                        }
                        args->ar_debug = 1;
                case Opt_commit:
                        rv = match_int(&tmp[0], &args->ar_commit);
                        if (rv || args->ar_commit <= 0) {
-                               printk(KERN_WARNING "GFS2: commit mount option requires a positive numeric argument\n");
+                               pr_warn("commit mount option requires a positive numeric argument\n");
                                return rv ? rv : -EINVAL;
                        }
                        break;
                case Opt_statfs_quantum:
                        rv = match_int(&tmp[0], &args->ar_statfs_quantum);
                        if (rv || args->ar_statfs_quantum < 0) {
-                               printk(KERN_WARNING "GFS2: statfs_quantum mount option requires a non-negative numeric argument\n");
+                               pr_warn("statfs_quantum mount option requires a non-negative numeric argument\n");
                                return rv ? rv : -EINVAL;
                        }
                        break;
                case Opt_quota_quantum:
                        rv = match_int(&tmp[0], &args->ar_quota_quantum);
                        if (rv || args->ar_quota_quantum <= 0) {
-                               printk(KERN_WARNING "GFS2: quota_quantum mount option requires a positive numeric argument\n");
+                               pr_warn("quota_quantum mount option requires a positive numeric argument\n");
                                return rv ? rv : -EINVAL;
                        }
                        break;
                        rv = match_int(&tmp[0], &args->ar_statfs_percent);
                        if (rv || args->ar_statfs_percent < 0 ||
                            args->ar_statfs_percent > 100) {
-                               printk(KERN_WARNING "statfs_percent mount option requires a numeric argument between 0 and 100\n");
+                               pr_warn("statfs_percent mount option requires a numeric argument between 0 and 100\n");
                                return rv ? rv : -EINVAL;
                        }
                        break;
                        break;
                case Opt_err_panic:
                        if (args->ar_debug) {
-                               printk(KERN_WARNING "GFS2: -o debug and -o errors=panic "
-                                       "are mutually exclusive.\n");
+                               pr_warn("-o debug and -o errors=panic are mutually exclusive\n");
                                return -EINVAL;
                        }
                        args->ar_errors = GFS2_ERRORS_PANIC;
                        break;
                case Opt_error:
                default:
-                       printk(KERN_WARNING "GFS2: invalid mount option: %s\n", o);
+                       pr_warn("invalid mount option: %s\n", o);
                        return -EINVAL;
                }
        }
  
  void gfs2_jindex_free(struct gfs2_sbd *sdp)
  {
-       struct list_head list, *head;
+       struct list_head list;
        struct gfs2_jdesc *jd;
-       struct gfs2_journal_extent *jext;
  
        spin_lock(&sdp->sd_jindex_spin);
        list_add(&list, &sdp->sd_jindex_list);
  
        while (!list_empty(&list)) {
                jd = list_entry(list.next, struct gfs2_jdesc, jd_list);
-               head = &jd->extent_list;
-               while (!list_empty(head)) {
-                       jext = list_entry(head->next,
-                                         struct gfs2_journal_extent,
-                                         extent_list);
-                       list_del(&jext->extent_list);
-                       kfree(jext);
-               }
+               gfs2_free_journal_extents(jd);
                list_del(&jd->jd_list);
                iput(jd->jd_inode);
                kfree(jd);
@@@ -1256,7 -1248,7 +1248,7 @@@ static int gfs2_drop_inode(struct inod
  {
        struct gfs2_inode *ip = GFS2_I(inode);
  
-       if (inode->i_nlink) {
+       if (!test_bit(GIF_FREE_VFS_INODE, &ip->i_flags) && inode->i_nlink) {
                struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
                if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags))
                        clear_nlink(inode);
@@@ -1471,6 -1463,11 +1463,11 @@@ static void gfs2_evict_inode(struct ino
        struct gfs2_holder gh;
        int error;
  
+       if (test_bit(GIF_FREE_VFS_INODE, &ip->i_flags)) {
+               clear_inode(inode);
+               return;
+       }
        if (inode->i_nlink || (sb->s_flags & MS_RDONLY))
                goto out;
  
@@@ -1558,7 -1555,7 +1555,7 @@@ out_unlock
                fs_warn(sdp, "gfs2_evict_inode: %d\n", error);
  out:
        /* Case 3 starts here */
 -      truncate_inode_pages(&inode->i_data, 0);
 +      truncate_inode_pages_final(&inode->i_data);
        gfs2_rs_delete(ip, NULL);
        gfs2_ordered_del_inode(ip);
        clear_inode(inode);
diff --combined fs/posix_acl.c
@@@ -521,11 -521,8 +521,11 @@@ posix_acl_chmod(struct inode *inode, um
                return -EOPNOTSUPP;
  
        acl = get_acl(inode, ACL_TYPE_ACCESS);
 -      if (IS_ERR_OR_NULL(acl))
 +      if (IS_ERR_OR_NULL(acl)) {
 +              if (acl == ERR_PTR(-EOPNOTSUPP))
 +                      return 0;
                return PTR_ERR(acl);
 +      }
  
        ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode);
        if (ret)
@@@ -547,15 -544,14 +547,15 @@@ posix_acl_create(struct inode *dir, umo
                goto no_acl;
  
        p = get_acl(dir, ACL_TYPE_DEFAULT);
 -      if (IS_ERR(p))
 +      if (IS_ERR(p)) {
 +              if (p == ERR_PTR(-EOPNOTSUPP))
 +                      goto apply_umask;
                return PTR_ERR(p);
 -
 -      if (!p) {
 -              *mode &= ~current_umask();
 -              goto no_acl;
        }
  
 +      if (!p)
 +              goto apply_umask;
 +
        *acl = posix_acl_clone(p, GFP_NOFS);
        if (!*acl)
                return -ENOMEM;
        }
        return 0;
  
 +apply_umask:
 +      *mode &= ~current_umask();
  no_acl:
        *default_acl = NULL;
        *acl = NULL;
@@@ -723,7 -717,7 +723,7 @@@ posix_acl_to_xattr(struct user_namespac
                   void *buffer, size_t size)
  {
        posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer;
-       posix_acl_xattr_entry *ext_entry = ext_acl->a_entries;
+       posix_acl_xattr_entry *ext_entry;
        int real_size, n;
  
        real_size = posix_acl_xattr_size(acl->a_count);
                return real_size;
        if (real_size > size)
                return -ERANGE;
-       
+       ext_entry = ext_acl->a_entries;
        ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
  
        for (n=0; n < acl->a_count; n++, ext_entry++) {