diff options
| author | James Simmons <jsimmons@kozmo.(none)> | 2003-03-26 00:00:40 -0800 |
|---|---|---|
| committer | James Simmons <jsimmons@kozmo.(none)> | 2003-03-26 00:00:40 -0800 |
| commit | 80d0fb70c7c053db2a9a0dcfdaeb8b56c959a188 (patch) | |
| tree | d80e5c2dc80bf0a914640dfa713519b6c88e7fe7 | |
| parent | c84b483af9fa45e631ccfc87a55e9b6edfb44d3c (diff) | |
| parent | fff263fed6ff605fdb20bfd3105f4117f30fb24a (diff) | |
Merge kozmo.(none):/usr/src/linus-2.5
into kozmo.(none):/usr/src/fbdev-2.5
118 files changed, 3712 insertions, 4157 deletions
@@ -1210,6 +1210,10 @@ S: 25360 Georgia Tech Station S: Atlanta, Georgia 30332 S: USA +N: Brad Hards +E: bradh@frogmouth.net +D: Various USB bits, other minor patches + N: Angelo Haritsis E: ah@computer.org D: kernel patches (serial, watchdog) diff --git a/MAINTAINERS b/MAINTAINERS index 7b7c9edf37b0..fef4dadcfffb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1869,11 +1869,12 @@ S: Maintained W: http://www.kroah.com/linux-usb/ USB CDC ETHERNET DRIVER -P: Brad Hards -M: bradh@frogmouth.net +P: Greg Kroah-Hartman +M: greg@kroah.com L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained +W: http://www.kroah.com/linux-usb/ USB EHCI DRIVER P: David Brownell diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index a5ff3a48a8fd..e87ca474a11c 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -76,7 +76,6 @@ #include <pcmcia/cistpl.h> #include <pcmcia/cisreg.h> #include <pcmcia/ds.h> -#include <pcmcia/bus_ops.h> #ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE #define CONFIG_SYNCLINK_SYNCPPP 1 @@ -241,7 +240,6 @@ typedef struct _mgslpc_info { dev_link_t link; dev_node_t node; int stop; - struct bus_operations *bus; /* SPPP/Cisco HDLC device parts */ int netcount; @@ -826,7 +824,6 @@ static int mgslpc_event(event_t event, int priority, break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - info->bus = args->bus; mgslpc_config(link); break; case CS_EVENT_PM_SUSPEND: diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index b79f67749311..00afdc97de31 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -53,7 +53,6 @@ #include <pcmcia/cistpl.h> #include <pcmcia/cisreg.h> #include <pcmcia/ds.h> -#include <pcmcia/bus_ops.h> MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Elsa PCM cards"); MODULE_AUTHOR("Klaus Lichtenwalder"); @@ -163,17 +162,12 @@ static dev_link_t *dev_list = NULL; "stopped" due to a power management event, or card ejection. The device IO routines can use a flag like this to throttle IO to a card that is not ready to accept it. - - The bus_operations pointer is used on platforms for which we need - to use special socket-specific versions of normal IO primitives - (inb, outb, readb, writeb, etc) for card IO. */ typedef struct local_info_t { dev_link_t link; dev_node_t node; int busy; - struct bus_operations *bus; } local_info_t; /*====================================================================*/ @@ -522,7 +516,6 @@ static int elsa_cs_event(event_t event, int priority, break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - dev->bus = args->bus; elsa_cs_config(link); break; case CS_EVENT_PM_SUSPEND: diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index a796311f7ae2..3ff07122b9fc 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -53,7 +53,6 @@ #include <pcmcia/cistpl.h> #include <pcmcia/cisreg.h> #include <pcmcia/ds.h> -#include <pcmcia/bus_ops.h> MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Sedlbauer cards"); MODULE_AUTHOR("Marcus Niemann"); @@ -171,17 +170,12 @@ static dev_link_t *dev_list = NULL; "stopped" due to a power management event, or card ejection. The device IO routines can use a flag like this to throttle IO to a card that is not ready to accept it. - - The bus_operations pointer is used on platforms for which we need - to use special socket-specific versions of normal IO primitives - (inb, outb, readb, writeb, etc) for card IO. */ typedef struct local_info_t { dev_link_t link; dev_node_t node; int stop; - struct bus_operations *bus; } local_info_t; /*====================================================================*/ @@ -620,7 +614,6 @@ static int sedlbauer_event(event_t event, int priority, break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - dev->bus = args->bus; sedlbauer_config(link); break; case CS_EVENT_PM_SUSPEND: diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 78ca0a2b3843..547939fdd943 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -29,6 +29,9 @@ ifdef CONFIG_HOTPLUG_PCI_CPCI obj-y += setup-bus.o endif +# Hotplug (eg, cardbus) now requires setup-bus +obj-$(CONFIG_HOTPLUG) += setup-bus.o + ifndef CONFIG_X86 obj-y += syscall.o endif diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index f6ea2466e1a8..357f836ea987 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -87,5 +87,9 @@ config PCMCIA_SA1111 tristate "SA1111 support" depends on PCMCIA_SA1100 && SA1111 +config PCMCIA_PROBE + bool + default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X + endmenu diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 64145126b7c8..9a593be3f399 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -2,46 +2,43 @@ # Makefile for the kernel pcmcia subsystem (c/o David Hinds) # -obj-$(CONFIG_PCMCIA) += pcmcia_core.o ds.o +obj-$(CONFIG_PCMCIA) += pcmcia_core.o ds.o ifeq ($(CONFIG_CARDBUS),y) - obj-$(CONFIG_PCMCIA) += yenta_socket.o + obj-$(CONFIG_PCMCIA) += yenta_socket.o endif -obj-$(CONFIG_I82365) += i82365.o -obj-$(CONFIG_I82092) += i82092.o -obj-$(CONFIG_TCIC) += tcic.o -obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o -obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o -obj-$(CONFIG_PCMCIA_SA1111) += sa1111_cs.o +obj-$(CONFIG_I82365) += i82365.o +obj-$(CONFIG_I82092) += i82092.o +obj-$(CONFIG_TCIC) += tcic.o +obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o +obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o +obj-$(CONFIG_PCMCIA_SA1111) += sa1111_cs.o -yenta_socket-objs := pci_socket.o yenta.o +yenta_socket-y += pci_socket.o yenta.o -pcmcia_core-objs-y := cistpl.o rsrc_mgr.o bulkmem.o cs.o -pcmcia_core-objs-$(CONFIG_CARDBUS) += cardbus.o -pcmcia_core-objs := $(pcmcia_core-objs-y) +pcmcia_core-y += cistpl.o rsrc_mgr.o bulkmem.o cs.o +pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o -sa1111_cs-objs-y := sa1111_generic.o -sa1111_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o -sa1111_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o -sa1111_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o -sa1111_cs-objs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o -sa1111_cs-objs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o -sa1111_cs-objs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o -sa1111_cs-objs-$(CONFIG_SA1100_PT_SYSTEM3) += sa1100_system3.o -sa1111_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o -sa1111_cs-objs := $(sa1111_cs-objs-y) +sa1111_cs-y += sa1111_generic.o +sa1111_cs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o +sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o +sa1111_cs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o +sa1111_cs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o +sa1111_cs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o +sa1111_cs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o +sa1111_cs-$(CONFIG_SA1100_PT_SYSTEM3) += sa1100_system3.o +sa1111_cs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o -sa1100_cs-objs-y := sa1100_generic.o -sa1100_cs-objs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o -sa1100_cs-objs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o -sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o -sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o -sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSCLIENT) += sa1100_graphicsclient.o -sa1100_cs-objs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o -sa1100_cs-objs-$(CONFIG_SA1100_PANGOLIN) += sa1100_pangolin.o -sa1100_cs-objs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o -sa1100_cs-objs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o -sa1100_cs-objs-$(CONFIG_SA1100_STORK) += sa1100_stork.o -sa1100_cs-objs-$(CONFIG_SA1100_TRIZEPS) += sa1100_trizeps.o -sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o -sa1100_cs-objs := $(sa1100_cs-objs-y) +sa1100_cs-y += sa1100_generic.o +sa1100_cs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o +sa1100_cs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o +sa1100_cs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o +sa1100_cs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o +sa1100_cs-$(CONFIG_SA1100_GRAPHICSCLIENT) += sa1100_graphicsclient.o +sa1100_cs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o +sa1100_cs-$(CONFIG_SA1100_PANGOLIN) += sa1100_pangolin.o +sa1100_cs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o +sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o +sa1100_cs-$(CONFIG_SA1100_STORK) += sa1100_stork.o +sa1100_cs-$(CONFIG_SA1100_TRIZEPS) += sa1100_trizeps.o +sa1100_cs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 40c33fc21ba5..00c30ba3ff56 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -87,10 +87,6 @@ static int pc_debug = PCMCIA_DEBUG; #define PCDATA_CODE_TYPE 0x0014 #define PCDATA_INDICATOR 0x0015 -typedef struct cb_config_t { - struct pci_dev *dev[8]; -} cb_config_t; - /*===================================================================== Expansion ROM's have a special layout, and pointers specify an @@ -173,11 +169,10 @@ int read_cb_mem(socket_info_t * s, int space, u_int addr, u_int len, void *ptr) DEBUG(3, "cs: read_cb_mem(%d, %#x, %u)\n", space, addr, len); - if (!s->cb_config) + dev = pci_find_slot(s->cap.cb_dev->subordinate->number, 0); + if (!dev) goto fail; - dev = s->cb_config->dev[0]; - /* Config space? */ if (space == 0) { if (addr + len > 0x100) @@ -219,171 +214,61 @@ fail: =====================================================================*/ -int cb_alloc(socket_info_t * s) +/* + * Since there is only one interrupt available to CardBus + * devices, all devices downstream of this device must + * be using this IRQ. + */ +static void cardbus_assign_irqs(struct pci_bus *bus, int irq) { - struct pci_bus *bus; - u_short vend, v, dev; - u_char i, hdr, fn; - cb_config_t *c; - int irq; - - bus = s->cap.cb_dev->subordinate; - - pci_bus_read_config_word(bus, 0, PCI_VENDOR_ID, &vend); - pci_bus_read_config_word(bus, 0, PCI_DEVICE_ID, &dev); - printk(KERN_INFO "cs: cb_alloc(bus %d): vendor 0x%04x, " - "device 0x%04x\n", bus->number, vend, dev); - - pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr); - fn = 1; - if (hdr & 0x80) { - do { - if (pci_bus_read_config_word(bus, fn, PCI_VENDOR_ID, &v) || - !v || v == 0xffff) - break; - fn++; - } while (fn < 8); - } - s->functions = fn; - - c = kmalloc(sizeof(struct cb_config_t), GFP_ATOMIC); - if (!c) - return CS_OUT_OF_RESOURCE; - memset(c, 0, sizeof(struct cb_config_t)); - - for (i = 0; i < fn; i++) { - c->dev[i] = kmalloc(sizeof(struct pci_dev), GFP_ATOMIC); - if (!c->dev[i]) { - for (; i--; ) - kfree(c->dev[i]); - kfree(c); - return CS_OUT_OF_RESOURCE; - } - memset(c->dev[i], 0, sizeof(struct pci_dev)); - } + struct pci_dev *dev; - irq = s->cap.pci_irq; - for (i = 0; i < fn; i++) { - struct pci_dev *dev = c->dev[i]; + list_for_each_entry(dev, &bus->devices, bus_list) { u8 irq_pin; - int r; - - dev->bus = bus; - dev->sysdata = bus->sysdata; - dev->dev.parent = bus->dev; - dev->dev.bus = &pci_bus_type; - dev->devfn = i; - - pci_read_config_word(dev, PCI_VENDOR_ID, &dev->vendor); - pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device); - dev->hdr_type = hdr & 0x7f; - dev->dma_mask = 0xffffffff; - dev->dev.dma_mask = &dev->dma_mask; - - pci_setup_device(dev); - strcpy(dev->dev.bus_id, dev->slot_name); - - /* We need to assign resources for expansion ROM. */ - for (r = 0; r < 7; r++) { - struct resource *res = dev->resource + r; - if (res->flags) - pci_assign_resource(dev, r); - } - - /* Does this function have an interrupt at all? */ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin); - if (irq_pin) + if (irq_pin) { dev->irq = irq; - - /* pci_enable_device needs to be called after pci_assign_resource */ - /* because it returns an error if (!res->start && res->end). */ - if (pci_enable_device(dev)) - continue; - - if (irq_pin) - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); - - device_register(&dev->dev); - pci_insert_device(dev, bus); - } - - s->cb_config = c; - s->irq.AssignedIRQ = irq; - return CS_SUCCESS; -} - -void cb_free(socket_info_t * s) -{ - cb_config_t *c = s->cb_config; - - if (c) { - s->cb_config = NULL; - pci_remove_behind_bridge(s->cap.cb_dev); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } - kfree(c); - printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cb_dev->subordinate->number); + if (dev->subordinate) + cardbus_assign_irqs(dev->subordinate, irq); } } -/*===================================================================== - - cb_enable() has the job of configuring a socket for a Cardbus - card, and initializing the card's PCI configuration registers. - - It first sets up the Cardbus bridge windows, for IO and memory - accesses. Then, it initializes each card function's base address - registers, interrupt line register, and command register. - - It is called as part of the RequestConfiguration card service. - It should be called after a previous call to cb_config() (via the - RequestIO service). - -======================================================================*/ - -void cb_enable(socket_info_t * s) +int cb_alloc(socket_info_t * s) { + struct pci_bus *bus = s->cap.cb_dev->subordinate; struct pci_dev *dev; - u_char i; - - DEBUG(0, "cs: cb_enable(bus %d)\n", s->cap.cb_dev->subordinate->number); - - /* Configure bridge */ - cb_release_cis_mem(s); - - /* Set up PCI interrupt and command registers */ - for (i = 0; i < s->functions; i++) { - dev = s->cb_config->dev[i]; - pci_write_config_byte(dev, PCI_COMMAND, PCI_COMMAND_MASTER | - PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, - L1_CACHE_BYTES / 4); - } - - if (s->irq.AssignedIRQ) { - for (i = 0; i < s->functions; i++) { - dev = s->cb_config->dev[i]; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - s->irq.AssignedIRQ); - } - s->socket.io_irq = s->irq.AssignedIRQ; - s->ss_entry->set_socket(s->sock, &s->socket); - } + unsigned int max, pass; + + s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); +// pcibios_fixup_bus(bus); + + max = bus->secondary; + for (pass = 0; pass < 2; pass++) + list_for_each_entry(dev, &bus->devices, bus_list) + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || + dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) + max = pci_scan_bridge(bus, dev, max, pass); + + /* + * Size all resources below the CardBus controller. + */ + pci_bus_size_bridges(bus); + pci_bus_assign_resources(bus); + cardbus_assign_irqs(bus, s->cap.pci_irq); + pci_enable_bridges(bus); + pci_bus_add_devices(bus); + + s->irq.AssignedIRQ = s->cap.pci_irq; + return CS_SUCCESS; } -/*====================================================================== - - cb_disable() unconfigures a Cardbus card previously set up by - cb_enable(). - - It is called from the ReleaseConfiguration service. - -======================================================================*/ - -void cb_disable(socket_info_t * s) +void cb_free(socket_info_t * s) { - DEBUG(0, "cs: cb_disable(bus %d)\n", s->cap.cb_dev->subordinate->number); + struct pci_dev *bridge = s->cap.cb_dev; - /* Turn off bridge windows */ - cb_release_cis_mem(s); + pci_remove_behind_bridge(bridge); } diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index e21005d25e45..c34acc53ebe3 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -47,7 +47,6 @@ #include <asm/byteorder.h> #include <pcmcia/cs_types.h> -#include <pcmcia/bus_ops.h> #include <pcmcia/ss.h> #include <pcmcia/cs.h> #include <pcmcia/bulkmem.h> @@ -83,6 +82,52 @@ static const u_int exponent[] = { INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */ +void release_cis_mem(socket_info_t *s) +{ + if (s->cis_mem.sys_start != 0) { + s->cis_mem.flags &= ~MAP_ACTIVE; + s->ss_entry->set_mem_map(s->sock, &s->cis_mem); + if (!(s->cap.features & SS_CAP_STATIC_MAP)) + release_mem_region(s->cis_mem.sys_start, s->cap.map_size); + iounmap(s->cis_virt); + s->cis_mem.sys_start = 0; + s->cis_virt = NULL; + } +} + +/* + * Map the card memory at "card_offset" into virtual space. + * If flags & MAP_ATTRIB, map the attribute space, otherwise + * map the memory space. + */ +static unsigned char * +set_cis_map(socket_info_t *s, unsigned int card_offset, unsigned int flags) +{ + pccard_mem_map *mem = &s->cis_mem; + if (!(s->cap.features & SS_CAP_STATIC_MAP) && + mem->sys_start == 0) { + int low = !(s->cap.features & SS_CAP_PAGE_REGS); + validate_mem(s); + mem->sys_start = 0; + if (find_mem_region(&mem->sys_start, s->cap.map_size, + s->cap.map_size, low, "card services", s)) { + printk(KERN_NOTICE "cs: unable to map card memory!\n"); + return NULL; + } + mem->sys_stop = mem->sys_start+s->cap.map_size-1; + s->cis_virt = ioremap(mem->sys_start, s->cap.map_size); + } + mem->card_start = card_offset; + mem->flags = flags; + s->ss_entry->set_mem_map(s->sock, mem); + if (s->cap.features & SS_CAP_STATIC_MAP) { + if (s->cis_virt) + iounmap(s->cis_virt); + s->cis_virt = ioremap(mem->sys_start, s->cap.map_size); + } + return s->cis_virt; +} + /*====================================================================== Low-level functions to read and write CIS memory. I think the @@ -94,60 +139,60 @@ INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */ #define IS_ATTR 1 #define IS_INDIRECT 8 -static int setup_cis_mem(socket_info_t *s); - -static void set_cis_map(socket_info_t *s, pccard_mem_map *mem) -{ - s->ss_entry->set_mem_map(s->sock, mem); - if (s->cap.features & SS_CAP_STATIC_MAP) { - if (s->cis_virt) - bus_iounmap(s->cap.bus, s->cis_virt); - s->cis_virt = bus_ioremap(s->cap.bus, mem->sys_start, - s->cap.map_size); - } -} - int read_cis_mem(socket_info_t *s, int attr, u_int addr, u_int len, void *ptr) { - pccard_mem_map *mem = &s->cis_mem; - u_char *sys, *buf = ptr; + u_char *sys, *end, *buf = ptr; DEBUG(3, "cs: read_cis_mem(%d, %#x, %u)\n", attr, addr, len); - if (setup_cis_mem(s) != 0) { - memset(ptr, 0xff, len); - return -1; - } - mem->flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0); if (attr & IS_INDIRECT) { /* Indirect accesses use a bunch of special registers at fixed locations in common memory */ u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN; - if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; } - mem->card_start = 0; mem->flags = MAP_ACTIVE; - set_cis_map(s, mem); - sys = s->cis_virt; - bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0); - bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0); - bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1); - bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2); - bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3); + if (attr & IS_ATTR) { + addr *= 2; + flags = ICTRL0_AUTOINC; + } + + sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0)); + if (!sys) { + memset(ptr, 0xff, len); + return -1; + } + + writeb(flags, sys+CISREG_ICTRL0); + writeb(addr & 0xff, sys+CISREG_IADDR0); + writeb((addr>>8) & 0xff, sys+CISREG_IADDR1); + writeb((addr>>16) & 0xff, sys+CISREG_IADDR2); + writeb((addr>>24) & 0xff, sys+CISREG_IADDR3); for ( ; len > 0; len--, buf++) - *buf = bus_readb(s->cap.bus, sys+CISREG_IDATA0); + *buf = readb(sys+CISREG_IDATA0); } else { - u_int inc = 1; - if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; } - sys += (addr & (s->cap.map_size-1)); - mem->card_start = addr & ~(s->cap.map_size-1); + u_int inc = 1, card_offset, flags; + + flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0); + if (attr) { + flags |= MAP_ATTRIB; + inc++; + addr *= 2; + } + + card_offset = addr & ~(s->cap.map_size-1); while (len) { - set_cis_map(s, mem); - sys = s->cis_virt + (addr & (s->cap.map_size-1)); + sys = set_cis_map(s, card_offset, flags); + if (!sys) { + memset(ptr, 0xff, len); + return -1; + } + end = sys + s->cap.map_size; + sys = sys + (addr & (s->cap.map_size-1)); for ( ; len > 0; len--, buf++, sys += inc) { - if (sys == s->cis_virt+s->cap.map_size) break; - *buf = bus_readb(s->cap.bus, sys); + if (sys == end) + break; + *buf = readb(sys); } - mem->card_start += s->cap.map_size; + card_offset += s->cap.map_size; addr = 0; } } @@ -160,134 +205,56 @@ int read_cis_mem(socket_info_t *s, int attr, u_int addr, void write_cis_mem(socket_info_t *s, int attr, u_int addr, u_int len, void *ptr) { - pccard_mem_map *mem = &s->cis_mem; - u_char *sys, *buf = ptr; + u_char *sys, *end, *buf = ptr; DEBUG(3, "cs: write_cis_mem(%d, %#x, %u)\n", attr, addr, len); - if (setup_cis_mem(s) != 0) return; - mem->flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0); if (attr & IS_INDIRECT) { /* Indirect accesses use a bunch of special registers at fixed locations in common memory */ u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN; - if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; } - mem->card_start = 0; mem->flags = MAP_ACTIVE; - set_cis_map(s, mem); - sys = s->cis_virt; - bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0); - bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0); - bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1); - bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2); - bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3); - for ( ; len > 0; len--, buf++) - bus_writeb(s->cap.bus, *buf, sys+CISREG_IDATA0); - } else { - int inc = 1; - if (attr & IS_ATTR) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; } - mem->card_start = addr & ~(s->cap.map_size-1); - while (len) { - set_cis_map(s, mem); - sys = s->cis_virt + (addr & (s->cap.map_size-1)); - for ( ; len > 0; len--, buf++, sys += inc) { - if (sys == s->cis_virt+s->cap.map_size) break; - bus_writeb(s->cap.bus, *buf, sys); - } - mem->card_start += s->cap.map_size; - addr = 0; + if (attr & IS_ATTR) { + addr *= 2; + flags = ICTRL0_AUTOINC; } - } -} - -/*====================================================================== - - This is tricky... when we set up CIS memory, we try to validate - the memory window space allocations. - -======================================================================*/ -/* Scratch pointer to the socket we use for validation */ -static socket_info_t *vs = NULL; + sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0)); + if (!sys) + return; /* FIXME: Error */ -/* Validation function for cards with a valid CIS */ -static int cis_readable(u_long base) -{ - cisinfo_t info1, info2; - int ret; - vs->cis_mem.sys_start = base; - vs->cis_mem.sys_stop = base+vs->cap.map_size-1; - vs->cis_virt = bus_ioremap(vs->cap.bus, base, vs->cap.map_size); - ret = pcmcia_validate_cis(vs->clients, &info1); - /* invalidate mapping and CIS cache */ - bus_iounmap(vs->cap.bus, vs->cis_virt); vs->cis_used = 0; - if ((ret != 0) || (info1.Chains == 0)) - return 0; - vs->cis_mem.sys_start = base+vs->cap.map_size; - vs->cis_mem.sys_stop = base+2*vs->cap.map_size-1; - vs->cis_virt = bus_ioremap(vs->cap.bus, base+vs->cap.map_size, - vs->cap.map_size); - ret = pcmcia_validate_cis(vs->clients, &info2); - bus_iounmap(vs->cap.bus, vs->cis_virt); vs->cis_used = 0; - return ((ret == 0) && (info1.Chains == info2.Chains)); -} + writeb(flags, sys+CISREG_ICTRL0); + writeb(addr & 0xff, sys+CISREG_IADDR0); + writeb((addr>>8) & 0xff, sys+CISREG_IADDR1); + writeb((addr>>16) & 0xff, sys+CISREG_IADDR2); + writeb((addr>>24) & 0xff, sys+CISREG_IADDR3); + for ( ; len > 0; len--, buf++) + writeb(*buf, sys+CISREG_IDATA0); + } else { + u_int inc = 1, card_offset, flags; -/* Validation function for simple memory cards */ -static int checksum(u_long base) -{ - int i, a, b, d; - vs->cis_mem.sys_start = base; - vs->cis_mem.sys_stop = base+vs->cap.map_size-1; - vs->cis_virt = bus_ioremap(vs->cap.bus, base, vs->cap.map_size); - vs->cis_mem.card_start = 0; - vs->cis_mem.flags = MAP_ACTIVE; - vs->ss_entry->set_mem_map(vs->sock, &vs->cis_mem); - /* Don't bother checking every word... */ - a = 0; b = -1; - for (i = 0; i < vs->cap.map_size; i += 44) { - d = bus_readl(vs->cap.bus, vs->cis_virt+i); - a += d; b &= d; - } - bus_iounmap(vs->cap.bus, vs->cis_virt); - return (b == -1) ? -1 : (a>>1); -} + flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0); + if (attr & IS_ATTR) { + flags |= MAP_ATTRIB; + inc++; + addr *= 2; + } -static int checksum_match(u_long base) -{ - int a = checksum(base), b = checksum(base+vs->cap.map_size); - return ((a == b) && (a >= 0)); -} + card_offset = addr & ~(s->cap.map_size-1); + while (len) { + sys = set_cis_map(s, card_offset, flags); + if (!sys) + return; /* FIXME: error */ -static int setup_cis_mem(socket_info_t *s) -{ - if (!(s->cap.features & SS_CAP_STATIC_MAP) && - (s->cis_mem.sys_start == 0)) { - int low = !(s->cap.features & SS_CAP_PAGE_REGS); - vs = s; - validate_mem(cis_readable, checksum_match, low, s); - s->cis_mem.sys_start = 0; - vs = NULL; - if (find_mem_region(&s->cis_mem.sys_start, s->cap.map_size, - s->cap.map_size, low, "card services", s)) { - printk(KERN_NOTICE "cs: unable to map card memory!\n"); - return -1; + end = sys + s->cap.map_size; + sys = sys + (addr & (s->cap.map_size-1)); + for ( ; len > 0; len--, buf++, sys += inc) { + if (sys == end) + break; + writeb(*buf, sys); + } + card_offset += s->cap.map_size; + addr = 0; } - s->cis_mem.sys_stop = s->cis_mem.sys_start+s->cap.map_size-1; - s->cis_virt = bus_ioremap(s->cap.bus, s->cis_mem.sys_start, - s->cap.map_size); - } - return 0; -} - -void release_cis_mem(socket_info_t *s) -{ - if (s->cis_mem.sys_start != 0) { - s->cis_mem.flags &= ~MAP_ACTIVE; - s->ss_entry->set_mem_map(s->sock, &s->cis_mem); - if (!(s->cap.features & SS_CAP_STATIC_MAP)) - release_mem_region(s->cis_mem.sys_start, s->cap.map_size); - bus_iounmap(s->cap.bus, s->cis_virt); - s->cis_mem.sys_start = 0; - s->cis_virt = NULL; } } @@ -427,11 +394,9 @@ int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple) tuple->TupleLink = tuple->Flags = 0; #ifdef CONFIG_CARDBUS if (s->state & SOCKET_CARDBUS) { + struct pci_dev *dev = s->cap.cb_dev; u_int ptr; - struct pci_dev *dev = pci_find_slot (s->cap.cb_dev->subordinate->number, 0); - if (!dev) - return CS_BAD_HANDLE; - pci_read_config_dword(dev, 0x28, &ptr); + pci_bus_read_config_dword(dev->subordinate, 0, PCI_CARDBUS_CIS, &ptr); tuple->CISOffset = ptr & ~7; SPACE(tuple->Flags) = (ptr & 7); } else diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index f235eb1fda73..31d8b5b451a3 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -59,7 +59,6 @@ #include <pcmcia/bulkmem.h> #include <pcmcia/cistpl.h> #include <pcmcia/cisreg.h> -#include <pcmcia/bus_ops.h> #include "cs_internal.h" #ifdef CONFIG_PCI @@ -622,8 +621,10 @@ static void unreset_socket(socket_info_t *s) send_event(s, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW); } else if (s->state & SOCKET_SETUP_PENDING) { #ifdef CONFIG_CARDBUS - if (s->state & SOCKET_CARDBUS) + if (s->state & SOCKET_CARDBUS) { cb_alloc(s); + s->state |= SOCKET_CARDBUS_CONFIG; + } #endif send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); s->state &= ~SOCKET_SETUP_PENDING; @@ -1077,7 +1078,7 @@ int pcmcia_get_configuration_info(client_handle_t handle, config->Vcc = s->socket.Vcc; config->Vpp1 = config->Vpp2 = s->socket.Vpp; config->Option = s->cap.cb_dev->subordinate->number; - if (s->cb_config) { + if (s->state & SOCKET_CARDBUS_CONFIG) { config->Attributes = CONF_VALID_CLIENT; config->IntType = INT_CARDBUS; config->AssignedIRQ = s->irq.AssignedIRQ; @@ -1473,7 +1474,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) client->event_handler = req->event_handler; client->event_callback_args = req->event_callback_args; client->event_callback_args.client_handle = client; - client->event_callback_args.bus = s->cap.bus; if (s->state & SOCKET_CARDBUS) client->state |= CLIENT_CARDBUS; @@ -1522,11 +1522,8 @@ int pcmcia_release_configuration(client_handle_t handle) s = SOCKET(handle); #ifdef CONFIG_CARDBUS - if (handle->state & CLIENT_CARDBUS) { - cb_disable(s); - s->lock_count = 0; + if (handle->state & CLIENT_CARDBUS) return CS_SUCCESS; - } #endif if (!(handle->state & CLIENT_STALE)) { @@ -1573,9 +1570,8 @@ int pcmcia_release_io(client_handle_t handle, io_req_t *req) s = SOCKET(handle); #ifdef CONFIG_CARDBUS - if (handle->state & CLIENT_CARDBUS) { + if (handle->state & CLIENT_CARDBUS) return CS_SUCCESS; - } #endif if (!(handle->state & CLIENT_STALE)) { @@ -1622,10 +1618,10 @@ int pcmcia_release_irq(client_handle_t handle, irq_req_t *req) } if (req->Attributes & IRQ_HANDLE_PRESENT) { - bus_free_irq(s->cap.bus, req->AssignedIRQ, req->Instance); + free_irq(req->AssignedIRQ, req->Instance); } -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE if (req->AssignedIRQ != s->cap.pci_irq) undo_irq(req->Attributes, req->AssignedIRQ); #endif @@ -1678,16 +1674,8 @@ int pcmcia_request_configuration(client_handle_t handle, return CS_NO_CARD; #ifdef CONFIG_CARDBUS - if (handle->state & CLIENT_CARDBUS) { - if (!(req->IntType & INT_CARDBUS)) - return CS_UNSUPPORTED_MODE; - if (s->lock_count != 0) - return CS_CONFIGURATION_LOCKED; - cb_enable(s); - handle->state |= CLIENT_CONFIG_LOCKED; - s->lock_count++; - return CS_SUCCESS; - } + if (handle->state & CLIENT_CARDBUS) + return CS_UNSUPPORTED_MODE; #endif if (req->IntType & INT_CARDBUS) @@ -1887,7 +1875,7 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) if (!s->cap.irq_mask) { irq = s->cap.pci_irq; ret = (irq) ? 0 : CS_IN_USE; -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE } else if (s->irq.AssignedIRQ != 0) { /* If the interrupt is already assigned, it must match */ irq = s->irq.AssignedIRQ; @@ -1917,7 +1905,7 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) if (ret != 0) return ret; if (req->Attributes & IRQ_HANDLE_PRESENT) { - if (bus_request_irq(s->cap.bus, irq, req->Handler, + if (request_irq(irq, req->Handler, ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || (s->functions > 1) || (irq == s->cap.pci_irq)) ? SA_SHIRQ : 0, diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index a0c8bf9196c8..963ca8abaca0 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -136,7 +136,6 @@ typedef struct socket_info_t { #ifdef CONFIG_CARDBUS struct resource * cb_cis_res; u_char *cb_cis_virt; - struct cb_config_t *cb_config; #endif struct { u_int AssignedIRQ; @@ -176,6 +175,7 @@ typedef struct socket_info_t { #define SOCKET_IO_REQ(i) (0x1000<<(i)) #define SOCKET_REGION_INFO 0x4000 #define SOCKET_CARDBUS 0x8000 +#define SOCKET_CARDBUS_CONFIG 0x10000 #define CHECK_HANDLE(h) \ (((h) == NULL) || ((h)->client_magic != CLIENT_MAGIC)) @@ -198,8 +198,6 @@ typedef struct socket_info_t { /* In cardbus.c */ int cb_alloc(socket_info_t *s); void cb_free(socket_info_t *s); -void cb_enable(socket_info_t *s); -void cb_disable(socket_info_t *s); int read_cb_mem(socket_info_t *s, int space, u_int addr, u_int len, void *ptr); void cb_release_cis_mem(socket_info_t *s); @@ -234,8 +232,7 @@ int write_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf); int copy_memory(memory_handle_t handle, copy_op_t *req); /* In rsrc_mgr */ -void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long), - int force_low, socket_info_t *s); +void validate_mem(socket_info_t *s); int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align, char *name, socket_info_t *s); int find_mem_region(u_long *base, u_long num, u_long align, diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c index 37b8a95a4421..580d63f59298 100644 --- a/drivers/pcmcia/hd64465_ss.c +++ b/drivers/pcmcia/hd64465_ss.c @@ -599,21 +599,6 @@ static int hs_set_socket(unsigned int sock, socket_state_t *state) /*============================================================*/ -static int hs_get_io_map(unsigned int sock, struct pccard_io_map *io) -{ - hs_socket_t *sp = &hs_sockets[sock]; - int map = io->map; - - DPRINTK("hs_get_io_map(%d, %d)\n", sock, map); - if (map >= MAX_IO_WIN) - return -EINVAL; - - *io = sp->io_maps[map]; - return 0; -} - -/*============================================================*/ - static int hs_set_io_map(unsigned int sock, struct pccard_io_map *io) { hs_socket_t *sp = &hs_sockets[sock]; @@ -696,21 +681,6 @@ static int hs_set_io_map(unsigned int sock, struct pccard_io_map *io) /*============================================================*/ -static int hs_get_mem_map(unsigned int sock, struct pccard_mem_map *mem) -{ - hs_socket_t *sp = &hs_sockets[sock]; - int map = mem->map; - - DPRINTK("hs_get_mem_map(%d, %d)\n", sock, map); - if (map >= MAX_WIN) - return -EINVAL; - - *mem = sp->mem_maps[map]; - return 0; -} - -/*============================================================*/ - static int hs_set_mem_map(unsigned int sock, struct pccard_mem_map *mem) { hs_socket_t *sp = &hs_sockets[sock]; @@ -894,9 +864,7 @@ static struct pccard_operations hs_operations = { .get_status = hs_get_status, .get_socket = hs_get_socket, .set_socket = hs_set_socket, - .get_io_map = hs_get_io_map, .set_io_map = hs_set_io_map, - .get_mem_map = hs_get_mem_map, .set_mem_map = hs_set_mem_map, .proc_setup = hs_proc_setup, }; diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index 9292bc1222ff..81afb84aa89d 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c @@ -63,9 +63,7 @@ static struct pccard_operations i82092aa_operations = { .get_status = i82092aa_get_status, .get_socket = i82092aa_get_socket, .set_socket = i82092aa_set_socket, - .get_io_map = i82092aa_get_io_map, .set_io_map = i82092aa_set_io_map, - .get_mem_map = i82092aa_get_mem_map, .set_mem_map = i82092aa_set_mem_map, .proc_setup = i82092aa_proc_setup, }; @@ -688,34 +686,6 @@ static int i82092aa_set_socket(unsigned int sock, socket_state_t *state) return 0; } -static int i82092aa_get_io_map(unsigned int sock, struct pccard_io_map *io) -{ - unsigned char map, ioctl, addr; - - enter("i82092aa_get_io_map"); - map = io->map; - if (map > 1) { - leave("i82092aa_get_io_map with -EINVAL"); - return -EINVAL; - } - - /* FIXME: How does this fit in with the PCI resource (re)allocation */ - io->start = indirect_read16(sock, I365_IO(map)+I365_W_START); - io->stop = indirect_read16(sock, I365_IO(map)+I365_W_START); - - ioctl = indirect_read(sock,I365_IOCTL); /* IOCREG: I/O Control Register */ - addr = indirect_read(sock,I365_ADDRWIN); /* */ - - io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0; /* check this out later */ - io->flags = 0; - - if (addr & I365_IOCTL_16BIT(map)) - io->flags |= MAP_AUTOSZ; - - leave("i82092aa_get_io_map"); - return 0; -} - static int i82092aa_set_io_map(unsigned sock, struct pccard_io_map *io) { unsigned char map, ioctl; @@ -759,64 +729,6 @@ static int i82092aa_set_io_map(unsigned sock, struct pccard_io_map *io) return 0; } -static int i82092aa_get_mem_map(unsigned sock, struct pccard_mem_map *mem) -{ - unsigned short base, i; - unsigned char map, addr; - - enter("i82092aa_get_mem_map"); - - mem->flags = 0; - mem->speed = 0; - map = mem->map; - if (map > 4) { - leave("i82092aa_get_mem_map: -EINVAL"); - return -EINVAL; - } - - addr = indirect_read(sock, I365_ADDRWIN); - - if (addr & I365_ENA_MEM(map)) - mem->flags |= MAP_ACTIVE; /* yes this mapping is active */ - - base = I365_MEM(map); - - /* Find the start address - this register also has mapping info */ - - i = indirect_read16(sock,base+I365_W_START); - if (i & I365_MEM_16BIT) - mem->flags |= MAP_16BIT; - if (i & I365_MEM_0WS) - mem->flags |= MAP_0WS; - - mem->sys_start = ((unsigned long)(i & 0x0fff) << 12); - - /* Find the end address - this register also has speed info */ - i = indirect_read16(sock,base+I365_W_STOP); - if (i & I365_MEM_WS0) - mem->speed = 1; - if (i & I365_MEM_WS1) - mem->speed += 2; - mem->speed = to_ns(mem->speed); - mem->sys_stop = ( (unsigned long)(i & 0x0fff) << 12) + 0x0fff; - - /* Find the card start address, also some more MAP attributes */ - - i = indirect_read16(sock, base+I365_W_OFF); - if (i & I365_MEM_WRPROT) - mem->flags |= MAP_WRPROT; - if (i & I365_MEM_REG) - mem->flags |= MAP_ATTRIB; - mem->card_start = ( (unsigned long)(i & 0x3fff)<12) + mem->sys_start; - mem->card_start &= 0x3ffffff; - - printk("Card %i is from %lx to %lx \n",sock,mem->sys_start,mem->sys_stop); - - leave("i82092aa_get_mem_map"); - return 0; - -} - static int i82092aa_set_mem_map(unsigned sock, struct pccard_mem_map *mem) { unsigned short base, i; diff --git a/drivers/pcmcia/i82092aa.h b/drivers/pcmcia/i82092aa.h index 4e857688ec78..dc56daec6bb9 100644 --- a/drivers/pcmcia/i82092aa.h +++ b/drivers/pcmcia/i82092aa.h @@ -29,9 +29,7 @@ static void i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs); static int i82092aa_get_status(unsigned int sock, u_int *value); static int i82092aa_get_socket(unsigned int sock, socket_state_t *state); static int i82092aa_set_socket(unsigned int sock, socket_state_t *state); -static int i82092aa_get_io_map(unsigned int sock, struct pccard_io_map *io); static int i82092aa_set_io_map(unsigned int sock, struct pccard_io_map *io); -static int i82092aa_get_mem_map(unsigned int sock, struct pccard_mem_map *mem); static int i82092aa_set_mem_map(unsigned int sock, struct pccard_mem_map *mem); static int i82092aa_init(unsigned int s); static int i82092aa_suspend(unsigned int sock); diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index afc8e7380f5a..257c3503941c 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -1250,29 +1250,6 @@ static int i365_set_socket(u_short sock, socket_state_t *state) /*====================================================================*/ -static int i365_get_io_map(u_short sock, struct pccard_io_map *io) -{ - u_char map, ioctl, addr; - - map = io->map; - if (map > 1) return -EINVAL; - io->start = i365_get_pair(sock, I365_IO(map)+I365_W_START); - io->stop = i365_get_pair(sock, I365_IO(map)+I365_W_STOP); - ioctl = i365_get(sock, I365_IOCTL); - addr = i365_get(sock, I365_ADDRWIN); - io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0; - io->flags = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0; - io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0; - io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0; - io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0; - DEBUG(1, "i82365: GetIOMap(%d, %d) = %#2.2x, %d ns, " - "%#4.4x-%#4.4x\n", sock, map, io->flags, io->speed, - io->start, io->stop); - return 0; -} /* i365_get_io_map */ - -/*====================================================================*/ - static int i365_set_io_map(u_short sock, struct pccard_io_map *io) { u_char map, ioctl; @@ -1302,42 +1279,6 @@ static int i365_set_io_map(u_short sock, struct pccard_io_map *io) /*====================================================================*/ -static int i365_get_mem_map(u_short sock, struct pccard_mem_map *mem) -{ - u_short base, i; - u_char map, addr; - - map = mem->map; - if (map > 4) return -EINVAL; - addr = i365_get(sock, I365_ADDRWIN); - mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0; - base = I365_MEM(map); - - i = i365_get_pair(sock, base+I365_W_START); - mem->flags |= (i & I365_MEM_16BIT) ? MAP_16BIT : 0; - mem->flags |= (i & I365_MEM_0WS) ? MAP_0WS : 0; - mem->sys_start = ((u_long)(i & 0x0fff) << 12); - - i = i365_get_pair(sock, base+I365_W_STOP); - mem->speed = (i & I365_MEM_WS0) ? 1 : 0; - mem->speed += (i & I365_MEM_WS1) ? 2 : 0; - mem->speed = to_ns(mem->speed); - mem->sys_stop = ((u_long)(i & 0x0fff) << 12) + 0x0fff; - - i = i365_get_pair(sock, base+I365_W_OFF); - mem->flags |= (i & I365_MEM_WRPROT) ? MAP_WRPROT : 0; - mem->flags |= (i & I365_MEM_REG) ? MAP_ATTRIB : 0; - mem->card_start = ((u_int)(i & 0x3fff) << 12) + mem->sys_start; - mem->card_start &= 0x3ffffff; - - DEBUG(1, "i82365: GetMemMap(%d, %d) = %#2.2x, %d ns, %#5.5lx-%#5." - "5lx, %#5.5x\n", sock, mem->map, mem->flags, mem->speed, - mem->sys_start, mem->sys_stop, mem->card_start); - return 0; -} /* i365_get_mem_map */ - -/*====================================================================*/ - static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem) { u_short base, i; @@ -1506,14 +1447,6 @@ static int pcic_set_socket(unsigned int sock, socket_state_t *state) LOCKED(i365_set_socket(sock, state)); } -static int pcic_get_io_map(unsigned int sock, struct pccard_io_map *io) -{ - if (socket[sock].flags & IS_ALIVE) - return -EINVAL; - - LOCKED(i365_get_io_map(sock, io)); -} - static int pcic_set_io_map(unsigned int sock, struct pccard_io_map *io) { if (socket[sock].flags & IS_ALIVE) @@ -1522,14 +1455,6 @@ static int pcic_set_io_map(unsigned int sock, struct pccard_io_map *io) LOCKED(i365_set_io_map(sock, io)); } -static int pcic_get_mem_map(unsigned int sock, struct pccard_mem_map *mem) -{ - if (socket[sock].flags & IS_ALIVE) - return -EINVAL; - - LOCKED(i365_get_mem_map(sock, mem)); -} - static int pcic_set_mem_map(unsigned int sock, struct pccard_mem_map *mem) { if (socket[sock].flags & IS_ALIVE) @@ -1571,9 +1496,7 @@ static struct pccard_operations pcic_operations = { .get_status = pcic_get_status, .get_socket = pcic_get_socket, .set_socket = pcic_set_socket, - .get_io_map = pcic_get_io_map, .set_io_map = pcic_set_io_map, - .get_mem_map = pcic_get_mem_map, .set_mem_map = pcic_set_mem_map, .proc_setup = pcic_proc_setup, }; diff --git a/drivers/pcmcia/pci_socket.c b/drivers/pcmcia/pci_socket.c index da0e6ae74b4c..147167f787c6 100644 --- a/drivers/pcmcia/pci_socket.c +++ b/drivers/pcmcia/pci_socket.c @@ -105,15 +105,6 @@ static int pci_set_socket(unsigned int sock, socket_state_t *state) return -EINVAL; } -static int pci_get_io_map(unsigned int sock, struct pccard_io_map *io) -{ - pci_socket_t *socket = pci_socket_array + sock; - - if (socket->op && socket->op->get_io_map) - return socket->op->get_io_map(socket, io); - return -EINVAL; -} - static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io) { pci_socket_t *socket = pci_socket_array + sock; @@ -123,15 +114,6 @@ static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io) return -EINVAL; } -static int pci_get_mem_map(unsigned int sock, struct pccard_mem_map *mem) -{ - pci_socket_t *socket = pci_socket_array + sock; - - if (socket->op && socket->op->get_mem_map) - return socket->op->get_mem_map(socket, mem); - return -EINVAL; -} - static int pci_set_mem_map(unsigned int sock, struct pccard_mem_map *mem) { pci_socket_t *socket = pci_socket_array + sock; @@ -158,9 +140,7 @@ static struct pccard_operations pci_socket_operations = { .get_status = pci_get_status, .get_socket = pci_get_socket, .set_socket = pci_set_socket, - .get_io_map = pci_get_io_map, .set_io_map = pci_set_io_map, - .get_mem_map = pci_get_mem_map, .set_mem_map = pci_set_mem_map, .proc_setup = pci_proc_setup, }; diff --git a/drivers/pcmcia/pci_socket.h b/drivers/pcmcia/pci_socket.h index c5daacaec7c9..206eddd05c11 100644 --- a/drivers/pcmcia/pci_socket.h +++ b/drivers/pcmcia/pci_socket.h @@ -37,9 +37,7 @@ struct pci_socket_ops { int (*get_status)(struct pci_socket *, unsigned int *); int (*get_socket)(struct pci_socket *, socket_state_t *); int (*set_socket)(struct pci_socket *, socket_state_t *); - int (*get_io_map)(struct pci_socket *, struct pccard_io_map *); int (*set_io_map)(struct pci_socket *, struct pccard_io_map *); - int (*get_mem_map)(struct pci_socket *, struct pccard_mem_map *); int (*set_mem_map)(struct pci_socket *, struct pccard_mem_map *); void (*proc_setup)(struct pci_socket *, struct proc_dir_entry *base); }; diff --git a/drivers/pcmcia/ricoh.h b/drivers/pcmcia/ricoh.h index aaf679f1ac70..14573f8d3646 100644 --- a/drivers/pcmcia/ricoh.h +++ b/drivers/pcmcia/ricoh.h @@ -170,9 +170,7 @@ static struct pci_socket_ops ricoh_ops = { yenta_get_status, yenta_get_socket, yenta_set_socket, - yenta_get_io_map, yenta_set_io_map, - yenta_get_mem_map, yenta_set_mem_map, yenta_proc_setup }; diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index a5736fee388e..01727ab93359 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -60,7 +60,7 @@ #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i") INT_MODULE_PARM(probe_mem, 1); /* memory probe? */ -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE INT_MODULE_PARM(probe_io, 1); /* IO port probe? */ INT_MODULE_PARM(mem_limit, 0x10000); #endif @@ -83,7 +83,9 @@ static resource_map_t mem_db = { 0, 0, &mem_db }; /* IO port resource database */ static resource_map_t io_db = { 0, 0, &io_db }; -#ifdef CONFIG_ISA +static DECLARE_MUTEX(rsrc_sem); + +#ifdef CONFIG_PCMCIA_PROBE typedef struct irq_info_t { u_int Attributes; @@ -269,7 +271,7 @@ static int sub_interval(resource_map_t *map, u_long base, u_long num) ======================================================================*/ -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE static void do_io_probe(ioaddr_t base, ioaddr_t num) { @@ -333,15 +335,69 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num) /*====================================================================== + This is tricky... when we set up CIS memory, we try to validate + the memory window space allocations. + +======================================================================*/ + +/* Validation function for cards with a valid CIS */ +static int cis_readable(socket_info_t *s, u_long base) +{ + cisinfo_t info1, info2; + int ret; + s->cis_mem.sys_start = base; + s->cis_mem.sys_stop = base+s->cap.map_size-1; + s->cis_virt = ioremap(base, s->cap.map_size); + ret = pcmcia_validate_cis(s->clients, &info1); + /* invalidate mapping and CIS cache */ + iounmap(s->cis_virt); + s->cis_used = 0; + if ((ret != 0) || (info1.Chains == 0)) + return 0; + s->cis_mem.sys_start = base+s->cap.map_size; + s->cis_mem.sys_stop = base+2*s->cap.map_size-1; + s->cis_virt = ioremap(base+s->cap.map_size, s->cap.map_size); + ret = pcmcia_validate_cis(s->clients, &info2); + iounmap(s->cis_virt); + s->cis_used = 0; + return ((ret == 0) && (info1.Chains == info2.Chains)); +} + +/* Validation function for simple memory cards */ +static int checksum(socket_info_t *s, u_long base) +{ + int i, a, b, d; + s->cis_mem.sys_start = base; + s->cis_mem.sys_stop = base+s->cap.map_size-1; + s->cis_virt = ioremap(base, s->cap.map_size); + s->cis_mem.card_start = 0; + s->cis_mem.flags = MAP_ACTIVE; + s->ss_entry->set_mem_map(s->sock, &s->cis_mem); + /* Don't bother checking every word... */ + a = 0; b = -1; + for (i = 0; i < s->cap.map_size; i += 44) { + d = readl(s->cis_virt+i); + a += d; b &= d; + } + iounmap(s->cis_virt); + return (b == -1) ? -1 : (a>>1); +} + +static int checksum_match(socket_info_t *s, u_long base) +{ + int a = checksum(s, base), b = checksum(s, base+s->cap.map_size); + return ((a == b) && (a >= 0)); +} + +/*====================================================================== + The memory probe. If the memory list includes a 64K-aligned block below 1MB, we probe in 64K chunks, and as soon as we accumulate at least mem_limit free space, we quit. ======================================================================*/ -static int do_mem_probe(u_long base, u_long num, - int (*is_valid)(u_long), int (*do_cksum)(u_long), - socket_info_t *s) +static int do_mem_probe(u_long base, u_long num, socket_info_t *s) { u_long i, j, bad, fail, step; @@ -349,18 +405,21 @@ static int do_mem_probe(u_long base, u_long num, base, base+num-1); bad = fail = 0; step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff); + /* cis_readable wants to map 2x map_size */ + if (step < 2 * s->cap.map_size) + step = 2 * s->cap.map_size; for (i = j = base; i < base+num; i = j + step) { if (!fail) { for (j = i; j < base+num; j += step) if ((check_mem_resource(j, step, s->cap.cb_dev) == 0) && - is_valid(j)) + cis_readable(s, j)) break; fail = ((i == base) && (j == base+num)); } if (fail) { for (j = i; j < base+num; j += 2*step) if ((check_mem_resource(j, 2*step, s->cap.cb_dev) == 0) && - do_cksum(j) && do_cksum(j+step)) + checksum_match(s, j) && checksum_match(s, j + step)) break; } if (i != j) { @@ -374,16 +433,14 @@ static int do_mem_probe(u_long base, u_long num, return (num - bad); } -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE -static u_long inv_probe(int (*is_valid)(u_long), - int (*do_cksum)(u_long), - resource_map_t *m, socket_info_t *s) +static u_long inv_probe(resource_map_t *m, socket_info_t *s) { u_long ok; if (m == &mem_db) return 0; - ok = inv_probe(is_valid, do_cksum, m->next, s); + ok = inv_probe(m->next, s); if (ok) { if (m->base >= 0x100000) sub_interval(&mem_db, m->base, m->num); @@ -391,32 +448,36 @@ static u_long inv_probe(int (*is_valid)(u_long), } if (m->base < 0x100000) return 0; - return do_mem_probe(m->base, m->num, is_valid, do_cksum, s); + return do_mem_probe(m->base, m->num, s); } -void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long), - int force_low, socket_info_t *s) +void validate_mem(socket_info_t *s) { resource_map_t *m, *n; static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 }; static int hi = 0, lo = 0; u_long b, i, ok = 0; - - if (!probe_mem) return; + int force_low = !(s->cap.features & SS_CAP_PAGE_REGS); + + if (!probe_mem) + return; + + down(&rsrc_sem); /* We do up to four passes through the list */ if (!force_low) { - if (hi++ || (inv_probe(is_valid, do_cksum, mem_db.next, s) > 0)) - return; + if (hi++ || (inv_probe(mem_db.next, s) > 0)) + goto out; printk(KERN_NOTICE "cs: warning: no high memory space " "available!\n"); } - if (lo++) return; + if (lo++) + goto out; for (m = mem_db.next; m != &mem_db; m = n) { n = m->next; /* Only probe < 1 MB */ if (m->base >= 0x100000) continue; if ((m->base | m->num) & 0xffff) { - ok += do_mem_probe(m->base, m->num, is_valid, do_cksum, s); + ok += do_mem_probe(m->base, m->num, s); continue; } /* Special probe for 64K-aligned block */ @@ -426,28 +487,31 @@ void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long), if (ok >= mem_limit) sub_interval(&mem_db, b, 0x10000); else - ok += do_mem_probe(b, 0x10000, is_valid, do_cksum, s); + ok += do_mem_probe(b, 0x10000, s); } } } + out: + up(&rsrc_sem); } -#else /* CONFIG_ISA */ +#else /* CONFIG_PCMCIA_PROBE */ -void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long), - int force_low, socket_info_t *s) +void validate_mem(socket_info_t *s) { resource_map_t *m; static int done = 0; - if (!probe_mem || done++) - return; - for (m = mem_db.next; m != &mem_db; m = m->next) - if (do_mem_probe(m->base, m->num, is_valid, do_cksum, s)) - return; + if (probe_mem && done++ == 0) { + down(&rsrc_sem); + for (m = mem_db.next; m != &mem_db; m = m->next) + if (do_mem_probe(m->base, m->num, s)) + break; + up(&rsrc_sem); + } } -#endif /* CONFIG_ISA */ +#endif /* CONFIG_PCMCIA_PROBE */ /*====================================================================== @@ -467,7 +531,9 @@ int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align, { ioaddr_t try; resource_map_t *m; - + int ret = -1; + + down(&rsrc_sem); for (m = io_db.next; m != &io_db; m = m->next) { try = (m->base & ~(align-1)) + *base; for (try = (try >= m->base) ? try : try+align; @@ -475,12 +541,16 @@ int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align, try += align) { if (request_io_resource(try, num, name, s->cap.cb_dev) == 0) { *base = try; - return 0; + ret = 0; + goto out; } - if (!align) break; + if (!align) + break; } } - return -1; + out: + up(&rsrc_sem); + return ret; } int find_mem_region(u_long *base, u_long num, u_long align, @@ -488,26 +558,35 @@ int find_mem_region(u_long *base, u_long num, u_long align, { u_long try; resource_map_t *m; + int ret = -1; + down(&rsrc_sem); while (1) { for (m = mem_db.next; m != &mem_db; m = m->next) { /* first pass >1MB, second pass <1MB */ - if ((force_low != 0) ^ (m->base < 0x100000)) continue; + if ((force_low != 0) ^ (m->base < 0x100000)) + continue; + try = (m->base & ~(align-1)) + *base; for (try = (try >= m->base) ? try : try+align; (try >= m->base) && (try+num <= m->base+m->num); try += align) { if (request_mem_resource(try, num, name, s->cap.cb_dev) == 0) { *base = try; - return 0; + ret = 0; + goto out; } - if (!align) break; + if (!align) + break; } } - if (force_low) break; + if (force_low) + break; force_low++; } - return -1; + out: + up(&rsrc_sem); + return ret; } /*====================================================================== @@ -518,7 +597,7 @@ int find_mem_region(u_long *base, u_long num, u_long align, ======================================================================*/ -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE static void fake_irq(int i, void *d, struct pt_regs *r) { } static inline int check_irq(int irq) @@ -532,66 +611,89 @@ static inline int check_irq(int irq) int try_irq(u_int Attributes, int irq, int specific) { irq_info_t *info = &irq_table[irq]; + int ret = 0; + + down(&rsrc_sem); if (info->Attributes & RES_ALLOCATED) { switch (Attributes & IRQ_TYPE) { case IRQ_TYPE_EXCLUSIVE: - return CS_IN_USE; + ret = CS_IN_USE; + break; case IRQ_TYPE_TIME: if ((info->Attributes & RES_IRQ_TYPE) - != RES_IRQ_TYPE_TIME) - return CS_IN_USE; - if (Attributes & IRQ_FIRST_SHARED) - return CS_BAD_ATTRIBUTE; + != RES_IRQ_TYPE_TIME) { + ret = CS_IN_USE; + break; + } + if (Attributes & IRQ_FIRST_SHARED) { + ret = CS_BAD_ATTRIBUTE; + break; + } info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED; info->time_share++; break; case IRQ_TYPE_DYNAMIC_SHARING: if ((info->Attributes & RES_IRQ_TYPE) - != RES_IRQ_TYPE_DYNAMIC) - return CS_IN_USE; - if (Attributes & IRQ_FIRST_SHARED) - return CS_BAD_ATTRIBUTE; + != RES_IRQ_TYPE_DYNAMIC) { + ret = CS_IN_USE; + break; + } + if (Attributes & IRQ_FIRST_SHARED) { + ret = CS_BAD_ATTRIBUTE; + break; + } info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED; info->dyn_share++; break; } } else { - if ((info->Attributes & RES_RESERVED) && !specific) - return CS_IN_USE; - if (check_irq(irq) != 0) - return CS_IN_USE; + if ((info->Attributes & RES_RESERVED) && !specific) { + ret = CS_IN_USE; + goto out; + } + if (check_irq(irq) != 0) { + ret = CS_IN_USE; + goto out; + } switch (Attributes & IRQ_TYPE) { case IRQ_TYPE_EXCLUSIVE: info->Attributes |= RES_ALLOCATED; break; case IRQ_TYPE_TIME: - if (!(Attributes & IRQ_FIRST_SHARED)) - return CS_BAD_ATTRIBUTE; + if (!(Attributes & IRQ_FIRST_SHARED)) { + ret = CS_BAD_ATTRIBUTE; + break; + } info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED; info->time_share = 1; break; case IRQ_TYPE_DYNAMIC_SHARING: - if (!(Attributes & IRQ_FIRST_SHARED)) - return CS_BAD_ATTRIBUTE; + if (!(Attributes & IRQ_FIRST_SHARED)) { + ret = CS_BAD_ATTRIBUTE; + break; + } info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED; info->dyn_share = 1; break; } } - return 0; + out: + up(&rsrc_sem); + return ret; } #endif /*====================================================================*/ -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE void undo_irq(u_int Attributes, int irq) { irq_info_t *info; info = &irq_table[irq]; + down(&rsrc_sem); switch (Attributes & IRQ_TYPE) { case IRQ_TYPE_EXCLUSIVE: info->Attributes &= RES_RESERVED; @@ -607,6 +709,7 @@ void undo_irq(u_int Attributes, int irq) info->Attributes &= RES_RESERVED; break; } + up(&rsrc_sem); } #endif @@ -629,6 +732,8 @@ static int adjust_memory(adjust_t *adj) return CS_BAD_SIZE; ret = CS_SUCCESS; + + down(&rsrc_sem); switch (adj->Action) { case ADD_MANAGED_RESOURCE: ret = add_interval(&mem_db, base, num); @@ -647,6 +752,7 @@ static int adjust_memory(adjust_t *adj) default: ret = CS_UNSUPPORTED_FUNCTION; } + up(&rsrc_sem); return ret; } @@ -655,7 +761,7 @@ static int adjust_memory(adjust_t *adj) static int adjust_io(adjust_t *adj) { - int base, num; + int base, num, ret = CS_SUCCESS; base = adj->resource.io.BasePort; num = adj->resource.io.NumPorts; @@ -664,11 +770,14 @@ static int adjust_io(adjust_t *adj) if ((num <= 0) || (base+num > 0x10000) || (base+num <= base)) return CS_BAD_SIZE; + down(&rsrc_sem); switch (adj->Action) { case ADD_MANAGED_RESOURCE: - if (add_interval(&io_db, base, num) != 0) - return CS_IN_USE; -#ifdef CONFIG_ISA + if (add_interval(&io_db, base, num) != 0) { + ret = CS_IN_USE; + break; + } +#ifdef CONFIG_PCMCIA_PROBE if (probe_io) do_io_probe(base, num); #endif @@ -677,18 +786,20 @@ static int adjust_io(adjust_t *adj) sub_interval(&io_db, base, num); break; default: - return CS_UNSUPPORTED_FUNCTION; + ret = CS_UNSUPPORTED_FUNCTION; break; } + up(&rsrc_sem); - return CS_SUCCESS; + return ret; } /*====================================================================*/ static int adjust_irq(adjust_t *adj) { -#ifdef CONFIG_ISA + int ret = CS_SUCCESS; +#ifdef CONFIG_PCMCIA_PROBE int irq; irq_info_t *info; @@ -696,33 +807,41 @@ static int adjust_irq(adjust_t *adj) if ((irq < 0) || (irq > 15)) return CS_BAD_IRQ; info = &irq_table[irq]; - + + down(&rsrc_sem); switch (adj->Action) { case ADD_MANAGED_RESOURCE: if (info->Attributes & RES_REMOVED) info->Attributes &= ~(RES_REMOVED|RES_ALLOCATED); else - if (adj->Attributes & RES_ALLOCATED) - return CS_IN_USE; + if (adj->Attributes & RES_ALLOCATED) { + ret = CS_IN_USE; + break; + } if (adj->Attributes & RES_RESERVED) info->Attributes |= RES_RESERVED; else info->Attributes &= ~RES_RESERVED; break; case REMOVE_MANAGED_RESOURCE: - if (info->Attributes & RES_REMOVED) - return 0; - if (info->Attributes & RES_ALLOCATED) - return CS_IN_USE; + if (info->Attributes & RES_REMOVED) { + ret = 0; + break; + } + if (info->Attributes & RES_ALLOCATED) { + ret = CS_IN_USE; + break; + } info->Attributes |= RES_ALLOCATED|RES_REMOVED; info->Attributes &= ~RES_RESERVED; break; default: - return CS_UNSUPPORTED_FUNCTION; + ret = CS_UNSUPPORTED_FUNCTION; break; } + up(&rsrc_sem); #endif - return CS_SUCCESS; + return ret; } /*====================================================================*/ diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index 3b7bd42aca97..19e23eca7ca6 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c @@ -52,7 +52,6 @@ #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/ss.h> -#include <pcmcia/bus_ops.h> #include <asm/hardware.h> #include <asm/io.h> @@ -567,31 +566,6 @@ sa1100_pcmcia_set_socket(unsigned int sock, socket_state_t *state) } /* sa1100_pcmcia_set_socket() */ -/* sa1100_pcmcia_get_io_map() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^ - * Implements the get_io_map() operation for the in-kernel PCMCIA - * service (formerly SS_GetIOMap in Card Services). Just returns an - * I/O map descriptor which was assigned earlier by a set_io_map(). - * - * Returns: 0 on success, -1 if the map index was out of range - */ -static int -sa1100_pcmcia_get_io_map(unsigned int sock, struct pccard_io_map *map) -{ - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); - int ret = -1; - - DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock); - - if (map->map < MAX_IO_WIN) { - *map = skt->io_map[map->map]; - ret = 0; - } - - return ret; -} - - /* sa1100_pcmcia_set_io_map() * ^^^^^^^^^^^^^^^^^^^^^^^^^^ * Implements the set_io_map() operation for the in-kernel PCMCIA @@ -646,32 +620,6 @@ sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map) } /* sa1100_pcmcia_set_io_map() */ -/* sa1100_pcmcia_get_mem_map() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * Implements the get_mem_map() operation for the in-kernel PCMCIA - * service (formerly SS_GetMemMap in Card Services). Just returns a - * memory map descriptor which was assigned earlier by a - * set_mem_map() request. - * - * Returns: 0 on success, -1 if the map index was out of range - */ -static int -sa1100_pcmcia_get_mem_map(unsigned int sock, struct pccard_mem_map *map) -{ - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); - int ret = -1; - - DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock); - - if (map->map < MAX_WIN) { - *map = skt->pc_mem_map[map->map]; - ret = 0; - } - - return ret; -} - - /* sa1100_pcmcia_set_mem_map() * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Implements the set_mem_map() operation for the in-kernel PCMCIA @@ -841,9 +789,7 @@ static struct pccard_operations sa1100_pcmcia_operations = { .get_status = sa1100_pcmcia_get_status, .get_socket = sa1100_pcmcia_get_socket, .set_socket = sa1100_pcmcia_set_socket, - .get_io_map = sa1100_pcmcia_get_io_map, .set_io_map = sa1100_pcmcia_set_io_map, - .get_mem_map = sa1100_pcmcia_get_mem_map, .set_mem_map = sa1100_pcmcia_set_mem_map, #ifdef CONFIG_PROC_FS .proc_setup = sa1100_pcmcia_proc_setup diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index d537519e4cce..6d701f9710ac 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -806,44 +806,6 @@ static int tcic_set_socket(unsigned int lsock, socket_state_t *state) /*====================================================================*/ -static int tcic_get_io_map(unsigned int lsock, struct pccard_io_map *io) -{ - u_short psock = socket_table[lsock].psock; - u_short base, ioctl; - u_int addr; - - if (io->map > 1) return -EINVAL; - tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT)); - addr = TCIC_IWIN(psock, io->map); - tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X); - base = tcic_getw(TCIC_DATA); - tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X); - ioctl = tcic_getw(TCIC_DATA); - - if (ioctl & TCIC_ICTL_TINY) - io->start = io->stop = base; - else { - io->start = base & (base-1); - io->stop = io->start + (base ^ (base-1)); - } - io->speed = to_ns(ioctl & TCIC_ICTL_WSCNT_MASK); - io->flags = (ioctl & TCIC_ICTL_ENA) ? MAP_ACTIVE : 0; - switch (ioctl & TCIC_ICTL_BW_MASK) { - case TCIC_ICTL_BW_DYN: - io->flags |= MAP_AUTOSZ; break; - case TCIC_ICTL_BW_16: - io->flags |= MAP_16BIT; break; - default: - break; - } - DEBUG(1, "tcic: GetIOMap(%d, %d) = %#2.2x, %d ns, " - "%#4.4x-%#4.4x\n", lsock, io->map, io->flags, - io->speed, io->start, io->stop); - return 0; -} /* tcic_get_io_map */ - -/*====================================================================*/ - static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io) { u_short psock = socket_table[lsock].psock; @@ -881,51 +843,6 @@ static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io) /*====================================================================*/ -static int tcic_get_mem_map(unsigned int lsock, struct pccard_mem_map *mem) -{ - u_short psock = socket_table[lsock].psock; - u_short addr, ctl; - u_long base, mmap; - - if (mem->map > 3) return -EINVAL; - tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT)); - addr = TCIC_MWIN(psock, mem->map); - - tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X); - base = tcic_getw(TCIC_DATA); - if (base & TCIC_MBASE_4K_BIT) { - mem->sys_start = base & TCIC_MBASE_HA_MASK; - mem->sys_stop = mem->sys_start; - } else { - base &= TCIC_MBASE_HA_MASK; - mem->sys_start = (base & (base-1)); - mem->sys_stop = mem->sys_start + (base ^ (base-1)); - } - mem->sys_start = mem->sys_start << TCIC_MBASE_HA_SHFT; - mem->sys_stop = (mem->sys_stop << TCIC_MBASE_HA_SHFT) + 0x0fff; - - tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X); - mmap = tcic_getw(TCIC_DATA); - mem->flags = (mmap & TCIC_MMAP_REG) ? MAP_ATTRIB : 0; - mmap &= TCIC_MMAP_CA_MASK; - mem->card_start = mem->sys_start + (mmap << TCIC_MMAP_CA_SHFT); - mem->card_start &= 0x3ffffff; - - tcic_setw(TCIC_ADDR, addr + TCIC_MCTL_X); - ctl = tcic_getw(TCIC_DATA); - mem->flags |= (ctl & TCIC_MCTL_ENA) ? MAP_ACTIVE : 0; - mem->flags |= (ctl & TCIC_MCTL_B8) ? 0 : MAP_16BIT; - mem->flags |= (ctl & TCIC_MCTL_WP) ? MAP_WRPROT : 0; - mem->speed = to_ns(ctl & TCIC_MCTL_WSCNT_MASK); - - DEBUG(1, "tcic: GetMemMap(%d, %d) = %#2.2x, %d ns, " - "%#5.5lx-%#5.5lx, %#5.5x\n", lsock, mem->map, mem->flags, - mem->speed, mem->sys_start, mem->sys_stop, mem->card_start); - return 0; -} /* tcic_get_mem_map */ - -/*====================================================================*/ - static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem) { u_short psock = socket_table[lsock].psock; @@ -1007,9 +924,7 @@ static struct pccard_operations tcic_operations = { .get_status = tcic_get_status, .get_socket = tcic_get_socket, .set_socket = tcic_set_socket, - .get_io_map = tcic_get_io_map, .set_io_map = tcic_set_io_map, - .get_mem_map = tcic_get_mem_map, .set_mem_map = tcic_set_mem_map, .proc_setup = tcic_proc_setup, }; diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index 8b1f6a02ef2d..353cc02b8181 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h @@ -185,9 +185,7 @@ static struct pci_socket_ops ti_ops = { yenta_get_status, yenta_get_socket, yenta_set_socket, - yenta_get_io_map, yenta_set_io_map, - yenta_get_mem_map, yenta_set_mem_map, yenta_proc_setup }; @@ -230,9 +228,7 @@ static struct pci_socket_ops ti113x_ops = { yenta_get_status, yenta_get_socket, yenta_set_socket, - yenta_get_io_map, yenta_set_io_map, - yenta_get_mem_map, yenta_set_mem_map, yenta_proc_setup }; @@ -272,9 +268,7 @@ static struct pci_socket_ops ti1250_ops = { yenta_get_status, yenta_get_socket, yenta_set_socket, - yenta_get_io_map, yenta_set_io_map, - yenta_get_mem_map, yenta_set_mem_map, yenta_proc_setup }; diff --git a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c index bf6c913752d0..4bb9cc7257ba 100644 --- a/drivers/pcmcia/yenta.c +++ b/drivers/pcmcia/yenta.c @@ -27,7 +27,7 @@ #include "i82365.h" #if 0 -#define DEBUG(x,args...) printk(__FUNCTION__ ": " x,##args) +#define DEBUG(x,args...) printk("%s: " x, __FUNCTION__, ##args) #else #define DEBUG(x,args...) #endif @@ -300,29 +300,6 @@ static int yenta_set_socket(pci_socket_t *socket, socket_state_t *state) return 0; } -static int yenta_get_io_map(pci_socket_t *socket, struct pccard_io_map *io) -{ - int map; - unsigned char ioctl, addr; - - map = io->map; - if (map > 1) - return -EINVAL; - - io->start = exca_readw(socket, I365_IO(map)+I365_W_START); - io->stop = exca_readw(socket, I365_IO(map)+I365_W_STOP); - - ioctl = exca_readb(socket, I365_IOCTL); - addr = exca_readb(socket, I365_ADDRWIN); - io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0; - io->flags = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0; - io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0; - io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0; - io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0; - - return 0; -} - static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io) { int map; @@ -356,41 +333,6 @@ static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io) return 0; } -static int yenta_get_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem) -{ - int map; - unsigned char addr; - unsigned int start, stop, page, offset; - - map = mem->map; - if (map > 4) - return -EINVAL; - - addr = exca_readb(socket, I365_ADDRWIN); - mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0; - - start = exca_readw(socket, I365_MEM(map) + I365_W_START); - mem->flags |= (start & I365_MEM_16BIT) ? MAP_16BIT : 0; - mem->flags |= (start & I365_MEM_0WS) ? MAP_0WS : 0; - start = (start & 0x0fff) << 12; - - stop = exca_readw(socket, I365_MEM(map) + I365_W_STOP); - mem->speed = to_ns(stop >> 14); - stop = ((stop & 0x0fff) << 12) + 0x0fff; - - offset = exca_readw(socket, I365_MEM(map) + I365_W_OFF); - mem->flags |= (offset & I365_MEM_WRPROT) ? MAP_WRPROT : 0; - mem->flags |= (offset & I365_MEM_REG) ? MAP_ATTRIB : 0; - offset = ((offset & 0x3fff) << 12) + start; - mem->card_start = offset & 0x3ffffff; - - page = exca_readb(socket, CB_MEM_PAGE(map)) << 24; - mem->sys_start = start + page; - mem->sys_stop = start + page; - - return 0; -} - static int yenta_set_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem) { int map; @@ -572,7 +514,6 @@ static void yenta_get_socket_capabilities(pci_socket_t *socket, u32 isa_irq_mask socket->cap.pci_irq = socket->cb_irq; socket->cap.irq_mask = yenta_probe_irq(socket, isa_irq_mask); socket->cap.cb_dev = socket->dev; - socket->cap.bus = NULL; printk("Yenta IRQ list %04x, PCI irq%d\n", socket->cap.irq_mask, socket->cb_irq); } @@ -935,9 +876,7 @@ struct pci_socket_ops yenta_operations = { yenta_get_status, yenta_get_socket, yenta_set_socket, - yenta_get_io_map, yenta_set_io_map, - yenta_get_mem_map, yenta_set_mem_map, yenta_proc_setup }; diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 50e9a2f24389..523a0b54769e 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -62,7 +62,6 @@ #include <pcmcia/cistpl.h> #include <pcmcia/cisreg.h> #include <pcmcia/ds.h> -#include <pcmcia/bus_ops.h> #include "nsp_cs.h" @@ -93,7 +92,6 @@ typedef struct scsi_info_t { int ndev; dev_node_t node[8]; int stop; - struct bus_operations *bus; } scsi_info_t; @@ -1948,7 +1946,6 @@ static int nsp_cs_event(event_t event, case CS_EVENT_CARD_INSERTION: DEBUG(0, " event: insert\n"); link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - info->bus = args->bus; nsp_cs_config(link); break; diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 0231b65954e3..5d2c2121535e 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_USB_SL811HS) += host/ obj-$(CONFIG_USB_ACM) += class/ obj-$(CONFIG_USB_AUDIO) += class/ obj-$(CONFIG_USB_BLUETOOTH_TTY) += class/ +obj-$(CONFIG_USB_MIDI) += class/ obj-$(CONFIG_USB_PRINTER) += class/ obj-$(CONFIG_USB_STORAGE) += storage/ diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c index b8803ce7301f..7e21997bf9bf 100644 --- a/drivers/usb/class/audio.c +++ b/drivers/usb/class/audio.c @@ -172,7 +172,6 @@ /*****************************************************************************/ -#include <linux/version.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/string.h> diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 7a6b3d0204e8..99233f6f06ef 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -538,7 +538,7 @@ static int acm_probe (struct usb_interface *intf, cfacm = dev->config + i; - dbg("probing config %d", cfacm->bConfigurationValue); + dbg("probing config %d", cfacm->desc.bConfigurationValue); if (cfacm->desc.bNumInterfaces != 2 || usb_interface_claimed(cfacm->interface + 0) || diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index 6e4392596750..e88cda590a31 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -7,7 +7,6 @@ #include <linux/config.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/pci.h> diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index ef25a85a939a..8ad8c112c1c0 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1024,9 +1024,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) */ urb->transfer_flags |= URB_NO_DMA_MAP; status = rh_urb_enqueue (hcd, urb); - if (status) - urb_unlink (urb); - return status; + goto done; } /* lower level hcd code should use *_dma exclusively, @@ -1051,8 +1049,11 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) } status = hcd->driver->urb_enqueue (hcd, urb, mem_flags); - if (status) +done: + if (status) { + usb_put_urb (urb); urb_unlink (urb); + } return status; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 03696016c495..fc8c00c3b432 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -135,8 +135,7 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs) default: /* presumably an error */ /* Cause a hub reset after 10 consecutive errors */ - dbg("hub '%s' status %d for interrupt transfer", - urb->dev->devpath, urb->status); + dev_dbg (&hub->intf->dev, "transfer --> %d\n", urb->status); if ((++hub->nerrors < 10) || hub->error) goto resubmit; hub->error = urb->status; @@ -158,10 +157,10 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs) spin_unlock_irqrestore(&hub_event_lock, flags); resubmit: - if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0) - err ("hub '%s-%s' status %d for interrupt resubmit", - urb->dev->bus->bus_name, urb->dev->devpath, - status); + if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0 + /* ENODEV means we raced disconnect() */ + && status != -ENODEV) + dev_err (&hub->intf->dev, "resubmit --> %d\n", urb->status); } /* USB 2.0 spec Section 11.24.2.3 */ @@ -648,12 +647,13 @@ static int usb_hub_port_status(struct usb_device *hub, int port, struct usb_port_status *portsts; int ret = -ENOMEM; - portsts = kmalloc(sizeof(*portsts), GFP_KERNEL); + portsts = kmalloc(sizeof(*portsts), GFP_NOIO); if (portsts) { ret = usb_get_port_status(hub, port + 1, portsts); if (ret < 0) - err("%s(%s-%s) failed (err = %d)", __FUNCTION__, - hub->bus->bus_name, hub->devpath, ret); + dev_err (hubdev (hub), + "%s failed (err = %d)\n", __FUNCTION__, + ret); else { *status = le16_to_cpu(portsts->wPortStatus); *change = le16_to_cpu(portsts->wPortChange); @@ -759,8 +759,8 @@ void usb_hub_port_disable(struct usb_device *hub, int port) ret = usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE); if (ret) - err("cannot disable port %d of hub %s (err = %d)", - port + 1, hub->devpath, ret); + dev_err(hubdev(hub), "cannot disable port %d (err = %d)\n", + port + 1, ret); } /* USB 2.0 spec, 7.1.7.3 / fig 7-29: @@ -983,12 +983,12 @@ static void usb_hub_events(void) spin_unlock_irqrestore(&hub_event_lock, flags); if (hub->error) { - dbg("resetting hub %s for error %d", - dev->devpath, hub->error); + dev_dbg (&hub->intf->dev, "resetting for error %d\n", + hub->error); if (usb_hub_reset(hub)) { - err("error resetting hub %s - disconnecting", - dev->devpath); + dev_dbg (&hub->intf->dev, + "can't reset; disconnecting\n"); up(&hub->khubd_sem); usb_hub_disconnect(dev); continue; @@ -1022,33 +1022,37 @@ static void usb_hub_events(void) if (!(portstatus & USB_PORT_STAT_ENABLE) && (portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) { - err("already running hub %s port %i " + dev_err (&hub->intf->dev, + "port %i " "disabled by hub (EMI?), " "re-enabling...", - dev->devpath, i + 1); + i + 1); usb_hub_port_connect_change(hub, i, portstatus, portchange); } } if (portchange & USB_PORT_STAT_C_SUSPEND) { - dbg("hub %s port %d suspend change", - dev->devpath, i + 1); + dev_dbg (&hub->intf->dev, + "suspend change on port %d\n", + i + 1); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_SUSPEND); } if (portchange & USB_PORT_STAT_C_OVERCURRENT) { - err("hub %s port %d over-current change", - dev->devpath, i + 1); + dev_err (&hub->intf->dev, + "over-current change on port %d\n", + i + 1); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT); usb_hub_power_on(hub); } if (portchange & USB_PORT_STAT_C_RESET) { - dbg("hub %s port %d reset change", - dev->devpath, i + 1); + dev_dbg (&hub->intf->dev, + "reset change on port %d\n", + i + 1); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); } @@ -1056,16 +1060,16 @@ static void usb_hub_events(void) /* deal with hub status changes */ if (usb_get_hub_status(dev, &hubsts) < 0) - err("get_hub_status %s failed", dev->devpath); + dev_err (&hub->intf->dev, "get_hub_status failed\n"); else { hubstatus = le16_to_cpup(&hubsts.wHubStatus); hubchange = le16_to_cpup(&hubsts.wHubChange); if (hubchange & HUB_CHANGE_LOCAL_POWER) { - dbg("hub %s power change", dev->devpath); + dev_dbg (&hub->intf->dev, "power change\n"); usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER); } if (hubchange & HUB_CHANGE_OVERCURRENT) { - dbg("hub %s overcurrent change", dev->devpath); + dev_dbg (&hub->intf->dev, "overcurrent change\n"); wait_ms(500); /* Cool down */ usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT); usb_hub_power_on(hub); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 793a82b23ac2..f0d1fdad80c0 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -7,6 +7,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/init.h> +#include <linux/mm.h> #include <asm/byteorder.h> #include "hcd.h" /* for usbcore internals */ diff --git a/drivers/usb/core/usb-debug.c b/drivers/usb/core/usb-debug.c index ea5d4f766bb6..91bea396940f 100644 --- a/drivers/usb/core/usb-debug.c +++ b/drivers/usb/core/usb-debug.c @@ -5,7 +5,6 @@ * face, but so that you can still use them.. */ #include <linux/config.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/slab.h> diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index b87e7aaaf14d..a3b3c32b3a6a 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -866,14 +866,11 @@ void usb_disconnect(struct usb_device **pdev) } /** - * usb_connect - connects a new device during enumeration (usbcore-internal) - * @dev: partially enumerated device - * - * Connect a new USB device. This basically just initializes - * the USB device information and sets up the topology - it's - * up to the low-level driver to reset the port and actually - * do the setup (the upper levels don't know how to do that). + * usb_connect - pick device address (usbcore-internal) + * @dev: newly detected device (in DEFAULT state) * + * Picks a device address. It's up to the hub (or root hub) driver + * to handle and manage enumeration, starting from the DEFAULT state. * Only hub drivers (including virtual root hub drivers for host * controllers) should ever call this. */ @@ -983,7 +980,7 @@ static void set_device_description (struct usb_device *dev) } /* - * By the time we get here, the device has gotten a new device ID + * By the time we get here, we chose a new device address * and is in the default state. We need to identify the thing and * get the ball rolling.. * diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 5c148c778e9c..798d2e0e1c50 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -94,7 +94,6 @@ #include <linux/list.h> #include <linux/interrupt.h> /* for in_interrupt () */ #include <linux/usb.h> -#include <linux/version.h> #include "../core/hcd.h" #include <asm/io.h> diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 602b597cedab..faf9c3b51b70 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -85,7 +85,6 @@ * (20/10/1999) */ -#include <linux/version.h> #include <linux/sched.h> #include <linux/signal.h> #include <linux/spinlock.h> diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c index 3f2305bf964b..7f456725a6b4 100644 --- a/drivers/usb/media/ov511.c +++ b/drivers/usb/media/ov511.c @@ -36,7 +36,6 @@ */ #include <linux/config.h> -#include <linux/version.h> #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c index 1b5df6990a4c..f8113626df13 100644 --- a/drivers/usb/media/stv680.c +++ b/drivers/usb/media/stv680.c @@ -60,7 +60,6 @@ #include <linux/config.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/vmalloc.h> diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index 02e22f53b45b..93a3b241c908 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c @@ -78,19 +78,28 @@ static int emi26_set_reset (struct usb_device *dev, unsigned char reset_bit) return response; } +#define FW_LOAD_SIZE 1023 + static int emi26_load_firmware (struct usb_device *dev) { int err; int i; int pos = 0; /* Position in hex record */ __u32 addr; /* Address to write */ - __u8 buf[1023]; + __u8 *buf; + + buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL); + if (!buf) { + err( "%s - error loading firmware: error = %d", __FUNCTION__, -ENOMEM); + err = -ENOMEM; + goto wraperr; + } /* Assert reset (stop the CPU in the EMI) */ err = emi26_set_reset(dev,1); if (err < 0) { err( "%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } /* 1. We need to put the loader for the FPGA into the EZ-USB */ @@ -98,7 +107,7 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } } @@ -113,7 +122,7 @@ static int emi26_load_firmware (struct usb_device *dev) addr = g_bitstream[pos].address; /* intel hex records are terminated with type 0 element */ - while ((g_bitstream[pos].type == 0) && (i + g_bitstream[pos].length < sizeof(buf))) { + while ((g_bitstream[pos].type == 0) && (i + g_bitstream[pos].length < FW_LOAD_SIZE)) { memcpy(buf + i, g_bitstream[pos].data, g_bitstream[pos].length); i += g_bitstream[pos].length; pos++; @@ -121,7 +130,7 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } } while (i > 0); @@ -129,7 +138,7 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_set_reset(dev,1); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */ @@ -137,7 +146,7 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } } @@ -145,7 +154,7 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_set_reset(dev,0); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */ @@ -154,7 +163,7 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_EXTERNAL); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } } } @@ -163,7 +172,7 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_set_reset(dev,1); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } for (i=0; g_Firmware[i].type == 0; i++) { @@ -171,7 +180,7 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_INTERNAL); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } } } @@ -180,12 +189,16 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_set_reset(dev,0); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } /* return 1 to fail the driver inialization * and give real driver change to load */ return 1; + +wraperr: + kfree(buf); + return err; } static __devinitdata struct usb_device_id id_table [] = { diff --git a/drivers/usb/misc/speedtch.c b/drivers/usb/misc/speedtch.c index d2006a09c36e..7ee2a0168392 100644 --- a/drivers/usb/misc/speedtch.c +++ b/drivers/usb/misc/speedtch.c @@ -148,27 +148,15 @@ struct udsl_control { #define UDSL_SKB(x) ((struct udsl_control *)(x)->cb) -struct atmsar_vcc_data { - struct atmsar_vcc_data *next; - - /* general atmsar flags, per connection */ - int flags; - int type; - - /* connection specific non-atmsar data */ +struct udsl_vcc_data { + /* vpi/vci lookup */ + struct list_head list; + short vpi; + int vci; struct atm_vcc *vcc; - struct k_atm_aal_stats *stats; - unsigned short mtu; /* max is actually 65k for AAL5... */ - - /* cell data */ - unsigned int vp; - unsigned int vc; - unsigned char gfc; - unsigned char pti; - unsigned int headerFlags; - unsigned long atmHeader; /* raw cell reassembly */ + unsigned short mtu; struct sk_buff *reasBuffer; }; @@ -186,7 +174,7 @@ struct udsl_instance_data { /* atm device part */ struct atm_dev *atm_dev; - struct atmsar_vcc_data *atmsar_vcc_list; + struct list_head vcc_list; /* receiving */ struct udsl_receiver all_receivers [UDSL_NUMBER_RCV_URBS]; @@ -258,73 +246,46 @@ static struct usb_driver udsl_usb_driver = { ** decode ** *************/ -#define ATM_HDR_VPVC_MASK (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK) -#define ATMSAR_USE_53BYTE_CELL 0x1L +static inline struct udsl_vcc_data *udsl_find_vcc (struct udsl_instance_data *instance, short vpi, int vci) +{ + struct udsl_vcc_data *vcc; + + list_for_each_entry (vcc, &instance->vcc_list, list) + if ((vcc->vpi == vpi) && (vcc->vci == vci)) + return vcc; + return NULL; +} -struct sk_buff *atmsar_decode_rawcell (struct atmsar_vcc_data *list, struct sk_buff *skb, - struct atmsar_vcc_data **ctx) +static struct sk_buff *udsl_decode_rawcell (struct udsl_instance_data *instance, struct sk_buff *skb, struct udsl_vcc_data **ctx) { + if (!instance || !skb || !ctx) + return NULL; + if (!skb->data || !skb->tail) + return NULL; + while (skb->len) { unsigned char *cell = skb->data; unsigned char *cell_payload; - struct atmsar_vcc_data *vcc = list; - unsigned long atmHeader = - ((unsigned long) (cell[0]) << 24) | ((unsigned long) (cell[1]) << 16) | - ((unsigned long) (cell[2]) << 8) | (cell[3] & 0xff); + struct udsl_vcc_data *vcc; + short vpi; + int vci; - dbg ("atmsar_decode_rawcell (0x%p, 0x%p, 0x%p) called", list, skb, ctx); - dbg ("atmsar_decode_rawcell skb->data %p, skb->tail %p", skb->data, skb->tail); + vpi = ((cell[0] & 0x0f) << 4) | (cell[1] >> 4); + vci = ((cell[1] & 0x0f) << 12) | (cell[2] << 4) | (cell[3] >> 4); - if (!list || !skb || !ctx) - return NULL; - if (!skb->data || !skb->tail) - return NULL; + dbg ("udsl_decode_rawcell (0x%p, 0x%p, 0x%p) called", instance, skb, ctx); + dbg ("udsl_decode_rawcell skb->data %p, skb->tail %p", skb->data, skb->tail); /* here should the header CRC check be... */ - /* look up correct vcc */ - for (; - vcc - && ((vcc->atmHeader & ATM_HDR_VPVC_MASK) != (atmHeader & ATM_HDR_VPVC_MASK)); - vcc = vcc->next); - - dbg ("atmsar_decode_rawcell found vcc %p for packet on vp %d, vc %d", vcc, - (int) ((atmHeader & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT), - (int) ((atmHeader & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT)); + if (!(vcc = udsl_find_vcc (instance, vpi, vci))) + dbg ("udsl_decode_rawcell: no vcc found for packet on vpi %d, vci %d", vpi, vci); + else { + dbg ("udsl_decode_rawcell found vcc %p for packet on vpi %d, vci %d", vcc, vpi, vci); - if (vcc && (skb->len >= (vcc->flags & ATMSAR_USE_53BYTE_CELL ? 53 : 52))) { - cell_payload = cell + (vcc->flags & ATMSAR_USE_53BYTE_CELL ? 5 : 4); + if (skb->len >= 53) { + cell_payload = cell + 5; - switch (vcc->type) { - case ATM_AAL0: - /* case ATM_AAL1: when we have a decode AAL1 function... */ - { - struct sk_buff *tmp = dev_alloc_skb (vcc->mtu); - - if (tmp) { - memcpy (tmp->tail, cell_payload, 48); - skb_put (tmp, 48); - - if (vcc->stats) - atomic_inc (&vcc->stats->rx); - - skb_pull (skb, - (vcc-> - flags & ATMSAR_USE_53BYTE_CELL ? 53 : - 52)); - dbg - ("atmsar_decode_rawcell returns ATM_AAL0 pdu 0x%p with length %d", - tmp, tmp->len); - return tmp; - }; - } - break; - case ATM_AAL1: - case ATM_AAL2: - case ATM_AAL34: - /* not supported */ - break; - case ATM_AAL5: if (!vcc->reasBuffer) vcc->reasBuffer = dev_alloc_skb (vcc->mtu); @@ -347,43 +308,36 @@ struct sk_buff *atmsar_decode_rawcell (struct atmsar_vcc_data *list, struct sk_b /* the aal5 buffer ends here, cut the buffer. */ /* buffer will always have at least one whole cell, so */ /* don't need to check return from skb_pull */ - skb_pull (skb, - (vcc-> - flags & ATMSAR_USE_53BYTE_CELL ? 53 : - 52)); + skb_pull (skb, 53); *ctx = vcc; tmp = vcc->reasBuffer; vcc->reasBuffer = NULL; - dbg - ("atmsar_decode_rawcell returns ATM_AAL5 pdu 0x%p with length %d", - tmp, tmp->len); + dbg ("udsl_decode_rawcell returns ATM_AAL5 pdu 0x%p with length %d", tmp, tmp->len); return tmp; } } - break; - }; - /* flush the cell */ - /* buffer will always contain at least one whole cell, so don't */ - /* need to check return value from skb_pull */ - skb_pull (skb, (vcc->flags & ATMSAR_USE_53BYTE_CELL ? 53 : 52)); - } else { - /* If data is corrupt and skb doesn't hold a whole cell, flush the lot */ - if (skb_pull (skb, (list->flags & ATMSAR_USE_53BYTE_CELL ? 53 : 52)) == - NULL) - return NULL; + /* flush the cell */ + /* buffer will always contain at least one whole cell, so don't */ + /* need to check return value from skb_pull */ + skb_pull (skb, 53); + } else { + /* If data is corrupt and skb doesn't hold a whole cell, flush the lot */ + if (skb_pull (skb, 53) == NULL) + return NULL; + } } } return NULL; -}; +} -struct sk_buff *atmsar_decode_aal5 (struct atmsar_vcc_data *ctx, struct sk_buff *skb) +static struct sk_buff *udsl_decode_aal5 (struct udsl_vcc_data *ctx, struct sk_buff *skb) { uint crc = 0xffffffff; uint length, pdu_crc, pdu_length; - dbg ("atmsar_decode_aal5 (0x%p, 0x%p) called", ctx, skb); + dbg ("udsl_decode_aal5 (0x%p, 0x%p) called", ctx, skb); if (skb->len && (skb->len % 48)) return NULL; @@ -393,20 +347,18 @@ struct sk_buff *atmsar_decode_aal5 (struct atmsar_vcc_data *ctx, struct sk_buff (skb->tail[-4] << 24) + (skb->tail[-3] << 16) + (skb->tail[-2] << 8) + skb->tail[-1]; pdu_length = ((length + 47 + 8) / 48) * 48; - dbg ("atmsar_decode_aal5: skb->len = %d, length = %d, pdu_crc = 0x%x, pdu_length = %d", - skb->len, length, pdu_crc, pdu_length); + dbg ("udsl_decode_aal5: skb->len = %d, length = %d, pdu_crc = 0x%x, pdu_length = %d", skb->len, length, pdu_crc, pdu_length); /* is skb long enough ? */ if (skb->len < pdu_length) { - if (ctx->stats) - atomic_inc (&ctx->stats->rx_err); + if (ctx->vcc->stats) + atomic_inc (&ctx->vcc->stats->rx_err); return NULL; } /* is skb too long ? */ if (skb->len > pdu_length) { - dbg ("atmsar_decode_aal5: Warning: readjusting illeagl size %d -> %d", - skb->len, pdu_length); + dbg ("udsl_decode_aal5: Warning: readjusting illegal size %d -> %d", skb->len, pdu_length); /* buffer is too long. we can try to recover * if we discard the first part of the skb. * the crc will decide whether this was ok @@ -418,9 +370,9 @@ struct sk_buff *atmsar_decode_aal5 (struct atmsar_vcc_data *ctx, struct sk_buff /* check crc */ if (pdu_crc != crc) { - dbg ("atmsar_decode_aal5: crc check failed!"); - if (ctx->stats) - atomic_inc (&ctx->stats->rx_err); + dbg ("udsl_decode_aal5: crc check failed!"); + if (ctx->vcc->stats) + atomic_inc (&ctx->vcc->stats->rx_err); return NULL; } @@ -428,19 +380,20 @@ struct sk_buff *atmsar_decode_aal5 (struct atmsar_vcc_data *ctx, struct sk_buff skb_trim (skb, length); /* update stats */ - if (ctx->stats) - atomic_inc (&ctx->stats->rx); + if (ctx->vcc->stats) + atomic_inc (&ctx->vcc->stats->rx); - dbg ("atmsar_decode_aal5 returns pdu 0x%p with length %d", skb, skb->len); + dbg ("udsl_decode_aal5 returns pdu 0x%p with length %d", skb, skb->len); return skb; -}; +} /************* ** encode ** *************/ -static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb) { +static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb) +{ struct udsl_control *ctrl = UDSL_SKB (skb); unsigned int i, zero_padding; unsigned char zero = 0; @@ -480,7 +433,8 @@ static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb) { ctrl->aal5_trailer [7] = crc; } -unsigned int udsl_write_cells (unsigned int howmany, struct sk_buff *skb, unsigned char **target_p) { +static unsigned int udsl_write_cells (unsigned int howmany, struct sk_buff *skb, unsigned char **target_p) +{ struct udsl_control *ctrl = UDSL_SKB (skb); unsigned char *target = *target_p; unsigned int nc, ne, i; @@ -569,7 +523,7 @@ static void udsl_process_receive (unsigned long data) unsigned char *data_start; struct sk_buff *skb; struct urb *urb; - struct atmsar_vcc_data *atmsar_vcc = NULL; + struct udsl_vcc_data *atmsar_vcc = NULL; struct sk_buff *new = NULL, *tmp = NULL; int err; @@ -597,40 +551,28 @@ static void udsl_process_receive (unsigned long data) dbg ("skb->len = %d", skb->len); PACKETDEBUG (skb->data, skb->len); - while ((new = - atmsar_decode_rawcell (instance->atmsar_vcc_list, skb, - &atmsar_vcc)) != NULL) { + while ((new = udsl_decode_rawcell (instance, skb, &atmsar_vcc))) { dbg ("(after cell processing)skb->len = %d", new->len); - switch (atmsar_vcc->type) { - case ATM_AAL5: - tmp = new; - new = atmsar_decode_aal5 (atmsar_vcc, new); - - /* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */ - if (new) { - dbg ("(after aal5 decap) skb->len = %d", new->len); - if (new->len && atm_charge (atmsar_vcc->vcc, new->truesize)) { - PACKETDEBUG (new->data, new->len); - atmsar_vcc->vcc->push (atmsar_vcc->vcc, new); - } else { - dbg - ("dropping incoming packet : rx_inuse = %d, vcc->sk->rcvbuf = %d, skb->true_size = %d", - atomic_read (&atmsar_vcc->vcc->rx_inuse), - atmsar_vcc->vcc->sk->rcvbuf, new->truesize); - dev_kfree_skb (new); - } + tmp = new; + new = udsl_decode_aal5 (atmsar_vcc, new); + + /* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */ + if (new) { + dbg ("(after aal5 decap) skb->len = %d", new->len); + if (new->len && atm_charge (atmsar_vcc->vcc, new->truesize)) { + PACKETDEBUG (new->data, new->len); + atmsar_vcc->vcc->push (atmsar_vcc->vcc, new); } else { - dbg ("atmsar_decode_aal5 returned NULL!"); - dev_kfree_skb (tmp); + dbg + ("dropping incoming packet : rx_inuse = %d, vcc->sk->rcvbuf = %d, skb->true_size = %d", + atomic_read (&atmsar_vcc->vcc->rx_inuse), + atmsar_vcc->vcc->sk->rcvbuf, new->truesize); + dev_kfree_skb (new); } - break; - default: - /* not supported. we delete the skb. */ - printk (KERN_INFO - "SpeedTouch USB: illegal vcc type. Dropping packet.\n"); - dev_kfree_skb (new); - break; + } else { + dbg ("udsl_decode_aal5 returned NULL!"); + dev_kfree_skb (tmp); } } @@ -901,95 +843,6 @@ static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb) ** ATM ** **********/ -#define ATMSAR_DEF_MTU_AAL0 48 -#define ATMSAR_DEF_MTU_AAL1 47 -#define ATMSAR_DEF_MTU_AAL2 0 /* not supported */ -#define ATMSAR_DEF_MTU_AAL34 0 /* not supported */ -#define ATMSAR_DEF_MTU_AAL5 65535 /* max mtu .. */ - -struct atmsar_vcc_data *atmsar_open (struct atmsar_vcc_data **list, struct atm_vcc *vcc, uint type, - ushort vpi, ushort vci, unchar pti, unchar gfc, uint flags) -{ - struct atmsar_vcc_data *new; - - if (!vcc) - return NULL; - - new = kmalloc (sizeof (struct atmsar_vcc_data), GFP_KERNEL); - - if (!new) - return NULL; - - memset (new, 0, sizeof (struct atmsar_vcc_data)); - new->vcc = vcc; - new->stats = vcc->stats; - new->type = type; - new->next = NULL; - new->gfc = gfc; - new->vp = vpi; - new->vc = vci; - new->pti = pti; - - switch (type) { - case ATM_AAL0: - new->mtu = ATMSAR_DEF_MTU_AAL0; - break; - case ATM_AAL1: - new->mtu = ATMSAR_DEF_MTU_AAL1; - break; - case ATM_AAL2: - new->mtu = ATMSAR_DEF_MTU_AAL2; - break; - case ATM_AAL34: - /* not supported */ - new->mtu = ATMSAR_DEF_MTU_AAL34; - break; - case ATM_AAL5: - new->mtu = ATMSAR_DEF_MTU_AAL5; - break; - } - - new->atmHeader = ((unsigned long) gfc << ATM_HDR_GFC_SHIFT) - | ((unsigned long) vpi << ATM_HDR_VPI_SHIFT) - | ((unsigned long) vci << ATM_HDR_VCI_SHIFT) - | ((unsigned long) pti << ATM_HDR_PTI_SHIFT); - new->flags = flags; - new->next = NULL; - new->reasBuffer = NULL; - - new->next = *list; - *list = new; - - dbg ("Allocated new SARLib vcc 0x%p with vp %d vc %d", new, vpi, vci); - - return new; -} - -void atmsar_close (struct atmsar_vcc_data **list, struct atmsar_vcc_data *vcc) -{ - struct atmsar_vcc_data *work; - - if (*list == vcc) { - *list = (*list)->next; - } else { - for (work = *list; work && work->next && (work->next != vcc); work = work->next); - - /* return if not found */ - if (work->next != vcc) - return; - - work->next = work->next->next; - } - - if (vcc->reasBuffer) { - dev_kfree_skb (vcc->reasBuffer); - } - - dbg ("Allocated SARLib vcc 0x%p with vp %d vc %d", vcc, vcc->vp, vcc->vc); - - kfree (vcc); -} - static void udsl_atm_dev_close (struct atm_dev *dev) { struct udsl_instance_data *instance = dev->dev_data; @@ -1061,11 +914,10 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page) return 0; } -#define ATMSAR_SET_PTI 0x2L - static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci) { struct udsl_instance_data *instance = vcc->dev->dev_data; + struct udsl_vcc_data *new; dbg ("udsl_atm_open called"); @@ -1074,63 +926,97 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci) return -ENODEV; } - /* at the moment only AAL5 support */ + if ((vpi == ATM_VPI_ANY) || (vci == ATM_VCI_ANY)) + return -EINVAL; + + /* only support AAL5 */ if (vcc->qos.aal != ATM_AAL5) return -EINVAL; - MOD_INC_USE_COUNT; + down (&instance->serialize); /* vs self, udsl_atm_close */ - vcc->dev_data = - atmsar_open (&(instance->atmsar_vcc_list), vcc, ATM_AAL5, vpi, vci, 0, 0, - ATMSAR_USE_53BYTE_CELL | ATMSAR_SET_PTI); - if (!vcc->dev_data) { - MOD_DEC_USE_COUNT; - return -ENOMEM; /* this is the only reason atmsar_open can fail... */ + if (udsl_find_vcc (instance, vpi, vci)) { + up (&instance->serialize); + return -EADDRINUSE; } + if (!(new = kmalloc (sizeof (struct udsl_vcc_data), GFP_KERNEL))) { + up (&instance->serialize); + return -ENOMEM; + } + + memset (new, 0, sizeof (struct udsl_vcc_data)); + new->vcc = vcc; + new->vpi = vpi; + new->vci = vci; + new->mtu = UDSL_MAX_AAL5_MRU; + + vcc->dev_data = new; vcc->vpi = vpi; vcc->vci = vci; + + tasklet_disable (&instance->receive_tasklet); + list_add (&new->list, &instance->vcc_list); + tasklet_enable (&instance->receive_tasklet); + set_bit (ATM_VF_ADDR, &vcc->flags); set_bit (ATM_VF_PARTIAL, &vcc->flags); set_bit (ATM_VF_READY, &vcc->flags); - ((struct atmsar_vcc_data *)vcc->dev_data)->mtu = UDSL_MAX_AAL5_MRU; + up (&instance->serialize); + + dbg ("Allocated new SARLib vcc 0x%p with vpi %d vci %d", new, vpi, vci); + + MOD_INC_USE_COUNT; if (instance->firmware_loaded) udsl_fire_receivers (instance); dbg ("udsl_atm_open successful"); + return 0; } static void udsl_atm_close (struct atm_vcc *vcc) { struct udsl_instance_data *instance = vcc->dev->dev_data; + struct udsl_vcc_data *vcc_data = vcc->dev_data; dbg ("udsl_atm_close called"); - if (!instance) { - dbg ("NULL instance!"); + if (!instance || !vcc_data) { + dbg ("NULL data!"); return; } - /* freeing resources */ - /* cancel all sends on this vcc */ + dbg ("Deallocating SARLib vcc 0x%p with vpi %d vci %d", vcc_data, vcc_data->vpi, vcc_data->vci); + udsl_cancel_send (instance, vcc); - atmsar_close (&(instance->atmsar_vcc_list), vcc->dev_data); + down (&instance->serialize); /* vs self, udsl_atm_open */ + + tasklet_disable (&instance->receive_tasklet); + list_del (&vcc_data->list); + tasklet_enable (&instance->receive_tasklet); + + if (vcc_data->reasBuffer) + kfree_skb (vcc_data->reasBuffer); + vcc_data->reasBuffer = NULL; + + kfree (vcc_data); vcc->dev_data = NULL; - clear_bit (ATM_VF_PARTIAL, &vcc->flags); - /* freeing address */ vcc->vpi = ATM_VPI_UNSPEC; vcc->vci = ATM_VCI_UNSPEC; + clear_bit (ATM_VF_READY, &vcc->flags); + clear_bit (ATM_VF_PARTIAL, &vcc->flags); clear_bit (ATM_VF_ADDR, &vcc->flags); + up (&instance->serialize); + MOD_DEC_USE_COUNT; dbg ("udsl_atm_close successful"); - return; } static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg) @@ -1209,6 +1095,8 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i instance->usb_dev = dev; + INIT_LIST_HEAD (&instance->vcc_list); + spin_lock_init (&instance->spare_receivers_lock); INIT_LIST_HEAD (&instance->spare_receivers); diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index cc0ecaaeee70..a0b1c423c832 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -881,6 +881,8 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) init_completion (&completion); urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size); + if (!urb) + return -ENOMEM; if (async) urb->transfer_flags |= URB_ASYNC_UNLINK; urb->context = &completion; @@ -1407,6 +1409,11 @@ static struct usb_device_id id_table [] = { .driver_info = (unsigned long) &fw_info, }, + /* "Gadget Zero" firmware runs under Linux */ + { USB_DEVICE (0x0525, 0xa4a0), + .driver_info = (unsigned long) &fw_info, + }, + #ifdef KEYSPAN_19Qi /* Keyspan 19qi uses an21xx (original EZ-USB) */ // this does not coexist with the real Keyspan 19qi driver! diff --git a/drivers/usb/net/cdc-ether.c b/drivers/usb/net/cdc-ether.c index e6b530720209..0d2cad6d33e7 100644 --- a/drivers/usb/net/cdc-ether.c +++ b/drivers/usb/net/cdc-ether.c @@ -269,22 +269,8 @@ static void CDCEther_tx_timeout( struct net_device *net ) static int CDCEther_start_xmit( struct sk_buff *skb, struct net_device *net ) { ether_dev_t *ether_dev = net->priv; - int count; int res; - // If we are told to transmit an ethernet frame that fits EXACTLY - // into an integer number of USB packets, we force it to send one - // more byte so the device will get a runt USB packet signalling the - // end of the ethernet frame - if ( (skb->len) ^ (ether_dev->data_ep_out_size) ) { - // It was not an exact multiple - // no need to add anything extra - count = skb->len; - } else { - // Add one to make it NOT an exact multiple - count = skb->len + 1; - } - // Tell the kernel, "No more frames 'til we are done // with this one.' netif_stop_queue( net ); @@ -299,7 +285,10 @@ static int CDCEther_start_xmit( struct sk_buff *skb, struct net_device *net ) write_bulk_callback, ether_dev ); // Tell the URB how much it will be transporting today - ether_dev->tx_urb->transfer_buffer_length = count; + ether_dev->tx_urb->transfer_buffer_length = skb->len; + + /* Deal with the zero length problem, I hope */ + ether_dev->tx_urb->transfer_flags |= URB_ZERO_PACKET; // Send the URB on its merry way. if ((res = usb_submit_urb(ether_dev->tx_urb, GFP_ATOMIC))) { diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 99c634017192..e15f060772f4 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -406,8 +406,6 @@ static int kobil_write (struct usb_serial_port *port, int from_user, int result = 0; int todo = 0; struct kobil_private * priv; - int i; - char *data; if (count == 0) { dbg("%s - port %d write request of 0 bytes", __FUNCTION__, port->number); @@ -421,19 +419,6 @@ static int kobil_write (struct usb_serial_port *port, int from_user, return -ENOMEM; } - // BEGIN DEBUG - data = (unsigned char *) kmalloc((3 * count + 10) * sizeof(char), GFP_KERNEL); - if (! data) { - return (-1); - } - memset(data, 0, (3 * count + 10)); - for (i = 0; i < count; i++) { - sprintf(data +3*i, "%02X ", buf[i]); - } - dbg(" %d --> %s", port->number, data ); - kfree(data); - // END DEBUG - // Copy data to buffer if (from_user) { if (copy_from_user(priv->buf + priv->filled, buf, count)) { @@ -443,6 +428,8 @@ static int kobil_write (struct usb_serial_port *port, int from_user, memcpy (priv->buf + priv->filled, buf, count); } + usb_serial_debug_data (__FILE__, __FUNCTION__, count, priv->buf + priv->filled); + priv->filled = priv->filled + count; diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 1f56f63bb8e5..9ac69a72555c 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -405,11 +405,14 @@ static int isd200_action( struct us_data *us, int action, { union ata_cdb ata; struct scsi_cmnd srb; + struct scsi_device srb_dev; struct isd200_info *info = (struct isd200_info *)us->extra; int status; memset(&ata, 0, sizeof(ata)); memset(&srb, 0, sizeof(srb)); + memset(&srb_dev, 0, sizeof(srb_dev)); + srb.device = &srb_dev; ata.generic.SignatureByte0 = info->ConfigData.ATAMajorCommand; ata.generic.SignatureByte1 = info->ConfigData.ATAMinorCommand; @@ -479,6 +482,7 @@ static int isd200_action( struct us_data *us, int action, } memcpy(srb.cmnd, &ata, sizeof(ata.generic)); + srb.cmd_len = sizeof(ata.generic); status = usb_stor_Bulk_transport(&srb, us); if (status == USB_STOR_TRANSPORT_GOOD) status = ISD200_GOOD; @@ -538,6 +542,7 @@ void isd200_invoke_transport( struct us_data *us, /* send the command to the transport layer */ srb->resid = 0; memcpy(srb->cmnd, ataCdb, sizeof(ataCdb->generic)); + srb->cmd_len = sizeof(ataCdb->generic); transferStatus = usb_stor_Bulk_transport(srb, us); /* if the command gets aborted by the higher layers, we need to diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index f30d8c162db9..f57afebe8df6 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -209,21 +209,14 @@ static int usb_storage_device_reset( Scsi_Cmnd *srb ) return result; } -/* This resets the device port, and simulates the device - * disconnect/reconnect for all drivers which have claimed - * interfaces, including ourself. */ +/* This resets the device port */ +/* It refuses to work if there's more than one interface in + this device, so that other users are not affected. */ /* This is always called with scsi_lock(srb->host) held */ -/* FIXME: This needs to be re-examined in the face of the new - * hotplug system -- this will implicitly cause a detach/reattach of - * usb-storage, which is not what we want now. - * - * Can we just skip over usb-storage in the while loop? - */ static int usb_storage_bus_reset( Scsi_Cmnd *srb ) { struct us_data *us; - int i; int result; /* we use the usb_reset_device() function to handle this for us */ @@ -231,36 +224,25 @@ static int usb_storage_bus_reset( Scsi_Cmnd *srb ) scsi_unlock(srb->device->host); us = (struct us_data *)srb->device->host->hostdata[0]; - /* attempt to reset the port */ - result = usb_reset_device(us->pusb_dev); - US_DEBUGP("usb_reset_device returns %d\n", result); - if (result < 0) { - scsi_lock(srb->device->host); - return FAILED; + /* The USB subsystem doesn't handle synchronisation between + a device's several drivers. Therefore we reset only devices + with one interface which we of course own. + */ + + //FIXME: needs locking against config changes + + if ( us->pusb_dev->actconfig->desc.bNumInterfaces == 1) { + /* attempt to reset the port */ + result = usb_reset_device(us->pusb_dev); + US_DEBUGP("usb_reset_device returns %d\n", result); + } else { + result = -EBUSY; + US_DEBUGP("cannot reset a multiinterface device. failing to reset.\n"); } - /* FIXME: This needs to lock out driver probing while it's working - * or we can have race conditions */ - /* This functionality really should be provided by the khubd thread */ - for (i = 0; i < us->pusb_dev->actconfig->desc.bNumInterfaces; i++) { - struct usb_interface *intf = - &us->pusb_dev->actconfig->interface[i]; - - /* if this is an unclaimed interface, skip it */ - if (!intf->driver) { - continue; - } - - US_DEBUGP("Examining driver %s...", intf->driver->name); - - /* simulate a disconnect and reconnect for all interfaces */ - US_DEBUGPX("simulating disconnect/reconnect.\n"); - usb_device_remove (&intf->dev); - usb_device_probe (&intf->dev); - } US_DEBUGP("bus_reset() complete\n"); scsi_lock(srb->device->host); - return SUCCESS; + return result < 0 ? FAILED : SUCCESS; } /*********************************************************************** diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index b0371f74e40a..0c59028691d0 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -126,6 +126,7 @@ static int usb_stor_msg_common(struct us_data *us) us->current_urb->actual_length = 0; us->current_urb->error_count = 0; us->current_urb->transfer_flags = URB_ASYNC_UNLINK; + us->current_urb->status = 0; /* submit the URB */ status = usb_submit_urb(us->current_urb, GFP_NOIO); @@ -900,7 +901,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) bcb.DataTransferLength = cpu_to_le32(transfer_length); bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0; bcb.Tag = srb->serial_number; - bcb.Lun = srb->cmnd[1] >> 5; + bcb.Lun = srb->device->lun; if (us->flags & US_FL_SCM_MULT_TARG) bcb.Lun |= srb->device->id << 4; bcb.Length = srb->cmd_len; diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 4c2b6de50c91..aa0b5ec968bc 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -360,7 +360,7 @@ static int usb_stor_control_thread(void * __us) } else if (us->srb->device->lun > us->max_lun) { - US_DEBUGP("Bad LUN (%d/%d)\n", + US_DEBUGP("Bad LUN (%d:%d)\n", us->srb->device->id, us->srb->device->lun); us->srb->result = DID_BAD_TARGET << 16; } @@ -475,8 +475,6 @@ static int usb_stor_allocate_urbs(struct us_data *ss) */ static void usb_stor_deallocate_urbs(struct us_data *ss) { - int result; - /* free the scatter-gather request block */ if (ss->current_sg) { kfree(ss->current_sg); @@ -486,8 +484,6 @@ static void usb_stor_deallocate_urbs(struct us_data *ss) /* free up the main URB for this device */ if (ss->current_urb) { US_DEBUGP("-- releasing main URB\n"); - result = usb_unlink_urb(ss->current_urb); - US_DEBUGP("-- usb_unlink_urb() returned %d\n", result); usb_free_urb(ss->current_urb); ss->current_urb = NULL; } diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 447382eca091..0c833fdeee42 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -72,13 +72,15 @@ MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); -/* Define these values to match your device */ +/* Define these values to match your devices */ #define USB_SKEL_VENDOR_ID 0xfff0 #define USB_SKEL_PRODUCT_ID 0xfff0 /* table of devices that work with this driver */ static struct usb_device_id skel_table [] = { { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, + /* "Gadget Zero" firmware runs under Linux */ + { USB_DEVICE(0x0525, 0xa4a0) }, { } /* Terminating entry */ }; @@ -707,7 +709,7 @@ static int __init usb_skel_init(void) /* register this driver with the USB subsystem */ result = usb_register(&skel_driver); if (result < 0) { - err("usb_register failed for the "__FILE__" driver. Error number %d", + err("usb_register failed. Error number %d", result); return -1; } diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 93afc0a65581..738ebec594dc 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. +# Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of version 2 of the GNU General Public License as @@ -29,13 +29,7 @@ # # http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ # -# Makefile for XFS on Linux. -# - -# This needs -I. because everything does #include <xfs.h> instead of "xfs.h". -# The code is wrong, local files should be included using "xfs.h", not <xfs.h> -# but I am not going to change every file at the moment. EXTRA_CFLAGS += -Ifs/xfs -funsigned-char ifeq ($(CONFIG_XFS_DEBUG),y) @@ -48,17 +42,22 @@ endif obj-$(CONFIG_XFS_FS) += xfs.o -xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o - -xfs-$(CONFIG_XFS_QUOTA) += xfs_dquot.o \ +xfs-$(CONFIG_XFS_QUOTA) += $(addprefix quota/, \ + xfs_dquot.o \ xfs_dquot_item.o \ xfs_trans_dquot.o \ xfs_qm_syscalls.o \ - xfs_qm.o + xfs_qm_bhv.o \ + xfs_qm.o) +ifeq ($(CONFIG_XFS_QUOTA),y) +xfs-$(CONFIG_PROC_FS) += quota/xfs_qm_stats.o +endif + +xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o -xfs-$(CONFIG_FS_POSIX_CAP) += xfs_cap.o -xfs-$(CONFIG_FS_POSIX_MAC) += xfs_mac.o +xfs-$(CONFIG_XFS_POSIX_CAP) += xfs_cap.o +xfs-$(CONFIG_XFS_POSIX_MAC) += xfs_mac.o xfs-$(CONFIG_PROC_FS) += linux/xfs_stats.o xfs-$(CONFIG_SYSCTL) += linux/xfs_sysctl.o @@ -127,6 +126,7 @@ xfs-y += $(addprefix linux/, \ xfs_iops.o \ xfs_lrw.o \ xfs_super.o \ + xfs_vfs.o \ xfs_vnode.o) # Objects in support/ @@ -139,6 +139,10 @@ xfs-y += $(addprefix support/, \ qsort.o \ uuid.o) +# Quota and DMAPI stubs +xfs-y += xfs_dmops.o \ + xfs_qmops.o + # If both xfs and kdb modules are built in then xfsidbg is built in. If xfs is # a module and kdb modules are being compiled then xfsidbg must be a module, to # follow xfs. If xfs is built in then xfsidbg tracks the kdb module state. diff --git a/fs/xfs/linux/xfs_aops.c b/fs/xfs/linux/xfs_aops.c index 75a9e1aa1e8e..3c33d98a7bbd 100644 --- a/fs/xfs/linux/xfs_aops.c +++ b/fs/xfs/linux/xfs_aops.c @@ -78,6 +78,7 @@ xfs_unwritten_conv( XFS_BUF_OFFSET(bp), XFS_BUF_SIZE(bp)); XFS_BUF_SET_FSPRIVATE(bp, NULL); XFS_BUF_CLR_IODONE_FUNC(bp); + XFS_BUF_UNDATAIO(bp); xfs_biodone(bp); } @@ -431,6 +432,7 @@ map_unwritten( size = nblocks; /* NB: using 64bit number here */ size <<= block_bits; /* convert fsb's to byte range */ + XFS_BUF_DATAIO(pb); XFS_BUF_SET_SIZE(pb, size); XFS_BUF_SET_OFFSET(pb, offset); XFS_BUF_SET_FSPRIVATE(pb, LINVFS_GET_VP(inode)->v_fbhv); diff --git a/fs/xfs/linux/xfs_behavior.c b/fs/xfs/linux/xfs_behavior.c index 9147a57c5ffa..b69fb1d94c28 100644 --- a/fs/xfs/linux/xfs_behavior.c +++ b/fs/xfs/linux/xfs_behavior.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -30,41 +30,77 @@ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ * */ +#include <xfs.h> /* * Source file used to associate/disassociate behaviors with virtualized - * objects. See behavior.h for more information about behaviors, etc. + * objects. See xfs_behavior.h for more information about behaviors, etc. * * The implementation is split between functions in this file and macros - * in behavior.h. + * in xfs_behavior.h. */ -#include <xfs.h> - -kmem_zone_t *bhv_global_zone; /* - * Global initialization function called out of main. + * Insert a new behavior descriptor into a behavior chain. + * + * The behavior chain is ordered based on the 'position' number which + * lives in the first field of the ops vector (higher numbers first). + * + * Attemps to insert duplicate ops result in an EINVAL return code. + * Otherwise, return 0 to indicate success. */ -void -bhv_global_init(void) +int +bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp) { + bhv_desc_t *curdesc, *prev; + int position; + + /* + * Validate the position value of the new behavior. + */ + position = BHV_POSITION(bdp); + ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP); + /* - * Initialize a behavior zone used by subsystems using behaviors - * but without any private data. In the UNIKERNEL case, this zone - * is used only for behaviors that are not yet isolated to a single - * cell. The only such user is in pshm.c in which a dummy vnode is - * obtained in support of vce avoidance logic. + * Find location to insert behavior. Check for duplicates. */ - bhv_global_zone = kmem_zone_init(sizeof(bhv_desc_t), "bhv_global_zone"); + prev = NULL; + for (curdesc = bhp->bh_first; + curdesc != NULL; + curdesc = curdesc->bd_next) { + + /* Check for duplication. */ + if (curdesc->bd_ops == bdp->bd_ops) { + ASSERT(0); + return EINVAL; + } + + /* Find correct position */ + if (position >= BHV_POSITION(curdesc)) { + ASSERT(position != BHV_POSITION(curdesc)); + break; /* found it */ + } + + prev = curdesc; + } + + if (prev == NULL) { + /* insert at front of chain */ + bdp->bd_next = bhp->bh_first; + bhp->bh_first = bdp; + } else { + /* insert after prev */ + bdp->bd_next = prev->bd_next; + prev->bd_next = bdp; + } + + return 0; } /* * Remove a behavior descriptor from a position in a behavior chain; * the postition is guaranteed not to be the first position. * Should only be called by the bhv_remove() macro. - * - * The act of modifying the chain is done atomically w.r.t. ops-in-progress - * (see comment at top of behavior.h for more info on synchronization). */ void bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp) @@ -86,7 +122,6 @@ bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp) ASSERT(curdesc == bdp); prev->bd_next = bdp->bd_next; /* remove from after prev */ - /* atomic wrt oip's */ } /* @@ -110,20 +145,28 @@ bhv_lookup(bhv_head_t *bhp, void *ops) } /* - * Look for a specific ops vector on the specified behavior chain. - * Return the associated behavior descriptor. Or NULL, if not found. - * - * The caller has not read locked the behavior chain, so acquire the - * lock before traversing the chain. + * Looks for the first behavior within a specified range of positions. + * Return the associated behavior descriptor. Or NULL, if none found. */ bhv_desc_t * -bhv_lookup_unlocked(bhv_head_t *bhp, void *ops) +bhv_lookup_range(bhv_head_t *bhp, int low, int high) { - bhv_desc_t *bdp; + bhv_desc_t *curdesc; + + for (curdesc = bhp->bh_first; + curdesc != NULL; + curdesc = curdesc->bd_next) { - bdp = bhv_lookup(bhp, ops); + int position = BHV_POSITION(curdesc); - return bdp; + if (position <= high) { + if (position >= low) + return curdesc; + return NULL; + } + } + + return NULL; } /* @@ -134,49 +177,36 @@ bhv_lookup_unlocked(bhv_head_t *bhp, void *ops) * lock before traversing the chain. */ bhv_desc_t * -bhv_base_unlocked(bhv_head_t *bhp) +bhv_base(bhv_head_t *bhp) { bhv_desc_t *curdesc; for (curdesc = bhp->bh_first; curdesc != NULL; curdesc = curdesc->bd_next) { - if (curdesc->bd_next == NULL) + + if (curdesc->bd_next == NULL) { return curdesc; + } } + return NULL; } -#define BHVMAGIC (void *)0xf00d - -/* ARGSUSED */ void bhv_head_init( bhv_head_t *bhp, char *name) { bhp->bh_first = NULL; - bhp->bh_lockp = BHVMAGIC; -} - - -/* ARGSUSED */ -void -bhv_head_reinit( - bhv_head_t *bhp) -{ - ASSERT(bhp->bh_first == NULL); - ASSERT(bhp->bh_lockp == BHVMAGIC); } - void bhv_insert_initial( bhv_head_t *bhp, bhv_desc_t *bdp) { ASSERT(bhp->bh_first == NULL); - ASSERT(bhp->bh_lockp == BHVMAGIC); (bhp)->bh_first = bdp; } @@ -185,7 +215,4 @@ bhv_head_destroy( bhv_head_t *bhp) { ASSERT(bhp->bh_first == NULL); - ASSERT(bhp->bh_lockp == BHVMAGIC); - bhp->bh_lockp = NULL; } - diff --git a/fs/xfs/linux/xfs_behavior.h b/fs/xfs/linux/xfs_behavior.h index fd165e527c8f..bae4c9359810 100644 --- a/fs/xfs/linux/xfs_behavior.h +++ b/fs/xfs/linux/xfs_behavior.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -91,8 +91,8 @@ * active object * */ - -typedef void bhv_head_lock_t; + +struct bhv_head_lock; /* * Behavior head. Head of the chain of behaviors. @@ -100,7 +100,7 @@ typedef void bhv_head_lock_t; */ typedef struct bhv_head { struct bhv_desc *bh_first; /* first behavior in chain */ - bhv_head_lock_t *bh_lockp; /* pointer to lock info struct */ + struct bhv_head_lock *bh_lockp; /* pointer to lock info struct */ } bhv_head_t; /* @@ -128,10 +128,8 @@ typedef struct bhv_identity { typedef bhv_identity_t bhv_position_t; #define BHV_IDENTITY_INIT(id,pos) {id, pos} - #define BHV_IDENTITY_INIT_POSITION(pos) BHV_IDENTITY_INIT(0, pos) - /* * Define boundaries of position values. */ @@ -154,7 +152,7 @@ typedef bhv_identity_t bhv_position_t; extern void bhv_head_init(bhv_head_t *, char *); extern void bhv_head_destroy(bhv_head_t *); -extern void bhv_head_reinit(bhv_head_t *); +extern int bhv_insert(bhv_head_t *, bhv_desc_t *); extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *); /* @@ -196,7 +194,11 @@ extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *); */ extern void bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp); extern bhv_desc_t * bhv_lookup(bhv_head_t *bhp, void *ops); -extern bhv_desc_t * bhv_lookup_unlocked(bhv_head_t *bhp, void *ops); -extern bhv_desc_t * bhv_base_unlocked(bhv_head_t *bhp); +extern bhv_desc_t * bhv_lookup_range(bhv_head_t *bhp, int low, int high); +extern bhv_desc_t * bhv_base(bhv_head_t *bhp); + +/* No bhv locking on Linux */ +#define bhv_lookup_unlocked bhv_lookup +#define bhv_base_unlocked bhv_base #endif /* __XFS_BEHAVIOR_H__ */ diff --git a/fs/xfs/linux/xfs_file.c b/fs/xfs/linux/xfs_file.c index 25d6df57e0ab..0331e582c830 100644 --- a/fs/xfs/linux/xfs_file.c +++ b/fs/xfs/linux/xfs_file.c @@ -299,7 +299,9 @@ linvfs_file_mmap( int error; if ((vp->v_type == VREG) && (vp->v_vfsp->vfs_flag & VFS_DMI)) { - error = -xfs_dm_send_mmap_event(vma, 0); + xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); + + error = -XFS_SEND_MMAP(mp, vma, 0); if (error) return error; } @@ -345,8 +347,10 @@ linvfs_mprotect( if ((vp->v_type == VREG) && (vp->v_vfsp->vfs_flag & VFS_DMI)) { if ((vma->vm_flags & VM_MAYSHARE) && - (newflags & PROT_WRITE) && !(vma->vm_flags & PROT_WRITE)){ - error = xfs_dm_send_mmap_event(vma, VM_WRITE); + (newflags & PROT_WRITE) && !(vma->vm_flags & PROT_WRITE)) { + xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); + + error = XFS_SEND_MMAP(mp, vma, VM_WRITE); } } return error; diff --git a/fs/xfs/linux/xfs_globals.c b/fs/xfs/linux/xfs_globals.c index 40fd5618f100..21ac11aecd99 100644 --- a/fs/xfs/linux/xfs_globals.c +++ b/fs/xfs/linux/xfs_globals.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -40,7 +40,7 @@ /* * System memory size - used to scale certain data structures in XFS. */ -unsigned long xfs_physmem; +unsigned long xfs_physmem; /* * Tunable XFS parameters. xfs_params is required even when CONFIG_SYSCTL=n, @@ -51,24 +51,14 @@ xfs_param_t xfs_params = { 0, 1, 0, 0, 0, 3 }; /* * Used to serialize atomicIncWithWrap. */ -spinlock_t Atomic_spin = SPIN_LOCK_UNLOCKED; +spinlock_t xfs_atomic_spin = SPIN_LOCK_UNLOCKED; /* * Global system credential structure. */ cred_t sys_cred_val, *sys_cred = &sys_cred_val; -/* - * The global quota manager. There is only one of these for the entire - * system, _not_ one per file system. XQM keeps track of the overall - * quota functionality, including maintaining the freelist and hash - * tables of dquots. - */ -struct xfs_qm *xfs_Gqm; -mutex_t xfs_Gqm_lock; - /* Export XFS symbols used by xfsidbg */ -EXPORT_SYMBOL(xfs_Gqm); EXPORT_SYMBOL(xfs_next_bit); EXPORT_SYMBOL(xfs_contig_bits); EXPORT_SYMBOL(xfs_bmbt_get_all); diff --git a/fs/xfs/linux/xfs_globals.h b/fs/xfs/linux/xfs_globals.h index 07c9856b1353..190e0717617c 100644 --- a/fs/xfs/linux/xfs_globals.h +++ b/fs/xfs/linux/xfs_globals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -39,11 +39,10 @@ extern uint64_t xfs_panic_mask; /* set to cause more panics */ -extern unsigned long xfs_physmem; +extern unsigned long xfs_physmem; -extern struct cred *sys_cred; +extern spinlock_t xfs_atomic_spin; -extern struct xfs_qm *xfs_Gqm; -extern mutex_t xfs_Gqm_lock; +extern struct cred *sys_cred; #endif /* __XFS_GLOBALS_H__ */ diff --git a/fs/xfs/linux/xfs_ioctl.c b/fs/xfs/linux/xfs_ioctl.c index f411729ca11e..b0dd066307dc 100644 --- a/fs/xfs/linux/xfs_ioctl.c +++ b/fs/xfs/linux/xfs_ioctl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -130,7 +130,7 @@ xfs_find_handle( int lock_mode; /* need to get access to the xfs_inode to read the generation */ - bhv = VNODE_TO_FIRST_BHV(vp); + bhv = vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops); ASSERT(bhv); ip = XFS_BHVTOI(bhv); ASSERT(ip); diff --git a/fs/xfs/linux/xfs_iomap.c b/fs/xfs/linux/xfs_iomap.c index cc1ab771ede0..a96e2141e141 100644 --- a/fs/xfs/linux/xfs_iomap.c +++ b/fs/xfs/linux/xfs_iomap.c @@ -258,11 +258,10 @@ xfs_iomap_write_direct( * the ilock across a disk read. */ - if (XFS_IS_QUOTA_ON(mp) && XFS_NOT_DQATTACHED(mp, ip)) { - if ((error = xfs_qm_dqattach(ip, XFS_QMOPT_ILOCKED))) { - return XFS_ERROR(error); - } - } + error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED); + if (error) + return XFS_ERROR(error); + maps = min(XFS_WRITE_IMAPS, *nmaps); nimaps = maps; @@ -291,7 +290,7 @@ xfs_iomap_write_direct( * determine if reserving space on * the data or realtime partition. */ - if ((rt = ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) { + if ((rt = XFS_IS_REALTIME_INODE(ip))) { int sbrtextsize, iprtextsize; sbrtextsize = mp->m_sb.sb_rextsize; @@ -333,11 +332,9 @@ xfs_iomap_write_direct( goto error_out; /* Don't return in above if .. trans .., need lock to return */ - if (XFS_IS_QUOTA_ON(mp)) { - if (xfs_trans_reserve_blkquota(tp, ip, resblks)) { - error = (EDQUOT); - goto error1; - } + if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) { + error = (EDQUOT); + goto error1; } nimaps = 1; @@ -422,11 +419,9 @@ xfs_iomap_write_delay( * the ilock across a disk read. */ - if (XFS_IS_QUOTA_ON(mp) && XFS_NOT_DQATTACHED(mp, ip)) { - if ((error = xfs_qm_dqattach(ip, XFS_QMOPT_ILOCKED))) { - return XFS_ERROR(error); - } - } + error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED); + if (error) + return XFS_ERROR(error); retry: isize = ip->i_d.di_size; @@ -538,11 +533,8 @@ xfs_iomap_write_allocate( * Make sure that the dquots are there. */ - if (XFS_IS_QUOTA_ON(mp) && XFS_NOT_DQATTACHED(mp, ip)) { - if ((error = xfs_qm_dqattach(ip, 0))) { - return XFS_ERROR(error); - } - } + if ((error = XFS_QM_DQATTACH(mp, ip, 0))) + return XFS_ERROR(error); offset_fsb = map->br_startoff; count_fsb = map->br_blockcount; diff --git a/fs/xfs/linux/xfs_linux.h b/fs/xfs/linux/xfs_linux.h index bd6434eb8c7a..aba0b1fdf2dc 100644 --- a/fs/xfs/linux/xfs_linux.h +++ b/fs/xfs/linux/xfs_linux.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -44,6 +44,7 @@ #include <linux/major.h> #include <linux/pagemap.h> #include <linux/vfs.h> +#include <linux/seq_file.h> #include <asm/page.h> #include <asm/div64.h> @@ -160,6 +161,15 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh) #define SYNCHRONIZE() barrier() #define __return_address __builtin_return_address(0) +/* + * IRIX (BSD) quotactl makes use of separate commands for user/group, + * whereas on Linux the syscall encodes this information into the cmd + * field (see the QCMD macro in quota.h). These macros help keep the + * code portable - they are not visible from the syscall interface. + */ +#define Q_XSETGQLIM XQM_CMD(0x8) /* set groups disk limits */ +#define Q_XGETGQUOTA XQM_CMD(0x9) /* get groups disk limits */ + /* IRIX uses a dynamic sizing algorithm (ndquot = 200 + numprocs*2) */ /* we may well need to fine-tune this if it ever becomes an issue. */ #define DQUOT_MAX_HEURISTIC 1024 /* NR_DQUOTS */ diff --git a/fs/xfs/linux/xfs_lrw.c b/fs/xfs/linux/xfs_lrw.c index 214ac45c2485..2ee9f08d8721 100644 --- a/fs/xfs/linux/xfs_lrw.c +++ b/fs/xfs/linux/xfs_lrw.c @@ -121,7 +121,8 @@ xfs_read( xfs_mount_t *mp; vnode_t *vp; unsigned long seg; - int direct = filp->f_flags & O_DIRECT; + int direct = (filp->f_flags & O_DIRECT); + int invisible = (filp->f_mode & FINVIS); ip = XFS_BHVTOI(bdp); vp = BHV_TO_VNODE(bdp); @@ -180,13 +181,12 @@ xfs_read( xfs_ilock(ip, XFS_IOLOCK_SHARED); - if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && - !(filp->f_mode & FINVIS)) { + if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && !invisible) { int error; vrwlock_t locktype = VRWLOCK_READ; - error = xfs_dm_send_data_event(DM_EVENT_READ, bdp, *offp, - size, FILP_DELAY_FLAG(filp), &locktype); + error = XFS_SEND_DATA(mp, DM_EVENT_READ, bdp, *offp, size, + FILP_DELAY_FLAG(filp), &locktype); if (error) { xfs_iunlock(ip, XFS_IOLOCK_SHARED); return -error; @@ -198,7 +198,7 @@ xfs_read( XFS_STATS_ADD(xfsstats.xs_read_bytes, ret); - if (!(filp->f_mode & FINVIS)) + if (!invisible) xfs_ichgtime(ip, XFS_ICHGTIME_ACC); return ret; @@ -217,11 +217,13 @@ xfs_sendfile( ssize_t ret; xfs_fsize_t n; xfs_inode_t *ip; + xfs_mount_t *mp; vnode_t *vp; int invisible = (filp->f_mode & FINVIS); ip = XFS_BHVTOI(bdp); vp = BHV_TO_VNODE(bdp); + mp = ip->i_mount; vn_trace_entry(vp, "xfs_sendfile", (inst_t *)__return_address); XFS_STATS_INC(xfsstats.xs_read_calls); @@ -241,8 +243,8 @@ xfs_sendfile( vrwlock_t locktype = VRWLOCK_READ; int error; - error = xfs_dm_send_data_event(DM_EVENT_READ, bdp, *offp, - count, FILP_DELAY_FLAG(filp), &locktype); + error = XFS_SEND_DATA(mp, DM_EVENT_READ, bdp, *offp, count, + FILP_DELAY_FLAG(filp), &locktype); if (error) { xfs_iunlock(ip, XFS_IOLOCK_SHARED); return -error; @@ -493,7 +495,8 @@ xfs_write( vnode_t *vp; unsigned long seg; int iolock; - int direct = file->f_flags & O_DIRECT; + int direct = (file->f_flags & O_DIRECT); + int invisible = (file->f_mode & FINVIS); int eventsent = 0; vrwlock_t locktype; @@ -573,13 +576,13 @@ start: } if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) && - !(file->f_mode & FINVIS) && !eventsent)) { + !invisible && !eventsent)) { loff_t savedsize = *offset; xfs_iunlock(xip, XFS_ILOCK_EXCL); - error = xfs_dm_send_data_event(DM_EVENT_WRITE, bdp, - *offset, size, - FILP_DELAY_FLAG(file), &locktype); + error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, bdp, + *offset, size, + FILP_DELAY_FLAG(file), &locktype); if (error) { xfs_iunlock(xip, iolock); return -error; @@ -588,12 +591,11 @@ start: eventsent = 1; /* - * The iolock was dropped and reaquired in - * xfs_dm_send_data_event so we have to recheck the size - * when appending. We will only "goto start;" once, - * since having sent the event prevents another call - * to xfs_dm_send_data_event, which is what - * allows the size to change in the first place. + * The iolock was dropped and reaquired in XFS_SEND_DATA + * so we have to recheck the size when appending. + * We will only "goto start;" once, since having sent the + * event prevents another call to XFS_SEND_DATA, which is + * what allows the size to change in the first place. */ if ((file->f_flags & O_APPEND) && savedsize != xip->i_d.di_size) { @@ -608,10 +610,8 @@ start: * * We must update xfs' times since revalidate will overcopy xfs. */ - if (size) { - if (!(file->f_mode & FINVIS)) - xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); - } + if (size && !invisible) + xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); /* * If the offset is beyond the size of the file, we have a couple @@ -658,11 +658,10 @@ retry: ret = generic_file_write_nolock(file, iovp, segs, offset); if ((ret == -ENOSPC) && - DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) && - !(file->f_mode & FINVIS)) { + DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) && !invisible) { xfs_rwunlock(bdp, locktype); - error = dm_send_namesp_event(DM_EVENT_NOSPACE, bdp, + error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, bdp, DM_RIGHT_NULL, bdp, DM_RIGHT_NULL, NULL, NULL, 0, 0, 0); /* Delay flag intentionally unused */ if (error) diff --git a/fs/xfs/linux/xfs_stats.c b/fs/xfs/linux/xfs_stats.c index 578d5bb0b4cf..5face9af532b 100644 --- a/fs/xfs/linux/xfs_stats.c +++ b/fs/xfs/linux/xfs_stats.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -61,7 +61,6 @@ xfs_read_xfsstats( { "xstrat", XFSSTAT_END_WRITE_CONVERT }, { "rw", XFSSTAT_END_READ_WRITE_OPS }, { "attr", XFSSTAT_END_ATTRIBUTE_OPS }, - { "qm", XFSSTAT_END_QUOTA_OPS }, { "icluster", XFSSTAT_END_INODE_CLUSTER }, { "vnodes", XFSSTAT_END_VNODE_OPS }, }; @@ -95,50 +94,17 @@ xfs_read_xfsstats( return len; } -STATIC int -xfs_read_xfsquota( - char *buffer, - char **start, - off_t offset, - int count, - int *eof, - void *data) -{ - int len; - - /* maximum; incore; ratio free to inuse; freelist */ - len = sprintf(buffer, "%d\t%d\t%d\t%u\n", - ndquot, - xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0, - xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0, - xfs_Gqm? xfs_Gqm->qm_dqfreelist.qh_nelems : 0); - - if (offset >= len) { - *start = buffer; - *eof = 1; - return 0; - } - *start = buffer + offset; - if ((len -= offset) > count) - return count; - *eof = 1; - - return len; -} - void xfs_init_procfs(void) { if (!proc_mkdir("fs/xfs", 0)) return; create_proc_read_entry("fs/xfs/stat", 0, 0, xfs_read_xfsstats, NULL); - create_proc_read_entry("fs/xfs/xqm", 0, 0, xfs_read_xfsquota, NULL); } void xfs_cleanup_procfs(void) { remove_proc_entry("fs/xfs/stat", NULL); - remove_proc_entry("fs/xfs/xqm", NULL); remove_proc_entry("fs/xfs", NULL); } diff --git a/fs/xfs/linux/xfs_stats.h b/fs/xfs/linux/xfs_stats.h index c4192e35482b..c5eb3b848c5a 100644 --- a/fs/xfs/linux/xfs_stats.h +++ b/fs/xfs/linux/xfs_stats.h @@ -107,16 +107,7 @@ struct xfsstats { __uint32_t xs_attr_set; __uint32_t xs_attr_remove; __uint32_t xs_attr_list; -# define XFSSTAT_END_QUOTA_OPS (XFSSTAT_END_ATTRIBUTE_OPS+8) - __uint32_t xs_qm_dqreclaims; - __uint32_t xs_qm_dqreclaim_misses; - __uint32_t xs_qm_dquot_dups; - __uint32_t xs_qm_dqcachemisses; - __uint32_t xs_qm_dqcachehits; - __uint32_t xs_qm_dqwants; - __uint32_t xs_qm_dqshake_reclaims; - __uint32_t xs_qm_dqinact_reclaims; -# define XFSSTAT_END_INODE_CLUSTER (XFSSTAT_END_QUOTA_OPS+3) +# define XFSSTAT_END_INODE_CLUSTER (XFSSTAT_END_ATTRIBUTE_OPS+3) __uint32_t xs_iflush_count; __uint32_t xs_icluster_flushcnt; __uint32_t xs_icluster_flushinode; diff --git a/fs/xfs/linux/xfs_super.c b/fs/xfs/linux/xfs_super.c index 58d5aea9bd2a..161c8f64b4c2 100644 --- a/fs/xfs/linux/xfs_super.c +++ b/fs/xfs/linux/xfs_super.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -31,107 +31,68 @@ */ #include <xfs.h> -#include <linux/bitops.h> #include <linux/blkdev.h> #include <linux/namei.h> -#include <linux/pagemap.h> -#include <linux/major.h> #include <linux/init.h> -#include <linux/ctype.h> -#include <linux/seq_file.h> #include <linux/mount.h> #include "xfs_version.h" -/* xfs_vfs[ops].c */ -extern int xfs_init(void); -extern void xfs_cleanup(void); - -/* For kernels which have the s_maxbytes field - set it */ -#ifdef MAX_NON_LFS -# define set_max_bytes(sb) ((sb)->s_maxbytes = XFS_MAX_FILE_OFFSET) -#else -# define set_max_bytes(sb) do { } while (0) -#endif - -#ifdef CONFIG_XFS_POSIX_ACL -# define set_posix_acl(sb) ((sb)->s_flags |= MS_POSIXACL) -#else -# define set_posix_acl(sb) do { } while (0) -#endif - -#ifdef CONFIG_XFS_QUOTA -STATIC struct quotactl_ops linvfs_qops = { - .get_xstate = linvfs_getxstate, - .set_xstate = linvfs_setxstate, - .get_xquota = linvfs_getxquota, - .set_xquota = linvfs_setxquota, -}; -# define set_quota_ops(sb) ((sb)->s_qcop = &linvfs_qops) -#else -# define set_quota_ops(sb) do { } while (0) -#endif - -#ifdef CONFIG_XFS_DMAPI -int dmapi_init(void); -void dmapi_uninit(void); -#else -#define dmapi_init() -#define dmapi_uninit() -#endif - +STATIC struct quotactl_ops linvfs_qops; STATIC struct super_operations linvfs_sops; STATIC struct export_operations linvfs_export_ops; +STATIC kmem_cache_t * linvfs_inode_cachep; #define MNTOPT_LOGBUFS "logbufs" /* number of XFS log buffers */ -#define MNTOPT_LOGBSIZE "logbsize" /* size of XFS log buffers */ +#define MNTOPT_LOGBSIZE "logbsize" /* size of XFS log buffers */ #define MNTOPT_LOGDEV "logdev" /* log device */ #define MNTOPT_RTDEV "rtdev" /* realtime I/O device */ -#define MNTOPT_DMAPI "dmapi" /* DMI enabled (DMAPI / XDSM) */ -#define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */ #define MNTOPT_BIOSIZE "biosize" /* log2 of preferred buffered io size */ #define MNTOPT_WSYNC "wsync" /* safe-mode nfs compatible mount */ #define MNTOPT_INO64 "ino64" /* force inodes into 64-bit range */ #define MNTOPT_NOALIGN "noalign" /* turn off stripe alignment */ #define MNTOPT_SUNIT "sunit" /* data volume stripe unit */ #define MNTOPT_SWIDTH "swidth" /* data volume stripe width */ -#define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */ -#define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */ -#define MNTOPT_QUOTA "quota" /* disk quotas */ -#define MNTOPT_NOQUOTA "noquota" /* no quotas */ -#define MNTOPT_UQUOTA "usrquota" /* user quota enabled */ -#define MNTOPT_GQUOTA "grpquota" /* group quota enabled */ -#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */ -#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */ -#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */ -#define MNTOPT_NOUUID "nouuid" /* Ignore FS uuid */ -#define MNTOPT_NOLOGFLUSH "nologflush" /* Don't use hard flushes in - log writing */ +#define MNTOPT_NOUUID "nouuid" /* ignore filesystem UUID */ #define MNTOPT_MTPT "mtpt" /* filesystem mount point */ +#define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */ +#define MNTOPT_NOLOGFLUSH "nologflush" /* don't hard flush on log writes */ +#define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */ -STATIC int +STATIC struct xfs_mount_args * +args_allocate( + struct super_block *sb) +{ + struct xfs_mount_args *args; + + args = kmem_zalloc(sizeof(struct xfs_mount_args), KM_SLEEP); + args->logbufs = args->logbufsize = -1; + strncpy(args->fsname, sb->s_id, MAXNAMELEN); + + /* Copy the already-parsed mount(2) flags we're interested in */ + if (sb->s_flags & MS_NOATIME) + args->flags |= XFSMNT_NOATIME; + + /* Default to 32 bit inodes on Linux all the time */ + args->flags |= XFSMNT_32BITINODES; + + return args; +} + +int xfs_parseargs( + struct bhv_desc *bhv, char *options, - int flags, - struct xfs_mount_args *args) + struct xfs_mount_args *args, + int update) { + struct vfs *vfsp = bhvtovfs(bhv); char *this_char, *value, *eov; int dsunit, dswidth, vol_dsunit, vol_dswidth; - int logbufs, logbufsize; int iosize; - /* Default to 32 bit inodes on linux all the time */ - args->flags |= XFSMNT_32BITINODES; - - /* Copy the already-parsed mount(2) flags we're interested in */ - if (flags & MS_NOATIME) - args->flags |= XFSMNT_NOATIME; - - if (!options) { - args->logbufs = args->logbufsize = -1; + if (!options) return 0; - } - logbufs = logbufsize = -1; iosize = dsunit = dswidth = vol_dsunit = vol_dswidth = 0; while ((this_char = strsep(&options, ",")) != NULL) { @@ -146,22 +107,23 @@ xfs_parseargs( MNTOPT_LOGBUFS); return -EINVAL; } - logbufs = simple_strtoul(value, &eov, 10); + args->logbufs = simple_strtoul(value, &eov, 10); } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { - int in_kilobytes = 0; + int last, in_kilobytes = 0; if (!value || !*value) { printk("XFS: %s option requires an argument\n", MNTOPT_LOGBSIZE); return -EINVAL; } - if (toupper(value[strlen(value)-1]) == 'K') { + last = strlen(value) - 1; + if (value[last] == 'K' || value[last] == 'k') { in_kilobytes = 1; - value[strlen(value)-1] = '\0'; + value[last] = '\0'; } - logbufsize = simple_strtoul(value, &eov, 10); + args->logbufsize = simple_strtoul(value, &eov, 10); if (in_kilobytes) - logbufsize = logbufsize * 1024; + args->logbufsize <<= 10; } else if (!strcmp(this_char, MNTOPT_LOGDEV)) { if (!value || !*value) { printk("XFS: %s option requires an argument\n", @@ -176,17 +138,6 @@ xfs_parseargs( return -EINVAL; } strncpy(args->mtpt, value, MAXNAMELEN); -#if CONFIG_XFS_DMAPI - } else if (!strcmp(this_char, MNTOPT_DMAPI)) { - args->flags |= XFSMNT_DMAPI; - } else if (!strcmp(this_char, MNTOPT_XDSM)) { - args->flags |= XFSMNT_DMAPI; -#else - } else if (!strcmp(this_char, MNTOPT_DMAPI) || - !strcmp(this_char, MNTOPT_XDSM)) { - printk("XFS: this kernel does not support dmapi/xdsm.\n"); - return -EINVAL; -#endif } else if (!strcmp(this_char, MNTOPT_RTDEV)) { if (!value || !*value) { printk("XFS: %s option requires an argument\n", @@ -210,28 +161,12 @@ xfs_parseargs( } else if (!strcmp(this_char, MNTOPT_NORECOVERY)) { args->flags |= XFSMNT_NORECOVERY; } else if (!strcmp(this_char, MNTOPT_INO64)) { -#ifdef XFS_BIG_FILESYSTEMS args->flags |= XFSMNT_INO64; -#else +#ifndef XFS_BIG_FILESYSTEMS printk("XFS: %s option not allowed on this system\n", MNTOPT_INO64); return -EINVAL; #endif - } else if (!strcmp(this_char, MNTOPT_UQUOTA)) { - args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF; - } else if (!strcmp(this_char, MNTOPT_QUOTA)) { - args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF; - } else if (!strcmp(this_char, MNTOPT_UQUOTANOENF)) { - args->flags |= XFSMNT_UQUOTA; - args->flags &= ~XFSMNT_UQUOTAENF; - } else if (!strcmp(this_char, MNTOPT_QUOTANOENF)) { - args->flags |= XFSMNT_UQUOTA; - args->flags &= ~XFSMNT_UQUOTAENF; - } else if (!strcmp(this_char, MNTOPT_GQUOTA)) { - args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF; - } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) { - args->flags |= XFSMNT_GQUOTA; - args->flags &= ~XFSMNT_GQUOTAENF; } else if (!strcmp(this_char, MNTOPT_NOALIGN)) { args->flags |= XFSMNT_NOALIGN; } else if (!strcmp(this_char, MNTOPT_SUNIT)) { @@ -264,7 +199,7 @@ printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n"); } if (args->flags & XFSMNT_NORECOVERY) { - if ((flags & MS_RDONLY) == 0) { + if ((vfsp->vfs_flag & VFS_RDONLY) == 0) { printk("XFS: no-recovery mounts must be read-only.\n"); return -EINVAL; } @@ -292,22 +227,21 @@ printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n"); if (dsunit) { args->sunit = dsunit; args->flags |= XFSMNT_RETERR; - } else + } else { args->sunit = vol_dsunit; + } dswidth ? (args->swidth = dswidth) : (args->swidth = vol_dswidth); - } else + } else { args->sunit = args->swidth = 0; - - args->logbufs = logbufs; - args->logbufsize = logbufsize; + } return 0; } -STATIC int +int xfs_showargs( - struct vfs *vfsp, + struct bhv_desc *bhv, struct seq_file *m) { static struct proc_xfs_info { @@ -322,7 +256,7 @@ xfs_showargs( { 0, NULL } }; struct proc_xfs_info *xfs_infop; - struct xfs_mount *mp = XFS_BHVTOM(vfsp->vfs_fbhv); + struct xfs_mount *mp = XFS_BHVTOM(bhv); char b[BDEVNAME_SIZE]; for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) { @@ -330,18 +264,6 @@ xfs_showargs( seq_puts(m, xfs_infop->str); } - if (mp->m_qflags & XFS_UQUOTA_ACCT) { - (mp->m_qflags & XFS_UQUOTA_ENFD) ? - seq_puts(m, "," MNTOPT_UQUOTA) : - seq_puts(m, "," MNTOPT_UQUOTANOENF); - } - - if (mp->m_qflags & XFS_GQUOTA_ACCT) { - (mp->m_qflags & XFS_GQUOTA_ENFD) ? - seq_puts(m, "," MNTOPT_GQUOTA) : - seq_puts(m, "," MNTOPT_GQUOTANOENF); - } - if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE) seq_printf(m, "," MNTOPT_BIOSIZE "=%d", mp->m_writeio_log); @@ -368,9 +290,6 @@ xfs_showargs( seq_printf(m, "," MNTOPT_SWIDTH "=%d", (int)XFS_FSB_TO_BB(mp, mp->m_swidth)); - if (vfsp->vfs_flag & VFS_DMI) - seq_puts(m, "," MNTOPT_DMAPI); - return 0; } @@ -402,21 +321,21 @@ xfs_set_inodeops( STATIC __inline__ void xfs_revalidate_inode( - xfs_mount_t *mp, - vnode_t *vp, - xfs_inode_t *ip) + xfs_mount_t *mp, + vnode_t *vp, + xfs_inode_t *ip) { - struct inode *inode = LINVFS_GET_IP(vp); + struct inode *inode = LINVFS_GET_IP(vp); inode->i_mode = (ip->i_d.di_mode & MODEMASK) | VTTOIF(vp->v_type); inode->i_nlink = ip->i_d.di_nlink; inode->i_uid = ip->i_d.di_uid; inode->i_gid = ip->i_d.di_gid; if (((1 << vp->v_type) & ((1<<VBLK) | (1<<VCHR))) == 0) { - inode->i_rdev = NODEV; + inode->i_rdev = NODEV; } else { xfs_dev_t dev = ip->i_df.if_u2.if_rdev; - inode->i_rdev = XFS_DEV_TO_KDEVT(dev); + inode->i_rdev = XFS_DEV_TO_KDEVT(dev); } inode->i_blksize = PAGE_CACHE_SIZE; inode->i_generation = ip->i_d.di_gen; @@ -435,23 +354,24 @@ xfs_revalidate_inode( void xfs_initialize_vnode( - bhv_desc_t *bdp, - vnode_t *vp, - bhv_desc_t *inode_bhv, - int unlock) + bhv_desc_t *bdp, + vnode_t *vp, + bhv_desc_t *inode_bhv, + int unlock) { - xfs_inode_t *ip = XFS_BHVTOI(inode_bhv); - struct inode *inode = LINVFS_GET_IP(vp); + xfs_inode_t *ip = XFS_BHVTOI(inode_bhv); + struct inode *inode = LINVFS_GET_IP(vp); - if (vp->v_fbhv == NULL) { + if (!inode_bhv->bd_vobj) { vp->v_vfsp = bhvtovfs(bdp); - bhv_desc_init(&(ip->i_bhv_desc), ip, vp, &xfs_vnodeops); - bhv_insert_initial(VN_BHV_HEAD(vp), &(ip->i_bhv_desc)); + bhv_desc_init(inode_bhv, ip, vp, &xfs_vnodeops); + bhv_insert(VN_BHV_HEAD(vp), inode_bhv); } vp->v_type = IFTOVT(ip->i_d.di_mode); + /* Have we been called during the new inode create process, - * in which case we are too early to fill in the linux inode. + * in which case we are too early to fill in the Linux inode. */ if (vp->v_type == VNON) return; @@ -497,7 +417,7 @@ xfs_free_buftarg( xfs_buftarg_t *btp) { pagebuf_delwri_flush(btp, PBDF_WAIT, NULL); - kfree(btp); + kmem_free(btp, sizeof(*btp)); } void @@ -548,8 +468,6 @@ xfs_alloc_buftarg( return btp; } -STATIC kmem_cache_t * linvfs_inode_cachep; - STATIC __inline__ unsigned int gfp_mask(void) { /* If we're not in a transaction, FS activity is ok */ @@ -557,7 +475,6 @@ STATIC __inline__ unsigned int gfp_mask(void) return GFP_KERNEL; } - STATIC struct inode * linvfs_alloc_inode( struct super_block *sb) @@ -606,119 +523,7 @@ STATIC void destroy_inodecache( void ) { if (kmem_cache_destroy(linvfs_inode_cachep)) - printk(KERN_INFO - "linvfs_inode_cache: not all structures were freed\n"); -} - -static int -linvfs_fill_super( - struct super_block *sb, - void *data, - int silent) -{ - vfs_t *vfsp; - vfsops_t *vfsops; - vnode_t *rootvp; - struct inode *ip; - struct xfs_mount_args *args; - struct statfs statvfs; - int error = EINVAL; - - args = kmalloc(sizeof(struct xfs_mount_args), GFP_KERNEL); - if (!args) - return -EINVAL; - memset(args, 0, sizeof(struct xfs_mount_args)); - args->slcount = args->stimeout = args->ctimeout = -1; - strncpy(args->fsname, sb->s_id, MAXNAMELEN); - if (xfs_parseargs((char *)data, sb->s_flags, args)) - goto out_null; - - /* Kludge in XFS until we have other VFS/VNODE FSs */ - vfsops = &xfs_vfsops; - - /* Set up the vfs_t structure */ - vfsp = vfs_allocate(); - if (!vfsp) { - error = ENOMEM; - goto out_null; - } - - if (sb->s_flags & MS_RDONLY) - vfsp->vfs_flag |= VFS_RDONLY; - - vfsp->vfs_super = sb; - set_max_bytes(sb); - set_quota_ops(sb); - sb->s_op = &linvfs_sops; - sb->s_export_op = &linvfs_export_ops; - - sb_min_blocksize(sb, BBSIZE); - - LINVFS_SET_VFS(sb, vfsp); - - VFSOPS_MOUNT(vfsops, vfsp, args, NULL, error); - if (error) - goto fail_vfsop; - - VFS_STATVFS(vfsp, &statvfs, NULL, error); - if (error) - goto fail_unmount; - - sb->s_magic = XFS_SB_MAGIC; - sb->s_dirt = 1; - sb->s_blocksize = statvfs.f_bsize; - sb->s_blocksize_bits = ffs(statvfs.f_bsize) - 1; - set_posix_acl(sb); - - VFS_ROOT(vfsp, &rootvp, error); - if (error) - goto fail_unmount; - - ip = LINVFS_GET_IP(rootvp); - - sb->s_root = d_alloc_root(ip); - if (!sb->s_root) - goto fail_vnrele; - if (is_bad_inode(sb->s_root->d_inode)) - goto fail_vnrele; - - /* Don't set the VFS_DMI flag until here because we don't want - * to send events while replaying the log. - */ - if (args->flags & XFSMNT_DMAPI) { - vfsp->vfs_flag |= VFS_DMI; - VFSOPS_DMAPI_MOUNT(vfsops, vfsp, args->mtpt, args->fsname, - error); - - if (error) { - if (atomic_read(&sb->s_active) == 1) - vfsp->vfs_flag &= ~VFS_DMI; - goto fail_vnrele; - } - } - - vn_trace_exit(rootvp, __FUNCTION__, (inst_t *)__return_address); - - kfree(args); - return 0; - -fail_vnrele: - if (sb->s_root) { - dput(sb->s_root); - sb->s_root = NULL; - } else { - VN_RELE(rootvp); - } - -fail_unmount: - VFS_UNMOUNT(vfsp, 0, NULL, error); - -fail_vfsop: - vfs_deallocate(vfsp); - -out_null: - kfree(args); - return -error; + printk(KERN_WARNING "%s: cache still in use!\n", __FUNCTION__); } /* @@ -789,8 +594,7 @@ linvfs_write_super( sb->s_dirt = 0; if (sb->s_flags & MS_RDONLY) return; - VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, - NULL, error); + VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error); } STATIC int @@ -811,30 +615,21 @@ linvfs_remount( int *flags, char *options) { - struct xfs_mount_args *args; - vfs_t *vfsp; - xfs_mount_t *mp; - int error = 0; - - vfsp = LINVFS_GET_VFS(sb); - mp = XFS_BHVTOM(vfsp->vfs_fbhv); + vfs_t *vfsp = LINVFS_GET_VFS(sb); + xfs_mount_t *mp = XFS_VFSTOM(vfsp); + struct xfs_mount_args *args = args_allocate(sb); + int error; - args = kmalloc(sizeof(struct xfs_mount_args), GFP_KERNEL); - if (!args) - return -ENOMEM; - memset(args, 0, sizeof(struct xfs_mount_args)); - args->slcount = args->stimeout = args->ctimeout = -1; - if (xfs_parseargs(options, *flags, args)) { - error = -EINVAL; + VFS_PARSEARGS(vfsp, options, args, 1, error); + if (error) goto out; - } if (args->flags & XFSMNT_NOATIME) mp->m_flags |= XFS_MOUNT_NOATIME; else mp->m_flags &= ~XFS_MOUNT_NOATIME; - set_posix_acl(sb); + set_posix_acl_flag(sb); linvfs_write_super(sb); if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) @@ -842,14 +637,14 @@ linvfs_remount( if (*flags & MS_RDONLY) { sb->s_flags |= MS_RDONLY; - XFS_log_write_unmount_ro(vfsp->vfs_fbhv); + XFS_log_write_unmount_ro(&mp->m_bhv); vfsp->vfs_flag |= VFS_RDONLY; } else { vfsp->vfs_flag &= ~VFS_RDONLY; } out: - kfree(args); + kmem_free(args, sizeof(*args)); return error; } @@ -950,6 +745,151 @@ linvfs_get_dentry( return result; } +STATIC int +linvfs_show_options( + struct seq_file *m, + struct vfsmount *mnt) +{ + struct vfs *vfsp = LINVFS_GET_VFS(mnt->mnt_sb); + int error; + + VFS_SHOWARGS(vfsp, m, error); + return error; +} + +STATIC int +linvfs_getxstate( + struct super_block *sb, + struct fs_quota_stat *fqs) +{ + struct vfs *vfsp = LINVFS_GET_VFS(sb); + int error; + + VFS_QUOTACTL(vfsp, Q_XGETQSTAT, 0, (caddr_t)fqs, error); + return -error; +} + +STATIC int +linvfs_setxstate( + struct super_block *sb, + unsigned int flags, + int op) +{ + struct vfs *vfsp = LINVFS_GET_VFS(sb); + int error; + + VFS_QUOTACTL(vfsp, op, 0, (caddr_t)&flags, error); + return -error; +} + +STATIC int +linvfs_getxquota( + struct super_block *sb, + int type, + qid_t id, + struct fs_disk_quota *fdq) +{ + struct vfs *vfsp = LINVFS_GET_VFS(sb); + int error, getmode; + + getmode = (type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETQUOTA; + VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error); + return -error; +} + +STATIC int +linvfs_setxquota( + struct super_block *sb, + int type, + qid_t id, + struct fs_disk_quota *fdq) +{ + struct vfs *vfsp = LINVFS_GET_VFS(sb); + int error, setmode; + + setmode = (type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETQLIM; + VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error); + return -error; +} + +STATIC int +linvfs_fill_super( + struct super_block *sb, + void *data, + int silent) +{ + vnode_t *rootvp; + struct vfs *vfsp = vfs_allocate(); + struct xfs_mount_args *args = args_allocate(sb); + struct statfs statvfs; + int error; + + vfsp->vfs_super = sb; + LINVFS_SET_VFS(sb, vfsp); + if (sb->s_flags & MS_RDONLY) + vfsp->vfs_flag |= VFS_RDONLY; + bhv_insert_all_vfsops(vfsp); + + VFS_PARSEARGS(vfsp, (char *)data, args, 0, error); + if (error) { + bhv_remove_all_vfsops(vfsp, 1); + goto fail_vfsop; + } + + sb_min_blocksize(sb, BBSIZE); + sb->s_maxbytes = XFS_MAX_FILE_OFFSET; + sb->s_export_op = &linvfs_export_ops; + sb->s_qcop = &linvfs_qops; + sb->s_op = &linvfs_sops; + + VFS_MOUNT(vfsp, args, NULL, error); + if (error) { + bhv_remove_all_vfsops(vfsp, 1); + goto fail_vfsop; + } + + VFS_STATVFS(vfsp, &statvfs, NULL, error); + if (error) + goto fail_unmount; + + sb->s_dirt = 1; + sb->s_magic = XFS_SB_MAGIC; + sb->s_blocksize = statvfs.f_bsize; + sb->s_blocksize_bits = ffs(statvfs.f_bsize) - 1; + set_posix_acl_flag(sb); + + VFS_ROOT(vfsp, &rootvp, error); + if (error) + goto fail_unmount; + + sb->s_root = d_alloc_root(LINVFS_GET_IP(rootvp)); + if (!sb->s_root) + goto fail_vnrele; + if (is_bad_inode(sb->s_root->d_inode)) + goto fail_vnrele; + + vn_trace_exit(rootvp, __FUNCTION__, (inst_t *)__return_address); + + kmem_free(args, sizeof(*args)); + return 0; + +fail_vnrele: + if (sb->s_root) { + dput(sb->s_root); + sb->s_root = NULL; + } else { + VN_RELE(rootvp); + } + +fail_unmount: + VFS_UNMOUNT(vfsp, 0, NULL, error); + +fail_vfsop: + vfs_deallocate(vfsp); + kmem_free(args, sizeof(*args)); + return -error; +} + STATIC struct super_block * linvfs_get_sb( struct file_system_type *fs_type, @@ -960,15 +900,6 @@ linvfs_get_sb( return get_sb_bdev(fs_type, flags, dev_name, data, linvfs_fill_super); } -STATIC int -linvfs_show_options( - struct seq_file *m, - struct vfsmount *mnt) -{ - vfs_t *vfsp = LINVFS_GET_VFS(mnt->mnt_sb); - - return xfs_showargs(vfsp, m); -} STATIC struct export_operations linvfs_export_ops = { .get_parent = linvfs_get_parent, @@ -989,6 +920,13 @@ STATIC struct super_operations linvfs_sops = { .show_options = linvfs_show_options, }; +STATIC struct quotactl_ops linvfs_qops = { + .get_xstate = linvfs_getxstate, + .set_xstate = linvfs_setxstate, + .get_xquota = linvfs_getxquota, + .set_xquota = linvfs_setxquota, +}; + STATIC struct file_system_type xfs_fs_type = { .owner = THIS_MODULE, .name = "xfs", @@ -997,6 +935,7 @@ STATIC struct file_system_type xfs_fs_type = { .fs_flags = FS_REQUIRES_DEV, }; + STATIC int __init init_xfs_fs( void ) { @@ -1008,37 +947,44 @@ init_xfs_fs( void ) printk(message); - error = init_inodecache(); - if (error < 0) - return error; - si_meminfo(&si); xfs_physmem = si.totalram; + error = init_inodecache(); + if (error < 0) + goto undo_inodecache; + error = pagebuf_init(); if (error < 0) - goto out; + goto undo_pagebuf; vn_init(); xfs_init(); - dmapi_init(); + vfs_initdmapi(); + vfs_initquota(); error = register_filesystem(&xfs_fs_type); if (error) - goto out; + goto undo_register; return 0; -out: +undo_register: + pagebuf_terminate(); + +undo_pagebuf: destroy_inodecache(); + +undo_inodecache: return error; } STATIC void __exit exit_xfs_fs( void ) { - dmapi_uninit(); - xfs_cleanup(); unregister_filesystem(&xfs_fs_type); + xfs_cleanup(); + vfs_exitquota(); + vfs_exitdmapi(); pagebuf_terminate(); destroy_inodecache(); } @@ -1047,5 +993,6 @@ module_init(init_xfs_fs); module_exit(exit_xfs_fs); MODULE_AUTHOR("SGI <sgi.com>"); -MODULE_DESCRIPTION("SGI XFS " XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled"); +MODULE_DESCRIPTION( + "SGI XFS " XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled"); MODULE_LICENSE("GPL"); diff --git a/fs/xfs/linux/xfs_super.h b/fs/xfs/linux/xfs_super.h index f0b2372d008b..72bedd79a0ef 100644 --- a/fs/xfs/linux/xfs_super.h +++ b/fs/xfs/linux/xfs_super.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -32,28 +32,38 @@ #ifndef __XFS_SUPER_H__ #define __XFS_SUPER_H__ -#ifdef CONFIG_XFS_POSIX_ACL -# define XFS_ACL_STRING "ACLs, " +#ifdef CONFIG_XFS_DMAPI +# define vfs_insertdmapi(vfs) vfs_insertops(vfsp, &xfs_dmops) +# define vfs_initdmapi() dmapi_init() +# define vfs_exitdmapi() dmapi_uninit() #else -# define XFS_ACL_STRING +# define vfs_insertdmapi(vfs) do { } while (0) +# define vfs_initdmapi() do { } while (0) +# define vfs_exitdmapi() do { } while (0) #endif -#ifdef CONFIG_XFS_DMAPI -# define XFS_DMAPI_STRING "DMAPI, " +#ifdef CONFIG_XFS_QUOTA +# define vfs_insertquota(vfs) vfs_insertops(vfsp, &xfs_qmops) +# define vfs_initquota() xfs_qm_init() +# define vfs_exitquota() xfs_qm_exit() #else -# define XFS_DMAPI_STRING +# define vfs_insertquota(vfs) do { } while (0) +# define vfs_initquota() do { } while (0) +# define vfs_exitquota() do { } while (0) #endif -#ifdef CONFIG_XFS_QUOTA -# define XFS_QUOTA_STRING "quota, " +#ifdef CONFIG_XFS_POSIX_ACL +# define XFS_ACL_STRING "ACLs, " +# define set_posix_acl_flag(sb) ((sb)->s_flags |= MS_POSIXACL) #else -# define XFS_QUOTA_STRING +# define XFS_ACL_STRING +# define set_posix_acl_flag(sb) do { } while (0) #endif #ifdef CONFIG_XFS_RT -# define XFS_RT_STRING "realtime, " +# define XFS_REALTIME_STRING "realtime, " #else -# define XFS_RT_STRING +# define XFS_REALTIME_STRING #endif #ifdef CONFIG_XFS_VNODE_TRACING @@ -68,9 +78,9 @@ # define XFS_DBG_STRING "no debug" #endif -#define XFS_BUILD_OPTIONS XFS_ACL_STRING XFS_DMAPI_STRING \ - XFS_RT_STRING \ - XFS_QUOTA_STRING XFS_VNTRACE_STRING \ +#define XFS_BUILD_OPTIONS XFS_ACL_STRING \ + XFS_REALTIME_STRING \ + XFS_VNTRACE_STRING \ XFS_DBG_STRING /* DBG must be last */ #define LINVFS_GET_VFS(s) \ @@ -82,6 +92,8 @@ struct xfs_mount; struct pb_target; struct block_device; +extern int xfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int); +extern int xfs_showargs(bhv_desc_t *, struct seq_file *); extern void xfs_initialize_vnode(bhv_desc_t *, vnode_t *, bhv_desc_t *, int); extern int xfs_blkdev_get(struct xfs_mount *, const char *, diff --git a/fs/xfs/linux/xfs_vfs.c b/fs/xfs/linux/xfs_vfs.c new file mode 100644 index 000000000000..17e6988bc7f8 --- /dev/null +++ b/fs/xfs/linux/xfs_vfs.c @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU 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. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +#include <xfs.h> + +int +vfs_mount( + struct bhv_desc *bdp, + struct xfs_mount_args *args, + struct cred *cr) +{ + struct bhv_desc *next = bdp; + + ASSERT(next); + while (! (bhvtovfsops(next))->vfs_mount) + next = BHV_NEXT(next); + return ((*bhvtovfsops(next)->vfs_mount)(next, args, cr)); +} + +int +vfs_parseargs( + struct bhv_desc *bdp, + char *s, + struct xfs_mount_args *args, + int f) +{ + struct bhv_desc *next = bdp; + + ASSERT(next); + while (! (bhvtovfsops(next))->vfs_parseargs) + next = BHV_NEXT(next); + return ((*bhvtovfsops(next)->vfs_parseargs)(next, s, args, f)); +} + +int +vfs_showargs( + struct bhv_desc *bdp, + struct seq_file *m) +{ + struct bhv_desc *next = bdp; + + ASSERT(next); + while (! (bhvtovfsops(next))->vfs_showargs) + next = BHV_NEXT(next); + return ((*bhvtovfsops(next)->vfs_showargs)(next, m)); +} + +int +vfs_unmount( + struct bhv_desc *bdp, + int fl, + struct cred *cr) +{ + struct bhv_desc *next = bdp; + + ASSERT(next); + while (! (bhvtovfsops(next))->vfs_unmount) + next = BHV_NEXT(next); + return ((*bhvtovfsops(next)->vfs_unmount)(next, fl, cr)); +} + +int +vfs_root( + struct bhv_desc *bdp, + struct vnode **vpp) +{ + struct bhv_desc *next = bdp; + + ASSERT(next); + while (! (bhvtovfsops(next))->vfs_root) + next = BHV_NEXT(next); + return ((*bhvtovfsops(next)->vfs_root)(next, vpp)); +} + +int +vfs_statvfs( + struct bhv_desc *bdp, + struct statfs *sp, + struct vnode *vp) +{ + struct bhv_desc *next = bdp; + + ASSERT(next); + while (! (bhvtovfsops(next))->vfs_statvfs) + next = BHV_NEXT(next); + return ((*bhvtovfsops(next)->vfs_statvfs)(next, sp, vp)); +} + +int +vfs_sync( + struct bhv_desc *bdp, + int fl, + struct cred *cr) +{ + struct bhv_desc *next = bdp; + + ASSERT(next); + while (! (bhvtovfsops(next))->vfs_sync) + next = BHV_NEXT(next); + return ((*bhvtovfsops(next)->vfs_sync)(next, fl, cr)); +} + +int +vfs_vget( + struct bhv_desc *bdp, + struct vnode **vpp, + struct fid *fidp) +{ + struct bhv_desc *next = bdp; + + ASSERT(next); + while (! (bhvtovfsops(next))->vfs_vget) + next = BHV_NEXT(next); + return ((*bhvtovfsops(next)->vfs_vget)(next, vpp, fidp)); +} + +int +vfs_dmapiops( + struct bhv_desc *bdp, + caddr_t addr) +{ + struct bhv_desc *next = bdp; + + ASSERT(next); + while (! (bhvtovfsops(next))->vfs_dmapiops) + next = BHV_NEXT(next); + return ((*bhvtovfsops(next)->vfs_dmapiops)(next, addr)); +} + +int +vfs_quotactl( + struct bhv_desc *bdp, + int cmd, + int id, + caddr_t addr) +{ + struct bhv_desc *next = bdp; + + ASSERT(next); + while (! (bhvtovfsops(next))->vfs_quotactl) + next = BHV_NEXT(next); + return ((*bhvtovfsops(next)->vfs_quotactl)(next, cmd, id, addr)); +} + +void +vfs_init_vnode( + struct bhv_desc *bdp, + struct vnode *vp, + struct bhv_desc *bp, + int unlock) +{ + struct bhv_desc *next = bdp; + + ASSERT(next); + while (! (bhvtovfsops(next))->vfs_init_vnode) + next = BHV_NEXT(next); + ((*bhvtovfsops(next)->vfs_init_vnode)(next, vp, bp, unlock)); +} + +void +vfs_force_shutdown( + struct bhv_desc *bdp, + int fl, + char *file, + int line) +{ + struct bhv_desc *next = bdp; + + ASSERT(next); + while (! (bhvtovfsops(next))->vfs_force_shutdown) + next = BHV_NEXT(next); + ((*bhvtovfsops(next)->vfs_force_shutdown)(next, fl, file, line)); +} + +vfs_t * +vfs_allocate( void ) +{ + struct vfs *vfsp; + + vfsp = kmem_zalloc(sizeof(vfs_t), KM_SLEEP); + bhv_head_init(VFS_BHVHEAD(vfsp), "vfs"); + return vfsp; +} + +void +vfs_deallocate( + struct vfs *vfsp) +{ + bhv_head_destroy(VFS_BHVHEAD(vfsp)); + kmem_free(vfsp, sizeof(vfs_t)); +} + +void +vfs_insertops( + struct vfs *vfsp, + struct bhv_vfsops *vfsops) +{ + struct bhv_desc *bdp; + + bdp = kmem_alloc(sizeof(struct bhv_desc), KM_SLEEP); + bhv_desc_init(bdp, NULL, vfsp, vfsops); + bhv_insert(&vfsp->vfs_bh, bdp); +} + +void +vfs_insertbhv( + struct vfs *vfsp, + struct bhv_desc *bdp, + struct vfsops *vfsops, + void *mount) +{ + bhv_desc_init(bdp, mount, vfsp, vfsops); + bhv_insert_initial(&vfsp->vfs_bh, bdp); +} + +void +bhv_remove_vfsops( + struct vfs *vfsp, + int pos) +{ + struct bhv_desc *bhv; + + bhv = bhv_lookup_range(&vfsp->vfs_bh, pos, pos); + if (!bhv) + return; + bhv_remove(&vfsp->vfs_bh, bhv); + kmem_free(bhv, sizeof(*bhv)); +} + +void +bhv_remove_all_vfsops( + struct vfs *vfsp, + int freebase) +{ + struct xfs_mount *mp; + + bhv_remove_vfsops(vfsp, VFS_POSITION_QM); + bhv_remove_vfsops(vfsp, VFS_POSITION_DM); + if (!freebase) + return; + mp = XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfsp), &xfs_vfsops)); + VFS_REMOVEBHV(vfsp, &mp->m_bhv); + xfs_mount_free(mp, 0); +} + +void +bhv_insert_all_vfsops( + struct vfs *vfsp) +{ + struct xfs_mount *mp; + + mp = xfs_mount_init(); + vfs_insertbhv(vfsp, &mp->m_bhv, &xfs_vfsops, mp); + vfs_insertdmapi(vfsp); + vfs_insertquota(vfsp); +} diff --git a/fs/xfs/linux/xfs_vfs.h b/fs/xfs/linux/xfs_vfs.h index e2b1bfe025d9..b18e6424b67c 100644 --- a/fs/xfs/linux/xfs_vfs.h +++ b/fs/xfs/linux/xfs_vfs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -34,162 +34,154 @@ #include <linux/vfs.h> -struct statfs; -struct vnode; +struct fid; struct cred; +struct vnode; +struct statfs; +struct seq_file; struct super_block; -struct fid; -struct dm_fcntl_vector; struct xfs_mount_args; typedef struct vfs { - u_int vfs_flag; /* flags */ - fsid_t vfs_fsid; /* file system id */ - fsid_t *vfs_altfsid; /* An ID fixed for life of FS */ - bhv_head_t vfs_bh; /* head of vfs behavior chain */ - struct super_block *vfs_super; /* pointer to super block structure */ + u_int vfs_flag; /* flags */ + fsid_t vfs_fsid; /* file system ID */ + fsid_t *vfs_altfsid; /* An ID fixed for life of FS */ + bhv_head_t vfs_bh; /* head of vfs behavior chain */ + struct super_block *vfs_super; /* Linux superblock structure */ } vfs_t; -#define vfs_fbhv vfs_bh.bh_first /* 1st on vfs behavior chain */ -#define VFS_FOPS(vfsp) \ - ((vfsops_t *)((vfsp)->vfs_fbhv->bd_ops))/* ops for 1st behavior */ - - -#define bhvtovfs(bdp) ((struct vfs *)BHV_VOBJ(bdp)) -#define VFS_BHVHEAD(vfsp) (&(vfsp)->vfs_bh) - - -#define VFS_RDONLY 0x0001 /* read-only vfs */ -#define VFS_GRPID 0x0002 /* group-ID assigned from directory */ -#define VFS_DMI 0x0004 /* filesystem has the DMI enabled */ - -#define SYNC_ATTR 0x0001 /* sync attributes */ -#define SYNC_CLOSE 0x0002 /* close file system down */ -#define SYNC_DELWRI 0x0004 /* look at delayed writes */ -#define SYNC_WAIT 0x0008 /* wait for i/o to complete */ -#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */ -#define SYNC_BDFLUSH 0x0010 /* BDFLUSH is calling -- don't block */ - +#define vfs_fbhv vfs_bh.bh_first /* 1st on vfs behavior chain */ + +#define bhvtovfs(bdp) ( (struct vfs *)BHV_VOBJ(bdp) ) +#define bhvtovfsops(bdp) ( (struct vfsops *)BHV_OPS(bdp) ) +#define VFS_BHVHEAD(vfs) ( &(vfs)->vfs_bh ) +#define VFS_REMOVEBHV(vfs, bdp) ( bhv_remove(VFS_BHVHEAD(vfs), bdp) ) + +#define VFS_POSITION_BASE BHV_POSITION_BASE /* chain bottom */ +#define VFS_POSITION_TOP BHV_POSITION_TOP /* chain top */ +#define VFS_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */ + +typedef enum { + VFS_BHV_UNKNOWN, /* not specified */ + VFS_BHV_XFS, /* xfs */ + VFS_BHV_DM, /* data migration */ + VFS_BHV_QM, /* quota manager */ + VFS_BHV_IO, /* IO path */ + VFS_BHV_END /* housekeeping end-of-range */ +} vfs_bhv_t; + +#define VFS_POSITION_XFS (BHV_POSITION_BASE) +#define VFS_POSITION_DM (VFS_POSITION_BASE+10) +#define VFS_POSITION_QM (VFS_POSITION_BASE+20) +#define VFS_POSITION_IO (VFS_POSITION_BASE+30) + +#define VFS_RDONLY 0x0001 /* read-only vfs */ +#define VFS_GRPID 0x0002 /* group-ID assigned from directory */ +#define VFS_DMI 0x0004 /* filesystem has the DMI enabled */ +#define VFS_END 0x0004 /* max flag */ + +#define SYNC_ATTR 0x0001 /* sync attributes */ +#define SYNC_CLOSE 0x0002 /* close file system down */ +#define SYNC_DELWRI 0x0004 /* look at delayed writes */ +#define SYNC_WAIT 0x0008 /* wait for i/o to complete */ +#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */ +#define SYNC_BDFLUSH 0x0010 /* BDFLUSH is calling -- don't block */ + +typedef int (*vfs_mount_t)(bhv_desc_t *, + struct xfs_mount_args *, struct cred *); +typedef int (*vfs_parseargs_t)(bhv_desc_t *, char *, + struct xfs_mount_args *, int); +typedef int (*vfs_showargs_t)(bhv_desc_t *, struct seq_file *); +typedef int (*vfs_unmount_t)(bhv_desc_t *, int, struct cred *); +typedef int (*vfs_root_t)(bhv_desc_t *, struct vnode **); +typedef int (*vfs_statvfs_t)(bhv_desc_t *, struct statfs *, struct vnode *); +typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *); +typedef int (*vfs_vget_t)(bhv_desc_t *, struct vnode **, struct fid *); +typedef int (*vfs_dmapiops_t)(bhv_desc_t *, caddr_t); +typedef int (*vfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t); +typedef void (*vfs_init_vnode_t)(bhv_desc_t *, + struct vnode *, bhv_desc_t *, int); +typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int); typedef struct vfsops { - int (*vfs_mount)(struct vfs *, struct xfs_mount_args *, - struct cred *); - /* mount file system */ - int (*vfs_unmount)(bhv_desc_t *, int, struct cred *); - /* unmount file system */ - int (*vfs_root)(bhv_desc_t *, struct vnode **); - /* get root vnode */ - int (*vfs_statvfs)(bhv_desc_t *, struct statfs *, struct vnode *); - /* get file system statistics */ - int (*vfs_sync)(bhv_desc_t *, int, struct cred *); - /* flush files */ - int (*vfs_vget)(bhv_desc_t *, struct vnode **, struct fid *); - /* get vnode from fid */ - int (*vfs_dmapi_mount)(struct vfs *, char *, char *); - /* send dmapi mount event */ - int (*vfs_dmapi_fsys_vector)(bhv_desc_t *, - struct dm_fcntl_vector *); - void (*vfs_init_vnode)(bhv_desc_t *, struct vnode *, - bhv_desc_t *, int); - void (*vfs_force_shutdown)(bhv_desc_t *, - int, char *, int); + bhv_position_t vf_position; /* behavior chain position */ + vfs_mount_t vfs_mount; /* mount file system */ + vfs_parseargs_t vfs_parseargs; /* parse mount options */ + vfs_showargs_t vfs_showargs; /* unparse mount options */ + vfs_unmount_t vfs_unmount; /* unmount file system */ + vfs_root_t vfs_root; /* get root vnode */ + vfs_statvfs_t vfs_statvfs; /* file system statistics */ + vfs_sync_t vfs_sync; /* flush files */ + vfs_vget_t vfs_vget; /* get vnode from fid */ + vfs_dmapiops_t vfs_dmapiops; /* data migration */ + vfs_quotactl_t vfs_quotactl; /* disk quota */ + vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */ + vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */ } vfsops_t; -#define VFS_UNMOUNT(vfsp,f,cr, rv) \ -{ \ - rv = (*(VFS_FOPS(vfsp)->vfs_unmount))((vfsp)->vfs_fbhv, f, cr); \ -} -#define VFS_ROOT(vfsp, vpp, rv) \ -{ \ - rv = (*(VFS_FOPS(vfsp)->vfs_root))((vfsp)->vfs_fbhv, vpp); \ -} -#define VFS_STATVFS(vfsp, sp, vp, rv) \ -{ \ - rv = (*(VFS_FOPS(vfsp)->vfs_statvfs))((vfsp)->vfs_fbhv, sp, vp);\ -} -#define VFS_SYNC(vfsp, flag, cr, rv) \ -{ \ - rv = (*(VFS_FOPS(vfsp)->vfs_sync))((vfsp)->vfs_fbhv, flag, cr); \ -} -#define VFS_VGET(vfsp, vpp, fidp, rv) \ -{ \ - rv = (*(VFS_FOPS(vfsp)->vfs_vget))((vfsp)->vfs_fbhv, vpp, fidp); \ -} - -#define VFS_INIT_VNODE(vfsp, vp, bhv, unlock) \ -{ \ - (*(VFS_FOPS(vfsp)->vfs_init_vnode))((vfsp)->vfs_fbhv, vp, bhv, unlock);\ -} - -/* No behavior lock here */ -#define VFS_FORCE_SHUTDOWN(vfsp, flags) \ - (*(VFS_FOPS(vfsp)->vfs_force_shutdown))((vfsp)->vfs_fbhv, flags, __FILE__, __LINE__); - -#define VFS_DMAPI_FSYS_VECTOR(vfsp, df, rv) \ -{ \ - rv = (*(VFS_FOPS(vfsp)->vfs_dmapi_fsys_vector))((vfsp)->vfs_fbhv, df); \ -} - - -#define VFSOPS_DMAPI_MOUNT(vfs_op, vfsp, dir_name, fsname, rv) \ - rv = (*(vfs_op)->vfs_dmapi_mount)(vfsp, dir_name, fsname) -#define VFSOPS_MOUNT(vfs_op, vfsp, args, cr, rv) \ - rv = (*(vfs_op)->vfs_mount)(vfsp, args, cr) - -#define VFS_REMOVEBHV(vfsp, bdp)\ -{ \ - bhv_remove(VFS_BHVHEAD(vfsp), bdp); \ -} - -#define PVFS_UNMOUNT(bdp,f,cr, rv) \ -{ \ - rv = (*((vfsops_t *)(bdp)->bd_ops)->vfs_unmount)(bdp, f, cr); \ -} - -#define PVFS_SYNC(bdp, flag, cr, rv) \ -{ \ - rv = (*((vfsops_t *)(bdp)->bd_ops)->vfs_sync)(bdp, flag, cr); \ -} - - -static __inline vfs_t * -vfs_allocate(void) -{ - vfs_t *vfsp; - - vfsp = kmalloc(sizeof(vfs_t), GFP_KERNEL); - if (vfsp) { - memset(vfsp, 0, sizeof(vfs_t)); - bhv_head_init(VFS_BHVHEAD(vfsp), "vfs"); - } - return (vfsp); -} - -static __inline void -vfs_deallocate( - vfs_t *vfsp) -{ - bhv_head_destroy(VFS_BHVHEAD(vfsp)); - kfree(vfsp); -} +/* + * VFS's. Operates on vfs structure pointers (starts at bhv head). + */ +#define VHEAD(v) ((v)->vfs_fbhv) +#define VFS_MOUNT(v, ma,cr, rv) ((rv) = vfs_mount(VHEAD(v), ma,cr)) +#define VFS_PARSEARGS(v, o,ma,f, rv) ((rv) = vfs_parseargs(VHEAD(v), o,ma,f)) +#define VFS_SHOWARGS(v, m, rv) ((rv) = vfs_showargs(VHEAD(v), m)) +#define VFS_UNMOUNT(v, f,cr, rv) ((rv) = vfs_unmount(VHEAD(v), f,cr)) +#define VFS_ROOT(v, vpp, rv) ((rv) = vfs_root(VHEAD(v), vpp)) +#define VFS_STATVFS(v, sp,vp, rv) ((rv) = vfs_statvfs(VHEAD(v), sp,vp)) +#define VFS_SYNC(v, flag,cr, rv) ((rv) = vfs_sync(VHEAD(v), flag,cr)) +#define VFS_VGET(v, vpp,fidp, rv) ((rv) = vfs_vget(VHEAD(v), vpp,fidp)) +#define VFS_DMAPIOPS(v, p, rv) ((rv) = vfs_dmapiops(VHEAD(v), p)) +#define VFS_QUOTACTL(v, c,id,p, rv) ((rv) = vfs_quotactl(VHEAD(v), c,id,p)) +#define VFS_INIT_VNODE(v, vp,b,ul) ( vfs_init_vnode(VHEAD(v), vp,b,ul) ) +#define VFS_FORCE_SHUTDOWN(v, fl,f,l) ( vfs_force_shutdown(VHEAD(v), fl,f,l) ) /* - * Called by fs dependent VFS_MOUNT code to link the VFS base file system - * dependent behavior with the VFS virtual object. + * PVFS's. Operates on behavior descriptor pointers. */ -static __inline void -vfs_insertbhv( - vfs_t *vfsp, - bhv_desc_t *bdp, - vfsops_t *vfsops, - void *mount) -{ - /* - * Initialize behavior desc with ops and data and then - * attach it to the vfs. - */ - bhv_desc_init(bdp, mount, vfsp, vfsops); - bhv_insert_initial(&vfsp->vfs_bh, bdp); -} +#define PVFS_MOUNT(b, ma,cr, rv) ((rv) = vfs_mount(b, ma,cr)) +#define PVFS_PARSEARGS(b, o,ma,f, rv) ((rv) = vfs_parseargs(b, o,ma,f)) +#define PVFS_SHOWARGS(b, m, rv) ((rv) = vfs_showargs(b, m)) +#define PVFS_UNMOUNT(b, f,cr, rv) ((rv) = vfs_unmount(b, f,cr)) +#define PVFS_ROOT(b, vpp, rv) ((rv) = vfs_root(b, vpp)) +#define PVFS_STATVFS(b, sp,vp, rv) ((rv) = vfs_statvfs(b, sp,vp)) +#define PVFS_SYNC(b, flag,cr, rv) ((rv) = vfs_sync(b, flag,cr)) +#define PVFS_VGET(b, vpp,fidp, rv) ((rv) = vfs_vget(b, vpp,fidp)) +#define PVFS_DMAPIOPS(b, p, rv) ((rv) = vfs_dmapiops(b, p)) +#define PVFS_QUOTACTL(b, c,id,p, rv) ((rv) = vfs_quotactl(b, c,id,p)) +#define PVFS_INIT_VNODE(b, vp,b2,ul) ( vfs_init_vnode(b, vp,b2,ul) ) +#define PVFS_FORCE_SHUTDOWN(b, fl,f,l) ( vfs_force_shutdown(b, fl,f,l) ) + +extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *); +extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int); +extern int vfs_showargs(bhv_desc_t *, struct seq_file *); +extern int vfs_unmount(bhv_desc_t *, int, struct cred *); +extern int vfs_root(bhv_desc_t *, struct vnode **); +extern int vfs_statvfs(bhv_desc_t *, struct statfs *, struct vnode *); +extern int vfs_sync(bhv_desc_t *, int, struct cred *); +extern int vfs_vget(bhv_desc_t *, struct vnode **, struct fid *); +extern int vfs_dmapiops(bhv_desc_t *, caddr_t); +extern int vfs_quotactl(bhv_desc_t *, int, int, caddr_t); +extern void vfs_init_vnode(bhv_desc_t *, struct vnode *, bhv_desc_t *, int); +extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int); + +typedef struct bhv_vfsops { + struct vfsops bhv_common; + void * bhv_custom; +} bhv_vfsops_t; + +#define vfs_bhv_lookup(v, id) ( bhv_lookup_range(&(v)->vfs_bh, (id), (id)) ) +#define vfs_bhv_custom(b) ( ((bhv_vfsops_t *)BHV_OPS(b))->bhv_custom ) +#define vfs_bhv_set_custom(b,o) ( (b)->bhv_custom = (void *)(o)) +#define vfs_bhv_clr_custom(b) ( (b)->bhv_custom = NULL ) + +extern vfs_t *vfs_allocate(void); +extern void vfs_deallocate(vfs_t *); +extern void vfs_insertops(vfs_t *, bhv_vfsops_t *); +extern void vfs_insertbhv(vfs_t *, bhv_desc_t *, vfsops_t *, void *); + +extern void bhv_insert_all_vfsops(struct vfs *); +extern void bhv_remove_all_vfsops(struct vfs *, int); +extern void bhv_remove_vfsops(struct vfs *, int); #endif /* __XFS_VFS_H__ */ diff --git a/fs/xfs/linux/xfs_vnode.c b/fs/xfs/linux/xfs_vnode.c index ff78d13e750f..c976fda746bb 100644 --- a/fs/xfs/linux/xfs_vnode.c +++ b/fs/xfs/linux/xfs_vnode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,6 @@ */ #include <xfs.h> -#include <linux/pagemap.h> uint64_t vn_generation; /* vnode generation number */ @@ -73,19 +72,19 @@ vn_init(void) * Clean a vnode of filesystem-specific data and prepare it for reuse. */ STATIC int -vn_reclaim(struct vnode *vp) +vn_reclaim( + struct vnode *vp) { - int error; + int error; XFS_STATS_INC(xfsstats.vn_reclaim); - vn_trace_entry(vp, "vn_reclaim", (inst_t *)__return_address); /* * Only make the VOP_RECLAIM call if there are behaviors * to call. */ - if (vp->v_fbhv != NULL) { + if (vp->v_fbhv) { VOP_RECLAIM(vp, error); if (error) return -error; @@ -108,18 +107,19 @@ vn_reclaim(struct vnode *vp) } STATIC void -vn_wakeup(struct vnode *vp) +vn_wakeup( + struct vnode *vp) { VN_LOCK(vp); - if (vp->v_flag & VWAIT) { + if (vp->v_flag & VWAIT) sv_broadcast(vptosync(vp)); - } vp->v_flag &= ~(VRECLM|VWAIT|VMODIFIED); VN_UNLOCK(vp, 0); } int -vn_wait(struct vnode *vp) +vn_wait( + struct vnode *vp) { VN_LOCK(vp); if (vp->v_flag & (VINACT | VRECLM)) { @@ -132,7 +132,8 @@ vn_wait(struct vnode *vp) } struct vnode * -vn_initialize(struct inode *inode) +vn_initialize( + struct inode *inode) { struct vnode *vp = LINVFS_GET_VP(inode); @@ -165,7 +166,9 @@ vn_initialize(struct inode *inode) * Get a reference on a vnode. */ vnode_t * -vn_get(struct vnode *vp, vmap_t *vmap) +vn_get( + struct vnode *vp, + vmap_t *vmap) { struct inode *inode; @@ -175,7 +178,7 @@ vn_get(struct vnode *vp, vmap_t *vmap) return NULL; inode = ilookup(vmap->v_vfsp->vfs_super, vmap->v_ino); - if (inode == NULL) /* Inode not present */ + if (!inode) /* Inode not present */ return NULL; vn_trace_exit(vp, "vn_get", (inst_t *)__return_address); @@ -187,16 +190,17 @@ vn_get(struct vnode *vp, vmap_t *vmap) * Revalidate the Linux inode from the vnode. */ int -vn_revalidate(struct vnode *vp) +vn_revalidate( + struct vnode *vp) { - int error; struct inode *inode; vattr_t va; + int error; vn_trace_entry(vp, "vn_revalidate", (inst_t *)__return_address); ASSERT(vp->v_fbhv != NULL); - va.va_mask = XFS_AT_STAT|XFS_AT_GENCOUNT; + va.va_mask = XFS_AT_STAT; VOP_GETATTR(vp, &va, 0, NULL, error); if (!error) { inode = LINVFS_GET_IP(vp); @@ -206,12 +210,9 @@ vn_revalidate(struct vnode *vp) inode->i_gid = va.va_gid; inode->i_size = va.va_size; inode->i_blocks = va.va_nblocks; - inode->i_mtime.tv_sec = va.va_mtime.tv_sec; - inode->i_mtime.tv_nsec = va.va_mtime.tv_nsec; - inode->i_ctime.tv_sec = va.va_ctime.tv_sec; - inode->i_ctime.tv_nsec = va.va_ctime.tv_nsec; - inode->i_atime.tv_sec = va.va_atime.tv_sec; - inode->i_atime.tv_nsec = va.va_atime.tv_nsec; + inode->i_mtime = va.va_mtime; + inode->i_ctime = va.va_ctime; + inode->i_atime = va.va_atime; VUNMODIFY(vp); } return -error; @@ -224,7 +225,9 @@ vn_revalidate(struct vnode *vp) * get a handle (via vn_get) on the vnode (usually done via a mount/vfs lock). */ void -vn_purge(struct vnode *vp, vmap_t *vmap) +vn_purge( + struct vnode *vp, + vmap_t *vmap) { vn_trace_entry(vp, "vn_purge", (inst_t *)__return_address); @@ -284,9 +287,10 @@ again: * Add a reference to a referenced vnode. */ struct vnode * -vn_hold(struct vnode *vp) +vn_hold( + struct vnode *vp) { - struct inode *inode; + struct inode *inode; XFS_STATS_INC(xfsstats.vn_hold); @@ -302,10 +306,11 @@ vn_hold(struct vnode *vp) * Call VOP_INACTIVE on last reference. */ void -vn_rele(struct vnode *vp) +vn_rele( + struct vnode *vp) { - int vcnt; - int cache; + int vcnt; + int cache; XFS_STATS_INC(xfsstats.vn_rele); @@ -319,7 +324,7 @@ vn_rele(struct vnode *vp) * that i_count won't be decremented after we * return. */ - if (vcnt == 0) { + if (!vcnt) { /* * As soon as we turn this on, noone can find us in vn_get * until we turn off VINACT or VRECLM @@ -331,19 +336,14 @@ vn_rele(struct vnode *vp) * Do not make the VOP_INACTIVE call if there * are no behaviors attached to the vnode to call. */ - if (vp->v_fbhv != NULL) { + if (vp->v_fbhv) VOP_INACTIVE(vp, NULL, cache); - } VN_LOCK(vp); - if (vp->v_flag & VWAIT) { - if (vp->v_flag & VWAIT) { - sv_broadcast(vptosync(vp)); - } - } + if (vp->v_flag & VWAIT) + sv_broadcast(vptosync(vp)); vp->v_flag &= ~(VINACT|VWAIT|VRECLM|VMODIFIED); - } VN_UNLOCK(vp, 0); @@ -355,17 +355,16 @@ vn_rele(struct vnode *vp) * Finish the removal of a vnode. */ void -vn_remove(struct vnode *vp) +vn_remove( + struct vnode *vp) { - /* REFERENCED */ - vmap_t vmap; + vmap_t vmap; /* Make sure we don't do this to the same vnode twice */ if (!(vp->v_fbhv)) return; XFS_STATS_INC(xfsstats.vn_remove); - vn_trace_exit(vp, "vn_remove", (inst_t *)__return_address); /* diff --git a/fs/xfs/linux/xfs_vnode.h b/fs/xfs/linux/xfs_vnode.h index f8078d6771bb..5d247729c2bc 100644 --- a/fs/xfs/linux/xfs_vnode.h +++ b/fs/xfs/linux/xfs_vnode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -85,10 +85,16 @@ typedef struct vnode { typedef enum { VN_BHV_UNKNOWN, /* not specified */ VN_BHV_XFS, /* xfs */ + VN_BHV_DM, /* data migration */ + VN_BHV_QM, /* quota manager */ + VN_BHV_IO, /* IO path */ VN_BHV_END /* housekeeping end-of-range */ } vn_bhv_t; #define VNODE_POSITION_XFS (VNODE_POSITION_BASE) +#define VNODE_POSITION_DM (VNODE_POSITION_BASE+10) +#define VNODE_POSITION_QM (VNODE_POSITION_BASE+20) +#define VNODE_POSITION_IO (VNODE_POSITION_BASE+30) /* * Macros for dealing with the behavior descriptor inside of the vnode. @@ -96,7 +102,6 @@ typedef enum { #define BHV_TO_VNODE(bdp) ((vnode_t *)BHV_VOBJ(bdp)) #define BHV_TO_VNODE_NULL(bdp) ((vnode_t *)BHV_VOBJNULL(bdp)) -#define VNODE_TO_FIRST_BHV(vp) (BHV_HEAD_FIRST(&(vp)->v_bh)) #define VN_BHV_HEAD(vp) ((bhv_head_t *)(&((vp)->v_bh))) #define vn_bhv_head_init(bhp,name) bhv_head_init(bhp,name) #define vn_bhv_remove(bhp,bdp) bhv_remove(bhp,bdp) @@ -127,16 +132,6 @@ extern ushort vttoif_tab[]; #define VWAIT 0x4 /* waiting for VINACT/VRECLM to end */ #define VMODIFIED 0x8 /* XFS inode state possibly differs */ /* to the Linux inode state. */ -#define VROOT 0x100000 /* root of its file system */ -#define VNOSWAP 0x200000 /* cannot be used as virt swap device */ -#define VISSWAP 0x400000 /* vnode is part of virt swap device */ -#define VREPLICABLE 0x800000 /* Vnode can have replicated pages */ -#define VNONREPLICABLE 0x1000000 /* Vnode has writers. Don't replicate */ -#define VDOCMP 0x2000000 /* Vnode has special VOP_CMP impl. */ -#define VSHARE 0x4000000 /* vnode part of global cache */ -#define VFRLOCKS 0x8000000 /* vnode has FR locks applied */ -#define VENF_LOCKING 0x10000000 /* enf. mode FR locking in effect */ -#define VOPLOCK 0x20000000 /* oplock set on the vnode */ typedef enum vrwlock { VRWLOCK_NONE, VRWLOCK_READ, VRWLOCK_WRITE, VRWLOCK_WRITE_DIRECT, @@ -267,163 +262,92 @@ typedef struct vnodeops { */ #define _VOP_(op, vp) (*((vnodeops_t *)(vp)->v_fops)->op) -#define VOP_READ(vp,file,iov,segs,offset,cr,rv) \ -{ \ - rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,iov,segs,offset,cr); \ -} -#define VOP_WRITE(vp,file,iov,segs,offset,cr,rv) \ -{ \ - rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,cr);\ -} -#define VOP_SENDFILE(vp,f,of,cnt,act,targ,cr,rv) \ -{ \ - rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,of,cnt,act,targ,cr);\ -} +#define VOP_READ(vp,file,iov,segs,offset,cr,rv) \ + rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,iov,segs,offset,cr) +#define VOP_WRITE(vp,file,iov,segs,offset,cr,rv) \ + rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,cr) +#define VOP_SENDFILE(vp,f,off,cnt,act,targ,cr,rv) \ + rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,cnt,act,targ,cr) #define VOP_BMAP(vp,of,sz,rw,b,n,rv) \ -{ \ - rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n); \ -} + rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n) #define VOP_OPEN(vp, cr, rv) \ -{ \ - rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr); \ -} + rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr) #define VOP_GETATTR(vp, vap, f, cr, rv) \ -{ \ - rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr); \ -} + rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr) #define VOP_SETATTR(vp, vap, f, cr, rv) \ -{ \ - rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr); \ -} + rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr) #define VOP_ACCESS(vp, mode, cr, rv) \ -{ \ - rv = _VOP_(vop_access, vp)((vp)->v_fbhv, mode, cr); \ -} + rv = _VOP_(vop_access, vp)((vp)->v_fbhv, mode, cr) #define VOP_LOOKUP(vp,d,vpp,f,rdir,cr,rv) \ -{ \ - rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,d,vpp,f,rdir,cr); \ -} + rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,d,vpp,f,rdir,cr) #define VOP_CREATE(dvp,d,vap,vpp,cr,rv) \ -{ \ - rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,d,vap,vpp,cr); \ -} + rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,d,vap,vpp,cr) #define VOP_REMOVE(dvp,d,cr,rv) \ -{ \ - rv = _VOP_(vop_remove, dvp)((dvp)->v_fbhv,d,cr); \ -} + rv = _VOP_(vop_remove, dvp)((dvp)->v_fbhv,d,cr) #define VOP_LINK(tdvp,fvp,d,cr,rv) \ -{ \ - rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,d,cr); \ -} + rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,d,cr) #define VOP_RENAME(fvp,fnm,tdvp,tnm,cr,rv) \ -{ \ - rv = _VOP_(vop_rename, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,cr); \ -} + rv = _VOP_(vop_rename, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,cr) #define VOP_MKDIR(dp,d,vap,vpp,cr,rv) \ -{ \ - rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,d,vap,vpp,cr); \ -} + rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,d,vap,vpp,cr) #define VOP_RMDIR(dp,d,cr,rv) \ -{ \ - rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,d,cr); \ -} + rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,d,cr) #define VOP_READDIR(vp,uiop,cr,eofp,rv) \ -{ \ - rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp); \ -} + rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp) #define VOP_SYMLINK(dvp,d,vap,tnm,vpp,cr,rv) \ -{ \ - rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr); \ -} + rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr) #define VOP_READLINK(vp,uiop,cr,rv) \ -{ \ - rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,cr); \ -} + rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,cr) #define VOP_FSYNC(vp,f,cr,b,e,rv) \ -{ \ - rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e); \ -} + rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e) #define VOP_INACTIVE(vp, cr, rv) \ -{ \ - rv = _VOP_(vop_inactive, vp)((vp)->v_fbhv, cr); \ -} + rv = _VOP_(vop_inactive, vp)((vp)->v_fbhv, cr) #define VOP_RELEASE(vp, rv) \ -{ \ - rv = _VOP_(vop_release, vp)((vp)->v_fbhv); \ -} + rv = _VOP_(vop_release, vp)((vp)->v_fbhv) #define VOP_FID2(vp, fidp, rv) \ -{ \ - rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp); \ -} + rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp) #define VOP_RWLOCK(vp,i) \ -{ \ - (void)_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i); \ -} + (void)_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i) #define VOP_RWLOCK_TRY(vp,i) \ _VOP_(vop_rwlock, vp)((vp)->v_fbhv, i) - #define VOP_RWUNLOCK(vp,i) \ -{ \ - (void)_VOP_(vop_rwunlock, vp)((vp)->v_fbhv, i); \ -} + (void)_VOP_(vop_rwunlock, vp)((vp)->v_fbhv, i) +#define VOP_FRLOCK(vp,c,fl,flags,offset,fr,rv) \ + rv = _VOP_(vop_frlock, vp)((vp)->v_fbhv,c,fl,flags,offset,fr) #define VOP_RECLAIM(vp, rv) \ -{ \ - rv = _VOP_(vop_reclaim, vp)((vp)->v_fbhv); \ -} + rv = _VOP_(vop_reclaim, vp)((vp)->v_fbhv) #define VOP_ATTR_GET(vp, name, val, vallenp, fl, cred, rv) \ -{ \ - rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred); \ -} + rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred) #define VOP_ATTR_SET(vp, name, val, vallen, fl, cred, rv) \ -{ \ - rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred); \ -} + rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred) #define VOP_ATTR_REMOVE(vp, name, flags, cred, rv) \ -{ \ - rv = _VOP_(vop_attr_remove, vp)((vp)->v_fbhv,name,flags,cred); \ -} + rv = _VOP_(vop_attr_remove, vp)((vp)->v_fbhv,name,flags,cred) #define VOP_ATTR_LIST(vp, buf, buflen, fl, cursor, cred, rv) \ -{ \ - rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred);\ -} + rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred) #define VOP_LINK_REMOVED(vp, dvp, linkzero) \ -{ \ - (void)_VOP_(vop_link_removed, vp)((vp)->v_fbhv, dvp, linkzero); \ -} + (void)_VOP_(vop_link_removed, vp)((vp)->v_fbhv, dvp, linkzero) #define VOP_VNODE_CHANGE(vp, cmd, val) \ -{ \ - (void)_VOP_(vop_vnode_change, vp)((vp)->v_fbhv,cmd,val); \ -} + (void)_VOP_(vop_vnode_change, vp)((vp)->v_fbhv,cmd,val) /* * These are page cache functions that now go thru VOPs. * 'last' parameter is unused and left in for IRIX compatibility */ #define VOP_TOSS_PAGES(vp, first, last, fiopt) \ -{ \ - _VOP_(vop_tosspages, vp)((vp)->v_fbhv,first, last, fiopt); \ -} + _VOP_(vop_tosspages, vp)((vp)->v_fbhv,first, last, fiopt) /* * 'last' parameter is unused and left in for IRIX compatibility */ #define VOP_FLUSHINVAL_PAGES(vp, first, last, fiopt) \ -{ \ - _VOP_(vop_flushinval_pages, vp)((vp)->v_fbhv,first,last,fiopt); \ -} + _VOP_(vop_flushinval_pages, vp)((vp)->v_fbhv,first,last,fiopt) /* * 'last' parameter is unused and left in for IRIX compatibility */ #define VOP_FLUSH_PAGES(vp, first, last, flags, fiopt, rv) \ -{ \ - rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt);\ -} + rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt) #define VOP_IOCTL(vp, inode, filp, cmd, arg, rv) \ -{ \ - rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,cmd,arg); \ -} + rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,cmd,arg) #define VOP_IFLUSH(vp, flags, rv) \ -{ \ - rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags); \ -} + rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags) /* * Flags for VOP_IFLUSH call diff --git a/fs/xfs/pagebuf/page_buf.c b/fs/xfs/pagebuf/page_buf.c index 5d2e91067b79..f50803bd2570 100644 --- a/fs/xfs/pagebuf/page_buf.c +++ b/fs/xfs/pagebuf/page_buf.c @@ -1290,7 +1290,7 @@ bio_end_io_pagebuf( if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) { pb->pb_locked = 0; - pagebuf_iodone(pb, 0, 1); + pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), 1); } bio_put(bio); @@ -1434,7 +1434,7 @@ io_submitted: if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) { pb->pb_locked = 0; - pagebuf_iodone(pb, 0, 0); + pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), 1); } return 0; @@ -1612,15 +1612,13 @@ pagebuf_daemon( refrigerator(PF_IOTHREAD); if (pbd_active == 1) { - del_timer(&pb_daemon_timer); - pb_daemon_timer.expires = jiffies + - pb_params.p_un.flush_interval; - add_timer(&pb_daemon_timer); + mod_timer(&pb_daemon_timer, + jiffies + pb_params.p_un.flush_interval); interruptible_sleep_on(&pbd_waitq); } if (pbd_active == 0) { - del_timer(&pb_daemon_timer); + del_timer_sync(&pb_daemon_timer); } spin_lock(&pbd_delwrite_lock); diff --git a/fs/xfs/pagebuf/page_buf.h b/fs/xfs/pagebuf/page_buf.h index 834410affe8e..0ab5297e6f75 100644 --- a/fs/xfs/pagebuf/page_buf.h +++ b/fs/xfs/pagebuf/page_buf.h @@ -96,6 +96,7 @@ typedef enum page_buf_flags_e { /* pb_flags values */ PBF_MAPPABLE = (1 << 9),/* use directly-addressable pages */ PBF_STALE = (1 << 10), /* buffer has been staled, do not find it */ PBF_FS_MANAGED = (1 << 11), /* filesystem controls freeing memory */ + PBF_FS_DATAIOD = (1 << 12), /* schedule IO completion on fs datad */ /* flags used only as arguments to access routines */ PBF_LOCK = (1 << 13), /* lock requested */ diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 2a8c831e5716..bd7e1e614391 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ */ #include <xfs.h> -#include <xfs_quota_priv.h> +#include "xfs_qm.h" /* @@ -290,37 +290,45 @@ xfs_qm_dqwarn( warned = 0; if (INT_GET(d->d_blk_softlimit, ARCH_CONVERT) && - (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) { + (INT_GET(d->d_bcount, ARCH_CONVERT) >= + INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) { if (flags & XFS_QMOPT_DOWARN) { INT_MOD(d->d_bwarns, ARCH_CONVERT, +1); warned++; } } else { if (INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) || - (INT_GET(d->d_bcount, ARCH_CONVERT) < INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) { + (INT_GET(d->d_bcount, ARCH_CONVERT) < + INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) { INT_ZERO(d->d_bwarns, ARCH_CONVERT); } } if (INT_GET(d->d_ino_softlimit, ARCH_CONVERT) > 0 && - (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) { + (INT_GET(d->d_icount, ARCH_CONVERT) >= + INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) { if (flags & XFS_QMOPT_DOWARN) { INT_MOD(d->d_iwarns, ARCH_CONVERT, +1); warned++; } } else { if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT)) || - (INT_GET(d->d_icount, ARCH_CONVERT) < INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) { + (INT_GET(d->d_icount, ARCH_CONVERT) < + INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) { INT_ZERO(d->d_iwarns, ARCH_CONVERT); } } #ifdef QUOTADEBUG if (INT_GET(d->d_iwarns, ARCH_CONVERT)) - printk("--------@@Inode warnings running : %Lu >= %Lu\n", - INT_GET(d->d_icount, ARCH_CONVERT), INT_GET(d->d_ino_softlimit, ARCH_CONVERT)); + cmn_err(CE_DEBUG, + "--------@@Inode warnings running : %Lu >= %Lu", + INT_GET(d->d_icount, ARCH_CONVERT), + INT_GET(d->d_ino_softlimit, ARCH_CONVERT)); if (INT_GET(d->d_bwarns, ARCH_CONVERT)) - printk("--------@@Blks warnings running : %Lu >= %Lu\n", - INT_GET(d->d_bcount, ARCH_CONVERT), INT_GET(d->d_blk_softlimit, ARCH_CONVERT)); + cmn_err(CE_DEBUG, + "--------@@Blks warnings running : %Lu >= %Lu", + INT_GET(d->d_bcount, ARCH_CONVERT), + INT_GET(d->d_blk_softlimit, ARCH_CONVERT)); #endif return (warned); } @@ -869,7 +877,7 @@ xfs_qm_dqget( if (xfs_do_dqerror) { if ((xfs_dqerror_dev == mp->m_dev) && (xfs_dqreq_num++ % xfs_dqerror_mod) == 0) { - printk("Returning error in dqget\n"); + cmn_err(CE_DEBUG, "Returning error in dqget"); return (EIO); } } @@ -894,7 +902,7 @@ xfs_qm_dqget( * The chain is kept locked during lookup. */ if (xfs_qm_dqlookup(mp, id, h, O_dqpp) == 0) { - XFS_STATS_INC(xfsstats.xs_qm_dqcachehits); + XQM_STATS_INC(xqmstats.xs_qm_dqcachehits); /* * The dquot was found, moved to the front of the chain, * taken off the freelist if it was on it, and locked @@ -906,7 +914,7 @@ xfs_qm_dqget( xfs_dqtrace_entry(*O_dqpp, "DQGET DONE (FROM CACHE)"); return (0); /* success */ } - XFS_STATS_INC(xfsstats.xs_qm_dqcachemisses); + XQM_STATS_INC(xqmstats.xs_qm_dqcachemisses); /* * Dquot cache miss. We don't want to keep the inode lock across @@ -1006,7 +1014,7 @@ xfs_qm_dqget( xfs_qm_dqput(tmpdqp); XFS_DQ_HASH_UNLOCK(h); xfs_qm_dqdestroy(dqp); - XFS_STATS_INC(xfsstats.xs_qm_dquot_dups); + XQM_STATS_INC(xqmstats.xs_qm_dquot_dups); goto again; } } @@ -1373,18 +1381,6 @@ xfs_dqlock2( /* - * A rarely used accessor. This exists because we don't really want - * to expose the internals of a dquot to the outside world. - */ -xfs_dqid_t -xfs_qm_dqid( - xfs_dquot_t *dqp) -{ - return (INT_GET(dqp->q_core.d_id, ARCH_CONVERT)); -} - - -/* * Take a dquot out of the mount's dqlist as well as the hashlist. * This is called via unmount as well as quotaoff, and the purge * will always succeed unless there are soft (temp) references @@ -1483,145 +1479,41 @@ xfs_qm_dqpurge( } -/* - * Do some primitive error checking on ondisk dquot - * data structures. Not just for debugging, actually; - * this can be useful for detecting data corruption mainly due to - * disk failures. - */ -/* ARGSUSED */ -int -xfs_qm_dqcheck( - xfs_disk_dquot_t *ddq, - xfs_dqid_t id, - uint type, /* used only when IO_dorepair is true */ - uint flags, - char *str) -{ - int errs; - - errs = 0; - /* ASSERT(flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN)); */ - /* - * We can encounter an uninitialized dquot buffer for 2 reasons: - * 1. If we crash while deleting the quotainode(s), and those blks get used - * for some user data. This is because we take the path of regular - * file deletion; however, the size field of quotainodes is never - * updated, so all the tricks that we play in itruncate_finish - * don't quite matter. - * - * 2. We don't play the quota buffers when there's a quotaoff logitem. - * But the allocation will be replayed so we'll end up with an - * uninitialized quota block. - * - * This is all fine; things are still consistent, and we haven't lost - * any quota information. Just don't complain about bad dquot blks. - */ - if (INT_GET(ddq->d_magic, ARCH_CONVERT) != XFS_DQUOT_MAGIC) { - if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, - "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x", - str, id, INT_GET(ddq->d_magic, ARCH_CONVERT), XFS_DQUOT_MAGIC); - errs++; - } - if (INT_GET(ddq->d_version, ARCH_CONVERT) != XFS_DQUOT_VERSION) { - if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, - "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x", - str, id, INT_GET(ddq->d_magic, ARCH_CONVERT), XFS_DQUOT_VERSION); - errs++; - } - - if (INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_USER && INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_GROUP) { - if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, - "%s : XFS dquot ID 0x%x, unknown flags 0x%x", - str, id, INT_GET(ddq->d_flags, ARCH_CONVERT)); - errs++; - } - - if (id != -1 && id != INT_GET(ddq->d_id, ARCH_CONVERT)) { - if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, - "%s : ondisk-dquot 0x%x, ID mismatch: " - "0x%x expected, found id 0x%x", - str, ddq, id, INT_GET(ddq->d_id, ARCH_CONVERT)); - errs++; - } - - if (! errs) { - if (INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT) && - INT_GET(ddq->d_bcount, ARCH_CONVERT) >= INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT)) { - if (INT_ISZERO(ddq->d_btimer, ARCH_CONVERT) && !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) { - if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, - "%s : Dquot ID 0x%x (0x%x) " - "BLK TIMER NOT STARTED", - str, (int) INT_GET(ddq->d_id, ARCH_CONVERT), ddq); - errs++; - } - } - if (INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT) && - INT_GET(ddq->d_icount, ARCH_CONVERT) >= INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT)) { - if (INT_ISZERO(ddq->d_itimer, ARCH_CONVERT) && !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) { - if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, - "%s : Dquot ID 0x%x (0x%x) " - "INODE TIMER NOT STARTED", - str, (int) INT_GET(ddq->d_id, ARCH_CONVERT), ddq); - errs++; - } - } - } - - if (!errs || !(flags & XFS_QMOPT_DQREPAIR)) - return (errs); - - if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_NOTE, "Re-initializing dquot ID 0x%x", id); - - /* - * Typically, a repair is only requested by quotacheck. - */ - ASSERT(id != -1); - ASSERT(flags & XFS_QMOPT_DQREPAIR); - memset(ddq, 0, sizeof(xfs_dqblk_t)); - xfs_qm_dqinit_core(id, type, (xfs_dqblk_t *)ddq); - return (errs); -} - #ifdef QUOTADEBUG void xfs_qm_dqprint(xfs_dquot_t *dqp) { - printk( "-----------KERNEL DQUOT----------------\n"); - printk( "---- dquot ID = %d\n", (int) INT_GET(dqp->q_core.d_id, ARCH_CONVERT)); - printk( "---- type = %s\n", XFS_QM_ISUDQ(dqp) ? "USR" : "GRP"); - printk( "---- fs = 0x%p\n", dqp->q_mount); - printk( "---- blkno = 0x%x\n", (int) dqp->q_blkno); - printk( "---- boffset = 0x%x\n", (int) dqp->q_bufoffset); - printk( "---- blkhlimit = %Lu (0x%x)\n", - INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT), - (int) INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT)); - printk( "---- blkslimit = %Lu (0x%x)\n", - INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT), - (int)INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT)); - printk( "---- inohlimit = %Lu (0x%x)\n", - INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT), - (int)INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT)); - printk( "---- inoslimit = %Lu (0x%x)\n", - INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT), - (int)INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)); - printk( "---- bcount = %Lu (0x%x)\n", - INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT), - (int)INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT)); - printk( "---- icount = %Lu (0x%x)\n", - INT_GET(dqp->q_core.d_icount, ARCH_CONVERT), - (int)INT_GET(dqp->q_core.d_icount, ARCH_CONVERT)); - printk( "---- btimer = %d\n", (int)INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT)); - printk( "---- itimer = %d\n", (int)INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT)); - - printk( "---------------------------\n"); + cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------"); + cmn_err(CE_DEBUG, "---- dquotID = %d", + (int)INT_GET(dqp->q_core.d_id, ARCH_CONVERT)); + cmn_err(CE_DEBUG, "---- type = %s", + XFS_QM_ISUDQ(dqp) ? "USR" : "GRP"); + cmn_err(CE_DEBUG, "---- fs = 0x%p", dqp->q_mount); + cmn_err(CE_DEBUG, "---- blkno = 0x%x", (int) dqp->q_blkno); + cmn_err(CE_DEBUG, "---- boffset = 0x%x", (int) dqp->q_bufoffset); + cmn_err(CE_DEBUG, "---- blkhlimit = %Lu (0x%x)", + INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT), + (int) INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT)); + cmn_err(CE_DEBUG, "---- blkslimit = %Lu (0x%x)", + INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT), + (int)INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT)); + cmn_err(CE_DEBUG, "---- inohlimit = %Lu (0x%x)", + INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT), + (int)INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT)); + cmn_err(CE_DEBUG, "---- inoslimit = %Lu (0x%x)", + INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT), + (int)INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)); + cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)", + INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT), + (int)INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT)); + cmn_err(CE_DEBUG, "---- icount = %Lu (0x%x)", + INT_GET(dqp->q_core.d_icount, ARCH_CONVERT), + (int)INT_GET(dqp->q_core.d_icount, ARCH_CONVERT)); + cmn_err(CE_DEBUG, "---- btimer = %d", + (int)INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT)); + cmn_err(CE_DEBUG, "---- itimer = %d", + (int)INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT)); + cmn_err(CE_DEBUG, "---------------------------"); } #endif diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h index 455830aee721..9d68757447e0 100644 --- a/fs/xfs/xfs_dquot.h +++ b/fs/xfs/quota/xfs_dquot.h @@ -146,6 +146,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp) } #endif + /* * The following three routines simply manage the q_flock * semaphore embedded in the dquot. This semaphore synchronizes @@ -197,7 +198,6 @@ extern void xfs_qm_dqprint(xfs_dquot_t *); #define xfs_qm_dqprint(a) #endif -extern xfs_dquot_t *xfs_qm_dqinit(xfs_mount_t *, xfs_dqid_t, uint); extern void xfs_qm_dqdestroy(xfs_dquot_t *); extern int xfs_qm_dqflush(xfs_dquot_t *, uint); extern int xfs_qm_dqpurge(xfs_dquot_t *, uint); @@ -206,7 +206,15 @@ extern int xfs_qm_dqlock_nowait(xfs_dquot_t *); extern int xfs_qm_dqflock_nowait(xfs_dquot_t *); extern void xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp); extern void xfs_qm_adjust_dqtimers(xfs_mount_t *, - xfs_disk_dquot_t *); + xfs_disk_dquot_t *); extern int xfs_qm_dqwarn(xfs_disk_dquot_t *, uint); +extern int xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *, + xfs_dqid_t, uint, uint, xfs_dquot_t **); +extern void xfs_qm_dqput(xfs_dquot_t *); +extern void xfs_qm_dqrele(xfs_dquot_t *); +extern void xfs_dqlock(xfs_dquot_t *); +extern void xfs_dqlock2(xfs_dquot_t *, xfs_dquot_t *); +extern void xfs_dqunlock(xfs_dquot_t *); +extern void xfs_dqunlock_nonotify(xfs_dquot_t *); #endif /* __XFS_DQUOT_H__ */ diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index 2d5c619543a2..a0562849bca6 100644 --- a/fs/xfs/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ */ #include <xfs.h> -#include <xfs_quota_priv.h> +#include "xfs_qm.h" /* diff --git a/fs/xfs/xfs_dquot_item.h b/fs/xfs/quota/xfs_dquot_item.h index a11987e5efc8..9c6500dabcaa 100644 --- a/fs/xfs/xfs_dquot_item.h +++ b/fs/xfs/quota/xfs_dquot_item.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -32,58 +32,22 @@ #ifndef __XFS_DQUOT_ITEM_H__ #define __XFS_DQUOT_ITEM_H__ -/* - * These are the structures used to lay out dquots and quotaoff - * records on the log. Quite similar to those of inodes. - */ - -/* - * log format struct for dquots. - * The first two fields must be the type and size fitting into - * 32 bits : log_recovery code assumes that. - */ -typedef struct xfs_dq_logformat { - __uint16_t qlf_type; /* dquot log item type */ - __uint16_t qlf_size; /* size of this item */ - xfs_dqid_t qlf_id; /* usr/grp id number : 32 bits */ - __int64_t qlf_blkno; /* blkno of dquot buffer */ - __int32_t qlf_len; /* len of dquot buffer */ - __uint32_t qlf_boffset; /* off of dquot in buffer */ -} xfs_dq_logformat_t; - -/* - * log format struct for QUOTAOFF records. - * The first two fields must be the type and size fitting into - * 32 bits : log_recovery code assumes that. - * We write two LI_QUOTAOFF logitems per quotaoff, the last one keeps a pointer - * to the first and ensures that the first logitem is taken out of the AIL - * only when the last one is securely committed. - */ -typedef struct xfs_qoff_logformat { - unsigned short qf_type; /* quotaoff log item type */ - unsigned short qf_size; /* size of this item */ - unsigned int qf_flags; /* USR and/or GRP */ - char qf_pad[12]; /* padding for future */ -} xfs_qoff_logformat_t; - - -#ifdef __KERNEL__ - struct xfs_dquot; struct xfs_trans; struct xfs_mount; +struct xfs_qoff_logitem; + typedef struct xfs_dq_logitem { xfs_log_item_t qli_item; /* common portion */ struct xfs_dquot *qli_dquot; /* dquot ptr */ xfs_lsn_t qli_flush_lsn; /* lsn at last flush */ - unsigned short qli_pushbuf_flag; /* one bit used in push_ail */ + unsigned short qli_pushbuf_flag; /* 1 bit used in push_ail */ #ifdef DEBUG uint64_t qli_push_owner; #endif xfs_dq_logformat_t qli_format; /* logged structure */ } xfs_dq_logitem_t; - typedef struct xfs_qoff_logitem { xfs_log_item_t qql_item; /* common portion */ struct xfs_qoff_logitem *qql_start_lip; /* qoff-start logitem, if any */ @@ -93,12 +57,10 @@ typedef struct xfs_qoff_logitem { extern void xfs_qm_dquot_logitem_init(struct xfs_dquot *); extern xfs_qoff_logitem_t *xfs_qm_qoff_logitem_init(struct xfs_mount *, - xfs_qoff_logitem_t *, uint); + struct xfs_qoff_logitem *, uint); extern xfs_qoff_logitem_t *xfs_trans_get_qoff_item(struct xfs_trans *, - xfs_qoff_logitem_t *, uint); + struct xfs_qoff_logitem *, uint); extern void xfs_trans_log_quotaoff_item(struct xfs_trans *, - xfs_qoff_logitem_t *); - -#endif /* __KERNEL__ */ + struct xfs_qoff_logitem *); #endif /* __XFS_DQUOT_ITEM_H__ */ diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 5971def62882..5b16a1772d61 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -31,8 +31,17 @@ */ #include <xfs.h> -#include <xfs_quota_priv.h> +#include "xfs_qm.h" +/* + * The global quota manager. There is only one of these for the entire + * system, _not_ one per file system. XQM keeps track of the overall + * quota functionality, including maintaining the freelist and hash + * tables of dquots. + */ +mutex_t xfs_Gqm_lock; +struct xfs_qm *xfs_Gqm; +EXPORT_SYMBOL(xfs_Gqm); /* used by xfsidbg */ kmem_zone_t *qm_dqzone; kmem_zone_t *qm_dqtrxzone; @@ -51,24 +60,27 @@ extern mutex_t qcheck_lock; #ifdef QUOTADEBUG #define XQM_LIST_PRINT(l, NXT, title) \ { \ - xfs_dquot_t *dqp; int i = 0;\ - printk("%s (#%d)\n", title, (int) (l)->qh_nelems); \ - for (dqp = (l)->qh_next; dqp != NULL; dqp = dqp->NXT) { \ - printk("\t%d.\t\"%d (%s)\"\t bcnt = %d, icnt = %d refs = %d\n", \ - ++i, (int) INT_GET(dqp->q_core.d_id, ARCH_CONVERT), \ - DQFLAGTO_TYPESTR(dqp), \ - (int) INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT), \ - (int) INT_GET(dqp->q_core.d_icount, ARCH_CONVERT), \ - (int) dqp->q_nrefs); } \ + xfs_dquot_t *dqp; int i = 0; \ + cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \ + for (dqp = (l)->qh_next; dqp != NULL; dqp = dqp->NXT) { \ + cmn_err(CE_DEBUG, " %d. \"%d (%s)\" " \ + "bcnt = %d, icnt = %d, refs = %d", \ + ++i, (int) INT_GET(dqp->q_core.d_id, ARCH_CONVERT), \ + DQFLAGTO_TYPESTR(dqp), \ + (int) INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT), \ + (int) INT_GET(dqp->q_core.d_icount, ARCH_CONVERT), \ + (int) dqp->q_nrefs); } \ } +#else +#define XQM_LIST_PRINT(l, NXT, title) do { } while (0) #endif /* * Initialize the XQM structure. * Note that there is not one quota manager per file system. */ -struct xfs_qm * -xfs_qm_init(void) +STATIC struct xfs_qm * +xfs_Gqm_init(void) { xfs_qm_t *xqm; int hsize, i; @@ -83,11 +95,6 @@ xfs_qm_init(void) XFS_QM_HASHSIZE_LOW : XFS_QM_HASHSIZE_HIGH; xqm->qm_dqhashmask = hsize - 1; - /* - * XXXsup We could keep reference counts on usr and grp quotas - * inside XQM separately, and avoid having two hashtables even - * when only one 'type' is active in the system. - */ xqm->qm_usr_dqhtable = (xfs_dqhash_t *)kmem_zalloc(hsize * sizeof(xfs_dqhash_t), KM_SLEEP); @@ -135,7 +142,7 @@ xfs_qm_init(void) #ifdef DEBUG mutex_init(&qcheck_lock, MUTEX_DEFAULT, "qchk"); #endif - return (xqm); + return xqm; } /* @@ -143,9 +150,9 @@ xfs_qm_init(void) */ void xfs_qm_destroy( - struct xfs_qm *xqm) + struct xfs_qm *xqm) { - int hsize, i; + int hsize, i; ASSERT(xqm != NULL); ASSERT(xqm->qm_nrefs == 0); @@ -186,7 +193,7 @@ xfs_qm_hold_quotafs_ref( XFS_QM_LOCK(xfs_Gqm); if (xfs_Gqm == NULL) { - if ((xfs_Gqm = xfs_qm_init()) == NULL) { + if ((xfs_Gqm = xfs_Gqm_init()) == NULL) { return (XFS_ERROR(EINVAL)); } } @@ -295,7 +302,8 @@ void xfs_qm_unmount_quotadestroy( xfs_mount_t *mp) { - xfs_qm_destroy_quotainfo(mp); + if (mp->m_quotainfo) + xfs_qm_destroy_quotainfo(mp); } @@ -416,23 +424,18 @@ xfs_qm_unmount_quotas( xfs_mount_t *mp) { xfs_inode_t *uqp, *gqp; - int error; - - error = 0; + int error = 0; /* * Release the dquots that root inode, et al might be holding, * before we flush quotas and blow away the quotainfo structure. */ ASSERT(mp->m_rootip); - if (mp->m_rootip->i_udquot || mp->m_rootip->i_gdquot) - xfs_qm_dqdettach_inode(mp->m_rootip); - if (mp->m_rbmip && - (mp->m_rbmip->i_udquot || mp->m_rbmip->i_gdquot)) - xfs_qm_dqdettach_inode(mp->m_rbmip); - if (mp->m_rsumip && - (mp->m_rsumip->i_udquot || mp->m_rsumip->i_gdquot)) - xfs_qm_dqdettach_inode(mp->m_rsumip); + xfs_qm_dqdetach(mp->m_rootip); + if (mp->m_rbmip) + xfs_qm_dqdetach(mp->m_rbmip); + if (mp->m_rsumip) + xfs_qm_dqdetach(mp->m_rsumip); /* * Flush out the quota inodes. @@ -579,10 +582,10 @@ xfs_qm_detach_gdquots( * parameter. This is used when turning off quota accounting for * users and/or groups, as well as when the filesystem is unmounting. */ -int -xfs_qm_dqpurge_all( - xfs_mount_t *mp, - uint flags) /* QUOTAOFF/UMOUNTING/UQUOTA/GQUOTA */ +STATIC int +xfs_qm_dqpurge_int( + xfs_mount_t *mp, + uint flags) /* QUOTAOFF/UMOUNTING/UQUOTA/GQUOTA */ { xfs_dquot_t *dqp; uint dqtype; @@ -652,7 +655,26 @@ xfs_qm_dqpurge_all( dqp = nextdqp; } xfs_qm_mplist_unlock(mp); - return (nmisses); + return nmisses; +} + +int +xfs_qm_dqpurge_all( + xfs_mount_t *mp, + uint flags) +{ + int ndquots; + + /* + * Purge the dquot cache. + * None of the dquots should really be busy at this point. + */ + if (mp->m_quotainfo) { + while ((ndquots = xfs_qm_dqpurge_int(mp, flags))) { + delay(ndquots * 10); + } + } + return 0; } STATIC int @@ -710,7 +732,6 @@ xfs_qm_dqattach_one( xfs_dqunlock(dqp); xfs_dqunlock(udqhint); } - /* XXX XFS_STATS */ goto done; } /* @@ -871,43 +892,45 @@ xfs_qm_dqattach_grouphint( */ int xfs_qm_dqattach( - xfs_inode_t *ip, - uint flags) + xfs_inode_t *ip, + uint flags) { - int error; - xfs_mount_t *mp; - uint nquotas; + xfs_mount_t *mp = ip->i_mount; + uint nquotas = 0; + int error = 0; - mp = ip->i_mount; - ASSERT(ip->i_ino != mp->m_sb.sb_uquotino && - ip->i_ino != mp->m_sb.sb_gquotino); + if ((! XFS_IS_QUOTA_ON(mp)) || + (! XFS_NOT_DQATTACHED(mp, ip)) || + (ip->i_ino == mp->m_sb.sb_uquotino) || + (ip->i_ino == mp->m_sb.sb_gquotino)) + return (0); ASSERT((flags & XFS_QMOPT_ILOCKED) == 0 || XFS_ISLOCKED_INODE_EXCL(ip)); - nquotas = 0; - error = 0; if (! (flags & XFS_QMOPT_ILOCKED)) xfs_ilock(ip, XFS_ILOCK_EXCL); if (XFS_IS_UQUOTA_ON(mp)) { - if ((error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER, + error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER, flags & XFS_QMOPT_DQALLOC, flags & XFS_QMOPT_DQLOCK, - NULL, &ip->i_udquot))) + NULL, &ip->i_udquot); + if (error) goto done; nquotas++; } ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); if (XFS_IS_GQUOTA_ON(mp)) { - if ((error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, + error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, flags & XFS_QMOPT_DQALLOC, flags & XFS_QMOPT_DQLOCK, - ip->i_udquot, &ip->i_gdquot))) - /* - * Don't worry about the udquot that we may have - * attached above. It'll get dettached, if not already. - */ + ip->i_udquot, &ip->i_gdquot); + /* + * Don't worry about the udquot that we may have + * attached above. It'll get detached, if not already. + */ + if (error) goto done; nquotas++; } @@ -975,9 +998,12 @@ xfs_qm_dqattach( * xfs_ireclaim. */ void -xfs_qm_dqdettach_inode( +xfs_qm_dqdetach( xfs_inode_t *ip) { + if (!(ip->i_udquot || ip->i_gdquot)) + return; + ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_uquotino); ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_gquotino); if (ip->i_udquot) @@ -992,33 +1018,8 @@ xfs_qm_dqdettach_inode( } } -int -xfs_qm_unmount( - xfs_mount_t *mp) -{ - vnode_t *vp; - - if (XFS_IS_UQUOTA_ON(mp)) { - vp = XFS_ITOV(XFS_QI_UQIP(mp)); - VN_RELE(vp); - if (vn_count(vp) > 1) - cmn_err(CE_WARN, "UQUOTA busy vp=0x%x count=%d", - vp, vn_count(vp)); - } - if (XFS_IS_GQUOTA_ON(mp)) { - vp = XFS_ITOV(XFS_QI_GQIP(mp)); - VN_RELE(vp); - if (vn_count(vp) > 1) - cmn_err(CE_WARN, "GQUOTA busy vp=0x%x count=%d", - vp, vn_count(vp)); - } - - return (0); -} - - /* - * This is called by xfs_sync and flags arg determines the caller, + * This is called by VFS_SYNC and flags arg determines the caller, * and its motives, as done in xfs_sync. * * vfs_sync: SYNC_FSDATA|SYNC_ATTR|SYNC_BDFLUSH 0x31 @@ -1923,9 +1924,7 @@ xfs_qm_quotacheck( mp->m_qflags &= ~(XFS_GQUOTA_CHKD | XFS_UQUOTA_CHKD); mp->m_qflags |= flags; -#ifdef QUOTADEBUG XQM_LIST_PRINT(&(XFS_QI_MPL_LIST(mp)), MPL_NEXT, "++++ Mp list +++"); -#endif error_return: cmn_err(CE_NOTE, "XFS quotacheck %s: Done.", mp->m_fsname); @@ -2033,7 +2032,7 @@ xfs_qm_shake_freelist( nflushes = 0; #ifdef QUOTADEBUG - printk("Shake free 0x%x\n", howmany); + cmn_err(CE_DEBUG, "Shake free 0x%x", howmany); #endif /* lock order is : hashchainlock, freelistlock, mplistlock */ tryagain: @@ -2053,7 +2052,7 @@ xfs_qm_shake_freelist( xfs_qm_freelist_unlock(xfs_Gqm); if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) return (nreclaimed != howmany); - XFS_STATS_INC(xfsstats.xs_qm_dqwants); + XQM_STATS_INC(xqmstats.xs_qm_dqwants); goto tryagain; } @@ -2067,7 +2066,7 @@ xfs_qm_shake_freelist( ASSERT(! XFS_DQ_IS_DIRTY(dqp)); ASSERT(dqp->HL_PREVP == NULL); ASSERT(dqp->MPL_PREVP == NULL); - XFS_STATS_INC(xfsstats.xs_qm_dqinact_reclaims); + XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims); nextdqp = dqp->dq_flnext; goto off_freelist; } @@ -2132,7 +2131,8 @@ xfs_qm_shake_freelist( } xfs_dqtrace_entry(dqp, "DQSHAKE: UNLINKING"); #ifdef QUOTADEBUG - printk("Shake 0x%p, ID 0x%x\n", dqp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT)); + cmn_err(CE_DEBUG, "Shake 0x%p, ID 0x%x\n", + dqp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT)); #endif ASSERT(dqp->q_nrefs == 0); nextdqp = dqp->dq_flnext; @@ -2146,7 +2146,7 @@ xfs_qm_shake_freelist( XQM_FREELIST_REMOVE(dqp); xfs_dqunlock(dqp); nreclaimed++; - XFS_STATS_INC(xfsstats.xs_qm_dqshake_reclaims); + XQM_STATS_INC(xqmstats.xs_qm_dqshake_reclaims); xfs_qm_dqdestroy(dqp); dqp = nextdqp; } @@ -2220,7 +2220,7 @@ xfs_qm_dqreclaim_one(void) xfs_qm_freelist_unlock(xfs_Gqm); if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) return (NULL); - XFS_STATS_INC(xfsstats.xs_qm_dqwants); + XQM_STATS_INC(xqmstats.xs_qm_dqwants); goto startagain; } @@ -2237,7 +2237,7 @@ xfs_qm_dqreclaim_one(void) XQM_FREELIST_REMOVE(dqp); xfs_dqunlock(dqp); dqpout = dqp; - XFS_STATS_INC(xfsstats.xs_qm_dqinact_reclaims); + XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims); break; } @@ -2323,7 +2323,7 @@ xfs_qm_dqalloc_incore( * Try to recycle a dquot from the freelist. */ if ((dqp = xfs_qm_dqreclaim_one())) { - XFS_STATS_INC(xfsstats.xs_qm_dqreclaims); + XQM_STATS_INC(xqmstats.xs_qm_dqreclaims); /* * Just zero the core here. The rest will get * reinitialized by caller. XXX we shouldn't even @@ -2333,7 +2333,7 @@ xfs_qm_dqalloc_incore( *O_dqpp = dqp; return (B_FALSE); } - XFS_STATS_INC(xfsstats.xs_qm_dqreclaim_misses); + XQM_STATS_INC(xqmstats.xs_qm_dqreclaim_misses); } /* @@ -2361,9 +2361,7 @@ xfs_qm_write_sb_changes( int error; #ifdef QUOTADEBUG - cmn_err(CE_NOTE, - "Writing superblock quota changes :%s", - mp->m_fsname); + cmn_err(CE_NOTE, "Writing superblock quota changes :%s", mp->m_fsname); #endif tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE); if ((error = xfs_trans_reserve(tp, 0, @@ -2408,6 +2406,9 @@ xfs_qm_vop_dqalloc( xfs_dquot_t *uq, *gq; uint lockflags; + if (!XFS_IS_QUOTA_ON(mp)) + return 0; + lockflags = XFS_ILOCK_EXCL; xfs_ilock(ip, lockflags); @@ -2564,7 +2565,7 @@ xfs_qm_vop_chown_reserve( xfs_inode_t *ip, xfs_dquot_t *udqp, xfs_dquot_t *gdqp, - uint privileged) + uint flags) { int error; xfs_mount_t *mp; @@ -2600,13 +2601,11 @@ xfs_qm_vop_chown_reserve( } } - if ((error = xfs_trans_reserve_quota(tp, delblksudq, - delblksgdq, - ip->i_d.di_nblocks, 1, - privileged))) + if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, + delblksudq, delblksgdq, ip->i_d.di_nblocks, 1, + flags | XFS_QMOPT_RES_REGBLKS))) return (error); - /* * Do the delayed blks reservations/unreservations now. Since, these * are done without the help of a transaction, if a reservation fails @@ -2619,15 +2618,13 @@ xfs_qm_vop_chown_reserve( */ ASSERT(delblksudq || delblksgdq); ASSERT(unresudq || unresgdq); - if ((error = xfs_trans_reserve_quota(NULL, - delblksudq, delblksgdq, - (xfs_qcnt_t)delblks, 0, - privileged))) + if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, + delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0, + flags | XFS_QMOPT_RES_REGBLKS))) return (error); - (void) xfs_trans_unreserve_quota(NULL, - unresudq, unresgdq, - (xfs_qcnt_t)delblks, 0, - 0); + xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, + unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0, + XFS_QMOPT_RES_REGBLKS); } return (0); @@ -2643,6 +2640,9 @@ xfs_qm_vop_rename_dqattach( ip = i_tab[0]; + if (! XFS_IS_QUOTA_ON(ip->i_mount)) + return (0); + if (XFS_NOT_DQATTACHED(ip->i_mount, ip)) { error = xfs_qm_dqattach(ip, 0); if (error) @@ -2670,6 +2670,9 @@ xfs_qm_vop_dqattach_and_dqmod_newinode( xfs_dquot_t *udqp, xfs_dquot_t *gdqp) { + if (!XFS_IS_QUOTA_ON(tp->t_mountp)) + return; + ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); ASSERT(XFS_IS_QUOTA_RUNNING(tp->t_mountp)); @@ -2714,7 +2717,7 @@ xfs_qm_freelist_destroy(xfs_frlist_t *ql) xfs_dqlock(dqp); nextdqp = dqp->dq_flnext; #ifdef QUOTADEBUG - printk("FREELIST destroy 0x%p\n", dqp); + cmn_err(CE_DEBUG, "FREELIST destroy 0x%p", dqp); #endif XQM_FREELIST_REMOVE(dqp); xfs_dqunlock(dqp); @@ -2753,25 +2756,6 @@ xfs_qm_freelist_unlink(xfs_dquot_t *dq) xfs_Gqm->qm_dqfreelist.qh_version++; } -#ifdef QUOTADEBUG -void -xfs_qm_freelist_print(xfs_frlist_t *qlist, char *title) -{ - xfs_dquot_t *dq; - int i = 0; - printk("%s (#%d)\n", title, (int) qlist->qh_nelems); - FOREACH_DQUOT_IN_FREELIST(dq, qlist) { - printk("\t%d.\t\"%d (%s:0x%p)\"\t bcnt = %d, icnt = %d " - "refs = %d\n", - ++i, INT_GET(dq->q_core.d_id, ARCH_CONVERT), - DQFLAGTO_TYPESTR(dq), dq, - (int) INT_GET(dq->q_core.d_bcount, ARCH_CONVERT), - (int) INT_GET(dq->q_core.d_icount, ARCH_CONVERT), - (int) dq->q_nrefs); - } -} -#endif - void xfs_qm_freelist_append(xfs_frlist_t *ql, xfs_dquot_t *dq) { diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/quota/xfs_qm.h index 1c2c02530862..c4bc3abdd608 100644 --- a/fs/xfs/xfs_qm.h +++ b/fs/xfs/quota/xfs_qm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -32,10 +32,16 @@ #ifndef __XFS_QM_H__ #define __XFS_QM_H__ -struct xfs_dqhash; -struct xfs_inode; -struct xfs_dquot; +#include "xfs_dquot_item.h" +#include "xfs_dquot.h" +#include "xfs_quota_priv.h" +#include "xfs_qm_stats.h" +struct xfs_qm; +struct xfs_inode; + +extern mutex_t xfs_Gqm_lock; +extern struct xfs_qm *xfs_Gqm; extern kmem_zone_t *qm_dqzone; extern kmem_zone_t *qm_dqtrxzone; @@ -136,24 +142,13 @@ typedef struct xfs_quotainfo { } xfs_quotainfo_t; -/* - * The structure kept inside the xfs_trans_t keep track of dquot changes - * within a transaction and apply them later. - */ -typedef struct xfs_dqtrx { - struct xfs_dquot *qt_dquot; /* the dquot this refers to */ - ulong qt_blk_res; /* blks reserved on a dquot */ - ulong qt_blk_res_used; /* blks used from the reservation */ - ulong qt_ino_res; /* inode reserved on a dquot */ - ulong qt_ino_res_used; /* inodes used from the reservation */ - long qt_bcount_delta; /* dquot blk count changes */ - long qt_delbcnt_delta; /* delayed dquot blk count changes */ - long qt_icount_delta; /* dquot inode count changes */ - ulong qt_rtblk_res; /* # blks reserved on a dquot */ - ulong qt_rtblk_res_used;/* # blks used from reservation */ - long qt_rtbcount_delta;/* dquot realtime blk changes */ - long qt_delrtb_delta; /* delayed RT blk count changes */ -} xfs_dqtrx_t; +extern xfs_dqtrxops_t xfs_trans_dquot_ops; + +extern void xfs_trans_mod_dquot(xfs_trans_t *, xfs_dquot_t *, uint, long); +extern int xfs_trans_reserve_quota_bydquots(xfs_trans_t *, xfs_mount_t *, + xfs_dquot_t *, xfs_dquot_t *, long, long, uint); +extern void xfs_trans_dqjoin(xfs_trans_t *, xfs_dquot_t *); +extern void xfs_trans_log_dquot(xfs_trans_t *, xfs_dquot_t *); /* * We keep the usr and grp dquots separately so that locking will be easier @@ -184,9 +179,33 @@ typedef struct xfs_dquot_acct { extern int xfs_qm_init_quotainfo(xfs_mount_t *); extern void xfs_qm_destroy_quotainfo(xfs_mount_t *); +extern int xfs_qm_mount_quotas(xfs_mount_t *); +extern void xfs_qm_mount_quotainit(xfs_mount_t *, uint); +extern void xfs_qm_unmount_quotadestroy(xfs_mount_t *); +extern int xfs_qm_unmount_quotas(xfs_mount_t *); +extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t); +extern int xfs_qm_sync(xfs_mount_t *, short); + +/* dquot stuff */ extern void xfs_qm_dqunlink(xfs_dquot_t *); extern boolean_t xfs_qm_dqalloc_incore(xfs_dquot_t **); -extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t); +extern int xfs_qm_dqattach(xfs_inode_t *, uint); +extern void xfs_qm_dqdetach(xfs_inode_t *); +extern int xfs_qm_dqpurge_all(xfs_mount_t *, uint); +extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint); + +/* vop stuff */ +extern int xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *, + uid_t, gid_t, uint, + xfs_dquot_t **, xfs_dquot_t **); +extern void xfs_qm_vop_dqattach_and_dqmod_newinode( + xfs_trans_t *, xfs_inode_t *, + xfs_dquot_t *, xfs_dquot_t *); +extern int xfs_qm_vop_rename_dqattach(xfs_inode_t **); +extern xfs_dquot_t * xfs_qm_vop_chown(xfs_trans_t *, xfs_inode_t *, + xfs_dquot_t **, xfs_dquot_t *); +extern int xfs_qm_vop_chown_reserve(xfs_trans_t *, xfs_inode_t *, + xfs_dquot_t *, xfs_dquot_t *, uint); /* list stuff */ extern void xfs_qm_freelist_init(xfs_frlist_t *); @@ -199,10 +218,7 @@ extern int xfs_qm_mplist_nowait(xfs_mount_t *); extern int xfs_qm_dqhashlock_nowait(xfs_dquot_t *); /* system call interface */ -extern int linvfs_getxstate(struct super_block *, struct fs_quota_stat *); -extern int linvfs_setxstate(struct super_block *, unsigned int, int); -extern int linvfs_getxquota(struct super_block *, int, qid_t, struct fs_disk_quota *); -extern int linvfs_setxquota(struct super_block *, int, qid_t, struct fs_disk_quota *); +extern int xfs_qm_quotactl(bhv_desc_t *, int, int, xfs_caddr_t); #ifdef DEBUG extern int xfs_qm_internalqcheck(xfs_mount_t *); @@ -210,10 +226,4 @@ extern int xfs_qm_internalqcheck(xfs_mount_t *); #define xfs_qm_internalqcheck(mp) (0) #endif -#ifdef QUOTADEBUG -extern void xfs_qm_freelist_print(xfs_frlist_t *, char *); -#else -#define xfs_qm_freelist_print(a, b) do { } while (0) -#endif - #endif /* __XFS_QM_H__ */ diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c new file mode 100644 index 000000000000..665de8bb45e0 --- /dev/null +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU 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. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +#include <xfs.h> +#include <linux/init.h> +#include "xfs_qm.h" + +#define MNTOPT_QUOTA "quota" /* disk quotas (user) */ +#define MNTOPT_NOQUOTA "noquota" /* no quotas */ +#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */ +#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */ +#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */ +#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */ +#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */ +#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */ +#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */ + +STATIC int +xfs_qm_parseargs( + struct bhv_desc *bhv, + char *options, + struct xfs_mount_args *args, + int update) +{ + size_t length; + char *local_options = options; + char *this_char; + int error; + int referenced = update; + + while ((this_char = strsep(&local_options, ",")) != NULL) { + length = strlen(this_char); + if (local_options) + length++; + + if (!strcmp(this_char, MNTOPT_NOQUOTA)) { + args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA); + args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA); + referenced = update; + } else if (!strcmp(this_char, MNTOPT_QUOTA) || + !strcmp(this_char, MNTOPT_UQUOTA) || + !strcmp(this_char, MNTOPT_USRQUOTA)) { + args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF; + referenced = 1; + } else if (!strcmp(this_char, MNTOPT_QUOTANOENF) || + !strcmp(this_char, MNTOPT_UQUOTANOENF)) { + args->flags |= XFSMNT_UQUOTA; + args->flags &= ~XFSMNT_UQUOTAENF; + referenced = 1; + } else if (!strcmp(this_char, MNTOPT_GQUOTA) || + !strcmp(this_char, MNTOPT_GRPQUOTA)) { + args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF; + referenced = 1; + } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) { + args->flags |= XFSMNT_GQUOTA; + args->flags &= ~XFSMNT_GQUOTAENF; + referenced = 1; + } else { + if (local_options) + *(local_options-1) = ','; + continue; + } + + while (length--) + *this_char++ = ','; + } + + PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error); + if (!error && !referenced) + bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM); + return error; +} + +STATIC int +xfs_qm_showargs( + struct bhv_desc *bhv, + struct seq_file *m) +{ + struct vfs *vfsp = bhvtovfs(bhv); + struct xfs_mount *mp = XFS_VFSTOM(vfsp); + int error; + + if (mp->m_qflags & XFS_UQUOTA_ACCT) { + (mp->m_qflags & XFS_UQUOTA_ENFD) ? + seq_puts(m, "," MNTOPT_USRQUOTA) : + seq_puts(m, "," MNTOPT_UQUOTANOENF); + } + + if (mp->m_qflags & XFS_GQUOTA_ACCT) { + (mp->m_qflags & XFS_GQUOTA_ENFD) ? + seq_puts(m, "," MNTOPT_GRPQUOTA) : + seq_puts(m, "," MNTOPT_GQUOTANOENF); + } + + if (!(mp->m_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT))) + seq_puts(m, "," MNTOPT_NOQUOTA); + + PVFS_SHOWARGS(BHV_NEXT(bhv), m, error); + return error; +} + +STATIC int +xfs_qm_mount( + struct bhv_desc *bhv, + struct xfs_mount_args *args, + struct cred *cr) +{ + struct vfs *vfsp = bhvtovfs(bhv); + struct xfs_mount *mp = XFS_VFSTOM(vfsp); + int error; + + if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA)) + xfs_qm_mount_quotainit(mp, args->flags); + PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error); + return error; +} + +STATIC int +xfs_qm_syncall( + struct bhv_desc *bhv, + int flags, + cred_t *credp) +{ + struct vfs *vfsp = bhvtovfs(bhv); + struct xfs_mount *mp = XFS_VFSTOM(vfsp); + int error; + + /* + * Get the Quota Manager to flush the dquots. + */ + if (XFS_IS_QUOTA_ON(mp)) { + if ((error = xfs_qm_sync(mp, flags))) { + /* + * If we got an IO error, we will be shutting down. + * So, there's nothing more for us to do here. + */ + ASSERT(error != EIO || XFS_FORCED_SHUTDOWN(mp)); + if (XFS_FORCED_SHUTDOWN(mp)) { + return XFS_ERROR(error); + } + } + } + PVFS_SYNC(BHV_NEXT(bhv), flags, credp, error); + return error; +} + +/* + * When xfsquotas isn't installed and the superblock had quotas, we need to + * clear the quotaflags from superblock. + */ +STATIC void +xfs_mount_reset_sbqflags( + xfs_mount_t *mp) +{ + xfs_trans_t *tp; + unsigned long s; + + mp->m_qflags = 0; + /* + * It is OK to look at sb_qflags here in mount path, + * without SB_LOCK. + */ + if (mp->m_sb.sb_qflags == 0) + return; + s = XFS_SB_LOCK(mp); + mp->m_sb.sb_qflags = 0; + XFS_SB_UNLOCK(mp, s); + + /* + * if the fs is readonly, let the incore superblock run + * with quotas off but don't flush the update out to disk + */ + if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY) + return; +#ifdef QUOTADEBUG + xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes"); +#endif + tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE); + if (xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, + XFS_DEFAULT_LOG_COUNT)) { + xfs_trans_cancel(tp, 0); + return; + } + xfs_mod_sb(tp, XFS_SB_QFLAGS); + xfs_trans_commit(tp, 0, NULL); +} + +STATIC int +xfs_qm_newmount( + xfs_mount_t *mp, + uint *needquotamount, + uint *quotaflags) +{ + uint quotaondisk; + uint uquotaondisk = 0, gquotaondisk = 0; + + *quotaflags = 0; + *needquotamount = B_FALSE; + + quotaondisk = XFS_SB_VERSION_HASQUOTA(&mp->m_sb) && + mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT); + + if (quotaondisk) { + uquotaondisk = mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT; + gquotaondisk = mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT; + } + + /* + * If the device itself is read-only, we can't allow + * the user to change the state of quota on the mount - + * this would generate a transaction on the ro device, + * which would lead to an I/O error and shutdown + */ + + if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) || + (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) || + (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) || + (!gquotaondisk && XFS_IS_GQUOTA_ON(mp))) && + xfs_dev_is_read_only(mp, "changing quota state")) { + cmn_err(CE_WARN, + "XFS: please mount with%s%s%s.", + (!quotaondisk ? "out quota" : ""), + (uquotaondisk ? " usrquota" : ""), + (gquotaondisk ? " grpquota" : "")); + return XFS_ERROR(EPERM); + } + + if (XFS_IS_QUOTA_ON(mp) || quotaondisk) { + /* + * Call mount_quotas at this point only if we won't have to do + * a quotacheck. + */ + if (quotaondisk && !XFS_QM_NEED_QUOTACHECK(mp)) { + /* + * If the xfs quota code isn't installed, + * we have to reset the quotachk'd bit. + * If an error occured, qm_mount_quotas code + * has already disabled quotas. So, just finish + * mounting, and get on with the boring life + * without disk quotas. + */ + if (xfs_qm_mount_quotas(mp)) + xfs_mount_reset_sbqflags(mp); + } else { + /* + * Clear the quota flags, but remember them. This + * is so that the quota code doesn't get invoked + * before we're ready. This can happen when an + * inode goes inactive and wants to free blocks, + * or via xfs_log_mount_finish. + */ + *needquotamount = B_TRUE; + *quotaflags = mp->m_qflags; + mp->m_qflags = 0; + } + } + + return 0; +} + +STATIC int +xfs_qm_endmount( + xfs_mount_t *mp, + uint needquotamount, + uint quotaflags) +{ + if (needquotamount) { + ASSERT(mp->m_qflags == 0); + mp->m_qflags = quotaflags; + if (xfs_qm_mount_quotas(mp)) + xfs_mount_reset_sbqflags(mp); + } + +#if defined(DEBUG) && defined(XFS_LOUD_RECOVERY) + if (! (XFS_IS_QUOTA_ON(mp))) + xfs_fs_cmn_err(CE_NOTE, mp, "Disk quotas not turned on"); + else + xfs_fs_cmn_err(CE_NOTE, mp, "Disk quotas turned on"); +#endif + +#ifdef QUOTADEBUG + if (XFS_IS_QUOTA_ON(mp) && xfs_qm_internalqcheck(mp)) + cmn_err(CE_WARN, "XFS: mount internalqcheck failed"); +#endif + + return 0; +} + +STATIC void +xfs_qm_dqrele_null( + xfs_dquot_t *dq) +{ + /* + * Called from XFS, where we always check first for a NULL dquot. + */ + if (!dq) + return; + xfs_qm_dqrele(dq); +} + + +struct xfs_qmops xfs_qmcore_xfs = { + .xfs_qminit = xfs_qm_newmount, + .xfs_qmdone = xfs_qm_unmount_quotadestroy, + .xfs_qmmount = xfs_qm_endmount, + .xfs_qmunmount = xfs_qm_unmount_quotas, + .xfs_dqrele = xfs_qm_dqrele_null, + .xfs_dqattach = xfs_qm_dqattach, + .xfs_dqdetach = xfs_qm_dqdetach, + .xfs_dqpurgeall = xfs_qm_dqpurge_all, + .xfs_dqvopalloc = xfs_qm_vop_dqalloc, + .xfs_dqvopcreate = xfs_qm_vop_dqattach_and_dqmod_newinode, + .xfs_dqvoprename = xfs_qm_vop_rename_dqattach, + .xfs_dqvopchown = xfs_qm_vop_chown, + .xfs_dqvopchownresv = xfs_qm_vop_chown_reserve, + .xfs_dqtrxops = &xfs_trans_dquot_ops, +}; + +struct bhv_vfsops xfs_qmops = { { + BHV_IDENTITY_INIT(VFS_BHV_QM, VFS_POSITION_QM), + .vfs_parseargs = xfs_qm_parseargs, + .vfs_showargs = xfs_qm_showargs, + .vfs_mount = xfs_qm_mount, + .vfs_sync = xfs_qm_syncall, + .vfs_quotactl = xfs_qm_quotactl, }, +}; + + +void __init +xfs_qm_init(void) +{ + static char message[] __initdata = + KERN_INFO "SGI XFS Quota Management subsystem\n"; + + printk(message); + mutex_init(&xfs_Gqm_lock, MUTEX_DEFAULT, "xfs_qmlock"); + vfs_bhv_set_custom(&xfs_qmops, &xfs_qmcore_xfs); + xfs_qm_init_procfs(); +} + +void __exit +xfs_qm_exit(void) +{ + vfs_bhv_clr_custom(&xfs_qmops); + xfs_qm_cleanup_procfs(); + if (qm_dqzone) + kmem_cache_destroy(qm_dqzone); + if (qm_dqtrxzone) + kmem_cache_destroy(qm_dqtrxzone); +} diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c new file mode 100644 index 000000000000..af0ee82189bb --- /dev/null +++ b/fs/xfs/quota/xfs_qm_stats.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU 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. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +#include <xfs.h> +#include <linux/proc_fs.h> +#include "xfs_qm.h" + +struct xqmstats xqmstats; + +STATIC int +xfs_qm_read_xfsquota( + char *buffer, + char **start, + off_t offset, + int count, + int *eof, + void *data) +{ + int len; + + /* maximum; incore; ratio free to inuse; freelist */ + len = sprintf(buffer, "%d\t%d\t%d\t%u\n", + ndquot, + xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0, + xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0, + xfs_Gqm? xfs_Gqm->qm_dqfreelist.qh_nelems : 0); + + if (offset >= len) { + *start = buffer; + *eof = 1; + return 0; + } + *start = buffer + offset; + if ((len -= offset) > count) + return count; + *eof = 1; + + return len; +} + +STATIC int +xfs_qm_read_stats( + char *buffer, + char **start, + off_t offset, + int count, + int *eof, + void *data) +{ + int len; + + /* quota performance statistics */ + len = sprintf(buffer, "qm %u %u %u %u %u %u %u %u\n", + xqmstats.xs_qm_dqreclaims, + xqmstats.xs_qm_dqreclaim_misses, + xqmstats.xs_qm_dquot_dups, + xqmstats.xs_qm_dqcachemisses, + xqmstats.xs_qm_dqcachehits, + xqmstats.xs_qm_dqwants, + xqmstats.xs_qm_dqshake_reclaims, + xqmstats.xs_qm_dqinact_reclaims); + + if (offset >= len) { + *start = buffer; + *eof = 1; + return 0; + } + *start = buffer + offset; + if ((len -= offset) > count) + return count; + *eof = 1; + + return len; +} + +void +xfs_qm_init_procfs(void) +{ + create_proc_read_entry("fs/xfs/xqmstat", 0, 0, xfs_qm_read_stats, NULL); + create_proc_read_entry("fs/xfs/xqm", 0, 0, xfs_qm_read_xfsquota, NULL); +} + +void +xfs_qm_cleanup_procfs(void) +{ + remove_proc_entry("fs/xfs/xqm", NULL); + remove_proc_entry("fs/xfs/xqmstat", NULL); +} diff --git a/fs/xfs/quota/xfs_qm_stats.h b/fs/xfs/quota/xfs_qm_stats.h new file mode 100644 index 000000000000..8093c5c284ec --- /dev/null +++ b/fs/xfs/quota/xfs_qm_stats.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2002 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU 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. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_QM_STATS_H__ +#define __XFS_QM_STATS_H__ + + +#if defined(CONFIG_PROC_FS) && !defined(XFS_STATS_OFF) + +/* + * XQM global statistics + */ +struct xqmstats { + __uint32_t xs_qm_dqreclaims; + __uint32_t xs_qm_dqreclaim_misses; + __uint32_t xs_qm_dquot_dups; + __uint32_t xs_qm_dqcachemisses; + __uint32_t xs_qm_dqcachehits; + __uint32_t xs_qm_dqwants; + __uint32_t xs_qm_dqshake_reclaims; + __uint32_t xs_qm_dqinact_reclaims; +}; + +extern struct xqmstats xqmstats; + +# define XQM_STATS_INC(count) ( (count)++ ) + +extern void xfs_qm_init_procfs(void); +extern void xfs_qm_cleanup_procfs(void); + +#else + +# define XQM_STATS_INC(count) do { } while (0) + +static __inline void xfs_qm_init_procfs(void) { }; +static __inline void xfs_qm_cleanup_procfs(void) { }; + +#endif + +#endif /* __XFS_QM_STATS_H__ */ diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 92e165dc2032..c5d4939d9b94 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -31,12 +31,12 @@ */ #include <xfs.h> -#include <xfs_quota_priv.h> +#include "xfs_qm.h" #ifdef DEBUG -# define qdprintk(s, args...) printk(s, ## args) +# define qdprintk(s, args...) cmn_err(CE_DEBUG, s, ## args) #else -# define qdprintk(s, args...) do { } while (0) +# define qdprintk(s, args...) do { } while (0) #endif STATIC int xfs_qm_scall_trunc_qfiles(xfs_mount_t *, uint); @@ -58,95 +58,123 @@ STATIC void xfs_qm_export_dquot(xfs_mount_t *, xfs_disk_dquot_t *, fs_disk_quota_t *); +/* + * The main distribution switch of all XFS quotactl system calls. + */ int -linvfs_getxstate( - struct super_block *sb, - struct fs_quota_stat *fqs) +xfs_qm_quotactl( + struct bhv_desc *bdp, + int cmd, + int id, + xfs_caddr_t addr) { - xfs_mount_t *mp; - vfs_t *vfsp; + xfs_mount_t *mp; + int error; + struct vfs *vfsp; - vfsp = LINVFS_GET_VFS(sb); - mp = XFS_BHVTOM(vfsp->vfs_fbhv); - return -xfs_qm_scall_getqstat(mp, fqs); -} + vfsp = bhvtovfs(bdp); + mp = XFS_VFSTOM(vfsp); -int -linvfs_setxstate( - struct super_block *sb, - unsigned int flags, - int op) -{ - xfs_mount_t *mp; - vfs_t *vfsp; - uint qflags; - - vfsp = LINVFS_GET_VFS(sb); - mp = XFS_BHVTOM(vfsp->vfs_fbhv); - if (vfsp->vfs_flag & VFS_RDONLY) - return -EROFS; - - switch (op) { - case Q_XQUOTARM: - if (XFS_IS_QUOTA_ON(mp)) { - qdprintk("cannot remove, quota on: flags=%x\n", flags); - return -EINVAL; - } - qflags = xfs_qm_import_qtype_flags(flags); - return -xfs_qm_scall_trunc_qfiles(mp, qflags); - case Q_XQUOTAON: - qflags = xfs_qm_import_flags(flags); - return -xfs_qm_scall_quotaon(mp, qflags); - case Q_XQUOTAOFF: - qflags = xfs_qm_import_flags(flags); - if (!XFS_IS_QUOTA_ON(mp)) - return -ESRCH; - return -xfs_qm_scall_quotaoff(mp, qflags, B_FALSE); + if (addr == NULL && cmd != Q_SYNC) + return XFS_ERROR(EINVAL); + if (id < 0 && cmd != Q_SYNC) + return XFS_ERROR(EINVAL); + + /* + * The following commands are valid even when quotaoff. + */ + switch (cmd) { + /* + * truncate quota files. quota must be off. + */ + case Q_XQUOTARM: + if (XFS_IS_QUOTA_ON(mp) || addr == NULL) + return XFS_ERROR(EINVAL); + if (vfsp->vfs_flag & VFS_RDONLY) + return XFS_ERROR(EROFS); + return (xfs_qm_scall_trunc_qfiles(mp, + xfs_qm_import_qtype_flags(*(uint *)addr))); + /* + * Get quota status information. + */ + case Q_XGETQSTAT: + return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr)); + + /* + * QUOTAON for root f/s and quota enforcement on others.. + * Quota accounting for non-root f/s's must be turned on + * at mount time. + */ + case Q_XQUOTAON: + if (addr == NULL) + return XFS_ERROR(EINVAL); + if (vfsp->vfs_flag & VFS_RDONLY) + return XFS_ERROR(EROFS); + return (xfs_qm_scall_quotaon(mp, + xfs_qm_import_flags(*(uint *)addr))); + case Q_XQUOTAOFF: + if (vfsp->vfs_flag & VFS_RDONLY) + return XFS_ERROR(EROFS); + break; + + default: + break; } - qdprintk("cannot set state, invalid op: op=%x flags=%x\n", op, flags); - return -EINVAL; -} -int -linvfs_getxquota( - struct super_block *sb, - int type, - qid_t id, - struct fs_disk_quota *fdq) -{ - xfs_mount_t *mp; - vfs_t *vfsp; - int qtype; - - vfsp = LINVFS_GET_VFS(sb); - mp = XFS_BHVTOM(vfsp->vfs_fbhv); - if (!XFS_IS_QUOTA_ON(mp)) - return -ESRCH; - qtype = (type == GRPQUOTA)? XFS_DQ_GROUP : XFS_DQ_USER; - return -xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, qtype, fdq); -} + if (! XFS_IS_QUOTA_ON(mp)) + return XFS_ERROR(ESRCH); -int -linvfs_setxquota( - struct super_block *sb, - int type, - qid_t id, - struct fs_disk_quota *fdq) -{ - xfs_mount_t *mp; - vfs_t *vfsp; - int qtype; - - vfsp = LINVFS_GET_VFS(sb); - mp = XFS_BHVTOM(vfsp->vfs_fbhv); - if (!XFS_IS_QUOTA_ON(mp)) - return -ESRCH; - if (vfsp->vfs_flag & VFS_RDONLY) - return -EROFS; - qtype = (type == GRPQUOTA)? XFS_DQ_GROUP : XFS_DQ_USER; - return xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, qtype, fdq); -} + switch (cmd) { + case Q_XQUOTAOFF: + if (vfsp->vfs_flag & VFS_RDONLY) + return XFS_ERROR(EROFS); + error = xfs_qm_scall_quotaoff(mp, + xfs_qm_import_flags(*(uint *)addr), + B_FALSE); + break; + + /* + * Defaults to XFS_GETUQUOTA. + */ + case Q_XGETQUOTA: + error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER, + (fs_disk_quota_t *)addr); + break; + /* + * Set limits, both hard and soft. Defaults to Q_SETUQLIM. + */ + case Q_XSETQLIM: + if (vfsp->vfs_flag & VFS_RDONLY) + return XFS_ERROR(EROFS); + error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER, + (fs_disk_quota_t *)addr); + break; + + case Q_XSETGQLIM: + if (vfsp->vfs_flag & VFS_RDONLY) + return XFS_ERROR(EROFS); + error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, + (fs_disk_quota_t *)addr); + break; + + + case Q_XGETGQUOTA: + error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, + (fs_disk_quota_t *)addr); + break; + /* + * Quotas are entirely undefined after quotaoff in XFS quotas. + * For instance, there's no way to set limits when quotaoff. + */ + + default: + error = XFS_ERROR(EINVAL); + break; + } + + return (error); +} /* * Turn off quota accounting and/or enforcement for all udquots and/or @@ -487,6 +515,7 @@ xfs_qm_scall_getqstat( out->qs_pad = 0; out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino; out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino; + if (mp->m_quotainfo) { uip = mp->m_quotainfo->qi_uquotaip; gip = mp->m_quotainfo->qi_gquotaip; @@ -1048,10 +1077,10 @@ mutex_t qcheck_lock; #define DQTEST_LIST_PRINT(l, NXT, title) \ { \ xfs_dqtest_t *dqp; int i = 0;\ - printk("%s (#%d)\n", title, (int) (l)->qh_nelems); \ + cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \ for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \ dqp = (xfs_dqtest_t *)dqp->NXT) { \ - printk("\t%d\.\t\"%d (%s)\"\t bcnt = %d, icnt = %d\n", \ + cmn_err(CE_DEBUG, " %d\. \"%d (%s)\" bcnt = %d, icnt = %d", \ ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp), \ dqp->d_bcount, dqp->d_icount); } \ } @@ -1081,13 +1110,15 @@ STATIC void xfs_qm_dqtest_print( xfs_dqtest_t *d) { - printk("-----------DQTEST DQUOT----------------\n"); - printk("---- dquot ID = %d\n", d->d_id); - printk("---- type = %s\n", XFS_QM_ISUDQ(d) ? "USR" : "GRP"); - printk("---- fs = 0x%p\n", d->q_mount); - printk("---- bcount = %Lu (0x%x)\n", d->d_bcount, (int)d->d_bcount); - printk("---- icount = %Lu (0x%x)\n", d->d_icount, (int)d->d_icount); - printk("---------------------------\n"); + cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------"); + cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id); + cmn_err(CE_DEBUG, "---- type = %s", XFS_QM_ISUDQ(d)? "USR" : "GRP"); + cmn_err(CE_DEBUG, "---- fs = 0x%p", d->q_mount); + cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)", + d->d_bcount, (int)d->d_bcount); + cmn_err(CE_DEBUG, "---- icount = %Lu (0x%x)", + d->d_icount, (int)d->d_icount); + cmn_err(CE_DEBUG, "---------------------------"); } STATIC void @@ -1101,10 +1132,10 @@ xfs_qm_dqtest_failed( { qmtest_nfails++; if (error) - printk("quotacheck failed for %d, error = %d\nreason = %s\n", + cmn_err(CE_DEBUG, "quotacheck failed id=%d, err=%d\nreason: %s", INT_GET(d->d_id, ARCH_CONVERT), error, reason); else - printk("quotacheck failed for %d (%s) [%d != %d]\n", + cmn_err(CE_DEBUG, "quotacheck failed id=%d (%s) [%d != %d]", INT_GET(d->d_id, ARCH_CONVERT), reason, (int)a, (int)b); xfs_qm_dqtest_print(d); if (dqp) @@ -1119,36 +1150,42 @@ xfs_dqtest_cmp2( int err = 0; if (INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) != d->d_icount) { xfs_qm_dqtest_failed(d, dqp, "icount mismatch", - INT_GET(dqp->q_core.d_icount, ARCH_CONVERT), d->d_icount, 0); + INT_GET(dqp->q_core.d_icount, ARCH_CONVERT), + d->d_icount, 0); err++; } if (INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT) != d->d_bcount) { xfs_qm_dqtest_failed(d, dqp, "bcount mismatch", - INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT), d->d_bcount, 0); + INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT), + d->d_bcount, 0); err++; } if (INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT) && - INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT) >= INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT)) { + INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT) >= + INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT)) { if (INT_ISZERO(dqp->q_core.d_btimer, ARCH_CONVERT) && !INT_ISZERO(dqp->q_core.d_id, ARCH_CONVERT)) { - printk("%d [%s] [0x%p] BLK TIMER NOT STARTED\n", - d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount); + cmn_err(CE_DEBUG, + "%d [%s] [0x%p] BLK TIMER NOT STARTED", + d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount); err++; } } if (INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT) && - INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)) { + INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= + INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)) { if (INT_ISZERO(dqp->q_core.d_itimer, ARCH_CONVERT) && !INT_ISZERO(dqp->q_core.d_id, ARCH_CONVERT)) { - printk("%d [%s] [0x%p] INO TIMER NOT STARTED\n", - d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount); + cmn_err(CE_DEBUG, + "%d [%s] [0x%p] INO TIMER NOT STARTED", + d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount); err++; } } -#if 0 +#ifdef QUOTADEBUG if (!err) { - printk("%d [%s] [0x%p] qchecked\n", - d->d_id, XFS_QM_ISUDQ(d) ? "USR" : "GRP", d->q_mount); + cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked", + d->d_id, XFS_QM_ISUDQ(d) ? "USR" : "GRP", d->q_mount); } #endif return (err); @@ -1338,10 +1375,9 @@ xfs_qm_internalqcheck( } } while (! done); if (error) { - printk("Bulkstat returned error 0x%x\n", - error); + cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error); } - printk("Checking results against system dquots\n"); + cmn_err(CE_DEBUG, "Checking results against system dquots"); for (i = 0; i < qmtest_hashmask; i++) { h1 = &qmtest_udqtab[i]; for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) { @@ -1360,10 +1396,10 @@ xfs_qm_internalqcheck( } if (qmtest_nfails) { - printk("************** quotacheck failed **************\n"); - printk("failures = %d\n", qmtest_nfails); + cmn_err(CE_DEBUG, "******** quotacheck failed ********"); + cmn_err(CE_DEBUG, "failures = %d", qmtest_nfails); } else { - printk("************** quotacheck successful! **************\n"); + cmn_err(CE_DEBUG, "******** quotacheck successful! ********"); } kmem_free(qmtest_udqtab, qmtest_hashmask * sizeof(xfs_dqhash_t)); kmem_free(qmtest_gdqtab, qmtest_hashmask * sizeof(xfs_dqhash_t)); diff --git a/fs/xfs/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h index d016d2b6cf8a..eeda93a2b951 100644 --- a/fs/xfs/xfs_quota_priv.h +++ b/fs/xfs/quota/xfs_quota_priv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -67,8 +67,8 @@ #define XQMLCK(h) (mutex_lock(&((h)->qh_lock), PINOD)) #define XQMUNLCK(h) (mutex_unlock(&((h)->qh_lock))) #ifdef DEBUG -static inline int -XQMISLCKD(xfs_dqhash_t *h) +struct xfs_dqhash; +static inline int XQMISLCKD(struct xfs_dqhash *h) { if (mutex_trylock(&h->qh_lock)) { mutex_unlock(&h->qh_lock); diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c index 19c83f9d4700..bf91133c9ae4 100644 --- a/fs/xfs/xfs_trans_dquot.c +++ b/fs/xfs/quota/xfs_trans_dquot.c @@ -31,8 +31,9 @@ */ #include <xfs.h> -#include <xfs_quota_priv.h> +#include "xfs_qm.h" +STATIC void xfs_trans_alloc_dqinfo(xfs_trans_t *); /* * Add the locked dquot to the transaction. @@ -95,7 +96,7 @@ xfs_trans_log_dquot( * Carry forward whatever is left of the quota blk reservation to * the spanky new transaction */ -void +STATIC void xfs_trans_dup_dqinfo( xfs_trans_t *otp, xfs_trans_t *ntp) @@ -104,6 +105,9 @@ xfs_trans_dup_dqinfo( int i,j; xfs_dqtrx_t *oqa, *nqa; + if (!otp->t_dqinfo) + return; + xfs_trans_alloc_dqinfo(ntp); oqa = otp->t_dqinfo->dqa_usrdquots; nqa = ntp->t_dqinfo->dqa_usrdquots; @@ -155,15 +159,23 @@ xfs_trans_mod_dquot_byino( uint field, long delta) { + xfs_mount_t *mp; + ASSERT(tp); + mp = tp->t_mountp; + + if (!XFS_IS_QUOTA_ON(mp) || + ip->i_ino == mp->m_sb.sb_uquotino || + ip->i_ino == mp->m_sb.sb_gquotino) + return; if (tp->t_dqinfo == NULL) xfs_trans_alloc_dqinfo(tp); - if (XFS_IS_UQUOTA_ON(tp->t_mountp) && ip->i_udquot) { + if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) { (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta); } - if (XFS_IS_GQUOTA_ON(tp->t_mountp) && ip->i_gdquot) { + if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot) { (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta); } } @@ -318,7 +330,7 @@ xfs_trans_dqlockedjoin( * xfs_trans_apply_sb_deltas(). * Go thru all the dquots belonging to this transaction and modify the * INCORE dquot to reflect the actual usages. - * Unreserve just the reservations done by this transaction + * Unreserve just the reservations done by this transaction. * dquot is still left locked at exit. */ void @@ -332,6 +344,9 @@ xfs_trans_apply_dquot_deltas( long totalbdelta; long totalrtbdelta; + if (! (tp->t_flags & XFS_TRANS_DQ_DIRTY)) + return; + ASSERT(tp->t_dqinfo); qa = tp->t_dqinfo->dqa_usrdquots; for (j = 0; j < 2; j++) { @@ -481,13 +496,15 @@ xfs_trans_apply_dquot_deltas( #ifdef QUOTADEBUG if (qtrx->qt_rtblk_res != 0) - printk("RT res %d for 0x%p\n", - (int) qtrx->qt_rtblk_res, - dqp); + cmn_err(CE_DEBUG, "RT res %d for 0x%p\n", + (int) qtrx->qt_rtblk_res, dqp); #endif - ASSERT(dqp->q_res_bcount >= INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT)); - ASSERT(dqp->q_res_icount >= INT_GET(dqp->q_core.d_icount, ARCH_CONVERT)); - ASSERT(dqp->q_res_rtbcount >= INT_GET(dqp->q_core.d_rtbcount, ARCH_CONVERT)); + ASSERT(dqp->q_res_bcount >= + INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT)); + ASSERT(dqp->q_res_icount >= + INT_GET(dqp->q_core.d_icount, ARCH_CONVERT)); + ASSERT(dqp->q_res_rtbcount >= + INT_GET(dqp->q_core.d_rtbcount, ARCH_CONVERT)); } /* * Do the group quotas next @@ -503,16 +520,18 @@ xfs_trans_apply_dquot_deltas( * we simply throw those away, since that's the expected behavior * when a transaction is curtailed without a commit. */ -void +STATIC void xfs_trans_unreserve_and_mod_dquots( - xfs_trans_t *tp) + xfs_trans_t *tp) { int i, j; xfs_dquot_t *dqp; xfs_dqtrx_t *qtrx, *qa; boolean_t locked; - ASSERT(tp->t_dqinfo); + if (!tp->t_dqinfo || !(tp->t_flags & XFS_TRANS_DQ_DIRTY)) + return; + qa = tp->t_dqinfo->dqa_usrdquots; for (j = 0; j < 2; j++) { @@ -604,8 +623,8 @@ xfs_trans_dqresv( !INT_ISZERO(dqp->q_core.d_id, ARCH_CONVERT) && XFS_IS_QUOTA_ENFORCED(dqp->q_mount)) { #ifdef QUOTADEBUG - printk("BLK Res: nblks=%ld + resbcount=%Ld > hardlimit=%Ld?\n", - nblks, *resbcountp, hardlimit); + cmn_err(CE_DEBUG, "BLK Res: nblks=%ld + resbcount=%Ld" + " > hardlimit=%Ld?", nblks, *resbcountp, hardlimit); #endif if (nblks > 0) { /* @@ -713,6 +732,7 @@ error_return: int xfs_trans_reserve_quota_bydquots( xfs_trans_t *tp, + xfs_mount_t *mp, xfs_dquot_t *udqp, xfs_dquot_t *gdqp, long nblks, @@ -721,6 +741,9 @@ xfs_trans_reserve_quota_bydquots( { int resvd; + if (! XFS_IS_QUOTA_ON(mp)) + return (0); + if (tp && tp->t_dqinfo == NULL) xfs_trans_alloc_dqinfo(tp); @@ -760,15 +783,22 @@ xfs_trans_reserve_quota_bydquots( * * Returns 0 on success, EDQUOT or other errors otherwise */ -int +STATIC int xfs_trans_reserve_quota_nblks( xfs_trans_t *tp, + xfs_mount_t *mp, xfs_inode_t *ip, long nblks, long ninos, uint type) { - int error; + int error; + + if (!XFS_IS_QUOTA_ON(mp)) + return (0); + + ASSERT(ip->i_ino != mp->m_sb.sb_uquotino); + ASSERT(ip->i_ino != mp->m_sb.sb_gquotino); #ifdef QUOTADEBUG if (ip->i_udquot) @@ -785,7 +815,7 @@ xfs_trans_reserve_quota_nblks( /* * Reserve nblks against these dquots, with trans as the mediator. */ - error = xfs_trans_reserve_quota_bydquots(tp, + error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot, ip->i_gdquot, nblks, ninos, type); @@ -836,17 +866,29 @@ xfs_trans_log_quotaoff_item( lidp->lid_flags |= XFS_LID_DIRTY; } -void +STATIC void xfs_trans_alloc_dqinfo( xfs_trans_t *tp) { (tp)->t_dqinfo = kmem_zone_zalloc(xfs_Gqm->qm_dqtrxzone, KM_SLEEP); } -void +STATIC void xfs_trans_free_dqinfo( xfs_trans_t *tp) { + if (!tp->t_dqinfo) + return; kmem_zone_free(xfs_Gqm->qm_dqtrxzone, (tp)->t_dqinfo); (tp)->t_dqinfo = NULL; } + +xfs_dqtrxops_t xfs_trans_dquot_ops = { + .qo_dup_dqinfo = xfs_trans_dup_dqinfo, + .qo_free_dqinfo = xfs_trans_free_dqinfo, + .qo_mod_dquot_byino = xfs_trans_mod_dquot_byino, + .qo_apply_dquot_deltas = xfs_trans_apply_dquot_deltas, + .qo_reserve_quota_nblks = xfs_trans_reserve_quota_nblks, + .qo_reserve_quota_bydquots = xfs_trans_reserve_quota_bydquots, + .qo_unreserve_and_mod_dquots = xfs_trans_unreserve_and_mod_dquots, +}; diff --git a/fs/xfs/support/atomic.h b/fs/xfs/support/atomic.h index 1cf5eecbf4fe..ac7705d2f5f9 100644 --- a/fs/xfs/support/atomic.h +++ b/fs/xfs/support/atomic.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -43,20 +43,20 @@ * This is used for two variables in XFS, one of which is a debug trace * buffer index. They are not accessed via any other atomic operations * so this is safe. All other atomic increments and decrements in XFS - * now use the linux built in functions. + * now use the Linux built-in functions. */ -extern spinlock_t Atomic_spin; +extern spinlock_t xfs_atomic_spin; static __inline__ int atomicIncWithWrap(int *ip, int val) { unsigned long flags; int ret; - spin_lock_irqsave(&Atomic_spin, flags); + spin_lock_irqsave(&xfs_atomic_spin, flags); ret = *ip; (*ip)++; if (*ip == val) *ip = 0; - spin_unlock_irqrestore(&Atomic_spin, flags); + spin_unlock_irqrestore(&xfs_atomic_spin, flags); return ret; } diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index 59c57fe26f83..cb0aa47974f3 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -55,7 +55,7 @@ assfail(char *a, char *f, int l) BUG(); } -#if (defined(DEBUG) || defined(INDUCE_IO_ERRROR)) +#if ((defined(DEBUG) || defined(INDUCE_IO_ERRROR)) && !defined(NO_WANT_RANDOM)) unsigned long random(void) @@ -79,7 +79,7 @@ get_thread_id(void) return current->pid; } -#endif /* DEBUG */ +#endif /* DEBUG || INDUCE_IO_ERRROR || !NO_WANT_RANDOM */ void cmn_err(register int level, char *fmt, ...) diff --git a/fs/xfs/support/mrlock.c b/fs/xfs/support/mrlock.c index 1558a8e56be1..0a9b36fe8203 100644 --- a/fs/xfs/support/mrlock.c +++ b/fs/xfs/support/mrlock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -272,15 +272,3 @@ mrdemote(mrlock_t *mrp) } MRUNLOCK(mrp); } - -int -mrislocked_access(mrlock_t *mrp) -{ - return(mrp->mr_count > 0); -} - -int -mrislocked_update(mrlock_t *mrp) -{ - return(mrp->mr_count < 0); -} diff --git a/fs/xfs/support/mrlock.h b/fs/xfs/support/mrlock.h index 7004e23b31e8..5f8d7c592075 100644 --- a/fs/xfs/support/mrlock.h +++ b/fs/xfs/support/mrlock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -80,7 +80,9 @@ extern void mrlock_init(mrlock_t *, int type, char *name, long sequence); extern void mrfree(mrlock_t *); #define mrinit(mrp, name) mrlock_init(mrp, MRLOCK_BARRIER, name, -1) -#define mraccess(mrp) mraccessf(mrp, 0) /* grab for READ/ACCESS */ -#define mrupdate(mrp) mrupdatef(mrp, 0) /* grab for WRITE/UPDATE */ +#define mraccess(mrp) mraccessf(mrp, 0) /* grab for READ/ACCESS */ +#define mrupdate(mrp) mrupdatef(mrp, 0) /* grab for WRITE/UPDATE */ +#define mrislocked_access(mrp) ((mrp)->mr_count > 0) +#define mrislocked_update(mrp) ((mrp)->mr_count < 0) #endif /* __XFS_SUPPORT_MRLOCK_H__ */ diff --git a/fs/xfs/support/mutex.h b/fs/xfs/support/mutex.h index 346b2d663a08..98bf753e24c8 100644 --- a/fs/xfs/support/mutex.h +++ b/fs/xfs/support/mutex.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * Portions Copyright (c) 2002 Christoph Hellwig. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it @@ -46,7 +46,6 @@ typedef struct semaphore mutex_t; #define mutex_init(lock, type, name) sema_init(lock, 1) -#define init_mutex(ptr, type, name, sequence) sema_init(lock, 1) #define mutex_destroy(lock) sema_init(lock, -99) #define mutex_lock(lock, num) down(lock) #define mutex_trylock(lock) (down_trylock(lock) ? 0 : 1) diff --git a/fs/xfs/support/time.h b/fs/xfs/support/time.h index 46b2132cee37..f4c23f80ca5c 100644 --- a/fs/xfs/support/time.h +++ b/fs/xfs/support/time.h @@ -45,11 +45,7 @@ static inline void delay(long ticks) static inline void nanotime(struct timespec *tvp) { - struct timeval tv; - - do_gettimeofday(&tv); - tvp->tv_sec = tv.tv_sec; - tvp->tv_nsec = tv.tv_usec * 1000; + *tvp = CURRENT_TIME; } #endif /* __XFS_SUPPORT_TIME_H__ */ diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h index eb5370140f53..0c869d102fd0 100644 --- a/fs/xfs/xfs.h +++ b/fs/xfs/xfs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -66,6 +66,9 @@ #include <xfs_dir.h> #include <xfs_dir2.h> #include <xfs_imap.h> +#include <xfs_alloc.h> +#include <xfs_dmapi.h> +#include <xfs_quota.h> #include <xfs_mount.h> #include <xfs_alloc_btree.h> #include <xfs_bmap_btree.h> @@ -77,17 +80,11 @@ #include <xfs_dir2_sf.h> #include <xfs_dinode.h> #include <xfs_inode.h> -#include <xfs_alloc.h> #include <xfs_bmap.h> #include <xfs_bit.h> #include <xfs_rtalloc.h> #include <xfs_error.h> -#include <xfs_quota.h> #include <xfs_itable.h> -#include <xfs_dqblk.h> -#include <xfs_dquot_item.h> -#include <xfs_dquot.h> -#include <xfs_qm.h> #include <xfs_rw.h> #include <xfs_da_btree.h> #include <xfs_dir_leaf.h> @@ -108,6 +105,5 @@ #include <xfs_trans_priv.h> #include <xfs_trans_space.h> #include <xfs_utils.h> -#include <xfs_dmapi.h> #endif /* __XFS_H__ */ diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index aeebe527657c..9035b4796c3f 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -197,10 +197,8 @@ xfs_attr_set(bhv_desc_t *bdp, char *name, char *value, int valuelen, int flags, /* * Attach the dquots to the inode. */ - if (XFS_IS_QUOTA_ON(mp)) { - if ((error = xfs_qm_dqattach(dp, 0))) - return (error); - } + if ((error = XFS_QM_DQATTACH(mp, dp, 0))) + return (error); /* * If the inode doesn't have an attribute fork, add one. @@ -280,19 +278,13 @@ xfs_attr_set(bhv_desc_t *bdp, char *name, char *value, int valuelen, int flags, } xfs_ilock(dp, XFS_ILOCK_EXCL); - if (XFS_IS_QUOTA_ON(mp)) { - if (rsvd) { - error = xfs_trans_reserve_blkquota_force(args.trans, - dp, nblks); - } else { - error = xfs_trans_reserve_blkquota(args.trans, - dp, nblks); - } - if (error) { - xfs_iunlock(dp, XFS_ILOCK_EXCL); - xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); - return (error); - } + error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, nblks, 0, + rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : + XFS_QMOPT_RES_REGBLKS); + if (error) { + xfs_iunlock(dp, XFS_ILOCK_EXCL); + xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); + return (error); } xfs_trans_ijoin(args.trans, dp, XFS_ILOCK_EXCL); @@ -483,12 +475,9 @@ xfs_attr_remove(bhv_desc_t *bdp, char *name, int flags, struct cred *cred) /* * Attach the dquots to the inode. */ - if (XFS_IS_QUOTA_ON(mp)) { - if (XFS_NOT_DQATTACHED(mp, dp)) { - if ((error = xfs_qm_dqattach(dp, 0))) - return (error); - } - } + if ((error = XFS_QM_DQATTACH(mp, dp, 0))) + return (error); + /* * Start our first transaction of the day. * diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 344a52aa9fcd..2f742c82c2d6 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2145,7 +2145,7 @@ xfs_bmap_alloc( */ mp = ap->ip->i_mount; nullfb = ap->firstblock == NULLFSBLOCK; - rt = (ap->ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && ap->userdata; + rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata; fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); #ifdef __KERNEL__ if (rt) { @@ -2467,14 +2467,10 @@ xfs_bmap_alloc( * Adjust the disk quota also. This was reserved * earlier. */ - if (XFS_IS_QUOTA_ON(mp) && - ap->ip->i_ino != mp->m_sb.sb_uquotino && - ap->ip->i_ino != mp->m_sb.sb_gquotino) - xfs_trans_mod_dquot_byino(ap->tp, ap->ip, - ap->wasdel ? - XFS_TRANS_DQ_DELRTBCOUNT : + XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip, + ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT : XFS_TRANS_DQ_RTBCOUNT, - (long)ralen); + (long) ralen); } else ap->alen = 0; #endif /* __KERNEL__ */ @@ -2691,14 +2687,10 @@ xfs_bmap_alloc( * Adjust the disk quota also. This was reserved * earlier. */ - if (XFS_IS_QUOTA_ON(mp) && - ap->ip->i_ino != mp->m_sb.sb_uquotino && - ap->ip->i_ino != mp->m_sb.sb_gquotino) - xfs_trans_mod_dquot_byino(ap->tp, ap->ip, - ap->wasdel ? - XFS_TRANS_DQ_DELBCOUNT : + XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip, + ap->wasdel ? XFS_TRANS_DQ_DELBCOUNT : XFS_TRANS_DQ_BCOUNT, - (long)args.len); + (long) args.len); } else { ap->rval = NULLFSBLOCK; ap->alen = 0; @@ -2755,10 +2747,7 @@ xfs_bmap_btree_to_extents( return error; xfs_bmap_add_free(cbno, 1, cur->bc_private.b.flist, mp); ip->i_d.di_nblocks--; - if (XFS_IS_QUOTA_ON(mp) && - ip->i_ino != mp->m_sb.sb_uquotino && - ip->i_ino != mp->m_sb.sb_gquotino) - xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); + XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); xfs_trans_binval(tp, cbp); if (cur->bc_bufs[0] == cbp) cur->bc_bufs[0] = NULL; @@ -2854,10 +2843,7 @@ xfs_bmap_del_extent( goto done; do_fx = 0; nblks = len * mp->m_sb.sb_rextsize; - if (XFS_IS_QUOTA_ON(mp) && - ip->i_ino != mp->m_sb.sb_uquotino && - ip->i_ino != mp->m_sb.sb_gquotino) - qfield = XFS_TRANS_DQ_RTBCOUNT; + qfield = XFS_TRANS_DQ_RTBCOUNT; } /* * Ordinary allocation. @@ -2865,10 +2851,7 @@ xfs_bmap_del_extent( else { do_fx = 1; nblks = del->br_blockcount; - if (XFS_IS_QUOTA_ON(mp) && - ip->i_ino != mp->m_sb.sb_uquotino && - ip->i_ino != mp->m_sb.sb_gquotino) - qfield = XFS_TRANS_DQ_BCOUNT; + qfield = XFS_TRANS_DQ_BCOUNT; } /* * Set up del_endblock and cur for later. @@ -3088,7 +3071,8 @@ xfs_bmap_del_extent( * Adjust quota data. */ if (qfield) - xfs_trans_mod_dquot_byino(tp, ip, qfield, (long)-nblks); + XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, qfield, (long)-nblks); + /* * Account for change in delayed indirect blocks. * Nothing to do for disk quota accounting here. @@ -3239,10 +3223,7 @@ xfs_bmap_extents_to_btree( *firstblock = cur->bc_private.b.firstblock = args.fsbno; cur->bc_private.b.allocated++; ip->i_d.di_nblocks++; - if (XFS_IS_QUOTA_ON(mp) && - ip->i_ino != mp->m_sb.sb_uquotino && - ip->i_ino != mp->m_sb.sb_gquotino) - xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L); + XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_BCOUNT, 1L); abp = xfs_btree_get_bufl(mp, tp, args.fsbno, 0); /* * Fill in the child block. @@ -3385,11 +3366,8 @@ xfs_bmap_local_to_extents( xfs_bmap_trace_post_update(fname, "new", ip, 0, whichfork); XFS_IFORK_NEXT_SET(ip, whichfork, 1); ip->i_d.di_nblocks = 1; - if (XFS_IS_QUOTA_ON(args.mp) && - ip->i_ino != args.mp->m_sb.sb_uquotino && - ip->i_ino != args.mp->m_sb.sb_gquotino) - xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, - 1L); + XFS_TRANS_MOD_DQUOT_BYINO(args.mp, tp, ip, + XFS_TRANS_DQ_BCOUNT, 1L); flags |= XFS_ILOG_FEXT(whichfork); } else ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0); @@ -3772,18 +3750,13 @@ xfs_bmap_add_attrfork( XFS_TRANS_PERM_LOG_RES, XFS_ADDAFORK_LOG_COUNT))) goto error0; xfs_ilock(ip, XFS_ILOCK_EXCL); - if (XFS_IS_QUOTA_ON(mp)) { - if (rsvd) { - error = xfs_trans_reserve_blkquota_force(tp, ip, blks); - } else { - error = xfs_trans_reserve_blkquota(tp, ip, blks); - } - - if (error) { - xfs_iunlock(ip, XFS_ILOCK_EXCL); - xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES); - return error; - } + error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, blks, 0, rsvd ? + XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : + XFS_QMOPT_RES_REGBLKS); + if (error) { + xfs_iunlock(ip, XFS_ILOCK_EXCL); + xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES); + return error; } if (XFS_IFORK_Q(ip)) goto error1; @@ -4655,8 +4628,8 @@ xfs_bmapi( cur = NULL; if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { ASSERT(wr && tp); - if ((error = xfs_bmap_local_to_extents(tp, ip, firstblock, total, - &logflags, whichfork))) + if ((error = xfs_bmap_local_to_extents(tp, ip, + firstblock, total, &logflags, whichfork))) goto error0; } if (wr && *firstblock == NULLFSBLOCK) { @@ -4730,9 +4703,8 @@ xfs_bmapi( * We return EDQUOT if we haven't allocated * blks already inside this loop; */ - if (XFS_IS_QUOTA_ON(ip->i_mount) && - xfs_trans_reserve_blkquota(NULL, ip, - (long)alen)) { + if (XFS_TRANS_RESERVE_BLKQUOTA( + mp, NULL, ip, (long)alen)) { if (n == 0) { *nmap = 0; ASSERT(cur == NULL); @@ -4740,12 +4712,10 @@ xfs_bmapi( } break; } - if (xfs_mod_incore_sb(ip->i_mount, - XFS_SBS_FDBLOCKS, + if (xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, -(alen + indlen), rsvd)) { - if (XFS_IS_QUOTA_ON(ip->i_mount)) - xfs_trans_unreserve_blkquota( - NULL, ip, (long)alen); + XFS_TRANS_UNRESERVE_BLKQUOTA( + mp, NULL, ip, (long)alen); break; } ip->i_delayed_blks += alen; @@ -4808,15 +4778,11 @@ xfs_bmapi( alen = bma.alen; aoff = bma.off; ASSERT(*firstblock == NULLFSBLOCK || - XFS_FSB_TO_AGNO(ip->i_mount, - *firstblock) == - XFS_FSB_TO_AGNO(ip->i_mount, - bma.firstblock) || + XFS_FSB_TO_AGNO(mp, *firstblock) == + XFS_FSB_TO_AGNO(mp, bma.firstblock) || (flist->xbf_low && - XFS_FSB_TO_AGNO(ip->i_mount, - *firstblock) < - XFS_FSB_TO_AGNO(ip->i_mount, - bma.firstblock))); + XFS_FSB_TO_AGNO(mp, *firstblock) < + XFS_FSB_TO_AGNO(mp, bma.firstblock))); *firstblock = bma.firstblock; if (cur) cur->bc_private.b.firstblock = @@ -4824,7 +4790,7 @@ xfs_bmapi( if (abno == NULLFSBLOCK) break; if ((ifp->if_flags & XFS_IFBROOT) && !cur) { - cur = xfs_btree_init_cursor(ip->i_mount, + cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip, whichfork); cur->bc_private.b.firstblock = @@ -4941,7 +4907,7 @@ xfs_bmapi( */ ASSERT(mval->br_blockcount <= len); if ((ifp->if_flags & XFS_IFBROOT) && !cur) { - cur = xfs_btree_init_cursor(ip->i_mount, + cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip, whichfork); cur->bc_private.b.firstblock = @@ -5063,12 +5029,12 @@ error0: if (cur) { if (!error) { ASSERT(*firstblock == NULLFSBLOCK || - XFS_FSB_TO_AGNO(ip->i_mount, *firstblock) == - XFS_FSB_TO_AGNO(ip->i_mount, + XFS_FSB_TO_AGNO(mp, *firstblock) == + XFS_FSB_TO_AGNO(mp, cur->bc_private.b.firstblock) || (flist->xbf_low && - XFS_FSB_TO_AGNO(ip->i_mount, *firstblock) < - XFS_FSB_TO_AGNO(ip->i_mount, + XFS_FSB_TO_AGNO(mp, *firstblock) < + XFS_FSB_TO_AGNO(mp, cur->bc_private.b.firstblock))); *firstblock = cur->bc_private.b.firstblock; } @@ -5378,16 +5344,11 @@ xfs_bunmapi( ASSERT(STARTBLOCKVAL(del.br_startblock) > 0); xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int)del.br_blockcount, rsvd); - if (XFS_IS_QUOTA_ON(ip->i_mount)) { - ASSERT(ip->i_ino != mp->m_sb.sb_uquotino); - ASSERT(ip->i_ino != mp->m_sb.sb_gquotino); - if (!isrt) - xfs_trans_unreserve_blkquota(NULL, ip, - (long)del.br_blockcount); - else - xfs_trans_unreserve_rtblkquota(NULL, ip, - (long)del.br_blockcount); - } + /* Unreserve our quota space */ + XFS_TRANS_RESERVE_QUOTA_NBLKS( + mp, NULL, ip, -((long)del.br_blockcount), 0, + isrt ? XFS_QMOPT_RES_RTBLKS : + XFS_QMOPT_RES_REGBLKS); ip->i_delayed_blks -= del.br_blockcount; if (cur) cur->bc_private.b.flags |= @@ -5556,8 +5517,7 @@ xfs_getbmap( && DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && whichfork == XFS_DATA_FORK) { - error = xfs_dm_send_data_event(DM_EVENT_READ, bdp, - 0, 0, 0, NULL); + error = XFS_SEND_DATA(mp, DM_EVENT_READ, bdp, 0, 0, 0, NULL); if (error) return XFS_ERROR(error); } @@ -5579,7 +5539,6 @@ xfs_getbmap( ip->i_d.di_format != XFS_DINODE_FMT_BTREE && ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) return XFS_ERROR(EINVAL); - if (whichfork == XFS_DATA_FORK) { if (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC) { prealloced = 1; @@ -5928,10 +5887,13 @@ xfs_check_block( thispa = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block, j, dmxr); } - if (INT_GET(*thispa, ARCH_CONVERT) == INT_GET(*pp, ARCH_CONVERT)) { - printk("xfs_check_block: thispa(%d) == pp(%d) %Ld\n", - j, i, INT_GET(*thispa, ARCH_CONVERT)); - panic("xfs_check_block: ptrs are equal in node\n"); + if (INT_GET(*thispa, ARCH_CONVERT) == + INT_GET(*pp, ARCH_CONVERT)) { + cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld", + __FUNCTION__, j, i, + INT_GET(*thispa, ARCH_CONVERT)); + panic("%s: ptrs are equal in node\n", + __FUNCTION__); } } } @@ -6089,12 +6051,13 @@ xfs_bmap_check_leaf_extents( return; error0: - printk("at error0\n"); + cmn_err(CE_WARN, "%s: at error0", __FUNCTION__); if (bp_release) xfs_trans_brelse(NULL, bp); error_norelse: - printk("xfs_bmap_check_leaf_extents: BAD after btree leaves for %d extents\n", i); - panic("xfs_bmap_check_leaf_extents: CORRUPTED BTREE OR SOMETHING"); + cmn_err(CE_WARN, "%s: BAD after btree leaves for %d extents", + i, __FUNCTION__); + panic("%s: CORRUPTED BTREE OR SOMETHING", __FUNCTION__); return; } #endif diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index cb0dc44fb9df..a41ea99c034b 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -76,10 +76,6 @@ typedef struct xfs_bmap_free #define XFS_BMAPI_IGSTATE 0x200 /* Ignore state - */ /* combine contig. space */ #define XFS_BMAPI_CONTIG 0x400 /* must allocate only one extent */ -#define XFS_BMAPI_DIRECT_IO 0x800 /* Flag from cxfs client, not used - * by xfs directly. Indicates alloc - * request is for direct I/O not - * extent conversion by server */ #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_BMAPI_AFLAG) int xfs_bmapi_aflag(int w); diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index f49fc3fd305e..43a0680371f4 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c @@ -629,8 +629,8 @@ xfs_bmbt_delrec( xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS); if (INT_GET(left->bb_rightsib, ARCH_CONVERT) != NULLDFSBNO) { if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, - INT_GET(left->bb_rightsib, ARCH_CONVERT), 0, &rrbp, - XFS_BMAP_BTREE_REF))) { + INT_GET(left->bb_rightsib, ARCH_CONVERT), + 0, &rrbp, XFS_BMAP_BTREE_REF))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); goto error0; } @@ -646,10 +646,7 @@ xfs_bmbt_delrec( cur->bc_private.b.flist, mp); cur->bc_private.b.ip->i_d.di_nblocks--; xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE); - if (XFS_IS_QUOTA_ON(mp) && - cur->bc_private.b.ip->i_ino != mp->m_sb.sb_uquotino && - cur->bc_private.b.ip->i_ino != mp->m_sb.sb_gquotino) - xfs_trans_mod_dquot_byino(cur->bc_tp, cur->bc_private.b.ip, + XFS_TRANS_MOD_DQUOT_BYINO(mp, cur->bc_tp, cur->bc_private.b.ip, XFS_TRANS_DQ_BCOUNT, -1L); xfs_trans_binval(cur->bc_tp, rbp); if (bp != lbp) { @@ -986,13 +983,10 @@ xfs_bmbt_killroot( #endif memcpy(pp, cpp, INT_GET(block->bb_numrecs, ARCH_CONVERT) * sizeof(*pp)); xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1, - cur->bc_private.b.flist, cur->bc_mp); + cur->bc_private.b.flist, cur->bc_mp); ip->i_d.di_nblocks--; - if (XFS_IS_QUOTA_ON(cur->bc_mp) && - ip->i_ino != cur->bc_mp->m_sb.sb_uquotino && - ip->i_ino != cur->bc_mp->m_sb.sb_gquotino) - xfs_trans_mod_dquot_byino(cur->bc_tp, ip, XFS_TRANS_DQ_BCOUNT, - -1L); + XFS_TRANS_MOD_DQUOT_BYINO(cur->bc_mp, cur->bc_tp, ip, + XFS_TRANS_DQ_BCOUNT, -1L); xfs_trans_binval(cur->bc_tp, cbp); cur->bc_bufs[level - 1] = NULL; INT_MOD(block->bb_level, ARCH_CONVERT, -1); @@ -1589,10 +1583,7 @@ xfs_bmbt_split( cur->bc_private.b.allocated++; cur->bc_private.b.ip->i_d.di_nblocks++; xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE); - if (XFS_IS_QUOTA_ON(args.mp) && - cur->bc_private.b.ip->i_ino != args.mp->m_sb.sb_uquotino && - cur->bc_private.b.ip->i_ino != args.mp->m_sb.sb_gquotino) - xfs_trans_mod_dquot_byino(args.tp, cur->bc_private.b.ip, + XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, XFS_TRANS_DQ_BCOUNT, 1L); rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0); right = XFS_BUF_TO_BMBT_BLOCK(rbp); @@ -2390,11 +2381,8 @@ xfs_bmbt_newroot( cur->bc_private.b.firstblock = args.fsbno; cur->bc_private.b.allocated++; cur->bc_private.b.ip->i_d.di_nblocks++; - if (XFS_IS_QUOTA_ON(args.mp) && - cur->bc_private.b.ip->i_ino != args.mp->m_sb.sb_uquotino && - cur->bc_private.b.ip->i_ino != args.mp->m_sb.sb_gquotino) - xfs_trans_mod_dquot_byino(args.tp, cur->bc_private.b.ip, - XFS_TRANS_DQ_BCOUNT, 1L); + XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, + XFS_TRANS_DQ_BCOUNT, 1L); bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0); cblock = XFS_BUF_TO_BMBT_BLOCK(bp); *cblock = *block; diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index 3f926f6034de..900f6cb80e8e 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h @@ -124,6 +124,9 @@ typedef struct page_buf_s xfs_buf_t; typedef struct pb_target xfs_buftarg_t; #define xfs_buftarg pb_target +#define XFS_BUF_DATAIO(x) ((x)->pb_flags |= PBF_FS_DATAIOD) +#define XFS_BUF_UNDATAIO(x) ((x)->pb_flags &= ~PBF_FS_DATAIOD) + #define XFS_BUF_IODONE_FUNC(buf) (buf)->pb_iodone #define XFS_BUF_SET_IODONE_FUNC(buf, func) \ (buf)->pb_iodone = (func) @@ -244,7 +247,7 @@ static inline void xfs_buf_relse(page_buf_t *bp) #define xfs_biodone(pb) \ - pagebuf_iodone(pb, 0, 0) + pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), 0) #define xfs_incore(buftarg,blkno,len,lockit) \ pagebuf_find(buftarg, blkno ,len, lockit) diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h index fd7d80ebe2ef..689cbac1b793 100644 --- a/fs/xfs/xfs_clnt.h +++ b/fs/xfs/xfs_clnt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -64,16 +64,6 @@ struct xfs_mount_args { int sunit; /* stripe unit (BBs) */ int swidth; /* stripe width (BBs), multiple of sunit */ uchar_t iosizelog; /* log2 of the preferred I/O size */ - - /* The remainder is for CXFS support. */ - char **servlist; /* Table of hosts which may be servers */ - int *servlistlen; /* Table of hostname lengths. */ - int slcount; /* Count of hosts which may be servers. */ - int stimeout; /* Server timeout in milliseconds */ - int ctimeout; /* Client timeout in milliseconds */ - char *server; /* Designated server hostname (for remount). */ - int servlen; /* Length of server hostname (for remount). */ - int servcell; /* Server cell (internal testing only) */ }; /* @@ -101,17 +91,6 @@ struct xfs_mount_args { #define XFSMNT_IOSIZE 0x00002000 /* optimize for I/O size */ #define XFSMNT_OSYNCISOSYNC 0x00004000 /* o_sync is REALLY o_sync */ /* (osyncisdsync is now default) */ -#define XFSMNT_CLNTONLY 0x00008000 /* cxfs mount as client only */ -#define XFSMNT_UNSHARED 0x00010000 /* cxfs filesystem mounted - * unshared */ -#define XFSMNT_CHGCLNTONLY 0x00020000 /* changing client only flag */ - /* (for remount only) */ -#define XFSMNT_SERVCELL 0x00040000 /* setting server cell */ - /* (allowed on remount) */ -#define XFSMNT_MAKESERVER 0x00080000 /* become the server (remount */ - /* only) */ -#define XFSMNT_NOTSERVER 0x00100000 /* give up being the server */ - /* (remount only) */ #define XFSMNT_32BITINODES 0x00200000 /* restrict inodes to 32 * bits of address space */ #define XFSMNT_GQUOTA 0x00400000 /* group quota accounting */ @@ -121,10 +100,4 @@ struct xfs_mount_args { #define XFSMNT_DMAPI 0x02000000 /* enable dmapi/xdsm */ #define XFSMNT_NOLOGFLUSH 0x04000000 /* Don't flush for log blocks */ -/* Did we get any args for CXFS to consume? */ -#define XFSARGS_FOR_CXFSARR(ap) \ - ((ap)->servlist || (ap)->slcount >= 0 || \ - (ap)->stimeout >= 0 || (ap)->ctimeout >= 0 || \ - (ap)->flags & (XFSMNT_CLNTONLY | XFSMNT_UNSHARED)) - #endif /* __XFS_CLNT_H__ */ diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index 49dced89c03c..184e0e46bc12 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -32,11 +32,6 @@ #ifndef __XFS_DMAPI_H__ #define __XFS_DMAPI_H__ -#ifdef CONFIG_XFS_DMAPI - -#include <dmapi/dmapi.h> -#include <dmapi/dmapi_kern.h> - /* Values used to define the on-disk version of dm_attrname_t. All * on-disk attribute names start with the 8-byte string "SGI_DMI_". * @@ -48,6 +43,42 @@ #define DMATTR_PREFIXLEN 8 #define DMATTR_PREFIXSTRING "SGI_DMI_" +typedef enum { + DM_EVENT_INVALID = -1, + DM_EVENT_CANCEL = 0, /* not supported */ + DM_EVENT_MOUNT = 1, + DM_EVENT_PREUNMOUNT = 2, + DM_EVENT_UNMOUNT = 3, + DM_EVENT_DEBUT = 4, /* not supported */ + DM_EVENT_CREATE = 5, + DM_EVENT_CLOSE = 6, /* not supported */ + DM_EVENT_POSTCREATE = 7, + DM_EVENT_REMOVE = 8, + DM_EVENT_POSTREMOVE = 9, + DM_EVENT_RENAME = 10, + DM_EVENT_POSTRENAME = 11, + DM_EVENT_LINK = 12, + DM_EVENT_POSTLINK = 13, + DM_EVENT_SYMLINK = 14, + DM_EVENT_POSTSYMLINK = 15, + DM_EVENT_READ = 16, + DM_EVENT_WRITE = 17, + DM_EVENT_TRUNCATE = 18, + DM_EVENT_ATTRIBUTE = 19, + DM_EVENT_DESTROY = 20, + DM_EVENT_NOSPACE = 21, + DM_EVENT_USER = 22, + DM_EVENT_MAX = 23 +} dm_eventtype_t; +#define HAVE_DM_EVENTTYPE_T + +typedef enum { + DM_RIGHT_NULL, + DM_RIGHT_SHARED, + DM_RIGHT_EXCL +} dm_right_t; +#define HAVE_DM_RIGHT_T + /* Defines for determining if an event message should be sent. */ #define DM_EVENT_ENABLED(vfsp, ip, event) ( \ unlikely ((vfsp)->vfs_flag & VFS_DMI) && \ @@ -61,21 +92,6 @@ ((io)->io_mount->m_dmevmask & (1 << event)) ) \ ) -/* - * Macros to turn caller specified delay/block flags into - * dm_send_xxxx_event flag DM_FLAGS_NDELAY. - */ - -#define FILP_DELAY_FLAG(filp) ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) ? \ - DM_FLAGS_NDELAY : 0) -#define AT_DELAY_FLAG(f) ((f&ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0) - - - -/* events valid in dm_set_eventlist() when called with a filesystem handle. - These events are not persistent. -*/ - #define DM_XFS_VALID_FS_EVENTS ( \ (1 << DM_EVENT_PREUNMOUNT) | \ (1 << DM_EVENT_UNMOUNT) | \ @@ -120,7 +136,6 @@ (1 << DM_EVENT_ATTRIBUTE) | \ (1 << DM_EVENT_DESTROY) ) - /* Events supported by the XFS filesystem. */ #define DM_XFS_SUPPORTED_EVENTS ( \ (1 << DM_EVENT_MOUNT) | \ @@ -144,162 +159,34 @@ (1 << DM_EVENT_DESTROY) ) -extern int -xfs_dm_mount( - vfs_t *vfsp, - char *dir_name, - char *fsname); - -extern int -xfs_dm_get_fsys_vector( - bhv_desc_t *bdp, - dm_fcntl_vector_t *vecrq); - -extern int -xfs_dm_send_data_event( - dm_eventtype_t event, - bhv_desc_t *bdp, - xfs_off_t offset, - size_t length, - int flags, - vrwlock_t *locktype); - -extern int -xfs_dm_send_mmap_event( - struct vm_area_struct *vma, - unsigned int wantflag); - -#else /* CONFIG_XFS_DMAPI */ - -/* - * Flags needed to build with dmapi disabled. - */ - -typedef enum { - DM_EVENT_INVALID = -1, - DM_EVENT_CANCEL = 0, /* not supported */ - DM_EVENT_MOUNT = 1, - DM_EVENT_PREUNMOUNT = 2, - DM_EVENT_UNMOUNT = 3, - DM_EVENT_DEBUT = 4, /* not supported */ - DM_EVENT_CREATE = 5, - DM_EVENT_CLOSE = 6, /* not supported */ - DM_EVENT_POSTCREATE = 7, - DM_EVENT_REMOVE = 8, - DM_EVENT_POSTREMOVE = 9, - DM_EVENT_RENAME = 10, - DM_EVENT_POSTRENAME = 11, - DM_EVENT_LINK = 12, - DM_EVENT_POSTLINK = 13, - DM_EVENT_SYMLINK = 14, - DM_EVENT_POSTSYMLINK = 15, - DM_EVENT_READ = 16, - DM_EVENT_WRITE = 17, - DM_EVENT_TRUNCATE = 18, - DM_EVENT_ATTRIBUTE = 19, - DM_EVENT_DESTROY = 20, - DM_EVENT_NOSPACE = 21, - DM_EVENT_USER = 22, - DM_EVENT_MAX = 23 -} dm_eventtype_t; - -typedef enum { - DM_RIGHT_NULL, - DM_RIGHT_SHARED, - DM_RIGHT_EXCL -} dm_right_t; - -/* - * Defines for determining if an event message should be sent. - */ -#define DM_EVENT_ENABLED(vfsp, ip, event) 0 -#define DM_EVENT_ENABLED_IO(vfsp, io, event) 0 - -/* - * Stubbed out DMAPI delay macros. - */ - -#define FILP_DELAY_FLAG(filp) 0 -#define AT_DELAY_FLAG(f) 0 - -/* - * Events supported by the XFS filesystem. - */ - -#define DM_XFS_VALID_FS_EVENTS 0 -#define DM_XFS_VALID_FILE_EVENTS 0 -#define DM_XFS_VALID_DIRECTORY_EVENTS 0 -#define DM_XFS_SUPPORTED_EVENTS 0 - /* - * Dummy definitions used for the flags field on dm_send_*_event(). + * Definitions used for the flags field on dm_send_*_event(). */ #define DM_FLAGS_NDELAY 0x001 /* return EAGAIN after dm_pending() */ #define DM_FLAGS_UNWANTED 0x002 /* event not in fsys dm_eventset_t */ /* - * Stubs for XFS DMAPI utility routines. + * Macros to turn caller specified delay/block flags into + * dm_send_xxxx_event flag DM_FLAGS_NDELAY. */ -static __inline int -xfs_dm_send_data_event( - dm_eventtype_t event, - bhv_desc_t *bdp, - xfs_off_t offset, - size_t length, - int flags, - vrwlock_t *locktype) -{ - return ENOSYS; -} - -static __inline int -xfs_dm_send_mmap_event( - struct vm_area_struct *vma, - unsigned int wantflag) -{ - return 0; -} +#define FILP_DELAY_FLAG(filp) ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) ? \ + DM_FLAGS_NDELAY : 0) +#define AT_DELAY_FLAG(f) ((f&ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0) /* - * Stubs for routines needed for the X/Open version of DMAPI. + * Macros to turn caller specified delay/block flags into + * dm_send_xxxx_event flag DM_FLAGS_NDELAY. */ -static __inline int -dm_send_destroy_event( - bhv_desc_t *bdp, - dm_right_t vp_right) -{ - return ENOSYS; -} +#define FILP_DELAY_FLAG(filp) ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) ? \ + DM_FLAGS_NDELAY : 0) + -static __inline int -dm_send_namesp_event( - dm_eventtype_t event, - bhv_desc_t *bdp1, - dm_right_t vp1_right, - bhv_desc_t *bdp2, - dm_right_t vp2_right, - char *name1, - char *name2, - mode_t mode, - int retcode, - int flags) -{ - return ENOSYS; -} +extern struct bhv_vfsops xfs_dmops; -static __inline void -dm_send_unmount_event( - vfs_t *vfsp, - vnode_t *vp, - dm_right_t vfsp_right, - mode_t mode, - int retcode, - int flags) -{ -} +extern void xfs_dm_init(void); +extern void xfs_dm_exit(void); -#endif /* CONFIG_XFS_DMAPI */ #endif /* __XFS_DMAPI_H__ */ diff --git a/fs/xfs/xfs_dmops.c b/fs/xfs/xfs_dmops.c new file mode 100644 index 000000000000..7448bac1e642 --- /dev/null +++ b/fs/xfs/xfs_dmops.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU 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. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#include <xfs.h> + +#ifndef CONFIG_XFS_DMAPI +xfs_dmops_t xfs_dmcore_xfs = { + .xfs_send_data = (xfs_send_data_t)fs_nosys, + .xfs_send_mmap = (xfs_send_mmap_t)fs_noerr, + .xfs_send_destroy = (xfs_send_destroy_t)fs_nosys, + .xfs_send_namesp = (xfs_send_namesp_t)fs_nosys, + .xfs_send_unmount = (xfs_send_unmount_t)fs_noval, +}; +#endif /* CONFIG_XFS_DMAPI */ diff --git a/fs/xfs/xfs_dqblk.h b/fs/xfs/xfs_dqblk.h deleted file mode 100644 index 40f6a4cd4a7b..000000000000 --- a/fs/xfs/xfs_dqblk.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU 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. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_DQBLK_H__ -#define __XFS_DQBLK_H__ - -/* - * The ondisk form of a dquot structure. - */ -#define XFS_DQUOT_MAGIC 0x4451 /* 'DQ' */ -#define XFS_DQUOT_VERSION (u_int8_t)0x01 /* latest version number */ - -/* - * This is the main portion of the on-disk representation of quota - * information for a user. This is the q_core of the xfs_dquot_t that - * is kept in kernel memory. We pad this with some more expansion room - * to construct the on disk structure. - */ -typedef struct xfs_disk_dquot { -/*16*/ u_int16_t d_magic; /* dquot magic = XFS_DQUOT_MAGIC */ -/*8 */ u_int8_t d_version; /* dquot version */ -/*8 */ u_int8_t d_flags; /* XFS_DQ_USER/PROJ/GROUP */ -/*32*/ xfs_dqid_t d_id; /* user,project,group id */ -/*64*/ xfs_qcnt_t d_blk_hardlimit;/* absolute limit on disk blks */ -/*64*/ xfs_qcnt_t d_blk_softlimit;/* preferred limit on disk blks */ -/*64*/ xfs_qcnt_t d_ino_hardlimit;/* maximum # allocated inodes */ -/*64*/ xfs_qcnt_t d_ino_softlimit;/* preferred inode limit */ -/*64*/ xfs_qcnt_t d_bcount; /* disk blocks owned by the user */ -/*64*/ xfs_qcnt_t d_icount; /* inodes owned by the user */ -/*32*/ __int32_t d_itimer; /* zero if within inode limits if not, - this is when we refuse service */ -/*32*/ __int32_t d_btimer; /* similar to above; for disk blocks */ -/*16*/ xfs_qwarncnt_t d_iwarns; /* warnings issued wrt num inodes */ -/*16*/ xfs_qwarncnt_t d_bwarns; /* warnings issued wrt disk blocks */ -/*32*/ __int32_t d_pad0; /* 64 bit align */ -/*64*/ xfs_qcnt_t d_rtb_hardlimit;/* absolute limit on realtime blks */ -/*64*/ xfs_qcnt_t d_rtb_softlimit;/* preferred limit on RT disk blks */ -/*64*/ xfs_qcnt_t d_rtbcount; /* realtime blocks owned */ -/*32*/ __int32_t d_rtbtimer; /* similar to above; for RT disk blocks */ -/*16*/ xfs_qwarncnt_t d_rtbwarns; /* warnings issued wrt RT disk blocks */ -/*16*/ __uint16_t d_pad; -} xfs_disk_dquot_t; - -/* - * This is what goes on disk. This is separated from the xfs_disk_dquot because - * carrying the unnecessary padding would be a waste of memory. - */ -typedef struct xfs_dqblk { - xfs_disk_dquot_t dd_diskdq; /* portion that lives incore as well */ - char dd_fill[32]; /* filling for posterity */ -} xfs_dqblk_t; - -/* - * flags for q_flags field in the dquot. - */ -#define XFS_DQ_USER 0x0001 /* a user quota */ -/* #define XFS_DQ_PROJ 0x0002 -- project quota (IRIX) */ -#define XFS_DQ_GROUP 0x0004 /* a group quota */ -#define XFS_DQ_FLOCKED 0x0008 /* flush lock taken */ -#define XFS_DQ_DIRTY 0x0010 /* dquot is dirty */ -#define XFS_DQ_WANT 0x0020 /* for lookup/reclaim race */ -#define XFS_DQ_INACTIVE 0x0040 /* dq off mplist & hashlist */ -#define XFS_DQ_MARKER 0x0080 /* sentinel */ - -/* - * In the worst case, when both user and group quotas are on, - * we can have a max of three dquots changing in a single transaction. - */ -#define XFS_DQUOT_LOGRES(mp) (sizeof(xfs_disk_dquot_t) * 3) - -#endif /* __XFS_DQBLK_H__ */ diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 14a167f6d848..aa65472385cc 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -591,9 +591,7 @@ xfs_ireclaim(xfs_inode_t *ip) * Release dquots (and their references) if any. An inode may escape * xfs_inactive and get here via vn_alloc->vn_reclaim path. */ - if (ip->i_udquot || ip->i_gdquot) { - xfs_qm_dqdettach_inode(ip); - } + XFS_QM_DQDETACH(ip->i_mount, ip); /* * Pull our behavior descriptor from the vnode chain. @@ -611,11 +609,8 @@ xfs_ireclaim(xfs_inode_t *ip) /* * This routine removes an about-to-be-destroyed inode from - * all of the lists in which it is lcoated with the exception - * of the behavior chain. It is used by xfs_ireclaim and - * by cxfs relocation cocde, in which case, we are removing - * the xfs_inode but leaving the vnode alone since it has - * been transformed into a client vnode. + * all of the lists in which it is located with the exception + * of the behavior chain. */ void xfs_iextract( diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index f0e286e95617..1a354c8589a5 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -1190,25 +1190,6 @@ xfs_ialloc( ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; ip->i_d.di_anextents = 0; -#if DEBUG - { - uint badflags = VNOSWAP | - VISSWAP | - VREPLICABLE | - /* VNONREPLICABLE | XXX uncomment this */ - VDOCMP | - VFRLOCKS; - - /* - * For shared mounts, VNOSWAP is set in xfs_iget - */ - if (tp->t_mountp->m_cxfstype != XFS_CXFS_NOT) - badflags &= ~VNOSWAP; - - ASSERT(!(vp->v_flag & badflags)); - } -#endif /* DEBUG */ - /* * Log the new values stuffed into the inode. */ @@ -3599,16 +3580,19 @@ xfs_ichgtime(xfs_inode_t *ip, nanotime(&tv); if (flags & XFS_ICHGTIME_MOD) { - inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec; - inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec; + inode->i_mtime = tv; + ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec; + ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec; } if (flags & XFS_ICHGTIME_ACC) { - inode->i_atime.tv_sec = ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec; - inode->i_atime.tv_nsec = ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec; + inode->i_atime = tv; + ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec; + ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec; } if (flags & XFS_ICHGTIME_CHG) { - inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec; - inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec; + inode->i_ctime = tv; + ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec; + ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec; } /* diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 79227f00b1a1..d58b8aa74dd6 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -154,11 +154,7 @@ typedef struct xfs_iocore { * Flags in the flags field */ -#define XFS_IOCORE_ISXFS 0x01 -#define XFS_IOCORE_ISCXFS 0x02 -#define XFS_IOCORE_RT 0x04 - -#define IO_IS_XFS(io) ((io)->io_flags & XFS_IOCORE_ISXFS) +#define XFS_IOCORE_RT 0x1 /* * xfs_iocore prototypes diff --git a/fs/xfs/xfs_iocore.c b/fs/xfs/xfs_iocore.c index ea669a083e47..38f7d9dde577 100644 --- a/fs/xfs/xfs_iocore.c +++ b/fs/xfs/xfs_iocore.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -33,15 +33,25 @@ #include <xfs.h> -static xfs_fsize_t +STATIC xfs_fsize_t xfs_size_fn( - xfs_inode_t *ip) + xfs_inode_t *ip) { return (ip->i_d.di_size); } +STATIC int +xfs_ioinit( + struct vfs *vfsp, + struct xfs_mount_args *mntargs, + int flags) +{ + return xfs_mountfs(vfsp, XFS_VFSTOM(vfsp), + vfsp->vfs_super->s_bdev->bd_dev, flags); +} + xfs_ioops_t xfs_iocore_xfs = { - .xfs_ioinit = (xfs_ioinit_t) fs_noerr, + .xfs_ioinit = (xfs_ioinit_t) xfs_ioinit, .xfs_bmapi_func = (xfs_bmapi_t) xfs_bmapi, .xfs_bmap_eof_func = (xfs_bmap_eof_t) xfs_bmap_eof, .xfs_iomap_write_direct = @@ -67,11 +77,9 @@ xfs_iocore_inode_reinit( { xfs_iocore_t *io = &ip->i_iocore; - io->io_flags = XFS_IOCORE_ISXFS; - if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) { + io->io_flags = 0; + if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) io->io_flags |= XFS_IOCORE_RT; - } - io->io_dmevmask = ip->i_d.di_dmevmask; io->io_dmstate = ip->i_d.di_dmstate; } diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 247e842f3299..18eeda703102 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -136,16 +136,15 @@ xlog_bwrite( /* * check log record header for recovery */ - static void xlog_header_check_dump(xfs_mount_t *mp, xlog_rec_header_t *head) { int b; - printk("xlog_header_check_dump:\n SB : uuid = "); + printk("%s: SB : uuid = ", __FUNCTION__); for (b=0;b<16;b++) printk("%02x",((unsigned char *)&mp->m_sb.sb_uuid)[b]); printk(", fmt = %d\n",XLOG_FMT); - printk(" log: uuid = "); + printk(" log : uuid = "); for (b=0;b<16;b++) printk("%02x",((unsigned char *)&head->h_fs_uuid)[b]); printk(", fmt = %d\n", INT_GET(head->h_fmt, ARCH_CONVERT)); } @@ -1813,7 +1812,6 @@ xlog_recover_do_reg_buffer(xfs_mount_t *mp, */ error = 0; if (buf_f->blf_flags & (XFS_BLI_UDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { - /* OK, if this returns ENOSYS */ error = xfs_qm_dqcheck((xfs_disk_dquot_t *) item->ri_buf[i].i_addr, -1, 0, XFS_QMOPT_DOWARN, @@ -1821,9 +1819,9 @@ xlog_recover_do_reg_buffer(xfs_mount_t *mp, } if (!error) memcpy(xfs_buf_offset(bp, - (uint)bit << XFS_BLI_SHIFT), /* dest */ - item->ri_buf[i].i_addr, /* source */ - nbits<<XFS_BLI_SHIFT); /* length */ + (uint)bit << XFS_BLI_SHIFT), /* dest */ + item->ri_buf[i].i_addr, /* source */ + nbits<<XFS_BLI_SHIFT); /* length */ i++; bit += nbits; } @@ -1832,6 +1830,120 @@ xlog_recover_do_reg_buffer(xfs_mount_t *mp, ASSERT(i == item->ri_total); } /* xlog_recover_do_reg_buffer */ +/* + * Do some primitive error checking on ondisk dquot data structures. + */ +int +xfs_qm_dqcheck( + xfs_disk_dquot_t *ddq, + xfs_dqid_t id, + uint type, /* used only when IO_dorepair is true */ + uint flags, + char *str) +{ + xfs_dqblk_t *d = (xfs_dqblk_t *)ddq; + int errs = 0; + + /* + * We can encounter an uninitialized dquot buffer for 2 reasons: + * 1. If we crash while deleting the quotainode(s), and those blks got + * used for user data. This is because we take the path of regular + * file deletion; however, the size field of quotainodes is never + * updated, so all the tricks that we play in itruncate_finish + * don't quite matter. + * + * 2. We don't play the quota buffers when there's a quotaoff logitem. + * But the allocation will be replayed so we'll end up with an + * uninitialized quota block. + * + * This is all fine; things are still consistent, and we haven't lost + * any quota information. Just don't complain about bad dquot blks. + */ + if (INT_GET(ddq->d_magic, ARCH_CONVERT) != XFS_DQUOT_MAGIC) { + if (flags & XFS_QMOPT_DOWARN) + cmn_err(CE_ALERT, + "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x", + str, id, + INT_GET(ddq->d_magic, ARCH_CONVERT), XFS_DQUOT_MAGIC); + errs++; + } + if (INT_GET(ddq->d_version, ARCH_CONVERT) != XFS_DQUOT_VERSION) { + if (flags & XFS_QMOPT_DOWARN) + cmn_err(CE_ALERT, + "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x", + str, id, + INT_GET(ddq->d_magic, ARCH_CONVERT), XFS_DQUOT_VERSION); + errs++; + } + + if (INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_USER && + INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_GROUP) { + if (flags & XFS_QMOPT_DOWARN) + cmn_err(CE_ALERT, + "%s : XFS dquot ID 0x%x, unknown flags 0x%x", + str, id, INT_GET(ddq->d_flags, ARCH_CONVERT)); + errs++; + } + + if (id != -1 && id != INT_GET(ddq->d_id, ARCH_CONVERT)) { + if (flags & XFS_QMOPT_DOWARN) + cmn_err(CE_ALERT, + "%s : ondisk-dquot 0x%x, ID mismatch: " + "0x%x expected, found id 0x%x", + str, ddq, id, INT_GET(ddq->d_id, ARCH_CONVERT)); + errs++; + } + + if (! errs) { + if (INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT) && + INT_GET(ddq->d_bcount, ARCH_CONVERT) >= + INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT)) { + if (INT_ISZERO(ddq->d_btimer, ARCH_CONVERT) && + !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) { + if (flags & XFS_QMOPT_DOWARN) + cmn_err(CE_ALERT, + "%s : Dquot ID 0x%x (0x%x) " + "BLK TIMER NOT STARTED", + str, (int) + INT_GET(ddq->d_id, ARCH_CONVERT), ddq); + errs++; + } + } + if (INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT) && + INT_GET(ddq->d_icount, ARCH_CONVERT) >= + INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT)) { + if (INT_ISZERO(ddq->d_itimer, ARCH_CONVERT) && + !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) { + if (flags & XFS_QMOPT_DOWARN) + cmn_err(CE_ALERT, + "%s : Dquot ID 0x%x (0x%x) " + "INODE TIMER NOT STARTED", + str, (int) + INT_GET(ddq->d_id, ARCH_CONVERT), ddq); + errs++; + } + } + } + + if (!errs || !(flags & XFS_QMOPT_DQREPAIR)) + return errs; + + if (flags & XFS_QMOPT_DOWARN) + cmn_err(CE_NOTE, "Re-initializing dquot ID 0x%x", id); + + /* + * Typically, a repair is only requested by quotacheck. + */ + ASSERT(id != -1); + ASSERT(flags & XFS_QMOPT_DQREPAIR); + memset(d, 0, sizeof(xfs_dqblk_t)); + INT_SET(d->dd_diskdq.d_magic, ARCH_CONVERT, XFS_DQUOT_MAGIC); + INT_SET(d->dd_diskdq.d_version, ARCH_CONVERT, XFS_DQUOT_VERSION); + INT_SET(d->dd_diskdq.d_id, ARCH_CONVERT, id); + INT_SET(d->dd_diskdq.d_flags, ARCH_CONVERT, type); + + return errs; +} /* * Perform a dquot buffer recovery. @@ -2335,8 +2447,6 @@ xlog_recover_do_dquot_trans(xlog_t *log, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, "xlog_recover_do_dquot_trans (log copy)"))) { - if (error == ENOSYS) - return (0); return XFS_ERROR(EIO); } ASSERT(dq_f->qlf_len == 1); @@ -2923,8 +3033,6 @@ xlog_recover_process_iunlinks(xlog_t *log) /* * Prevent any DMAPI event from being sent while in this function. - * Not a problem for xfs since the file system isn't mounted - * yet. It is a problem for cxfs recovery. */ mp_dmevmask = mp->m_dmevmask; mp->m_dmevmask = 0; @@ -2982,11 +3090,8 @@ xlog_recover_process_iunlinks(xlog_t *log) * Prevent any DMAPI event from * being sent when the * reference on the inode is - * dropped. Not a problem for - * xfs since the file system - * isn't mounted yet. It is a - * problem for cxfs recovery. - */ + * dropped. + */ ip->i_d.di_dmevmask = 0; /* diff --git a/fs/xfs/xfs_macros.c b/fs/xfs/xfs_macros.c index 316443b4e4bf..a4b66e0ddbc5 100644 --- a/fs/xfs/xfs_macros.c +++ b/fs/xfs/xfs_macros.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -358,6 +358,14 @@ xfs_bhvtom(bhv_desc_t *bdp) } #endif +#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_VFSTOM) +xfs_mount_t * +xfs_vfstom(vfs_t *vfs) +{ + return XFS_VFSTOM(vfs); +} +#endif + #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_BM_MAXLEVELS) int xfs_bm_maxlevels(xfs_mount_t *mp, int w) diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 398673b87f22..c3f64fb7711f 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -32,16 +32,14 @@ #include <xfs.h> -STATIC void xfs_mount_reset_sbqflags(xfs_mount_t *); STATIC void xfs_mount_log_sbunit(xfs_mount_t *, __int64_t); STATIC int xfs_uuid_mount(xfs_mount_t *); +STATIC void xfs_uuid_unmount(xfs_mount_t *mp); mutex_t xfs_uuidtabmon; /* monitor for uuidtab */ STATIC int xfs_uuidtab_size; STATIC uuid_t *xfs_uuidtab; -STATIC void xfs_uuid_unmount(xfs_mount_t *); - void xfs_xlatesb(void *, xfs_sb_t *, int, xfs_arch_t, __int64_t); static struct { @@ -120,10 +118,9 @@ xfs_mount_init(void) spinlock_init(&mp->m_freeze_lock, "xfs_freeze"); init_sv(&mp->m_wait_unfreeze, SV_DEFAULT, "xfs_freeze", 0); atomic_set(&mp->m_active_trans, 0); - mp->m_cxfstype = XFS_CXFS_NOT; return mp; -} /* xfs_mount_init */ +} /* * Free up the resources associated with a mount structure. Assume that @@ -146,34 +143,29 @@ xfs_mount_free( for (agno = 0; agno < mp->m_maxagi; agno++) if (mp->m_perag[agno].pagb_list) kmem_free(mp->m_perag[agno].pagb_list, - sizeof(xfs_perag_busy_t) * XFS_PAGB_NUM_SLOTS); + sizeof(xfs_perag_busy_t) * + XFS_PAGB_NUM_SLOTS); kmem_free(mp->m_perag, sizeof(xfs_perag_t) * mp->m_sb.sb_agcount); } -#if 0 - /* - * XXXdpd - Doesn't work now for shutdown case. - * Should at least free the memory. - */ - ASSERT(mp->m_ail.ail_back == (xfs_log_item_t*)&(mp->m_ail)); - ASSERT(mp->m_ail.ail_forw == (xfs_log_item_t*)&(mp->m_ail)); -#endif AIL_LOCK_DESTROY(&mp->m_ail_lock); spinlock_destroy(&mp->m_sb_lock); mutex_destroy(&mp->m_ilock); freesema(&mp->m_growlock); + if (mp->m_quotainfo) + XFS_QM_DONE(mp); - if (mp->m_fsname != NULL) { + if (mp->m_fsname != NULL) kmem_free(mp->m_fsname, mp->m_fsname_len); - } - if (mp->m_quotainfo != NULL) { - xfs_qm_unmount_quotadestroy(mp); - } if (remove_bhv) { - VFS_REMOVEBHV(XFS_MTOVFS(mp), &mp->m_bhv); + struct vfs *vfsp = XFS_MTOVFS(mp); + + bhv_remove_all_vfsops(vfsp, 0); + VFS_REMOVEBHV(vfsp, &mp->m_bhv); } + spinlock_destroy(&mp->m_freeze_lock); sv_destroy(&mp->m_wait_unfreeze); kmem_free(mp, sizeof(xfs_mount_t)); @@ -605,21 +597,17 @@ xfs_mountfs( { xfs_buf_t *bp; xfs_sb_t *sbp = &(mp->m_sb); - int error = 0; xfs_inode_t *rip; vnode_t *rvp = 0; - int readio_log; - int writeio_log; + int readio_log, writeio_log; vmap_t vmap; xfs_daddr_t d; - extern xfs_ioops_t xfs_iocore_xfs; /* from xfs_iocore.c */ __uint64_t ret64; - uint quotaflags, quotaondisk; - uint uquotaondisk = 0, gquotaondisk = 0; - boolean_t needquotamount; __int64_t update_flags; + uint quotamount, quotaflags; int agno, noio; int uuid_mounted = 0; + int error = 0; noio = dev == 0 && mp->m_sb_bp != NULL; if (mp->m_sb_bp == NULL) { @@ -644,7 +632,8 @@ xfs_mountfs( if ((BBTOB(mp->m_dalign) & mp->m_blockmask) || (BBTOB(mp->m_swidth) & mp->m_blockmask)) { if (mp->m_flags & XFS_MOUNT_RETERR) { - cmn_err(CE_WARN, "XFS: alignment check 1 failed"); + cmn_err(CE_WARN, + "XFS: alignment check 1 failed"); error = XFS_ERROR(EINVAL); goto error1; } @@ -664,7 +653,8 @@ xfs_mountfs( mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth); } else { if (mp->m_flags & XFS_MOUNT_RETERR) { - cmn_err(CE_WARN, "XFS: alignment check 3 failed"); + cmn_err(CE_WARN, + "XFS: alignment check 3 failed"); error = XFS_ERROR(EINVAL); goto error1; } @@ -718,7 +708,8 @@ xfs_mountfs( * since a single partition filesystem is identical to a single * partition volume/filesystem. */ - if ((mfsi_flags & XFS_MFSI_SECOND) == 0 && (mp->m_flags & XFS_MOUNT_NOUUID) == 0) { + if ((mfsi_flags & XFS_MFSI_SECOND) == 0 && + (mp->m_flags & XFS_MOUNT_NOUUID) == 0) { if (xfs_uuid_mount(mp)) { error = XFS_ERROR(EINVAL); goto error1; @@ -859,9 +850,6 @@ xfs_mountfs( return(0); } - /* Initialize the I/O function vector with XFS functions */ - mp->m_io_ops = xfs_iocore_xfs; - /* * Copies the low order bits of the timestamp and the randomly * set "sequence" number out of a UUID. @@ -953,54 +941,22 @@ xfs_mountfs( ASSERT(rip != NULL); rvp = XFS_ITOV(rip); + VMAP(rvp, vmap); + if (unlikely((rip->i_d.di_mode & IFMT) != IFDIR)) { cmn_err(CE_WARN, "XFS: corrupted root inode"); - VMAP(rvp, vmap); prdev("Root inode %llu is not a directory", mp->m_dev, (unsigned long long)rip->i_ino); xfs_iunlock(rip, XFS_ILOCK_EXCL); - VN_RELE(rvp); - vn_purge(rvp, &vmap); XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); - goto error3; + goto error4; } mp->m_rootip = rip; /* save it */ xfs_iunlock(rip, XFS_ILOCK_EXCL); - quotaondisk = XFS_SB_VERSION_HASQUOTA(&mp->m_sb) && - mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT); - - if (quotaondisk) { - uquotaondisk = mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT; - gquotaondisk = mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT; - } - - /* - * If the device itself is read-only, we can't allow - * the user to change the state of quota on the mount - - * this would generate a transaction on the ro device, - * which would lead to an I/O error and shutdown - */ - - if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) || - (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) || - (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) || - (!gquotaondisk && XFS_IS_GQUOTA_ON(mp))) && - xfs_dev_is_read_only(mp, "changing quota state")) { - cmn_err(CE_WARN, - "XFS: please mount with%s%s%s.", - (!quotaondisk ? "out quota" : ""), - (uquotaondisk ? " usrquota" : ""), - (gquotaondisk ? " grpquota" : "")); - VN_RELE(rvp); - vn_remove(rvp); - error = XFS_ERROR(EPERM); - goto error3; - } - /* * Initialize realtime inode pointers in the mount structure */ @@ -1009,10 +965,7 @@ xfs_mountfs( * Free up the root inode. */ cmn_err(CE_WARN, "XFS: failed to read RT inodes"); - VMAP(rvp, vmap); - VN_RELE(rvp); - vn_purge(rvp, &vmap); - goto error3; + goto error4; } /* @@ -1022,41 +975,11 @@ xfs_mountfs( if (update_flags && !(vfsp->vfs_flag & VFS_RDONLY)) xfs_mount_log_sbunit(mp, update_flags); - quotaflags = 0; - needquotamount = B_FALSE; - /* - * Figure out if we'll need to do a quotacheck. + * Initialise the XFS quota management subsystem for this mount */ - if (XFS_IS_QUOTA_ON(mp) || quotaondisk) { - /* - * Call mount_quotas at this point only if we won't have to do - * a quotacheck. - */ - if (quotaondisk && !XFS_QM_NEED_QUOTACHECK(mp)) { - /* - * If the xfs quota code isn't installed, - * we have to reset the quotachk'd bit. - * If an error occurred, qm_mount_quotas code - * has already disabled quotas. So, just finish - * mounting, and get on with the boring life - * without disk quotas. - */ - if (xfs_qm_mount_quotas(mp)) - xfs_mount_reset_sbqflags(mp); - } else { - /* - * Clear the quota flags, but remember them. This - * is so that the quota code doesn't get invoked - * before we're ready. This can happen when an - * inode goes inactive and wants to free blocks, - * or via xfs_log_mount_finish. - */ - quotaflags = mp->m_qflags; - mp->m_qflags = 0; - needquotamount = B_TRUE; - } - } + if ((error = XFS_QM_INIT(mp, "amount, "aflags))) + goto error4; /* * Finish recovering the file system. This part needed to be @@ -1066,30 +989,23 @@ xfs_mountfs( error = xfs_log_mount_finish(mp, mfsi_flags); if (error) { cmn_err(CE_WARN, "XFS: log mount finish failed"); - goto error3; - } - - if (needquotamount) { - ASSERT(mp->m_qflags == 0); - mp->m_qflags = quotaflags; - if (xfs_qm_mount_quotas(mp)) - xfs_mount_reset_sbqflags(mp); + goto error4; } -#if defined(DEBUG) && defined(XFS_LOUD_RECOVERY) - if (! (XFS_IS_QUOTA_ON(mp))) - xfs_fs_cmn_err(CE_NOTE, mp, "Disk quotas not turned on"); - else - xfs_fs_cmn_err(CE_NOTE, mp, "Disk quotas turned on"); -#endif - -#ifdef QUOTADEBUG - if (XFS_IS_QUOTA_ON(mp) && xfs_qm_internalqcheck(mp)) - cmn_err(CE_WARN, "XFS: mount internalqcheck failed"); -#endif + /* + * Complete the quota initialisation, post-log-replay component. + */ + if ((error = XFS_QM_MOUNT(mp, quotamount, quotaflags))) + goto error4; - return (0); + return 0; + error4: + /* + * Free up the root inode. + */ + VN_RELE(rvp); + vn_purge(rvp, &vmap); error3: xfs_log_unmount_dealloc(mp); error2: @@ -1118,25 +1034,15 @@ xfs_mountfs( int xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) { - int ndquots; + struct vfs *vfsp = XFS_MTOVFS(mp); #if defined(DEBUG) || defined(INDUCE_IO_ERROR) int64_t fsid; #endif xfs_iflush_all(mp, XFS_FLUSH_ALL); - /* - * Purge the dquot cache. - * None of the dquots should really be busy at this point. - */ - if (mp->m_quotainfo) { - while ((ndquots = xfs_qm_dqpurge_all(mp, - XFS_QMOPT_UQUOTA| - XFS_QMOPT_GQUOTA| - XFS_QMOPT_UMOUNTING))) { - delay(ndquots * 10); - } - } + XFS_QM_DQPURGEALL(mp, + XFS_QMOPT_UQUOTA | XFS_QMOPT_GQUOTA | XFS_QMOPT_UMOUNTING); /* * Flush out the log synchronously so that we know for sure @@ -1178,14 +1084,14 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) /* * clear all error tags on this filesystem */ - memcpy(&fsid, &(XFS_MTOVFS(mp)->vfs_fsid), sizeof(int64_t)); - (void) xfs_errortag_clearall_umount(fsid, mp->m_fsname, 0); + memcpy(&fsid, &vfsp->vfs_fsid, sizeof(int64_t)); + xfs_errortag_clearall_umount(fsid, mp->m_fsname, 0); #endif - + XFS_IODONE(vfsp); xfs_mount_free(mp, 1); return 0; } - + void xfs_unmountfs_close(xfs_mount_t *mp, struct cred *cr) { @@ -1652,47 +1558,6 @@ xfs_uuid_unmount(xfs_mount_t *mp) } /* - * When xfsquotas isn't installed and the superblock had quotas, we need to - * clear the quotaflags from superblock. - */ -STATIC void -xfs_mount_reset_sbqflags( - xfs_mount_t *mp) -{ - xfs_trans_t *tp; - unsigned long s; - - mp->m_qflags = 0; - /* - * It is OK to look at sb_qflags here in mount path, - * without SB_LOCK. - */ - if (mp->m_sb.sb_qflags == 0) - return; - s = XFS_SB_LOCK(mp); - mp->m_sb.sb_qflags = 0; - XFS_SB_UNLOCK(mp, s); - - /* - * if the fs is readonly, let the incore superblock run - * with quotas off but don't flush the update out to disk - */ - if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY) - return; -#ifdef QUOTADEBUG - xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes"); -#endif - tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE); - if (xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, - XFS_DEFAULT_LOG_COUNT)) { - xfs_trans_cancel(tp, 0); - return; - } - xfs_mod_sb(tp, XFS_SB_QFLAGS); - (void)xfs_trans_commit(tp, 0, NULL); -} - -/* * Used to log changes to the superblock unit and width fields which could * be altered by the mount options. Only the first superblock is updated. */ diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 881114ae6c66..62f598e4d533 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -75,7 +75,6 @@ struct xfs_ihash; struct xfs_chash; struct xfs_inode; struct xfs_perag; -struct xfs_quotainfo; struct xfs_iocore; struct xfs_bmbt_irec; struct xfs_bmap_free; @@ -87,15 +86,120 @@ struct xfs_bmap_free; #define AIL_LOCK(mp,s) s=mutex_spinlock(&(mp)->m_ail_lock) #define AIL_UNLOCK(mp,s) mutex_spinunlock(&(mp)->m_ail_lock, s) + +/* + * Prototypes and functions for the Data Migration subsystem. + */ + +typedef int (*xfs_send_data_t)(int, struct bhv_desc *, + xfs_off_t, size_t, int, vrwlock_t *); +typedef int (*xfs_send_mmap_t)(struct vm_area_struct *, uint); +typedef int (*xfs_send_destroy_t)(struct bhv_desc *, dm_right_t); +typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct bhv_desc *, + dm_right_t, struct bhv_desc *, dm_right_t, + char *, char *, mode_t, int, int); +typedef void (*xfs_send_unmount_t)(struct vfs *, struct vnode *, + dm_right_t, mode_t, int, int); + +typedef struct xfs_dmops { + xfs_send_data_t xfs_send_data; + xfs_send_mmap_t xfs_send_mmap; + xfs_send_destroy_t xfs_send_destroy; + xfs_send_namesp_t xfs_send_namesp; + xfs_send_unmount_t xfs_send_unmount; +} xfs_dmops_t; + +#define XFS_SEND_DATA(mp, ev,bdp,off,len,fl,lock) \ + (*(mp)->m_dm_ops.xfs_send_data)(ev,bdp,off,len,fl,lock) +#define XFS_SEND_MMAP(mp, vma,fl) \ + (*(mp)->m_dm_ops.xfs_send_mmap)(vma,fl) +#define XFS_SEND_DESTROY(mp, bdp,right) \ + (*(mp)->m_dm_ops.xfs_send_destroy)(bdp,right) +#define XFS_SEND_NAMESP(mp, ev,b1,r1,b2,r2,n1,n2,mode,rval,fl) \ + (*(mp)->m_dm_ops.xfs_send_namesp)(ev,b1,r1,b2,r2,n1,n2,mode,rval,fl) +#define XFS_SEND_UNMOUNT(mp, vfsp,vp,right,mode,rval,fl) \ + (*(mp)->m_dm_ops.xfs_send_unmount)(vfsp,vp,right,mode,rval,fl) + + +/* + * Prototypes and functions for the Quota Management subsystem. + */ + +struct xfs_dquot; +struct xfs_dqtrxops; +struct xfs_quotainfo; + +typedef int (*xfs_qminit_t)(struct xfs_mount *, uint *, uint *); +typedef int (*xfs_qmmount_t)(struct xfs_mount *, uint, uint); +typedef int (*xfs_qmunmount_t)(struct xfs_mount *); +typedef void (*xfs_qmdone_t)(struct xfs_mount *); +typedef void (*xfs_dqrele_t)(struct xfs_dquot *); +typedef int (*xfs_dqattach_t)(struct xfs_inode *, uint); +typedef void (*xfs_dqdetach_t)(struct xfs_inode *); +typedef int (*xfs_dqpurgeall_t)(struct xfs_mount *, uint); +typedef int (*xfs_dqvopalloc_t)(struct xfs_mount *, + struct xfs_inode *, uid_t, gid_t, uint, + struct xfs_dquot **, struct xfs_dquot **); +typedef void (*xfs_dqvopcreate_t)(struct xfs_trans *, struct xfs_inode *, + struct xfs_dquot *, struct xfs_dquot *); +typedef int (*xfs_dqvoprename_t)(struct xfs_inode **); +typedef struct xfs_dquot * (*xfs_dqvopchown_t)( + struct xfs_trans *, struct xfs_inode *, + struct xfs_dquot **, struct xfs_dquot *); +typedef int (*xfs_dqvopchownresv_t)(struct xfs_trans *, struct xfs_inode *, + struct xfs_dquot *, struct xfs_dquot *, uint); + +typedef struct xfs_qmops { + xfs_qminit_t xfs_qminit; + xfs_qmdone_t xfs_qmdone; + xfs_qmmount_t xfs_qmmount; + xfs_qmunmount_t xfs_qmunmount; + xfs_dqrele_t xfs_dqrele; + xfs_dqattach_t xfs_dqattach; + xfs_dqdetach_t xfs_dqdetach; + xfs_dqpurgeall_t xfs_dqpurgeall; + xfs_dqvopalloc_t xfs_dqvopalloc; + xfs_dqvopcreate_t xfs_dqvopcreate; + xfs_dqvoprename_t xfs_dqvoprename; + xfs_dqvopchown_t xfs_dqvopchown; + xfs_dqvopchownresv_t xfs_dqvopchownresv; + struct xfs_dqtrxops *xfs_dqtrxops; +} xfs_qmops_t; + +#define XFS_QM_INIT(mp, mnt, fl) \ + (*(mp)->m_qm_ops.xfs_qminit)(mp, mnt, fl) +#define XFS_QM_MOUNT(mp, mnt, fl) \ + (*(mp)->m_qm_ops.xfs_qmmount)(mp, mnt, fl) +#define XFS_QM_UNMOUNT(mp) \ + (*(mp)->m_qm_ops.xfs_qmunmount)(mp) +#define XFS_QM_DONE(mp) \ + (*(mp)->m_qm_ops.xfs_qmdone)(mp) +#define XFS_QM_DQRELE(mp, dq) \ + (*(mp)->m_qm_ops.xfs_dqrele)(dq) +#define XFS_QM_DQATTACH(mp, ip, fl) \ + (*(mp)->m_qm_ops.xfs_dqattach)(ip, fl) +#define XFS_QM_DQDETACH(mp, ip) \ + (*(mp)->m_qm_ops.xfs_dqdetach)(ip) +#define XFS_QM_DQPURGEALL(mp, fl) \ + (*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl) +#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, fl, dq1, dq2) \ + (*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, fl, dq1, dq2) +#define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \ + (*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2) +#define XFS_QM_DQVOPRENAME(mp, ip) \ + (*(mp)->m_qm_ops.xfs_dqvoprename)(ip) +#define XFS_QM_DQVOPCHOWN(mp, tp, ip, dqp, dq) \ + (*(mp)->m_qm_ops.xfs_dqvopchown)(tp, ip, dqp, dq) +#define XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, dq1, dq2, fl) \ + (*(mp)->m_qm_ops.xfs_dqvopchownresv)(tp, ip, dq1, dq2, fl) + + /* * Prototypes and functions for I/O core modularization. */ -struct flid; -struct buf; - typedef int (*xfs_ioinit_t)(struct vfs *, - struct xfs_mount_args *, int *); + struct xfs_mount_args *, int); typedef int (*xfs_bmapi_t)(struct xfs_trans *, void *, xfs_fileoff_t, xfs_filblks_t, int, xfs_fsblock_t *, xfs_extlen_t, @@ -137,61 +241,42 @@ typedef struct xfs_ioops { xfs_iodone_t xfs_iodone; } xfs_ioops_t; - #define XFS_IOINIT(vfsp, args, flags) \ (*(mp)->m_io_ops.xfs_ioinit)(vfsp, args, flags) - #define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist) \ (*(mp)->m_io_ops.xfs_bmapi_func) \ (trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist) - #define XFS_BMAP_EOF(mp, io, endoff, whichfork, eof) \ (*(mp)->m_io_ops.xfs_bmap_eof_func) \ ((io)->io_obj, endoff, whichfork, eof) - #define XFS_IOMAP_WRITE_DIRECT(mp, io, offset, count, flags, mval, nmap, found)\ (*(mp)->m_io_ops.xfs_iomap_write_direct) \ ((io)->io_obj, offset, count, flags, mval, nmap, found) - #define XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, flags, mval, nmap) \ (*(mp)->m_io_ops.xfs_iomap_write_delay) \ ((io)->io_obj, offset, count, flags, mval, nmap) - #define XFS_IOMAP_WRITE_ALLOCATE(mp, io, mval, nmap) \ (*(mp)->m_io_ops.xfs_iomap_write_allocate) \ ((io)->io_obj, mval, nmap) - #define XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count) \ (*(mp)->m_io_ops.xfs_iomap_write_unwritten) \ ((io)->io_obj, offset, count) - #define XFS_LCK_MAP_SHARED(mp, io) \ (*(mp)->m_io_ops.xfs_lck_map_shared)((io)->io_obj) - #define XFS_ILOCK(mp, io, mode) \ (*(mp)->m_io_ops.xfs_ilock)((io)->io_obj, mode) - #define XFS_ILOCK_NOWAIT(mp, io, mode) \ (*(mp)->m_io_ops.xfs_ilock_nowait)((io)->io_obj, mode) - #define XFS_IUNLOCK(mp, io, mode) \ (*(mp)->m_io_ops.xfs_unlock)((io)->io_obj, mode) - #define XFS_ILOCK_DEMOTE(mp, io, mode) \ (*(mp)->m_io_ops.xfs_ilock_demote)((io)->io_obj, mode) - #define XFS_SIZE(mp, io) \ (*(mp)->m_io_ops.xfs_size_func)((io)->io_obj) - #define XFS_IODONE(vfsp) \ (*(mp)->m_io_ops.xfs_iodone)(vfsp) -/* - * Prototypes and functions for the XFS realtime subsystem. - */ - - typedef struct xfs_mount { bhv_desc_t m_bhv; /* vfs xfs behavior */ xfs_tid_t m_tid; /* next unused tid for fs */ @@ -289,13 +374,9 @@ typedef struct xfs_mount { int m_chsize; /* size of next field */ struct xfs_chash *m_chash; /* fs private inode per-cluster * hash table */ + struct xfs_dmops m_dm_ops; /* vector of DMI ops */ + struct xfs_qmops m_qm_ops; /* vector of XQM ops */ struct xfs_ioops m_io_ops; /* vector of I/O ops */ - struct xfs_expinfo *m_expinfo; /* info to export to other - cells. */ - uint64_t m_shadow_pinmask; - /* which bits matter in rpc - log item pin masks */ - uint m_cxfstype; /* mounted shared, etc. */ lock_t m_freeze_lock; /* Lock for m_frozen */ uint m_frozen; /* FS frozen for shutdown or * snapshot */ @@ -324,8 +405,7 @@ typedef struct xfs_mount { #define XFS_MOUNT_NOALIGN 0x00000080 /* turn off stripe alignment allocations */ /* 0x00000100 -- currently unused */ -#define XFS_MOUNT_REGISTERED 0x00000200 /* registered with cxfs master - cell logic */ + /* 0x00000200 -- currently unused */ #define XFS_MOUNT_NORECOVERY 0x00000400 /* no recovery - dirty fs */ #define XFS_MOUNT_SHARED 0x00000800 /* shared mount */ #define XFS_MOUNT_DFLT_IOSIZE 0x00001000 /* set default i/o size */ @@ -336,14 +416,6 @@ typedef struct xfs_mount { * 32 bits in size */ #define XFS_MOUNT_NOLOGFLUSH 0x00010000 -/* - * Flags for m_cxfstype - */ -#define XFS_CXFS_NOT 0x00000001 /* local mount */ -#define XFS_CXFS_SERVER 0x00000002 /* we're the CXFS server */ -#define XFS_CXFS_CLIENT 0x00000004 /* We're a CXFS client */ -#define XFS_CXFS_REC_ENABLED 0x00000008 /* recovery is enabled */ - #define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN) /* @@ -370,15 +442,17 @@ typedef struct xfs_mount { #define XFS_WSYNC_READIO_LOG 15 /* 32K */ #define XFS_WSYNC_WRITEIO_LOG 14 /* 16K */ -#define xfs_force_shutdown(m,f) VFS_FORCE_SHUTDOWN(XFS_MTOVFS(m),f) +#define xfs_force_shutdown(m,f) \ + VFS_FORCE_SHUTDOWN((XFS_MTOVFS(m)), f, __FILE__, __LINE__) + /* * Flags sent to xfs_force_shutdown. */ #define XFS_METADATA_IO_ERROR 0x1 #define XFS_LOG_IO_ERROR 0x2 #define XFS_FORCE_UMOUNT 0x4 -#define XFS_CORRUPT_INCORE 0x8 /* corrupt in-memory data structures */ -#define XFS_SHUTDOWN_REMOTE_REQ 0x10 /* shutdown came from remote cell */ +#define XFS_CORRUPT_INCORE 0x8 /* Corrupt in-memory data structures */ +#define XFS_SHUTDOWN_REMOTE_REQ 0x10 /* Shutdown came from remote cell */ /* * xflags for xfs_syncsub @@ -388,9 +462,7 @@ typedef struct xfs_mount { /* * Flags for xfs_mountfs */ -#define XFS_MFSI_SECOND 0x01 /* Is a cxfs secondary mount -- skip */ - /* stuff which should only be done */ - /* once. */ +#define XFS_MFSI_SECOND 0x01 /* Secondary mount -- skip stuff */ #define XFS_MFSI_CLIENT 0x02 /* Is a client -- skip lots of stuff */ #define XFS_MFSI_NOUNLINK 0x08 /* Skip unlinked inode processing in */ /* log recovery */ @@ -410,6 +482,13 @@ xfs_mount_t *xfs_bhvtom(bhv_desc_t *bdp); #else #define XFS_BHVTOM(bdp) ((xfs_mount_t *)BHV_PDATA(bdp)) #endif +#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_VFSTOM) +xfs_mount_t *xfs_vfstom(vfs_t *vfs); +#define XFS_VFSTOM(vfs) xfs_vfstom(vfs) +#else +#define XFS_VFSTOM(vfs) \ + (XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfs), &xfs_vfsops))) +#endif /* @@ -447,7 +526,7 @@ static inline xfs_agblock_t XFS_DADDR_TO_AGBNO(xfs_mount_t *mp, xfs_daddr_t d) */ typedef struct xfs_mod_sb { xfs_sb_field_t msb_field; /* Field to modify, see below */ - int msb_delta; /* change to make to the specified field */ + int msb_delta; /* Change to make to specified field */ } xfs_mod_sb_t; #define XFS_MOUNT_ILOCK(mp) mutex_lock(&((mp)->m_ilock), PINOD) @@ -455,24 +534,26 @@ typedef struct xfs_mod_sb { #define XFS_SB_LOCK(mp) mutex_spinlock(&(mp)->m_sb_lock) #define XFS_SB_UNLOCK(mp,s) mutex_spinunlock(&(mp)->m_sb_lock,(s)) -void xfs_mod_sb(xfs_trans_t *, __int64_t); -xfs_mount_t *xfs_mount_init(void); -void xfs_mount_free(xfs_mount_t *mp, int remove_bhv); -int xfs_mountfs(struct vfs *, xfs_mount_t *mp, dev_t, int); - -int xfs_unmountfs(xfs_mount_t *, struct cred *); -void xfs_unmountfs_close(xfs_mount_t *, struct cred *); -int xfs_unmountfs_writesb(xfs_mount_t *); -int xfs_unmount_flush(xfs_mount_t *, int); -int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int, int); -int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, uint, int); -int xfs_readsb(xfs_mount_t *mp); -struct xfs_buf *xfs_getsb(xfs_mount_t *, int); -void xfs_freesb(xfs_mount_t *); -void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int); -int xfs_syncsub(xfs_mount_t *, int, int, int *); -void xfs_initialize_perag(xfs_mount_t *, int); -void xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t, __int64_t); +extern xfs_mount_t *xfs_mount_init(void); +extern void xfs_mod_sb(xfs_trans_t *, __int64_t); +extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv); +extern int xfs_mountfs(struct vfs *, xfs_mount_t *mp, dev_t, int); + +extern int xfs_unmountfs(xfs_mount_t *, struct cred *); +extern void xfs_unmountfs_close(xfs_mount_t *, struct cred *); +extern int xfs_unmountfs_writesb(xfs_mount_t *); +extern int xfs_unmount_flush(xfs_mount_t *, int); +extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int, int); +extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, + uint, int); +extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int); +extern int xfs_readsb(xfs_mount_t *mp); +extern void xfs_freesb(xfs_mount_t *); +extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int); +extern int xfs_syncsub(xfs_mount_t *, int, int, int *); +extern void xfs_initialize_perag(xfs_mount_t *, int); +extern void xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t, + __int64_t); /* * Flags for freeze operations. @@ -480,11 +561,19 @@ void xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t, __int64_t); #define XFS_FREEZE_WRITE 1 #define XFS_FREEZE_TRANS 2 -void xfs_start_freeze(xfs_mount_t *, int); -void xfs_finish_freeze(xfs_mount_t *); -void xfs_check_frozen(xfs_mount_t *, bhv_desc_t *, int); +extern void xfs_start_freeze(xfs_mount_t *, int); +extern void xfs_finish_freeze(xfs_mount_t *); +extern void xfs_check_frozen(xfs_mount_t *, bhv_desc_t *, int); + +extern struct vfsops xfs_vfsops; +extern struct vnodeops xfs_vnodeops; + +extern struct xfs_dmops xfs_dmcore_xfs; +extern struct xfs_qmops xfs_qmcore_xfs; +extern struct xfs_ioops xfs_iocore_xfs; -extern struct vfsops xfs_vfsops; +extern int xfs_init(void); +extern void xfs_cleanup(void); #endif /* __KERNEL__ */ diff --git a/fs/xfs/xfs_qmops.c b/fs/xfs/xfs_qmops.c new file mode 100644 index 000000000000..75d1029ceb77 --- /dev/null +++ b/fs/xfs/xfs_qmops.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU 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. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#include <xfs.h> + +#ifndef CONFIG_XFS_QUOTA +STATIC struct xfs_dquot * +xfs_dqvopchown_default( + struct xfs_trans *tp, + struct xfs_inode *ip, + struct xfs_dquot **dqp, + struct xfs_dquot *dq) +{ + return NULL; +} + +xfs_qmops_t xfs_qmcore_xfs = { + .xfs_qminit = (xfs_qminit_t) fs_noerr, + .xfs_qmdone = (xfs_qmdone_t) fs_noerr, + .xfs_qmmount = (xfs_qmmount_t) fs_noerr, + .xfs_qmunmount = (xfs_qmunmount_t) fs_noerr, + .xfs_dqrele = (xfs_dqrele_t) fs_noerr, + .xfs_dqattach = (xfs_dqattach_t) fs_noerr, + .xfs_dqdetach = (xfs_dqdetach_t) fs_noerr, + .xfs_dqpurgeall = (xfs_dqpurgeall_t) fs_noerr, + .xfs_dqvopalloc = (xfs_dqvopalloc_t) fs_noerr, + .xfs_dqvopcreate = (xfs_dqvopcreate_t) fs_noerr, + .xfs_dqvoprename = (xfs_dqvoprename_t) fs_noerr, + .xfs_dqvopchown = xfs_dqvopchown_default, + .xfs_dqvopchownresv = (xfs_dqvopchownresv_t) fs_noerr, +}; +#endif /* CONFIG_XFS_QUOTA */ diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 37639212e07d..57c2bb304aa3 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -33,6 +33,12 @@ #define __XFS_QUOTA_H__ /* + * The ondisk form of a dquot structure. + */ +#define XFS_DQUOT_MAGIC 0x4451 /* 'DQ' */ +#define XFS_DQUOT_VERSION (u_int8_t)0x01 /* latest version number */ + +/* * uid_t and gid_t are hard-coded to 32 bits in the inode. * Hence, an 'id' in a dquot is 32 bits.. */ @@ -47,6 +53,100 @@ typedef __uint64_t xfs_qcnt_t; typedef __uint16_t xfs_qwarncnt_t; /* + * This is the main portion of the on-disk representation of quota + * information for a user. This is the q_core of the xfs_dquot_t that + * is kept in kernel memory. We pad this with some more expansion room + * to construct the on disk structure. + */ +typedef struct xfs_disk_dquot { +/*16*/ u_int16_t d_magic; /* dquot magic = XFS_DQUOT_MAGIC */ +/*8 */ u_int8_t d_version; /* dquot version */ +/*8 */ u_int8_t d_flags; /* XFS_DQ_USER/PROJ/GROUP */ +/*32*/ xfs_dqid_t d_id; /* user,project,group id */ +/*64*/ xfs_qcnt_t d_blk_hardlimit;/* absolute limit on disk blks */ +/*64*/ xfs_qcnt_t d_blk_softlimit;/* preferred limit on disk blks */ +/*64*/ xfs_qcnt_t d_ino_hardlimit;/* maximum # allocated inodes */ +/*64*/ xfs_qcnt_t d_ino_softlimit;/* preferred inode limit */ +/*64*/ xfs_qcnt_t d_bcount; /* disk blocks owned by the user */ +/*64*/ xfs_qcnt_t d_icount; /* inodes owned by the user */ +/*32*/ __int32_t d_itimer; /* zero if within inode limits if not, + this is when we refuse service */ +/*32*/ __int32_t d_btimer; /* similar to above; for disk blocks */ +/*16*/ xfs_qwarncnt_t d_iwarns; /* warnings issued wrt num inodes */ +/*16*/ xfs_qwarncnt_t d_bwarns; /* warnings issued wrt disk blocks */ +/*32*/ __int32_t d_pad0; /* 64 bit align */ +/*64*/ xfs_qcnt_t d_rtb_hardlimit;/* absolute limit on realtime blks */ +/*64*/ xfs_qcnt_t d_rtb_softlimit;/* preferred limit on RT disk blks */ +/*64*/ xfs_qcnt_t d_rtbcount; /* realtime blocks owned */ +/*32*/ __int32_t d_rtbtimer; /* similar to above; for RT disk blocks */ +/*16*/ xfs_qwarncnt_t d_rtbwarns; /* warnings issued wrt RT disk blocks */ +/*16*/ __uint16_t d_pad; +} xfs_disk_dquot_t; + +/* + * This is what goes on disk. This is separated from the xfs_disk_dquot because + * carrying the unnecessary padding would be a waste of memory. + */ +typedef struct xfs_dqblk { + xfs_disk_dquot_t dd_diskdq; /* portion that lives incore as well */ + char dd_fill[32]; /* filling for posterity */ +} xfs_dqblk_t; + +/* + * flags for q_flags field in the dquot. + */ +#define XFS_DQ_USER 0x0001 /* a user quota */ +/* #define XFS_DQ_PROJ 0x0002 -- project quota (IRIX) */ +#define XFS_DQ_GROUP 0x0004 /* a group quota */ +#define XFS_DQ_FLOCKED 0x0008 /* flush lock taken */ +#define XFS_DQ_DIRTY 0x0010 /* dquot is dirty */ +#define XFS_DQ_WANT 0x0020 /* for lookup/reclaim race */ +#define XFS_DQ_INACTIVE 0x0040 /* dq off mplist & hashlist */ +#define XFS_DQ_MARKER 0x0080 /* sentinel */ + +/* + * In the worst case, when both user and group quotas are on, + * we can have a max of three dquots changing in a single transaction. + */ +#define XFS_DQUOT_LOGRES(mp) (sizeof(xfs_disk_dquot_t) * 3) + + +/* + * These are the structures used to lay out dquots and quotaoff + * records on the log. Quite similar to those of inodes. + */ + +/* + * log format struct for dquots. + * The first two fields must be the type and size fitting into + * 32 bits : log_recovery code assumes that. + */ +typedef struct xfs_dq_logformat { + __uint16_t qlf_type; /* dquot log item type */ + __uint16_t qlf_size; /* size of this item */ + xfs_dqid_t qlf_id; /* usr/grp id number : 32 bits */ + __int64_t qlf_blkno; /* blkno of dquot buffer */ + __int32_t qlf_len; /* len of dquot buffer */ + __uint32_t qlf_boffset; /* off of dquot in buffer */ +} xfs_dq_logformat_t; + +/* + * log format struct for QUOTAOFF records. + * The first two fields must be the type and size fitting into + * 32 bits : log_recovery code assumes that. + * We write two LI_QUOTAOFF logitems per quotaoff, the last one keeps a pointer + * to the first and ensures that the first logitem is taken out of the AIL + * only when the last one is securely committed. + */ +typedef struct xfs_qoff_logformat { + unsigned short qf_type; /* quotaoff log item type */ + unsigned short qf_size; /* size of this item */ + unsigned int qf_flags; /* USR and/or GRP */ + char qf_pad[12]; /* padding for future */ +} xfs_qoff_logformat_t; + + +/* * Disk quotas status in m_qflags, and also sb_qflags. 16 bits. */ #define XFS_UQUOTA_ACCT 0x0001 /* user quota accounting ON */ @@ -134,13 +234,14 @@ typedef __uint16_t xfs_qwarncnt_t; #define XFS_QMOPT_QUOTALL (XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA) #define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS) +#ifdef __KERNEL__ /* * This check is done typically without holding the inode lock; * that may seem racey, but it is harmless in the context that it is used. * The inode cannot go inactive as long a reference is kept, and * therefore if dquot(s) were attached, they'll stay consistent. * If, for example, the ownership of the inode changes while - * we didnt have the inode locked, the appropriate dquot(s) will be + * we didn't have the inode locked, the appropriate dquot(s) will be * attached atomically. */ #define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\ @@ -161,190 +262,93 @@ typedef __uint16_t xfs_qwarncnt_t; #define XFS_MOUNT_QUOTA_MASK (XFS_MOUNT_QUOTA_ALL | XFS_UQUOTA_ACTIVE | \ XFS_GQUOTA_ACTIVE) -#define XFS_IS_REALTIME_INODE(ip) ((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME) - - -#ifdef __KERNEL__ - -#ifdef CONFIG_XFS_QUOTA -/* - * External Interface to the XFS disk quota subsystem. - */ -struct xfs_disk_dquot; -struct xfs_dqhash; -struct xfs_dquot; -struct xfs_inode; -struct xfs_mount; -struct xfs_trans; - -/* - * Quota Manager Interface. - */ -extern struct xfs_qm *xfs_qm_init(void); -extern void xfs_qm_destroy(struct xfs_qm *); -extern int xfs_qm_dqflush_all(struct xfs_mount *, int); -extern int xfs_qm_dqattach(struct xfs_inode *, uint); -extern int xfs_qm_dqpurge_all(struct xfs_mount *, uint); -extern void xfs_qm_mount_quotainit(struct xfs_mount *, uint); -extern void xfs_qm_unmount_quotadestroy(struct xfs_mount *); -extern int xfs_qm_mount_quotas(struct xfs_mount *); -extern int xfs_qm_unmount_quotas(struct xfs_mount *); -extern void xfs_qm_dqdettach_inode(struct xfs_inode *); -extern int xfs_qm_sync(struct xfs_mount *, short); /* - * Dquot interface. + * The structure kept inside the xfs_trans_t keep track of dquot changes + * within a transaction and apply them later. */ -extern void xfs_dqlock(struct xfs_dquot *); -extern void xfs_dqunlock(struct xfs_dquot *); -extern void xfs_dqunlock_nonotify(struct xfs_dquot *); -extern void xfs_dqlock2(struct xfs_dquot *, struct xfs_dquot *); -extern void xfs_qm_dqput(struct xfs_dquot *); -extern void xfs_qm_dqrele(struct xfs_dquot *); -extern xfs_dqid_t xfs_qm_dqid(struct xfs_dquot *); -extern int xfs_qm_dqget(struct xfs_mount *, - struct xfs_inode *, xfs_dqid_t, - uint, uint, struct xfs_dquot **); -extern int xfs_qm_dqcheck(struct xfs_disk_dquot *, - xfs_dqid_t, uint, uint, char *); +typedef struct xfs_dqtrx { + struct xfs_dquot *qt_dquot; /* the dquot this refers to */ + ulong qt_blk_res; /* blks reserved on a dquot */ + ulong qt_blk_res_used; /* blks used from the reservation */ + ulong qt_ino_res; /* inode reserved on a dquot */ + ulong qt_ino_res_used; /* inodes used from the reservation */ + long qt_bcount_delta; /* dquot blk count changes */ + long qt_delbcnt_delta; /* delayed dquot blk count changes */ + long qt_icount_delta; /* dquot inode count changes */ + ulong qt_rtblk_res; /* # blks reserved on a dquot */ + ulong qt_rtblk_res_used;/* # blks used from reservation */ + long qt_rtbcount_delta;/* dquot realtime blk changes */ + long qt_delrtb_delta; /* delayed RT blk count changes */ +} xfs_dqtrx_t; /* - * Vnodeops specific code that should actually be _in_ xfs_vnodeops.c, but - * is here because it's nicer to keep vnodeops (therefore, XFS) lean - * and clean. + * Dquot transaction functions, used if quota is enabled. */ -extern struct xfs_dquot * xfs_qm_vop_chown(struct xfs_trans *, - struct xfs_inode *, - struct xfs_dquot **, - struct xfs_dquot *); -extern int xfs_qm_vop_dqalloc(struct xfs_mount *, - struct xfs_inode *, - uid_t, gid_t, uint, - struct xfs_dquot **, - struct xfs_dquot **); - -extern int xfs_qm_vop_chown_reserve(struct xfs_trans *, - struct xfs_inode *, - struct xfs_dquot *, - struct xfs_dquot *, - uint); - -extern int xfs_qm_vop_rename_dqattach(struct xfs_inode **); -extern void xfs_qm_vop_dqattach_and_dqmod_newinode( - struct xfs_trans *, - struct xfs_inode *, - struct xfs_dquot *, - struct xfs_dquot *); - - -/* - * Dquot Transaction interface - */ -extern void xfs_trans_alloc_dqinfo(struct xfs_trans *); -extern void xfs_trans_free_dqinfo(struct xfs_trans *); -extern void xfs_trans_dup_dqinfo(struct xfs_trans *, - struct xfs_trans *); -extern void xfs_trans_mod_dquot(struct xfs_trans *, - struct xfs_dquot *, - uint, long); -extern void xfs_trans_mod_dquot_byino(struct xfs_trans *, - struct xfs_inode *, - uint, long); -extern void xfs_trans_apply_dquot_deltas(struct xfs_trans *); -extern void xfs_trans_unreserve_and_mod_dquots(struct xfs_trans *); - -extern int xfs_trans_reserve_quota_nblks(struct xfs_trans *, - struct xfs_inode *, - long, long, uint); - - -extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, - struct xfs_dquot *, - struct xfs_dquot *, - long, long, uint); -extern void xfs_trans_log_dquot(struct xfs_trans *, - struct xfs_dquot *); -extern void xfs_trans_dqjoin(struct xfs_trans *, - struct xfs_dquot *); -extern void xfs_qm_dqrele_all_inodes(struct xfs_mount *, uint); - -# define _XQM_ZONE_DESTROY(z) ((z)? kmem_cache_destroy(z) : (void)0) - -#else -# define xfs_qm_init() (NULL) -# define xfs_qm_destroy(xqm) do { } while (0) -# define xfs_qm_dqflush_all(m,t) (ENOSYS) -# define xfs_qm_dqattach(i,t) (ENOSYS) -# define xfs_qm_dqpurge_all(m,t) (ENOSYS) -# define xfs_qm_mount_quotainit(m,t) do { } while (0) -# define xfs_qm_unmount_quotadestroy(m) do { } while (0) -# define xfs_qm_mount_quotas(m) (ENOSYS) -# define xfs_qm_unmount_quotas(m) (ENOSYS) -# define xfs_qm_dqdettach_inode(i) do { } while (0) -# define xfs_qm_sync(m,t) (ENOSYS) -# define xfs_dqlock(d) do { } while (0) -# define xfs_dqunlock(d) do { } while (0) -# define xfs_dqunlock_nonotify(d) do { } while (0) -# define xfs_dqlock2(d1,d2) do { } while (0) -# define xfs_qm_dqput(d) do { } while (0) -# define xfs_qm_dqrele(d) do { } while (0) -# define xfs_qm_dqid(d) (-1) -# define xfs_qm_dqget(m,i,di,t,f,d) (ENOSYS) -# define xfs_qm_dqcheck(dd,di,t,f,s) (ENOSYS) -# define xfs_trans_alloc_dqinfo(t) do { } while (0) -# define xfs_trans_free_dqinfo(t) do { } while (0) -# define xfs_trans_dup_dqinfo(t1,t2) do { } while (0) -# define xfs_trans_mod_dquot(t,d,f,x) do { } while (0) -# define xfs_trans_mod_dquot_byino(t,i,f,x) do { } while (0) -# define xfs_trans_apply_dquot_deltas(t) do { } while (0) -# define xfs_trans_unreserve_and_mod_dquots(t) do { } while (0) -# define xfs_trans_reserve_quota_nblks(t,i,nb,ni,f) (ENOSYS) -# define xfs_trans_reserve_quota_bydquots(t,x,y,b,i,f) (ENOSYS) -# define xfs_trans_log_dquot(t,d) do { } while (0) -# define xfs_trans_dqjoin(t,d) do { } while (0) -# define xfs_qm_dqrele_all_inodes(m,t) do { } while (0) -# define xfs_qm_vop_chown(t,i,d1,d2) (NULL) -# define xfs_qm_vop_dqalloc(m,i,u,g,f,d1,d2) (ENOSYS) -# define xfs_qm_vop_chown_reserve(t,i,d1,d2,f) (ENOSYS) -# define xfs_qm_vop_rename_dqattach(i) (ENOSYS) -# define xfs_qm_vop_dqattach_and_dqmod_newinode(t,i,x,y) do { } while (0) -# define _XQM_ZONE_DESTROY(z) do { } while (0) -#endif /* CONFIG_XFS_QUOTA */ - -/* - * Regular disk block quota reservations - */ -#define xfs_trans_reserve_blkquota(tp, ip, nblks) \ -xfs_trans_reserve_quota_nblks(tp, ip, nblks, 0, XFS_QMOPT_RES_REGBLKS) - -#define xfs_trans_reserve_blkquota_force(tp, ip, nblks) \ -xfs_trans_reserve_quota_nblks(tp, ip, nblks, 0, \ - XFS_QMOPT_RES_REGBLKS|XFS_QMOPT_FORCE_RES) - -#define xfs_trans_unreserve_blkquota(tp, ip, nblks) \ -(void)xfs_trans_reserve_quota_nblks(tp, ip, -(nblks), 0, XFS_QMOPT_RES_REGBLKS) - -#define xfs_trans_reserve_quota(tp, udq, gdq, nb, ni, f) \ -xfs_trans_reserve_quota_bydquots(tp, udq, gdq, nb, ni, f|XFS_QMOPT_RES_REGBLKS) - -#define xfs_trans_unreserve_quota(tp, ud, gd, b, i, f) \ -xfs_trans_reserve_quota_bydquots(tp, ud, gd, -(b), -(i), f|XFS_QMOPT_RES_REGBLKS) - -/* - * Realtime disk block quota reservations - */ -#define xfs_trans_reserve_rtblkquota(mp, tp, ip, nblks) \ -xfs_trans_reserve_quota_nblks(tp, ip, nblks, 0, XFS_QMOPT_RES_RTBLKS) - -#define xfs_trans_unreserve_rtblkquota(tp, ip, nblks) \ -(void)xfs_trans_reserve_quota_nblks(tp, ip, -(nblks), 0, XFS_QMOPT_RES_RTBLKS) - -#define xfs_trans_reserve_rtquota(mp, tp, uq, pq, blks, f) \ -xfs_trans_reserve_quota_bydquots(mp, tp, uq, pq, blks, 0, f|XFS_QMOPT_RES_RTBLKS) - -#define xfs_trans_unreserve_rtquota(tp, uq, pq, blks) \ -xfs_trans_reserve_quota_bydquots(tp, uq, pq, -(blks), XFS_QMOPT_RES_RTBLKS) - +typedef void (*qo_dup_dqinfo_t)(struct xfs_trans *, struct xfs_trans *); +typedef void (*qo_mod_dquot_byino_t)(struct xfs_trans *, + struct xfs_inode *, uint, long); +typedef void (*qo_free_dqinfo_t)(struct xfs_trans *); +typedef void (*qo_apply_dquot_deltas_t)(struct xfs_trans *); +typedef void (*qo_unreserve_and_mod_dquots_t)(struct xfs_trans *); +typedef int (*qo_reserve_quota_nblks_t)( + struct xfs_trans *, struct xfs_mount *, + struct xfs_inode *, long, long, uint); +typedef int (*qo_reserve_quota_bydquots_t)( + struct xfs_trans *, struct xfs_mount *, + struct xfs_dquot *, struct xfs_dquot *, + long, long, uint); +typedef struct xfs_dqtrxops { + qo_dup_dqinfo_t qo_dup_dqinfo; + qo_free_dqinfo_t qo_free_dqinfo; + qo_mod_dquot_byino_t qo_mod_dquot_byino; + qo_apply_dquot_deltas_t qo_apply_dquot_deltas; + qo_reserve_quota_nblks_t qo_reserve_quota_nblks; + qo_reserve_quota_bydquots_t qo_reserve_quota_bydquots; + qo_unreserve_and_mod_dquots_t qo_unreserve_and_mod_dquots; +} xfs_dqtrxops_t; + +#define XFS_DQTRXOP(mp, tp, op, args...) \ + ((mp)->m_qm_ops.xfs_dqtrxops ? \ + ((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0) + +#define XFS_TRANS_DUP_DQINFO(mp, otp, ntp) \ + XFS_DQTRXOP(mp, otp, qo_dup_dqinfo, ntp) +#define XFS_TRANS_FREE_DQINFO(mp, tp) \ + XFS_DQTRXOP(mp, tp, qo_free_dqinfo) +#define XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, field, delta) \ + XFS_DQTRXOP(mp, tp, qo_mod_dquot_byino, ip, field, delta) +#define XFS_TRANS_APPLY_DQUOT_DELTAS(mp, tp) \ + XFS_DQTRXOP(mp, tp, qo_apply_dquot_deltas) +#define XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, ninos, fl) \ + XFS_DQTRXOP(mp, tp, qo_reserve_quota_nblks, mp, ip, nblks, ninos, fl) +#define XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, fl) \ + XFS_DQTRXOP(mp, tp, qo_reserve_quota_bydquots, mp, ud, gd, nb, ni, fl) +#define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \ + XFS_DQTRXOP(mp, tp, qo_unreserve_and_mod_dquots) + +#define XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, nblks) \ + XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \ + XFS_QMOPT_RES_REGBLKS) +#define XFS_TRANS_RESERVE_BLKQUOTA_FORCE(mp, tp, ip, nblks) \ + XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \ + XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES) +#define XFS_TRANS_UNRESERVE_BLKQUOTA(mp, tp, ip, nblks) \ + XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, -(nblks), 0, \ + XFS_QMOPT_RES_REGBLKS) +#define XFS_TRANS_RESERVE_QUOTA(mp, tp, ud, gd, nb, ni, f) \ + XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, \ + f | XFS_QMOPT_RES_REGBLKS) +#define XFS_TRANS_UNRESERVE_QUOTA(mp, tp, ud, gd, nb, ni, f) \ + XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, -(nb), -(ni), \ + f | XFS_QMOPT_RES_REGBLKS) + +extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *); + +extern struct bhv_vfsops xfs_qmops; + +extern void xfs_qm_init(void); +extern void xfs_qm_exit(void); #endif /* __KERNEL__ */ diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c index 616c1baf2d0a..dc6b2b1dd4d4 100644 --- a/fs/xfs/xfs_rename.c +++ b/fs/xfs/xfs_rename.c @@ -261,11 +261,12 @@ xfs_rename( src_dp = XFS_BHVTOI(src_dir_bdp); target_dp = XFS_BHVTOI(target_dir_bdp); + mp = src_dp->i_mount; if (DM_EVENT_ENABLED(src_dir_vp->v_vfsp, src_dp, DM_EVENT_RENAME) || DM_EVENT_ENABLED(target_dir_vp->v_vfsp, target_dp, DM_EVENT_RENAME)) { - error = dm_send_namesp_event(DM_EVENT_RENAME, + error = XFS_SEND_NAMESP(mp, DM_EVENT_RENAME, src_dir_bdp, DM_RIGHT_NULL, target_dir_bdp, DM_RIGHT_NULL, src_name, target_name, @@ -323,7 +324,6 @@ xfs_rename( xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED); XFS_BMAP_INIT(&free_list, &first_block); - mp = src_dp->i_mount; tp = xfs_trans_alloc(mp, XFS_TRANS_RENAME); cancel_flags = XFS_TRANS_RELEASE_LOG_RES; spaceres = XFS_RENAME_SPACE_RES(mp, target_namelen); @@ -343,12 +343,10 @@ xfs_rename( /* * Attach the dquots to the inodes */ - if (XFS_IS_QUOTA_ON(mp)) { - if ((error = xfs_qm_vop_rename_dqattach(inodes))) { - xfs_trans_cancel(tp, cancel_flags); - rename_which_error_return = __LINE__; - goto rele_return; - } + if ((error = XFS_QM_DQVOPRENAME(mp, inodes))) { + xfs_trans_cancel(tp, cancel_flags); + rename_which_error_return = __LINE__; + goto rele_return; } /* @@ -625,7 +623,7 @@ std_return: if (DM_EVENT_ENABLED(src_dir_vp->v_vfsp, src_dp, DM_EVENT_POSTRENAME) || DM_EVENT_ENABLED(target_dir_vp->v_vfsp, target_dp, DM_EVENT_POSTRENAME)) { - (void) dm_send_namesp_event(DM_EVENT_POSTRENAME, + (void) XFS_SEND_NAMESP (mp, DM_EVENT_POSTRENAME, src_dir_bdp, DM_RIGHT_NULL, target_dir_bdp, DM_RIGHT_NULL, src_name, target_name, diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h index 286436f823d1..19e70410788d 100644 --- a/fs/xfs/xfs_rtalloc.h +++ b/fs/xfs/xfs_rtalloc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -35,6 +35,8 @@ struct xfs_mount; struct xfs_trans; +#define XFS_IS_REALTIME_INODE(ip) ((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME) + /* Min and max rt extent sizes, specified in bytes */ #define XFS_MAX_RTEXTSIZE (1024 * 1024 * 1024) /* 1GB */ #define XFS_DFL_RTEXTSIZE (64 * 1024) /* 64KB */ diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 599ec46ec7a6..fe1050a8ea95 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -173,11 +173,7 @@ xfs_trans_dup( ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used; tp->t_rtx_res = tp->t_rtx_res_used; - /* - * dup the dquot stuff too. - */ - if (tp->t_dqinfo) - xfs_trans_dup_dqinfo(tp, ntp); + XFS_TRANS_DUP_DQINFO(tp->t_mountp, tp, ntp); atomic_inc(&tp->t_mountp->m_active_trans); return ntp; @@ -703,9 +699,7 @@ shut_us_down: * means is that we have some (non-persistent) quota * reservations that need to be unreserved. */ - if (tp->t_dqinfo && (tp->t_flags & XFS_TRANS_DQ_DIRTY)) { - xfs_trans_unreserve_and_mod_dquots(tp); - } + XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp); if (tp->t_ticket) { commit_lsn = xfs_log_done(mp, tp->t_ticket, NULL, log_flags); @@ -733,9 +727,7 @@ shut_us_down: if (tp->t_flags & XFS_TRANS_SB_DIRTY) { xfs_trans_apply_sb_deltas(tp); } - if (tp->t_flags & XFS_TRANS_DQ_DIRTY) { - xfs_trans_apply_dquot_deltas(tp); - } + XFS_TRANS_APPLY_DQUOT_DELTAS(mp, tp); /* * Ask each log item how many log_vector entries it will @@ -955,9 +947,7 @@ xfs_trans_uncommit( } xfs_trans_unreserve_and_mod_sb(tp); - if (tp->t_dqinfo && (tp->t_flags & XFS_TRANS_DQ_DIRTY)) { - xfs_trans_unreserve_and_mod_dquots(tp); - } + XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(tp->t_mountp, tp); xfs_trans_free_items(tp, flags); xfs_trans_free_busy(tp); @@ -1079,9 +1069,7 @@ xfs_trans_cancel( } #endif xfs_trans_unreserve_and_mod_sb(tp); - - if (tp->t_dqinfo && (tp->t_flags & XFS_TRANS_DQ_DIRTY)) - xfs_trans_unreserve_and_mod_dquots(tp); + XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(tp->t_mountp, tp); if (tp->t_ticket) { if (flags & XFS_TRANS_RELEASE_LOG_RES) { @@ -1110,8 +1098,7 @@ xfs_trans_free( xfs_trans_t *tp) { atomic_dec(&tp->t_mountp->m_active_trans); - if (tp->t_dqinfo) - xfs_trans_free_dqinfo(tp); + XFS_TRANS_FREE_DQINFO(tp->t_mountp, tp); kmem_zone_free(xfs_trans_zone, tp); } diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index ed091cb1ce99..23264a5b9cdc 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -64,7 +64,6 @@ typedef struct xfs_trans_header { #define XFS_LI_BUF 0x123c /* v2 bufs, variable sized inode bufs */ #define XFS_LI_DQUOT 0x123d #define XFS_LI_QUOTAOFF 0x123e -#define XFS_LI_RPC 0x123f /* CXFS RPC return info */ /* * Transaction types. Used to distinguish types of buffers. @@ -1014,10 +1013,7 @@ void xfs_trans_log_efd_extent(xfs_trans_t *, struct xfs_efd_log_item *, xfs_fsblock_t, xfs_extlen_t); -void xfs_trans_log_create_rpc(xfs_trans_t *, int, xfs_ino_t); -void xfs_trans_log_setattr_rpc(xfs_trans_t *, int); int xfs_trans_commit(xfs_trans_t *, uint flags, xfs_lsn_t *); -void xfs_trans_commit_async(struct xfs_mount *); void xfs_trans_cancel(xfs_trans_t *, int); void xfs_trans_ail_init(struct xfs_mount *); xfs_lsn_t xfs_trans_push_ail(struct xfs_mount *, xfs_lsn_t); diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index 9059b4261e89..c4d552a134e3 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c @@ -232,7 +232,7 @@ xfs_dir_ialloc( xfs_buf_relse(ialloc_context); if (dqinfo) { tp->t_dqinfo = dqinfo; - xfs_trans_free_dqinfo(tp); + XFS_TRANS_FREE_DQINFO(tp->t_mountp, tp); } *tpp = ntp; *ipp = NULL; @@ -254,7 +254,7 @@ xfs_dir_ialloc( *ipp = NULL; return code; } - xfs_trans_bjoin (tp, ialloc_context); + xfs_trans_bjoin(tp, ialloc_context); /* * Call ialloc again. Since we've locked out all diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index a78344c9113d..dff3827adec4 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -1,7 +1,7 @@ /* * XFS filesystem operations. * - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -68,7 +68,6 @@ xfs_init(void) spinlock_init(&xfs_dabuf_global_lock, "xfsda"); #endif mutex_init(&xfs_uuidtabmon, MUTEX_DEFAULT, "xfs_uuidtab"); - mutex_init(&xfs_Gqm_lock, MUTEX_DEFAULT, "xfs_qmlock"); /* * Initialize all of the zone allocators we use. @@ -175,8 +174,6 @@ xfs_cleanup(void) kmem_cache_destroy(xfs_ifork_zone); kmem_cache_destroy(xfs_ili_zone); kmem_cache_destroy(xfs_chashlist_zone); - _XQM_ZONE_DESTROY(qm_dqzone); - _XQM_ZONE_DESTROY(qm_dqtrxzone); _ACL_ZONE_DESTROY(xfs_acl_zone); #if (defined(DEBUG) || defined(CONFIG_XFS_VNODE_TRACING)) ktrace_uninit(); @@ -248,9 +245,6 @@ xfs_start_flags( if (ap->flags & XFSMNT_NOATIME) mp->m_flags |= XFS_MOUNT_NOATIME; - if (ap->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA)) - xfs_qm_mount_quotainit(mp, ap->flags); - if (ap->flags & XFSMNT_RETERR) mp->m_flags |= XFS_MOUNT_RETERR; @@ -387,11 +381,13 @@ xfs_finish_flags( */ STATIC int xfs_mount( - vfs_t *vfsp, + struct bhv_desc *bhvp, struct xfs_mount_args *args, cred_t *credp) { - xfs_mount_t *mp; + struct vfs *vfsp = bhvtovfs(bhvp); + struct bhv_desc *p; + struct xfs_mount *mp = XFS_BHVTOM(bhvp); struct block_device *ddev, *logdev, *rtdev; int ronly = (vfsp->vfs_flag & VFS_RDONLY); int flags = 0, error; @@ -400,23 +396,18 @@ xfs_mount( logdev = rtdev = NULL; /* - * Allocate VFS private data (xfs mount structure). - */ - mp = xfs_mount_init(); - - /* * Open real time and log devices - order is important. */ if (args->logname[0]) { error = xfs_blkdev_get(mp, args->logname, &logdev); if (error) - goto free_mp; + return error; } if (args->rtname[0]) { error = xfs_blkdev_get(mp, args->rtname, &rtdev); if (error) { xfs_blkdev_put(logdev); - goto free_mp; + return error; } if (rtdev == ddev || rtdev == logdev) { @@ -424,33 +415,47 @@ xfs_mount( "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev."); xfs_blkdev_put(logdev); xfs_blkdev_put(rtdev); - error = EINVAL; - goto free_mp; + return EINVAL; } } - vfs_insertbhv(vfsp, &mp->m_bhv, &xfs_vfsops, mp); + /* + * Setup xfs_mount function vectors from available behaviors + */ + p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM); + mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_xfs; + p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM); + mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_xfs; + p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO); + mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs; + /* + * Setup xfs_mount buffer target pointers + */ mp->m_ddev_targp = xfs_alloc_buftarg(ddev); if (rtdev) mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev); mp->m_logdev_targp = (logdev && logdev != ddev) ? xfs_alloc_buftarg(logdev) : mp->m_ddev_targp; + /* + * Setup flags based on mount(2) options and then the superblock + */ error = xfs_start_flags(args, mp, ronly); if (error) goto error; - error = xfs_readsb(mp); if (error) goto error; - error = xfs_finish_flags(args, mp, ronly); if (error) { xfs_freesb(mp); goto error; } + /* + * Setup xfs_mount buffer target pointers based on superblock + */ xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize, mp->m_sb.sb_sectsize); if (logdev && logdev != ddev) { @@ -465,10 +470,8 @@ xfs_mount( xfs_setsize_buftarg(mp->m_rtdev_targp, mp->m_sb.sb_blocksize, mp->m_sb.sb_blocksize); - error = xfs_mountfs(vfsp, mp, ddev->bd_dev, flags); - if (error) - goto error; - return 0; + if (!(error = XFS_IOINIT(vfsp, args, flags))) + return 0; error: xfs_binval(mp->m_ddev_targp); @@ -479,9 +482,6 @@ xfs_mount( xfs_binval(mp->m_rtdev_targp); } xfs_unmountfs_close(mp, NULL); - - free_mp: - xfs_mount_free(mp, 1); return error; } @@ -523,8 +523,9 @@ xfs_ibusy( continue; } #ifdef DEBUG - printk("busy vp=0x%p ip=0x%p inum %Ld count=%d\n", - vp, ip, ip->i_ino, vn_count(vp)); + cmn_err(CE_WARN, "%s: busy vp=0x%p ip=0x%p " + "inum %Ld count=%d", + __FUNCTION__, vp, ip, ip->i_ino, vn_count(vp)); #endif busy++; } @@ -543,16 +544,15 @@ xfs_unmount( int flags, cred_t *credp) { - xfs_mount_t *mp; - xfs_inode_t *rip; - vnode_t *rvp = 0; struct vfs *vfsp = bhvtovfs(bdp); + xfs_mount_t *mp = XFS_BHVTOM(bdp); + xfs_inode_t *rip; + vnode_t *rvp; int unmount_event_wanted = 0; int unmount_event_flags = 0; int xfs_unmountfs_needed = 0; int error; - mp = XFS_BHVTOM(bdp); rip = mp->m_rootip; rvp = XFS_ITOV(rip); @@ -560,7 +560,7 @@ xfs_unmount( bhv_desc_t *rbdp; rbdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(rvp), &xfs_vnodeops); - error = dm_send_namesp_event(DM_EVENT_PREUNMOUNT, + error = XFS_SEND_NAMESP(mp, DM_EVENT_PREUNMOUNT, rbdp, DM_RIGHT_NULL, rbdp, DM_RIGHT_NULL, NULL, NULL, 0, 0, (mp->m_dmevmask & (1<<DM_EVENT_PREUNMOUNT))? @@ -577,7 +577,8 @@ xfs_unmount( */ if (xfs_ibusy(mp)) { error = XFS_ERROR(EBUSY); - printk("xfs_unmount: xfs_ibusy says error/%d\n", error); + cmn_err(CE_ALERT, "%s: xfs_ibusy failed -- error code %d", + __FUNCTION__, error); goto out; } @@ -598,7 +599,7 @@ xfs_unmount( * we want to make sure we invalidate dirty pages that belong to * referenced vnodes as well. */ - if (XFS_FORCED_SHUTDOWN(mp)) { + if (XFS_FORCED_SHUTDOWN(mp)) { error = xfs_sync(&mp->m_bhv, (SYNC_WAIT | SYNC_CLOSE), credp); ASSERT(error != EFSCORRUPTED); @@ -612,9 +613,9 @@ out: */ if (unmount_event_wanted) { /* Note: mp structure must still exist for - * dm_send_unmount_event() call. + * XFS_SEND_UNMOUNT() call. */ - dm_send_unmount_event(vfsp, error == 0 ? rvp : NULL, + XFS_SEND_UNMOUNT(mp, vfsp, error == 0 ? rvp : NULL, DM_RIGHT_NULL, 0, error, unmount_event_flags); } if (xfs_unmountfs_needed) { @@ -641,7 +642,7 @@ xfs_unmount_flush( { xfs_inode_t *rip = mp->m_rootip; xfs_inode_t *rbmip; - xfs_inode_t *rsumip=NULL; + xfs_inode_t *rsumip = NULL; vnode_t *rvp = XFS_ITOV(rip); int error; @@ -675,23 +676,22 @@ xfs_unmount_flush( } /* - * synchronously flush root inode to disk + * Synchronously flush root inode to disk */ error = xfs_iflush(rip, XFS_IFLUSH_SYNC); - if (error == EFSCORRUPTED) goto fscorrupt_out2; if (vn_count(rvp) != 1 && !relocation) { xfs_iunlock(rip, XFS_ILOCK_EXCL); - error = XFS_ERROR(EBUSY); - return (error); + return XFS_ERROR(EBUSY); } + /* * Release dquot that rootinode, rbmino and rsumino might be holding, * flush and purge the quota inodes. */ - error = xfs_qm_unmount_quotas(mp); + error = XFS_QM_UNMOUNT(mp); if (error == EFSCORRUPTED) goto fscorrupt_out2; @@ -701,7 +701,7 @@ xfs_unmount_flush( } xfs_iunlock(rip, XFS_ILOCK_EXCL); - return (0); + return 0; fscorrupt_out: xfs_ifunlock(rip); @@ -709,8 +709,7 @@ fscorrupt_out: fscorrupt_out2: xfs_iunlock(rip, XFS_ILOCK_EXCL); - error = XFS_ERROR(EFSCORRUPTED); - return (error); + return XFS_ERROR(EFSCORRUPTED); } /* @@ -725,12 +724,11 @@ xfs_root( bhv_desc_t *bdp, vnode_t **vpp) { - vnode_t *vp; + vnode_t *vp; vp = XFS_ITOV((XFS_BHVTOM(bdp))->m_rootip); VN_HOLD(vp); *vpp = vp; - return 0; } @@ -1411,23 +1409,6 @@ xfs_syncsub( ASSERT(ipointer_in == B_FALSE); /* - * Get the Quota Manager to flush the dquots in a similar manner. - */ - if (XFS_IS_QUOTA_ON(mp)) { - if ((error = xfs_qm_sync(mp, flags))) { - /* - * If we got an IO error, we will be shutting down. - * So, there's nothing more for us to do here. - */ - ASSERT(error != EIO || XFS_FORCED_SHUTDOWN(mp)); - if (XFS_FORCED_SHUTDOWN(mp)) { - kmem_free(ipointer, sizeof(xfs_iptr_t)); - return XFS_ERROR(error); - } - } - } - - /* * Flushing out dirty data above probably generated more * log activity, so if this isn't vfs_sync() then flush * the log again. If SYNC_WAIT is set then do it synchronously. @@ -1581,16 +1562,17 @@ xfs_vget( vfsops_t xfs_vfsops = { + BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS), + .vfs_parseargs = xfs_parseargs, + .vfs_showargs = xfs_showargs, .vfs_mount = xfs_mount, .vfs_unmount = xfs_unmount, .vfs_root = xfs_root, .vfs_statvfs = xfs_statvfs, .vfs_sync = xfs_sync, .vfs_vget = xfs_vget, + .vfs_dmapiops = (vfs_dmapiops_t)fs_nosys, + .vfs_quotactl = (vfs_quotactl_t)fs_nosys, .vfs_init_vnode = xfs_initialize_vnode, .vfs_force_shutdown = xfs_do_force_shutdown, -#ifdef CONFIG_XFS_DMAPI - .vfs_dmapi_mount = xfs_dm_mount, - .vfs_dmapi_fsys_vector = xfs_dm_get_fsys_vector, -#endif }; diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 593384e38a54..1ad2d54f7027 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -254,28 +254,26 @@ xfs_getattr( */ STATIC int xfs_setattr( - bhv_desc_t *bdp, - vattr_t *vap, - int flags, - cred_t *credp) + bhv_desc_t *bdp, + vattr_t *vap, + int flags, + cred_t *credp) { - xfs_inode_t *ip; - xfs_trans_t *tp; - xfs_mount_t *mp; - int mask; - int code; - uint lock_flags; - uint commit_flags=0; - uid_t uid=0, iuid=0; - gid_t gid=0, igid=0; - int timeflags = 0; - vnode_t *vp; - xfs_prid_t projid=0, iprojid=0; - int privileged; - int mandlock_before, mandlock_after; - uint qflags; - xfs_dquot_t *udqp, *gdqp, *olddquot1, *olddquot2; - int file_owner; + xfs_inode_t *ip; + xfs_trans_t *tp; + xfs_mount_t *mp; + int mask; + int code; + uint lock_flags; + uint commit_flags=0; + uid_t uid=0, iuid=0; + gid_t gid=0, igid=0; + int timeflags = 0; + vnode_t *vp; + xfs_prid_t projid=0, iprojid=0; + int mandlock_before, mandlock_after; + struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; + int file_owner; vp = BHV_TO_VNODE(bdp); vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); @@ -319,7 +317,8 @@ xfs_setattr( * because the i_*dquot fields will get updated anyway. */ if (XFS_IS_QUOTA_ON(mp) && (mask & (XFS_AT_UID|XFS_AT_GID))) { - qflags = 0; + uint qflags = 0; + if (mask & XFS_AT_UID) { uid = vap->va_uid; qflags |= XFS_QMOPT_UQUOTA; @@ -339,8 +338,8 @@ xfs_setattr( */ ASSERT(udqp == NULL); ASSERT(gdqp == NULL); - if ((code = xfs_qm_vop_dqalloc(mp, ip, uid, gid, qflags, - &udqp, &gdqp))) + code = XFS_QM_DQVOPALLOC(mp, ip, uid,gid, qflags, &udqp, &gdqp); + if (code) return (code); } @@ -365,7 +364,7 @@ xfs_setattr( } else { if (DM_EVENT_ENABLED (vp->v_vfsp, ip, DM_EVENT_TRUNCATE) && !(flags & ATTR_DMI)) { - code = xfs_dm_send_data_event (DM_EVENT_TRUNCATE, bdp, + code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, bdp, vap->va_size, 0, AT_DELAY_FLAG(flags), NULL); if (code) { lock_flags = 0; @@ -482,15 +481,10 @@ xfs_setattr( if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) || (XFS_IS_GQUOTA_ON(mp) && igid != gid)) { ASSERT(tp); - /* - * XXX:casey - This may result in unnecessary auditing. - */ - privileged = capable(CAP_FOWNER); - if ((code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, - privileged ? - XFS_QMOPT_FORCE_RES : - 0))) - /* out of quota */ + code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp, + capable(CAP_FOWNER) ? + XFS_QMOPT_FORCE_RES : 0); + if (code) /* out of quota */ goto error_return; } } @@ -520,10 +514,8 @@ xfs_setattr( /* * Make sure that the dquots are attached to the inode. */ - if (XFS_IS_QUOTA_ON(mp) && XFS_NOT_DQATTACHED(mp, ip)) { - if ((code = xfs_qm_dqattach(ip, XFS_QMOPT_ILOCKED))) - goto error_return; - } + if ((code = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED))) + goto error_return; } /* @@ -730,13 +722,8 @@ xfs_setattr( if (XFS_IS_UQUOTA_ON(mp)) { ASSERT(mask & XFS_AT_UID); ASSERT(udqp); - ASSERT(xfs_qm_dqid(udqp) == (xfs_dqid_t)uid); - olddquot1 = xfs_qm_vop_chown(tp, ip, - &ip->i_udquot, - udqp); - /* - * We'll dqrele olddquot at the end. - */ + olddquot1 = XFS_QM_DQVOPCHOWN(mp, tp, ip, + &ip->i_udquot, udqp); } ip->i_d.di_uid = uid; } @@ -744,10 +731,8 @@ xfs_setattr( if (XFS_IS_GQUOTA_ON(mp)) { ASSERT(mask & XFS_AT_GID); ASSERT(gdqp); - ASSERT(xfs_qm_dqid(gdqp) == gid); - olddquot2 = xfs_qm_vop_chown(tp, ip, - &ip->i_gdquot, - gdqp); + olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip, + &ip->i_gdquot, gdqp); } ip->i_d.di_gid = gid; } @@ -802,9 +787,6 @@ xfs_setattr( ip->i_d.di_flags = 0; if (vap->va_xflags & XFS_XFLAG_REALTIME) { ip->i_d.di_flags |= XFS_DIFLAG_REALTIME; - /* This is replicated in the io core for - * CXFS use - */ ip->i_iocore.io_flags |= XFS_IOCORE_RT; } /* can't set PREALLOC this way, just ignore it */ @@ -866,16 +848,12 @@ xfs_setattr( xfs_iunlock(ip, lock_flags); /* - * release any dquot(s) inode had kept before chown + * Release any dquot(s) the inode had kept before chown. */ - if (olddquot1) - xfs_qm_dqrele(olddquot1); - if (olddquot2) - xfs_qm_dqrele(olddquot2); - if (udqp) - xfs_qm_dqrele(udqp); - if (gdqp) - xfs_qm_dqrele(gdqp); + XFS_QM_DQRELE(mp, olddquot1); + XFS_QM_DQRELE(mp, olddquot2); + XFS_QM_DQRELE(mp, udqp); + XFS_QM_DQRELE(mp, gdqp); if (code) { return code; @@ -883,9 +861,9 @@ xfs_setattr( if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_ATTRIBUTE) && !(flags & ATTR_DMI)) { - (void) dm_send_namesp_event (DM_EVENT_ATTRIBUTE, bdp, DM_RIGHT_NULL, - NULL, DM_RIGHT_NULL, NULL, NULL, - 0, 0, AT_DELAY_FLAG(flags)); + (void) XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, bdp, DM_RIGHT_NULL, + NULL, DM_RIGHT_NULL, NULL, NULL, + 0, 0, AT_DELAY_FLAG(flags)); } return 0; @@ -893,10 +871,8 @@ xfs_setattr( commit_flags |= XFS_TRANS_ABORT; /* FALLTHROUGH */ error_return: - if (udqp) - xfs_qm_dqrele(udqp); - if (gdqp) - xfs_qm_dqrele(gdqp); + XFS_QM_DQRELE(mp, udqp); + XFS_QM_DQRELE(mp, gdqp); if (tp) { xfs_trans_cancel(tp, commit_flags); } @@ -1286,14 +1262,8 @@ xfs_inactive_free_eofblocks( /* * Attach the dquots to the inode up front. */ - if (XFS_IS_QUOTA_ON(mp) && - ip->i_ino != mp->m_sb.sb_uquotino && - ip->i_ino != mp->m_sb.sb_gquotino) { - if (XFS_NOT_DQATTACHED(mp, ip)) { - if ((error = xfs_qm_dqattach(ip, 0))) - return (error); - } - } + if ((error = XFS_QM_DQATTACH(mp, ip, 0))) + return (error); /* * There are blocks after the end of file. @@ -1683,7 +1653,7 @@ xfs_inactive( if (ip->i_d.di_nlink == 0 && DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_DESTROY)) { - (void) dm_send_destroy_event(bdp, DM_RIGHT_NULL); + (void) XFS_SEND_DESTROY(mp, bdp, DM_RIGHT_NULL); } error = 0; @@ -1709,14 +1679,9 @@ xfs_inactive( ASSERT(ip->i_d.di_nlink == 0); - if (XFS_IS_QUOTA_ON(mp) && - ip->i_ino != mp->m_sb.sb_uquotino && - ip->i_ino != mp->m_sb.sb_gquotino) { - if (XFS_NOT_DQATTACHED(mp, ip)) { - if ((error = xfs_qm_dqattach(ip, 0))) - return (VN_INACTIVE_CACHE); - } - } + if ((error = XFS_QM_DQATTACH(mp, ip, 0))) + return (VN_INACTIVE_CACHE); + tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); if (truncate) { /* @@ -1826,20 +1791,18 @@ xfs_inactive( * might do that, we need to make sure. Otherwise the * inode might be lost for a long time or forever. */ - if (!XFS_FORCED_SHUTDOWN(tp->t_mountp)) { + if (!XFS_FORCED_SHUTDOWN(mp)) { cmn_err(CE_NOTE, - "xfs_inactive: xfs_ifree() returned an error = %d on %s", - error,tp->t_mountp->m_fsname); - xfs_force_shutdown(tp->t_mountp, XFS_METADATA_IO_ERROR); + "xfs_inactive: xfs_ifree() returned an error = %d on %s", + error, mp->m_fsname); + xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); } xfs_trans_cancel(tp, commit_flags | XFS_TRANS_ABORT); } else { /* * Credit the quota account(s). The inode is gone. */ - if (XFS_IS_QUOTA_ON(tp->t_mountp)) - xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, - -1); + XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_ICOUNT, -1); /* * Just ignore errors at this point. There is @@ -1850,8 +1813,7 @@ xfs_inactive( /* * Release the dquots held by inode, if any. */ - if (ip->i_udquot || ip->i_gdquot) - xfs_qm_dqdettach_inode(ip); + XFS_QM_DQDETACH(mp, ip); xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); @@ -1925,7 +1887,7 @@ xfs_create( uint cancel_flags; int committed; xfs_prid_t prid; - xfs_dquot_t *udqp, *gdqp; + struct xfs_dquot *udqp, *gdqp; uint resblks; int dm_di_mode; int namelen; @@ -1935,22 +1897,22 @@ xfs_create( vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address); dp = XFS_BHVTOI(dir_bdp); + mp = dp->i_mount; dm_di_mode = vap->va_mode|VTTOIF(vap->va_type); namelen = VNAMELEN(dentry); if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_CREATE)) { - error = dm_send_namesp_event(DM_EVENT_CREATE, + error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE, dir_bdp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, name, NULL, dm_di_mode, 0, 0); + if (error) return error; dm_event_sent = 1; } - mp = dp->i_mount; - if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); @@ -1965,14 +1927,10 @@ xfs_create( /* * Make sure that we have allocated dquot(s) on disk. */ - if (XFS_IS_QUOTA_ON(mp)) { - error = xfs_qm_vop_dqalloc(mp, dp, - current->fsuid, current->fsgid, - XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, - &udqp, &gdqp); - if (error) - goto std_return; - } + error = XFS_QM_DQVOPALLOC(mp, dp, current->fsuid, current->fsgid, + XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp); + if (error) + goto std_return; ip = NULL; dp_joined_to_trans = B_FALSE; @@ -2008,13 +1966,10 @@ xfs_create( /* * Reserve disk quota and the inode. */ - if (XFS_IS_QUOTA_ON(mp)) { - if (xfs_trans_reserve_quota(tp, udqp, gdqp, resblks, - 1, 0)) { - error = EDQUOT; - goto error_return; - } - } + error = XFS_TRANS_RESERVE_QUOTA(mp, tp, udqp, gdqp, resblks, 1, 0); + if (error) + goto error_return; + if (resblks == 0 && (error = XFS_DIR_CANENTER(mp, tp, dp, name, namelen))) goto error_return; @@ -2074,9 +2029,7 @@ xfs_create( * These ids of the inode couldn't have changed since the new * inode has been locked ever since it was created. */ - if (XFS_IS_QUOTA_ON(mp)) - xfs_qm_vop_dqattach_and_dqmod_newinode(tp, ip, udqp, - gdqp); + XFS_QM_DQVOPCREATE(mp, tp, ip, udqp, gdqp); /* * xfs_trans_commit normally decrements the vnode ref count @@ -2099,10 +2052,8 @@ xfs_create( goto error_return; } - if (udqp) - xfs_qm_dqrele(udqp); - if (gdqp) - xfs_qm_dqrele(gdqp); + XFS_QM_DQRELE(mp, udqp); + XFS_QM_DQRELE(mp, gdqp); /* * Propogate the fact that the vnode changed after the @@ -2118,7 +2069,7 @@ std_return: if ( (*vpp || (error != 0 && dm_event_sent != 0)) && DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp), DM_EVENT_POSTCREATE)) { - (void) dm_send_namesp_event(DM_EVENT_POSTCREATE, + (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE, dir_bdp, DM_RIGHT_NULL, *vpp ? vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops):NULL, DM_RIGHT_NULL, name, NULL, @@ -2136,10 +2087,8 @@ std_return: if (!dp_joined_to_trans && (dp != NULL)) xfs_iunlock(dp, XFS_ILOCK_EXCL); - if (udqp) - xfs_qm_dqrele(udqp); - if (gdqp) - xfs_qm_dqrele(gdqp); + XFS_QM_DQRELE(mp, udqp); + XFS_QM_DQRELE(mp, gdqp); goto std_return; @@ -2153,10 +2102,8 @@ std_return: xfs_trans_cancel(tp, cancel_flags); IRELE(ip); - if (udqp) - xfs_qm_dqrele(udqp); - if (gdqp) - xfs_qm_dqrele(gdqp); + XFS_QM_DQRELE(mp, udqp); + XFS_QM_DQRELE(mp, gdqp); goto std_return; } @@ -2437,8 +2384,8 @@ xfs_remove( namelen = VNAMELEN(dentry); if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) { - error = dm_send_namesp_event(DM_EVENT_REMOVE, dir_bdp, DM_RIGHT_NULL, - NULL, DM_RIGHT_NULL, + error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dir_bdp, + DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, name, NULL, 0, 0, 0); if (error) return error; @@ -2471,17 +2418,13 @@ xfs_remove( ITRACE(ip); - if (XFS_IS_QUOTA_ON(mp)) { - ASSERT(! error); - if (XFS_NOT_DQATTACHED(mp, dp)) - error = xfs_qm_dqattach(dp, 0); - if (!error && dp != ip && XFS_NOT_DQATTACHED(mp, ip)) - error = xfs_qm_dqattach(ip, 0); - if (error) { - REMOVE_DEBUG_TRACE(__LINE__); - IRELE(ip); - goto std_return; - } + error = XFS_QM_DQATTACH(mp, dp, 0); + if (!error && dp != ip) + error = XFS_QM_DQATTACH(mp, ip, 0); + if (error) { + REMOVE_DEBUG_TRACE(__LINE__); + IRELE(ip); + goto std_return; } tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE); @@ -2606,7 +2549,7 @@ xfs_remove( std_return: if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_POSTREMOVE)) { - (void) dm_send_namesp_event(DM_EVENT_POSTREMOVE, + (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dir_bdp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, name, NULL, dm_di_mode, error, 0); @@ -2690,7 +2633,7 @@ xfs_link( return XFS_ERROR(EIO); if (DM_EVENT_ENABLED(src_vp->v_vfsp, tdp, DM_EVENT_LINK)) { - error = dm_send_namesp_event(DM_EVENT_LINK, + error = XFS_SEND_NAMESP(mp, DM_EVENT_LINK, target_dir_bdp, DM_RIGHT_NULL, src_bdp, DM_RIGHT_NULL, target_name, NULL, 0, 0, 0); @@ -2700,15 +2643,11 @@ xfs_link( /* Return through std_return after this point. */ - if (XFS_IS_QUOTA_ON(mp)) { - error = 0; - if (XFS_NOT_DQATTACHED(mp, sip)) - error = xfs_qm_dqattach(sip, 0); - if (!error && sip != tdp && XFS_NOT_DQATTACHED(mp, tdp)) - error = xfs_qm_dqattach(tdp, 0); - if (error) - goto std_return; - } + error = XFS_QM_DQATTACH(mp, sip, 0); + if (!error && sip != tdp) + error = XFS_QM_DQATTACH(mp, tdp, 0); + if (error) + goto std_return; tp = xfs_trans_alloc(mp, XFS_TRANS_LINK); cancel_flags = XFS_TRANS_RELEASE_LOG_RES; @@ -2798,7 +2737,7 @@ xfs_link( std_return: if (DM_EVENT_ENABLED(src_vp->v_vfsp, sip, DM_EVENT_POSTLINK)) { - (void) dm_send_namesp_event(DM_EVENT_POSTLINK, + (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTLINK, target_dir_bdp, DM_RIGHT_NULL, src_bdp, DM_RIGHT_NULL, target_name, NULL, 0, error, 0); @@ -2813,8 +2752,6 @@ std_return: goto std_return; } - - /* * xfs_mkdir * @@ -2844,7 +2781,7 @@ xfs_mkdir( boolean_t created = B_FALSE; int dm_event_sent = 0; xfs_prid_t prid; - xfs_dquot_t *udqp, *gdqp; + struct xfs_dquot *udqp, *gdqp; uint resblks; int dm_di_mode; int dir_namelen; @@ -2863,7 +2800,7 @@ xfs_mkdir( dm_di_mode = vap->va_mode|VTTOIF(vap->va_type); if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_CREATE)) { - error = dm_send_namesp_event(DM_EVENT_CREATE, + error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE, dir_bdp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, dir_name, NULL, dm_di_mode, 0, 0); @@ -2886,14 +2823,10 @@ xfs_mkdir( /* * Make sure that we have allocated dquot(s) on disk. */ - if (XFS_IS_QUOTA_ON(mp)) { - error = xfs_qm_vop_dqalloc(mp, dp, - current->fsuid, current->fsgid, - XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, - &udqp, &gdqp); - if (error) - goto std_return; - } + error = XFS_QM_DQVOPALLOC(mp, dp, current->fsuid, current->fsgid, + XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); + if (error) + goto std_return; tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR); cancel_flags = XFS_TRANS_RELEASE_LOG_RES; @@ -2925,12 +2858,9 @@ xfs_mkdir( /* * Reserve disk quota and the inode. */ - if (XFS_IS_QUOTA_ON(mp)) { - if (xfs_trans_reserve_quota(tp, udqp, gdqp, resblks, 1, 0)) { - error = XFS_ERROR(EDQUOT); - goto error_return; - } - } + error = XFS_TRANS_RESERVE_QUOTA(mp, tp, udqp, gdqp, resblks, 1, 0); + if (error) + goto error_return; if (resblks == 0 && (error = XFS_DIR_CANENTER(mp, tp, dp, dir_name, dir_namelen))) @@ -2999,9 +2929,7 @@ xfs_mkdir( /* * Attach the dquots to the new inode and modify the icount incore. */ - if (XFS_IS_QUOTA_ON(mp)) { - xfs_qm_vop_dqattach_and_dqmod_newinode(tp, cdp, udqp, gdqp); - } + XFS_QM_DQVOPCREATE(mp, tp, cdp, udqp, gdqp); /* * If this is a synchronous mount, make sure that the @@ -3019,11 +2947,8 @@ xfs_mkdir( } error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); - if (udqp) - xfs_qm_dqrele(udqp); - if (gdqp) - xfs_qm_dqrele(gdqp); - + XFS_QM_DQRELE(mp, udqp); + XFS_QM_DQRELE(mp, gdqp); if (error) { IRELE(cdp); } @@ -3035,7 +2960,7 @@ std_return: if ( (created || (error != 0 && dm_event_sent != 0)) && DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp), DM_EVENT_POSTCREATE)) { - (void) dm_send_namesp_event(DM_EVENT_POSTCREATE, + (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE, dir_bdp, DM_RIGHT_NULL, created ? XFS_ITOBHV(cdp):NULL, DM_RIGHT_NULL, @@ -3051,11 +2976,8 @@ std_return: cancel_flags |= XFS_TRANS_ABORT; error_return: xfs_trans_cancel(tp, cancel_flags); - - if (udqp) - xfs_qm_dqrele(udqp); - if (gdqp) - xfs_qm_dqrele(gdqp); + XFS_QM_DQRELE(mp, udqp); + XFS_QM_DQRELE(mp, gdqp); if (!dp_joined_to_trans && (dp != NULL)) { xfs_iunlock(dp, XFS_ILOCK_EXCL); @@ -3093,6 +3015,7 @@ xfs_rmdir( dir_vp = BHV_TO_VNODE(dir_bdp); dp = XFS_BHVTOI(dir_bdp); + mp = dp->i_mount; vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address); @@ -3101,7 +3024,7 @@ xfs_rmdir( namelen = VNAMELEN(dentry); if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) { - error = dm_send_namesp_event(DM_EVENT_REMOVE, + error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dir_bdp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, name, NULL, 0, 0, 0); @@ -3136,17 +3059,13 @@ xfs_rmdir( /* * Get the dquots for the inodes. */ - if (XFS_IS_QUOTA_ON(mp)) { - ASSERT(! error); - if (XFS_NOT_DQATTACHED(mp, dp)) - error = xfs_qm_dqattach(dp, 0); - if (!error && dp != cdp && XFS_NOT_DQATTACHED(mp, cdp)) - error = xfs_qm_dqattach(cdp, 0); - if (error) { - IRELE(cdp); - REMOVE_DEBUG_TRACE(__LINE__); - goto std_return; - } + error = XFS_QM_DQATTACH(mp, dp, 0); + if (!error && dp != cdp) + error = XFS_QM_DQATTACH(mp, cdp, 0); + if (error) { + IRELE(cdp); + REMOVE_DEBUG_TRACE(__LINE__); + goto std_return; } tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR); @@ -3298,9 +3217,8 @@ xfs_rmdir( /* Fall through to std_return with error = 0 or the errno * from xfs_trans_commit. */ std_return: - if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, - DM_EVENT_POSTREMOVE)) { - (void) dm_send_namesp_event(DM_EVENT_POSTREMOVE, + if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_POSTREMOVE)) { + (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dir_bdp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, name, NULL, dm_di_mode, @@ -3391,7 +3309,7 @@ xfs_symlink( int n; xfs_buf_t *bp; xfs_prid_t prid; - xfs_dquot_t *udqp, *gdqp; + struct xfs_dquot *udqp, *gdqp; uint resblks; char *link_name = VNAME(dentry); int link_namelen; @@ -3446,10 +3364,9 @@ xfs_symlink( } if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_SYMLINK)) { - error = dm_send_namesp_event(DM_EVENT_SYMLINK, dir_bdp, DM_RIGHT_NULL, - NULL, DM_RIGHT_NULL, - link_name, target_path, - 0, 0, 0); + error = XFS_SEND_NAMESP(mp, DM_EVENT_SYMLINK, dir_bdp, + DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, + link_name, target_path, 0, 0, 0); if (error) return error; } @@ -3465,14 +3382,10 @@ xfs_symlink( /* * Make sure that we have allocated dquot(s) on disk. */ - if (XFS_IS_QUOTA_ON(mp)) { - error = xfs_qm_vop_dqalloc(mp, dp, - current->fsuid, current->fsgid, - XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, - &udqp, &gdqp); - if (error) - goto std_return; - } + error = XFS_QM_DQVOPALLOC(mp, dp, current->fsuid, current->fsgid, + XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); + if (error) + goto std_return; tp = xfs_trans_alloc(mp, XFS_TRANS_SYMLINK); cancel_flags = XFS_TRANS_RELEASE_LOG_RES; @@ -3503,12 +3416,9 @@ xfs_symlink( /* * Reserve disk quota : blocks and inode. */ - if (XFS_IS_QUOTA_ON(mp)) { - if (xfs_trans_reserve_quota(tp, udqp, gdqp, resblks, 1, 0)) { - error = XFS_ERROR(EDQUOT); - goto error_return; - } - } + error = XFS_TRANS_RESERVE_QUOTA(mp, tp, udqp, gdqp, resblks, 1, 0); + if (error) + goto error_return; /* * Check for ability to enter directory entry, if no space reserved. @@ -3543,9 +3453,7 @@ xfs_symlink( /* * Also attach the dquot(s) to it, if applicable. */ - if (XFS_IS_QUOTA_ON(mp)) { - xfs_qm_vop_dqattach_and_dqmod_newinode(tp, ip, udqp, gdqp); - } + XFS_QM_DQVOPCREATE(mp, tp, ip, udqp, gdqp); if (resblks) resblks -= XFS_IALLOC_SPACE_RES(mp); @@ -3641,22 +3549,19 @@ xfs_symlink( goto error2; } error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); - if (udqp) - xfs_qm_dqrele(udqp); - if (gdqp) - xfs_qm_dqrele(gdqp); + XFS_QM_DQRELE(mp, udqp); + XFS_QM_DQRELE(mp, gdqp); /* Fall through to std_return with error = 0 or errno from * xfs_trans_commit */ std_return: if (DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp), DM_EVENT_POSTSYMLINK)) { - (void) dm_send_namesp_event(DM_EVENT_POSTSYMLINK, - dir_bdp, DM_RIGHT_NULL, - error? NULL:XFS_ITOBHV(ip), - DM_RIGHT_NULL, - link_name, target_path, - 0, error, 0); + (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTSYMLINK, + dir_bdp, DM_RIGHT_NULL, + error ? NULL : XFS_ITOBHV(ip), + DM_RIGHT_NULL, link_name, target_path, + 0, error, 0); } if (!error) { @@ -3675,10 +3580,8 @@ std_return: cancel_flags |= XFS_TRANS_ABORT; error_return: xfs_trans_cancel(tp, cancel_flags); - if (udqp) - xfs_qm_dqrele(udqp); - if (gdqp) - xfs_qm_dqrele(gdqp); + XFS_QM_DQRELE(mp, udqp); + XFS_QM_DQRELE(mp, gdqp); if (!dp_joined_to_trans && (dp != NULL)) { xfs_iunlock(dp, XFS_ILOCK_EXCL); @@ -4165,7 +4068,7 @@ xfs_alloc_file_space( /* * determine if this is a realtime file */ - if ((rt = (ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) != 0) { + if ((rt = XFS_IS_REALTIME_INODE(ip)) != 0) { if (ip->i_d.di_extsize) rtextsize = ip->i_d.di_extsize; else @@ -4173,12 +4076,8 @@ xfs_alloc_file_space( } else rtextsize = 0; - if (XFS_IS_QUOTA_ON(mp)) { - if (XFS_NOT_DQATTACHED(mp, ip)) { - if ((error = xfs_qm_dqattach(ip, 0))) - return error; - } - } + if ((error = XFS_QM_DQATTACH(mp, ip, 0))) + return error; if (len <= 0) return XFS_ERROR(EINVAL); @@ -4200,7 +4099,7 @@ xfs_alloc_file_space( end_dmi_offset = offset+len; if (end_dmi_offset > ip->i_d.di_size) end_dmi_offset = ip->i_d.di_size; - error = xfs_dm_send_data_event(DM_EVENT_WRITE, XFS_ITOBHV(ip), + error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOBHV(ip), offset, end_dmi_offset - offset, 0, NULL); if (error) @@ -4255,15 +4154,11 @@ retry: break; } xfs_ilock(ip, XFS_ILOCK_EXCL); - if (XFS_IS_QUOTA_ON(mp)) { - if (xfs_trans_reserve_quota(tp, - ip->i_udquot, - ip->i_gdquot, - resblks, 0, 0)) { - error = XFS_ERROR(EDQUOT); - goto error1; - } - } + error = XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, + ip->i_udquot, ip->i_gdquot, resblks, 0, rt ? + XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); + if (error) + goto error1; xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_ihold(tp, ip); @@ -4308,13 +4203,13 @@ dmapi_enospc_check: if (error == ENOSPC && (attr_flags&ATTR_DMI) == 0 && DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_NOSPACE)) { - error = dm_send_namesp_event(DM_EVENT_NOSPACE, + error = XFS_SEND_NAMESP(mp, DM_EVENT_NOSPACE, XFS_ITOBHV(ip), DM_RIGHT_NULL, XFS_ITOBHV(ip), DM_RIGHT_NULL, NULL, NULL, 0, 0, 0); /* Delay flag intentionally unused */ if (error == 0) goto retry; /* Maybe DMAPI app. has made space */ - /* else fall through with error from xfs_dm_send_data_event */ + /* else fall through with error from XFS_SEND_DATA */ } return error; @@ -4434,38 +4329,32 @@ xfs_free_file_space( int nimap; uint resblks; int rounding; - int specrt; + int rt; xfs_fileoff_t startoffset_fsb; xfs_trans_t *tp; vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); mp = ip->i_mount; - if (XFS_IS_QUOTA_ON(mp)) { - if (XFS_NOT_DQATTACHED(mp, ip)) { - if ((error = xfs_qm_dqattach(ip, 0))) - return error; - } - } + if ((error = XFS_QM_DQATTACH(mp, ip, 0))) + return error; error = 0; if (len <= 0) /* if nothing being freed */ return error; - specrt = - (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && - !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb); + rt = (ip->i_d.di_flags & XFS_DIFLAG_REALTIME); startoffset_fsb = XFS_B_TO_FSB(mp, offset); end_dmi_offset = offset + len; endoffset_fsb = XFS_B_TO_FSBT(mp, end_dmi_offset); if (offset < ip->i_d.di_size && - (attr_flags&ATTR_DMI) == 0 && + (attr_flags & ATTR_DMI) == 0 && DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) { if (end_dmi_offset > ip->i_d.di_size) end_dmi_offset = ip->i_d.di_size; - error = xfs_dm_send_data_event(DM_EVENT_WRITE, XFS_ITOBHV(ip), - offset, end_dmi_offset - offset, - AT_DELAY_FLAG(attr_flags), NULL); + error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOBHV(ip), + offset, end_dmi_offset - offset, + AT_DELAY_FLAG(attr_flags), NULL); if (error) return(error); } @@ -4480,11 +4369,11 @@ xfs_free_file_space( xfs_inval_cached_pages(XFS_ITOV(ip), &(ip->i_iocore), ioffset, 0, 0); /* * Need to zero the stuff we're not freeing, on disk. - * If its specrt (realtime & can't use unwritten extents) then - * we actually need to zero the extent edges. Otherwise xfs_bunmapi + * If its a realtime file & can't use unwritten extents then we + * actually need to zero the extent edges. Otherwise xfs_bunmapi * will take care of it for us. */ - if (specrt) { + if (rt && !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) { nimap = 1; error = xfs_bmapi(NULL, ip, startoffset_fsb, 1, 0, NULL, 0, &imap, &nimap, NULL); @@ -4561,15 +4450,11 @@ xfs_free_file_space( break; } xfs_ilock(ip, XFS_ILOCK_EXCL); - if (XFS_IS_QUOTA_ON(mp)) { - if (xfs_trans_reserve_quota(tp, - ip->i_udquot, - ip->i_gdquot, - resblks, 0, 0)) { - error = XFS_ERROR(EDQUOT); - goto error1; - } - } + error = XFS_TRANS_RESERVE_QUOTA(mp, tp, + ip->i_udquot, ip->i_gdquot, resblks, 0, rt ? + XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); + if (error) + goto error1; xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_ihold(tp, ip); diff --git a/fs/xfs/xfsidbg.c b/fs/xfs/xfsidbg.c index 469622afcf09..b519b40626d7 100644 --- a/fs/xfs/xfsidbg.c +++ b/fs/xfs/xfsidbg.c @@ -31,8 +31,8 @@ */ #include <xfs.h> -#include <xfs_quota_priv.h> #include <xfs_log_recover.h> +#include "quota/xfs_qm.h" #include "pagebuf/page_buf_internal.h" #include <linux/ctype.h> @@ -1320,13 +1320,13 @@ char *tab_vflags[] = { "INVALID0x40000", /* 0x40000 */ "INVALID0x80000", /* 0x80000 */ "VROOT", /* 0x100000 */ - "VNOSWAP", /* 0x200000 */ - "VISSWAP", /* 0x400000 */ - "VREPLICABLE", /* 0x800000 */ - "VNOTREPLICABLE", /* 0x1000000 */ - "VDOCMP", /* 0x2000000 */ + "INVALID0x200000", /* 0x200000 */ + "INVALID00x400000", /* 0x400000 */ + "INVALID0x800000", /* 0x800000 */ + "INVALID0x1000000", /* 0x1000000 */ + "INVALID0x2000000", /* 0x2000000 */ "VSHARE", /* 0x4000000 */ - "VFRLOCKS", /* 0x8000000 */ + "INVALID0x8000000", /* 0x8000000 */ "VENF_LOCKING", /* 0x10000000 */ "VOPLOCK", /* 0x20000000 */ "VPURGE", /* 0x40000000 */ @@ -1373,9 +1373,10 @@ static void printvnode(vnode_t *vp) kdb_printf("vnode: 0x%p type ", vp); if ((size_t)vp->v_type >= sizeof(vnode_type)/sizeof(vnode_type[0])) - kdb_printf("out of range 0x%x\n", vp->v_type); + kdb_printf("out of range 0x%x", vp->v_type); else - kdb_printf("%s\n", vnode_type[vp->v_type]); + kdb_printf("%s", vnode_type[vp->v_type]); + kdb_printf(" v_bh %p\n", &vp->v_bh); if ((bh = vp->v_bh.bh_first)) { kdb_printf(" v_inode 0x%p v_bh->bh_first 0x%p pobj 0x%p\n", @@ -1397,6 +1398,9 @@ static void printvnode(vnode_t *vp) #ifdef CONFIG_XFS_VNODE_TRACING kdb_printf(" v_trace 0x%p\n", vp->v_trace); #endif /* CONFIG_XFS_VNODE_TRACING */ + + kdb_printf(" v_vfsp 0x%p v_number %Lx\n", + vp->v_vfsp, vp->v_number); } @@ -4808,13 +4812,8 @@ xfsidbg_xnode(xfs_inode_t *ip) static void xfsidbg_xcore(xfs_iocore_t *io) { - if (IO_IS_XFS(io)) { - kdb_printf("io_obj 0x%p (xinode) io_mount 0x%p\n", - io->io_obj, io->io_mount); - } else { - kdb_printf("io_obj 0x%p (dcxvn) io_mount 0x%p\n", - io->io_obj, io->io_mount); - } + kdb_printf("io_obj 0x%p io_flags 0x%x io_mount 0x%p\n", + io->io_obj, io->io_flags, io->io_mount); kdb_printf("new_size %Lx\n", io->io_new_size); } diff --git a/include/pcmcia/bus_ops.h b/include/pcmcia/bus_ops.h index d99634af16f3..eb094dd03fca 100644 --- a/include/pcmcia/bus_ops.h +++ b/include/pcmcia/bus_ops.h @@ -1,152 +1,2 @@ -/* - * bus_ops.h 1.10 2000/06/12 21:55:41 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. - * - * The initial developer of the original code is David A. Hinds - * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds - * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. - */ - -#ifndef _LINUX_BUS_OPS_H -#define _LINUX_BUS_OPS_H - -#include <linux/config.h> - -#ifdef CONFIG_VIRTUAL_BUS - -typedef struct bus_operations { - void *priv; - u32 (*b_in)(void *bus, u32 port, s32 sz); - void (*b_ins)(void *bus, u32 port, void *buf, - u32 count, s32 sz); - void (*b_out)(void *bus, u32 val, u32 port, s32 sz); - void (*b_outs)(void *bus, u32 port, void *buf, - u32 count, s32 sz); - void *(*b_ioremap)(void *bus, u_long ofs, u_long sz); - void (*b_iounmap)(void *bus, void *addr); - u32 (*b_read)(void *bus, void *addr, s32 sz); - void (*b_write)(void *bus, u32 val, void *addr, s32 sz); - void (*b_copy_from)(void *bus, void *d, void *s, u32 count); - void (*b_copy_to)(void *bus, void *d, void *s, u32 count); - int (*b_request_irq)(void *bus, u_int irq, - void (*handler)(int, void *, - struct pt_regs *), - u_long flags, const char *device, - void *dev_id); - void (*b_free_irq)(void *bus, u_int irq, void *dev_id); -} bus_operations; - -#define bus_inb(b,p) (b)->b_in((b),(p),0) -#define bus_inw(b,p) (b)->b_in((b),(p),1) -#define bus_inl(b,p) (b)->b_in((b),(p),2) -#define bus_inw_ns(b,p) (b)->b_in((b),(p),-1) -#define bus_inl_ns(b,p) (b)->b_in((b),(p),-2) - -#define bus_insb(b,p,a,c) (b)->b_ins((b),(p),(a),(c),0) -#define bus_insw(b,p,a,c) (b)->b_ins((b),(p),(a),(c),1) -#define bus_insl(b,p,a,c) (b)->b_ins((b),(p),(a),(c),2) -#define bus_insw_ns(b,p,a,c) (b)->b_ins((b),(p),(a),(c),-1) -#define bus_insl_ns(b,p,a,c) (b)->b_ins((b),(p),(a),(c),-2) - -#define bus_outb(b,v,p) (b)->b_out((b),(v),(p),0) -#define bus_outw(b,v,p) (b)->b_out((b),(v),(p),1) -#define bus_outl(b,v,p) (b)->b_out((b),(v),(p),2) -#define bus_outw_ns(b,v,p) (b)->b_out((b),(v),(p),-1) -#define bus_outl_ns(b,v,p) (b)->b_out((b),(v),(p),-2) - -#define bus_outsb(b,p,a,c) (b)->b_outs((b),(p),(a),(c),0) -#define bus_outsw(b,p,a,c) (b)->b_outs((b),(p),(a),(c),1) -#define bus_outsl(b,p,a,c) (b)->b_outs((b),(p),(a),(c),2) -#define bus_outsw_ns(b,p,a,c) (b)->b_outs((b),(p),(a),(c),-1) -#define bus_outsl_ns(b,p,a,c) (b)->b_outs((b),(p),(a),(c),-2) - -#define bus_readb(b,a) (b)->b_read((b),(a),0) -#define bus_readw(b,a) (b)->b_read((b),(a),1) -#define bus_readl(b,a) (b)->b_read((b),(a),2) -#define bus_readw_ns(b,a) (b)->b_read((b),(a),-1) -#define bus_readl_ns(b,a) (b)->b_read((b),(a),-2) - -#define bus_writeb(b,v,a) (b)->b_write((b),(v),(a),0) -#define bus_writew(b,v,a) (b)->b_write((b),(v),(a),1) -#define bus_writel(b,v,a) (b)->b_write((b),(v),(a),2) -#define bus_writew_ns(b,v,a) (b)->b_write((b),(v),(a),-1) -#define bus_writel_ns(b,v,a) (b)->b_write((b),(v),(a),-2) - -#define bus_ioremap(b,s,n) (b)->b_ioremap((b),(s),(n)) -#define bus_iounmap(b,a) (b)->b_iounmap((b),(a)) -#define bus_memcpy_fromio(b,d,s,n) (b)->b_copy_from((b),(d),(s),(n)) -#define bus_memcpy_toio(b,d,s,n) (b)->b_copy_to((b),(d),(s),(n)) - -#define bus_request_irq(b,i,h,f,n,d) \ - (b)->b_request_irq((b),(i),(h),(f),(n),(d)) -#define bus_free_irq(b,i,d) (b)->b_free_irq((b),(i),(d)) - -#else - -#define bus_inb(b,p) inb(p) -#define bus_inw(b,p) inw(p) -#define bus_inl(b,p) inl(p) -#define bus_inw_ns(b,p) inw_ns(p) -#define bus_inl_ns(b,p) inl_ns(p) - -#define bus_insb(b,p,a,c) insb(p,a,c) -#define bus_insw(b,p,a,c) insw(p,a,c) -#define bus_insl(b,p,a,c) insl(p,a,c) -#define bus_insw_ns(b,p,a,c) insw_ns(p,a,c) -#define bus_insl_ns(b,p,a,c) insl_ns(p,a,c) - -#define bus_outb(b,v,p) outb(b,v,p) -#define bus_outw(b,v,p) outw(b,v,p) -#define bus_outl(b,v,p) outl(b,v,p) -#define bus_outw_ns(b,v,p) outw_ns(b,v,p) -#define bus_outl_ns(b,v,p) outl_ns(b,v,p) - -#define bus_outsb(b,p,a,c) outsb(p,a,c) -#define bus_outsw(b,p,a,c) outsw(p,a,c) -#define bus_outsl(b,p,a,c) outsl(p,a,c) -#define bus_outsw_ns(b,p,a,c) outsw_ns(p,a,c) -#define bus_outsl_ns(b,p,a,c) outsl_ns(p,a,c) - -#define bus_readb(b,a) readb(a) -#define bus_readw(b,a) readw(a) -#define bus_readl(b,a) readl(a) -#define bus_readw_ns(b,a) readw_ns(a) -#define bus_readl_ns(b,a) readl_ns(a) - -#define bus_writeb(b,v,a) writeb(v,a) -#define bus_writew(b,v,a) writew(v,a) -#define bus_writel(b,v,a) writel(v,a) -#define bus_writew_ns(b,v,a) writew_ns(v,a) -#define bus_writel_ns(b,v,a) writel_ns(v,a) - -#define bus_ioremap(b,s,n) ioremap(s,n) -#define bus_iounmap(b,a) iounmap(a) -#define bus_memcpy_fromio(b,d,s,n) memcpy_fromio(d,s,n) -#define bus_memcpy_toio(b,d,s,n) memcpy_toio(d,s,n) - -#define bus_request_irq(b,i,h,f,n,d) request_irq((i),(h),(f),(n),(d)) -#define bus_free_irq(b,i,d) free_irq((i),(d)) - -#endif /* CONFIG_VIRTUAL_BUS */ - -#endif /* _LINUX_BUS_OPS_H */ +/* now empty */ +#warning please remove the reference to this file diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index 2bd505c969dc..e29dfbb82a99 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -98,7 +98,6 @@ typedef struct event_callback_args_t { void *buffer; void *misc; void *client_data; - struct bus_operations *bus; } event_callback_args_t; /* for GetConfigurationInfo */ diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index 2d8fee9e7733..fcc6515cc2e1 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -58,7 +58,6 @@ typedef struct socket_cap_t { ioaddr_t io_offset; u_char pci_irq; struct pci_dev *cb_dev; - struct bus_operations *bus; } socket_cap_t; /* InquireSocket capabilities */ @@ -134,9 +133,7 @@ struct pccard_operations { int (*get_status)(unsigned int sock, u_int *value); int (*get_socket)(unsigned int sock, socket_state_t *state); int (*set_socket)(unsigned int sock, socket_state_t *state); - int (*get_io_map)(unsigned int sock, struct pccard_io_map *io); int (*set_io_map)(unsigned int sock, struct pccard_io_map *io); - int (*get_mem_map)(unsigned int sock, struct pccard_mem_map *mem); int (*set_mem_map)(unsigned int sock, struct pccard_mem_map *mem); void (*proc_setup)(unsigned int sock, struct proc_dir_entry *base); }; |
