Merge branch 'for-3.4' of git://linux-nfs.org/~bfields/linux
Linus Torvalds [Thu, 29 Mar 2012 21:53:25 +0000 (14:53 -0700)]
Pull nfsd changes from Bruce Fields:

Highlights:
 - Benny Halevy and Tigran Mkrtchyan implemented some more 4.1 features,
   moving us closer to a complete 4.1 implementation.
 - Bernd Schubert fixed a long-standing problem with readdir cookies on
   ext2/3/4.
 - Jeff Layton performed a long-overdue overhaul of the server reboot
   recovery code which will allow us to deprecate the current code (a
   rather unusual user of the vfs), and give us some needed flexibility
   for further improvements.
 - Like the client, we now support numeric uid's and gid's in the
   auth_sys case, allowing easier upgrades from NFSv2/v3 to v4.x.

Plus miscellaneous bugfixes and cleanup.

Thanks to everyone!

There are also some delegation fixes waiting on vfs review that I
suppose will have to wait for 3.5.  With that done I think we'll finally
turn off the "EXPERIMENTAL" dependency for v4 (though that's mostly
symbolic as it's been on by default in distro's for a while).

And the list of 4.1 todo's should be achievable for 3.5 as well:

   http://wiki.linux-nfs.org/wiki/index.php/Server_4.0_and_4.1_issues

though we may still want a bit more experience with it before turning it
on by default.

* 'for-3.4' of git://linux-nfs.org/~bfields/linux: (55 commits)
  nfsd: only register cld pipe notifier when CONFIG_NFSD_V4 is enabled
  nfsd4: use auth_unix unconditionally on backchannel
  nfsd: fix NULL pointer dereference in cld_pipe_downcall
  nfsd4: memory corruption in numeric_name_to_id()
  sunrpc: skip portmap calls on sessions backchannel
  nfsd4: allow numeric idmapping
  nfsd: don't allow legacy client tracker init for anything but init_net
  nfsd: add notifier to handle mount/unmount of rpc_pipefs sb
  nfsd: add the infrastructure to handle the cld upcall
  nfsd: add a header describing upcall to nfsdcld
  nfsd: add a per-net-namespace struct for nfsd
  sunrpc: create nfsd dir in rpc_pipefs
  nfsd: add nfsd4_client_tracking_ops struct and a way to set it
  nfsd: convert nfs4_client->cl_cb_flags to a generic flags field
  NFSD: Fix nfs4_verifier memory alignment
  NFSD: Fix warnings when NFSD_DEBUG is not defined
  nfsd: vfs_llseek() with 32 or 64 bit offsets (hashes)
  nfsd: rename 'int access' to 'int may_flags' in nfsd_open()
  ext4: return 32/64-bit dir name hash according to usage type
  fs: add new FMODE flags: FMODE_32bithash and FMODE_64bithash
  ...

1  2 
Documentation/kernel-parameters.txt
fs/ext4/dir.c
fs/ext4/ext4.h
fs/nfsd/vfs.c
include/linux/fs.h
net/sunrpc/rpc_pipe.c

@@@ -713,21 -713,6 +713,21 @@@ bytes respectively. Such letter suffixe
                        The filter can be disabled or changed to another
                        driver later using sysfs.
  
 +      drm_kms_helper.edid_firmware=[<connector>:]<file>
 +                      Broken monitors, graphic adapters and KVMs may
 +                      send no or incorrect EDID data sets. This parameter
 +                      allows to specify an EDID data set in the
 +                      /lib/firmware directory that is used instead.
 +                      Generic built-in EDID data sets are used, if one of
 +                      edid/1024x768.bin, edid/1280x1024.bin,
 +                      edid/1680x1050.bin, or edid/1920x1080.bin is given
 +                      and no file with the same name exists. Details and
 +                      instructions how to build your own EDID data are
 +                      available in Documentation/EDID/HOWTO.txt. An EDID
 +                      data set will only be used for a particular connector,
 +                      if its name and a colon are prepended to the EDID
 +                      name.
 +
        dscc4.setup=    [NET]
  
        earlycon=       [KNL] Output early console device and options.
                             controller
        i8042.nopnp     [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
                             controllers
 -      i8042.notimeout [HW] Ignore timeout condition signalled by conroller
 +      i8042.notimeout [HW] Ignore timeout condition signalled by controller
        i8042.reset     [HW] Reset the controller during init and cleanup
        i8042.unlock    [HW] Unlock (ignore) the keylock
  
                        no_x2apic_optout
                                BIOS x2APIC opt-out request will be ignored
  
 -      inttest=        [IA-64]
 -
        iomem=          Disable strict checking of access to MMIO memory
                strict  regions from userspace.
                relaxed
                        The default is to send the implementation identification
                        information.
  
+       nfsd.nfs4_disable_idmapping=
+                       [NFSv4] When set to the default of '1', the NFSv4
+                       server will return only numeric uids and gids to
+                       clients using auth_sys, and will accept numeric uids
+                       and gids from such clients.  This is intended to ease
+                       migration from NFSv2/v3.
  
        objlayoutdriver.osd_login_prog=
                        [NFS] [OBJLAYOUT] sets the pathname to the program which
                        shutdown the other cpus.  Instead use the REBOOT_VECTOR
                        irq.
  
 +      nomodule        Disable module load
 +
        nopat           [X86] Disable PAT (page attribute table extension of
                        pagetables) support.
  
                                the default.
                                off: Turn ECRC off
                                on: Turn ECRC on.
 -              realloc         reallocate PCI resources if allocations done by BIOS
 -                              are erroneous.
 +              realloc=        Enable/disable reallocating PCI bridge resources
 +                              if allocations done by BIOS are too small to
 +                              accommodate resources required by all child
 +                              devices.
 +                              off: Turn realloc off
 +                              on: Turn realloc on
 +              realloc         same as realloc=on
 +              noari           do not use PCIe ARI.
  
        pcie_aspm=      [PCIE] Forcibly enable or disable PCIe Active State Power
                        Management.
                force   Enable ASPM even on devices that claim not to support it.
                        WARNING: Forcing ASPM on may cause system lockups.
  
 +      pcie_hp=        [PCIE] PCI Express Hotplug driver options:
 +              nomsi   Do not use MSI for PCI Express Native Hotplug (this
 +                      makes all PCIe ports use INTx for hotplug services).
 +
        pcie_ports=     [PCIE] PCIe ports handling:
                auto    Ask the BIOS whether or not to use native PCIe services
                        associated with PCIe ports (PME, hot-plug, AER).  Use
  
                        default: off.
  
 +      printk.always_kmsg_dump=
 +                      Trigger kmsg_dump for cases other than kernel oops or
 +                      panics
 +                      Format: <bool>  (1/Y/y=enable, 0/N/n=disable)
 +                      default: disabled
 +
        printk.time=    Show timing data prefixed to each printk message line
                        Format: <bool>  (1/Y/y=enable, 0/N/n=disable)
  
                        For more information see Documentation/vm/slub.txt.
  
        slub_min_order= [MM, SLUB]
 -                      Determines the mininum page order for slabs. Must be
 +                      Determines the minimum page order for slabs. Must be
                        lower than slub_max_order.
                        For more information see Documentation/vm/slub.txt.
  
  
        threadirqs      [KNL]
                        Force threading of all interrupt handlers except those
 -                      marked explicitely IRQF_NO_THREAD.
 +                      marked explicitly IRQF_NO_THREAD.
  
        topology=       [S390]
                        Format: {off | on}
                        to facilitate early boot debugging.
                        See also Documentation/trace/events.txt
  
 +      transparent_hugepage=
 +                      [KNL]
 +                      Format: [always|madvise|never]
 +                      Can be used to control the default behavior of the system
 +                      with respect to transparent hugepages.
 +                      See Documentation/vm/transhuge.txt for more details.
 +
        tsc=            Disable clocksource stability checks for TSC.
                        Format: <string>
                        [x86] reliable: mark tsc clocksource as reliable, this
diff --combined fs/ext4/dir.c
@@@ -32,24 -32,8 +32,8 @@@ static unsigned char ext4_filetype_tabl
        DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
  };
  
- static int ext4_readdir(struct file *, void *, filldir_t);
  static int ext4_dx_readdir(struct file *filp,
                           void *dirent, filldir_t filldir);
- static int ext4_release_dir(struct inode *inode,
-                               struct file *filp);
- const struct file_operations ext4_dir_operations = {
-       .llseek         = ext4_llseek,
-       .read           = generic_read_dir,
-       .readdir        = ext4_readdir,         /* we take BKL. needed?*/
-       .unlocked_ioctl = ext4_ioctl,
- #ifdef CONFIG_COMPAT
-       .compat_ioctl   = ext4_compat_ioctl,
- #endif
-       .fsync          = ext4_sync_file,
-       .release        = ext4_release_dir,
- };
  
  static unsigned char get_dtype(struct super_block *sb, int filetype)
  {
        return (ext4_filetype_table[filetype]);
  }
  
+ /**
+  * Check if the given dir-inode refers to an htree-indexed directory
+  * (or a directory which chould potentially get coverted to use htree
+  * indexing).
+  *
+  * Return 1 if it is a dx dir, 0 if not
+  */
+ static int is_dx_dir(struct inode *inode)
+ {
+       struct super_block *sb = inode->i_sb;
+       if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
+                    EXT4_FEATURE_COMPAT_DIR_INDEX) &&
+           ((ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) ||
+            ((inode->i_size >> sb->s_blocksize_bits) == 1)))
+               return 1;
+       return 0;
+ }
  /*
   * Return 0 if the directory entry is OK, and 1 if there is a problem
   *
@@@ -91,17 -95,17 +95,17 @@@ int __ext4_check_dir_entry(const char *
                return 0;
  
        if (filp)
 -              ext4_error_file(filp, function, line, bh ? bh->b_blocknr : 0,
 +              ext4_error_file(filp, function, line, bh->b_blocknr,
                                "bad entry in directory: %s - offset=%u(%u), "
                                "inode=%u, rec_len=%d, name_len=%d",
 -                              error_msg, (unsigned) (offset%bh->b_size),
 +                              error_msg, (unsigned) (offset % bh->b_size),
                                offset, le32_to_cpu(de->inode),
                                rlen, de->name_len);
        else
 -              ext4_error_inode(dir, function, line, bh ? bh->b_blocknr : 0,
 +              ext4_error_inode(dir, function, line, bh->b_blocknr,
                                "bad entry in directory: %s - offset=%u(%u), "
                                "inode=%u, rec_len=%d, name_len=%d",
 -                              error_msg, (unsigned) (offset%bh->b_size),
 +                              error_msg, (unsigned) (offset % bh->b_size),
                                offset, le32_to_cpu(de->inode),
                                rlen, de->name_len);
  
@@@ -115,18 -119,13 +119,13 @@@ static int ext4_readdir(struct file *fi
        unsigned int offset;
        int i, stored;
        struct ext4_dir_entry_2 *de;
-       struct super_block *sb;
        int err;
        struct inode *inode = filp->f_path.dentry->d_inode;
+       struct super_block *sb = inode->i_sb;
        int ret = 0;
        int dir_has_error = 0;
  
-       sb = inode->i_sb;
-       if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
-                                   EXT4_FEATURE_COMPAT_DIR_INDEX) &&
-           ((ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) ||
-            ((inode->i_size >> sb->s_blocksize_bits) == 1))) {
+       if (is_dx_dir(inode)) {
                err = ext4_dx_readdir(filp, dirent, filldir);
                if (err != ERR_BAD_DX_DIR) {
                        ret = err;
        return ret;
  }
  
+ static inline int is_32bit_api(void)
+ {
+ #ifdef CONFIG_COMPAT
+       return is_compat_task();
+ #else
+       return (BITS_PER_LONG == 32);
+ #endif
+ }
  /*
   * These functions convert from the major/minor hash to an f_pos
-  * value.
+  * value for dx directories
+  *
+  * Upper layer (for example NFS) should specify FMODE_32BITHASH or
+  * FMODE_64BITHASH explicitly. On the other hand, we allow ext4 to be mounted
+  * directly on both 32-bit and 64-bit nodes, under such case, neither
+  * FMODE_32BITHASH nor FMODE_64BITHASH is specified.
+  */
+ static inline loff_t hash2pos(struct file *filp, __u32 major, __u32 minor)
+ {
+       if ((filp->f_mode & FMODE_32BITHASH) ||
+           (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
+               return major >> 1;
+       else
+               return ((__u64)(major >> 1) << 32) | (__u64)minor;
+ }
+ static inline __u32 pos2maj_hash(struct file *filp, loff_t pos)
+ {
+       if ((filp->f_mode & FMODE_32BITHASH) ||
+           (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
+               return (pos << 1) & 0xffffffff;
+       else
+               return ((pos >> 32) << 1) & 0xffffffff;
+ }
+ static inline __u32 pos2min_hash(struct file *filp, loff_t pos)
+ {
+       if ((filp->f_mode & FMODE_32BITHASH) ||
+           (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
+               return 0;
+       else
+               return pos & 0xffffffff;
+ }
+ /*
+  * Return 32- or 64-bit end-of-file for dx directories
+  */
+ static inline loff_t ext4_get_htree_eof(struct file *filp)
+ {
+       if ((filp->f_mode & FMODE_32BITHASH) ||
+           (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
+               return EXT4_HTREE_EOF_32BIT;
+       else
+               return EXT4_HTREE_EOF_64BIT;
+ }
+ /*
+  * ext4_dir_llseek() based on generic_file_llseek() to handle both
+  * non-htree and htree directories, where the "offset" is in terms
+  * of the filename hash value instead of the byte offset.
   *
-  * Currently we only use major hash numer.  This is unfortunate, but
-  * on 32-bit machines, the same VFS interface is used for lseek and
-  * llseek, so if we use the 64 bit offset, then the 32-bit versions of
-  * lseek/telldir/seekdir will blow out spectacularly, and from within
-  * the ext2 low-level routine, we don't know if we're being called by
-  * a 64-bit version of the system call or the 32-bit version of the
-  * system call.  Worse yet, NFSv2 only allows for a 32-bit readdir
-  * cookie.  Sigh.
+  * NOTE: offsets obtained *before* ext4_set_inode_flag(dir, EXT4_INODE_INDEX)
+  *       will be invalid once the directory was converted into a dx directory
   */
- #define hash2pos(major, minor)        (major >> 1)
- #define pos2maj_hash(pos)     ((pos << 1) & 0xffffffff)
- #define pos2min_hash(pos)     (0)
+ loff_t ext4_dir_llseek(struct file *file, loff_t offset, int origin)
+ {
+       struct inode *inode = file->f_mapping->host;
+       loff_t ret = -EINVAL;
+       int dx_dir = is_dx_dir(inode);
+       mutex_lock(&inode->i_mutex);
+       /* NOTE: relative offsets with dx directories might not work
+        *       as expected, as it is difficult to figure out the
+        *       correct offset between dx hashes */
+       switch (origin) {
+       case SEEK_END:
+               if (unlikely(offset > 0))
+                       goto out_err; /* not supported for directories */
+               /* so only negative offsets are left, does that have a
+                * meaning for directories at all? */
+               if (dx_dir)
+                       offset += ext4_get_htree_eof(file);
+               else
+                       offset += inode->i_size;
+               break;
+       case SEEK_CUR:
+               /*
+                * Here we special-case the lseek(fd, 0, SEEK_CUR)
+                * position-querying operation.  Avoid rewriting the "same"
+                * f_pos value back to the file because a concurrent read(),
+                * write() or lseek() might have altered it
+                */
+               if (offset == 0) {
+                       offset = file->f_pos;
+                       goto out_ok;
+               }
+               offset += file->f_pos;
+               break;
+       }
+       if (unlikely(offset < 0))
+               goto out_err;
+       if (!dx_dir) {
+               if (offset > inode->i_sb->s_maxbytes)
+                       goto out_err;
+       } else if (offset > ext4_get_htree_eof(file))
+               goto out_err;
+       /* Special lock needed here? */
+       if (offset != file->f_pos) {
+               file->f_pos = offset;
+               file->f_version = 0;
+       }
+ out_ok:
+       ret = offset;
+ out_err:
+       mutex_unlock(&inode->i_mutex);
+       return ret;
+ }
  
  /*
   * This structure holds the nodes of the red-black tree used to store
@@@ -330,15 -441,16 +441,16 @@@ static void free_rb_tree_fname(struct r
  }
  
  
- static struct dir_private_info *ext4_htree_create_dir_info(loff_t pos)
+ static struct dir_private_info *ext4_htree_create_dir_info(struct file *filp,
+                                                          loff_t pos)
  {
        struct dir_private_info *p;
  
        p = kzalloc(sizeof(struct dir_private_info), GFP_KERNEL);
        if (!p)
                return NULL;
-       p->curr_hash = pos2maj_hash(pos);
-       p->curr_minor_hash = pos2min_hash(pos);
+       p->curr_hash = pos2maj_hash(filp, pos);
+       p->curr_minor_hash = pos2min_hash(filp, pos);
        return p;
  }
  
@@@ -425,12 -537,11 +537,12 @@@ static int call_filldir(struct file *fi
        sb = inode->i_sb;
  
        if (!fname) {
 -              printk(KERN_ERR "EXT4-fs: call_filldir: called with "
 -                     "null fname?!?\n");
 +              ext4_msg(sb, KERN_ERR, "%s:%d: inode #%lu: comm %s: "
 +                       "called with null fname?!?", __func__, __LINE__,
 +                       inode->i_ino, current->comm);
                return 0;
        }
-       curr_pos = hash2pos(fname->hash, fname->minor_hash);
+       curr_pos = hash2pos(filp, fname->hash, fname->minor_hash);
        while (fname) {
                error = filldir(dirent, fname->name,
                                fname->name_len, curr_pos,
@@@ -455,13 -566,13 +567,13 @@@ static int ext4_dx_readdir(struct file 
        int     ret;
  
        if (!info) {
-               info = ext4_htree_create_dir_info(filp->f_pos);
+               info = ext4_htree_create_dir_info(filp, filp->f_pos);
                if (!info)
                        return -ENOMEM;
                filp->private_data = info;
        }
  
-       if (filp->f_pos == EXT4_HTREE_EOF)
+       if (filp->f_pos == ext4_get_htree_eof(filp))
                return 0;       /* EOF */
  
        /* Some one has messed with f_pos; reset the world */
                free_rb_tree_fname(&info->root);
                info->curr_node = NULL;
                info->extra_fname = NULL;
-               info->curr_hash = pos2maj_hash(filp->f_pos);
-               info->curr_minor_hash = pos2min_hash(filp->f_pos);
+               info->curr_hash = pos2maj_hash(filp, filp->f_pos);
+               info->curr_minor_hash = pos2min_hash(filp, filp->f_pos);
        }
  
        /*
                        if (ret < 0)
                                return ret;
                        if (ret == 0) {
-                               filp->f_pos = EXT4_HTREE_EOF;
+                               filp->f_pos = ext4_get_htree_eof(filp);
                                break;
                        }
                        info->curr_node = rb_first(&info->root);
                        info->curr_minor_hash = fname->minor_hash;
                } else {
                        if (info->next_hash == ~0) {
-                               filp->f_pos = EXT4_HTREE_EOF;
+                               filp->f_pos = ext4_get_htree_eof(filp);
                                break;
                        }
                        info->curr_hash = info->next_hash;
@@@ -541,3 -652,15 +653,15 @@@ static int ext4_release_dir(struct inod
  
        return 0;
  }
+ const struct file_operations ext4_dir_operations = {
+       .llseek         = ext4_dir_llseek,
+       .read           = generic_read_dir,
+       .readdir        = ext4_readdir,
+       .unlocked_ioctl = ext4_ioctl,
+ #ifdef CONFIG_COMPAT
+       .compat_ioctl   = ext4_compat_ioctl,
+ #endif
+       .fsync          = ext4_sync_file,
+       .release        = ext4_release_dir,
+ };
diff --combined fs/ext4/ext4.h
@@@ -53,7 -53,7 +53,7 @@@
                printk(KERN_DEBUG f, ## a);                             \
        } while (0)
  #else
 -#define ext4_debug(f, a...)   do {} while (0)
 +#define ext4_debug(fmt, ...)  no_printk(fmt, ##__VA_ARGS__)
  #endif
  
  #define EXT4_ERROR_INODE(inode, fmt, a...) \
@@@ -184,8 -184,6 +184,8 @@@ struct mpage_da_data 
  #define       EXT4_IO_END_UNWRITTEN   0x0001
  #define EXT4_IO_END_ERROR     0x0002
  #define EXT4_IO_END_QUEUED    0x0004
 +#define EXT4_IO_END_DIRECT    0x0008
 +#define EXT4_IO_END_IN_FSYNC  0x0010
  
  struct ext4_io_page {
        struct page     *p_page;
  
  #define MAX_IO_PAGES 128
  
 +/*
 + * For converting uninitialized extents on a work queue.
 + *
 + * 'page' is only used from the writepage() path; 'pages' is only used for
 + * buffered writes; they are used to keep page references until conversion
 + * takes place.  For AIO/DIO, neither field is filled in.
 + */
  typedef struct ext4_io_end {
        struct list_head        list;           /* per-file finished IO list */
        struct inode            *inode;         /* file being written to */
        unsigned int            flag;           /* unwritten or not */
 -      struct page             *page;          /* page struct for buffer write */
 +      struct page             *page;          /* for writepage() path */
        loff_t                  offset;         /* offset in the file */
        ssize_t                 size;           /* size of the extent */
        struct work_struct      work;           /* data work queue */
        struct kiocb            *iocb;          /* iocb struct for AIO */
        int                     result;         /* error value for AIO */
 -      int                     num_io_pages;
 -      struct ext4_io_page     *pages[MAX_IO_PAGES];
 +      int                     num_io_pages;   /* for writepages() */
 +      struct ext4_io_page     *pages[MAX_IO_PAGES]; /* for writepages() */
  } ext4_io_end_t;
  
  struct ext4_io_submit {
@@@ -932,7 -923,6 +932,7 @@@ struct ext4_inode_info 
  #define EXT4_MOUNT_ERRORS_CONT                0x00010 /* Continue on errors */
  #define EXT4_MOUNT_ERRORS_RO          0x00020 /* Remount fs ro on errors */
  #define EXT4_MOUNT_ERRORS_PANIC               0x00040 /* Panic on errors */
 +#define EXT4_MOUNT_ERRORS_MASK                0x00070
  #define EXT4_MOUNT_MINIX_DF           0x00080 /* Mimics the Minix statfs */
  #define EXT4_MOUNT_NOLOAD             0x00100 /* Don't use existing journal*/
  #define EXT4_MOUNT_DATA_FLAGS         0x00C00 /* Mode for data writes: */
  #define EXT4_MOUNT_DIOREAD_NOLOCK     0x400000 /* Enable support for dio read nolocking */
  #define EXT4_MOUNT_JOURNAL_CHECKSUM   0x800000 /* Journal checksums */
  #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT       0x1000000 /* Journal Async Commit */
 -#define EXT4_MOUNT_I_VERSION            0x2000000 /* i_version support */
  #define EXT4_MOUNT_MBLK_IO_SUBMIT     0x4000000 /* multi-block io submits */
  #define EXT4_MOUNT_DELALLOC           0x8000000 /* Delalloc support */
  #define EXT4_MOUNT_DATA_ERR_ABORT     0x10000000 /* Abort on file data write */
@@@ -1151,7 -1142,6 +1151,7 @@@ struct ext4_sb_info 
        unsigned int s_mount_opt;
        unsigned int s_mount_opt2;
        unsigned int s_mount_flags;
 +      unsigned int s_def_mount_opt;
        ext4_fsblk_t s_sb_block;
        uid_t s_resuid;
        gid_t s_resgid;
@@@ -1430,9 -1420,8 +1430,9 @@@ static inline void ext4_clear_state_fla
  #define EXT4_FEATURE_INCOMPAT_FLEX_BG         0x0200
  #define EXT4_FEATURE_INCOMPAT_EA_INODE                0x0400 /* EA in inode */
  #define EXT4_FEATURE_INCOMPAT_DIRDATA         0x1000 /* data in dirent */
 -#define EXT4_FEATURE_INCOMPAT_INLINEDATA      0x2000 /* data in inode */
 +#define EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM        0x2000 /* use crc32c for bg */
  #define EXT4_FEATURE_INCOMPAT_LARGEDIR                0x4000 /* >2GB or 3-lvl htree */
 +#define EXT4_FEATURE_INCOMPAT_INLINEDATA      0x8000 /* data in inode */
  
  #define EXT2_FEATURE_COMPAT_SUPP      EXT4_FEATURE_COMPAT_EXT_ATTR
  #define EXT2_FEATURE_INCOMPAT_SUPP    (EXT4_FEATURE_INCOMPAT_FILETYPE| \
@@@ -1623,7 -1612,11 +1623,11 @@@ struct dx_hash_inf
        u32             *seed;
  };
  
- #define EXT4_HTREE_EOF        0x7fffffff
+ /* 32 and 64 bit signed EOF for dx directories */
+ #define EXT4_HTREE_EOF_32BIT   ((1UL  << (32 - 1)) - 1)
+ #define EXT4_HTREE_EOF_64BIT   ((1ULL << (64 - 1)) - 1)
  
  /*
   * Control parameters used by ext4_htree_next_block
@@@ -1805,14 -1798,8 +1809,14 @@@ extern struct ext4_group_desc * ext4_ge
                                                    ext4_group_t block_group,
                                                    struct buffer_head ** bh);
  extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
 -struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
 -                                    ext4_group_t block_group);
 +
 +extern struct buffer_head *ext4_read_block_bitmap_nowait(struct super_block *sb,
 +                                              ext4_group_t block_group);
 +extern int ext4_wait_block_bitmap(struct super_block *sb,
 +                                ext4_group_t block_group,
 +                                struct buffer_head *bh);
 +extern struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
 +                                                ext4_group_t block_group);
  extern void ext4_init_block_bitmap(struct super_block *sb,
                                   struct buffer_head *bh,
                                   ext4_group_t group,
@@@ -1858,7 -1845,6 +1862,7 @@@ extern void ext4_check_inodes_bitmap(st
  extern void ext4_mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
  extern int ext4_init_inode_table(struct super_block *sb,
                                 ext4_group_t group, int barrier);
 +extern void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate);
  
  /* mballoc.c */
  extern long ext4_mb_stats;
diff --combined fs/nfsd/vfs.c
@@@ -737,12 -737,13 +737,13 @@@ static int nfsd_open_break_lease(struc
  
  /*
   * Open an existing file or directory.
-  * The access argument indicates the type of open (read/write/lock)
+  * The may_flags argument indicates the type of open (read/write/lock)
+  * and additional flags.
   * N.B. After this call fhp needs an fh_put
   */
  __be32
  nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
-                       int access, struct file **filp)
+                       int may_flags, struct file **filp)
  {
        struct dentry   *dentry;
        struct inode    *inode;
         * and (hopefully) checked permission - so allow OWNER_OVERRIDE
         * in case a chmod has now revoked permission.
         */
-       err = fh_verify(rqstp, fhp, type, access | NFSD_MAY_OWNER_OVERRIDE);
+       err = fh_verify(rqstp, fhp, type, may_flags | NFSD_MAY_OWNER_OVERRIDE);
        if (err)
                goto out;
  
         * or any access when mandatory locking enabled
         */
        err = nfserr_perm;
-       if (IS_APPEND(inode) && (access & NFSD_MAY_WRITE))
+       if (IS_APPEND(inode) && (may_flags & NFSD_MAY_WRITE))
                goto out;
        /*
         * We must ignore files (but only files) which might have mandatory
        if (!inode->i_fop)
                goto out;
  
-       host_err = nfsd_open_break_lease(inode, access);
+       host_err = nfsd_open_break_lease(inode, may_flags);
        if (host_err) /* NOMEM or WOULDBLOCK */
                goto out_nfserr;
  
-       if (access & NFSD_MAY_WRITE) {
-               if (access & NFSD_MAY_READ)
+       if (may_flags & NFSD_MAY_WRITE) {
+               if (may_flags & NFSD_MAY_READ)
                        flags = O_RDWR|O_LARGEFILE;
                else
                        flags = O_WRONLY|O_LARGEFILE;
                            flags, current_cred());
        if (IS_ERR(*filp))
                host_err = PTR_ERR(*filp);
-       else
-               host_err = ima_file_check(*filp, access);
+       else {
+               host_err = ima_file_check(*filp, may_flags);
+               if (may_flags & NFSD_MAY_64BIT_COOKIE)
+                       (*filp)->f_mode |= FMODE_64BITHASH;
+               else
+                       (*filp)->f_mode |= FMODE_32BITHASH;
+       }
  out_nfserr:
        err = nfserrno(host_err);
  out:
@@@ -1541,31 -1549,30 +1549,31 @@@ do_nfsd_create(struct svc_rqst *rqstp, 
  __be32
  nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
  {
 -      struct dentry   *dentry;
        struct inode    *inode;
        mm_segment_t    oldfs;
        __be32          err;
        int             host_err;
 +      struct path path;
  
        err = fh_verify(rqstp, fhp, S_IFLNK, NFSD_MAY_NOP);
        if (err)
                goto out;
  
 -      dentry = fhp->fh_dentry;
 -      inode = dentry->d_inode;
 +      path.mnt = fhp->fh_export->ex_path.mnt;
 +      path.dentry = fhp->fh_dentry;
 +      inode = path.dentry->d_inode;
  
        err = nfserr_inval;
        if (!inode->i_op->readlink)
                goto out;
  
 -      touch_atime(fhp->fh_export->ex_path.mnt, dentry);
 +      touch_atime(&path);
        /* N.B. Why does this call need a get_fs()??
         * Remove the set_fs and watch the fireworks:-) --okir
         */
  
        oldfs = get_fs(); set_fs(KERNEL_DS);
 -      host_err = inode->i_op->readlink(dentry, buf, *lenp);
 +      host_err = inode->i_op->readlink(path.dentry, buf, *lenp);
        set_fs(oldfs);
  
        if (host_err < 0)
@@@ -2021,8 -2028,13 +2029,13 @@@ nfsd_readdir(struct svc_rqst *rqstp, st
        __be32          err;
        struct file     *file;
        loff_t          offset = *offsetp;
+       int             may_flags = NFSD_MAY_READ;
+       /* NFSv2 only supports 32 bit cookies */
+       if (rqstp->rq_vers > 2)
+               may_flags |= NFSD_MAY_64BIT_COOKIE;
  
-       err = nfsd_open(rqstp, fhp, S_IFDIR, NFSD_MAY_READ, &file);
+       err = nfsd_open(rqstp, fhp, S_IFDIR, may_flags, &file);
        if (err)
                goto out;
  
diff --combined include/linux/fs.h
@@@ -92,6 -92,10 +92,10 @@@ struct inodes_stat_t 
  /* File is opened using open(.., 3, ..) and is writeable only for ioctls
     (specialy hack for floppy.c) */
  #define FMODE_WRITE_IOCTL     ((__force fmode_t)0x100)
+ /* 32bit hashes as llseek() offset (for directories) */
+ #define FMODE_32BITHASH         ((__force fmode_t)0x200)
+ /* 64bit hashes as llseek() offset (for directories) */
+ #define FMODE_64BITHASH         ((__force fmode_t)0x400)
  
  /*
   * Don't update ctime and mtime.
  #include <linux/prio_tree.h>
  #include <linux/init.h>
  #include <linux/pid.h>
 +#include <linux/bug.h>
  #include <linux/mutex.h>
  #include <linux/capability.h>
  #include <linux/semaphore.h>
@@@ -1460,7 -1463,6 +1464,7 @@@ struct super_block 
        u8 s_uuid[16];                          /* UUID */
  
        void                    *s_fs_info;     /* Filesystem private info */
 +      unsigned int            s_max_links;
        fmode_t                 s_mode;
  
        /* Granularity of c/m/atime in ns.
@@@ -1813,11 -1815,11 +1817,11 @@@ static inline void inode_inc_iversion(s
         spin_unlock(&inode->i_lock);
  }
  
 -extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry);
 +extern void touch_atime(struct path *);
  static inline void file_accessed(struct file *file)
  {
        if (!(file->f_flags & O_NOATIME))
 -              touch_atime(file->f_path.mnt, file->f_path.dentry);
 +              touch_atime(&file->f_path);
  }
  
  int sync_inode(struct inode *inode, struct writeback_control *wbc);
@@@ -1872,6 -1874,19 +1876,6 @@@ extern struct dentry *mount_pseudo(stru
        const struct dentry_operations *dops,
        unsigned long);
  
 -static inline void sb_mark_dirty(struct super_block *sb)
 -{
 -      sb->s_dirt = 1;
 -}
 -static inline void sb_mark_clean(struct super_block *sb)
 -{
 -      sb->s_dirt = 0;
 -}
 -static inline int sb_is_dirty(struct super_block *sb)
 -{
 -      return sb->s_dirt;
 -}
 -
  /* Alas, no aliases. Too much hassle with bringing module.h everywhere */
  #define fops_get(fops) \
        (((fops) && try_module_get((fops)->owner) ? (fops) : NULL))
@@@ -2293,10 -2308,7 +2297,10 @@@ extern struct inode * igrab(struct inod
  extern ino_t iunique(struct super_block *, ino_t);
  extern int inode_needs_sync(struct inode *inode);
  extern int generic_delete_inode(struct inode *inode);
 -extern int generic_drop_inode(struct inode *inode);
 +static inline int generic_drop_inode(struct inode *inode)
 +{
 +      return !inode->i_nlink || inode_unhashed(inode);
 +}
  
  extern struct inode *ilookup5_nowait(struct super_block *sb,
                unsigned long hashval, int (*test)(struct inode *, void *),
@@@ -2488,7 -2500,6 +2492,7 @@@ extern void get_filesystem(struct file_
  extern void put_filesystem(struct file_system_type *fs);
  extern struct file_system_type *get_fs_type(const char *name);
  extern struct super_block *get_super(struct block_device *);
 +extern struct super_block *get_super_thawed(struct block_device *);
  extern struct super_block *get_active_super(struct block_device *bdev);
  extern void drop_super(struct super_block *sb);
  extern void iterate_supers(void (*)(struct super_block *, void *), void *);
diff --combined net/sunrpc/rpc_pipe.c
@@@ -1014,6 -1014,7 +1014,7 @@@ enum 
        RPCAUTH_statd,
        RPCAUTH_nfsd4_cb,
        RPCAUTH_cache,
+       RPCAUTH_nfsd,
        RPCAUTH_RootEOF
  };
  
@@@ -1046,6 -1047,10 +1047,10 @@@ static const struct rpc_filelist files[
                .name = "cache",
                .mode = S_IFDIR | S_IRUGO | S_IXUGO,
        },
+       [RPCAUTH_nfsd] = {
+               .name = "nfsd",
+               .mode = S_IFDIR | S_IRUGO | S_IXUGO,
+       },
  };
  
  /*
@@@ -1114,9 -1119,13 +1119,9 @@@ rpc_fill_super(struct super_block *sb, 
        sb->s_time_gran = 1;
  
        inode = rpc_get_inode(sb, S_IFDIR | 0755);
 -      if (!inode)
 -              return -ENOMEM;
 -      sb->s_root = root = d_alloc_root(inode);
 -      if (!root) {
 -              iput(inode);
 +      sb->s_root = root = d_make_root(inode);
 +      if (!root)
                return -ENOMEM;
 -      }
        if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
                return -ENOMEM;
        dprintk("RPC:   sending pipefs MOUNT notification for net %p%s\n", net,