- Update to 2.6.38-rc1.
authorJeff Mahoney <jeffm@suse.de>
Fri, 21 Jan 2011 23:27:46 +0000 (18:27 -0500)
committerJeff Mahoney <jeffm@suse.com>
Sat, 22 Jan 2011 16:11:59 +0000 (11:11 -0500)
  - Removed 12 patches.
  - Xen is disabled.
  - Quite a few patches need updating.

suse-commit: 9163bb79e0ca382470c44b4334613d9b29ca7771

187 files changed:
1  2 
Documentation/filesystems/Locking
Documentation/filesystems/vfs.txt
Documentation/kernel-parameters.txt
Documentation/sysctl/kernel.txt
Documentation/target/tcm_mod_builder.py
Makefile
arch/ia64/Kconfig
arch/ia64/include/asm/page.h
arch/ia64/kernel/acpi.c
arch/powerpc/kernel/ptrace32.c
arch/s390/Kconfig
arch/x86/Kconfig
arch/x86/include/asm/mce.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/cpu/mcheck/Makefile
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/e820.c
arch/x86/kernel/process.c
arch/x86/kvm/svm.c
arch/x86/kvm/x86.c
arch/x86/mm/init_32.c
arch/x86/mm/pageattr.c
arch/x86/mm/srat_64.c
arch/x86/oprofile/nmi_int.c
block/genhd.c
drivers/Makefile
drivers/acpi/numa.c
drivers/acpi/osl.c
drivers/acpi/thermal.c
drivers/ata/libata-core.c
drivers/block/Kconfig
drivers/block/Makefile
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/mem.c
drivers/char/raw.c
drivers/connector/cn_proc.c
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/infiniband/hw/mthca/mthca_catas.c
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.h
drivers/input/serio/i8042-x86ia64io.h
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/md/Kconfig
drivers/md/Makefile
drivers/md/dm-mpath.c
drivers/md/dm-table.c
drivers/md/dm.c
drivers/net/bnx2.c
drivers/net/e1000/e1000_main.c
drivers/net/e1000e/e1000.h
drivers/net/e1000e/netdev.c
drivers/net/e1000e/param.c
drivers/net/ehea/ehea_main.c
drivers/net/igb/igb_main.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/mlx4/catas.c
drivers/net/sky2.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tulip/tulip_core.c
drivers/net/wireless/Kconfig
drivers/net/wireless/b43/main.c
drivers/scsi/device_handler/scsi_dh.c
drivers/scsi/qla4xxx/ql4_nx.h
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_netlink.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/sd.c
drivers/serial/8250.c
drivers/tty/vt/vt.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/console/vgacon.c
fs/Kconfig
fs/dcache.c
fs/ext3/super.c
fs/ext4/acl.c
fs/ext4/ext4.h
fs/ext4/file.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/namei.c
fs/ext4/richacl.c
fs/ext4/richacl.h
fs/ext4/super.c
fs/ext4/xattr.c
fs/fs-writeback.c
fs/inode.c
fs/namei.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/pagelist.c
fs/novfs/inode.c
fs/partitions/check.c
fs/proc/array.c
fs/reiserfs/super.c
fs/reiserfs/xattr.c
fs/richacl_base.c
fs/richacl_inode.c
fs/super.c
include/linux/audit.h
include/linux/blkdev.h
include/linux/dcache.h
include/linux/device.h
include/linux/fb.h
include/linux/fs.h
include/linux/genhd.h
include/linux/gfp.h
include/linux/init_task.h
include/linux/kernel.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/mmzone.h
include/linux/module.h
include/linux/nfs_fs.h
include/linux/page-flags.h
include/linux/pagemap.h
include/linux/printk.h
include/linux/reiserfs_xattr.h
include/linux/richacl.h
include/linux/sched.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/slub_def.h
include/linux/sunrpc/xprt.h
include/linux/swap.h
include/net/sock.h
init/Kconfig
kernel/Kconfig.preempt
kernel/Makefile
kernel/audit.c
kernel/module.c
kernel/panic.c
kernel/printk.c
kernel/sched.c
kernel/softirq.c
kernel/sysctl.c
kernel/sysctl_binary.c
lib/Kconfig.debug
mm/Makefile
mm/filemap.c
mm/internal.h
mm/memory.c
mm/migrate.c
mm/page-writeback.c
mm/page_alloc.c
mm/page_io.c
mm/slab.c
mm/slob.c
mm/slub.c
mm/swap_state.c
mm/swapfile.c
mm/vmscan.c
mm/vmstat.c
net/Kconfig
net/bridge/br_if.c
net/caif/caif_socket.c
net/core/dev.c
net/core/filter.c
net/core/skbuff.c
net/core/sock.c
net/ipv4/ip_fragment.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv6/addrconf.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/mac80211/Kconfig
net/netfilter/core.c
net/sunrpc/clnt.c
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c
scripts/Makefile.build
scripts/mod/modpost.c
security/security.c
tools/perf/builtin-timechart.c
tools/testing/ktest/compare-ktest-sample.pl
tools/testing/ktest/ktest.pl

Simple merge
Simple merge
Simple merge
Simple merge
diff --cc Makefile
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -601,18 -606,10 +606,18 @@@ config S390_GUES
          virtio transport. If KVM is detected, the virtio console will be
          the default console.
  
 +config KMSG_IDS
 +      bool "Kernel message numbers"
 +      default y
 +      help
 +        Select this option if you want to include a message number to the
 +        prefix for kernel messages issued by the s390 architecture and
 +        driver code. See "Documentation/s390/kmsg.txt" for more details.
 +
  config SECCOMP
-       bool "Enable seccomp to safely compute untrusted bytecode"
+       def_bool y
+       prompt "Enable seccomp to safely compute untrusted bytecode"
        depends on PROC_FS
-       default y
        help
          This kernel feature is useful for number crunching applications
          that may need to compute untrusted bytecode during their
Simple merge
Simple merge
@@@ -1396,23 -1343,7 +1343,22 @@@ static int __init dmi_ignore_irq0_timer
        }
        return 0;
  }
- #endif
  
 +static int __init force_acpi_rsdt(const struct dmi_system_id *d)
 +{
 +      if (!acpi_force) {
 +              printk(KERN_NOTICE "%s detected: force use of acpi=rsdt\n",
 +                     d->ident);
 +              acpi_rsdt_forced = 1;
 +      } else {
 +              printk(KERN_NOTICE
 +                     "Warning: acpi=force overrules DMI blacklist: "
 +                     "acpi=rsdt\n");
 +      }
 +      return 0;
 +
 +}
 +
  /*
   * If your system is blacklisted here, but you find that acpi=force
   * works for you, please contact linux-acpi@vger.kernel.org
@@@ -2,9 -2,7 +2,8 @@@ obj-y                            =  mce.o mce-severity.
  
  obj-$(CONFIG_X86_ANCIENT_MCE) += winchip.o p5.o
  obj-$(CONFIG_X86_MCE_INTEL)   += mce_intel.o
 +obj-$(CONFIG_X86_MCE_XEON75XX)        += mce-xeon75xx.o
  obj-$(CONFIG_X86_MCE_AMD)     += mce_amd.o
- obj-$(CONFIG_X86_XEN_MCE)     += mce_dom0.o
  obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o
  obj-$(CONFIG_X86_MCE_INJECT)  += mce-inject.o
  
Simple merge
Simple merge
Simple merge
@@@ -2426,22 -2557,19 +2557,35 @@@ static int skinit_interception(struct v
        return 1;
  }
  
+ static int xsetbv_interception(struct vcpu_svm *svm)
+ {
+       u64 new_bv = kvm_read_edx_eax(&svm->vcpu);
+       u32 index = kvm_register_read(&svm->vcpu, VCPU_REGS_RCX);
+       if (kvm_set_xcr(&svm->vcpu, index, new_bv) == 0) {
+               svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
+               skip_emulated_instruction(&svm->vcpu);
+       }
+       return 1;
+ }
 +static int monitor_interception(struct vcpu_svm *svm)
 +{
 +      svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
 +      skip_emulated_instruction(&svm->vcpu);
 +
 +      return 1;
 +}
 +
 +static int mwait_interception(struct vcpu_svm *svm)
 +{
 +      svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
 +      skip_emulated_instruction(&svm->vcpu);
 +
 +      return kvm_emulate_halt(&svm->vcpu);
 +}
 +
  static int invalid_op_interception(struct vcpu_svm *svm)
  {
        kvm_queue_exception(&svm->vcpu, UD_VECTOR);
@@@ -2868,8 -3091,9 +3107,9 @@@ static int (*svm_exit_handlers[])(struc
        [SVM_EXIT_CLGI]                         = clgi_interception,
        [SVM_EXIT_SKINIT]                       = skinit_interception,
        [SVM_EXIT_WBINVD]                       = emulate_on_interception,
 -      [SVM_EXIT_MONITOR]                      = invalid_op_interception,
 -      [SVM_EXIT_MWAIT]                        = invalid_op_interception,
 +      [SVM_EXIT_MONITOR]                      = monitor_interception,
 +      [SVM_EXIT_MWAIT]                        = mwait_interception,
+       [SVM_EXIT_XSETBV]                       = xsetbv_interception,
        [SVM_EXIT_NPF]                          = pf_interception,
  };
  
Simple merge
@@@ -946,20 -965,7 +965,21 @@@ void mark_rodata_ro(void
        printk(KERN_INFO "Testing CPA: write protecting again\n");
        set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
  #endif
+       mark_nxdata_nx();
  }
 +EXPORT_SYMBOL_GPL(mark_rodata_ro);
 +
 +void mark_rodata_rw(void)
 +{
 +      unsigned long start = PFN_ALIGN(_text);
 +      unsigned long size = PFN_ALIGN(_etext) - start;
 +
 +      start += size;
 +      size = (unsigned long)__end_rodata - start;
 +      set_pages_rw_force(virt_to_page(start), size >> PAGE_SHIFT);
 +      printk(KERN_INFO "Write enabling the kernel read-only data: %luk\n",
 +              size >> 10);
 +}
 +EXPORT_SYMBOL_GPL(mark_rodata_rw);
  #endif
  
@@@ -278,11 -280,15 +282,18 @@@ static inline pgprot_t static_protectio
         * catches all aliases.
         */
        if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT,
 -                 __pa((unsigned long)__end_rodata) >> PAGE_SHIFT))
 -              pgprot_val(forbidden) |= _PAGE_RW;
 +                 __pa((unsigned long)__end_rodata) >> PAGE_SHIFT)) {
 +              if (!static_protections_allow_rodata)
 +                      pgprot_val(forbidden) |= _PAGE_RW;
 +      }
 +
+       /*
+        * .data and .bss should always be writable.
+        */
+       if (within(address, (unsigned long)_sdata, (unsigned long)_edata) ||
+           within(address, (unsigned long)__bss_start, (unsigned long)__bss_stop))
+               pgprot_val(required) |= _PAGE_RW;
  #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA)
        /*
         * Once the kernel maps the text as RO (kernel_set_to_readonly is set),
Simple merge
Simple merge
diff --cc block/genhd.c
@@@ -502,18 -507,64 +507,76 @@@ static int exact_lock(dev_t devt, void 
        return 0;
  }
  
+ void register_disk(struct gendisk *disk)
+ {
+       struct device *ddev = disk_to_dev(disk);
+       struct block_device *bdev;
+       struct disk_part_iter piter;
+       struct hd_struct *part;
+       int err;
+       ddev->parent = disk->driverfs_dev;
+       dev_set_name(ddev, disk->disk_name);
+       /* delay uevents, until we scanned partition table */
+       dev_set_uevent_suppress(ddev, 1);
+       if (device_add(ddev))
+               return;
+       if (!sysfs_deprecated) {
+               err = sysfs_create_link(block_depr, &ddev->kobj,
+                                       kobject_name(&ddev->kobj));
+               if (err) {
+                       device_del(ddev);
+                       return;
+               }
+       }
+       disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj);
+       disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
+       /* No minors to use for partitions */
+       if (!disk_partitionable(disk))
+               goto exit;
+       /* No such device (e.g., media were just removed) */
+       if (!get_capacity(disk))
+               goto exit;
+       bdev = bdget_disk(disk, 0);
+       if (!bdev)
+               goto exit;
+       bdev->bd_invalidated = 1;
+       err = blkdev_get(bdev, FMODE_READ, NULL);
+       if (err < 0)
+               goto exit;
+       blkdev_put(bdev, FMODE_READ);
+ exit:
+       /* announce disk after possible partitions are created */
+       dev_set_uevent_suppress(ddev, 0);
+       kobject_uevent(&ddev->kobj, KOBJ_ADD);
+       /* announce possible partitions */
+       disk_part_iter_init(&piter, disk, 0);
+       while ((part = disk_part_iter_next(&piter)))
+               kobject_uevent(&part_to_dev(part)->kobj, KOBJ_ADD);
+       disk_part_iter_exit(&piter);
+ }
 +static int __read_mostly no_partition_scan;
 +
 +static int __init no_partition_scan_setup(char *str)
 +{
 +      no_partition_scan = 1;
 +      printk(KERN_INFO "genhd: omit partition scan.\n");
 +
 +      return 1;
 +}
 +
 +__setup("no_partition_scan", no_partition_scan_setup);
 +
  /**
   * add_disk - add partitioning information to kernel list
   * @disk: per-device partitioning information
@@@ -29,14 -29,20 +29,13 @@@ obj-$(CONFIG_REGULATOR)            += regulator
  obj-y                         += tty/
  obj-y                         += char/
  
 -# gpu/ comes after char for AGP vs DRM startup
 -obj-y                         += gpu/
 -
  obj-$(CONFIG_CONNECTOR)               += connector/
  
 -# i810fb and intelfb depend on char/agp/
 -obj-$(CONFIG_FB_I810)           += video/i810/
 -obj-$(CONFIG_FB_INTEL)          += video/intelfb/
 -
  obj-y                         += serial/
  obj-$(CONFIG_PARPORT)         += parport/
- obj-y                         += base/ block/ misc/ mfd/
+ obj-y                         += base/ block/ misc/ mfd/ nfc/
  obj-$(CONFIG_NUBUS)           += nubus/
  obj-y                         += macintosh/
- obj-$(CONFIG_XEN)             += xen/
  obj-$(CONFIG_IDE)             += ide/
  obj-$(CONFIG_SCSI)            += scsi/
  obj-$(CONFIG_ATA)             += ata/
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1604,8 -1642,7 +1642,9 @@@ static const struct hid_device_id hid_i
        { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_4000U) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_4500U) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
  #define USB_VENDOR_ID_ELECOM          0x056e
  #define USB_DEVICE_ID_ELECOM_BM084    0x0061
  
+ #define USB_VENDOR_ID_DREAM_CHEEKY    0x1d34
  #define USB_VENDOR_ID_ELO             0x04E7
 +#define USB_DEVICE_ID_ELO_4000U               0x0009
  #define USB_DEVICE_ID_ELO_TS2700      0x0020
 +#define USB_DEVICE_ID_ELO_4500U               0x0030
  
+ #define USB_VENDOR_ID_EMS             0x2006
+ #define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118
  #define USB_VENDOR_ID_ESSENTIAL_REALITY       0x0d7f
  #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
  
Simple merge
  
  #include <linux/module.h>
  #include <linux/dmi.h>
- #include <linux/input.h>
+ #include <linux/input/mt.h>
  #include <linux/serio.h>
  #include <linux/libps2.h>
 +#include <linux/leds.h>
  #include <linux/slab.h>
  #include "psmouse.h"
  #include "synaptics.h"
@@@ -808,8 -777,11 +883,13 @@@ static int synaptics_reconnect(struct p
                return -1;
        }
  
+       if (synaptics_set_advanced_gesture_mode(psmouse)) {
+               printk(KERN_ERR "Advanced gesture mode reconnect failed.\n");
+               return -1;
+       }
 +      synaptics_sync_led(psmouse);
 +
        return 0;
  }
  
@@@ -115,7 -114,8 +116,9 @@@ struct synaptics_data 
        int scroll;
  
        struct serio *pt_port;                  /* Pass-through serio port */
+       struct synaptics_hw_state mt;           /* current gesture packet */
 +      struct synaptics_led *led;
  };
  
  void synaptics_module_init(void);
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -36,7 -36,7 +36,8 @@@ obj-$(CONFIG_DM_SNAPSHOT)     += dm-snapsho
  obj-$(CONFIG_DM_MIRROR)               += dm-mirror.o dm-log.o dm-region-hash.o
  obj-$(CONFIG_DM_LOG_USERSPACE)        += dm-log-userspace.o
  obj-$(CONFIG_DM_ZERO)         += dm-zero.o
- obj-$(CONFIG_DM_RAID45)               += dm-raid45.o dm-log.o dm-memcache.o \
+ obj-$(CONFIG_DM_RAID) += dm-raid.o
++obj-$(CONFIG_DM_RAID45)               += dm-raid45.o dm-log.o dm-memcache.o
  
  ifeq ($(CONFIG_DM_UEVENT),y)
  dm-mod-objs                   += dm-uevent.o
@@@ -85,7 -87,7 +90,8 @@@ struct multipath 
        unsigned saved_queue_if_no_path;/* Saved state during suspension */
        unsigned pg_init_retries;       /* Number of times to retry pg_init */
        unsigned pg_init_count;         /* Number of times pg_init called */
+       unsigned pg_init_delay_msecs;   /* Number of msecs before pg_init retry */
 +      unsigned features;              /* Additional selected features */
  
        struct work_struct process_queued_ios;
        struct list_head queued_ios;
@@@ -170,7 -160,7 +165,6 @@@ static struct priority_group *alloc_pri
  static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
  {
        struct pgpath *pgpath, *tmp;
--      struct multipath *m = ti->private;
  
        list_for_each_entry_safe(pgpath, tmp, pgpaths, list) {
                list_del(&pgpath->list);
@@@ -1237,9 -1190,8 +1199,9 @@@ static void pg_init_done(void *data, in
                        errors = 0;
                        break;
                }
 -              DMERR("Could not failover the device: Handler scsi_dh_%s "
 -                    "Error %d.", m->hw_handler_name, errors);
 +              DMERR("Count not failover device %s: Handler scsi_dh_%s "
-                     "was not loaded.", pgpath->path.pdev,
++                    "was not loaded.", pgpath->path.dev->name,
 +                    m->hw_handler_name);
                /*
                 * Fail path for now, so we do not ping pong
                 */
                 */
                bypass_pg(m, pg, 1);
                break;
 +      case SCSI_DH_DEV_OFFLINED:
-               DMWARN("Device %s offlined.", pgpath->path.pdev);
++              DMWARN("Device %s offlined.", pgpath->path.dev->name);
 +              errors = 0;
 +              break;
-       /* TODO: For SCSI_DH_RETRY we should wait a couple seconds */
        case SCSI_DH_RETRY:
+               /* Wait before retrying. */
+               delay_retry = 1;
        case SCSI_DH_IMM_RETRY:
        case SCSI_DH_RES_TEMP_UNAVAIL:
                if (pg_init_limit_reached(m, pgpath))
        spin_lock_irqsave(&m->lock, flags);
        if (errors) {
                if (pgpath == m->current_pgpath) {
 -                      DMERR("Could not failover device. Error %d.", errors);
 +                      DMERR("Could not failover device %s, error %d.",
-                             pgpath->path.pdev, errors);
++                            pgpath->path.dev->name, errors);
                        m->current_pgpath = NULL;
                        m->current_pg = NULL;
                }
@@@ -1494,13 -1396,13 +1457,16 @@@ static int multipath_status(struct dm_t
        else {
                DMEMIT("%u ", m->queue_if_no_path +
                              (m->pg_init_retries > 0) * 2 +
 -                            (m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT) * 2);
++                            (m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT) * 2 +
 +                            (m->features & FEATURE_NO_PARTITIONS));
                if (m->queue_if_no_path)
                        DMEMIT("queue_if_no_path ");
                if (m->pg_init_retries)
                        DMEMIT("pg_init_retries %u ", m->pg_init_retries);
 +              if (m->features & FEATURE_NO_PARTITIONS)
 +                      DMEMIT("no_partitions ");
+               if (m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT)
+                       DMEMIT("pg_init_delay_msecs %u ", m->pg_init_delay_msecs);
        }
  
        if (!m->hw_handler_name || type == STATUSTYPE_INFO)
Simple merge
diff --cc drivers/md/dm.c
@@@ -327,9 -326,7 +326,8 @@@ int dm_deleting_md(struct mapped_devic
  static int dm_blk_open(struct block_device *bdev, fmode_t mode)
  {
        struct mapped_device *md;
 +      int retval = 0;
  
-       mutex_lock(&dm_mutex);
        spin_lock(&_minor_lock);
  
        md = bdev->bd_disk->private_data;
  
  out:
        spin_unlock(&_minor_lock);
-       mutex_unlock(&dm_mutex);
  
 -      return md ? 0 : -ENXIO;
 +      return retval;
  }
  
  static int dm_blk_close(struct gendisk *disk, fmode_t mode)
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1243,20 -1363,25 +1368,22 @@@ static void ixgbe_clean_rx_irq(struct i
                }
  
                if (upper_len) {
-                       dma_unmap_page(&pdev->dev, rx_buffer_info->page_dma,
-                                      PAGE_SIZE / 2, DMA_FROM_DEVICE);
+                       dma_unmap_page(rx_ring->dev,
+                                      rx_buffer_info->page_dma,
+                                      PAGE_SIZE / 2,
+                                      DMA_FROM_DEVICE);
                        rx_buffer_info->page_dma = 0;
 -                      skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
 -                                         rx_buffer_info->page,
 -                                         rx_buffer_info->page_offset,
 -                                         upper_len);
 +                      skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
 +                                      rx_buffer_info->page,
 +                                      rx_buffer_info->page_offset,
 +                                      upper_len);
  
-                       if ((rx_ring->rx_buf_len > (PAGE_SIZE / 2)) ||
-                           (page_count(rx_buffer_info->page) != 1))
-                               rx_buffer_info->page = NULL;
-                       else
+                       if ((page_count(rx_buffer_info->page) == 1) &&
+                           (page_to_nid(rx_buffer_info->page) == current_node))
                                get_page(rx_buffer_info->page);
+                       else
+                               rx_buffer_info->page = NULL;
  
 -                      skb->len += upper_len;
 -                      skb->data_len += upper_len;
 -                      skb->truesize += upper_len;
                }
  
                i++;
@@@ -2147,36 -2324,36 +2327,41 @@@ static int ixgbe_request_msix_irqs(stru
        /* Decrement for Other and TCP Timer vectors */
        q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
  
-       /* Map the Tx/Rx rings to the vectors we were allotted. */
-       err = ixgbe_map_rings_to_vectors(adapter, q_vectors);
+       err = ixgbe_map_rings_to_vectors(adapter);
        if (err)
-               goto out;
+               return err;
  
- #define SET_HANDLER(_v) ((!(_v)->rxr_count) ? &ixgbe_msix_clean_tx : \
-                        (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \
-                        &ixgbe_msix_clean_many)
+ #define SET_HANDLER(_v) (((_v)->rxr_count && (_v)->txr_count)        \
+                                         ? &ixgbe_msix_clean_many : \
+                         (_v)->rxr_count ? &ixgbe_msix_clean_rx   : \
+                         (_v)->txr_count ? &ixgbe_msix_clean_tx   : \
+                         NULL)
        for (vector = 0; vector < q_vectors; vector++) {
-               handler = SET_HANDLER(adapter->q_vector[vector]);
+               struct ixgbe_q_vector *q_vector = adapter->q_vector[vector];
+               handler = SET_HANDLER(q_vector);
  
 +              irq_flags = 0;
                if (handler == &ixgbe_msix_clean_rx) {
-                       sprintf(adapter->name[vector], "%s-%s-%d",
-                               netdev->name, "rx", ri++);
+                       snprintf(q_vector->name, sizeof(q_vector->name) - 1,
+                                "%s-%s-%d", netdev->name, "rx", ri++);
 +                      if (entropy)
 +                              irq_flags = IRQF_SAMPLE_RANDOM;
                } else if (handler == &ixgbe_msix_clean_tx) {
-                       sprintf(adapter->name[vector], "%s-%s-%d",
-                               netdev->name, "tx", ti++);
-               } else {
-                       sprintf(adapter->name[vector], "%s-%s-%d",
-                               netdev->name, "TxRx", vector);
+                       snprintf(q_vector->name, sizeof(q_vector->name) - 1,
+                                "%s-%s-%d", netdev->name, "tx", ti++);
+               } else if (handler == &ixgbe_msix_clean_many) {
+                       snprintf(q_vector->name, sizeof(q_vector->name) - 1,
+                                "%s-%s-%d", netdev->name, "TxRx", ri++);
 +                      if (entropy)
 +                              irq_flags = IRQF_SAMPLE_RANDOM;
+                       ti++;
+               } else {
+                       /* skip this unused q_vector */
+                       continue;
                }
                err = request_irq(adapter->msix_entries[vector].vector,
-                                 handler, irq_flags, adapter->name[vector],
-                                 adapter->q_vector[vector]);
 -                                handler, 0, q_vector->name,
++                                handler, irq_flags, q_vector->name,
+                                 q_vector);
                if (err) {
                        e_err(probe, "request_irq failed for MSIX interrupt "
                              "Error: %d\n", err);
Simple merge
Simple merge
  
  #include "tg3.h"
  
 +static int entropy = 0;
 +module_param(entropy, int, 0);
 +MODULE_PARM_DESC(entropy, "Allow tg3 to populate the /dev/random entropy pool");
 +
  #define DRV_MODULE_NAME               "tg3"
  #define TG3_MAJ_NUM                   3
- #define TG3_MIN_NUM                   115
+ #define TG3_MIN_NUM                   116
  #define DRV_MODULE_VERSION    \
        __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
- #define DRV_MODULE_RELDATE    "October 14, 2010"
+ #define DRV_MODULE_RELDATE    "December 3, 2010"
  
  #define TG3_DEF_MAC_MODE      0
  #define TG3_DEF_RX_MODE               0
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -444,15 -439,22 +444,22 @@@ int scsi_dh_activate(struct request_que
        struct scsi_device_handler *scsi_dh = NULL;
  
        spin_lock_irqsave(q->queue_lock, flags);
 -      sdev = q->queuedata;
 +      sdev = scsi_device_from_queue(q);
        if (sdev && sdev->scsi_dh_data)
                scsi_dh = sdev->scsi_dh_data->scsi_dh;
-       if (!scsi_dh || !get_device(&sdev->sdev_gendev))
+       if (!scsi_dh || !get_device(&sdev->sdev_gendev) ||
+           sdev->sdev_state == SDEV_CANCEL ||
+           sdev->sdev_state == SDEV_DEL)
                err = SCSI_DH_NOSYS;
+       if (sdev->sdev_state == SDEV_OFFLINE)
+               err = SCSI_DH_DEV_OFFLINED;
        spin_unlock_irqrestore(q->queue_lock, flags);
  
-       if (err)
+       if (err) {
+               if (fn)
+                       fn(data, err);
                return err;
+       }
  
        if (scsi_dh->activate)
                err = scsi_dh->activate(sdev, fn, data);
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc fs/Kconfig
@@@ -30,18 -30,6 +30,9 @@@ config FS_MBCACH
  source "fs/reiserfs/Kconfig"
  source "fs/jfs/Kconfig"
  
- config FS_POSIX_ACL
- # Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs/nfs4)
- #
- # NOTE: you can implement Posix ACLs without these helpers (XFS does).
- #     Never use this symbol for ifdefs.
- #
-       bool
-       default n
 +config FS_RICHACL
 +      bool
 +
  source "fs/xfs/Kconfig"
  source "fs/gfs2/Kconfig"
  source "fs/ocfs2/Kconfig"
diff --cc fs/dcache.c
Simple merge
diff --cc fs/ext3/super.c
Simple merge
diff --cc fs/ext4/acl.c
Simple merge
diff --cc fs/ext4/ext4.h
Simple merge
diff --cc fs/ext4/file.c
@@@ -202,10 -224,6 +225,9 @@@ const struct inode_operations ext4_file
        .removexattr    = generic_removexattr,
  #endif
        .check_acl      = ext4_check_acl,
-       .fallocate      = ext4_fallocate,
        .fiemap         = ext4_fiemap,
 +      .permission     = ext4_permission,
 +      .may_create     = ext4_may_create,
 +      .may_delete     = ext4_may_delete,
  };
  
Simple merge
diff --cc fs/ext4/inode.c
@@@ -4860,10 -4890,7 +4891,10 @@@ struct inode *ext4_iget(struct super_bl
        }
        inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
  
-       ei->i_state_flags = 0;
+       ext4_clear_state_flags(ei);     /* Only relevant on 32-bit archs */
 +#ifdef CONFIG_EXT4_FS_RICHACL
 +      ei->i_richacl = EXT4_RICHACL_NOT_CACHED;
 +#endif
        ei->i_dir_start_lookup = 0;
        ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
        /* We now have enough fields to check if the inode was active or not.
diff --cc fs/ext4/namei.c
Simple merge
index 54e9239,0000000..a44c2e5
mode 100644,000000..100644
--- /dev/null
@@@ -1,293 -1,0 +1,294 @@@
 +/*
 + * Copyright IBM Corporation, 2010
 + * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of version 2.1 of the GNU Lesser General Public License
 + * as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it would be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 + *
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/fs.h>
 +#include <linux/richacl_xattr.h>
 +
 +#include "ext4.h"
 +#include "ext4_jbd2.h"
 +#include "xattr.h"
 +#include "acl.h"
 +#include "richacl.h"
 +
 +static inline struct richacl *
 +ext4_iget_richacl(struct inode *inode)
 +{
 +      struct richacl *acl = EXT4_RICHACL_NOT_CACHED;
 +      struct ext4_inode_info *ei = EXT4_I(inode);
 +
 +      spin_lock(&inode->i_lock);
 +      if (ei->i_richacl != EXT4_RICHACL_NOT_CACHED)
 +              acl = richacl_get(ei->i_richacl);
 +      spin_unlock(&inode->i_lock);
 +
 +      return acl;
 +}
 +
 +static inline void
 +ext4_iset_richacl(struct inode *inode, struct richacl *acl)
 +{
 +      struct ext4_inode_info *ei = EXT4_I(inode);
 +
 +      spin_lock(&inode->i_lock);
 +      if (ei->i_richacl != EXT4_RICHACL_NOT_CACHED)
 +              richacl_put(ei->i_richacl);
 +      ei->i_richacl = richacl_get(acl);
 +      spin_unlock(&inode->i_lock);
 +}
 +
 +static struct richacl *
 +ext4_get_richacl(struct inode *inode)
 +{
 +      const int name_index = EXT4_XATTR_INDEX_RICHACL;
 +      void *value = NULL;
 +      struct richacl *acl;
 +      int retval;
 +
 +      if (!IS_RICHACL(inode))
 +              return ERR_PTR(-EOPNOTSUPP);
 +      acl = ext4_iget_richacl(inode);
 +      if (acl != EXT4_RICHACL_NOT_CACHED)
 +              return acl;
 +      retval = ext4_xattr_get(inode, name_index, "", NULL, 0);
 +      if (retval > 0) {
 +              value = kmalloc(retval, GFP_KERNEL);
 +              if (!value)
 +                      return ERR_PTR(-ENOMEM);
 +              retval = ext4_xattr_get(inode, name_index, "", value, retval);
 +      }
 +      if (retval > 0) {
 +              acl = richacl_from_xattr(value, retval);
 +              if (acl == ERR_PTR(-EINVAL))
 +                      acl = ERR_PTR(-EIO);
 +      } else if (retval == -ENODATA || retval == -ENOSYS)
 +              acl = NULL;
 +      else
 +              acl = ERR_PTR(retval);
 +      kfree(value);
 +
 +      if (!IS_ERR_OR_NULL(acl))
 +              ext4_iset_richacl(inode, acl);
 +
 +      return acl;
 +}
 +
 +static int
 +ext4_set_richacl(handle_t *handle, struct inode *inode, struct richacl *acl)
 +{
 +      const int name_index = EXT4_XATTR_INDEX_RICHACL;
 +      size_t size = 0;
 +      void *value = NULL;
 +      int retval;
 +
 +      if (acl) {
 +              mode_t mode = inode->i_mode;
 +              if (richacl_equiv_mode(acl, &mode) == 0) {
 +                      inode->i_mode = mode;
 +                      ext4_mark_inode_dirty(handle, inode);
 +                      acl = NULL;
 +              }
 +      }
 +      if (acl) {
 +              size = richacl_xattr_size(acl);
 +              value = kmalloc(size, GFP_KERNEL);
 +              if (!value)
 +                      return -ENOMEM;
 +              richacl_to_xattr(acl, value);
 +      }
 +      if (handle)
 +              retval = ext4_xattr_set_handle(handle, inode, name_index, "",
 +                                             value, size, 0);
 +      else
 +              retval = ext4_xattr_set(inode, name_index, "", value, size, 0);
 +      kfree(value);
 +      if (!retval)
 +              ext4_iset_richacl(inode, acl);
 +
 +      return retval;
 +}
 +
 +int
- ext4_richacl_permission(struct inode *inode, unsigned int mask)
++ext4_richacl_permission(struct inode *inode, unsigned int mask,
++                      unsigned int flags)
 +{
 +      struct richacl *acl;
 +      int retval;
 +
 +      if (!IS_RICHACL(inode))
 +              BUG();
 +
 +      acl = ext4_get_richacl(inode);
 +      if (acl && IS_ERR(acl))
 +              retval = PTR_ERR(acl);
 +      else {
-               retval = richacl_inode_permission(inode, acl, mask);
++              retval = richacl_inode_permission(inode, acl, mask, flags);
 +              richacl_put(acl);
 +      }
 +
 +      return retval;
 +}
 +
- int ext4_permission(struct inode *inode, int mask)
++int ext4_permission(struct inode *inode, int mask, unsigned int flags)
 +{
 +      if (IS_RICHACL(inode))
 +              return ext4_richacl_permission(inode,
-                                       richacl_want_to_mask(mask));
++                                      richacl_want_to_mask(mask), flags);
 +      else
-               return generic_permission(inode, mask, ext4_check_acl);
++              return generic_permission(inode, mask, flags, ext4_check_acl);
 +}
 +
 +int ext4_may_create(struct inode *dir, int isdir)
 +{
 +      return richacl_may_create(dir, isdir, ext4_richacl_permission);
 +}
 +
 +int ext4_may_delete(struct inode *dir, struct inode *inode, int replace)
 +{
 +      return richacl_may_delete(dir, inode, replace, ext4_richacl_permission);
 +}
 +
 +int
 +ext4_init_richacl(handle_t *handle, struct inode *inode, struct inode *dir)
 +{
 +      struct richacl *dir_acl = NULL;
 +
 +      if (!S_ISLNK(inode->i_mode)) {
 +              dir_acl = ext4_get_richacl(dir);
 +              if (IS_ERR(dir_acl))
 +                      return PTR_ERR(dir_acl);
 +      }
 +      if (dir_acl) {
 +              struct richacl *acl;
 +              int retval;
 +
 +              acl = richacl_inherit(dir_acl, inode);
 +              richacl_put(dir_acl);
 +
 +              retval = PTR_ERR(acl);
 +              if (acl && !IS_ERR(acl)) {
 +                      retval = ext4_set_richacl(handle, inode, acl);
 +                      richacl_put(acl);
 +              }
 +              return retval;
 +      } else {
 +              inode->i_mode &= ~current_umask();
 +              return 0;
 +      }
 +}
 +
 +int
 +ext4_richacl_chmod(struct inode *inode)
 +{
 +      struct richacl *acl;
 +      int retval;
 +
 +      if (S_ISLNK(inode->i_mode))
 +              return -EOPNOTSUPP;
 +      acl = ext4_get_richacl(inode);
 +      if (IS_ERR_OR_NULL(acl))
 +              return PTR_ERR(acl);
 +      acl = richacl_chmod(acl, inode->i_mode);
 +      if (IS_ERR(acl))
 +              return PTR_ERR(acl);
 +      retval = ext4_set_richacl(NULL, inode, acl);
 +      richacl_put(acl);
 +
 +      return retval;
 +}
 +
 +static size_t
 +ext4_xattr_list_richacl(struct dentry *dentry, char *list, size_t list_len,
 +                      const char *name, size_t name_len, int type)
 +{
 +      const size_t size = sizeof(RICHACL_XATTR);
 +      if (!IS_RICHACL(dentry->d_inode))
 +              return 0;
 +      if (list && size <= list_len)
 +              memcpy(list, RICHACL_XATTR, size);
 +      return size;
 +}
 +
 +static int
 +ext4_xattr_get_richacl(struct dentry *dentry, const char *name, void *buffer,
 +              size_t buffer_size, int type)
 +{
 +      struct richacl *acl;
 +      size_t size;
 +
 +      if (strcmp(name, "") != 0)
 +              return -EINVAL;
 +      acl = ext4_get_richacl(dentry->d_inode);
 +      if (IS_ERR(acl))
 +              return PTR_ERR(acl);
 +      if (acl == NULL)
 +              return -ENODATA;
 +      size = richacl_xattr_size(acl);
 +      if (buffer) {
 +              if (size > buffer_size)
 +                      return -ERANGE;
 +              richacl_to_xattr(acl, buffer);
 +      }
 +      richacl_put(acl);
 +
 +      return size;
 +}
 +
 +static int
 +ext4_xattr_set_richacl(struct dentry *dentry, const char *name,
 +              const void *value, size_t size, int flags, int type)
 +{
 +      handle_t *handle;
 +      struct richacl *acl = NULL;
 +      int retval, retries = 0;
 +      struct inode *inode = dentry->d_inode;
 +
 +      if (!IS_RICHACL(dentry->d_inode))
 +              return -EOPNOTSUPP;
 +      if (S_ISLNK(inode->i_mode))
 +              return -EOPNOTSUPP;
 +      if (strcmp(name, "") != 0)
 +              return -EINVAL;
 +      if (current_fsuid() != inode->i_uid &&
-           ext4_richacl_permission(inode, ACE4_WRITE_ACL) &&
++          ext4_richacl_permission(inode, ACE4_WRITE_ACL, 0) &&
 +          !capable(CAP_FOWNER))
 +              return -EPERM;
 +      if (value) {
 +              acl = richacl_from_xattr(value, size);
 +              if (IS_ERR(acl))
 +                      return PTR_ERR(acl);
 +
 +              inode->i_mode &= ~S_IRWXUGO;
 +              inode->i_mode |= richacl_masks_to_mode(acl);
 +      }
 +
 +retry:
 +      handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
 +      if (IS_ERR(handle))
 +              return PTR_ERR(handle);
 +      ext4_mark_inode_dirty(handle, inode);
 +      retval = ext4_set_richacl(handle, inode, acl);
 +      ext4_journal_stop(handle);
 +      if (retval == ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
 +              goto retry;
 +      richacl_put(acl);
 +      return retval;
 +}
 +
 +const struct xattr_handler ext4_richacl_xattr_handler = {
 +      .prefix = RICHACL_XATTR,
 +      .list   = ext4_xattr_list_richacl,
 +      .get    = ext4_xattr_get_richacl,
 +      .set    = ext4_xattr_set_richacl,
 +};
index 00d89f2,0000000..fdb1a5b
mode 100644,000000..100644
--- /dev/null
@@@ -1,56 -1,0 +1,56 @@@
 +/*
 + * Copyright IBM Corporation, 2010
 + * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of version 2.1 of the GNU Lesser General Public License
 + * as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it would be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 + *
 + */
 +
 +#ifndef __FS_EXT4_RICHACL_H
 +#define __FS_EXT4_RICHACL_H
 +
 +#include <linux/richacl.h>
 +
 +#ifdef CONFIG_EXT4_FS_RICHACL
 +
 +# define EXT4_IS_RICHACL(inode) IS_RICHACL(inode)
 +
 +/* Value for i_richacl if RICHACL has not been cached */
 +# define EXT4_RICHACL_NOT_CACHED ((void *)-1)
 +
- extern int ext4_permission(struct inode *, int);
- extern int ext4_richacl_permission(struct inode *, unsigned int);
++extern int ext4_permission(struct inode *, int, unsigned int);
++extern int ext4_richacl_permission(struct inode *, unsigned int, unsigned int);
 +extern int ext4_may_create(struct inode *, int);
 +extern int ext4_may_delete(struct inode *, struct inode *, int);
 +extern int ext4_init_richacl(handle_t *, struct inode *, struct inode *);
 +extern int ext4_richacl_chmod(struct inode *);
 +
 +#else  /* CONFIG_FS_EXT4_RICHACL */
 +
 +# define EXT4_IS_RICHACL(inode) (0)
 +
 +# define ext4_permission NULL
 +# define ext4_may_create NULL
 +# define ext4_may_delete NULL
 +# define ext4_richacl_permission NULL
 +
 +static inline int
 +ext4_init_richacl(handle_t *handle, struct inode *inode, struct inode *dir)
 +{
 +      return 0;
 +}
 +
 +static inline int
 +ext4_richacl_chmod(struct inode *inode)
 +{
 +      return 0;
 +}
 +
 +#endif  /* CONFIG_FS_EXT4_RICHACL */
 +#endif  /* __FS_EXT4_RICHACL_H */
diff --cc fs/ext4/super.c
@@@ -894,17 -900,13 +903,20 @@@ void ext4_clear_inode(struct inode *ino
        invalidate_inode_buffers(inode);
        end_writeback(inode);
        dquot_drop(inode);
 +#ifdef CONFIG_EXT4_FS_RICHACL
 +      if (EXT4_I(inode)->i_richacl &&
 +              EXT4_I(inode)->i_richacl != EXT4_RICHACL_NOT_CACHED) {
 +              richacl_put(EXT4_I(inode)->i_richacl);
 +              EXT4_I(inode)->i_richacl = EXT4_RICHACL_NOT_CACHED;
 +      }
 +#endif
        ext4_discard_preallocations(inode);
-       if (EXT4_JOURNAL(inode))
-               jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal,
-                                      &EXT4_I(inode)->jinode);
+       if (EXT4_I(inode)->jinode) {
+               jbd2_journal_release_jbd_inode(EXT4_JOURNAL(inode),
+                                              EXT4_I(inode)->jinode);
+               jbd2_free_inode(EXT4_I(inode)->jinode);
+               EXT4_I(inode)->jinode = NULL;
+       }
  }
  
  static inline void ext4_show_quota_options(struct seq_file *seq,
@@@ -3103,35 -3089,35 +3112,35 @@@ static int ext4_fill_super(struct super
        if (def_mount_opts & EXT4_DEFM_BSDGROUPS) {
                ext4_msg(sb, KERN_WARNING, deprecated_msg, "bsdgroups",
                        "2.6.38");
-               set_opt(sbi->s_mount_opt, GRPID);
+               set_opt(sb, GRPID);
        }
        if (def_mount_opts & EXT4_DEFM_UID16)
-               set_opt(sbi->s_mount_opt, NO_UID32);
+               set_opt(sb, NO_UID32);
  #ifdef CONFIG_EXT4_FS_XATTR
        if (def_mount_opts & EXT4_DEFM_XATTR_USER)
-               set_opt(sbi->s_mount_opt, XATTR_USER);
+               set_opt(sb, XATTR_USER);
  #endif
 -#ifdef CONFIG_EXT4_FS_POSIX_ACL
 +#if defined(CONFIG_EXT4_FS_POSIX_ACL)
        if (def_mount_opts & EXT4_DEFM_ACL)
 -              set_opt(sb, POSIX_ACL);
 +              sb->s_flags |= MS_POSIXACL;
  #endif
        if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA)
-               set_opt(sbi->s_mount_opt, JOURNAL_DATA);
+               set_opt(sb, JOURNAL_DATA);
        else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED)
-               set_opt(sbi->s_mount_opt, ORDERED_DATA);
+               set_opt(sb, ORDERED_DATA);
        else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_WBACK)
-               set_opt(sbi->s_mount_opt, WRITEBACK_DATA);
+               set_opt(sb, WRITEBACK_DATA);
  
        if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_PANIC)
-               set_opt(sbi->s_mount_opt, ERRORS_PANIC);
+               set_opt(sb, ERRORS_PANIC);
        else if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_CONTINUE)
-               set_opt(sbi->s_mount_opt, ERRORS_CONT);
+               set_opt(sb, ERRORS_CONT);
        else
-               set_opt(sbi->s_mount_opt, ERRORS_RO);
+               set_opt(sb, ERRORS_RO);
        if (def_mount_opts & EXT4_DEFM_BLOCK_VALIDITY)
-               set_opt(sbi->s_mount_opt, BLOCK_VALIDITY);
+               set_opt(sb, BLOCK_VALIDITY);
        if (def_mount_opts & EXT4_DEFM_DISCARD)
-               set_opt(sbi->s_mount_opt, DISCARD);
+               set_opt(sb, DISCARD);
  
        sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
        sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
diff --cc fs/ext4/xattr.c
Simple merge
Simple merge
diff --cc fs/inode.c
Simple merge
diff --cc fs/namei.c
@@@ -385,8 -566,28 +566,29 @@@ void release_open_intent(struct nameida
        else
                fput(nd->intent.open.file);
  }
 +EXPORT_SYMBOL_GPL(release_open_intent);
  
+ /*
+  * Call d_revalidate and handle filesystems that request rcu-walk
+  * to be dropped. This may be called and return in rcu-walk mode,
+  * regardless of success or error. If -ECHILD is returned, the caller
+  * must return -ECHILD back up the path walk stack so path walk may
+  * be restarted in ref-walk mode.
+  */
+ static int d_revalidate(struct dentry *dentry, struct nameidata *nd)
+ {
+       int status;
+       status = dentry->d_op->d_revalidate(dentry, nd);
+       if (status == -ECHILD) {
+               if (nameidata_dentry_drop_rcu(nd, dentry))
+                       return status;
+               status = dentry->d_op->d_revalidate(dentry, nd);
+       }
+       return status;
+ }
  static inline struct dentry *
  do_revalidate(struct dentry *dentry, struct nameidata *nd)
  {
diff --cc fs/nfs/inode.c
Simple merge
Simple merge
@@@ -26,12 -26,9 +26,9 @@@ static struct kmem_cache *nfs_page_cach
  static inline struct nfs_page *
  nfs_page_alloc(void)
  {
-       struct nfs_page *p;
-       p = kmem_cache_alloc(nfs_page_cachep, GFP_NOIO);
-       if (p) {
-               memset(p, 0, sizeof(*p));
 -      struct nfs_page *p = kmem_cache_zalloc(nfs_page_cachep, GFP_KERNEL);
++      struct nfs_page *p = kmem_cache_zalloc(nfs_page_cachep, GFP_NOIO);
+       if (p)
                INIT_LIST_HEAD(&p->wb_list);
-       }
        return p;
  }
  
index 590e999,0000000..9323738
mode 100644,000000..100644
--- /dev/null
@@@ -1,4107 -1,0 +1,4107 @@@
 +/*
 + * Novell NCP Redirector for Linux
 + * Author: James Turner
 + *
 + * This file contains functions used to control access to the Linux file
 + * system.
 + *
 + * Copyright (C) 2005 Novell, Inc.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + */
 +
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/fs.h>
 +#include <linux/dcache.h>
 +#include <linux/mount.h>
 +#include <linux/pagemap.h>
 +#include <linux/string.h>
 +#include <linux/smp_lock.h>
 +#include <linux/slab.h>
 +#include <linux/unistd.h>
 +#include <asm/statfs.h>
 +#include <asm/uaccess.h>
 +#include <linux/ctype.h>
 +#include <linux/statfs.h>
 +#include <linux/pagevec.h>
 +#include <linux/writeback.h>
 +#include <linux/backing-dev.h>
 +#include <linux/mm.h>
 +#include <linux/file.h>
 +
 +/*===[ Include files specific to this module ]============================*/
 +#include "vfs.h"
 +
 +struct inode_data {
 +      void *Scope;
 +      unsigned long Flags;
 +      struct list_head IList;
 +      struct inode *Inode;
 +      unsigned long cntDC;
 +      struct list_head DirCache;
 +      struct mutex DirCacheLock;
 +      void *FileHandle;
 +      int CacheFlag;
 +      char Name[1];           /* Needs to be last entry */
 +};
 +
 +#define FILE_UPDATE_TIMEOUT   2
 +
 +/*===[ Function prototypes ]=============================================*/
 +
 +static unsigned long novfs_internal_hash(struct qstr *name);
 +static int novfs_d_add(struct dentry *p, struct dentry *d, struct inode *i, int add);
 +
 +static int novfs_get_sb(struct file_system_type *Fstype, int Flags, const char *Dev_name, void *Data, struct vfsmount *Mnt);
 +
 +static void novfs_kill_sb(struct super_block *SB);
 +
 +/*
 + * Declared dentry_operations
 + */
 +int novfs_d_revalidate(struct dentry *, struct nameidata *);
- int novfs_d_hash(struct dentry *, struct qstr *);
- int novfs_d_compare(struct dentry *, struct qstr *, struct qstr *);
++int novfs_d_hash(const struct dentry *, const struct inode *, struct qstr *);
++int novfs_d_compare(const struct dentry *, const struct inode *,
++                  const struct dentry *, const struct inode *,
++                  unsigned int, const char *, const struct qstr *);
 +int novfs_d_delete(struct dentry *dentry);
 +void novfs_d_release(struct dentry *dentry);
 +void novfs_d_iput(struct dentry *dentry, struct inode *inode);
 +
 +/*
 + * Declared directory operations
 + */
 +int novfs_dir_open(struct inode *inode, struct file *file);
 +int novfs_dir_release(struct inode *inode, struct file *file);
 +loff_t novfs_dir_lseek(struct file *file, loff_t offset, int origin);
 +ssize_t novfs_dir_read(struct file *file, char *buf, size_t len, loff_t * off);
 +void addtodentry(struct dentry *Parent, unsigned char *List, int Level);
 +int novfs_filldir(void *data, const char *name, int namelen, loff_t off, ino_t ino, unsigned ftype);
 +int novfs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir);
 +int novfs_dir_fsync(struct file *file, int datasync);
 +
 +/*
 + * Declared address space operations
 + */
 +int novfs_a_writepage(struct page *page, struct writeback_control *wbc);
 +int novfs_a_writepages(struct address_space *mapping, struct writeback_control *wbc);
 +int novfs_a_write_begin(struct file *file, struct address_space *mapping,
 +                      loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata);
 +int novfs_a_write_end(struct file *file, struct address_space *mapping,
 +                    loff_t pos, unsigned len, unsigned copied, struct page *pagep, void *fsdata);
 +int novfs_a_readpage(struct file *file, struct page *page);
 +int novfs_a_readpages(struct file *file, struct address_space *mapping, struct list_head *page_lst, unsigned nr_pages);
 +ssize_t novfs_a_direct_IO(int rw, struct kiocb *kiocb, const struct iovec *iov, loff_t offset, unsigned long nr_segs);
 +
 +/*
 + * Declared file_operations
 + */
 +ssize_t novfs_f_read(struct file *, char *, size_t, loff_t *);
 +ssize_t novfs_f_write(struct file *, const char *, size_t, loff_t *);
 +int novfs_f_readdir(struct file *, void *, filldir_t);
 +int novfs_f_mmap(struct file *file, struct vm_area_struct *vma);
 +int novfs_f_open(struct inode *, struct file *);
 +int novfs_f_flush(struct file *, fl_owner_t);
 +int novfs_f_release(struct inode *, struct file *);
 +int novfs_f_fsync(struct file *, int datasync);
 +int novfs_f_lock(struct file *, int, struct file_lock *);
 +
 +/*
 + * Declared inode_operations
 + */
 +int novfs_i_create(struct inode *, struct dentry *, int, struct nameidata *);
 +struct dentry *novfs_i_lookup(struct inode *, struct dentry *, struct nameidata *);
 +int novfs_i_mkdir(struct inode *, struct dentry *, int);
 +int novfs_i_unlink(struct inode *dir, struct dentry *dentry);
 +int novfs_i_rmdir(struct inode *, struct dentry *);
 +int novfs_i_mknod(struct inode *, struct dentry *, int, dev_t);
 +int novfs_i_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
 +int novfs_i_setattr(struct dentry *, struct iattr *);
 +int novfs_i_getattr(struct vfsmount *mnt, struct dentry *, struct kstat *);
 +int novfs_i_revalidate(struct dentry *dentry);
 +
 +/*
 + * Extended attributes operations
 + */
 +
 +ssize_t novfs_i_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
 +int novfs_i_setxattr(struct dentry *dentry, const char *name, const void *value, size_t value_size, int flags);
 +ssize_t novfs_i_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
 +
 +void update_inode(struct inode *Inode, struct novfs_entry_info *Info);
 +
 +/*
 + * Declared super_operations
 + */
 +void novfs_read_inode(struct inode *inode);
 +void novfs_write_inode(struct inode *inode);
 +int novfs_notify_change(struct dentry *dentry, struct iattr *attr);
 +void novfs_evict_inode(struct inode *inode);
 +int novfs_show_options(struct seq_file *s, struct vfsmount *m);
 +
 +int novfs_statfs(struct dentry *de, struct kstatfs *buf);
 +
 +/*
 + * Declared control interface functions
 + */
 +ssize_t novfs_control_Read(struct file *file, char *buf, size_t nbytes, loff_t * ppos);
 +
 +ssize_t novfs_control_write(struct file *file, const char *buf, size_t nbytes, loff_t * ppos);
 +
 +int __init init_novfs(void);
 +void __exit exit_novfs(void);
 +
 +int novfs_lock_inode_cache(struct inode *i);
 +void novfs_unlock_inode_cache(struct inode *i);
 +int novfs_enumerate_inode_cache(struct inode *i, struct list_head **iteration, ino_t * ino, struct novfs_entry_info *info);
 +int novfs_get_entry(struct inode *i, struct qstr *name, ino_t * ino, struct novfs_entry_info *info);
 +int novfs_get_entry_by_pos(struct inode *i, loff_t pos, ino_t * ino, struct novfs_entry_info *info);
 +int novfs_get_entry_time(struct inode *i, struct qstr *name, ino_t * ino, struct novfs_entry_info *info, u64 * EntryTime);
 +int novfs_get_remove_entry(struct inode *i, ino_t * ino, struct novfs_entry_info *info);
 +void novfs_invalidate_inode_cache(struct inode *i);
 +struct novfs_dir_cache *novfs_lookup_inode_cache(struct inode *i, struct qstr *name, ino_t ino);
 +int novfs_lookup_validate(struct inode *i, struct qstr *name, ino_t ino);
 +int novfs_add_inode_entry(struct inode *i, struct qstr *name, ino_t ino, struct novfs_entry_info *info);
 +int novfs_update_entry(struct inode *i, struct qstr *name, ino_t ino, struct novfs_entry_info *info);
 +void novfs_remove_inode_entry(struct inode *i, struct qstr *name, ino_t ino);
 +void novfs_free_invalid_entries(struct inode *i);
 +void novfs_free_inode_cache(struct inode *i);
 +
 +/*===[ Global variables ]=================================================*/
 +struct dentry_operations novfs_dentry_operations = {
 +      .d_revalidate = novfs_d_revalidate,
 +      .d_hash = novfs_d_hash,
 +      .d_compare = novfs_d_compare,
 +      //.d_delete      = novfs_d_delete,
 +      .d_release = novfs_d_release,
 +      .d_iput = novfs_d_iput,
 +};
 +
 +struct file_operations novfs_dir_operations = {
 +      .owner = THIS_MODULE,
 +      .open = novfs_dir_open,
 +      .release = novfs_dir_release,
 +      .llseek = novfs_dir_lseek,
 +      .read = novfs_dir_read,
 +      .readdir = novfs_dir_readdir,
 +      .fsync = novfs_dir_fsync,
 +};
 +
 +static struct file_operations novfs_file_operations = {
 +      .owner = THIS_MODULE,
 +      .read = novfs_f_read,
 +      .write = novfs_f_write,
 +      .readdir = novfs_f_readdir,
 +      .mmap = novfs_f_mmap,
 +      .open = novfs_f_open,
 +      .flush = novfs_f_flush,
 +      .release = novfs_f_release,
 +      .fsync = novfs_f_fsync,
 +      .llseek = generic_file_llseek,
 +      .lock = novfs_f_lock,
 +};
 +
 +static struct address_space_operations novfs_nocache_aops = {
 +      .readpage = novfs_a_readpage,
 +};
 +
 +struct backing_dev_info novfs_backing_dev_info = {
 +      .ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE,
 +      .state = 0,
 +      .capabilities = BDI_CAP_NO_WRITEBACK | BDI_CAP_MAP_COPY,
 +      .unplug_io_fn = default_unplug_io_fn,
 +};
 +
 +static struct address_space_operations novfs_aops = {
 +      .readpage = novfs_a_readpage,
 +      .readpages = novfs_a_readpages,
 +      .writepage = novfs_a_writepage,
 +      .writepages = novfs_a_writepages,
 +      .write_begin = novfs_a_write_begin,
 +      .write_end = novfs_a_write_end,
 +      .set_page_dirty = __set_page_dirty_nobuffers,
 +      .direct_IO = novfs_a_direct_IO,
 +};
 +
 +static struct inode_operations novfs_inode_operations = {
 +      .create = novfs_i_create,
 +      .lookup = novfs_i_lookup,
 +      .unlink = novfs_i_unlink,
 +      .mkdir = novfs_i_mkdir,
 +      .rmdir = novfs_i_rmdir,
 +      .mknod = novfs_i_mknod,
 +      .rename = novfs_i_rename,
 +      .setattr = novfs_i_setattr,
 +      .getattr = novfs_i_getattr,
 +      .getxattr = novfs_i_getxattr,
 +      .setxattr = novfs_i_setxattr,
 +      .listxattr = novfs_i_listxattr,
 +};
 +
 +static struct inode_operations novfs_file_inode_operations = {
 +      .setattr = novfs_i_setattr,
 +      .getattr = novfs_i_getattr,
 +      .getxattr = novfs_i_getxattr,
 +      .setxattr = novfs_i_setxattr,
 +      .listxattr = novfs_i_listxattr,
 +};
 +
 +static struct super_operations novfs_ops = {
 +      .statfs = novfs_statfs,
 +      .evict_inode = novfs_evict_inode,
 +      .drop_inode = generic_delete_inode,
 +      .show_options = novfs_show_options,
 +
 +};
 +
 +/* Not currently used
 +static struct file_operations novfs_Control_operations = {
 +   .read    = novfs_Control_read,
 +   .write   = novfs_Control_write,
 +};
 +*/
 +
 +static atomic_t novfs_Inode_Number = ATOMIC_INIT(0);
 +
 +struct dentry *novfs_root = NULL;
 +char *novfs_current_mnt = NULL;
 +
 +DEFINE_MUTEX(InodeList_lock);
 +
 +LIST_HEAD(InodeList);
 +
 +DEFINE_MUTEX(TimeDir_Lock);
 +uint64_t lastTime;
 +char lastDir[PATH_MAX];
 +
 +uint64_t inHAXTime;
 +int inHAX;
 +
 +unsigned long InodeCount = 0, DCCount = 0;
 +unsigned long novfs_update_timeout = FILE_UPDATE_TIMEOUT;
 +int novfs_page_cache = 0;
 +
 +struct file_private {
 +      int listedall;
 +      void *enumHandle;
 +};
 +
 +static void PRINT_DENTRY(const char *s, struct dentry *d)
 +{
 +      __DbgPrint("%s: 0x%p\n", s, d);
 +      __DbgPrint("   d_count:      0x%x\n", d->d_count);
 +      __DbgPrint("   d_lock:       0x%x\n", d->d_lock);
 +      __DbgPrint("   d_inode:      0x%x\n", d->d_inode);
 +      __DbgPrint("   d_lru:        0x%p\n"
 +                 "      next:      0x%p\n" "      prev:      0x%p\n", &d->d_lru, d->d_lru.next, d->d_lru.prev);
 +      __DbgPrint("   d_child:      0x%p\n" "      next:      0x%p\n"
 +                 "      prev:      0x%p\n", &d->d_u.d_child, d->d_u.d_child.next, d->d_u.d_child.prev);
 +      __DbgPrint("   d_subdirs:    0x%p\n" "      next:      0x%p\n"
 +                 "      prev:      0x%p\n", &d->d_subdirs, d->d_subdirs.next, d->d_subdirs.prev);
 +      __DbgPrint("   d_alias:      0x%p\n" "      next:      0x%p\n"
 +                 "      prev:      0x%p\n", &d->d_alias, d->d_alias.next, d->d_alias.prev);
 +      __DbgPrint("   d_time:       0x%x\n", d->d_time);
 +      __DbgPrint("   d_op:         0x%p\n", d->d_op);
 +      __DbgPrint("   d_sb:         0x%p\n", d->d_sb);
 +      __DbgPrint("   d_flags:      0x%x\n", d->d_flags);
-       __DbgPrint("   d_mounted:    0x%x\n", d->d_mounted);
 +      __DbgPrint("   d_fsdata:     0x%p\n", d->d_fsdata);
 +/*   DbgPrint("   d_cookie:     0x%x\n", d->d_cookie); */
 +      __DbgPrint("   d_parent:     0x%p\n", d->d_parent);
 +      __DbgPrint("   d_name:       0x%p %.*s\n", &d->d_name, d->d_name.len, d->d_name.name);
 +      __DbgPrint("      name:      0x%p\n" "      len:       %d\n"
 +                 "      hash:      0x%x\n", d->d_name.name, d->d_name.len, d->d_name.hash);
 +      __DbgPrint("   d_hash:       0x%x\n" "      next:      0x%x\n"
 +                 "      pprev:     0x%x\n", d->d_hash, d->d_hash.next, d->d_hash.pprev);
 +}
 +
 +/*++======================================================================*/
 +int novfs_remove_from_root(char *RemoveName)
 +{
 +      struct qstr name;
 +      struct dentry *dentry;
 +      struct inode *dir;
 +
 +      DbgPrint("%s", RemoveName);
 +      name.len = strlen(RemoveName);
 +      name.name = RemoveName;
-       novfs_d_hash(novfs_root, &name);
++      novfs_d_hash(novfs_root, novfs_root->d_inode, &name);
 +
 +      dentry = d_lookup(novfs_root, &name);
 +      if (dentry) {
 +              if (dentry->d_inode && dentry->d_inode->i_private) {
 +                      struct inode_data *n_inode = dentry->d_inode->i_private;
 +                      n_inode->Scope = NULL;
 +              }
 +              dput(dentry);
 +      }
 +
 +      dir = novfs_root->d_inode;
 +
 +      novfs_lock_inode_cache(dir);
 +      novfs_remove_inode_entry(dir, &name, 0);
 +      novfs_unlock_inode_cache(dir);
 +
 +      return (0);
 +}
 +
 +/*++======================================================================*/
 +int novfs_add_to_root(char *AddName)
 +{
 +      struct qstr name;
 +      struct inode *dir;
 +      struct novfs_entry_info info;
 +      ino_t ino;
 +
 +      DbgPrint("%s", AddName);
 +      name.len = strlen(AddName);
 +      name.name = AddName;
-       novfs_d_hash(novfs_root, &name);
++      novfs_d_hash(novfs_root, novfs_root->d_inode, &name);
 +
 +      dir = novfs_root->d_inode;
 +
 +      novfs_lock_inode_cache(dir);
 +
 +      ino = 0;
 +
 +      if (!novfs_lookup_inode_cache(dir, &name, 0)) {
 +              info.mode = S_IFDIR | 0700;
 +              info.size = 0;
 +              info.atime = info.ctime = info.mtime = CURRENT_TIME;
 +
 +              ino = (ino_t) atomic_inc_return(&novfs_Inode_Number);
 +              novfs_add_inode_entry(dir, &name, ino, &info);
 +      }
 +
 +      novfs_unlock_inode_cache(dir);
 +
 +      return (0);
 +}
 +
 +/*++======================================================================*/
 +int novfs_Add_to_Root2(char *AddName)
 +{
 +      struct dentry *entry;
 +      struct qstr name;
 +      struct inode *inode;
 +      void *scope;
 +
 +      DbgPrint("%s", AddName);
 +      name.len = strlen(AddName);
 +      name.name = AddName;
 +
-       novfs_d_hash(novfs_root, &name);
++      novfs_d_hash(novfs_root, novfs_root->d_inode, &name);
 +
 +      entry = d_lookup(novfs_root, &name);
 +      DbgPrint("novfs_d_lookup 0x%p", entry);
 +      if (NULL == entry) {
 +              scope = novfs_scope_lookup();
 +
 +              entry = d_alloc(novfs_root, &name);
 +              DbgPrint("d_alloc 0x%p", entry);
 +              if (entry) {
 +                      entry->d_op = &novfs_dentry_operations;
 +                      entry->d_time = jiffies + (novfs_update_timeout * HZ);
 +                      /*
 +                       * done in novfs_d_add now... entry->d_fsdata = (void *)novfs_internal_hash( &name );
 +                       */
 +                      inode = novfs_get_inode(novfs_root->d_sb, S_IFDIR | 0700, 0, novfs_scope_get_uid(scope), 0, &name);
 +                      DbgPrint("Inode=0x%p", inode);
 +                      if (inode) {
 +                              inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
 +                              if (!novfs_d_add(novfs_root, entry, inode, 1)) {
 +                                      if (inode->i_private) {
 +                                              struct inode_data *n_inode = inode->i_private;
 +                                              n_inode->Flags = USER_INODE;
 +                                      }
 +                                      PRINT_DENTRY("After novfs_d_add", entry);
 +                              } else {
 +                                      dput(entry);
 +                                      iput(inode);
 +                              }
 +                      }
 +              }
 +      } else {
 +              dput(entry);
 +              PRINT_DENTRY("novfs_Add_to_Root: After dput Dentry", entry);
 +      }
 +      return (0);
 +}
 +
 +char *novfs_dget_path(struct dentry *Dentry, char *Buf, unsigned int Buflen)
 +{
 +      char *retval = &Buf[Buflen];
 +      struct dentry *p = Dentry;
 +
 +      *(--retval) = '\0';
 +      Buflen--;
 +
 +      if (!IS_ROOT(p) && !IS_ROOT(p->d_parent)) {
 +              while (Buflen && !IS_ROOT(p) && !IS_ROOT(p->d_parent)) {
 +                      if (Buflen > p->d_name.len) {
 +                              retval -= p->d_name.len;
 +                              Buflen -= p->d_name.len;
 +                              memcpy(retval, p->d_name.name, p->d_name.len);
 +                              *(--retval) = '\\';
 +                              Buflen--;
 +                              p = p->d_parent;
 +                      } else {
 +                              retval = NULL;
 +                              break;
 +                      }
 +              }
 +      } else {
 +              *(--retval) = '\\';
 +      }
 +
 +      if (retval)
 +              DbgPrint("%s", retval);
 +      return (retval);
 +}
 +
 +int verify_dentry(struct dentry *dentry, int Flags)
 +{
 +      int retVal = -ENOENT;
 +      struct inode *dir;
 +      struct novfs_entry_info *info = NULL;
 +      struct inode_data *id;
 +      struct novfs_schandle session;
 +      char *path, *list = NULL, *cp;
 +      ino_t ino = 0;
 +      struct qstr name;
 +      int iLock = 0;
 +      struct dentry *parent = NULL;
 +      u64 ctime;
 +      struct inode *inode;
 +
 +      if (IS_ROOT(dentry)) {
 +              DbgPrint("Root entry");
 +              return (0);
 +      }
 +
 +      if (dentry && dentry->d_parent && (dir = dentry->d_parent->d_inode) && (id = dir->i_private)) {
 +              parent = dget_parent(dentry);
 +
 +              info = kmalloc(sizeof(struct novfs_entry_info) + PATH_LENGTH_BUFFER, GFP_KERNEL);
 +
 +              if (info) {
 +                      if (novfs_lock_inode_cache(dir)) {
 +                              name.len = dentry->d_name.len;
 +                              name.name = dentry->d_name.name;
 +                              name.hash = novfs_internal_hash(&name);
 +                              if (!novfs_get_entry_time(dir, &name, &ino, info, &ctime)) {
 +                                      inode = dentry->d_inode;
 +                                      if (inode && inode->i_private &&
 +                                          ((inode->i_size != info->size) || (inode->i_mtime.tv_sec != info->mtime.tv_sec)
 +                                           || (inode->i_mtime.tv_nsec != info->mtime.tv_nsec))) {
 +                                              /*
 +                                               * Values don't match so update.
 +                                               */
 +                                              struct inode_data *n_inode = inode->i_private;
 +                                              n_inode->Flags |= UPDATE_INODE;
 +                                      }
 +
 +                                      ctime = get_jiffies_64() - ctime;
 +                                      if (Flags || ctime < (u64) (novfs_update_timeout * HZ)) {
 +                                              retVal = 0;
 +                                              novfs_unlock_inode_cache(dir);
 +                                              dput(parent);
 +                                              kfree(info);
 +                                              return (0);
 +                                      }
 +                              }
 +                              novfs_unlock_inode_cache(dir);
 +                      }
 +
 +                      if (IS_ROOT(dentry->d_parent)) {
 +                              session = novfs_scope_get_sessionId(novfs_get_scope_from_name(&dentry->d_name));
 +                      } else
 +                              session = novfs_scope_get_sessionId(id->Scope);
 +
 +                      if (!SC_PRESENT(session)) {
 +                              id->Scope = novfs_get_scope(dentry);
 +                              session = novfs_scope_get_sessionId(id->Scope);
 +                      }
 +
 +                      ino = 0;
 +                      retVal = 0;
 +
 +                      if (IS_ROOT(dentry->d_parent)) {
 +                              DbgPrint("parent is Root directory");
 +                              list = novfs_get_scopeusers();
 +
 +                              iLock = novfs_lock_inode_cache(dir);
 +                              novfs_invalidate_inode_cache(dir);
 +
 +                              if (list) {
 +                                      cp = list;
 +                                      while (*cp) {
 +                                              name.name = cp;
 +                                              name.len = strlen(cp);
 +                                              name.hash = novfs_internal_hash(&name);
 +                                              cp += (name.len + 1);
 +                                              ino = 0;
 +                                              if (novfs_get_entry(dir, &name, &ino, info)) {
 +                                                      info->mode = S_IFDIR | 0700;
 +                                                      info->size = 0;
 +                                                      info->atime = info->ctime = info->mtime = CURRENT_TIME;
 +                                                      ino = (ino_t) atomic_inc_return(&novfs_Inode_Number);
 +                                                      novfs_add_inode_entry(dir, &name, ino, info);
 +                                              }
 +                                      }
 +                              }
 +                              novfs_free_invalid_entries(dir);
 +                      } else {
 +
 +                              path = novfs_dget_path(dentry, info->name, PATH_LENGTH_BUFFER);
 +                              if (path) {
 +                                      if (dentry->d_name.len <= NW_MAX_PATH_LENGTH) {
 +                                              name.hash = novfs_internal_hash(&dentry->d_name);
 +                                              name.len = dentry->d_name.len;
 +                                              name.name = dentry->d_name.name;
 +
 +                                              retVal = novfs_get_file_info(path, info, session);
 +                                              if (0 == retVal) {
 +                                                      dentry->d_time = jiffies + (novfs_update_timeout * HZ);
 +                                                      iLock = novfs_lock_inode_cache(dir);
 +                                                      if (novfs_update_entry(dir, &name, 0, info)) {
 +                                                              if (dentry->d_inode) {
 +                                                                      ino = dentry->d_inode->i_ino;
 +                                                              } else {
 +                                                                      ino = (ino_t) atomic_inc_return(&novfs_Inode_Number);
 +                                                              }
 +                                                              novfs_add_inode_entry(dir, &name, ino, info);
 +                                                      }
 +                                                      if (dentry->d_inode) {
 +                                                              update_inode(dentry->d_inode, info);
 +                                                              id->Flags &= ~UPDATE_INODE;
 +
 +                                                              dentry->d_inode->i_flags &= ~S_DEAD;
 +                                                              if (dentry->d_inode->i_private) {
 +                                                                      ((struct inode_data *)dentry->d_inode->i_private)->Scope =
 +                                                                          id->Scope;
 +                                                              }
 +                                                      }
 +                                              } else if (-EINTR != retVal) {
 +                                                      retVal = 0;
 +                                                      iLock = novfs_lock_inode_cache(dir);
 +                                                      novfs_remove_inode_entry(dir, &name, 0);
 +                                                      if (dentry->d_inode && !(dentry->d_inode->i_flags & S_DEAD)) {
 +                                                              dentry->d_inode->i_flags |= S_DEAD;
 +                                                              dentry->d_inode->i_size = 0;
 +                                                              dentry->d_inode->i_atime.tv_sec =
 +                                                                  dentry->d_inode->i_atime.tv_nsec =
 +                                                                  dentry->d_inode->i_ctime.tv_sec =
 +                                                                  dentry->d_inode->i_ctime.tv_nsec =
 +                                                                  dentry->d_inode->i_mtime.tv_sec =
 +                                                                  dentry->d_inode->i_mtime.tv_nsec = 0;
 +                                                              dentry->d_inode->i_blocks = 0;
 +                                                              d_delete(dentry);       /* Remove from cache */
 +                                                      }
 +                                              }
 +                                      } else {
 +                                              retVal = -ENAMETOOLONG;
 +                                      }
 +                              }
 +                      }
 +              } else {
 +                      retVal = -ENOMEM;
 +              }
 +              if (iLock) {
 +                      novfs_unlock_inode_cache(dir);
 +              }
 +              dput(parent);
 +      }
 +
 +      if (list)
 +              kfree(list);
 +      if (info)
 +              kfree(info);
 +
 +      DbgPrint("return=0x%x", retVal);
 +
 +      return (retVal);
 +}
 +
 +static int novfs_d_add(struct dentry *Parent, struct dentry *d, struct inode *i, int a)
 +{
 +      void *scope;
 +      struct inode_data *id = NULL;
 +
 +      char *path, *buf;
 +
 +      buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +      if (buf) {
 +              path = novfs_dget_path(d, buf, PATH_LENGTH_BUFFER);
 +              if (path) {
 +                      DbgPrint("inode=0x%p ino=%d path %s", i, i->i_ino, path);
 +              }
 +              kfree(buf);
 +      }
 +
 +      if (Parent && Parent->d_inode && Parent->d_inode->i_private) {
 +              id = (struct inode_data *)Parent->d_inode->i_private;
 +      }
 +
 +      if (id && id->Scope) {
 +              scope = id->Scope;
 +      } else {
 +              scope = novfs_get_scope(d);
 +      }
 +
 +      ((struct inode_data *)i->i_private)->Scope = scope;
 +
 +      d->d_time = jiffies + (novfs_update_timeout * HZ);
 +      if (a) {
 +              d_add(d, i);
 +      } else {
 +              d_instantiate(d, i);
 +      }
 +
 +      return (0);
 +}
 +
 +int novfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
 +{
 +      int retCode = 0;
 +      struct inode *dir;
 +      struct inode_data *id;
 +      struct qstr name;
 +
 +      __DbgPrint("%s: 0x%p %.*s\n"
 +                 "   d_count: %d\n"
 +                 "   d_inode: 0x%p\n", __func__,
 +                 dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_count, dentry->d_inode);
 +
 +      if (IS_ROOT(dentry)) {
 +              retCode = 1;
 +      } else {
 +              if (dentry->d_inode && dentry->d_parent && (dir = dentry->d_parent->d_inode) && (id = dir->i_private)) {
 +                      /*
 +                       * Check timer to see if in valid time limit
 +                       */
 +                      if (jiffies > dentry->d_time) {
 +                              /*
 +                               * Revalidate entry
 +                               */
 +                              name.len = dentry->d_name.len;
 +                              name.name = dentry->d_name.name;
 +                              name.hash = novfs_internal_hash(&dentry->d_name);
 +                              dentry->d_time = 0;
 +
 +                              if (0 == verify_dentry(dentry, 0)) {
 +                                      if (novfs_lock_inode_cache(dir)) {
 +                                              if (novfs_lookup_inode_cache(dir, &name, 0)) {
 +                                                      dentry->d_time = jiffies + (novfs_update_timeout * HZ);
 +                                                      retCode = 1;
 +                                              }
 +                                              novfs_unlock_inode_cache(dir);
 +                                      }
 +                              }
 +                      } else {
 +                              retCode = 1;
 +                      }
 +              }
 +      }
 +
 +      if ((0 == retCode) && dentry->d_inode) {
 +              /*
 +               * Entry has become invalid
 +               */
 +/*      dput(dentry);
 +*/
 +      }
 +
 +      DbgPrint("return 0x%x %.*s", retCode, dentry->d_name.len, dentry->d_name.name);
 +
 +      return (retCode);
 +}
 +
 +static unsigned long novfs_internal_hash(struct qstr *name)
 +{
 +      unsigned long hash = 0;
 +      unsigned int len = name->len;
 +      unsigned char *c = (unsigned char *)name->name;
 +
 +      while (len--) {
 +              /*
 +               * Lower case values for the hash.
 +               */
 +              hash = partial_name_hash(tolower(*c++), hash);
 +      }
 +
 +      return (hash);
 +}
 +
- int novfs_d_hash(struct dentry *dentry, struct qstr *name)
++int novfs_d_hash(const struct dentry *dentry, const struct inode *inode,
++               struct qstr *name)
 +{
 +      DbgPrint("%.*s", name->len, name->name);
 +
 +      name->hash = novfs_internal_hash(name);
 +
 +      return (0);
 +}
 +
- int novfs_d_strcmp(struct qstr *s1, struct qstr *s2)
++static int novfs_d_strcmp(const char *str1, unsigned int len,
++                        const struct qstr *s2)
 +{
 +      int retCode = 1;
-       unsigned char *str1, *str2;
-       unsigned int len;
++      const unsigned char *str2 = s2->name;
 +
-       DbgPrint("s1=%.*s s2=%.*s", s1->len, s1->name, s2->len, s2->name);
++      DbgPrint("s1=%.*s s2=%.*s", len, str1, s2->len, s2->name);
 +
-       if (s1->len && (s1->len == s2->len) && (s1->hash == s2->hash)) {
-               len = s1->len;
-               str1 = (unsigned char *)s1->name;
-               str2 = (unsigned char *)s2->name;
++      if (len && (len == s2->len)) {
 +              for (retCode = 0; len--; str1++, str2++) {
 +                      if (*str1 != *str2) {
 +                              if (tolower(*str1) != tolower(*str2)) {
 +                                      retCode = 1;
 +                                      break;
 +                              }
 +                      }
 +              }
 +      }
 +
 +      DbgPrint("retCode=0x%x", retCode);
 +      return (retCode);
 +}
 +
- int novfs_d_compare(struct dentry *parent, struct qstr *s1, struct qstr *s2)
++int novfs_d_compare(const struct dentry *parent,
++                  const struct inode *parent_inode,
++                  const struct dentry *dentry, const struct inode *inode,
++                  unsigned int len, const char *s1, const struct qstr *s2)
 +{
 +      int retCode;
 +
-       retCode = novfs_d_strcmp(s1, s2);
++      retCode = novfs_d_strcmp(s1, len, s2);
 +
 +      DbgPrint("retCode=0x%x", retCode);
 +      return (retCode);
 +}
 +
 +int novfs_d_delete(struct dentry *dentry)
 +{
 +      int retVal = 0;
 +
 +      DbgPrint("0x%p %.*s; d_count: %d; d_inode: 0x%p",
 +               dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_count, dentry->d_inode);
 +
 +      if (dentry->d_inode && (dentry->d_inode->i_flags & S_DEAD)) {
 +              retVal = 1;
 +      }
 +
 +      dentry->d_time = 0;
 +
 +      return (retVal);
 +}
 +
 +void novfs_d_release(struct dentry *dentry)
 +{
 +      DbgPrint("0x%p %.*s", dentry, dentry->d_name.len, dentry->d_name.name);
 +}
 +
 +void novfs_d_iput(struct dentry *dentry, struct inode *inode)
 +{
 +      DbgPrint("Inode=0x%p Ino=%d Dentry=0x%p i_state=%d Name=%.*s",
 +               inode, inode->i_ino, dentry, inode->i_state, dentry->d_name.len, dentry->d_name.name);
 +
 +      iput(inode);
 +
 +}
 +
 +int novfs_dir_open(struct inode *dir, struct file *file)
 +{
 +      char *path, *buf;
 +      struct file_private *file_private = NULL;
 +
 +      DbgPrint("Inode 0x%p %d Name %.*s", dir, dir->i_ino, file->f_dentry->d_name.len, file->f_dentry->d_name.name);
 +
 +      buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +      if (buf) {
 +              path = novfs_dget_path(file->f_dentry, buf, PATH_LENGTH_BUFFER);
 +              if (path) {
 +                      DbgPrint("path %s", path);
 +              }
 +              kfree(buf);
 +      }
 +
 +      file_private = kmalloc(sizeof(struct file_private), GFP_KERNEL);
 +      file_private->listedall = 0;
 +      file_private->enumHandle = NULL;
 +
 +      file->private_data = file_private;
 +
 +      return (0);
 +}
 +
 +int novfs_dir_release(struct inode *dir, struct file *file)
 +{
 +      struct file_private *file_private = file->private_data;
 +      struct inode *inode = file->f_dentry->d_inode;
 +      struct novfs_schandle sessionId;
 +
 +      DbgPrint("Inode 0x%p %d Name %.*s", dir, dir->i_ino, file->f_dentry->d_name.len, file->f_dentry->d_name.name);
 +
 +      if (file_private) {
 +              if (file_private->enumHandle && (file_private->enumHandle != ((void *)-1))) {
 +                      sessionId = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +                      if (SC_PRESENT(sessionId) == 0) {
 +                              ((struct inode_data *)inode->i_private)->Scope = novfs_get_scope(file->f_dentry);
 +                              sessionId = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +                      }
 +                      novfs_end_directory_enumerate(file_private->enumHandle, sessionId);
 +              }
 +              kfree(file_private);
 +              file->private_data = NULL;
 +      }
 +
 +      return (0);
 +}
 +
 +loff_t novfs_dir_lseek(struct file * file, loff_t offset, int origin)
 +{
 +      struct file_private *file_private = NULL;
 +
 +      DbgPrint("offset %lld %d Name %.*s", offset, origin, file->f_dentry->d_name.len, file->f_dentry->d_name.name);
 +      //printk("<1> seekdir file = %.*s offset = %i\n", file->f_dentry->d_name.len, file->f_dentry->d_name.name, (int)offset);
 +
 +      if (0 != offset) {
 +              return -ESPIPE;
 +      }
 +
 +      file->f_pos = 0;
 +
 +      file_private = (struct file_private *)file->private_data;
 +      file_private->listedall = 0;
 +      if (file_private->enumHandle && (file_private->enumHandle != ((void *)-1))) {
 +              struct novfs_schandle sessionId;
 +              struct inode *inode = file->f_dentry->d_inode;
 +              sessionId = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +              if (SC_PRESENT(sessionId) == 0) {
 +                      ((struct inode_data *)inode->i_private)->Scope = novfs_get_scope(file->f_dentry);
 +                      sessionId = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +              }
 +              novfs_end_directory_enumerate(file_private->enumHandle, sessionId);
 +      }
 +      file_private->enumHandle = NULL;
 +
 +      return 0;
 +      //return(default_llseek(file, offset, origin));
 +}
 +
 +ssize_t novfs_dir_read(struct file * file, char *buf, size_t len, loff_t * off)
 +{
 +/*
 +   int rlen = 0;
 +
 +   DbgPrint("dentry path %.*s buf=0x%p len=%d off=%lld", file->f_dentry->d_name.len, file->f_dentry->d_name.name, buf, len, *off);
 +
 +   if (0 == *off)
 +   {
 +      rlen = 8;
 +      rlen -= copy_to_user(buf, "Testing\n", 8);
 +      *off += rlen;
 +   }
 +   return(rlen);
 +*/
 +      DbgPrint("%lld %d Name %.*s", *off, len, file->f_dentry->d_name.len, file->f_dentry->d_name.name);
 +      return (generic_read_dir(file, buf, len, off));
 +}
 +
 +static void novfs_Dump_Info(struct novfs_entry_info *info)
 +{
 +      char atime_buf[32], mtime_buf[32], ctime_buf[32];
 +      char namebuf[512];
 +      int len = 0;
 +
 +      if (info == NULL) {
 +              DbgPrint("Dump_Info info == NULL");
 +              return;
 +      }
 +
 +      if (info->namelength >= 512) {
 +              len = 511;
 +      } else {
 +              len = info->namelength;
 +      }
 +
 +      memcpy(namebuf, info->name, len);
 +      namebuf[len] = '\0';
 +
 +      ctime_r(&info->atime.tv_sec, atime_buf);
 +      ctime_r(&info->mtime.tv_sec, mtime_buf);
 +      ctime_r(&info->ctime.tv_sec, ctime_buf);
 +      DbgPrint("type = %i", info->type);
 +      DbgPrint("mode = %x", info->mode);
 +      DbgPrint("uid = %d", info->uid);
 +      DbgPrint("gid = %d", info->gid);
 +      DbgPrint("size = %i", info->size);
 +      DbgPrint("atime = %s", atime_buf);
 +      DbgPrint("mtime = %s", mtime_buf);
 +      DbgPrint("ctime = %s", ctime_buf);
 +      DbgPrint("namelength = %i", info->namelength);
 +      DbgPrint("name = %s", namebuf);
 +}
 +
 +void processList(struct file *file, void *dirent, filldir_t filldir, char *list, int type, struct novfs_schandle SessionId)
 +{
 +      unsigned char *path, *buf = NULL, *cp;
 +      struct qstr name;
 +      struct novfs_entry_info *pinfo = NULL;
 +
 +      buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +      path = buf;
 +      if (buf) {
 +              path = novfs_dget_path(file->f_dentry, buf, PATH_LENGTH_BUFFER);
 +              if (path) {
 +                      strcpy(buf, path);
 +              }
 +              path = buf + strlen(buf);
 +              *path++ = '\\';
 +      }
 +
 +      if (list) {
 +              cp = list;
 +              while (*cp) {
 +                      name.name = cp;
 +                      DbgPrint("name.name = %s", name.name);
 +                      name.len = strlen(cp);
 +                      name.hash = novfs_internal_hash(&name);
 +                      cp += (name.len + 1);
 +
 +                      pinfo = kmalloc(sizeof(struct novfs_entry_info) + PATH_LENGTH_BUFFER, GFP_KERNEL);
 +                      pinfo->mode = S_IFDIR | 0700;
 +                      pinfo->size = 0;
 +                      pinfo->atime = pinfo->ctime = pinfo->mtime = CURRENT_TIME;
 +                      strcpy(pinfo->name, name.name);
 +                      pinfo->namelength = name.len;
 +
 +                      novfs_Dump_Info(pinfo);
 +
 +                      filldir(dirent, pinfo->name, pinfo->namelength, file->f_pos, file->f_pos, pinfo->mode >> 12);
 +                      file->f_pos += 1;
 +
 +                      kfree(pinfo);
 +              }
 +      }
 +
 +      if (buf) {
 +              kfree(buf);
 +      }
 +}
 +
 +int processEntries(struct file *file, void *dirent, filldir_t filldir, void **enumHandle, struct novfs_schandle sessionId)
 +{
 +      unsigned char *path = NULL, *buf = NULL;
 +      int count = 0, status = 0;
 +      struct novfs_entry_info *pinfo = NULL;
 +      struct novfs_entry_info *pInfoMem = NULL;
 +
 +      buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +      if (!buf) {
 +              return -ENOMEM;
 +      }
 +
 +      path = novfs_dget_path(file->f_dentry, buf, PATH_LENGTH_BUFFER);
 +      if (!path) {
 +              kfree(buf);
 +              return -ENOMEM;
 +      }
 +      //NWSearchfiles
 +      count = 0;
 +      status = novfs_get_dir_listex(path, enumHandle, &count, &pinfo, sessionId);
 +      pInfoMem = pinfo;
 +
 +      if ((count == -1) || (count == 0) || (status != 0)) {
 +              kfree(pInfoMem);
 +              kfree(buf);
 +              return -1;
 +      }
 +      // parse resultset
 +      while (pinfo && count--) {
 +              filldir(dirent, pinfo->name, pinfo->namelength, file->f_pos, file->f_pos, pinfo->mode >> 12);
 +              file->f_pos += 1;
 +
 +              pinfo = (struct novfs_entry_info *)(pinfo->name + pinfo->namelength);
 +      }
 +
 +      kfree(pInfoMem);
 +      kfree(buf);
 +      return 0;
 +}
 +
 +int novfs_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
 +{
 +      unsigned char *list = NULL;
 +      int status = 0;         //-ENOMEM;
 +      struct inode *inode = file->f_dentry->d_inode;
 +      struct novfs_schandle sessionId;
 +      uid_t uid;
 +      int type = 0;
 +      struct file_private *file_private = NULL;
 +      int lComm;
 +
 +      file_private = (struct file_private *)file->private_data;
 +      DbgPrint("Name %.*s", file->f_dentry->d_name.len, file->f_dentry->d_name.name);
 +
 +      //printk("<1> file = %.*s\n", file->f_dentry->d_name.len, file->f_dentry->d_name.name);
 +
 +// Use this hack by default
 +#ifndef SKIP_CROSSOVER_HACK
 +      // Hack for crossover - begin
 +      mutex_lock(&TimeDir_Lock);
 +      if ((file->f_dentry->d_name.len == 7) &&
 +          ((0 == strncmp(file->f_dentry->d_name.name, " !xover", 7)) ||
 +           (0 == strncmp(file->f_dentry->d_name.name, "z!xover", 7)))) {
 +              //printk("<1> xoverhack: we are in xoverHack\n");
 +
 +              inHAX = 1;
 +              inHAXTime = get_nanosecond_time();
 +              //up( &TimeDir_Lock );
 +              //return 0;
 +              file_private->listedall = 1;
 +      } else {
 +              if (inHAX) {
 +                      if (get_nanosecond_time() - inHAXTime > 100 * 1000 * 1000) {
 +                              //printk("<1> xoverhack: it was long, long, long ago...\n");
 +                              inHAX = 0;
 +                      } else {
 +                              //printk("<1> xoverhack: word gotcha in xoverHack...\n");
 +                              inHAXTime = get_nanosecond_time();
 +                              //up( &TimeDir_Lock );
 +                              //return 0;
 +                              file_private->listedall = 1;
 +                      }
 +              }
 +      }
 +
 +      mutex_unlock(&TimeDir_Lock);
 +      // Hack for crossover - end
 +#endif
 +
 +      if (file->f_pos == 0) {
 +              if (filldir(dirent, ".", 1, file->f_pos, inode->i_ino, DT_DIR) < 0)
 +                      return 1;
 +              file->f_pos++;
 +              return 1;
 +      }
 +
 +      if (file->f_pos == 1) {
 +              if (filldir(dirent, "..", 2, file->f_pos, file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
 +                      return 1;
 +              file->f_pos++;
 +              return 1;
 +      }
 +
 +      if (file_private->listedall != 0) {
 +              return 0;
 +      }
 +
 +      inode = file->f_dentry->d_inode;
 +      if (inode && inode->i_private) {
 +              sessionId = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +              if (0 == SC_PRESENT(sessionId)) {
 +                      ((struct inode_data *)inode->i_private)->Scope = novfs_get_scope(file->f_dentry);
 +                      sessionId = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +              }
 +              uid = novfs_scope_get_uid(((struct inode_data *)inode->i_private)->Scope);
 +      } else {
 +              SC_INITIALIZE(sessionId);
 +              uid = current_euid();
 +      }
 +
 +      if (IS_ROOT(file->f_dentry) ||  // Root
 +          IS_ROOT(file->f_dentry->d_parent) ||        // User
 +          IS_ROOT(file->f_dentry->d_parent->d_parent))        // Server
 +      {
 +              if (IS_ROOT(file->f_dentry)) {
 +                      DbgPrint("Root directory");
 +                      list = novfs_get_scopeusers();
 +                      type = USER_LIST;
 +              } else if (IS_ROOT(file->f_dentry->d_parent)) {
 +                      DbgPrint("Parent is Root directory");
 +                      novfs_get_servers(&list, sessionId);
 +                      type = SERVER_LIST;
 +              } else {
 +                      DbgPrint("Parent-Parent is Root directory");
 +                      novfs_get_vols(&file->f_dentry->d_name, &list, sessionId);
 +                      type = VOLUME_LIST;
 +              }
 +
 +              processList(file, dirent, filldir, list, type, sessionId);
 +              file_private->listedall = 1;
 +      } else {
 +              status = processEntries(file, dirent, filldir, &file_private->enumHandle, sessionId);
 +
 +              if (status != 0) {
 +                      file_private->listedall = 1;
 +#ifndef SKIP_CROSSOVER_HACK
 +                      // Hack for crossover part 2 - begin
 +                      lComm = strlen(current->comm);
 +                      if ((lComm > 4)
 +                          && (0 == strcmp(current->comm + lComm - 4, ".EXE"))) {
 +                              if (filldir(dirent, " !xover", 7, file->f_pos, inode->i_ino, DT_DIR) < 0)
 +                                      return 1;
 +                              if (filldir(dirent, "z!xover", 7, file->f_pos, inode->i_ino, DT_DIR) < 0)
 +                                      return 1;
 +                              file->f_pos += 2;
 +                      }
 +                      // Hack for crossover part2 - end
 +#endif
 +              }
 +      }
 +
 +      file->private_data = file_private;
 +      return 1;
 +}
 +
 +int novfs_dir_fsync(struct file *file, int datasync)
 +{
 +      DbgPrint("Name %.*s", file->f_dentry->d_name.len,
 +               file->f_dentry->d_name.name);
 +      return generic_file_fsync(file, datasync);
 +}
 +
 +ssize_t novfs_f_read(struct file * file, char *buf, size_t len, loff_t * off)
 +{
 +      size_t thisread, totalread = 0;
 +      loff_t offset = *off;
 +      struct inode *inode;
 +      struct novfs_schandle session;
 +      struct inode_data *id;
 +
 +      if (file->f_dentry && (inode = file->f_dentry->d_inode) && (id = (struct inode_data *)inode->i_private)) {
 +
 +              DbgPrint("(0x%p 0x%p %d %lld %.*s)",
 +                       file->private_data, buf, len, offset, file->f_dentry->d_name.len, file->f_dentry->d_name.name);
 +
 +              if (novfs_page_cache && !(file->f_flags & O_DIRECT) && id->CacheFlag) {
 +                      totalread = do_sync_read(file, buf, len, off);
 +              } else {
 +                      session = novfs_scope_get_sessionId(id->Scope);
 +                      if (0 == SC_PRESENT(session)) {
 +                              id->Scope = novfs_get_scope(file->f_dentry);
 +                              session = novfs_scope_get_sessionId(id->Scope);
 +                      }
 +
 +                      while (len > 0 && (offset < i_size_read(inode))) {
 +                              int retval;
 +                              thisread = len;
 +                              retval = novfs_read_file(file->private_data, buf, &thisread, &offset, session);
 +                              if (retval || !thisread) {
 +                                      if (retval) {
 +                                              totalread = retval;
 +                                      }
 +                                      break;
 +                              }
 +                              DbgPrint("thisread = 0x%x", thisread);
 +                              len -= thisread;
 +                              buf += thisread;
 +                              offset += thisread;
 +                              totalread += thisread;
 +                      }
 +                      *off = offset;
 +              }
 +      }
 +      DbgPrint("return = %d", totalread);
 +
 +      return (totalread);
 +}
 +
 +ssize_t novfs_f_write(struct file * file, const char *buf, size_t len, loff_t * off)
 +{
 +      ssize_t thiswrite, totalwrite = 0;
 +      loff_t offset = *off;
 +      struct novfs_schandle session;
 +      struct inode *inode;
 +      int status;
 +      struct inode_data *id;
 +
 +      if (file->f_dentry && (inode = file->f_dentry->d_inode) && (id = file->f_dentry->d_inode->i_private)) {
 +              DbgPrint("(0x%p 0x%p 0x%p %d %lld %.*s)",
 +                       file->private_data, inode, id->FileHandle, len, offset,
 +                       file->f_dentry->d_name.len, file->f_dentry->d_name.name);
 +
 +              if (novfs_page_cache && !(file->f_flags & O_DIRECT) && id->CacheFlag && !(file->f_flags & O_WRONLY)) {
 +                      totalwrite = do_sync_write(file, buf, len, off);
 +              } else {
 +                      if (file->f_flags & O_APPEND) {
 +                              offset = i_size_read(inode);
 +                              DbgPrint("appending to end %lld %.*s",
 +                                       offset, file->f_dentry->d_name.len, file->f_dentry->d_name.name);
 +                      }
 +
 +                      session = novfs_scope_get_sessionId(id->Scope);
 +                      if (0 == SC_PRESENT(session)) {
 +                              id->Scope = novfs_get_scope(file->f_dentry);
 +                              session = novfs_scope_get_sessionId(id->Scope);
 +                      }
 +
 +                      while (len > 0) {
 +                              thiswrite = len;
 +                              if ((status =
 +                                   novfs_write_file(file->private_data,
 +                                                    (unsigned char *)buf, &thiswrite, &offset, session)) || !thiswrite) {
 +                                      totalwrite = status;
 +                                      break;
 +                              }
 +                              DbgPrint("thiswrite = 0x%x", thiswrite);
 +                              len -= thiswrite;
 +                              buf += thiswrite;
 +                              offset += thiswrite;
 +                              totalwrite += thiswrite;
 +                              if (offset > i_size_read(inode)) {
 +                                      i_size_write(inode, offset);
 +                                      inode->i_blocks = (offset + inode->i_sb->s_blocksize - 1) >> inode->i_blkbits;
 +                              }
 +                              inode->i_mtime = inode->i_atime = CURRENT_TIME;
 +                              id->Flags |= UPDATE_INODE;
 +
 +                      }
 +                      *off = offset;
 +              }
 +      }
 +      DbgPrint("return = 0x%x", totalwrite);
 +
 +      return (totalwrite);
 +}
 +
 +int novfs_f_readdir(struct file *file, void *data, filldir_t fill)
 +{
 +      return -EISDIR;
 +}
 +
 +int novfs_f_mmap(struct file *file, struct vm_area_struct *vma)
 +{
 +      int retCode = -EINVAL;
 +
 +      DbgPrint("file=0x%p %.*s", file, file->f_dentry->d_name.len, file->f_dentry->d_name.name);
 +
 +      retCode = generic_file_mmap(file, vma);
 +
 +      DbgPrint("retCode=0x%x", retCode);
 +      return (retCode);
 +}
 +
 +int novfs_f_open(struct inode *inode, struct file *file)
 +{
 +      struct novfs_entry_info *info = NULL;
 +      int retCode = -ENOENT;
 +      struct novfs_schandle session;
 +      char *path;
 +      struct dentry *parent;
 +      ino_t ino;
 +      struct inode_data *id;
 +      int errInfo;
 +
 +      DbgPrint("inode=0x%p file=0x%p dentry=0x%p dentry->d_inode=0x%p %.*s",
 +               inode, file, file->f_dentry, file->f_dentry->d_inode, file->f_dentry->d_name.len, file->f_dentry->d_name.name);
 +      if (file->f_dentry) {
 +              DbgPrint("%.*s f_flags=0%o f_mode=0%o i_mode=0%o",
 +                       file->f_dentry->d_name.len, file->f_dentry->d_name.name, file->f_flags, file->f_mode, inode->i_mode);
 +      }
 +
 +      if (inode && inode->i_private) {
 +              id = (struct inode_data *)file->f_dentry->d_inode->i_private;
 +              session = novfs_scope_get_sessionId(id->Scope);
 +              if (0 == SC_PRESENT(session)) {
 +                      id->Scope = novfs_get_scope(file->f_dentry);
 +                      session = novfs_scope_get_sessionId(id->Scope);
 +              }
 +
 +              info = kmalloc(sizeof(struct novfs_entry_info) + PATH_LENGTH_BUFFER, GFP_KERNEL);
 +              if (info) {
 +                      path = novfs_dget_path(file->f_dentry, info->name, PATH_LENGTH_BUFFER);
 +                      if (path) {
 +                              if (file->f_flags & O_TRUNC) {
 +                                      errInfo = novfs_get_file_info(path, info, session);
 +
 +                                      if (errInfo || info->size == 0) {
 +                                              // clear O_TRUNC flag, bug #275366
 +                                              file->f_flags = file->f_flags & (~O_TRUNC);
 +                                      }
 +                              }
 +
 +                              DbgPrint("%s", path);
 +                              retCode = novfs_open_file(path, file->f_flags & ~O_EXCL, info, &file->private_data, session);
 +
 +                              DbgPrint("0x%x 0x%p", retCode, file->private_data);
 +                              if (!retCode) {
 +                                      /*
 +                                       *update_inode(inode, &info);
 +                                       */
 +                                      //id->FileHandle = file->private_data;
 +                                      id->CacheFlag = novfs_get_file_cache_flag(path, session);
 +
 +                                      if (!novfs_get_file_info(path, info, session)) {
 +                                              update_inode(inode, info);
 +                                      }
 +
 +                                      parent = dget_parent(file->f_dentry);
 +
 +                                      if (parent && parent->d_inode) {
 +                                              struct inode *dir = parent->d_inode;
 +                                              novfs_lock_inode_cache(dir);
 +                                              ino = 0;
 +                                              if (novfs_get_entry(dir, &file->f_dentry->d_name, &ino, info)) {
 +                                                      ((struct inode_data *)inode->i_private)->Flags |= UPDATE_INODE;
 +                                              }
 +
 +                                              novfs_unlock_inode_cache(dir);
 +                                      }
 +                                      dput(parent);
 +                              }
 +                      }
 +                      kfree(info);
 +              }
 +      }
 +      DbgPrint("retCode=0x%x", retCode);
 +      return (retCode);
 +}
 +
 +int novfs_flush_mapping(void *Handle, struct address_space *mapping, struct novfs_schandle Session)
 +{
 +      struct pagevec pagevec;
 +      unsigned nrpages;
 +      pgoff_t index = 0;
 +      int done, rc = 0;
 +
 +      pagevec_init(&pagevec, 0);
 +
 +      do {
 +              done = 1;
 +              nrpages = pagevec_lookup_tag(&pagevec, mapping, &index, PAGECACHE_TAG_DIRTY, PAGEVEC_SIZE);
 +
 +              if (nrpages) {
 +                      struct page *page;
 +                      int i;
 +
 +                      DbgPrint("%u", nrpages);
 +
 +                      done = 0;
 +                      for (i = 0; !rc && (i < nrpages); i++) {
 +                              page = pagevec.pages[i];
 +
 +                              DbgPrint("page 0x%p %lu", page, page->index);
 +
 +                              lock_page(page);
 +                              page_cache_get(page);
 +                              if (page->mapping == mapping) {
 +                                      if (clear_page_dirty_for_io(page)) {
 +                                              rc = novfs_write_page(Handle, page, Session);
 +                                              if (!rc) {
 +                                                      //ClearPageDirty(page);
 +                                                      radix_tree_tag_clear
 +                                                          (&mapping->page_tree, page_index(page), PAGECACHE_TAG_DIRTY);
 +                                              }
 +                                      }
 +                              }
 +
 +                              page_cache_release(page);
 +                              unlock_page(page);
 +                      }
 +                      pagevec_release(&pagevec);
 +              }
 +      } while (!rc && !done);
 +
 +      DbgPrint("return %d", rc);
 +
 +      return (rc);
 +}
 +
 +int novfs_f_flush(struct file *file, fl_owner_t ownid)
 +{
 +
 +      int rc = 0;
 +#ifdef FLUSH
 +      struct inode *inode;
 +      struct novfs_schandle session;
 +      struct inode_data *id;
 +
 +      DbgPrint("Called from 0x%p", __builtin_return_address(0));
 +      if (file->f_dentry && (inode = file->f_dentry->d_inode)
 +          && (id = file->f_dentry->d_inode->i_private)) {
 +
 +              if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
 +                      inode = file->f_dentry->d_inode;
 +                      DbgPrint("%.*s f_flags=0%o f_mode=0%o i_mode=0%o",
 +                               file->f_dentry->d_name.len,
 +                               file->f_dentry->d_name.name, file->f_flags, file->f_mode, inode->i_mode);
 +
 +                      session = novfs_scope_get_sessionId(id->Scope);
 +                      if (0 == SC_PRESENT(session)) {
 +                              id->Scope = novfs_get_scope(file->f_dentry);
 +                              session = novfs_scope_get_sessionId(id->Scope);
 +                      }
 +
 +                      if (inode && inode->i_mapping && inode->i_mapping->nrpages) {
 +
 +                              DbgPrint("%.*s pages=%lu",
 +                                       file->f_dentry->d_name.len, file->f_dentry->d_name.name, inode->i_mapping->nrpages);
 +
 +                              if (file->f_dentry &&
 +                                  file->f_dentry->d_inode &&
 +                                  file->f_dentry->d_inode->i_mapping &&
 +                                  file->f_dentry->d_inode->i_mapping->a_ops &&
 +                                  file->f_dentry->d_inode->i_mapping->a_ops->writepage) {
 +                                      rc = filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
 +                              } else {
 +                                      rc = novfs_flush_mapping(file->private_data, file->f_dentry->d_inode->i_mapping, session);
 +                              }
 +                      }
 +              }
 +      }
 +#endif
 +      return (rc);
 +}
 +
 +int novfs_f_release(struct inode *inode, struct file *file)
 +{
 +      int retCode = -EACCES;
 +      struct novfs_schandle session;
 +      struct inode_data *id;
 +
 +      DbgPrint("path=%.*s handle=%p", file->f_dentry->d_name.len, file->f_dentry->d_name.name, file->private_data);
 +
 +      if (inode && (id = inode->i_private)) {
 +              session = novfs_scope_get_sessionId(id->Scope);
 +              if (0 == SC_PRESENT(session)) {
 +                      id->Scope = novfs_get_scope(file->f_dentry);
 +                      session = novfs_scope_get_sessionId(id->Scope);
 +              }
 +
 +              if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
 +                      DbgPrint("%.*s f_flags=0%o f_mode=0%o i_mode=0%o",
 +                               file->f_dentry->d_name.len,
 +                               file->f_dentry->d_name.name, file->f_flags, file->f_mode, inode->i_mode);
 +
 +                      if (inode->i_mapping && inode->i_mapping->nrpages) {
 +
 +                              DbgPrint("%.*s pages=%lu",
 +                                       file->f_dentry->d_name.len, file->f_dentry->d_name.name, inode->i_mapping->nrpages);
 +
 +                              if (inode->i_mapping->a_ops && inode->i_mapping->a_ops->writepage) {
 +                                      filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
 +                              } else {
 +                                      novfs_flush_mapping(file->private_data, file->f_dentry->d_inode->i_mapping, session);
 +                              }
 +                      }
 +              }
 +
 +              if (file->f_dentry && file->f_dentry->d_inode) {
 +                      invalidate_remote_inode(file->f_dentry->d_inode);
 +              }
 +
 +              retCode = novfs_close_file(file->private_data, session);
 +              //id->FileHandle = 0;
 +      }
 +      return (retCode);
 +}
 +
 +int novfs_f_fsync(struct file *file, int datasync)
 +{
 +      return 0;
 +}
 +
 +int novfs_f_llseek(struct file *file, loff_t offset, int origin)
 +{
 +      DbgPrint("File=0x%p Name=%.*s offset=%lld origin=%d",
 +               file, file->f_dentry->d_name.len, file->f_dentry->d_name.name, offset, origin);
 +      return (generic_file_llseek(file, offset, origin));
 +}
 +
 +/*++======================================================================*/
 +int novfs_f_lock(struct file *file, int cmd, struct file_lock *lock)
 +/*
 + *  Arguments:
 + *      "file" - pointer to file structure - contains file handle in "file->private_data"
 + *
 + *      "cmd" could be F_SETLK, F_SETLKW, F_GETLK
 + *      F_SETLK/F_SETLKW are for setting/unsetting file lock
 + *      F_GETLK is for getting infomation about region - is it locked, or not
 + *
 + *      "lock" structure - contains "start" and "end" of locking region
 + *
 + *  Returns:
 + *      0 on success
 + *      -ENOSYS on F_GETLK cmd. It's not implemented.
 + *      -EINVAL if (lock->fl_start > lock->fl_end)
 + *      -EAGAIN on all other errors
 + *  Abstract:
 + *
 + *  Notes:
 + *      "lock->fl_start" and "lock->fl_end" are of type "long long",
 + *      but xtier functions in novfsd "NCFsdLockFile" and "NCFsdUnlockFile"
 + *      receive arguments in u64 type.
 + *
 + *
 + *========================================================================*/
 +{
 +      int err_code;
 +
 +      struct inode *inode;
 +      struct novfs_schandle session;
 +      struct inode_data *id;
 +      loff_t len;
 +
 +      DbgPrint("(0x%p): begin in novfs_f_lock 0x%p", __builtin_return_address(0), file->private_data);
 +      DbgPrint("cmd = %d, F_GETLK = %d, F_SETLK = %d, F_SETLKW = %d", cmd, F_GETLK, F_SETLK, F_SETLKW);
 +      DbgPrint("lock->fl_start = 0x%llX, lock->fl_end = 0x%llX", lock->fl_start, lock->fl_end);
 +
 +      err_code = -1;
 +      if (lock->fl_start <= lock->fl_end) {
 +              /* Get len from "start" and "end" */
 +              len = lock->fl_end - lock->fl_start + 1;
 +              if ((0 == lock->fl_start) && (OFFSET_MAX == lock->fl_end)) {
 +                      len = 0;
 +              }
 +
 +              if (file->f_dentry && (inode = file->f_dentry->d_inode) && (id = (struct inode_data *)inode->i_private)) {
 +                      DbgPrint("(0x%p 0x%p %.*s)",
 +                               file->private_data, inode, file->f_dentry->d_name.len, file->f_dentry->d_name.name);
 +
 +                      session = novfs_scope_get_sessionId(id->Scope);
 +                      if (0 == SC_PRESENT(session)) {
 +                              id->Scope = novfs_get_scope(file->f_dentry);
 +                              session = novfs_scope_get_sessionId(id->Scope);
 +                      }
 +
 +                      /* fl_type = F_RDLCK, F_WRLCK, F_UNLCK */
 +                      switch (cmd) {
 +                      case F_SETLK:
 +#ifdef F_GETLK64
 +                      case F_SETLK64:
 +#endif
 +
 +                              err_code = novfs_set_file_lock(session, file->private_data, lock->fl_type, lock->fl_start, len);
 +                              break;
 +
 +                      case F_SETLKW:
 +#ifdef F_GETLK64
 +                      case F_SETLKW64:
 +#endif
 +                              err_code = novfs_set_file_lock(session, file->private_data, lock->fl_type, lock->fl_start, len);
 +                              break;
 +
 +                      case F_GETLK:
 +#ifdef F_GETLK64
 +                      case F_GETLK64:
 +#endif
 +                              err_code = -ENOSYS;
 +                              /*
 +                               * Not implemented. We doesn't have appropriate xtier function.
 +                               * */
 +                              break;
 +
 +                      default:
 +                              printk("<1> novfs in novfs_f_lock, not implemented cmd = %d\n", cmd);
 +                              DbgPrint("novfs in novfs_f_lock, not implemented cmd = %d", cmd);
 +                              break;
 +                      }
 +              }
 +
 +              DbgPrint("lock->fl_type = %u, err_code 0x%X", lock->fl_type, err_code);
 +
 +              if ((err_code != 0) && (err_code != -1)
 +                  && (err_code != -ENOSYS)) {
 +                      err_code = -EAGAIN;
 +              }
 +      } else {
 +              err_code = -EINVAL;
 +      }
 +
 +      return (err_code);
 +}
 +
 +/*++======================================================================*/
 +static void novfs_copy_cache_pages(struct address_space *mapping,
 +                                 struct list_head *pages, int bytes_read, char *data, struct pagevec *plru_pvec)
 +{
 +      struct page *page;
 +      char *target;
 +
 +      while (bytes_read > 0) {
 +              if (list_empty(pages))
 +                      break;
 +
 +              page = list_entry(pages->prev, struct page, lru);
 +              list_del(&page->lru);
 +
 +              if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
 +                      page_cache_release(page);
 +                      data += PAGE_CACHE_SIZE;
 +                      bytes_read -= PAGE_CACHE_SIZE;
 +                      continue;
 +              }
 +
 +              target = kmap_atomic(page, KM_USER0);
 +
 +              if (PAGE_CACHE_SIZE > bytes_read) {
 +                      memcpy(target, data, bytes_read);
 +                      /* zero the tail end of this partial page */
 +                      memset(target + bytes_read, 0, PAGE_CACHE_SIZE - bytes_read);
 +                      bytes_read = 0;
 +              } else {
 +                      memcpy(target, data, PAGE_CACHE_SIZE);
 +                      bytes_read -= PAGE_CACHE_SIZE;
 +              }
 +              kunmap_atomic(target, KM_USER0);
 +
 +              flush_dcache_page(page);
 +              SetPageUptodate(page);
 +              unlock_page(page);
 +              if (!pagevec_add(plru_pvec, page))
 +                      __pagevec_lru_add_file(plru_pvec);
 +              data += PAGE_CACHE_SIZE;
 +      }
 +      return;
 +}
 +
 +int novfs_a_writepage(struct page *page, struct writeback_control *wbc)
 +{
 +      int retCode = -EFAULT;
 +      struct inode *inode = page->mapping->host;
 +      struct inode_data *id = inode->i_private;
 +      loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT);
 +      struct novfs_schandle session;
 +      struct novfs_data_list dlst[2];
 +      size_t len = PAGE_CACHE_SIZE;
 +
 +      session = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +
 +      page_cache_get(page);
 +
 +      pos = ((loff_t) page->index << PAGE_CACHE_SHIFT);
 +
 +      /*
 +       * Leave first dlst entry for reply header.
 +       */
 +      dlst[1].page = page;
 +      dlst[1].offset = NULL;
 +      dlst[1].len = len;
 +      dlst[1].rwflag = DLREAD;
 +
 +      /*
 +       * Check size so we don't write pass end of file.
 +       */
 +      if ((pos + (loff_t) len) > i_size_read(inode)) {
 +              len = (size_t) (i_size_read(inode) - pos);
 +      }
 +
 +      retCode = novfs_write_pages(id->FileHandle, dlst, 2, len, pos, session);
 +      if (!retCode) {
 +              SetPageUptodate(page);
 +      }
 +
 +      unlock_page(page);
 +      page_cache_release(page);
 +
 +      return (retCode);
 +}
 +
 +int novfs_a_writepages(struct address_space *mapping, struct writeback_control *wbc)
 +{
 +      int retCode = 0;
 +      struct inode *inode = mapping->host;
 +      struct novfs_schandle session;
 +      void *fh = NULL;
 +      struct inode_data *id = NULL;
 +
 +      int max_page_lookup = novfs_max_iosize / PAGE_CACHE_SIZE;
 +
 +      struct novfs_data_list *dlist, *dlptr;
 +      struct page **pages;
 +
 +      int dlist_idx, i = 0;
 +      pgoff_t index, next_index = 0;
 +      loff_t pos = 0;
 +      size_t tsize;
 +
 +      SC_INITIALIZE(session);
 +      DbgPrint("inode=0x%p mapping=0x%p wbc=0x%p nr_to_write=%d", inode, mapping, wbc, wbc->nr_to_write);
 +
 +      if (inode) {
 +              DbgPrint("Inode=0x%p Ino=%d Id=0x%p", inode, inode->i_ino, inode->i_private);
 +
 +              if (NULL != (id = inode->i_private)) {
 +                      session = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +                      fh = ((struct inode_data *)inode->i_private)->FileHandle;
 +              }
 +      }
 +
 +      dlist = kmalloc(sizeof(struct novfs_data_list) * max_page_lookup, GFP_KERNEL);
 +      pages = kmalloc(sizeof(struct page *) * max_page_lookup, GFP_KERNEL);
 +
 +      if (id)
 +              DbgPrint("inode=0x%p fh=0x%p dlist=0x%p pages=0x%p %s", inode, fh, dlist, pages, id->Name);
 +      else
 +              DbgPrint("inode=0x%p fh=0x%p dlist=0x%p pages=0x%p", inode, fh, dlist, pages);
 +
 +      if (dlist && pages) {
 +              struct backing_dev_info *bdi = mapping->backing_dev_info;
 +              int done = 0;
 +              int nr_pages = 0;
 +              int scanned = 0;
 +
 +              if (wbc->nonblocking && bdi_write_congested(bdi)) {
 +                      wbc->encountered_congestion = 1;
 +                      return 0;
 +              }
 +
 +              if (wbc->sync_mode == WB_SYNC_NONE) {
 +                      index = mapping->writeback_index;       /* Start from prev offset */
 +              } else {
 +                      index = 0;      /* whole-file sweep */
 +                      scanned = 1;
 +              }
 +
 +              next_index = index;
 +
 +              while (!done && (wbc->nr_to_write > 0)) {
 +                      dlist_idx = 0;
 +                      dlptr = &dlist[1];
 +
 +                      DbgPrint("nr_pages=%d", nr_pages);
 +                      if (!nr_pages) {
 +                              memset(pages, 0, sizeof(struct page *) * max_page_lookup);
 +
 +                              spin_lock_irq(&mapping->tree_lock);
 +
 +                              /*
 +                               * Need to ask for one less then max_page_lookup or we
 +                               * will overflow the request buffer.  This also frees
 +                               * the first entry for the reply buffer.
 +                               */
 +                              nr_pages =
 +                                  radix_tree_gang_lookup_tag(&mapping->page_tree,
 +                                                             (void **)pages, index, max_page_lookup - 1, PAGECACHE_TAG_DIRTY);
 +
 +                              DbgPrint("2; nr_pages=%d\n", nr_pages);
 +                              /*
 +                               * Check to see if there are dirty pages and there is a valid
 +                               * file handle.
 +                               */
 +                              if (nr_pages && !fh) {
 +                                      set_bit(AS_EIO, &mapping->flags);
 +                                      done = 1;
 +                                      DbgPrint("set_bit AS_EIO");
 +                                      break;
 +                              }
 +
 +                              for (i = 0; i < nr_pages; i++) {
 +                                      page_cache_get(pages[i]);
 +                              }
 +
 +                              spin_unlock_irq(&mapping->tree_lock);
 +
 +                              if (nr_pages) {
 +                                      index = pages[nr_pages - 1]->index + 1;
 +                                      pos = (loff_t) pages[0]->index << PAGE_CACHE_SHIFT;
 +                              }
 +
 +                              if (!nr_pages) {
 +                                      if (scanned) {
 +                                              index = 0;
 +                                              scanned = 0;
 +                                              continue;
 +                                      }
 +                                      done = 1;
 +                              } else {
 +                                      next_index = pages[0]->index;
 +                                      i = 0;
 +                              }
 +                      } else {
 +                              if (pages[i]) {
 +                                      pos = (loff_t) pages[i]->index << PAGE_CACHE_SHIFT;
 +                              }
 +                      }
 +
 +                      for (; i < nr_pages; i++) {
 +                              struct page *page = pages[i];
 +
 +                              /*
 +                               * At this point we hold neither mapping->tree_lock nor
 +                               * lock on the page itself: the page may be truncated or
 +                               * invalidated (changing page->mapping to NULL), or even
 +                               * swizzled back from swapper_space to tmpfs file
 +                               * mapping
 +                               */
 +
 +                              DbgPrint
 +                                  ("novfs_a_writepages: pos=0x%llx index=%d page->index=%d next_index=%d\n",
 +                                   pos, index, page->index, next_index);
 +
 +                              if (page->index != next_index) {
 +                                      next_index = page->index;
 +                                      break;
 +                              }
 +                              next_index = page->index + 1;
 +
 +                              lock_page(page);
 +
 +                              if (wbc->sync_mode != WB_SYNC_NONE)
 +                                      wait_on_page_writeback(page);
 +
 +                              if (page->mapping != mapping || PageWriteback(page)
 +                                  || !clear_page_dirty_for_io(page)) {
 +                                      unlock_page(page);
 +                                      continue;
 +                              }
 +
 +                              dlptr[dlist_idx].page = page;
 +                              dlptr[dlist_idx].offset = NULL;
 +                              dlptr[dlist_idx].len = PAGE_CACHE_SIZE;
 +                              dlptr[dlist_idx].rwflag = DLREAD;
 +                              dlist_idx++;
 +                              DbgPrint("Add page=0x%p index=0x%lx", page, page->index);
 +                      }
 +
 +                      DbgPrint("dlist_idx=%d", dlist_idx);
 +                      if (dlist_idx) {
 +                              tsize = dlist_idx * PAGE_CACHE_SIZE;
 +                              /*
 +                               * Check size so we don't write pass end of file.
 +                               */
 +                              if ((pos + tsize) > i_size_read(inode)) {
 +                                      tsize = (size_t) (i_size_read(inode) - pos);
 +                              }
 +
 +                              retCode = novfs_write_pages(fh, dlist, dlist_idx + 1, tsize, pos, session);
 +                              switch (retCode) {
 +                              case 0:
 +                                      wbc->nr_to_write -= dlist_idx;
 +                                      break;
 +
 +                              case -ENOSPC:
 +                                      set_bit(AS_ENOSPC, &mapping->flags);
 +                                      done = 1;
 +                                      break;
 +
 +                              default:
 +                                      set_bit(AS_EIO, &mapping->flags);
 +                                      done = 1;
 +                                      break;
 +                              }
 +
 +                              do {
 +                                      unlock_page((struct page *)
 +                                                  dlptr[dlist_idx - 1].page);
 +                                      page_cache_release((struct page *)
 +                                                         dlptr[dlist_idx - 1].page);
 +                                      DbgPrint("release page=0x%p index=0x%lx", dlptr[dlist_idx - 1].page, ((struct page *)
 +                                                                                                            dlptr[dlist_idx -
 +                                                                                                                  1].page)->
 +                                               index);
 +                                      if (!retCode) {
 +                                              wbc->nr_to_write--;
 +                                      }
 +                              } while (--dlist_idx);
 +                      }
 +
 +                      if (i >= nr_pages) {
 +                              nr_pages = 0;
 +                      }
 +              }
 +
 +              mapping->writeback_index = index;
 +
 +      } else {
 +              DbgPrint("set_bit AS_EIO");
 +              set_bit(AS_EIO, &mapping->flags);
 +      }
 +      if (dlist)
 +              kfree(dlist);
 +      if (pages)
 +              kfree(pages);
 +
 +      DbgPrint("retCode=%d", retCode);
 +      return (0);
 +
 +}
 +
 +int novfs_a_readpage(struct file *file, struct page *page)
 +{
 +      int retCode = 0;
 +      void *pbuf;
 +      struct inode *inode = NULL;
 +      struct dentry *dentry = NULL;
 +      loff_t offset;
 +      size_t len;
 +      struct novfs_schandle session;
 +
 +      SC_INITIALIZE(session);
 +      DbgPrint("File=0x%p Name=%.*s Page=0x%p", file, file->f_dentry->d_name.len, file->f_dentry->d_name.name, page);
 +
 +      dentry = file->f_dentry;
 +
 +      if (dentry) {
 +              DbgPrint("Dentry=0x%p Name=%.*s", dentry, dentry->d_name.len, dentry->d_name.name);
 +              if (dentry->d_inode) {
 +                      inode = dentry->d_inode;
 +              }
 +      }
 +
 +      if (inode) {
 +              DbgPrint("Inode=0x%p Ino=%d", inode, inode->i_ino);
 +
 +              if (inode->i_private) {
 +                      session = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +                      if (0 == SC_PRESENT(session)) {
 +                              ((struct inode_data *)inode->i_private)->Scope = novfs_get_scope(file->f_dentry);
 +                              session = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +                      }
 +              }
 +      }
 +
 +      if (!PageUptodate(page)) {
 +              struct novfs_data_list dlst[2];
 +
 +              offset = page->index << PAGE_CACHE_SHIFT;
 +              len = PAGE_CACHE_SIZE;
 +
 +              /*
 +               * Save the first entry for the reply header.
 +               */
 +              dlst[1].page = page;
 +              dlst[1].offset = NULL;
 +              dlst[1].len = PAGE_CACHE_SIZE;
 +              dlst[1].rwflag = DLWRITE;
 +
 +              DbgPrint("calling= novfs_Read_Pages %lld", offset);
 +              retCode = novfs_read_pages(file->private_data, dlst, 2, &len, &offset, session);
 +              if (len && (len < PAGE_CACHE_SIZE)) {
 +                      pbuf = kmap_atomic(page, KM_USER0);
 +                      memset(&((char *)pbuf)[len], 0, PAGE_CACHE_SIZE - len);
 +                      kunmap_atomic(pbuf, KM_USER0);
 +              }
 +
 +              flush_dcache_page(page);
 +              SetPageUptodate(page);
 +      }
 +      unlock_page(page);
 +
 +      DbgPrint("retCode=%d", retCode);
 +      return (retCode);
 +
 +}
 +
 +int novfs_a_readpages(struct file *file, struct address_space *mapping, struct list_head *page_lst, unsigned nr_pages)
 +{
 +      int retCode = 0;
 +      struct inode *inode = NULL;
 +      struct dentry *dentry = NULL;
 +      struct novfs_schandle session;
 +      loff_t offset;
 +      size_t len;
 +
 +      unsigned page_idx;
 +      struct pagevec lru_pvec;
 +      pgoff_t next_index;
 +
 +      char *rbuf, done = 0;
 +      SC_INITIALIZE(session);
 +
 +      DbgPrint("File=0x%p Name=%.*s Pages=%d", file, file->f_dentry->d_name.len, file->f_dentry->d_name.name, nr_pages);
 +
 +      dentry = file->f_dentry;
 +
 +      if (dentry) {
 +              DbgPrint("Dentry=0x%p Name=%.*s", dentry, dentry->d_name.len, dentry->d_name.name);
 +              if (dentry->d_inode) {
 +                      inode = dentry->d_inode;
 +              }
 +      }
 +
 +      if (inode) {
 +              DbgPrint("Inode=0x%p Ino=%d", inode, inode->i_ino);
 +
 +              if (inode->i_private) {
 +                      session = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +                      if (0 == SC_PRESENT(session)) {
 +                              ((struct inode_data *)inode->i_private)->Scope = novfs_get_scope(file->f_dentry);
 +                              session = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +                      }
 +              }
 +      }
 +
 +      rbuf = kmalloc(novfs_max_iosize, GFP_KERNEL);
 +      if (rbuf) {
 +              pagevec_init(&lru_pvec, 0);
 +              for (page_idx = 0; page_idx < nr_pages && !done;) {
 +                      struct page *page, *tpage;
 +
 +                      if (list_empty(page_lst))
 +                              break;
 +
 +                      page = list_entry(page_lst->prev, struct page, lru);
 +
 +                      next_index = page->index;
 +                      offset = (loff_t) page->index << PAGE_CACHE_SHIFT;
 +                      len = 0;
 +
 +                      /*
 +                       * Count number of contiguous pages.
 +                       */
 +                      list_for_each_entry_reverse(tpage, page_lst, lru) {
 +                              if ((next_index != tpage->index) || (len >= novfs_max_iosize - PAGE_SIZE)) {
 +                                      break;
 +                              }
 +                              len += PAGE_SIZE;
 +                              next_index++;
 +                      }
 +
 +                      if (len && !done) {
 +                              struct novfs_data_list dllst[2];
 +
 +                              dllst[1].page = NULL;
 +                              dllst[1].offset = rbuf;
 +                              dllst[1].len = len;
 +                              dllst[1].rwflag = DLWRITE;
 +
 +                              DbgPrint("calling novfs_Read_Pages %lld", offset);
 +                              if (!novfs_read_pages(file->private_data, dllst, 2, &len, &offset, session)) {
 +                                      novfs_copy_cache_pages(mapping, page_lst, len, rbuf, &lru_pvec);
 +                                      page_idx += len >> PAGE_CACHE_SHIFT;
 +                                      if ((int)(len & PAGE_CACHE_MASK) != len) {
 +                                              page_idx++;
 +                                      }
 +                                      if (len == 0) {
 +                                              done = 1;
 +                                      }
 +                              } else {
 +                                      done = 1;
 +                              }
 +                      }
 +              }
 +
 +              /*
 +               * Free any remaining pages.
 +               */
 +              while (!list_empty(page_lst)) {
 +                      struct page *page = list_entry(page_lst->prev, struct page, lru);
 +
 +                      list_del(&page->lru);
 +                      page_cache_release(page);
 +              }
 +
 +              pagevec_lru_add_file(&lru_pvec);
 +              kfree(rbuf);
 +      } else {
 +              retCode = -ENOMEM;
 +      }
 +
 +      DbgPrint("retCode=%d", retCode);
 +      return (retCode);
 +
 +}
 +
 +int novfs_a_write_begin(struct file *file, struct address_space *mapping,
 +                      loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata)
 +{
 +      int retVal = 0;
 +      loff_t offset = pos;
 +      struct novfs_schandle session;
 +      struct novfs_data_list dllst[2];
 +      struct inode *inode = file->f_dentry->d_inode;
 +      struct page *page;
 +      pgoff_t index;
 +      unsigned from, to;
 +      SC_INITIALIZE(session);
 +
 +      index = pos >> PAGE_CACHE_SHIFT;
 +      from = pos & (PAGE_CACHE_SIZE - 1);
 +      to = from + len;
 +
 +      page = grab_cache_page_write_begin(mapping, index, flags);
 +      if (!page)
 +              return -ENOMEM;
 +
 +      *pagep = page;
 +
 +      DbgPrint("File=0x%p Page=0x%p offset=0x%llx From=%u To=%u "
 +               "filesize=%lld\n", file, page, offset, from, to, i_size_read(file->f_dentry->d_inode));
 +      if (!PageUptodate(page)) {
 +              /*
 +               * Check to see if whole page
 +               */
 +              if ((to == PAGE_CACHE_SIZE) && (from == 0)) {
 +                      SetPageUptodate(page);
 +              }
 +
 +              /*
 +               * Check to see if we can read page.
 +               */
 +              else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
 +                      /*
 +                       * Get session.
 +                       */
 +                      if (file->f_dentry && file->f_dentry->d_inode) {
 +                              if (file->f_dentry->d_inode->i_private) {
 +                                      session = novfs_scope_get_sessionId(((struct inode_data *)
 +                                                                           inode->i_private)->Scope);
 +                                      if (0 == SC_PRESENT(session)) {
 +                                              ((struct inode_data *)inode->i_private)->Scope = novfs_get_scope(file->f_dentry);
 +                                              session = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +                                      }
 +                              }
 +                      }
 +
 +                      page_cache_get(page);
 +
 +                      len = i_size_read(inode) - offset;
 +                      if (len > PAGE_CACHE_SIZE) {
 +                              len = PAGE_CACHE_SIZE;
 +                      }
 +
 +                      if (len) {
 +                              /*
 +                               * Read page from server.
 +                               */
 +
 +                              dllst[1].page = page;
 +                              dllst[1].offset = 0;
 +                              dllst[1].len = len;
 +                              dllst[1].rwflag = DLWRITE;
 +
 +                              DbgPrint("calling novfs_Read_Pages %lld", offset);
 +                              novfs_read_pages(file->private_data, dllst, 2, &len, &offset, session);
 +
 +                              /*
 +                               * Zero unnsed page.
 +                               */
 +                      }
 +
 +                      if (len < PAGE_CACHE_SIZE) {
 +                              char *adr = kmap_atomic(page, KM_USER0);
 +                              memset(adr + len, 0, PAGE_CACHE_SIZE - len);
 +                              kunmap_atomic(adr, KM_USER0);
 +                      }
 +              } else {
 +                      /*
 +                       * Zero section of memory that not going to be used.
 +                       */
 +                      char *adr = kmap_atomic(page, KM_USER0);
 +                      memset(adr, 0, from);
 +                      memset(adr + to, 0, PAGE_CACHE_SIZE - to);
 +                      kunmap_atomic(adr, KM_USER0);
 +
 +                      DbgPrint("memset 0x%p", adr);
 +              }
 +              flush_dcache_page(page);
 +              SetPageUptodate(page);
 +      }
 +//   DbgPrint("return %d", retVal);
 +      return (retVal);
 +}
 +
 +int novfs_a_write_end(struct file *file, struct address_space *mapping,
 +                    loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata)
 +{
 +      int retCode = 0;
 +      struct inode *inode = page->mapping->host;
 +      loff_t offset = pos;
 +      struct novfs_schandle session;
 +      struct inode_data *id;
 +      struct novfs_data_list dlst[1];
 +      pgoff_t index;
 +      unsigned from, to;
 +      SC_INITIALIZE(session);
 +
 +      index = pos >> PAGE_CACHE_SHIFT;
 +      from = pos & (PAGE_CACHE_SIZE - 1);
 +      to = from + len;
 +
 +      DbgPrint("File=0x%p Page=0x%p offset=0x%x To=%u filesize=%lld",
 +               file, page, offset, to, i_size_read(file->f_dentry->d_inode));
 +      if (file->f_dentry->d_inode && (id = file->f_dentry->d_inode->i_private)) {
 +              session = novfs_scope_get_sessionId(id->Scope);
 +              if (0 == SC_PRESENT(session)) {
 +                      id->Scope = novfs_get_scope(file->f_dentry);
 +                      session = novfs_scope_get_sessionId(id->Scope);
 +              }
 +
 +              /*
 +               * Setup file handle
 +               */
 +              id->FileHandle = file->private_data;
 +
 +              if (pos > inode->i_size) {
 +                      i_size_write(inode, pos);
 +              }
 +
 +              if (!PageUptodate(page)) {
 +                      pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + offset;
 +
 +                      if (to < offset) {
 +                              return (retCode);
 +                      }
 +                      dlst[0].page = page;
 +                      dlst[0].offset = (void *)(unsigned long)offset;
 +                      dlst[0].len = len;
 +                      dlst[0].rwflag = DLREAD;
 +
 +                      retCode = novfs_write_pages(id->FileHandle, dlst, 1, len, pos, session);
 +
 +              } else {
 +                      set_page_dirty(page);
 +              }
 +      }
 +
 +      return (retCode);
 +}
 +
 +/*++======================================================================*/
 +ssize_t novfs_a_direct_IO(int rw, struct kiocb * kiocb, const struct iovec * iov, loff_t offset, unsigned long nr_segs)
 +/*
 + *
 + *  Notes:        This is a dummy function so that we can allow a file
 + *                to get the direct IO flag set.  novfs_f_read and
 + *                novfs_f_write will do the work.  Maybe not the best
 + *                way to do but it was the easiest to implement.
 + *
 + *========================================================================*/
 +{
 +      return (-EIO);
 +}
 +
 +/*++======================================================================*/
 +int novfs_i_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
 +{
 +      char *path, *buf;
 +      struct novfs_entry_info info;
 +      void *handle;
 +      struct novfs_schandle session;
 +      int retCode = -EACCES;
 +
 +      DbgPrint("mode=0%o flags=0%o %.*s", mode, nd->NDOPENFLAGS, dentry->d_name.len, dentry->d_name.name);
 +
 +      if (IS_ROOT(dentry) ||  /* Root */
 +          IS_ROOT(dentry->d_parent) ||        /* User */
 +          IS_ROOT(dentry->d_parent->d_parent) ||      /* Server */
 +          IS_ROOT(dentry->d_parent->d_parent->d_parent)) {    /* Volume */
 +              return (-EACCES);
 +      }
 +
 +      if (mode | S_IFREG) {
 +              if (dir->i_private) {
 +                      session = novfs_scope_get_sessionId(((struct inode_data *)dir->i_private)->Scope);
 +                      if (0 == SC_PRESENT(session)) {
 +                              ((struct inode_data *)dir->i_private)->Scope = novfs_get_scope(dentry);
 +                              session = novfs_scope_get_sessionId(((struct inode_data *)dir->i_private)->Scope);
 +                      }
 +
 +                      buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +                      if (buf) {
 +                              path = novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
 +                              if (path) {
 +                                      retCode = novfs_open_file(path, nd->NDOPENFLAGS | O_RDWR, &info, &handle, session);
 +                                      if (!retCode && handle) {
 +                                              novfs_close_file(handle, session);
 +                                              if (!novfs_i_mknod(dir, dentry, mode | S_IFREG, 0)) {
 +                                                      if (dentry->d_inode) {
 +                                                              ((struct inode_data *)
 +                                                               dentry->d_inode->i_private)->Flags |= UPDATE_INODE;
 +                                                      }
 +                                              }
 +                                      }
 +                              }
 +                              kfree(buf);
 +                      }
 +              }
 +      }
 +      return (retCode);
 +}
 +
 +void update_inode(struct inode *Inode, struct novfs_entry_info *Info)
 +{
 +      static char dbuf[128];
 +
 +      DbgPrint("Inode=0x%p I_ino=%d", Inode, Inode->i_ino);
 +
 +      DbgPrint("atime=%s", ctime_r(&Info->atime.tv_sec, dbuf));
 +      DbgPrint("ctime=%s", ctime_r(&Info->ctime.tv_sec, dbuf));
 +      DbgPrint("mtime=%s %d", ctime_r(&Info->mtime.tv_sec, dbuf), Info->mtime.tv_nsec);
 +      DbgPrint("size=%lld", Info->size);
 +      DbgPrint("mode=0%o", Info->mode);
 +
 +      if (Inode &&
 +          ((Inode->i_size != Info->size) ||
 +           (Inode->i_mtime.tv_sec != Info->mtime.tv_sec) || (Inode->i_mtime.tv_nsec != Info->mtime.tv_nsec))) {
 +              DbgPrint("calling invalidate_remote_inode sz  %d %d", Inode->i_size, Info->size);
 +              DbgPrint("calling invalidate_remote_inode sec %d %d", Inode->i_mtime.tv_sec, Info->mtime.tv_sec);
 +              DbgPrint("calling invalidate_remote_inode ns  %d %d", Inode->i_mtime.tv_nsec, Info->mtime.tv_nsec);
 +
 +              if (Inode && Inode->i_mapping) {
 +                      invalidate_remote_inode(Inode);
 +              }
 +      }
 +
 +      Inode->i_mode = Info->mode;
 +      Inode->i_size = Info->size;
 +      Inode->i_atime = Info->atime;
 +      Inode->i_ctime = Info->ctime;
 +      Inode->i_mtime = Info->mtime;
 +
 +      if (Inode->i_size && Inode->i_sb->s_blocksize) {
 +
 +              /*
 +               * Filling number of blocks as in NSS filesystem.
 +               * The s_blocksize is initialized to PAGE_CACHE_SIZE in
 +               * the super block initialization.
 +               *
 +               * Update i_blocks to have the number of 512 blocks
 +               */
 +              Inode->i_blocks = (((loff_t) Info->size) + Inode->i_sb->s_blocksize - 1)
 +                  >> (loff_t) Inode->i_blkbits;
 +              Inode->i_blocks = Inode->i_blocks << (PAGE_CACHE_SHIFT - 9);
 +              Inode->i_bytes = Info->size & (Inode->i_sb->s_blocksize - 1);
 +
 +              DbgPrint("i_sb->s_blocksize=%d", Inode->i_sb->s_blocksize);
 +              DbgPrint("i_blkbits=%d", Inode->i_blkbits);
 +              DbgPrint("i_blocks=%d", Inode->i_blocks);
 +              DbgPrint("i_bytes=%d", Inode->i_bytes);
 +      }
 +}
 +
 +struct dentry *novfs_i_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 +{
 +      struct dentry *retVal = ERR_PTR(-ENOENT);
 +      struct dentry *parent;
 +      struct novfs_entry_info *info = NULL;
 +      struct inode_data *id;
 +      struct inode *inode = NULL;
 +      uid_t uid = current_euid();
 +      ino_t ino = 0;
 +      struct qstr name;
 +      char *buf;
 +
 +      buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +      if (buf) {
 +              char *path;
 +              path = novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
 +              if (path) {
 +                      DbgPrint("dir 0x%p %d hash %d inode 0x%0p %s", dir, dir->i_ino, dentry->d_name.hash, dentry->d_inode, path);
 +              }
 +              kfree(buf);
 +      } else {
 +              DbgPrint("dir 0x%p %d name %.*s hash %d inode 0x%0p",
 +                       dir, dir->i_ino, dentry->d_name.len, dentry->d_name.name, dentry->d_name.hash, dentry->d_inode);
 +      }
 +
 +      if ((dentry->d_name.len == 7)
 +          && (0 == strncmp(dentry->d_name.name, " !xover", 7))) {
 +              dentry->d_op = &novfs_dentry_operations;
 +              igrab(dir);
 +              d_add(dentry, dir);
 +              return NULL;
 +      }
 +      if ((dentry->d_name.len == 7)
 +          && (0 == strncmp(dentry->d_name.name, "z!xover", 7))) {
 +              dentry->d_op = &novfs_dentry_operations;
 +              igrab(dir);
 +              d_add(dentry, dir);
 +              return NULL;
 +      }
 +
 +      if (dir && (id = dir->i_private)) {
 +              retVal = 0;
 +              if (IS_ROOT(dentry)) {
 +                      DbgPrint("Root entry=0x%p", novfs_root);
 +                      inode = novfs_root->d_inode;
 +                      return (0);
 +              } else {
 +                      info = kmalloc(sizeof(struct novfs_entry_info) + PATH_LENGTH_BUFFER, GFP_KERNEL);
 +                      if (info) {
 +                              if (NULL == (retVal = ERR_PTR(verify_dentry(dentry, 1)))) {
 +                                      name.name = dentry->d_name.name;
 +                                      name.len = dentry->d_name.len;
 +                                      name.hash = novfs_internal_hash(&name);
 +
 +                                      if (novfs_lock_inode_cache(dir)) {
 +                                              if (!novfs_get_entry(dir, &name, &ino, info)) {
 +                                                      inode = ilookup(dentry->d_sb, ino);
 +                                                      if (inode) {
 +                                                              update_inode(inode, info);
 +                                                      }
 +                                              }
 +                                              novfs_unlock_inode_cache(dir);
 +                                      }
 +
 +                                      if (!inode && ino) {
 +                                              if (id && id->Scope) {
 +                                                      uid = novfs_scope_get_uid(id->Scope);
 +                                              } else {
 +                                                      uid = novfs_scope_get_uid(novfs_get_scope(dentry));
 +                                              }
 +                                              if (novfs_lock_inode_cache(dir)) {
 +                                                      inode = novfs_get_inode(dentry->d_sb, info->mode, 0, uid, ino, &name);
 +                                                      if (inode) {
 +                                                              if (!novfs_get_entry(dir, &dentry->d_name, &ino, info)) {
 +                                                                      update_inode(inode, info);
 +                                                              }
 +                                                      }
 +                                                      novfs_unlock_inode_cache(dir);
 +                                              }
 +                                      }
 +                              }
 +                      }
 +              }
 +      }
 +
 +      if (!retVal) {
 +              dentry->d_op = &novfs_dentry_operations;
 +              if (inode) {
 +                      parent = dget_parent(dentry);
 +                      novfs_d_add(dentry->d_parent, dentry, inode, 1);
 +                      dput(parent);
 +              } else {
 +                      d_add(dentry, inode);
 +              }
 +      }
 +
 +      if (info)
 +              kfree(info);
 +
 +      DbgPrint("inode=0x%p dentry->d_inode=0x%p return=0x%p", dir, dentry->d_inode, retVal);
 +
 +      return (retVal);
 +}
 +
 +int novfs_i_unlink(struct inode *dir, struct dentry *dentry)
 +{
 +      int retCode = -ENOENT;
 +      struct inode *inode;
 +      struct novfs_schandle session;
 +      char *path, *buf;
 +      uint64_t t64;
 +
 +      DbgPrint("dir=0x%p dir->i_ino=%d %.*s", dir, dir->i_ino, dentry->d_name.len, dentry->d_name.name);
 +      DbgPrint("IS_ROOT(dentry)=%d", IS_ROOT(dentry));
 +      DbgPrint("IS_ROOT(dentry->d_parent)=%d", IS_ROOT(dentry->d_parent));
 +      DbgPrint("IS_ROOT(dentry->d_parent->d_parent)=%d", IS_ROOT(dentry->d_parent->d_parent));
 +      DbgPrint("IS_ROOT(dentry->d_parent->d_parent->d_parent)=%d", IS_ROOT(dentry->d_parent->d_parent->d_parent));
 +
 +      if (IS_ROOT(dentry) ||  /* Root */
 +          IS_ROOT(dentry->d_parent) ||        /* User */
 +          (!IS_ROOT(dentry->d_parent->d_parent) &&    /* Server */
 +           IS_ROOT(dentry->d_parent->d_parent->d_parent))) {  /* Volume */
 +              return (-EACCES);
 +      }
 +
 +      inode = dentry->d_inode;
 +      if (inode) {
 +              DbgPrint("dir=0x%p dir->i_ino=%d inode=0x%p ino=%d", dir, dir->i_ino, inode, inode->i_ino);
 +              if (inode->i_private) {
 +                      session = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +                      if (0 == SC_PRESENT(session)) {
 +                              ((struct inode_data *)inode->i_private)->Scope = novfs_get_scope(dentry);
 +                              session = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +                      }
 +
 +                      buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +                      if (buf) {
 +                              path = novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
 +                              if (path) {
 +                                      DbgPrint("path %s mode 0%o", path, inode->i_mode);
 +                                      if (IS_ROOT(dentry->d_parent->d_parent)) {
 +                                              retCode = novfs_daemon_logout(&dentry->d_name, &session);
 +                                      } else {
 +                                              retCode = novfs_delete(path, S_ISDIR(inode->i_mode), session);
 +                                              if (retCode) {
 +                                                      struct iattr ia;
 +                                                      memset(&ia, 0, sizeof(ia));
 +                                                      ia.ia_valid = ATTR_MODE;
 +                                                      ia.ia_mode = S_IRWXU;
 +                                                      novfs_set_attr(path, &ia, session);
 +                                                      retCode = novfs_delete(path, S_ISDIR(inode->i_mode), session);
 +                                              }
 +                                      }
 +                                      if (!retCode || IS_DEADDIR(inode)) {
 +                                              novfs_remove_inode_entry(dir, &dentry->d_name, 0);
 +                                              dentry->d_time = 0;
 +                                              t64 = 0;
 +                                              novfs_scope_set_userspace(&t64, &t64, &t64, &t64);
 +                                              retCode = 0;
 +                                      }
 +                              }
 +                              kfree(buf);
 +                      }
 +              }
 +      }
 +
 +      DbgPrint("retCode 0x%x", retCode);
 +      return (retCode);
 +}
 +
 +int novfs_i_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 +{
 +      char *path, *buf;
 +      struct novfs_schandle session;
 +      int retCode = 0;
 +      struct inode *inode;
 +      struct novfs_entry_info info;
 +      uid_t uid;
 +
 +      DbgPrint("dir=0x%p ino=%d dentry=0x%p %.*s mode=0%lo",
 +               dir, dir->i_ino, dentry, dentry->d_name.len, dentry->d_name.name, mode);
 +
 +      if (IS_ROOT(dentry) ||  /* Root */
 +          IS_ROOT(dentry->d_parent) ||        /* User */
 +          IS_ROOT(dentry->d_parent->d_parent) ||      /* Server */
 +          IS_ROOT(dentry->d_parent->d_parent->d_parent)) {    /* Volume */
 +              return (-EACCES);
 +      }
 +
 +      mode |= S_IFDIR;
 +      mode &= (S_IFMT | S_IRWXU);
 +      if (dir->i_private) {
 +              session = novfs_scope_get_sessionId(((struct inode_data *)dir->i_private)->Scope);
 +              if (0 == SC_PRESENT(session)) {
 +                      ((struct inode_data *)dir->i_private)->Scope = novfs_get_scope(dentry);
 +                      session = novfs_scope_get_sessionId(((struct inode_data *)dir->i_private)->Scope);
 +              }
 +
 +              uid = novfs_scope_get_uid(((struct inode_data *)dir->i_private)->Scope);
 +              buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +              if (buf) {
 +                      path = novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
 +                      if (path) {
 +                              DbgPrint("path %s", path);
 +                              retCode = novfs_create(path, S_ISDIR(mode), session);
 +                              if (!retCode) {
 +                                      retCode = novfs_get_file_info(path, &info, session);
 +                                      if (!retCode) {
 +                                              retCode = novfs_i_mknod(dir, dentry, mode, 0);
 +                                              inode = dentry->d_inode;
 +                                              if (inode) {
 +                                                      update_inode(inode, &info);
 +                                                      ((struct inode_data *)inode->i_private)->Flags &= ~UPDATE_INODE;
 +
 +                                                      dentry->d_time = jiffies + (novfs_update_timeout * HZ);
 +
 +                                                      novfs_lock_inode_cache(dir);
 +                                                      if (novfs_update_entry(dir, &dentry->d_name, 0, &info)) {
 +                                                              novfs_add_inode_entry(dir, &dentry->d_name, inode->i_ino, &info);
 +                                                      }
 +                                                      novfs_unlock_inode_cache(dir);
 +                                              }
 +
 +                                      }
 +                              }
 +                      }
 +                      kfree(buf);
 +              }
 +      }
 +
 +      return (retCode);
 +}
 +
 +int novfs_i_rmdir(struct inode *inode, struct dentry *dentry)
 +{
 +      return (novfs_i_unlink(inode, dentry));
 +}
 +
 +int novfs_i_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 +{
 +      struct inode *inode = NULL;
 +      int retCode = -EACCES;
 +      uid_t uid;
 +      struct dentry *parent;
 +
 +      if (IS_ROOT(dentry) ||  /* Root */
 +          IS_ROOT(dentry->d_parent) ||        /* User */
 +          IS_ROOT(dentry->d_parent->d_parent) ||      /* Server */
 +          IS_ROOT(dentry->d_parent->d_parent->d_parent)) {    /* Volume */
 +              return (-EACCES);
 +      }
 +
 +      if (((struct inode_data *)dir->i_private)) {
 +              uid = novfs_scope_get_uid(((struct inode_data *)dir->i_private)->Scope);
 +              if (mode & (S_IFREG | S_IFDIR)) {
 +                      inode = novfs_get_inode(dir->i_sb, mode, dev, uid, 0, &dentry->d_name);
 +              }
 +      }
 +      if (inode) {
 +              struct novfs_entry_info info;
 +
 +              dentry->d_op = &novfs_dentry_operations;
 +              parent = dget_parent(dentry);
 +              novfs_d_add(parent, dentry, inode, 0);
 +              memset(&info, 0, sizeof(info));
 +              info.mode = inode->i_mode;
 +              novfs_lock_inode_cache(dir);
 +              novfs_add_inode_entry(dir, &dentry->d_name, inode->i_ino, &info);
 +              novfs_unlock_inode_cache(dir);
 +
 +              dput(parent);
 +
 +              retCode = 0;
 +      }
 +      DbgPrint("return 0x%x", retCode);
 +      return retCode;
 +}
 +
 +int novfs_i_rename(struct inode *odir, struct dentry *od, struct inode *ndir, struct dentry *nd)
 +{
 +      int retCode = -ENOTEMPTY;
 +      char *newpath, *newbuf, *newcon;
 +      char *oldpath, *oldbuf, *oldcon;
-       struct qstr newname, oldname;
++      struct qstr oldname;
 +      struct novfs_entry_info *info = NULL;
 +      int oldlen, newlen;
 +      struct novfs_schandle session;
 +      ino_t ino;
 +
 +      if (IS_ROOT(od) ||      /* Root */
 +          IS_ROOT(od->d_parent) ||    /* User */
 +          IS_ROOT(od->d_parent->d_parent) ||  /* Server */
 +          IS_ROOT(od->d_parent->d_parent->d_parent)) {        /* Volume */
 +              return (-EACCES);
 +      }
 +
 +      DbgPrint("odir=0x%p ino=%d ndir=0x%p ino=%d", odir, odir->i_ino, ndir, ndir->i_ino);
 +
 +      oldbuf = kmalloc(PATH_LENGTH_BUFFER * 2, GFP_KERNEL);
 +      newbuf = oldbuf + PATH_LENGTH_BUFFER;
 +      if (oldbuf && newbuf) {
 +              oldpath = novfs_dget_path(od, oldbuf, PATH_LENGTH_BUFFER);
 +              newpath = novfs_dget_path(nd, newbuf, PATH_LENGTH_BUFFER);
 +              if (oldpath && newpath) {
 +                      oldlen = PATH_LENGTH_BUFFER - (int)(oldpath - oldbuf);
 +                      newlen = PATH_LENGTH_BUFFER - (int)(newpath - newbuf);
 +
 +                      DbgPrint("od=0x%p od->inode=0x%p od->inode->i_ino=%d %s", od, od->d_inode, od->d_inode->i_ino, oldpath);
 +                      if (nd->d_inode) {
 +                              DbgPrint("nd=0x%p nd->inode=0x%p nd->inode->i_ino=%d %s",
 +                                       nd, nd->d_inode, nd->d_inode->i_ino, newpath);
 +                      } else {
 +                              DbgPrint("nd=0x%p nd->inode=0x%p %s", nd, nd->d_inode, newpath);
 +                      }
 +
 +                      /*
 +                       * Check to see if two different servers or different volumes
 +                       */
 +                      newcon = strchr(newpath + 1, '\\');
 +                      oldcon = strchr(oldpath + 1, '\\');
 +                      DbgPrint("newcon=0x%p newpath=0x%p", newcon, newpath);
 +                      DbgPrint("oldcon=0x%p oldpath=0x%p", oldcon, oldpath);
 +                      retCode = -EXDEV;
 +                      if (newcon && oldcon && ((int)(newcon - newpath) == (int)(oldcon - oldpath))) {
 +                              newcon = strchr(newcon + 1, '\\');
 +                              oldcon = strchr(oldcon + 1, '\\');
 +                              DbgPrint("2; newcon=0x%p newpath=0x%p", newcon, newpath);
 +                              DbgPrint("2; oldcon=0x%p oldpath=0x%p", oldcon, oldpath);
 +                              if (newcon && oldcon && ((int)(newcon - newpath) == (int)(oldcon - oldpath))) {
-                                       newname.name = newpath;
-                                       newname.len = (int)(newcon - newpath);
-                                       newname.hash = 0;
 +                                      oldname.name = oldpath;
 +                                      oldname.len = (int)(oldcon - oldpath);
 +                                      oldname.hash = 0;
-                                       if (!novfs_d_strcmp(&newname, &oldname)) {
++                                      if (!novfs_d_strcmp(newpath,
++                                                  newcon - newpath,
++                                                  &oldname)) {
 +
 +                                              if (od->d_inode && od->d_inode->i_private) {
 +
 +                                                      if (nd->d_inode && nd->d_inode->i_private) {
 +                                                              session =
 +                                                                  novfs_scope_get_sessionId
 +                                                                  (((struct inode_data *)ndir->i_private)->Scope);
 +                                                              if (0 == SC_PRESENT(session)) {
 +                                                                      ((struct inode_data *)ndir->i_private)->Scope =
 +                                                                          novfs_get_scope(nd);
 +                                                                      session =
 +                                                                          novfs_scope_get_sessionId(((struct inode_data *)ndir->
 +                                                                                                     i_private)->Scope);
 +                                                              }
 +
 +                                                              retCode =
 +                                                                  novfs_delete(newpath, S_ISDIR(nd->d_inode->i_mode), session);
 +                                                              if (retCode) {
 +                                                                      struct iattr ia;
 +                                                                      memset(&ia, 0, sizeof(ia));
 +                                                                      ia.ia_valid = ATTR_MODE;
 +                                                                      ia.ia_mode = S_IRWXU;
 +                                                                      novfs_set_attr(newpath, &ia, session);
 +                                                                      retCode =
 +                                                                          novfs_delete(newpath, S_ISDIR(nd->d_inode->i_mode),
 +                                                                                       session);
 +                                                              }
 +
 +                                                      }
 +
 +                                                      session =
 +                                                          novfs_scope_get_sessionId(((struct inode_data *)ndir->i_private)->
 +                                                                                    Scope);
 +                                                      if (0 == SC_PRESENT(session)) {
 +                                                              ((struct inode_data *)ndir->i_private)->Scope = novfs_get_scope(nd);
 +                                                              session =
 +                                                                  novfs_scope_get_sessionId(((struct inode_data *)ndir->
 +                                                                                             i_private)->Scope);
 +                                                      }
 +                                                      retCode =
 +                                                          novfs_rename_file(S_ISDIR(od->d_inode->i_mode), oldpath, oldlen - 1,
 +                                                                            newpath, newlen - 1, session);
 +
 +                                                      if (!retCode) {
 +                                                              info = (struct novfs_entry_info *)oldbuf;
 +                                                              od->d_time = 0;
 +                                                              novfs_remove_inode_entry(odir, &od->d_name, 0);
 +                                                              novfs_remove_inode_entry(ndir, &nd->d_name, 0);
 +                                                              novfs_get_file_info(newpath, info, session);
 +                                                              nd->d_time = jiffies + (novfs_update_timeout * HZ);
 +
 +                                                              if (od->d_inode && od->d_inode->i_ino) {
 +                                                                      ino = od->d_inode->i_ino;
 +                                                              } else {
 +                                                                      ino = (ino_t) atomic_inc_return(&novfs_Inode_Number);
 +                                                              }
 +                                                              novfs_add_inode_entry(ndir, &nd->d_name, ino, info);
 +                                                      }
 +                                              }
 +                                      }
 +                              }
 +                      }
 +              }
 +      }
 +
 +      if (oldbuf)
 +              kfree(oldbuf);
 +
 +      DbgPrint("return %d", retCode);
 +      return (retCode);
 +}
 +
 +int novfs_i_setattr(struct dentry *dentry, struct iattr *attr)
 +{
 +      char *path, *buf;
 +      struct inode *inode = dentry->d_inode;
 +      char atime_buf[32];
 +      char mtime_buf[32];
 +      char ctime_buf[32];
 +      unsigned int ia_valid = attr->ia_valid;
 +      struct novfs_schandle session;
 +      int retVal = 0;
 +
 +      if (IS_ROOT(dentry) ||  /* Root */
 +          IS_ROOT(dentry->d_parent) ||        /* User */
 +          IS_ROOT(dentry->d_parent->d_parent) ||      /* Server */
 +          IS_ROOT(dentry->d_parent->d_parent->d_parent)) {    /* Volume */
 +              return (-EACCES);
 +      }
 +
 +      if (inode && inode->i_private) {
 +              session = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +              if (0 == SC_PRESENT(session)) {
 +                      ((struct inode_data *)inode->i_private)->Scope = novfs_get_scope(dentry);
 +                      session = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +              }
 +
 +              buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +              if (buf) {
 +                      path = novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
 +                      if (path) {
 +                              strcpy(atime_buf, "Unspecified");
 +                              strcpy(mtime_buf, "Unspecified");
 +                              strcpy(ctime_buf, "Unspecified");
 +                              if (attr->ia_valid & ATTR_ATIME) {
 +                                      ctime_r(&attr->ia_atime.tv_sec, atime_buf);
 +                              }
 +                              if (attr->ia_valid & ATTR_MTIME) {
 +                                      ctime_r(&attr->ia_mtime.tv_sec, mtime_buf);
 +                              }
 +                              if (attr->ia_valid & ATTR_CTIME) {
 +                                      ctime_r(&attr->ia_ctime.tv_sec, ctime_buf);
 +                              }
 +                              /* Removed for Bug 132374. jlt */
 +                              __DbgPrint("%s: %s\n"
 +                                         "   ia_valid:      0x%x\n"
 +                                         "   ia_mode:       0%o\n"
 +                                         "   ia_uid:        %d\n"
 +                                         "   ia_gid:        %d\n"
 +                                         "   ia_size:       %lld\n"
 +                                         "   ia_atime:      %s\n"
 +                                         "   ia_mtime:      %s\n"
 +                                         "   ia_ctime:      %s\n", __func__,
 +                                         path,
 +                                         attr->ia_valid,
 +                                         attr->ia_mode,
 +                                         attr->ia_uid, attr->ia_gid, attr->ia_size, atime_buf, mtime_buf, ctime_buf);
 +
 +                              if (ia_valid && !(retVal = novfs_set_attr(path, attr, session))) {
 +                                      ((struct inode_data *)inode->i_private)->Flags |= UPDATE_INODE;
 +
 +                                      if (ia_valid & ATTR_ATIME)
 +                                              inode->i_atime = attr->ia_atime;
 +                                      if (ia_valid & ATTR_MTIME)
 +                                              inode->i_mtime = attr->ia_mtime;
 +                                      if (ia_valid & ATTR_CTIME)
 +                                              inode->i_ctime = attr->ia_ctime;
 +                                      if (ia_valid & ATTR_MODE) {
 +                                              inode->i_mode = attr->ia_mode & (S_IFMT | S_IRWXU);
 +                                      }
 +                              }
 +                      }
 +              }
 +              kfree(buf);
 +      }
 +      DbgPrint("return 0x%x", retVal);
 +
 +      return (retVal);
 +}
 +
 +int novfs_i_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *kstat)
 +{
 +      int retCode = 0;
 +      char atime_buf[32];
 +      char mtime_buf[32];
 +      char ctime_buf[32];
 +      struct inode *inode = dentry->d_inode;
 +
 +      struct novfs_entry_info info;
 +      char *path, *buf;
 +      struct novfs_schandle session;
 +      struct inode_data *id;
 +
 +      if (!IS_ROOT(dentry) && !IS_ROOT(dentry->d_parent)) {
 +              SC_INITIALIZE(session);
 +              id = dentry->d_inode->i_private;
 +
 +              if (id && (id->Flags & UPDATE_INODE)) {
 +                      session = novfs_scope_get_sessionId(id->Scope);
 +
 +                      if (0 == SC_PRESENT(session)) {
 +                              id->Scope = novfs_get_scope(dentry);
 +                              session = novfs_scope_get_sessionId(id->Scope);
 +                      }
 +
 +                      buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +                      if (buf) {
 +                              path = novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
 +                              if (path) {
 +                                      retCode = novfs_get_file_info(path, &info, session);
 +                                      if (!retCode) {
 +                                              update_inode(inode, &info);
 +                                              id->Flags &= ~UPDATE_INODE;
 +                                      }
 +                              }
 +                              kfree(buf);
 +                      }
 +              }
 +      }
 +
 +      kstat->ino = inode->i_ino;
 +      kstat->dev = inode->i_sb->s_dev;
 +      kstat->mode = inode->i_mode;
 +      kstat->nlink = inode->i_nlink;
 +      kstat->uid = inode->i_uid;
 +      kstat->gid = inode->i_gid;
 +      kstat->rdev = inode->i_rdev;
 +      kstat->size = i_size_read(inode);
 +      kstat->atime = inode->i_atime;
 +      kstat->mtime = inode->i_mtime;
 +      kstat->ctime = inode->i_ctime;
 +      kstat->blksize = inode->i_sb->s_blocksize;
 +      kstat->blocks = inode->i_blocks;
 +      if (inode->i_bytes) {
 +              kstat->blocks++;
 +      }
 +      ctime_r(&kstat->atime.tv_sec, atime_buf);
 +      ctime_r(&kstat->mtime.tv_sec, mtime_buf);
 +      ctime_r(&kstat->ctime.tv_sec, ctime_buf);
 +
 +      __DbgPrint("%s: 0x%x 0x%p <%.*s>\n"
 +                 "   ino: %d\n"
 +                 "   dev: 0x%x\n"
 +                 "   mode: 0%o\n"
 +                 "   nlink: 0x%x\n"
 +                 "   uid: 0x%x\n"
 +                 "   gid: 0x%x\n"
 +                 "   rdev: 0x%x\n"
 +                 "   size: 0x%llx\n"
 +                 "   atime: %s\n"
 +                 "   mtime: %s\n"
 +                 "   ctime: %s\n"
 +                 "   blksize: 0x%x\n"
 +                 "   blocks: 0x%x\n", __func__,
 +                 retCode, dentry, dentry->d_name.len, dentry->d_name.name,
 +                 kstat->ino,
 +                 kstat->dev,
 +                 kstat->mode,
 +                 kstat->nlink,
 +                 kstat->uid,
 +                 kstat->gid, kstat->rdev, kstat->size, atime_buf, mtime_buf, ctime_buf, kstat->blksize, kstat->blocks);
 +      return (retCode);
 +}
 +
 +ssize_t novfs_i_getxattr(struct dentry * dentry, const char *name, void *buffer, size_t buffer_size)
 +{
 +      struct inode *inode = dentry->d_inode;
 +      struct novfs_schandle sessionId;
 +      char *path, *buf, *bufRead;
 +      ssize_t dataLen;
 +
 +      int retxcode = 0;
 +
 +      SC_INITIALIZE(sessionId);
 +
 +      DbgPrint("Ian");        /*%.*s\n", dentry->d_name.len, dentry->d_name.name); */
 +      DbgPrint("dentry->d_name.len %u, dentry->d_name.name %s", dentry->d_name.len, dentry->d_name.name);
 +      DbgPrint("name %s", name);
 +      DbgPrint("size %u", buffer_size);
 +
 +      if (inode && inode->i_private) {
 +              sessionId = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +              DbgPrint("SessionId = %u", sessionId);
 +              //if (0 == sessionId)
 +              if (0 == SC_PRESENT(sessionId)) {
 +                      ((struct inode_data *)inode->i_private)->Scope = novfs_get_scope(dentry);
 +                      sessionId = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +                      DbgPrint("SessionId = %u", sessionId);
 +              }
 +      }
 +
 +      dataLen = 0;
 +      buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +      if (buf) {
 +              path = novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
 +              if (path) {
 +                      bufRead = kmalloc(XA_BUFFER, GFP_KERNEL);
 +                      if (bufRead) {
 +                              retxcode = novfs_getx_file_info(path, name, bufRead, XA_BUFFER, &dataLen, sessionId);
 +                              DbgPrint("after novfs_GetX_File_Info retxcode = %d", retxcode);
 +                              if (!retxcode) {
 +                                      novfs_dump(64, bufRead);
 +                                      if (buffer_size != 0) {
 +                                              if (buffer_size >= dataLen) {
 +                                                      memcpy(buffer, bufRead, dataLen);
 +                                              } else {
 +                                                      DbgPrint("(!!!) not enough buffer_size. buffer_size = %d, dataLen = %d",
 +                                                               buffer_size, dataLen);
 +                                                      retxcode = -ERANGE;
 +                                              }
 +                                      }
 +                              }
 +                              kfree(bufRead);
 +                      }
 +              }
 +              kfree(buf);
 +      }
 +
 +      if (retxcode) {
 +              dataLen = retxcode;
 +      } else {
 +              if ((buffer_size > 0) && (buffer_size < dataLen)) {
 +                      dataLen = -ERANGE;
 +              }
 +      }
 +
 +      return (dataLen);
 +}
 +
 +int novfs_i_setxattr(struct dentry *dentry, const char *name, const void *value, size_t value_size, int flags)
 +{
 +
 +      struct inode *inode = dentry->d_inode;
 +      struct novfs_schandle sessionId;
 +      char *path, *buf;
 +      unsigned long bytesWritten = 0;
 +      int retError = 0;
 +      int retxcode = 0;
 +
 +      SC_INITIALIZE(sessionId);
 +
 +      DbgPrint("Ian");        /*%.*s\n", dentry->d_name.len, dentry->d_name.name); */
 +      DbgPrint("dentry->d_name.len %u, dentry->d_name.name %s", dentry->d_name.len, dentry->d_name.name);
 +      DbgPrint("name %s", name);
 +      DbgPrint("value_size %u", value_size);
 +      DbgPrint("flags %d", flags);
 +
 +      if (inode && inode->i_private) {
 +              sessionId = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +              DbgPrint("SessionId = %u", sessionId);
 +              //if (0 == sessionId)
 +              if (0 == SC_PRESENT(sessionId)) {
 +                      ((struct inode_data *)inode->i_private)->Scope = novfs_get_scope(dentry);
 +                      sessionId = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +                      DbgPrint("SessionId = %u", sessionId);
 +              }
 +      }
 +
 +      buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +      if (buf) {
 +              path = novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
 +              if (path) {
 +                      retxcode = novfs_setx_file_info(path, name, value, value_size, &bytesWritten, flags, sessionId);
 +                      if (!retxcode) {
 +                              DbgPrint("bytesWritten = %u", bytesWritten);
 +                      }
 +              }
 +              kfree(buf);
 +      }
 +
 +      if (retxcode) {
 +              retError = retxcode;
 +      }
 +
 +      if (bytesWritten < value_size) {
 +              retError = retxcode;
 +      }
 +      return (retError);
 +}
 +
 +ssize_t novfs_i_listxattr(struct dentry * dentry, char *buffer, size_t buffer_size)
 +{
 +      struct inode *inode = dentry->d_inode;
 +      struct novfs_schandle sessionId;
 +      char *path, *buf, *bufList;
 +      ssize_t dataLen;
 +      int retxcode = 0;
 +
 +      SC_INITIALIZE(sessionId);
 +
 +      DbgPrint("Ian");        //%.*s\n", dentry->d_name.len, dentry->d_name.name);
 +      DbgPrint("dentry->d_name.len %u, dentry->d_name.name %s", dentry->d_name.len, dentry->d_name.name);
 +      DbgPrint("size %u", buffer_size);
 +
 +      if (inode && inode->i_private) {
 +              sessionId = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +              DbgPrint("SessionId = %u", sessionId);
 +              //if (0 == sessionId)
 +              if (0 == SC_PRESENT(sessionId)) {
 +                      ((struct inode_data *)inode->i_private)->Scope = novfs_get_scope(dentry);
 +                      sessionId = novfs_scope_get_sessionId(((struct inode_data *)inode->i_private)->Scope);
 +                      DbgPrint("SessionId = %u", sessionId);
 +              }
 +      }
 +
 +      dataLen = 0;
 +      buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +      if (buf) {
 +              path = novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER);
 +              if (path) {
 +                      bufList = kmalloc(XA_BUFFER, GFP_KERNEL);
 +                      if (bufList) {
 +                              retxcode = novfs_listx_file_info(path, bufList, XA_BUFFER, &dataLen, sessionId);
 +
 +                              novfs_dump(64, bufList);
 +                              if (buffer_size != 0) {
 +                                      if (buffer_size >= dataLen) {
 +                                              memcpy(buffer, bufList, dataLen);
 +                                      } else {
 +                                              DbgPrint("(!!!) not enough buffer_size. buffer_size = %d, dataLen = %d",
 +                                                       buffer_size, dataLen);
 +                                              retxcode = -1;
 +                                      }
 +                              }
 +
 +                              if (bufList) {
 +                                      kfree(bufList);
 +                              }
 +                      }
 +
 +              }
 +              kfree(buf);
 +      }
 +
 +      if (retxcode) {
 +              dataLen = -1;
 +      } else {
 +
 +              if ((buffer_size > 0) && (buffer_size < dataLen)) {
 +                      dataLen = -ERANGE;
 +              }
 +      }
 +      return (dataLen);
 +}
 +
 +int novfs_i_revalidate(struct dentry *dentry)
 +{
 +
 +      DbgPrint("name %.*s", dentry->d_name.len, dentry->d_name.name);
 +
 +      return (0);
 +}
 +
 +void novfs_read_inode(struct inode *inode)
 +{
 +      DbgPrint("0x%p %d", inode, inode->i_ino);
 +}
 +
 +void novfs_write_inode(struct inode *inode)
 +{
 +      DbgPrint("Inode=0x%p Ino=%d", inode, inode->i_ino);
 +}
 +
 +int novfs_notify_change(struct dentry *dentry, struct iattr *attr)
 +{
 +      struct inode *inode = dentry->d_inode;
 +
 +      DbgPrint("Dentry=0x%p Name=%.*s Inode=0x%p Ino=%d ia_valid=0x%x",
 +               dentry, dentry->d_name.len, dentry->d_name.name, inode, inode->i_ino, attr->ia_valid);
 +      return (0);
 +}
 +
 +void novfs_evict_inode(struct inode *inode)
 +{
 +      truncate_inode_pages(&inode->i_data, 0);
 +      end_writeback(inode);
 +
 +      InodeCount--;
 +
 +      if (inode->i_private) {
 +              struct inode_data *id = inode->i_private;
 +
 +              DbgPrint("inode=0x%p ino=%d Scope=0x%p Name=%s", inode, inode->i_ino, id->Scope, id->Name);
 +
 +              novfs_free_inode_cache(inode);
 +
 +              mutex_lock(&InodeList_lock);
 +              list_del(&id->IList);
 +              mutex_unlock(&InodeList_lock);
 +
 +              kfree(inode->i_private);
 +              inode->i_private = NULL;
 +
 +              remove_inode_hash(inode);
 +
 +      } else {
 +              DbgPrint("inode=0x%p ino=%d", inode, inode->i_ino);
 +      }
 +}
 +
 +/* Called when /proc/mounts is read */
 +int novfs_show_options(struct seq_file *s, struct vfsmount *m)
 +{
 +      char *buf, *path, *tmp;
 +
 +      buf = kmalloc(PATH_LENGTH_BUFFER, GFP_KERNEL);
 +      if (buf) {
 +              struct path my_path;
 +              my_path.mnt = m;
 +              my_path.dentry = m->mnt_root;
 +              path = d_path(&my_path, buf, PATH_LENGTH_BUFFER);
 +              if (path) {
 +                      if (!novfs_current_mnt || (novfs_current_mnt && strcmp(novfs_current_mnt, path))) {
 +                              DbgPrint("%.*s %.*s %s",
 +                                       m->mnt_root->d_name.len,
 +                                       m->mnt_root->d_name.name,
 +                                       m->mnt_mountpoint->d_name.len, m->mnt_mountpoint->d_name.name, path);
 +                              tmp = kmalloc(PATH_LENGTH_BUFFER - (int)(path - buf), GFP_KERNEL);
 +                              if (tmp) {
 +                                      strcpy(tmp, path);
 +                                      path = novfs_current_mnt;
 +                                      novfs_current_mnt = tmp;
 +                                      novfs_daemon_set_mnt_point(novfs_current_mnt);
 +
 +                                      if (path) {
 +                                              kfree(path);
 +                                      }
 +                              }
 +                      }
 +              }
 +              kfree(buf);
 +      }
 +      return (0);
 +}
 +
 +/*   Called when statfs(2) system called. */
 +int novfs_statfs(struct dentry *de, struct kstatfs *buf)
 +{
 +      uint64_t td, fd, te, fe;
 +      struct super_block *sb = de->d_sb;
 +
 +      DbgPrint("");
 +
 +      td = fd = te = fe = 0;
 +
 +      novfs_scope_get_userspace(&td, &fd, &te, &fe);
 +
 +      DbgPrint("td=%llu", td);
 +      DbgPrint("fd=%llu", fd);
 +      DbgPrint("te=%llu", te);
 +      DbgPrint("fe=%llu", fd);
 +      /* fix for Nautilus */
 +      if (sb->s_blocksize == 0)
 +              sb->s_blocksize = 4096;
 +
 +      buf->f_type = sb->s_magic;
 +      buf->f_bsize = sb->s_blocksize;
 +      buf->f_namelen = NW_MAX_PATH_LENGTH;
 +      buf->f_blocks = (sector_t) (td + (uint64_t) (sb->s_blocksize - 1)) >> (uint64_t) sb->s_blocksize_bits;
 +      buf->f_bfree = (sector_t) fd >> (uint64_t) sb->s_blocksize_bits;
 +      buf->f_bavail = (sector_t) buf->f_bfree;
 +      buf->f_files = (sector_t) te;
 +      buf->f_ffree = (sector_t) fe;
 +      buf->f_frsize = sb->s_blocksize;
 +      if (te > 0xffffffff)
 +              buf->f_files = 0xffffffff;
 +
 +      if (fe > 0xffffffff)
 +              buf->f_ffree = 0xffffffff;
 +
 +      DbgPrint("f_type:    0x%x", buf->f_type);
 +      DbgPrint("f_bsize:   %u", buf->f_bsize);
 +      DbgPrint("f_namelen: %d", buf->f_namelen);
 +      DbgPrint("f_blocks:  %llu", buf->f_blocks);
 +      DbgPrint("f_bfree:   %llu", buf->f_bfree);
 +      DbgPrint("f_bavail:  %llu", buf->f_bavail);
 +      DbgPrint("f_files:   %llu", buf->f_files);
 +      DbgPrint("f_ffree:   %llu", buf->f_ffree);
 +      DbgPrint("f_frsize:  %u", buf->f_frsize);
 +
 +      return 0;
 +}
 +
 +struct inode *novfs_get_inode(struct super_block *sb, int mode, int dev, uid_t Uid, ino_t ino, struct qstr *name)
 +{
 +      struct inode *inode = new_inode(sb);
 +
 +      if (inode) {
 +              InodeCount++;
 +              inode->i_mode = mode;
 +              inode->i_uid = Uid;
 +              inode->i_gid = 0;
 +              inode->i_blkbits = sb->s_blocksize_bits;
 +              inode->i_blocks = 0;
 +              inode->i_rdev = 0;
 +              inode->i_ino = (ino) ? ino : (ino_t) atomic_inc_return(&novfs_Inode_Number);
 +              if (novfs_page_cache) {
 +                      inode->i_mapping->a_ops = &novfs_aops;
 +              } else {
 +                      inode->i_mapping->a_ops = &novfs_nocache_aops;
 +              }
 +              inode->i_mapping->backing_dev_info = &novfs_backing_dev_info;
 +              inode->i_atime.tv_sec = 0;
 +              inode->i_atime.tv_nsec = 0;
 +              inode->i_mtime = inode->i_ctime = inode->i_atime;
 +
 +              DbgPrint("Inode=0x%p I_ino=%d len=%d", inode, inode->i_ino, name->len);
 +
 +              if (NULL != (inode->i_private = kmalloc(sizeof(struct inode_data) + name->len, GFP_KERNEL))) {
 +                      struct inode_data *id;
 +                      id = inode->i_private;
 +
 +                      DbgPrint("i_private 0x%p", id);
 +
 +                      id->Scope = NULL;
 +                      id->Flags = 0;
 +                      id->Inode = inode;
 +
 +                      id->cntDC = 1;
 +
 +                      INIT_LIST_HEAD(&id->DirCache);
 +                      mutex_init(&id->DirCacheLock);
 +
 +                      id->FileHandle = 0;
 +                      id->CacheFlag = 0;
 +
 +                      mutex_lock(&InodeList_lock);
 +
 +                      list_add_tail(&id->IList, &InodeList);
 +                      mutex_unlock(&InodeList_lock);
 +
 +                      id->Name[0] = '\0';
 +
 +                      memcpy(id->Name, name->name, name->len);
 +                      id->Name[name->len] = '\0';
 +
 +                      DbgPrint("name %s", id->Name);
 +              }
 +
 +              insert_inode_hash(inode);
 +
 +              switch (mode & S_IFMT) {
 +
 +              case S_IFREG:
 +                      inode->i_op = &novfs_file_inode_operations;
 +                      inode->i_fop = &novfs_file_operations;
 +                      break;
 +
 +              case S_IFDIR:
 +                      inode->i_op = &novfs_inode_operations;
 +                      inode->i_fop = &novfs_dir_operations;
 +                      inode->i_blkbits = 0;
 +                      break;
 +
 +              default:
 +                      init_special_inode(inode, mode, dev);
 +                      break;
 +              }
 +
 +              DbgPrint("size=%lld", inode->i_size);
 +              DbgPrint("mode=0%o", inode->i_mode);
 +              DbgPrint("i_sb->s_blocksize=%d", inode->i_sb->s_blocksize);
 +              DbgPrint("i_blkbits=%d", inode->i_blkbits);
 +              DbgPrint("i_blocks=%d", inode->i_blocks);
 +              DbgPrint("i_bytes=%d", inode->i_bytes);
 +      }
 +
 +      DbgPrint("0x%p %d", inode, inode->i_ino);
 +      return (inode);
 +}
 +
 +int novfs_fill_super(struct super_block *SB, void *Data, int Silent)
 +{
 +      struct inode *inode;
 +      struct dentry *server, *tree;
 +      struct qstr name;
 +      struct novfs_entry_info info;
 +
 +      SB->s_blocksize = PAGE_CACHE_SIZE;
 +      SB->s_blocksize_bits = PAGE_CACHE_SHIFT;
 +      SB->s_maxbytes = MAX_LFS_FILESIZE;      /* Max file size */
 +      SB->s_op = &novfs_ops;
 +      SB->s_flags |= (MS_NODIRATIME | MS_NODEV | MS_POSIXACL);
 +      SB->s_magic = NOVFS_MAGIC;
 +
 +      name.len = 1;
 +      name.name = "/";
 +
 +      inode = novfs_get_inode(SB, S_IFDIR | 0777, 0, 0, 0, &name);
 +      if (!inode) {
 +              return (-ENOMEM);
 +      }
 +
 +      novfs_root = d_alloc_root(inode);
 +
 +      if (!novfs_root) {
 +              iput(inode);
 +              return (-ENOMEM);
 +      }
 +      novfs_root->d_time = jiffies + (novfs_update_timeout * HZ);
 +
 +      inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
 +
 +      SB->s_root = novfs_root;
 +
 +      DbgPrint("root 0x%p", novfs_root);
 +
 +      if (novfs_root) {
 +              novfs_root->d_op = &novfs_dentry_operations;
 +
 +              name.name = SERVER_DIRECTORY_NAME;
 +              name.len = strlen(SERVER_DIRECTORY_NAME);
 +              name.hash = novfs_internal_hash(&name);
 +
 +              inode = novfs_get_inode(SB, S_IFDIR | 0777, 0, 0, 0, &name);
 +              if (inode) {
 +                      info.mode = inode->i_mode;
 +                      info.namelength = 0;
 +                      inode->i_size = info.size = 0;
 +                      inode->i_uid = info.uid = 0;
 +                      inode->i_gid = info.gid = 0;
 +                      inode->i_atime = info.atime = inode->i_ctime = info.ctime = inode->i_mtime = info.mtime = CURRENT_TIME;
 +
 +                      server = d_alloc(novfs_root, &name);
 +                      if (server) {
 +                              server->d_op = &novfs_dentry_operations;
 +                              server->d_time = 0xffffffff;
 +                              d_add(server, inode);
 +                              DbgPrint("d_add %s 0x%p", SERVER_DIRECTORY_NAME, server);
 +                              novfs_add_inode_entry(novfs_root->d_inode, &name, inode->i_ino, &info);
 +                      }
 +              }
 +
 +              name.name = TREE_DIRECTORY_NAME;
 +              name.len = strlen(TREE_DIRECTORY_NAME);
 +              name.hash = novfs_internal_hash(&name);
 +
 +              inode = novfs_get_inode(SB, S_IFDIR | 0777, 0, 0, 0, &name);
 +              if (inode) {
 +                      info.mode = inode->i_mode;
 +                      info.namelength = 0;
 +                      inode->i_size = info.size = 0;
 +                      inode->i_uid = info.uid = 0;
 +                      inode->i_gid = info.gid = 0;
 +                      inode->i_atime = info.atime = inode->i_ctime = info.ctime = inode->i_mtime = info.mtime = CURRENT_TIME;
 +                      tree = d_alloc(novfs_root, &name);
 +                      if (tree) {
 +                              tree->d_op = &novfs_dentry_operations;
 +                              tree->d_time = 0xffffffff;
 +
 +                              d_add(tree, inode);
 +                              DbgPrint("d_add %s 0x%p", TREE_DIRECTORY_NAME, tree);
 +                              novfs_add_inode_entry(novfs_root->d_inode, &name, inode->i_ino, &info);
 +                      }
 +              }
 +      }
 +
 +      return (0);
 +}
 +
 +static int novfs_get_sb(struct file_system_type *Fstype, int Flags, const char *Dev_name, void *Data, struct vfsmount *Mnt)
 +{
 +      DbgPrint("Fstype=0x%x Dev_name=%s", Fstype, Dev_name);
 +      return get_sb_nodev(Fstype, Flags, Data, novfs_fill_super, Mnt);
 +}
 +
 +static void novfs_kill_sb(struct super_block *super)
 +{
 +      shrink_dcache_sb(super);
 +      kill_litter_super(super);
 +}
 +
 +/* This should be removed */
 +#ifndef kernel_locked
 +#define kernel_locked() (current->lock_depth >= 0)
 +#endif
 +
 +ssize_t novfs_Control_read(struct file *file, char *buf, size_t nbytes, loff_t * ppos)
 +{
 +      ssize_t retval = 0;
 +
 +      DbgPrint("kernel_locked 0x%x", kernel_locked());
 +
 +      return retval;
 +}
 +
 +ssize_t novfs_Control_write(struct file * file, const char *buf, size_t nbytes, loff_t * ppos)
 +{
 +      ssize_t retval = 0;
 +
 +      DbgPrint("kernel_locked 0x%x", kernel_locked());
 +      if (buf && nbytes) {
 +      }
 +
 +      return (retval);
 +}
 +
 +static struct file_system_type novfs_fs_type = {
 +      .name = "novfs",
 +      .get_sb = novfs_get_sb,
 +      .kill_sb = novfs_kill_sb,
 +      .owner = THIS_MODULE,
 +};
 +
 +int __init init_novfs(void)
 +{
 +      int retCode;
 +
 +      lastDir[0] = 0;
 +      lastTime = get_nanosecond_time();
 +
 +      inHAX = 0;
 +      inHAXTime = get_nanosecond_time();
 +
 +      retCode = bdi_init(&novfs_backing_dev_info);
 +
 +      if (!retCode)
 +              retCode = bdi_register(&novfs_backing_dev_info, NULL, "novfs-map");
 +      if (retCode) {
 +              bdi_destroy(&novfs_backing_dev_info);
 +              goto bdi_fail;
 +      }
 +
 +      retCode = novfs_proc_init();
 +
 +      novfs_profile_init();
 +
 +      if (!retCode) {
 +              DbgPrint("%s %s %s", __DATE__, __TIME__, NOVFS_VERSION_STRING);
 +              novfs_daemon_queue_init();
 +              novfs_scope_init();
 +              retCode = register_filesystem(&novfs_fs_type);
 +              if (retCode) {
 +                      novfs_proc_exit();
 +                      novfs_daemon_queue_exit();
 +                      novfs_scope_exit();
 +              }
 +      }
 +
 +bdi_fail:
 +      return (retCode);
 +}
 +
 +void __exit exit_novfs(void)
 +{
 +      novfs_scope_exit();
 +      novfs_daemon_queue_exit();
 +      novfs_profile_exit();
 +      novfs_proc_exit();
 +      unregister_filesystem(&novfs_fs_type);
 +
 +      if (novfs_current_mnt) {
 +              kfree(novfs_current_mnt);
 +              novfs_current_mnt = NULL;
 +      }
 +
 +      bdi_destroy(&novfs_backing_dev_info);
 +}
 +
 +int novfs_lock_inode_cache(struct inode *i)
 +{
 +      struct inode_data *id;
 +      int retVal = 0;
 +
 +      DbgPrint("0x%p", i);
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +              mutex_lock(&id->DirCacheLock);
 +              retVal = 1;
 +      }
 +      DbgPrint("return %d", retVal);
 +      return (retVal);
 +}
 +
 +void novfs_unlock_inode_cache(struct inode *i)
 +{
 +      struct inode_data *id;
 +
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +              mutex_unlock(&id->DirCacheLock);
 +      }
 +}
 +
 +int novfs_enumerate_inode_cache(struct inode *i, struct list_head **iteration, ino_t * ino, struct novfs_entry_info *info)
 +/*
 + *  Arguments:   struct inode *i - pointer to directory inode
 + *
 + *  Returns:     0 - item found
 + *              -1 - done
 + *
 + *  Abstract:    Unlocks inode cache.
 + *
 + *  Notes:       DirCacheLock should be held before calling this routine.
 + *========================================================================*/
 +{
 +      struct inode_data *id;
 +      struct novfs_dir_cache *dc;
 +      struct list_head *l = NULL;
 +      int retVal = -1;
 +
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +              if ((NULL == iteration) || (NULL == *iteration)) {
 +                      l = id->DirCache.next;
 +              } else {
 +                      l = *iteration;
 +              }
 +
 +              if (l == &id->DirCache) {
 +                      l = NULL;
 +              } else {
 +                      dc = list_entry(l, struct novfs_dir_cache, list);
 +
 +                      *ino = dc->ino;
 +                      info->type = 0;
 +                      info->mode = dc->mode;
 +                      info->size = dc->size;
 +                      info->atime = dc->atime;
 +                      info->mtime = dc->mtime;
 +                      info->ctime = dc->ctime;
 +                      info->namelength = dc->nameLen;
 +                      memcpy(info->name, dc->name, dc->nameLen);
 +                      info->name[dc->nameLen] = '\0';
 +                      retVal = 0;
 +
 +                      l = l->next;
 +              }
 +      }
 +      *iteration = l;
 +      return (retVal);
 +}
 +
 +/* DirCacheLock should be held before calling this routine. */
 +int novfs_get_entry(struct inode *i, struct qstr *name, ino_t * ino, struct novfs_entry_info *info)
 +{
 +      struct inode_data *id;
 +      struct novfs_dir_cache *dc;
 +      int retVal = -1;
 +      char *n = "<NULL>";
 +      int nl = 6;
 +
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +              if (name && name->len) {
 +                      n = (char *)name->name;
 +                      nl = name->len;
 +              }
 +
 +              dc = novfs_lookup_inode_cache(i, name, *ino);
 +              if (dc) {
 +                      dc->flags |= ENTRY_VALID;
 +                      retVal = 0;
 +                      *ino = dc->ino;
 +                      info->type = 0;
 +                      info->mode = dc->mode;
 +                      info->size = dc->size;
 +                      info->atime = dc->atime;
 +                      info->mtime = dc->mtime;
 +                      info->ctime = dc->ctime;
 +                      info->namelength = dc->nameLen;
 +                      memcpy(info->name, dc->name, dc->nameLen);
 +                      info->name[dc->nameLen] = '\0';
 +                      retVal = 0;
 +              }
 +
 +              DbgPrint("inode: 0x%p; name: %.*s; ino: %d\n", i, nl, n, *ino);
 +      }
 +      DbgPrint("return %d", retVal);
 +      return (retVal);
 +}
 +
 + /*DirCacheLock should be held before calling this routine. */
 +int novfs_get_entry_by_pos(struct inode *i, loff_t pos, ino_t * ino, struct novfs_entry_info *info)
 +{
 +      int retVal = -1;
 +      loff_t count = 0;
 +      loff_t i_pos = pos - 2;
 +      struct list_head *inter = NULL;
 +      while (!novfs_enumerate_inode_cache(i, &inter, ino, info)) {
 +              DbgPrint("info->name = %s", info->name);
 +              if (count == i_pos) {
 +                      retVal = 0;
 +                      break;
 +              } else
 +                      count++;
 +      }
 +
 +      return retVal;
 +}
 +
 +/* DirCacheLock should be held before calling this routine. */
 +int novfs_get_entry_time(struct inode *i, struct qstr *name, ino_t * ino, struct novfs_entry_info *info, u64 * EntryTime)
 +{
 +      struct inode_data *id;
 +      struct novfs_dir_cache *dc;
 +      int retVal = -1;
 +      char *n = "<NULL>";
 +      int nl = 6;
 +
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +              if (name && name->len) {
 +                      n = (char *)name->name;
 +                      nl = name->len;
 +              }
 +              DbgPrint("inode: 0x%p; name:  %.*s; ino: %d", i, nl, n, *ino);
 +
 +              dc = novfs_lookup_inode_cache(i, name, *ino);
 +              if (dc) {
 +                      retVal = 0;
 +                      *ino = dc->ino;
 +                      info->type = 0;
 +                      info->mode = dc->mode;
 +                      info->size = dc->size;
 +                      info->atime = dc->atime;
 +                      info->mtime = dc->mtime;
 +                      info->ctime = dc->ctime;
 +                      info->namelength = dc->nameLen;
 +                      memcpy(info->name, dc->name, dc->nameLen);
 +                      info->name[dc->nameLen] = '\0';
 +                      if (EntryTime) {
 +                              *EntryTime = dc->jiffies;
 +                      }
 +                      retVal = 0;
 +              }
 +      }
 +      DbgPrint("return %d", retVal);
 +      return (retVal);
 +}
 +
 +/*
 + *  Abstract:    This routine will return the first entry on the list
 + *               and then remove it.
 + *
 + *  Notes:       DirCacheLock should be held before calling this routine.
 + *
 + */
 +int novfs_get_remove_entry(struct inode *i, ino_t * ino, struct novfs_entry_info *info)
 +{
 +      struct inode_data *id;
 +      struct novfs_dir_cache *dc;
 +      struct list_head *l = NULL;
 +      int retVal = -1;
 +
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +              l = id->DirCache.next;
 +
 +              if (l != &id->DirCache) {
 +                      dc = list_entry(l, struct novfs_dir_cache, list);
 +
 +                      *ino = dc->ino;
 +                      info->type = 0;
 +                      info->mode = dc->mode;
 +                      info->size = dc->size;
 +                      info->atime = dc->atime;
 +                      info->mtime = dc->mtime;
 +                      info->ctime = dc->ctime;
 +                      info->namelength = dc->nameLen;
 +                      memcpy(info->name, dc->name, dc->nameLen);
 +                      info->name[dc->nameLen] = '\0';
 +                      retVal = 0;
 +
 +                      list_del(&dc->list);
 +                      kfree(dc);
 +                      DCCount--;
 +
 +                      id->cntDC--;
 +              }
 +      }
 +      return (retVal);
 +}
 +
 +/*
 + *  Abstract:    Marks all entries in the directory cache as invalid.
 + *
 + *  Notes:       DirCacheLock should be held before calling this routine.
 + *
 + *========================================================================*/
 +void novfs_invalidate_inode_cache(struct inode *i)
 +{
 +      struct inode_data *id;
 +      struct novfs_dir_cache *dc;
 +      struct list_head *l;
 +
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +              list_for_each(l, &id->DirCache) {
 +                      dc = list_entry(l, struct novfs_dir_cache, list);
 +                      dc->flags &= ~ENTRY_VALID;
 +              }
 +      }
 +}
 +
 +/*++======================================================================*/
 +struct novfs_dir_cache *novfs_lookup_inode_cache(struct inode *i, struct qstr *name, ino_t ino)
 +/*
 + *  Returns:     struct novfs_dir_cache entry if match
 + *               NULL - if there is no match.
 + *
 + *  Abstract:    Checks a inode directory to see if there are any enties
 + *               matching name or ino.  If name is specified then ino is
 + *               not used.  ino is use if name is not specified.
 + *
 + *  Notes:       DirCacheLock should be held before calling this routine.
 + *
 + *========================================================================*/
 +{
 +      struct inode_data *id;
 +      struct novfs_dir_cache *dc, *retVal = NULL;
 +      struct list_head *l;
 +      char *n = "<NULL>";
 +      int nl = 6;
 +      int hash = 0;
 +
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +              if (name && name->name) {
 +                      nl = name->len;
 +                      n = (char *)name->name;
 +                      hash = name->hash;
 +              }
 +              DbgPrint("inode: 0x%p; name:  %.*s; hash:  0x%x;\n" "   len:   %d; ino:   %d", i, nl, n, hash, nl, ino);
 +
 +              list_for_each(l, &id->DirCache) {
 +                      dc = list_entry(l, struct novfs_dir_cache, list);
 +                      if (name) {
 +
 +/*         DbgPrint("novfs_lookup_inode_cache: 0x%p\n" \
 +                  "   ino:   %d\n" \
 +                  "   hash:  0x%x\n" \
 +                  "   len:   %d\n" \
 +                  "   name:  %.*s\n",
 +            dc, dc->ino, dc->hash, dc->nameLen, dc->nameLen, dc->name);
 +*/
 +                              if ((name->hash == dc->hash) &&
 +                                  (name->len == dc->nameLen) && (0 == memcmp(name->name, dc->name, name->len))) {
 +                                      retVal = dc;
 +                                      break;
 +                              }
 +                      } else {
 +                              if (ino == dc->ino) {
 +                                      retVal = dc;
 +                                      break;
 +                              }
 +                      }
 +              }
 +      }
 +
 +      DbgPrint("return 0x%p", retVal);
 +      return (retVal);
 +}
 +
 +/*
 + * Checks a inode directory to see if there are any enties matching name
 + * or ino.  If entry is found the valid bit is set.
 + *
 + * DirCacheLock should be held before calling this routine.
 + */
 +int novfs_lookup_validate(struct inode *i, struct qstr *name, ino_t ino)
 +{
 +      struct inode_data *id;
 +      struct novfs_dir_cache *dc;
 +      int retVal = -1;
 +      char *n = "<NULL>";
 +      int nl = 6;
 +
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +              if (name && name->len) {
 +                      n = (char *)name->name;
 +                      nl = name->len;
 +              }
 +              DbgPrint("inode: 0x%p; name:  %.*s; ino:   %d", i, nl, n, ino);
 +
 +              dc = novfs_lookup_inode_cache(i, name, ino);
 +              if (dc) {
 +                      dc->flags |= ENTRY_VALID;
 +                      retVal = 0;
 +              }
 +      }
 +      return (retVal);
 +}
 +
 +/*
 + * Added entry to directory cache.
 + *
 + * DirCacheLock should be held before calling this routine.
 + */
 +int novfs_add_inode_entry(struct inode *i, struct qstr *name, ino_t ino, struct novfs_entry_info *info)
 +{
 +      struct inode_data *id;
 +      struct novfs_dir_cache *new;
 +      int retVal = -ENOMEM;
 +
 +      //SClark
 +      DbgPrint("i: %p", i);
 +      if ((id = i->i_private)) {
 +              DbgPrint("i->i_private: %p", id);
 +              if (id->DirCache.next)
 +                      DbgPrint("id->DirCache.next: %p", id->DirCache.next);
 +      }
 +      //SClark
 +
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +              new = kmalloc(sizeof(struct novfs_dir_cache) + name->len, GFP_KERNEL);
 +              if (new) {
 +                      id->cntDC++;
 +
 +                      DCCount++;
 +                      DbgPrint("inode: 0x%p; id: 0x%p; DC: 0x%p; new: 0x%p; "
 +                               "name:  %.*s; ino: %d; size: %lld; mode: 0x%x",
 +                               i, id, &id->DirCache, new, name->len, name->name, ino, info->size, info->mode);
 +
 +                      retVal = 0;
 +                      new->flags = ENTRY_VALID;
 +                      new->jiffies = get_jiffies_64();
 +                      new->size = info->size;
 +                      new->mode = info->mode;
 +                      new->atime = info->atime;
 +                      new->mtime = info->mtime;
 +                      new->ctime = info->ctime;
 +                      new->ino = ino;
 +                      new->hash = name->hash;
 +                      new->nameLen = name->len;
 +                      memcpy(new->name, name->name, name->len);
 +                      new->name[new->nameLen] = '\0';
 +                      list_add(&new->list, &id->DirCache);
 +              }
 +      }
 +      return (retVal);
 +}
 +
 +/*
 + *  DirCacheLock should be held before calling this routine.
 + */
 +int novfs_update_entry(struct inode *i, struct qstr *name, ino_t ino, struct novfs_entry_info *info)
 +{
 +      struct inode_data *id;
 +      struct novfs_dir_cache *dc;
 +      int retVal = -1;
 +      char *n = "<NULL>";
 +      int nl = 6;
 +      char atime_buf[32];
 +      char mtime_buf[32];
 +      char ctime_buf[32];
 +
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +
 +              if (name && name->len) {
 +                      n = (char *)name->name;
 +                      nl = name->len;
 +              }
 +              ctime_r(&info->atime.tv_sec, atime_buf);
 +              ctime_r(&info->mtime.tv_sec, mtime_buf);
 +              ctime_r(&info->ctime.tv_sec, ctime_buf);
 +              DbgPrint("inode: 0x%p; name: %.*s; ino: %d; size: %lld; "
 +                       "atime: %s; mtime: %s; ctime: %s", i, nl, n, ino, info->size, atime_buf, mtime_buf, ctime_buf);
 +
 +              dc = novfs_lookup_inode_cache(i, name, ino);
 +              if (dc) {
 +                      retVal = 0;
 +                      dc->flags = ENTRY_VALID;
 +                      dc->jiffies = get_jiffies_64();
 +                      dc->size = info->size;
 +                      dc->mode = info->mode;
 +                      dc->atime = info->atime;
 +                      dc->mtime = info->mtime;
 +                      dc->ctime = info->ctime;
 +
 +                      ctime_r(&dc->atime.tv_sec, atime_buf);
 +                      ctime_r(&dc->mtime.tv_sec, mtime_buf);
 +                      ctime_r(&dc->ctime.tv_sec, ctime_buf);
 +                      DbgPrint("entry: 0x%p; flags: 0x%x; jiffies: %lld; "
 +                               "ino: %d; size: %lld; mode: 0%o; atime: %s; "
 +                               "mtime: %s %d; ctime: %s; hash: 0x%x; "
 +                               " nameLen: %d; name: %s",
 +                               dc, dc->flags, dc->jiffies, dc->ino, dc->size,
 +                               dc->mode, atime_buf, mtime_buf, dc->mtime.tv_nsec, ctime_buf, dc->hash, dc->nameLen, dc->name);
 +              }
 +      }
 +      DbgPrint("return %d", retVal);
 +      return (retVal);
 +}
 +
 +/*
 + *  Removes entry from directory cache.  You can specify a name
 + *  or an inode number.
 + *
 + *  DirCacheLock should be held before calling this routine.
 + */
 +void novfs_remove_inode_entry(struct inode *i, struct qstr *name, ino_t ino)
 +{
 +      struct inode_data *id;
 +      struct novfs_dir_cache *dc;
 +      char *n = "<NULL>";
 +      int nl = 6;
 +
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +              dc = novfs_lookup_inode_cache(i, name, ino);
 +              if (dc) {
 +                      if (name && name->name) {
 +                              nl = name->len;
 +                              n = (char *)name->name;
 +                      }
 +                      DbgPrint("inode: 0x%p; id: 0x%p; DC: 0x%p; "
 +                               "name: %.*s; ino: %d entry: 0x%p "
 +                               "[name: %.*s; ino: %d; next: 0x%p; "
 +                               "prev: 0x%p]",
 +                               i, id, &id->DirCache, nl, n, ino, dc,
 +                               dc->nameLen, dc->name, dc->ino, dc->list.next, dc->list.prev);
 +                      list_del(&dc->list);
 +                      kfree(dc);
 +                      DCCount--;
 +
 +                      id->cntDC--;
 +              }
 +      }
 +}
 +
 +/*
 + * Frees all invalid entries in the directory cache.
 + *
 + * DirCacheLock should be held before calling this routine.
 + */
 +void novfs_free_invalid_entries(struct inode *i)
 +{
 +      struct inode_data *id;
 +      struct novfs_dir_cache *dc;
 +      struct list_head *l;
 +
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +              list_for_each(l, &id->DirCache) {
 +                      dc = list_entry(l, struct novfs_dir_cache, list);
 +                      if (0 == (dc->flags & ENTRY_VALID)) {
 +                              DbgPrint("inode: 0x%p; id: 0x%p; entry: 0x%p; "
 +                                       "name: %.*s; ino: %d", i, id, dc, dc->nameLen, dc->name, dc->ino);
 +                              l = l->prev;
 +                              list_del(&dc->list);
 +                              kfree(dc);
 +                              DCCount--;
 +
 +                              id->cntDC--;
 +                      }
 +              }
 +      }
 +}
 +
 +/*
 + *  Frees all entries in the inode cache.
 + *
 + *  DirCacheLock should be held before calling this routine.
 + */
 +void novfs_free_inode_cache(struct inode *i)
 +{
 +      struct inode_data *id;
 +      struct novfs_dir_cache *dc;
 +      struct list_head *l;
 +
 +      if (i && (id = i->i_private) && id->DirCache.next) {
 +              list_for_each(l, &id->DirCache) {
 +                      dc = list_entry(l, struct novfs_dir_cache, list);
 +                      l = l->prev;
 +                      list_del(&dc->list);
 +                      kfree(dc);
 +                      DCCount--;
 +
 +                      id->cntDC--;
 +              }
 +      }
 +}
 +
 +void novfs_dump_inode(void *pf)
 +{
 +      struct inode *inode;
 +      void (*pfunc) (char *Fmt, ...) = pf;
 +      struct inode_data *id;
 +      struct novfs_dir_cache *dc;
 +      struct list_head *il, *l;
 +      char atime_buf[32];
 +      char mtime_buf[32];
 +      char ctime_buf[32];
 +      unsigned long icnt = 0, dccnt = 0;
 +
 +      mutex_lock(&InodeList_lock);
 +      list_for_each(il, &InodeList) {
 +              id = list_entry(il, struct inode_data, IList);
 +              inode = id->Inode;
 +              if (inode) {
 +                      icnt++;
 +
 +                      pfunc("Inode=0x%p I_ino=%d\n", inode, inode->i_ino);
 +
 +                      pfunc("   atime=%s\n", ctime_r(&inode->i_atime.tv_sec, atime_buf));
 +                      pfunc("   ctime=%s\n", ctime_r(&inode->i_mtime.tv_sec, atime_buf));
 +                      pfunc("   mtime=%s\n", ctime_r(&inode->i_ctime.tv_sec, atime_buf));
 +                      pfunc("   size=%lld\n", inode->i_size);
 +                      pfunc("   mode=0%o\n", inode->i_mode);
 +                      pfunc("   count=0%o\n", atomic_read(&inode->i_count));
 +              }
 +
 +              pfunc("   nofs_inode_data: 0x%p Name=%s Scope=0x%p\n", id, id->Name, id->Scope);
 +
 +              if (id->DirCache.next) {
 +                      list_for_each(l, &id->DirCache) {
 +                              dccnt++;
 +                              dc = list_entry(l, struct novfs_dir_cache, list);
 +                              ctime_r(&dc->atime.tv_sec, atime_buf);
 +                              ctime_r(&dc->mtime.tv_sec, mtime_buf);
 +                              ctime_r(&dc->ctime.tv_sec, ctime_buf);
 +
 +                              pfunc("   Cache Entry: 0x%p\n"
 +                                    "      flags:   0x%x\n"
 +                                    "      jiffies: %llu\n"
 +                                    "      ino:     %u\n"
 +                                    "      size:    %llu\n"
 +                                    "      mode:    0%o\n"
 +                                    "      atime:   %s\n"
 +                                    "      mtime:   %s\n"
 +                                    "      ctime:   %s\n"
 +                                    "      hash:    0x%x\n"
 +                                    "      len:     %d\n"
 +                                    "      name:    %s\n",
 +                                    dc, dc->flags, dc->jiffies,
 +                                    dc->ino, dc->size, dc->mode,
 +                                    atime_buf, mtime_buf, ctime_buf, dc->hash, dc->nameLen, dc->name);
 +                      }
 +              }
 +      }
 +      mutex_unlock(&InodeList_lock);
 +
 +      pfunc("Inodes: %d(%d) DirCache: %d(%d)\n", InodeCount, icnt, DCCount, dccnt);
 +
 +}
 +
 +module_init(init_novfs);
 +module_exit(exit_novfs);
 +
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Novell Inc.");
 +MODULE_DESCRIPTION("Novell NetWare Client for Linux");
 +MODULE_VERSION(NOVFS_VERSION_STRING);
Simple merge
diff --cc fs/proc/array.c
Simple merge
@@@ -450,33 -450,24 +450,6 @@@ int remove_save_link(struct inode *inod
        return journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT);
  }
  
- /*
-  * Detach the priv root from the root. Technically this becomes anonymous
-  * but we don't want it added to the anon list. This is necessary to
-  * work around shrink_dcache_for_umount BUG'ing on the xattr dentries if
-  * we don't clean them up before the call and Oopsing on cleaning up
-  * xattrs during inode deletion if we do.
-  */
- static void detach_privroot(struct super_block *s)
- {
-       struct dentry *root = REISERFS_SB(s)->priv_root;
-       if (!root)
-               return;
-       d_drop(root);
-       dput(root->d_parent);
-       spin_lock(&dcache_lock);
-       list_del_init(&root->d_u.d_child);
-       root->d_parent = root;
-       spin_unlock(&dcache_lock);
- }
--static void reiserfs_kill_sb(struct super_block *s)
--{
-       detach_privroot(s);
-       kill_block_super(s);
- }
 -      if (REISERFS_SB(s)) {
 -              if (REISERFS_SB(s)->xattr_root) {
 -                      d_invalidate(REISERFS_SB(s)->xattr_root);
 -                      dput(REISERFS_SB(s)->xattr_root);
 -                      REISERFS_SB(s)->xattr_root = NULL;
 -              }
 -              if (REISERFS_SB(s)->priv_root) {
 -                      d_invalidate(REISERFS_SB(s)->priv_root);
 -                      dput(REISERFS_SB(s)->priv_root);
 -                      REISERFS_SB(s)->priv_root = NULL;
 -              }
 -      }
 -
 -      kill_block_super(s);
 -}
 -
  static void reiserfs_put_super(struct super_block *s)
  {
        struct reiserfs_transaction_handle th;
@@@ -2275,7 -2259,7 +2255,7 @@@ struct file_system_type reiserfs_fs_typ
        .owner = THIS_MODULE,
        .name = "reiserfs",
        .mount = get_super_block,
--      .kill_sb = reiserfs_kill_sb,
++      .kill_sb = kill_block_super,
        .fs_flags = FS_REQUIRES_DEV,
  };
  
@@@ -981,18 -989,18 +989,36 @@@ static const struct dentry_operations x
  
  int reiserfs_lookup_privroot(struct super_block *s)
  {
++      struct qstr fake_name = {
++              .name = ".priv_root",
++              .len = strlen(".priv_root"),
++      };
++      struct dentry *fake_root = d_alloc_pseudo(s, &fake_name);
        struct dentry *dentry;
        int err = 0;
  
++      if (!fake_root) {
++              reiserfs_warning(s, "", "Couldn't initalize fake root for "
++                               "extended attributes.");
++              return -ENOMEM;
++      }
++
        /* If we don't have the privroot located yet - go find it */
        reiserfs_mutex_lock_safe(&s->s_root->d_inode->i_mutex, s);
        dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,
                                strlen(PRIVROOT_NAME));
        if (!IS_ERR(dentry)) {
--              REISERFS_SB(s)->priv_root = dentry;
-               dentry->d_op = &xattr_lookup_poison_ops;
-               if (dentry->d_inode)
++              REISERFS_SB(s)->priv_root = fake_root;
+               d_set_d_op(dentry, &xattr_lookup_poison_ops);
 -              if (dentry->d_inode)
++              if (dentry->d_inode) {
                        dentry->d_inode->i_flags |= S_PRIVATE;
++
++                      /* This is disconnected from the root */
++                      ihold(dentry->d_inode);
++                      d_add(fake_root, dentry->d_inode);
++              }
++              d_delete(dentry);
++              dput(dentry);
        } else
                err = PTR_ERR(dentry);
        mutex_unlock(&s->s_root->d_inode->i_mutex);
index 143f0f8,0000000..9b27c36
mode 100644,000000..100644
--- /dev/null
@@@ -1,617 -1,0 +1,617 @@@
 +/*
 + * Copyright (C) 2006, 2010  Novell, Inc.
 + * Written by Andreas Gruenbacher <agruen@suse.de>
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2, or (at your option) any
 + * later version.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + */
 +
 +#include <linux/sched.h>
 +#include <linux/module.h>
 +#include <linux/fs.h>
 +#include <linux/richacl.h>
 +
 +MODULE_LICENSE("GPL");
 +
 +/*
 + * Special e_who identifiers:  ACEs which have ACE4_SPECIAL_WHO set in
 + * ace->e_flags use these constants in ace->u.e_who.
 + *
 + * For efficiency, we compare pointers instead of comparing strings.
 + */
 +const char richace_owner_who[]          = "OWNER@";
 +EXPORT_SYMBOL_GPL(richace_owner_who);
 +const char richace_group_who[]          = "GROUP@";
 +EXPORT_SYMBOL_GPL(richace_group_who);
 +const char richace_everyone_who[] = "EVERYONE@";
 +EXPORT_SYMBOL_GPL(richace_everyone_who);
 +
 +/**
 + * richacl_alloc  -  allocate a richacl
 + * @count:    number of entries
 + */
 +struct richacl *
 +richacl_alloc(int count)
 +{
 +      size_t size = sizeof(struct richacl) + count * sizeof(struct richace);
 +      struct richacl *acl = kzalloc(size, GFP_KERNEL);
 +
 +      if (acl) {
 +              atomic_set(&acl->a_refcount, 1);
 +              acl->a_count = count;
 +      }
 +      return acl;
 +}
 +EXPORT_SYMBOL_GPL(richacl_alloc);
 +
 +/**
 + * richacl_clone  -  create a copy of a richacl
 + */
 +static struct richacl *
 +richacl_clone(const struct richacl *acl)
 +{
 +      int count = acl->a_count;
 +      size_t size = sizeof(struct richacl) + count * sizeof(struct richace);
 +      struct richacl *dup = kmalloc(size, GFP_KERNEL);
 +
 +      if (dup) {
 +              memcpy(dup, acl, size);
 +              atomic_set(&dup->a_refcount, 1);
 +      }
 +      return dup;
 +}
 +
 +/**
 + * richacl_mask_to_mode  -  compute the file permission bits which correspond to @mask
 + * @mask:     %ACE4_* permission mask
 + *
 + * See richacl_masks_to_mode().
 + */
 +static int
 +richacl_mask_to_mode(unsigned int mask)
 +{
 +      int mode = 0;
 +
 +      if (mask & ACE4_POSIX_MODE_READ)
 +              mode |= MAY_READ;
 +      if (mask & ACE4_POSIX_MODE_WRITE)
 +              mode |= MAY_WRITE;
 +      if (mask & ACE4_POSIX_MODE_EXEC)
 +              mode |= MAY_EXEC;
 +
 +      return mode;
 +}
 +
 +/**
 + * richacl_masks_to_mode  -  compute the file permission bits from the file masks
 + *
 + * When setting a richacl, we set the file permission bits to indicate maximum
 + * permissions: for example, we set the Write permission when a mask contains
 + * ACE4_APPEND_DATA even if it does not also contain ACE4_WRITE_DATA.
 + *
 + * Permissions which are not in ACE4_POSIX_MODE_READ, ACE4_POSIX_MODE_WRITE, or
 + * ACE4_POSIX_MODE_EXEC cannot be represented in the file permission bits.
 + * Such permissions can still be effective, but not for new files or after a
 + * chmod(), and only if they were set explicitly, for example, by setting a
 + * richacl.
 + */
 +int
 +richacl_masks_to_mode(const struct richacl *acl)
 +{
 +      return richacl_mask_to_mode(acl->a_owner_mask) << 6 |
 +             richacl_mask_to_mode(acl->a_group_mask) << 3 |
 +             richacl_mask_to_mode(acl->a_other_mask);
 +}
 +EXPORT_SYMBOL_GPL(richacl_masks_to_mode);
 +
 +/**
 + * richacl_mode_to_mask  - compute a file mask from the lowest three mode bits
 + *
 + * When the file permission bits of a file are set with chmod(), this specifies
 + * the maximum permissions that processes will get.  All permissions beyond
 + * that will be removed from the file masks, and become ineffective.
 + *
 + * We also add in the permissions which are always allowed no matter what the
 + * acl says.
 + */
 +unsigned int
 +richacl_mode_to_mask(mode_t mode)
 +{
 +      unsigned int mask = ACE4_POSIX_ALWAYS_ALLOWED;
 +
 +      if (mode & MAY_READ)
 +              mask |= ACE4_POSIX_MODE_READ;
 +      if (mode & MAY_WRITE)
 +              mask |= ACE4_POSIX_MODE_WRITE;
 +      if (mode & MAY_EXEC)
 +              mask |= ACE4_POSIX_MODE_EXEC;
 +
 +      return mask;
 +}
 +
 +/**
 + * richacl_want_to_mask  - convert the iop->permission want argument to a mask
 + * @want:     @want argument of the permission inode operation
 + *
 + * When checking for append, @want is (MAY_WRITE | MAY_APPEND).
 + *
 + * Richacls use the iop->may_create and iop->may_delete hooks which are
 + * used for checking if creating and deleting files is allowed.  These hooks do
 + * not use richacl_want_to_mask(), so we do not have to deal with mapping
 + * MAY_WRITE to ACE4_ADD_FILE, ACE4_ADD_SUBDIRECTORY, and ACE4_DELETE_CHILD
 + * here.
 + */
 +unsigned int
 +richacl_want_to_mask(int want)
 +{
 +      unsigned int mask = 0;
 +
 +      if (want & MAY_READ)
 +              mask |= ACE4_READ_DATA;
 +      if (want & MAY_APPEND)
 +              mask |= ACE4_APPEND_DATA;
 +      else if (want & MAY_WRITE)
 +              mask |= ACE4_WRITE_DATA;
 +      if (want & MAY_EXEC)
 +              mask |= ACE4_EXECUTE;
 +
 +      return mask;
 +}
 +EXPORT_SYMBOL_GPL(richacl_want_to_mask);
 +
 +/**
 + * richace_is_same_identifier  -  are both identifiers the same?
 + */
 +int
 +richace_is_same_identifier(const struct richace *a, const struct richace *b)
 +{
 +#define WHO_FLAGS (ACE4_SPECIAL_WHO | ACE4_IDENTIFIER_GROUP)
 +      if ((a->e_flags & WHO_FLAGS) != (b->e_flags & WHO_FLAGS))
 +              return 0;
 +      if (a->e_flags & ACE4_SPECIAL_WHO)
 +              return a->u.e_who == b->u.e_who;
 +      else
 +              return a->u.e_id == b->u.e_id;
 +#undef WHO_FLAGS
 +}
 +
 +/**
 + * richacl_set_who  -  set a special who value
 + * @ace:      acl entry
 + * @who:      who value to use
 + */
 +int
 +richace_set_who(struct richace *ace, const char *who)
 +{
 +      if (!strcmp(who, richace_owner_who))
 +              who = richace_owner_who;
 +      else if (!strcmp(who, richace_group_who))
 +              who = richace_group_who;
 +      else if (!strcmp(who, richace_everyone_who))
 +              who = richace_everyone_who;
 +      else
 +              return -EINVAL;
 +
 +      ace->u.e_who = who;
 +      ace->e_flags |= ACE4_SPECIAL_WHO;
 +      ace->e_flags &= ~ACE4_IDENTIFIER_GROUP;
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(richace_set_who);
 +
 +/**
 + * richacl_allowed_to_who  -  mask flags allowed to a specific who value
 + *
 + * Computes the mask values allowed to a specific who value, taking
 + * EVERYONE@ entries into account.
 + */
 +static unsigned int richacl_allowed_to_who(struct richacl *acl,
 +                                         struct richace *who)
 +{
 +      struct richace *ace;
 +      unsigned int allowed = 0;
 +
 +      richacl_for_each_entry_reverse(ace, acl) {
 +              if (richace_is_inherit_only(ace))
 +                      continue;
 +              if (richace_is_same_identifier(ace, who) ||
 +                  richace_is_everyone(ace)) {
 +                      if (richace_is_allow(ace))
 +                              allowed |= ace->e_mask;
 +                      else if (richace_is_deny(ace))
 +                              allowed &= ~ace->e_mask;
 +              }
 +      }
 +      return allowed;
 +}
 +
 +/**
 + * richacl_group_class_allowed  -  maximum permissions the group class is allowed
 + *
 + * See richacl_compute_max_masks().
 + */
 +static unsigned int richacl_group_class_allowed(struct richacl *acl)
 +{
 +      struct richace *ace;
 +      unsigned int everyone_allowed = 0, group_class_allowed = 0;
 +      int had_group_ace = 0;
 +
 +      richacl_for_each_entry_reverse(ace, acl) {
 +              if (richace_is_inherit_only(ace) ||
 +                  richace_is_owner(ace))
 +                      continue;
 +
 +              if (richace_is_everyone(ace)) {
 +                      if (richace_is_allow(ace))
 +                              everyone_allowed |= ace->e_mask;
 +                      else if (richace_is_deny(ace))
 +                              everyone_allowed &= ~ace->e_mask;
 +              } else {
 +                      group_class_allowed |=
 +                              richacl_allowed_to_who(acl, ace);
 +
 +                      if (richace_is_group(ace))
 +                              had_group_ace = 1;
 +              }
 +      }
 +      if (!had_group_ace)
 +              group_class_allowed |= everyone_allowed;
 +      return group_class_allowed;
 +}
 +
 +/**
 + * richacl_compute_max_masks  -  compute upper bound masks
 + *
 + * Computes upper bound owner, group, and other masks so that none of
 + * the mask flags allowed by the acl are disabled (for any choice of the
 + * file owner or group membership).
 + */
 +void richacl_compute_max_masks(struct richacl *acl)
 +{
 +      unsigned int gmask = ~0;
 +      struct richace *ace;
 +
 +      /*
 +       * @gmask contains all permissions which the group class is ever
 +       * allowed.  We use it to avoid adding permissions to the group mask
 +       * from everyone@ allow aces which the group class is always denied
 +       * through other aces.  For example, the following acl would otherwise
 +       * result in a group mask or rw:
 +       *
 +       *      group@:w::deny
 +       *      everyone@:rw::allow
 +       *
 +       * Avoid computing @gmask for acls which do not include any group class
 +       * deny aces: in such acls, the group class is never denied any
 +       * permissions from everyone@ allow aces.
 +       */
 +
 +restart:
 +      acl->a_owner_mask = 0;
 +      acl->a_group_mask = 0;
 +      acl->a_other_mask = 0;
 +
 +      richacl_for_each_entry_reverse(ace, acl) {
 +              if (richace_is_inherit_only(ace))
 +                      continue;
 +
 +              if (richace_is_owner(ace)) {
 +                      if (richace_is_allow(ace))
 +                              acl->a_owner_mask |= ace->e_mask;
 +                      else if (richace_is_deny(ace))
 +                              acl->a_owner_mask &= ~ace->e_mask;
 +              } else if (richace_is_everyone(ace)) {
 +                      if (richace_is_allow(ace)) {
 +                              acl->a_owner_mask |= ace->e_mask;
 +                              acl->a_group_mask |= ace->e_mask & gmask;
 +                              acl->a_other_mask |= ace->e_mask;
 +                      } else if (richace_is_deny(ace)) {
 +                              acl->a_owner_mask &= ~ace->e_mask;
 +                              acl->a_group_mask &= ~ace->e_mask;
 +                              acl->a_other_mask &= ~ace->e_mask;
 +                      }
 +              } else {
 +                      if (richace_is_allow(ace)) {
 +                              acl->a_owner_mask |= ace->e_mask & gmask;
 +                              acl->a_group_mask |= ace->e_mask & gmask;
 +                      } else if (richace_is_deny(ace) && gmask == ~0) {
 +                              gmask = richacl_group_class_allowed(acl);
 +                              if (likely(gmask != ~0))  /* should always be true */
 +                                      goto restart;
 +                      }
 +              }
 +      }
 +}
 +EXPORT_SYMBOL_GPL(richacl_compute_max_masks);
 +
 +/**
 + * richacl_chmod  -  update the file masks to reflect the new mode
 + * @mode:     new file permission bits
 + *
 + * Return a copy of @acl where the file masks have been replaced by the file
 + * masks corresponding to the file permission bits in @mode, or returns @acl
 + * itself if the file masks are already up to date.  Takes over a reference
 + * to @acl.
 + */
 +struct richacl *
 +richacl_chmod(struct richacl *acl, mode_t mode)
 +{
 +      unsigned int owner_mask, group_mask, other_mask;
 +      struct richacl *clone;
 +
 +      owner_mask = richacl_mode_to_mask(mode >> 6);
 +      group_mask = richacl_mode_to_mask(mode >> 3);
 +      other_mask = richacl_mode_to_mask(mode);
 +
 +      if (acl->a_owner_mask == owner_mask &&
 +          acl->a_group_mask == group_mask &&
 +          acl->a_other_mask == other_mask &&
 +          (!richacl_is_auto_inherit(acl) || richacl_is_protected(acl)))
 +              return acl;
 +
 +      clone = richacl_clone(acl);
 +      richacl_put(acl);
 +      if (!clone)
 +              return ERR_PTR(-ENOMEM);
 +
 +      clone->a_owner_mask = owner_mask;
 +      clone->a_group_mask = group_mask;
 +      clone->a_other_mask = other_mask;
 +      if (richacl_is_auto_inherit(clone))
 +              clone->a_flags |= ACL4_PROTECTED;
 +
 +      return clone;
 +}
 +EXPORT_SYMBOL_GPL(richacl_chmod);
 +
 +/**
 + * richacl_permission  -  richacl permission check algorithm
 + * @inode:    inode to check
 + * @acl:      rich acl of the inode
 + * @mask:     requested access (ACE4_* bitmask)
 + *
 + * Checks if the current process is granted @mask flags in @acl.
 + */
 +int
 +richacl_permission(struct inode *inode, const struct richacl *acl,
-                  unsigned int mask)
++                 unsigned int mask, unsigned int flags)
 +{
 +      const struct richace *ace;
 +      unsigned int file_mask, requested = mask, denied = 0;
 +      int in_owning_group = in_group_p(inode->i_gid);
 +      int in_owner_or_group_class = in_owning_group;
 +
 +      /*
 +       * A process is
 +       *   - in the owner file class if it owns the file,
 +       *   - in the group file class if it is in the file's owning group or
 +       *     it matches any of the user or group entries, and
 +       *   - in the other file class otherwise.
 +       */
 +
 +      /*
 +       * Check if the acl grants the requested access and determine which
 +       * file class the process is in.
 +       */
 +      richacl_for_each_entry(ace, acl) {
 +              unsigned int ace_mask = ace->e_mask;
 +
 +              if (richace_is_inherit_only(ace))
 +                      continue;
 +              if (richace_is_owner(ace)) {
 +                      if (current_fsuid() != inode->i_uid)
 +                              continue;
 +                      goto is_owner;
 +              } else if (richace_is_group(ace)) {
 +                      if (!in_owning_group)
 +                              continue;
 +              } else if (richace_is_unix_id(ace)) {
 +                      if (ace->e_flags & ACE4_IDENTIFIER_GROUP) {
 +                              if (!in_group_p(ace->u.e_id))
 +                                      continue;
 +                      } else {
 +                              if (current_fsuid() != ace->u.e_id)
 +                                      continue;
 +                      }
 +              } else
 +                      goto is_everyone;
 +
 +              /*
 +               * Apply the group file mask to entries other than OWNER@ and
 +               * EVERYONE@. This is not required for correct access checking
 +               * but ensures that we grant the same permissions as the acl
 +               * computed by richacl_apply_masks() would grant.  See
 +               * richacl_apply_masks() for a more detailed explanation.
 +               */
 +              if (richace_is_allow(ace))
 +                      ace_mask &= acl->a_group_mask;
 +
 +is_owner:
 +              /* The process is in the owner or group file class. */
 +              in_owner_or_group_class = 1;
 +
 +is_everyone:
 +              /* Check which mask flags the ACE allows or denies. */
 +              if (richace_is_deny(ace))
 +                      denied |= ace_mask & mask;
 +              mask &= ~ace_mask;
 +
 +              /*
 +               * Keep going until we know which file class
 +               * the process is in.
 +               */
 +              if (!mask && in_owner_or_group_class)
 +                      break;
 +      }
 +      denied |= mask;
 +
 +      /*
 +       * The file class a process is in determines which file mask applies.
 +       * Check if that file mask also grants the requested access.
 +       */
 +      if (current_fsuid() == inode->i_uid)
 +              file_mask = acl->a_owner_mask;
 +      else if (in_owner_or_group_class)
 +              file_mask = acl->a_group_mask;
 +      else
 +              file_mask = acl->a_other_mask;
 +      denied |= requested & ~file_mask;
 +
 +      return denied ? -EACCES : 0;
 +}
 +EXPORT_SYMBOL_GPL(richacl_permission);
 +
 +/**
 + * richacl_inherit  -  compute the inherited acl of a new file
 + * @dir_acl:  acl of the containing direcory
 + * @inode:    inode of the new file (create mode in i_mode)
 + *
 + * A directory can have acl entries which files and/or directories created
 + * inside the directory will inherit.  This function computes the acl for such
 + * a new file.  If there is no inheritable acl, it will return %NULL.
 + *
 + * The file permission bits in inode->i_mode must be set to the create mode.
 + * If there is an inheritable acl, the maximum permissions that the acl grants
 + * will be computed and permissions not granted by the acl will be removed from
 + * inode->i_mode.  If there is no inheritable acl, the umask will be applied
 + * instead.
 + */
 +struct richacl *
 +richacl_inherit(const struct richacl *dir_acl, struct inode *inode)
 +{
 +      const struct richace *dir_ace;
 +      struct richacl *acl = NULL;
 +      struct richace *ace;
 +      int count = 0;
 +      mode_t mask = ~current_umask();
 +
 +      if (S_ISDIR(inode->i_mode)) {
 +              richacl_for_each_entry(dir_ace, dir_acl) {
 +                      if (!richace_is_inheritable(dir_ace))
 +                              continue;
 +                      count++;
 +              }
 +              if (!count)
 +                      goto mask;
 +              acl = richacl_alloc(count);
 +              if (!acl)
 +                      return ERR_PTR(-ENOMEM);
 +              ace = acl->a_entries;
 +              richacl_for_each_entry(dir_ace, dir_acl) {
 +                      if (!richace_is_inheritable(dir_ace))
 +                              continue;
 +                      memcpy(ace, dir_ace, sizeof(struct richace));
 +                      if (dir_ace->e_flags & ACE4_NO_PROPAGATE_INHERIT_ACE)
 +                              richace_clear_inheritance_flags(ace);
 +                      if ((dir_ace->e_flags & ACE4_FILE_INHERIT_ACE) &&
 +                          !(dir_ace->e_flags & ACE4_DIRECTORY_INHERIT_ACE))
 +                              ace->e_flags |= ACE4_INHERIT_ONLY_ACE;
 +                      ace++;
 +              }
 +      } else {
 +              richacl_for_each_entry(dir_ace, dir_acl) {
 +                      if (!(dir_ace->e_flags & ACE4_FILE_INHERIT_ACE))
 +                              continue;
 +                      count++;
 +              }
 +              if (!count)
 +                      goto mask;
 +              acl = richacl_alloc(count);
 +              if (!acl)
 +                      return ERR_PTR(-ENOMEM);
 +              ace = acl->a_entries;
 +              richacl_for_each_entry(dir_ace, dir_acl) {
 +                      if (!(dir_ace->e_flags & ACE4_FILE_INHERIT_ACE))
 +                              continue;
 +                      memcpy(ace, dir_ace, sizeof(struct richace));
 +                      richace_clear_inheritance_flags(ace);
 +                      /*
 +                       * ACE4_DELETE_CHILD is meaningless for
 +                       * non-directories, so clear it.
 +                       */
 +                      ace->e_mask &= ~ACE4_DELETE_CHILD;
 +                      ace++;
 +              }
 +      }
 +
 +      richacl_compute_max_masks(acl);
 +
 +      /*
 +       * Ensure that the acl will not grant any permissions beyond the create
 +       * mode.
 +       */
 +      acl->a_owner_mask &= richacl_mode_to_mask(inode->i_mode >> 6);
 +      acl->a_group_mask &= richacl_mode_to_mask(inode->i_mode >> 3);
 +      acl->a_other_mask &= richacl_mode_to_mask(inode->i_mode);
 +      mask = ~S_IRWXUGO | richacl_masks_to_mode(acl);
 +
 +      if (richacl_is_auto_inherit(dir_acl)) {
 +              /*
 +               * We need to set ACL4_PROTECTED because we are
 +               * doing an implicit chmod
 +               */
 +              acl->a_flags = ACL4_AUTO_INHERIT | ACL4_PROTECTED;
 +              richacl_for_each_entry(ace, acl)
 +                      ace->e_flags |= ACE4_INHERITED_ACE;
 +      }
 +
 +mask:
 +      inode->i_mode &= mask;
 +      return acl;
 +}
 +EXPORT_SYMBOL_GPL(richacl_inherit);
 +
 +/**
 + * richacl_equiv_mode  -  check if @acl is equivalent to file permission bits
 + * @mode_p:   the file mode (including the file type)
 + *
 + * If @acl can be fully represented by file permission bits, this function
 + * returns 0, and the file permission bits in @mode_p are set to the equivalent
 + * of @acl.
 + *
 + * This function is used to avoid storing richacls on disk if the acl can be
 + * computed from the file permission bits.  It allows user-space to make sure
 + * that a file has no explicit richacl set.
 + */
 +int
 +richacl_equiv_mode(const struct richacl *acl, mode_t *mode_p)
 +{
 +      const struct richace *ace = acl->a_entries;
 +      unsigned int x;
 +      mode_t mode;
 +
 +      if (acl->a_count != 1 ||
 +          acl->a_flags ||
 +          !richace_is_everyone(ace) ||
 +          !richace_is_allow(ace) ||
 +          ace->e_flags & ~ACE4_SPECIAL_WHO)
 +              return -1;
 +
 +      /*
 +       * Figure out the permissions we care about: ACE4_DELETE_CHILD is
 +       * meaningless for non-directories, so we ignore it.
 +       */
 +      x = ~ACE4_POSIX_ALWAYS_ALLOWED;
 +      if (!S_ISDIR(*mode_p))
 +              x &= ~ACE4_DELETE_CHILD;
 +
 +      if ((ace->e_mask & x) != (ACE4_POSIX_MODE_ALL & x))
 +              return -1;
 +
 +      mode = richacl_masks_to_mode(acl);
 +      if ((acl->a_owner_mask & x) != (richacl_mode_to_mask(mode >> 6) & x) ||
 +          (acl->a_group_mask & x) != (richacl_mode_to_mask(mode >> 3) & x) ||
 +          (acl->a_other_mask & x) != (richacl_mode_to_mask(mode) & x))
 +              return -1;
 +
 +      *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(richacl_equiv_mode);
index 42f7f68,0000000..cc237f3
mode 100644,000000..100644
--- /dev/null
@@@ -1,194 -1,0 +1,198 @@@
 +/*
 + * Copyright (C) 2010  Novell, Inc.
 + * Written by Andreas Gruenbacher <agruen@suse.de>
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2, or (at your option) any
 + * later version.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + */
 +
 +#include <linux/sched.h>
 +#include <linux/module.h>
 +#include <linux/fs.h>
 +#include <linux/richacl.h>
 +
 +/**
 + * richacl_may_create  -  helper for implementing iop->may_create
 + */
 +int
 +richacl_may_create(struct inode *dir, int isdir,
-               int (*richacl_permission)(struct inode *, unsigned int))
++              int (*richacl_permission)(struct inode *, unsigned int,
++                                        unsigned int))
 +{
 +      if (IS_RICHACL(dir))
 +              return richacl_permission(dir,
 +                              ACE4_EXECUTE | (isdir ?
-                               ACE4_ADD_SUBDIRECTORY : ACE4_ADD_FILE));
++                              ACE4_ADD_SUBDIRECTORY : ACE4_ADD_FILE), 0);
 +      else
-               return generic_permission(dir, MAY_WRITE | MAY_EXEC,
++              return generic_permission(dir, MAY_WRITE | MAY_EXEC, 0,
 +                                        dir->i_op->check_acl);
 +}
 +EXPORT_SYMBOL(richacl_may_create);
 +
 +static int
 +check_sticky(struct inode *dir, struct inode *inode)
 +{
 +      if (!(dir->i_mode & S_ISVTX))
 +              return 0;
 +      if (inode->i_uid == current_fsuid())
 +              return 0;
 +      if (dir->i_uid == current_fsuid())
 +              return 0;
 +      return !capable(CAP_FOWNER);
 +}
 +
 +/**
 + * richacl_may_delete  -  helper for implementing iop->may_delete
 + */
 +int
 +richacl_may_delete(struct inode *dir, struct inode *inode, int replace,
-                  int (*richacl_permission)(struct inode *, unsigned int))
++                 int (*richacl_permission)(struct inode *, unsigned int,
++                                           unsigned int))
 +{
 +      int error;
 +
 +      if (IS_RICHACL(inode)) {
 +              error = richacl_permission(dir,
-                               ACE4_EXECUTE | ACE4_DELETE_CHILD);
++                              ACE4_EXECUTE | ACE4_DELETE_CHILD, 0);
 +              if (!error && check_sticky(dir, inode))
 +                      error = -EPERM;
-               if (error && !richacl_permission(inode, ACE4_DELETE))
++              if (error && !richacl_permission(inode, ACE4_DELETE, 0))
 +                      error = 0;
 +              if (!error && replace)
 +                      error = richacl_permission(dir,
 +                                      ACE4_EXECUTE | (S_ISDIR(inode->i_mode) ?
-                                       ACE4_ADD_SUBDIRECTORY : ACE4_ADD_FILE));
++                                      ACE4_ADD_SUBDIRECTORY : ACE4_ADD_FILE),
++                                      0);
 +      } else {
-               error = generic_permission(dir, MAY_WRITE | MAY_EXEC,
++              error = generic_permission(dir, MAY_WRITE | MAY_EXEC, 0,
 +                                         dir->i_op->check_acl);
 +              if (!error && check_sticky(dir, inode))
 +                      error = -EPERM;
 +      }
 +
 +      return error;
 +}
 +EXPORT_SYMBOL(richacl_may_delete);
 +
 +/**
 + * richacl_inode_permission  -  helper for implementing iop->permission
 + * @inode:    inode to check
 + * @acl:      rich acl of the inode (may be NULL)
 + * @mask:     requested access (ACE4_* bitmask)
 + *
 + * This function is supposed to be used by file systems for implementing the
 + * permission inode operation.
 + */
 +int
 +richacl_inode_permission(struct inode *inode, const struct richacl *acl,
-                        unsigned int mask)
++                       unsigned int mask, unsigned int flags)
 +{
 +      if (acl) {
-               if (!richacl_permission(inode, acl, mask))
++              if (!richacl_permission(inode, acl, mask, flags))
 +                      return 0;
 +      } else {
 +              int mode = inode->i_mode;
 +
 +              if (current_fsuid() == inode->i_uid)
 +                      mode >>= 6;
 +              else if (in_group_p(inode->i_gid))
 +                      mode >>= 3;
 +              if (!(mask & ~richacl_mode_to_mask(mode)))
 +                      return 0;
 +      }
 +
 +      /*
 +       * Keep in sync with the capability checks in generic_permission().
 +       */
 +      if (!(mask & ~ACE4_POSIX_MODE_ALL)) {
 +              /*
 +               * Read/write DACs are always overridable.
 +               * Executable DACs are overridable if at
 +               * least one exec bit is set.
 +               */
 +              if (!(mask & ACE4_POSIX_MODE_EXEC) || execute_ok(inode))
 +                      if (capable(CAP_DAC_OVERRIDE))
 +                              return 0;
 +      }
 +      /*
 +       * Searching includes executable on directories, else just read.
 +       */
 +      if (!(mask & ~(ACE4_READ_DATA | ACE4_LIST_DIRECTORY | ACE4_EXECUTE)) &&
 +          (S_ISDIR(inode->i_mode) || !(mask & ACE4_EXECUTE)))
 +              if (capable(CAP_DAC_READ_SEARCH))
 +                      return 0;
 +
 +      return -EACCES;
 +}
 +EXPORT_SYMBOL_GPL(richacl_inode_permission);
 +
 +/**
 + * richacl_inode_change_ok  -  helper for implementing iop->setattr
 + * @inode:    inode to check
 + * @attr:     requested inode attribute changes
 + * @richacl_permission:       permission function taking an inode and ACE4_* flags
 + *
 + * Keep in sync with inode_change_ok().
 + */
 +int
 +richacl_inode_change_ok(struct inode *inode, struct iattr *attr,
-                       int (*richacl_permission)(struct inode *, unsigned int))
++                      int (*richacl_permission)(struct inode *, unsigned int,
++                                                unsigned int))
 +{
 +      unsigned int ia_valid = attr->ia_valid;
 +
 +      /* If force is set do it anyway. */
 +      if (ia_valid & ATTR_FORCE)
 +              return 0;
 +
 +      /* Make sure a caller can chown. */
 +      if ((ia_valid & ATTR_UID) &&
 +          (current_fsuid() != inode->i_uid ||
 +           attr->ia_uid != inode->i_uid) &&
 +          (current_fsuid() != attr->ia_uid ||
-            richacl_permission(inode, ACE4_WRITE_OWNER)) &&
++           richacl_permission(inode, ACE4_WRITE_OWNER, 0)) &&
 +          !capable(CAP_CHOWN))
 +              goto error;
 +
 +      /* Make sure caller can chgrp. */
 +      if ((ia_valid & ATTR_GID)) {
 +              int in_group = in_group_p(attr->ia_gid);
 +              if ((current_fsuid() != inode->i_uid ||
 +                  (!in_group && attr->ia_gid != inode->i_gid)) &&
 +                  (!in_group ||
-                    richacl_permission(inode, ACE4_WRITE_OWNER)) &&
++                   richacl_permission(inode, ACE4_WRITE_OWNER, 0)) &&
 +                  !capable(CAP_CHOWN))
 +                      goto error;
 +      }
 +
 +      /* Make sure a caller can chmod. */
 +      if (ia_valid & ATTR_MODE) {
 +              if (current_fsuid() != inode->i_uid &&
-                   richacl_permission(inode, ACE4_WRITE_ACL) &&
++                  richacl_permission(inode, ACE4_WRITE_ACL, 0) &&
 +                  !capable(CAP_FOWNER))
 +                      goto error;
 +              /* Also check the setgid bit! */
 +              if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
 +                              inode->i_gid) && !capable(CAP_FSETID))
 +                      attr->ia_mode &= ~S_ISGID;
 +      }
 +
 +      /* Check for setting the inode time. */
 +      if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
 +              if (current_fsuid() != inode->i_uid &&
-                   richacl_permission(inode, ACE4_WRITE_ATTRIBUTES) &&
++                  richacl_permission(inode, ACE4_WRITE_ATTRIBUTES, 0) &&
 +                  !capable(CAP_FOWNER))
 +                      goto error;
 +      }
 +      return 0;
 +error:
 +      return -EPERM;
 +}
 +EXPORT_SYMBOL_GPL(richacl_inode_change_ok);
diff --cc fs/super.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -279,13 -278,8 +280,14 @@@ struct inodes_stat_t 
  #define IS_SWAPFILE(inode)    ((inode)->i_flags & S_SWAPFILE)
  #define IS_PRIVATE(inode)     ((inode)->i_flags & S_PRIVATE)
  #define IS_IMA(inode)         ((inode)->i_flags & S_IMA)
+ #define IS_AUTOMOUNT(inode)   ((inode)->i_flags & S_AUTOMOUNT)
  
 +/*
 + * IS_ACL() tells the VFS to not apply the umask
 + * and use iop->check_acl for acl permission checks when defined.
 + */
 +#define IS_ACL(inode)         __IS_FLG(inode, MS_POSIXACL | MS_RICHACL)
 +
  /* the read-only stuff doesn't really belong here, but any other place is
     probably as bad and I don't want to create yet another include file. */
  
@@@ -1590,15 -1584,9 +1602,13 @@@ struct inode_operations 
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
        int (*removexattr) (struct dentry *, const char *);
        void (*truncate_range)(struct inode *, loff_t, loff_t);
-       long (*fallocate)(struct inode *inode, int mode, loff_t offset,
-                         loff_t len);
        int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
                      u64 len);
 +      int (*may_create) (struct inode *, int);
 +      int (*may_delete) (struct inode *, struct inode *, int);
 +
 +
- };
+ } ____cacheline_aligned;
  
  struct seq_file;
  
@@@ -126,8 -127,12 +127,13 @@@ struct hd_struct 
  #define GENHD_FL_SUPPRESS_PARTITION_INFO      32
  #define GENHD_FL_EXT_DEVT                     64 /* allow extended devt */
  #define GENHD_FL_NATIVE_CAPACITY              128
 +#define GENHD_FL_NO_PARTITION_SCAN            256
  
+ enum {
+       DISK_EVENT_MEDIA_CHANGE                 = 1 << 0, /* media changed */
+       DISK_EVENT_EJECT_REQUEST                = 1 << 1, /* eject requested */
+ };
  #define BLK_SCSI_MAX_CMDS     (256)
  #define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8))
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -435,14 -394,49 +402,55 @@@ static inline void __ClearPageTail(stru
        page->flags &= ~PG_head_tail_mask;
  }
  
+ #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ static inline void ClearPageCompound(struct page *page)
+ {
+       BUG_ON((page->flags & PG_head_tail_mask) != (1 << PG_compound));
+       clear_bit(PG_compound, &page->flags);
+ }
+ #endif
  #endif /* !PAGEFLAGS_EXTENDED */
  
 +#ifdef CONFIG_PAGEFLAGS_EXTENDED
 +PAGEFLAG(MemError, memerror)
 +#else
 +PAGEFLAG_FALSE(MemError)
 +#endif
 +
+ #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ /*
+  * PageHuge() only returns true for hugetlbfs pages, but not for
+  * normal or transparent huge pages.
+  *
+  * PageTransHuge() returns true for both transparent huge and
+  * hugetlbfs pages, but not normal pages. PageTransHuge() can only be
+  * called only in the core VM paths where hugetlbfs pages can't exist.
+  */
+ static inline int PageTransHuge(struct page *page)
+ {
+       VM_BUG_ON(PageTail(page));
+       return PageHead(page);
+ }
+ static inline int PageTransCompound(struct page *page)
+ {
+       return PageCompound(page);
+ }
+ #else
+ static inline int PageTransHuge(struct page *page)
+ {
+       return 0;
+ }
+ static inline int PageTransCompound(struct page *page)
+ {
+       return 0;
+ }
+ #endif
  #ifdef CONFIG_MMU
  #define __PG_MLOCKED          (1 << PG_mlocked)
  #else
Simple merge
@@@ -161,42 -145,23 +145,42 @@@ extern void dump_stack(void) __cold
  #define pr_fmt(fmt) fmt
  #endif
  
 +#if defined(__KMSG_CHECKER) && defined(KMSG_COMPONENT)
 +
 +/* generate magic string for scripts/kmsg-doc to parse */
 +#define pr_printk_hash(level, format, ...) \
 +      __KMSG_PRINT(level _FMT_ format _ARGS_ #__VA_ARGS__ _END_)
 +
 +#elif defined(CONFIG_KMSG_IDS) && defined(KMSG_COMPONENT)
 +
 +int printk_hash(const char *, const char *, ...);
 +#define pr_printk_hash(level, format, ...) \
 +      printk_hash(level KMSG_COMPONENT ".%06x" ": ", format, ##__VA_ARGS__)
 +
 +#else /* !defined(CONFIG_KMSG_IDS) */
 +
 +#define pr_printk_hash(level, format, ...) \
 +      printk(level pr_fmt(format), ##__VA_ARGS__)
 +
 +#endif
 +
  #define pr_emerg(fmt, ...) \
-         pr_printk_hash(KERN_EMERG, fmt, ##__VA_ARGS__)
 -      printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
++      pr_printk_hash(KERN_EMERG, fmt, ##__VA_ARGS__)
  #define pr_alert(fmt, ...) \
-         pr_printk_hash(KERN_ALERT, fmt, ##__VA_ARGS__)
 -      printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
++      pr_printk_hash(KERN_ALERT, fmt, ##__VA_ARGS__)
  #define pr_crit(fmt, ...) \
-         pr_printk_hash(KERN_CRIT, fmt, ##__VA_ARGS__)
 -      printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
++      pr_printk_hash(KERN_CRIT, fmt, ##__VA_ARGS__)
  #define pr_err(fmt, ...) \
-         pr_printk_hash(KERN_ERR, fmt, ##__VA_ARGS__)
 -      printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
++      pr_printk_hash(KERN_ERR, fmt, ##__VA_ARGS__)
  #define pr_warning(fmt, ...) \
-         pr_printk_hash(KERN_WARNING, fmt, ##__VA_ARGS__)
 -      printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
++      pr_printk_hash(KERN_WARNING, fmt, ##__VA_ARGS__)
  #define pr_warn pr_warning
  #define pr_notice(fmt, ...) \
-         pr_printk_hash(KERN_NOTICE, fmt, ##__VA_ARGS__)
 -      printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
++      pr_printk_hash(KERN_NOTICE, fmt, ##__VA_ARGS__)
  #define pr_info(fmt, ...) \
-         pr_printk_hash(KERN_INFO, fmt, ##__VA_ARGS__)
 -      printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
++      pr_printk_hash(KERN_INFO, fmt, ##__VA_ARGS__)
  #define pr_cont(fmt, ...) \
 -      printk(KERN_CONT fmt, ##__VA_ARGS__)
 +      pr_printk_hash(KERN_CONT, fmt, ##__VA_ARGS__)
  
  /* pr_devel() should produce zero code unless DEBUG is defined */
  #ifdef DEBUG
Simple merge
index 3da00a2,0000000..a90304b
mode 100644,000000..100644
--- /dev/null
@@@ -1,322 -1,0 +1,326 @@@
 +/*
 + * Copyright (C) 2006, 2010  Novell, Inc.
 + * Written by Andreas Gruenbacher <agruen@suse.de>
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2, or (at your option) any
 + * later version.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + */
 +
 +#ifndef __RICHACL_H
 +#define __RICHACL_H
 +#include <linux/slab.h>
 +
 +struct richace {
 +      unsigned short  e_type;
 +      unsigned short  e_flags;
 +      unsigned int    e_mask;
 +      union {
 +              unsigned int    e_id;
 +              const char      *e_who;
 +      } u;
 +};
 +
 +struct richacl {
 +      atomic_t        a_refcount;
 +      unsigned int    a_owner_mask;
 +      unsigned int    a_group_mask;
 +      unsigned int    a_other_mask;
 +      unsigned short  a_count;
 +      unsigned short  a_flags;
 +      struct richace  a_entries[0];
 +};
 +
 +#define richacl_for_each_entry(_ace, _acl) \
 +      for (_ace = _acl->a_entries; \
 +           _ace != _acl->a_entries + _acl->a_count; \
 +           _ace++)
 +
 +#define richacl_for_each_entry_reverse(_ace, _acl) \
 +      for (_ace = _acl->a_entries + _acl->a_count - 1; \
 +           _ace != _acl->a_entries - 1; \
 +           _ace--)
 +
 +/* a_flags values */
 +#define ACL4_AUTO_INHERIT             0x01
 +#define ACL4_PROTECTED                        0x02
 +/*#define ACL4_DEFAULTED                      0x04*/
 +
 +#define ACL4_VALID_FLAGS (    \
 +      ACL4_AUTO_INHERIT |     \
 +      ACL4_PROTECTED)
 +
 +/* e_type values */
 +#define ACE4_ACCESS_ALLOWED_ACE_TYPE  0x0000
 +#define ACE4_ACCESS_DENIED_ACE_TYPE   0x0001
 +/*#define ACE4_SYSTEM_AUDIT_ACE_TYPE  0x0002*/
 +/*#define ACE4_SYSTEM_ALARM_ACE_TYPE  0x0003*/
 +
 +/* e_flags bitflags */
 +#define ACE4_FILE_INHERIT_ACE         0x0001
 +#define ACE4_DIRECTORY_INHERIT_ACE    0x0002
 +#define ACE4_NO_PROPAGATE_INHERIT_ACE 0x0004
 +#define ACE4_INHERIT_ONLY_ACE         0x0008
 +/*#define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG     0x0010*/
 +/*#define ACE4_FAILED_ACCESS_ACE_FLAG 0x0020*/
 +#define ACE4_IDENTIFIER_GROUP         0x0040
 +#define ACE4_INHERITED_ACE            0x0080
 +/* in-memory representation only */
 +#define ACE4_SPECIAL_WHO              0x4000
 +
 +#define ACE4_VALID_FLAGS (                    \
 +      ACE4_FILE_INHERIT_ACE |                 \
 +      ACE4_DIRECTORY_INHERIT_ACE |            \
 +      ACE4_NO_PROPAGATE_INHERIT_ACE |         \
 +      ACE4_INHERIT_ONLY_ACE |                 \
 +      ACE4_IDENTIFIER_GROUP |                 \
 +      ACE4_INHERITED_ACE)
 +
 +/* e_mask bitflags */
 +#define ACE4_READ_DATA                        0x00000001
 +#define ACE4_LIST_DIRECTORY           0x00000001
 +#define ACE4_WRITE_DATA                       0x00000002
 +#define ACE4_ADD_FILE                 0x00000002
 +#define ACE4_APPEND_DATA              0x00000004
 +#define ACE4_ADD_SUBDIRECTORY         0x00000004
 +#define ACE4_READ_NAMED_ATTRS         0x00000008
 +#define ACE4_WRITE_NAMED_ATTRS                0x00000010
 +#define ACE4_EXECUTE                  0x00000020
 +#define ACE4_DELETE_CHILD             0x00000040
 +#define ACE4_READ_ATTRIBUTES          0x00000080
 +#define ACE4_WRITE_ATTRIBUTES         0x00000100
 +#define ACE4_WRITE_RETENTION          0x00000200
 +#define ACE4_WRITE_RETENTION_HOLD     0x00000400
 +#define ACE4_DELETE                   0x00010000
 +#define ACE4_READ_ACL                 0x00020000
 +#define ACE4_WRITE_ACL                        0x00040000
 +#define ACE4_WRITE_OWNER              0x00080000
 +#define ACE4_SYNCHRONIZE              0x00100000
 +
 +/* Valid ACE4_* flags for directories and non-directories */
 +#define ACE4_VALID_MASK (                             \
 +      ACE4_READ_DATA | ACE4_LIST_DIRECTORY |          \
 +      ACE4_WRITE_DATA | ACE4_ADD_FILE |               \
 +      ACE4_APPEND_DATA | ACE4_ADD_SUBDIRECTORY |      \
 +      ACE4_READ_NAMED_ATTRS |                         \
 +      ACE4_WRITE_NAMED_ATTRS |                        \
 +      ACE4_EXECUTE |                                  \
 +      ACE4_DELETE_CHILD |                             \
 +      ACE4_READ_ATTRIBUTES |                          \
 +      ACE4_WRITE_ATTRIBUTES |                         \
 +      ACE4_WRITE_RETENTION |                          \
 +      ACE4_WRITE_RETENTION_HOLD |                     \
 +      ACE4_DELETE |                                   \
 +      ACE4_READ_ACL |                                 \
 +      ACE4_WRITE_ACL |                                \
 +      ACE4_WRITE_OWNER |                              \
 +      ACE4_SYNCHRONIZE)
 +
 +/*
 + * The POSIX permissions are supersets of the following NFSv4 permissions:
 + *
 + *  - MAY_READ maps to READ_DATA or LIST_DIRECTORY, depending on the type
 + *    of the file system object.
 + *
 + *  - MAY_WRITE maps to WRITE_DATA or ACE4_APPEND_DATA for files, and to
 + *    ADD_FILE, ACE4_ADD_SUBDIRECTORY, or ACE4_DELETE_CHILD for directories.
 + *
 + *  - MAY_EXECUTE maps to ACE4_EXECUTE.
 + *
 + *  (Some of these NFSv4 permissions have the same bit values.)
 + */
 +#define ACE4_POSIX_MODE_READ ( \
 +      ACE4_READ_DATA | ACE4_LIST_DIRECTORY)
 +#define ACE4_POSIX_MODE_WRITE ( \
 +      ACE4_WRITE_DATA | ACE4_ADD_FILE | \
 +      ACE4_APPEND_DATA | ACE4_ADD_SUBDIRECTORY | \
 +      ACE4_DELETE_CHILD)
 +#define ACE4_POSIX_MODE_EXEC ( \
 +      ACE4_EXECUTE)
 +#define ACE4_POSIX_MODE_ALL (ACE4_POSIX_MODE_READ | ACE4_POSIX_MODE_WRITE | \
 +                           ACE4_POSIX_MODE_EXEC)
 +
 +/* These permissions are always allowed no matter what the acl says. */
 +#define ACE4_POSIX_ALWAYS_ALLOWED (   \
 +      ACE4_SYNCHRONIZE |              \
 +      ACE4_READ_ATTRIBUTES |          \
 +      ACE4_READ_ACL)
 +
 +/**
 + * richacl_get  -  grab another reference to a richacl handle
 + */
 +static inline struct richacl *
 +richacl_get(struct richacl *acl)
 +{
 +      if (acl)
 +              atomic_inc(&acl->a_refcount);
 +      return acl;
 +}
 +
 +/**
 + * richacl_put  -  free a richacl handle
 + */
 +static inline void
 +richacl_put(struct richacl *acl)
 +{
 +      if (acl && atomic_dec_and_test(&acl->a_refcount))
 +              kfree(acl);
 +}
 +
 +static inline int
 +richacl_is_auto_inherit(const struct richacl *acl)
 +{
 +      return acl->a_flags & ACL4_AUTO_INHERIT;
 +}
 +
 +static inline int
 +richacl_is_protected(const struct richacl *acl)
 +{
 +      return acl->a_flags & ACL4_PROTECTED;
 +}
 +
 +/*
 + * Special e_who identifiers: we use these pointer values in comparisons
 + * instead of doing a strcmp.
 + */
 +extern const char richace_owner_who[];
 +extern const char richace_group_who[];
 +extern const char richace_everyone_who[];
 +
 +/**
 + * richace_is_owner  -  check if @ace is an OWNER@ entry
 + */
 +static inline int
 +richace_is_owner(const struct richace *ace)
 +{
 +      return (ace->e_flags & ACE4_SPECIAL_WHO) &&
 +             ace->u.e_who == richace_owner_who;
 +}
 +
 +/**
 + * richace_is_group  -  check if @ace is a GROUP@ entry
 + */
 +static inline int
 +richace_is_group(const struct richace *ace)
 +{
 +      return (ace->e_flags & ACE4_SPECIAL_WHO) &&
 +             ace->u.e_who == richace_group_who;
 +}
 +
 +/**
 + * richace_is_everyone  -  check if @ace is an EVERYONE@ entry
 + */
 +static inline int
 +richace_is_everyone(const struct richace *ace)
 +{
 +      return (ace->e_flags & ACE4_SPECIAL_WHO) &&
 +             ace->u.e_who == richace_everyone_who;
 +}
 +
 +/**
 + * richace_is_unix_id  -  check if @ace applies to a specific uid or gid
 + */
 +static inline int
 +richace_is_unix_id(const struct richace *ace)
 +{
 +      return !(ace->e_flags & ACE4_SPECIAL_WHO);
 +}
 +
 +/**
 + * richace_is_inherit_only  -  check if @ace is for inheritance only
 + *
 + * ACEs with the %ACE4_INHERIT_ONLY_ACE flag set have no effect during
 + * permission checking.
 + */
 +static inline int
 +richace_is_inherit_only(const struct richace *ace)
 +{
 +      return ace->e_flags & ACE4_INHERIT_ONLY_ACE;
 +}
 +
 +/**
 + * richace_is_inheritable  -  check if @ace is inheritable
 + */
 +static inline int
 +richace_is_inheritable(const struct richace *ace)
 +{
 +      return ace->e_flags & (ACE4_FILE_INHERIT_ACE |
 +                             ACE4_DIRECTORY_INHERIT_ACE);
 +}
 +
 +/**
 + * richace_clear_inheritance_flags  - clear all inheritance flags in @ace
 + */
 +static inline void
 +richace_clear_inheritance_flags(struct richace *ace)
 +{
 +      ace->e_flags &= ~(ACE4_FILE_INHERIT_ACE |
 +                        ACE4_DIRECTORY_INHERIT_ACE |
 +                        ACE4_NO_PROPAGATE_INHERIT_ACE |
 +                        ACE4_INHERIT_ONLY_ACE);
 +}
 +
 +/**
 + * richace_is_allow  -  check if @ace is an %ALLOW type entry
 + */
 +static inline int
 +richace_is_allow(const struct richace *ace)
 +{
 +      return ace->e_type == ACE4_ACCESS_ALLOWED_ACE_TYPE;
 +}
 +
 +/**
 + * richace_is_deny  -  check if @ace is a %DENY type entry
 + */
 +static inline int
 +richace_is_deny(const struct richace *ace)
 +{
 +      return ace->e_type == ACE4_ACCESS_DENIED_ACE_TYPE;
 +}
 +
 +extern struct richacl *richacl_alloc(int);
 +extern int richace_is_same_identifier(const struct richace *,
 +                                    const struct richace *);
 +extern int richace_set_who(struct richace *, const char *);
 +extern int richacl_masks_to_mode(const struct richacl *);
 +extern unsigned int richacl_mode_to_mask(mode_t);
 +extern unsigned int richacl_want_to_mask(int);
 +extern void richacl_compute_max_masks(struct richacl *);
 +extern struct richacl *richacl_chmod(struct richacl *, mode_t);
 +extern int richacl_permission(struct inode *, const struct richacl *,
-                             unsigned int);
++                            unsigned int, unsigned int);
 +extern struct richacl *richacl_inherit(const struct richacl *, struct inode *);
 +extern int richacl_equiv_mode(const struct richacl *, mode_t *);
 +
 +/* richacl_inode.c */
 +
 +#ifdef CONFIG_FS_RICHACL
 +extern int richacl_may_create(struct inode *, int,
-                             int (*)(struct inode *, unsigned int));
++                            int (*)(struct inode *, unsigned int,
++                                    unsigned int));
 +extern int richacl_may_delete(struct inode *, struct inode *, int,
-                             int (*)(struct inode *, unsigned int));
++                            int (*)(struct inode *, unsigned int,
++                                    unsigned int));
 +extern int richacl_inode_permission(struct inode *, const struct richacl *,
-                                   unsigned int);
++                                  unsigned int, unsigned int);
 +extern int richacl_inode_change_ok(struct inode *, struct iattr *,
-                                  int (*)(struct inode *, unsigned int));
++                                 int (*)(struct inode *, unsigned int,
++                                         unsigned int));
 +#else
 +static inline int
 +richacl_inode_change_ok(struct inode *inode, struct iattr *attr,
 +                      int (*richacl_permission)(struct inode *inode,
-                                                 unsigned int mask))
++                                                unsigned int mask,
++                                                unsigned int flags))
 +{
 +      return -EPERM;
 +}
 +#endif
 +
 +#endif /* __RICHACL_H */
Simple merge
@@@ -387,12 -393,10 +394,13 @@@ struct sk_buff 
  #else
        __u8                    deliver_no_wcard:1;
  #endif
+       __u8                    ooo_okay:1;
 +#ifdef        CONFIG_NETVM
 +      __u8                    emergency:1;
 +#endif
        kmemcheck_bitfield_end(flags2);
  
-       /* 0/14 bit hole */
 -      /* 0/13 bit hole */
++      /* 0/12 bit hole */
  
  #ifdef CONFIG_NET_DMA
        dma_cookie_t            dma_cookie;
@@@ -106,10 -106,6 +106,8 @@@ int kmem_cache_shrink(struct kmem_cach
  void kmem_cache_free(struct kmem_cache *, void *);
  unsigned int kmem_cache_size(struct kmem_cache *);
  const char *kmem_cache_name(struct kmem_cache *);
- int kern_ptr_validate(const void *ptr, unsigned long size);
- int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr);
 +unsigned kmem_alloc_estimate(struct kmem_cache *cachep,
 +                      gfp_t flags, int objects);
  
  /*
   * Please use this macro to create slab caches. Simply specify the
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc init/Kconfig
Simple merge
Simple merge
diff --cc kernel/Makefile
Simple merge
diff --cc kernel/audit.c
Simple merge
diff --cc kernel/module.c
Simple merge
diff --cc kernel/panic.c
Simple merge
diff --cc kernel/printk.c
@@@ -39,8 -39,7 +39,9 @@@
  #include <linux/syslog.h>
  #include <linux/cpu.h>
  #include <linux/notifier.h>
+ #include <linux/rculist.h>
 +#include <linux/jhash.h>
 +#include <linux/device.h>
  
  #include <asm/uaccess.h>
  
@@@ -1587,56 -1575,9 +1577,52 @@@ void kmsg_dump(enum kmsg_dump_reason re
                l2 = chars;
        }
  
-       if (!spin_trylock_irqsave(&dump_list_lock, flags)) {
-               printk(KERN_ERR "dump_kmsg: dump list lock is held during %s, skipping dump\n",
-                               kmsg_to_str(reason));
-               return;
-       }
-       list_for_each_entry(dumper, &dump_list, list)
+       rcu_read_lock();
+       list_for_each_entry_rcu(dumper, &dump_list, list)
                dumper->dump(dumper, reason, s1, l1, s2, l2);
-       spin_unlock_irqrestore(&dump_list_lock, flags);
+       rcu_read_unlock();
  }
  #endif
 +
 +#if defined CONFIG_PRINTK && defined CONFIG_KMSG_IDS
 +
 +/**
 + * printk_hash - print a kernel message include a hash over the message
 + * @prefix: message prefix including the ".%06x" for the hash
 + * @fmt: format string
 + */
 +asmlinkage int printk_hash(const char *prefix, const char *fmt, ...)
 +{
 +      va_list args;
 +      int r;
 +
 +      r = printk(prefix, jhash(fmt, strlen(fmt), 0) & 0xffffff);
 +      va_start(args, fmt);
 +      r += vprintk(fmt, args);
 +      va_end(args);
 +
 +      return r;
 +}
 +EXPORT_SYMBOL(printk_hash);
 +
 +/**
 + * printk_dev_hash - print a kernel message include a hash over the message
 + * @prefix: message prefix including the ".%06x" for the hash
 + * @dev: device this printk is all about
 + * @fmt: format string
 + */
 +asmlinkage int printk_dev_hash(const char *prefix, const char *driver_name,
 +                             const char *fmt, ...)
 +{
 +      va_list args;
 +      int r;
 +
 +      r = printk(prefix, driver_name, jhash(fmt, strlen(fmt), 0) & 0xffffff);
 +      va_start(args, fmt);
 +      r += vprintk(fmt, args);
 +      va_end(args);
 +
 +      return r;
 +}
 +EXPORT_SYMBOL(printk_dev_hash);
 +#endif
diff --cc kernel/sched.c
Simple merge
Simple merge
diff --cc kernel/sysctl.c
Simple merge
@@@ -136,9 -136,7 +136,8 @@@ static const struct bin_table bin_kern_
        { CTL_INT,      KERN_IA64_UNALIGNED,            "ignore-unaligned-usertrap" },
        { CTL_INT,      KERN_COMPAT_LOG,                "compat-log" },
        { CTL_INT,      KERN_MAX_LOCK_DEPTH,            "max_lock_depth" },
-       { CTL_INT,      KERN_NMI_WATCHDOG,              "nmi_watchdog" },
        { CTL_INT,      KERN_PANIC_ON_NMI,              "panic_on_unrecovered_nmi" },
 +      { CTL_INT,      KERN_SETUID_DUMPABLE,           "suid_dumpable" },
        {}
  };
  
Simple merge
diff --cc mm/Makefile
Simple merge
diff --cc mm/filemap.c
Simple merge
diff --cc mm/internal.h
Simple merge
diff --cc mm/memory.c
Simple merge
diff --cc mm/migrate.c
Simple merge
Simple merge
diff --cc mm/page_alloc.c
@@@ -1479,8 -1469,8 +1459,8 @@@ static bool __zone_watermark_ok(struct 
        if (alloc_flags & ALLOC_HARDER)
                min -= min / 4;
  
 -      if (free_pages <= min + z->lowmem_reserve[classzone_idx])
 +      if (free_pages <= min+z->lowmem_reserve[classzone_idx]+z->pages_emerg)
-               return 0;
+               return false;
        for (o = 0; o < order; o++) {
                /* At the next order, this order's pages become unavailable */
                free_pages -= z->free_area[o].nr_free << o;
@@@ -1931,12 -1942,12 +1934,11 @@@ void wake_all_kswapd(unsigned int order
        struct zone *zone;
  
        for_each_zone_zonelist(zone, z, zonelist, high_zoneidx)
-               wakeup_kswapd(zone, order);
+               wakeup_kswapd(zone, order, classzone_idx);
  }
  
 -static inline int
 -gfp_to_alloc_flags(gfp_t gfp_mask)
 +int gfp_to_alloc_flags(gfp_t gfp_mask)
  {
-       struct task_struct *p = current;
        int alloc_flags = ALLOC_WMARK_MIN | ALLOC_CPUSET;
        const gfp_t wait = gfp_mask & __GFP_WAIT;
  
                alloc_flags |= ALLOC_HARDER;
  
        if (likely(!(gfp_mask & __GFP_NOMEMALLOC))) {
 -              if (!in_interrupt() &&
 -                  ((current->flags & PF_MEMALLOC) ||
 -                   unlikely(test_thread_flag(TIF_MEMDIE))))
 +              if (gfp_mask & __GFP_MEMALLOC)
 +                      alloc_flags |= ALLOC_NO_WATERMARKS;
-               else if (!in_irq() && (p->flags & PF_MEMALLOC))
++              else if (!in_irq() && (current->flags & PF_MEMALLOC))
 +                      alloc_flags |= ALLOC_NO_WATERMARKS;
 +              else if (!in_interrupt() &&
 +                              unlikely(test_thread_flag(TIF_MEMDIE)))
                        alloc_flags |= ALLOC_NO_WATERMARKS;
        }
  
@@@ -1982,10 -1995,10 +1989,10 @@@ __alloc_pages_slowpath(gfp_t gfp_mask, 
  {
        const gfp_t wait = gfp_mask & __GFP_WAIT;
        struct page *page = NULL;
 -      int alloc_flags;
 +      int alloc_flags = 0;
        unsigned long pages_reclaimed = 0;
        unsigned long did_some_progress;
-       struct task_struct *p = current;
+       bool sync_migration = false;
  
        /*
         * In the slowpath, we sanity check order to avoid ever trying to
@@@ -2118,15 -2147,9 +2146,16 @@@ rebalance
  
  nopage:
        if (!(gfp_mask & __GFP_NOWARN) && printk_ratelimit()) {
 -              printk(KERN_WARNING "%s: page allocation failure."
 -                      " order:%d, mode:0x%x\n",
 -                      current->comm, order, gfp_mask);
 +              if (!wait) {
 +                      printk(KERN_INFO "The following is only an harmless informational message.\n");
 +                      printk(KERN_INFO "Unless you get a _continuous_flood_ of these messages it means\n");
 +                      printk(KERN_INFO "everything is working fine. Allocations from irqs cannot be\n");
 +                      printk(KERN_INFO "perfectly reliable and the kernel is designed to handle that.\n");
 +              }
 +              printk(KERN_INFO "%s: page allocation failure."
 +                      " order:%d, mode:0x%x, alloc_flags:0x%x pflags:0x%x\n",
-                       p->comm, order, gfp_mask, alloc_flags, p->flags);
++                      current->comm, order, gfp_mask, alloc_flags,
++                      current->flags);
                dump_stack();
                show_mem();
        }
@@@ -2460,10 -2483,10 +2489,10 @@@ void show_free_areas(void
                        " all_unreclaimable? %s"
                        "\n",
                        zone->name,
-                       K(zone_nr_free_pages(zone)),
+                       K(zone_page_state(zone, NR_FREE_PAGES)),
 -                      K(min_wmark_pages(zone)),
 -                      K(low_wmark_pages(zone)),
 -                      K(high_wmark_pages(zone)),
 +                      K(zone->pages_emerg + min_wmark_pages(zone)),
 +                      K(zone->pages_emerg + low_wmark_pages(zone)),
 +                      K(zone->pages_emerg + high_wmark_pages(zone)),
                        K(zone_page_state(zone, NR_ACTIVE_ANON)),
                        K(zone_page_state(zone, NR_INACTIVE_ANON)),
                        K(zone_page_state(zone, NR_ACTIVE_FILE)),
@@@ -5012,72 -5021,6 +5032,72 @@@ static void __init setup_per_zone_inact
                calculate_zone_inactive_ratio(zone);
  }
  
 +void setup_per_zone_wmarks(void)
 +{
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&min_free_lock, flags);
 +      __setup_per_zone_wmarks();
 +      spin_unlock_irqrestore(&min_free_lock, flags);
 +}
 +
 +static void __adjust_memalloc_reserve(int pages)
 +{
 +      var_free_kbytes += pages << (PAGE_SHIFT - 10);
 +      BUG_ON(var_free_kbytes < 0);
 +      setup_per_zone_wmarks();
 +}
 +
 +static int test_reserve_limits(void)
 +{
 +      struct zone *zone;
 +      int node;
 +
 +      for_each_zone(zone)
-               wakeup_kswapd(zone, 0);
++              wakeup_kswapd(zone, 0, zone_idx(zone));
 +
 +      for_each_online_node(node) {
 +              struct page *page = alloc_pages_node(node, GFP_KERNEL, 0);
 +              if (!page)
 +                      return -ENOMEM;
 +
 +              __free_page(page);
 +      }
 +
 +      return 0;
 +}
 +
 +/**
 + *    adjust_memalloc_reserve - adjust the memalloc reserve
 + *    @pages: number of pages to add
 + *
 + *    It adds a number of pages to the memalloc reserve; if
 + *    the number was positive it kicks reclaim into action to
 + *    satisfy the higher watermarks.
 + *
 + *    returns -ENOMEM when it failed to satisfy the watermarks.
 + */
 +int adjust_memalloc_reserve(int pages)
 +{
 +      int err = 0;
 +
 +      mutex_lock(&var_free_mutex);
 +      __adjust_memalloc_reserve(pages);
 +      if (pages > 0) {
 +              err = test_reserve_limits();
 +              if (err) {
 +                      __adjust_memalloc_reserve(-pages);
 +                      goto unlock;
 +              }
 +      }
 +      printk(KERN_DEBUG "Emergency reserve: %d\n", var_free_kbytes);
 +
 +unlock:
 +      mutex_unlock(&var_free_mutex);
 +      return err;
 +}
 +EXPORT_SYMBOL_GPL(adjust_memalloc_reserve);
 +
  /*
   * Initialise min_free_kbytes.
   *
diff --cc mm/page_io.c
@@@ -100,24 -98,6 +100,17 @@@ int swap_writepage(struct page *page, s
                unlock_page(page);
                goto out;
        }
 +
 +      if (sis->flags & SWP_FILE) {
 +              struct file *swap_file = sis->swap_file;
 +              struct address_space *mapping = swap_file->f_mapping;
 +
 +              ret = mapping->a_ops->swap_out(swap_file, page, wbc);
 +              if (!ret)
 +                      count_vm_event(PSWPOUT);
 +              return ret;
 +      }
 +
-       if (preswap_put(page) == 1) {
-               set_page_writeback(page);
-               unlock_page(page);
-               end_page_writeback(page);
-               goto out;
-       }
        bio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write);
        if (bio == NULL) {
                set_page_dirty(page);
@@@ -175,23 -122,6 +168,17 @@@ int swap_readpage(struct page *page
  
        VM_BUG_ON(!PageLocked(page));
        VM_BUG_ON(PageUptodate(page));
 +
 +      if (sis->flags & SWP_FILE) {
 +              struct file *swap_file = sis->swap_file;
 +              struct address_space *mapping = swap_file->f_mapping;
 +
 +              ret = mapping->a_ops->swap_in(swap_file, page);
 +              if (!ret)
 +                      count_vm_event(PSWPIN);
 +              return ret;
 +      }
 +
-       if (preswap_get(page) == 1) {
-               SetPageUptodate(page);
-               unlock_page(page);
-               goto out;
-       }
        bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read);
        if (bio == NULL) {
                unlock_page(page);
diff --cc mm/slab.c
Simple merge
diff --cc mm/slob.c
Simple merge
diff --cc mm/slub.c
+++ b/mm/slub.c
  #include <linux/memory.h>
  #include <linux/math64.h>
  #include <linux/fault-inject.h>
 +#include "internal.h"
 +
  
+ #include <trace/events/kmem.h>
  /*
   * Lock order:
   *   1. slab_lock(page)
diff --cc mm/swap_state.c
Simple merge
diff --cc mm/swapfile.c
@@@ -588,12 -589,9 +588,11 @@@ static unsigned char swap_entry_free(st
                        swap_list.next = p->type;
                nr_swap_pages++;
                p->inuse_pages--;
-               preswap_flush(p->type, offset);
 -              if ((p->flags & SWP_BLKDEV) &&
 -                              disk->fops->swap_slot_free_notify)
 -                      disk->fops->swap_slot_free_notify(p->bdev, offset);
 +              if (p->flags & SWP_BLKDEV) {
 +                      struct gendisk *disk = p->bdev->bd_disk;
 +                      if (disk->fops->swap_slot_free_notify)
 +                              disk->fops->swap_slot_free_notify(p->bdev, offset);
 +              }
        }
  
        return usage;
diff --cc mm/vmscan.c
Simple merge
diff --cc mm/vmstat.c
@@@ -834,10 -956,10 +956,10 @@@ static void zoneinfo_show_print(struct 
                   "\n        scanned  %lu"
                   "\n        spanned  %lu"
                   "\n        present  %lu",
-                  zone_nr_free_pages(zone),
+                  zone_page_state(zone, NR_FREE_PAGES),
 -                 min_wmark_pages(zone),
 -                 low_wmark_pages(zone),
 -                 high_wmark_pages(zone),
 +                 zone->pages_emerg + min_wmark_pages(zone),
 +                 zone->pages_emerg + min_wmark_pages(zone),
 +                 zone->pages_emerg + high_wmark_pages(zone),
                   zone->pages_scanned,
                   zone->spanned_pages,
                   zone->present_pages);
diff --cc net/Kconfig
Simple merge
Simple merge
Simple merge
diff --cc net/core/dev.c
Simple merge
Simple merge
@@@ -845,11 -780,29 +847,33 @@@ int pskb_expand_head(struct sk_buff *sk
  
        size = SKB_DATA_ALIGN(size);
  
+       /* Check if we can avoid taking references on fragments if we own
+        * the last reference on skb->head. (see skb_release_data())
+        */
+       if (!skb->cloned)
+               fastpath = true;
+       else {
+               int delta = skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1;
+               fastpath = atomic_read(&skb_shinfo(skb)->dataref) == delta;
+       }
+       if (fastpath &&
+           size + sizeof(struct skb_shared_info) <= ksize(skb->head)) {
+               memmove(skb->head + size, skb_shinfo(skb),
+                       offsetof(struct skb_shared_info,
+                                frags[skb_shinfo(skb)->nr_frags]));
+               memmove(skb->head + nhead, skb->head,
+                       skb_tail_pointer(skb) - skb->head);
+               off = nhead;
+               goto adjust_others;
+       }
 -      data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
 +      if (skb_emergency(skb))
 +              gfp_mask |= __GFP_MEMALLOC;
 +
 +      data = kmalloc_reserve(size + sizeof(struct skb_shared_info),
 +                      gfp_mask, -1, &net_skb_reserve, NULL);
        if (!data)
                goto nodata;
  
diff --cc net/core/sock.c
Simple merge
@@@ -45,8 -45,7 +45,9 @@@
  #include <linux/udp.h>
  #include <linux/inet.h>
  #include <linux/netfilter_ipv4.h>
+ #include <net/inet_ecn.h>
 +#include <linux/reserve.h>
 +#include <linux/nsproxy.h>
  
  /* NOTE. Logic of IP defragmentation is parallel to corresponding IPv6
   * code now. If you change something here, _PLEASE_ update ipv6/reassembly.c
Simple merge
diff --cc net/ipv4/tcp.c
Simple merge
Simple merge
Simple merge
@@@ -2669,8 -2669,9 +2669,7 @@@ static int addrconf_ifdown(struct net_d
  
        ASSERT_RTNL();
  
 -      /* Flush routes if device is being removed or it is not loopback */
 -      if (how || !(dev->flags & IFF_LOOPBACK))
 -              rt6_ifdown(net, dev);
 +      rt6_ifdown(net, dev);
-       neigh_ifdown(&nd_tbl, dev);
  
        idev = __in6_dev_get(dev);
        if (idev == NULL)
Simple merge
Simple merge
Simple merge
@@@ -4,7 -4,9 +4,8 @@@ config MAC8021
        select CRYPTO
        select CRYPTO_ECB
        select CRYPTO_ARC4
 -      select CRYPTO_AES
        select CRC32
+       select AVERAGE
        ---help---
          This option enables the hardware independent IEEE 802.11
          networking stack.
@@@ -173,13 -173,12 +173,15 @@@ next_hook
                             outdev, &elem, okfn, hook_thresh);
        if (verdict == NF_ACCEPT || verdict == NF_STOP) {
                ret = 1;
-       } else if (verdict == NF_DROP) {
+       } else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {
 +drop:
                kfree_skb(skb);
-               ret = -EPERM;
+               ret = -(verdict >> NF_VERDICT_BITS);
+               if (ret == 0)
+                       ret = -EPERM;
        } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
 +              if (skb_emergency(skb))
 +                      goto drop;
                if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
                              verdict >> NF_VERDICT_BITS))
                        goto next_hook;
Simple merge
@@@ -965,9 -965,10 +965,10 @@@ struct rpc_xprt *xprt_alloc(struct net 
        xprt = kzalloc(size, GFP_KERNEL);
        if (xprt == NULL)
                goto out;
+       kref_init(&xprt->kref);
  
        xprt->max_reqs = max_req;
 -      xprt->slot = kcalloc(max_req, sizeof(struct rpc_rqst), GFP_KERNEL);
 +      xprt->slot = kcalloc(max_req, sizeof(struct rpc_rqst), GFP_KERNEL | __GFP_REPEAT);
        if (xprt->slot == NULL)
                goto out_free;
  
Simple merge
Simple merge
Simple merge
@@@ -512,8 -512,16 +512,17 @@@ int security_inode_permission(struct in
                return 0;
        return security_ops->inode_permission(inode, mask);
  }
 +EXPORT_SYMBOL_GPL(security_inode_permission);
  
+ int security_inode_exec_permission(struct inode *inode, unsigned int flags)
+ {
+       if (unlikely(IS_PRIVATE(inode)))
+               return 0;
+       if (flags)
+               return -ECHILD;
+       return security_ops->inode_permission(inode, MAY_EXEC);
+ }
  int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
  {
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
Simple merge
index 0000000,e1c62ee..e1c62ee
mode 000000,100755..100644
--- /dev/null