diff options
56 files changed, 879 insertions, 965 deletions
diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl index e36986663570..f3f37f141dbd 100644 --- a/Documentation/DocBook/mac80211.tmpl +++ b/Documentation/DocBook/mac80211.tmpl | |||
@@ -184,8 +184,6 @@ usage should require reading the full document. | |||
184 | !Finclude/net/mac80211.h ieee80211_ctstoself_get | 184 | !Finclude/net/mac80211.h ieee80211_ctstoself_get |
185 | !Finclude/net/mac80211.h ieee80211_ctstoself_duration | 185 | !Finclude/net/mac80211.h ieee80211_ctstoself_duration |
186 | !Finclude/net/mac80211.h ieee80211_generic_frame_duration | 186 | !Finclude/net/mac80211.h ieee80211_generic_frame_duration |
187 | !Finclude/net/mac80211.h ieee80211_get_hdrlen_from_skb | ||
188 | !Finclude/net/mac80211.h ieee80211_hdrlen | ||
189 | !Finclude/net/mac80211.h ieee80211_wake_queue | 187 | !Finclude/net/mac80211.h ieee80211_wake_queue |
190 | !Finclude/net/mac80211.h ieee80211_stop_queue | 188 | !Finclude/net/mac80211.h ieee80211_stop_queue |
191 | !Finclude/net/mac80211.h ieee80211_wake_queues | 189 | !Finclude/net/mac80211.h ieee80211_wake_queues |
diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h index b7e5db876399..4e77853321db 100644 --- a/arch/x86/include/asm/spinlock.h +++ b/arch/x86/include/asm/spinlock.h | |||
@@ -302,4 +302,8 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw) | |||
302 | #define _raw_read_relax(lock) cpu_relax() | 302 | #define _raw_read_relax(lock) cpu_relax() |
303 | #define _raw_write_relax(lock) cpu_relax() | 303 | #define _raw_write_relax(lock) cpu_relax() |
304 | 304 | ||
305 | /* The {read|write|spin}_lock() on x86 are full memory barriers. */ | ||
306 | static inline void smp_mb__after_lock(void) { } | ||
307 | #define ARCH_HAS_SMP_MB_AFTER_LOCK | ||
308 | |||
305 | #endif /* _ASM_X86_SPINLOCK_H */ | 309 | #endif /* _ASM_X86_SPINLOCK_H */ |
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index a76315dc7767..206144f2470f 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c | |||
@@ -431,7 +431,7 @@ bmac_init_phy(struct net_device *dev) | |||
431 | printk(KERN_DEBUG); | 431 | printk(KERN_DEBUG); |
432 | printk(KERN_CONT " %.4x", bmac_mif_read(dev, addr)); | 432 | printk(KERN_CONT " %.4x", bmac_mif_read(dev, addr)); |
433 | } | 433 | } |
434 | print(KERN_CONT "\n"); | 434 | printk(KERN_CONT "\n"); |
435 | 435 | ||
436 | if (bp->is_bmac_plus) { | 436 | if (bp->is_bmac_plus) { |
437 | unsigned int capable, ctrl; | 437 | unsigned int capable, ctrl; |
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 538dda4422dc..fb5df5c6203e 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
@@ -642,8 +642,7 @@ static int setup_sge_qsets(struct adapter *adap) | |||
642 | struct port_info *pi = netdev_priv(dev); | 642 | struct port_info *pi = netdev_priv(dev); |
643 | 643 | ||
644 | pi->qs = &adap->sge.qs[pi->first_qset]; | 644 | pi->qs = &adap->sge.qs[pi->first_qset]; |
645 | for (j = pi->first_qset; j < pi->first_qset + pi->nqsets; | 645 | for (j = 0; j < pi->nqsets; ++j, ++qset_idx) { |
646 | ++j, ++qset_idx) { | ||
647 | set_qset_lro(dev, qset_idx, pi->rx_offload & T3_LRO); | 646 | set_qset_lro(dev, qset_idx, pi->rx_offload & T3_LRO); |
648 | err = t3_sge_alloc_qset(adap, qset_idx, 1, | 647 | err = t3_sge_alloc_qset(adap, qset_idx, 1, |
649 | (adap->flags & USING_MSIX) ? qset_idx + 1 : | 648 | (adap->flags & USING_MSIX) ? qset_idx + 1 : |
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 2df8fb0af701..12fd446f9895 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c | |||
@@ -1820,11 +1820,19 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) | |||
1820 | struct device *emac_dev = &priv->ndev->dev; | 1820 | struct device *emac_dev = &priv->ndev->dev; |
1821 | struct sockaddr *sa = addr; | 1821 | struct sockaddr *sa = addr; |
1822 | 1822 | ||
1823 | if (!is_valid_ether_addr(sa->sa_data)) | ||
1824 | return -EINVAL; | ||
1825 | |||
1823 | /* Store mac addr in priv and rx channel and set it in EMAC hw */ | 1826 | /* Store mac addr in priv and rx channel and set it in EMAC hw */ |
1824 | memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); | 1827 | memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); |
1825 | memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); | ||
1826 | memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); | 1828 | memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); |
1827 | emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); | 1829 | |
1830 | /* If the interface is down - rxch is NULL. */ | ||
1831 | /* MAC address is configured only after the interface is enabled. */ | ||
1832 | if (netif_running(ndev)) { | ||
1833 | memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); | ||
1834 | emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); | ||
1835 | } | ||
1828 | 1836 | ||
1829 | if (netif_msg_drv(priv)) | 1837 | if (netif_msg_drv(priv)) |
1830 | dev_notice(emac_dev, "DaVinci EMAC: emac_dev_setmac_addr %pM\n", | 1838 | dev_notice(emac_dev, "DaVinci EMAC: emac_dev_setmac_addr %pM\n", |
diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 30b7dd671336..cc47f3f057c7 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h | |||
@@ -46,12 +46,12 @@ | |||
46 | 46 | ||
47 | #else | 47 | #else |
48 | 48 | ||
49 | #define FEC_ECNTRL; 0x000 /* Ethernet control reg */ | 49 | #define FEC_ECNTRL 0x000 /* Ethernet control reg */ |
50 | #define FEC_IEVENT; 0x004 /* Interrupt even reg */ | 50 | #define FEC_IEVENT 0x004 /* Interrupt even reg */ |
51 | #define FEC_IMASK; 0x008 /* Interrupt mask reg */ | 51 | #define FEC_IMASK 0x008 /* Interrupt mask reg */ |
52 | #define FEC_IVEC; 0x00c /* Interrupt vec status reg */ | 52 | #define FEC_IVEC 0x00c /* Interrupt vec status reg */ |
53 | #define FEC_R_DES_ACTIVE; 0x010 /* Receive descriptor reg */ | 53 | #define FEC_R_DES_ACTIVE 0x010 /* Receive descriptor reg */ |
54 | #define FEC_X_DES_ACTIVE; 0x01c /* Transmit descriptor reg */ | 54 | #define FEC_X_DES_ACTIVE 0x014 /* Transmit descriptor reg */ |
55 | #define FEC_MII_DATA 0x040 /* MII manage frame reg */ | 55 | #define FEC_MII_DATA 0x040 /* MII manage frame reg */ |
56 | #define FEC_MII_SPEED 0x044 /* MII speed control reg */ | 56 | #define FEC_MII_SPEED 0x044 /* MII speed control reg */ |
57 | #define FEC_R_BOUND 0x08c /* FIFO receive bound reg */ | 57 | #define FEC_R_BOUND 0x08c /* FIFO receive bound reg */ |
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index efd9be214885..ac28dd5a4fd1 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c | |||
@@ -190,6 +190,10 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) | |||
190 | phy->ops.write_reg = igb_write_phy_reg_igp; | 190 | phy->ops.write_reg = igb_write_phy_reg_igp; |
191 | } | 191 | } |
192 | 192 | ||
193 | /* set lan id */ | ||
194 | hw->bus.func = (rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) >> | ||
195 | E1000_STATUS_FUNC_SHIFT; | ||
196 | |||
193 | /* Set phy->phy_addr and phy->id. */ | 197 | /* Set phy->phy_addr and phy->id. */ |
194 | ret_val = igb_get_phy_id_82575(hw); | 198 | ret_val = igb_get_phy_id_82575(hw); |
195 | if (ret_val) | 199 | if (ret_val) |
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index d56890f5c9d5..7c5978ad929a 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c | |||
@@ -138,6 +138,10 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) | |||
138 | adapter->hw.fc.requested_mode = ixgbe_fc_none; | 138 | adapter->hw.fc.requested_mode = ixgbe_fc_none; |
139 | } | 139 | } |
140 | adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; | 140 | adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; |
141 | if (adapter->hw.mac.type == ixgbe_mac_82599EB) { | ||
142 | adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; | ||
143 | adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; | ||
144 | } | ||
141 | adapter->flags |= IXGBE_FLAG_DCB_ENABLED; | 145 | adapter->flags |= IXGBE_FLAG_DCB_ENABLED; |
142 | ixgbe_init_interrupt_scheme(adapter); | 146 | ixgbe_init_interrupt_scheme(adapter); |
143 | if (netif_running(netdev)) | 147 | if (netif_running(netdev)) |
@@ -154,6 +158,8 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) | |||
154 | adapter->dcb_cfg.pfc_mode_enable = false; | 158 | adapter->dcb_cfg.pfc_mode_enable = false; |
155 | adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; | 159 | adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; |
156 | adapter->flags |= IXGBE_FLAG_RSS_ENABLED; | 160 | adapter->flags |= IXGBE_FLAG_RSS_ENABLED; |
161 | if (adapter->hw.mac.type == ixgbe_mac_82599EB) | ||
162 | adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; | ||
157 | ixgbe_init_interrupt_scheme(adapter); | 163 | ixgbe_init_interrupt_scheme(adapter); |
158 | if (netif_running(netdev)) | 164 | if (netif_running(netdev)) |
159 | netdev->netdev_ops->ndo_open(netdev); | 165 | netdev->netdev_ops->ndo_open(netdev); |
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index a3061aacffd8..e3442f47f932 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
@@ -3130,7 +3130,11 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter) | |||
3130 | #endif | 3130 | #endif |
3131 | if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { | 3131 | if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { |
3132 | DPRINTK(PROBE, INFO, "FCOE enabled with RSS \n"); | 3132 | DPRINTK(PROBE, INFO, "FCOE enabled with RSS \n"); |
3133 | ixgbe_set_rss_queues(adapter); | 3133 | if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) || |
3134 | (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) | ||
3135 | ixgbe_set_fdir_queues(adapter); | ||
3136 | else | ||
3137 | ixgbe_set_rss_queues(adapter); | ||
3134 | } | 3138 | } |
3135 | /* adding FCoE rx rings to the end */ | 3139 | /* adding FCoE rx rings to the end */ |
3136 | f->mask = adapter->num_rx_queues; | 3140 | f->mask = adapter->num_rx_queues; |
@@ -3388,7 +3392,12 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter) | |||
3388 | } | 3392 | } |
3389 | #endif /* CONFIG_IXGBE_DCB */ | 3393 | #endif /* CONFIG_IXGBE_DCB */ |
3390 | if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { | 3394 | if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { |
3391 | ixgbe_cache_ring_rss(adapter); | 3395 | if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) || |
3396 | (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) | ||
3397 | ixgbe_cache_ring_fdir(adapter); | ||
3398 | else | ||
3399 | ixgbe_cache_ring_rss(adapter); | ||
3400 | |||
3392 | fcoe_i = f->mask; | 3401 | fcoe_i = f->mask; |
3393 | } | 3402 | } |
3394 | for (i = 0; i < f->indices; i++, fcoe_i++) | 3403 | for (i = 0; i < f->indices; i++, fcoe_i++) |
@@ -5578,12 +5587,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
5578 | netdev->features |= NETIF_F_FCOE_CRC; | 5587 | netdev->features |= NETIF_F_FCOE_CRC; |
5579 | netdev->features |= NETIF_F_FSO; | 5588 | netdev->features |= NETIF_F_FSO; |
5580 | netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1; | 5589 | netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1; |
5581 | DPRINTK(DRV, INFO, "FCoE enabled, " | ||
5582 | "disabling Flow Director\n"); | ||
5583 | adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; | ||
5584 | adapter->flags &= | ||
5585 | ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; | ||
5586 | adapter->atr_sample_rate = 0; | ||
5587 | } else { | 5590 | } else { |
5588 | adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; | 5591 | adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; |
5589 | } | 5592 | } |
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index ed63d23a6452..961b5397a531 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c | |||
@@ -49,8 +49,8 @@ | |||
49 | #include <asm/processor.h> | 49 | #include <asm/processor.h> |
50 | 50 | ||
51 | #define DRV_NAME "r6040" | 51 | #define DRV_NAME "r6040" |
52 | #define DRV_VERSION "0.23" | 52 | #define DRV_VERSION "0.24" |
53 | #define DRV_RELDATE "05May2009" | 53 | #define DRV_RELDATE "08Jul2009" |
54 | 54 | ||
55 | /* PHY CHIP Address */ | 55 | /* PHY CHIP Address */ |
56 | #define PHY1_ADDR 1 /* For MAC1 */ | 56 | #define PHY1_ADDR 1 /* For MAC1 */ |
@@ -704,8 +704,11 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id) | |||
704 | /* Read MISR status and clear */ | 704 | /* Read MISR status and clear */ |
705 | status = ioread16(ioaddr + MISR); | 705 | status = ioread16(ioaddr + MISR); |
706 | 706 | ||
707 | if (status == 0x0000 || status == 0xffff) | 707 | if (status == 0x0000 || status == 0xffff) { |
708 | /* Restore RDC MAC interrupt */ | ||
709 | iowrite16(misr, ioaddr + MIER); | ||
708 | return IRQ_NONE; | 710 | return IRQ_NONE; |
711 | } | ||
709 | 712 | ||
710 | /* RX interrupt request */ | 713 | /* RX interrupt request */ |
711 | if (status & RX_INTS) { | 714 | if (status & RX_INTS) { |
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index d26e7b485315..eb0337c49546 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | config ATH_COMMON | 1 | config ATH_COMMON |
2 | tristate "Atheros Wireless Cards" | 2 | tristate "Atheros Wireless Cards" |
3 | depends on WLAN_80211 | ||
3 | depends on ATH5K || ATH9K || AR9170_USB | 4 | depends on ATH5K || ATH9K || AR9170_USB |
4 | 5 | ||
5 | source "drivers/net/wireless/ath/ath5k/Kconfig" | 6 | source "drivers/net/wireless/ath/ath5k/Kconfig" |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index b61a071788a5..4ccf48e396df 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -355,7 +355,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
355 | } | 355 | } |
356 | 356 | ||
357 | if (bf_next == NULL) { | 357 | if (bf_next == NULL) { |
358 | INIT_LIST_HEAD(&bf_head); | 358 | /* |
359 | * Make sure the last desc is reclaimed if it | ||
360 | * not a holding desc. | ||
361 | */ | ||
362 | if (!bf_last->bf_stale) | ||
363 | list_move_tail(&bf->list, &bf_head); | ||
364 | else | ||
365 | INIT_LIST_HEAD(&bf_head); | ||
359 | } else { | 366 | } else { |
360 | ASSERT(!list_empty(bf_q)); | 367 | ASSERT(!list_empty(bf_q)); |
361 | list_move_tail(&bf->list, &bf_head); | 368 | list_move_tail(&bf->list, &bf_head); |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index f580c2812d91..40448067e4cc 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -648,6 +648,7 @@ struct b43_wl { | |||
648 | u8 nr_devs; | 648 | u8 nr_devs; |
649 | 649 | ||
650 | bool radiotap_enabled; | 650 | bool radiotap_enabled; |
651 | bool radio_enabled; | ||
651 | 652 | ||
652 | /* The beacon we are currently using (AP or IBSS mode). | 653 | /* The beacon we are currently using (AP or IBSS mode). |
653 | * This beacon stuff is protected by the irq_lock. */ | 654 | * This beacon stuff is protected by the irq_lock. */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 6456afebdba1..e71c8d9cd706 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -3497,8 +3497,8 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) | |||
3497 | if (phy->ops->set_rx_antenna) | 3497 | if (phy->ops->set_rx_antenna) |
3498 | phy->ops->set_rx_antenna(dev, antenna); | 3498 | phy->ops->set_rx_antenna(dev, antenna); |
3499 | 3499 | ||
3500 | if (!!conf->radio_enabled != phy->radio_on) { | 3500 | if (wl->radio_enabled != phy->radio_on) { |
3501 | if (conf->radio_enabled) { | 3501 | if (wl->radio_enabled) { |
3502 | b43_software_rfkill(dev, false); | 3502 | b43_software_rfkill(dev, false); |
3503 | b43info(dev->wl, "Radio turned on by software\n"); | 3503 | b43info(dev->wl, "Radio turned on by software\n"); |
3504 | if (!dev->radio_hw_enable) { | 3504 | if (!dev->radio_hw_enable) { |
@@ -4339,6 +4339,7 @@ static int b43_op_start(struct ieee80211_hw *hw) | |||
4339 | wl->beacon0_uploaded = 0; | 4339 | wl->beacon0_uploaded = 0; |
4340 | wl->beacon1_uploaded = 0; | 4340 | wl->beacon1_uploaded = 0; |
4341 | wl->beacon_templates_virgin = 1; | 4341 | wl->beacon_templates_virgin = 1; |
4342 | wl->radio_enabled = 1; | ||
4342 | 4343 | ||
4343 | mutex_lock(&wl->mutex); | 4344 | mutex_lock(&wl->mutex); |
4344 | 4345 | ||
@@ -4378,6 +4379,7 @@ static void b43_op_stop(struct ieee80211_hw *hw) | |||
4378 | if (b43_status(dev) >= B43_STAT_STARTED) | 4379 | if (b43_status(dev) >= B43_STAT_STARTED) |
4379 | b43_wireless_core_stop(dev); | 4380 | b43_wireless_core_stop(dev); |
4380 | b43_wireless_core_exit(dev); | 4381 | b43_wireless_core_exit(dev); |
4382 | wl->radio_enabled = 0; | ||
4381 | mutex_unlock(&wl->mutex); | 4383 | mutex_unlock(&wl->mutex); |
4382 | 4384 | ||
4383 | cancel_work_sync(&(wl->txpower_adjust_work)); | 4385 | cancel_work_sync(&(wl->txpower_adjust_work)); |
@@ -4560,6 +4562,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
4560 | B43_WARN_ON(1); | 4562 | B43_WARN_ON(1); |
4561 | 4563 | ||
4562 | dev->phy.gmode = have_2ghz_phy; | 4564 | dev->phy.gmode = have_2ghz_phy; |
4565 | dev->phy.radio_on = 1; | ||
4563 | tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; | 4566 | tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; |
4564 | b43_wireless_core_reset(dev, tmp); | 4567 | b43_wireless_core_reset(dev, tmp); |
4565 | 4568 | ||
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index 3cfc30307a27..6c3a74964ab8 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | static /*const */ struct pcmcia_device_id b43_pcmcia_tbl[] = { | 36 | static /*const */ struct pcmcia_device_id b43_pcmcia_tbl[] = { |
37 | PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), | 37 | PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), |
38 | PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476), | ||
38 | PCMCIA_DEVICE_NULL, | 39 | PCMCIA_DEVICE_NULL, |
39 | }; | 40 | }; |
40 | 41 | ||
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 77fda148ac46..038baa8869e2 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h | |||
@@ -607,6 +607,7 @@ struct b43legacy_wl { | |||
607 | u8 nr_devs; | 607 | u8 nr_devs; |
608 | 608 | ||
609 | bool radiotap_enabled; | 609 | bool radiotap_enabled; |
610 | bool radio_enabled; | ||
610 | 611 | ||
611 | /* The beacon we are currently using (AP or IBSS mode). | 612 | /* The beacon we are currently using (AP or IBSS mode). |
612 | * This beacon stuff is protected by the irq_lock. */ | 613 | * This beacon stuff is protected by the irq_lock. */ |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index e5136fb65ddd..c4973c1942bf 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -2689,8 +2689,8 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, | |||
2689 | /* Antennas for RX and management frame TX. */ | 2689 | /* Antennas for RX and management frame TX. */ |
2690 | b43legacy_mgmtframe_txantenna(dev, antenna_tx); | 2690 | b43legacy_mgmtframe_txantenna(dev, antenna_tx); |
2691 | 2691 | ||
2692 | if (!!conf->radio_enabled != phy->radio_on) { | 2692 | if (wl->radio_enabled != phy->radio_on) { |
2693 | if (conf->radio_enabled) { | 2693 | if (wl->radio_enabled) { |
2694 | b43legacy_radio_turn_on(dev); | 2694 | b43legacy_radio_turn_on(dev); |
2695 | b43legacyinfo(dev->wl, "Radio turned on by software\n"); | 2695 | b43legacyinfo(dev->wl, "Radio turned on by software\n"); |
2696 | if (!dev->radio_hw_enable) | 2696 | if (!dev->radio_hw_enable) |
@@ -3441,6 +3441,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) | |||
3441 | wl->beacon0_uploaded = 0; | 3441 | wl->beacon0_uploaded = 0; |
3442 | wl->beacon1_uploaded = 0; | 3442 | wl->beacon1_uploaded = 0; |
3443 | wl->beacon_templates_virgin = 1; | 3443 | wl->beacon_templates_virgin = 1; |
3444 | wl->radio_enabled = 1; | ||
3444 | 3445 | ||
3445 | mutex_lock(&wl->mutex); | 3446 | mutex_lock(&wl->mutex); |
3446 | 3447 | ||
@@ -3479,6 +3480,7 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw) | |||
3479 | if (b43legacy_status(dev) >= B43legacy_STAT_STARTED) | 3480 | if (b43legacy_status(dev) >= B43legacy_STAT_STARTED) |
3480 | b43legacy_wireless_core_stop(dev); | 3481 | b43legacy_wireless_core_stop(dev); |
3481 | b43legacy_wireless_core_exit(dev); | 3482 | b43legacy_wireless_core_exit(dev); |
3483 | wl->radio_enabled = 0; | ||
3482 | mutex_unlock(&wl->mutex); | 3484 | mutex_unlock(&wl->mutex); |
3483 | } | 3485 | } |
3484 | 3486 | ||
@@ -3620,6 +3622,7 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev) | |||
3620 | have_bphy = 1; | 3622 | have_bphy = 1; |
3621 | 3623 | ||
3622 | dev->phy.gmode = (have_gphy || have_bphy); | 3624 | dev->phy.gmode = (have_gphy || have_bphy); |
3625 | dev->phy.radio_on = 1; | ||
3623 | tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0; | 3626 | tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0; |
3624 | b43legacy_wireless_core_reset(dev, tmp); | 3627 | b43legacy_wireless_core_reset(dev, tmp); |
3625 | 3628 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig index 1eccb6df46dd..030401d367d3 100644 --- a/drivers/net/wireless/iwmc3200wifi/Kconfig +++ b/drivers/net/wireless/iwmc3200wifi/Kconfig | |||
@@ -4,6 +4,15 @@ config IWM | |||
4 | depends on CFG80211 | 4 | depends on CFG80211 |
5 | select WIRELESS_EXT | 5 | select WIRELESS_EXT |
6 | select FW_LOADER | 6 | select FW_LOADER |
7 | help | ||
8 | The Intel Wireless Multicomm 3200 hardware is a combo | ||
9 | card with GPS, Bluetooth, WiMax and 802.11 radios. It | ||
10 | runs over SDIO and is typically found on Moorestown | ||
11 | based platform. This driver takes care of the 802.11 | ||
12 | part, which is a fullmac one. | ||
13 | |||
14 | If you choose to build it as a module, it'll be called | ||
15 | iwmc3200wifi.ko. | ||
7 | 16 | ||
8 | config IWM_DEBUG | 17 | config IWM_DEBUG |
9 | bool "Enable full debugging output in iwmc3200wifi" | 18 | bool "Enable full debugging output in iwmc3200wifi" |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index e789c6e9938c..a111bda392e2 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -418,6 +418,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | |||
418 | continue; | 418 | continue; |
419 | 419 | ||
420 | if (!data2->started || !hwsim_ps_rx_ok(data2, skb) || | 420 | if (!data2->started || !hwsim_ps_rx_ok(data2, skb) || |
421 | !data->channel || !data2->channel || | ||
421 | data->channel->center_freq != data2->channel->center_freq || | 422 | data->channel->center_freq != data2->channel->center_freq || |
422 | !(data->group & data2->group)) | 423 | !(data->group & data2->group)) |
423 | continue; | 424 | continue; |
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 48d81d98e12d..22ca122bd798 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -912,13 +912,14 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
912 | } | 912 | } |
913 | 913 | ||
914 | __skb_unlink(entry, &priv->tx_queue); | 914 | __skb_unlink(entry, &priv->tx_queue); |
915 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | ||
916 | 915 | ||
917 | frame_len = entry->len; | 916 | frame_len = entry->len; |
918 | entry_hdr = (struct p54_hdr *) entry->data; | 917 | entry_hdr = (struct p54_hdr *) entry->data; |
919 | entry_data = (struct p54_tx_data *) entry_hdr->data; | 918 | entry_data = (struct p54_tx_data *) entry_hdr->data; |
920 | priv->tx_stats[entry_data->hw_queue].len--; | 919 | if (priv->tx_stats[entry_data->hw_queue].len) |
920 | priv->tx_stats[entry_data->hw_queue].len--; | ||
921 | priv->stats.dot11ACKFailureCount += payload->tries - 1; | 921 | priv->stats.dot11ACKFailureCount += payload->tries - 1; |
922 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | ||
922 | 923 | ||
923 | /* | 924 | /* |
924 | * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are | 925 | * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 14a19baff214..0e6e44689cc6 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -38,7 +38,6 @@ static struct usb_device_id usb_ids[] = { | |||
38 | /* ZD1211 */ | 38 | /* ZD1211 */ |
39 | { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 }, | 39 | { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 }, |
40 | { USB_DEVICE(0x0ace, 0xa211), .driver_info = DEVICE_ZD1211 }, | 40 | { USB_DEVICE(0x0ace, 0xa211), .driver_info = DEVICE_ZD1211 }, |
41 | { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 }, | ||
42 | { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 }, | 41 | { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 }, |
43 | { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, | 42 | { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, |
44 | { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, | 43 | { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, |
@@ -61,6 +60,7 @@ static struct usb_device_id usb_ids[] = { | |||
61 | { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 }, | 60 | { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 }, |
62 | { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 }, | 61 | { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 }, |
63 | /* ZD1211B */ | 62 | /* ZD1211B */ |
63 | { USB_DEVICE(0x054c, 0x0257), .driver_info = DEVICE_ZD1211B }, | ||
64 | { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, | 64 | { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, |
65 | { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B }, | 65 | { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B }, |
66 | { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, | 66 | { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, |
@@ -87,6 +87,7 @@ static struct usb_device_id usb_ids[] = { | |||
87 | { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, | 87 | { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, |
88 | { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, | 88 | { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, |
89 | { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B }, | 89 | { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B }, |
90 | { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211B }, | ||
90 | /* "Driverless" devices that need ejecting */ | 91 | /* "Driverless" devices that need ejecting */ |
91 | { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, | 92 | { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, |
92 | { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, | 93 | { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, |
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 4ac2311c00af..ca508564a181 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
@@ -171,7 +171,7 @@ static int hp_wmi_tablet_state(void) | |||
171 | static int hp_wmi_set_block(void *data, bool blocked) | 171 | static int hp_wmi_set_block(void *data, bool blocked) |
172 | { | 172 | { |
173 | unsigned long b = (unsigned long) data; | 173 | unsigned long b = (unsigned long) data; |
174 | int query = BIT(b + 8) | ((!!blocked) << b); | 174 | int query = BIT(b + 8) | ((!blocked) << b); |
175 | 175 | ||
176 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); | 176 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); |
177 | } | 177 | } |
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index 131030f693c7..100e7a5c5ea1 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c | |||
@@ -678,7 +678,8 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | |||
678 | sprom->board_rev = tuple.TupleData[1]; | 678 | sprom->board_rev = tuple.TupleData[1]; |
679 | break; | 679 | break; |
680 | case SSB_PCMCIA_CIS_PA: | 680 | case SSB_PCMCIA_CIS_PA: |
681 | GOTO_ERROR_ON(tuple.TupleDataLen != 9, | 681 | GOTO_ERROR_ON((tuple.TupleDataLen != 9) && |
682 | (tuple.TupleDataLen != 10), | ||
682 | "pa tpl size"); | 683 | "pa tpl size"); |
683 | sprom->pa0b0 = tuple.TupleData[1] | | 684 | sprom->pa0b0 = tuple.TupleData[1] | |
684 | ((u16)tuple.TupleData[2] << 8); | 685 | ((u16)tuple.TupleData[2] << 8); |
@@ -718,7 +719,8 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | |||
718 | sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1]; | 719 | sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1]; |
719 | break; | 720 | break; |
720 | case SSB_PCMCIA_CIS_BFLAGS: | 721 | case SSB_PCMCIA_CIS_BFLAGS: |
721 | GOTO_ERROR_ON(tuple.TupleDataLen != 3, | 722 | GOTO_ERROR_ON((tuple.TupleDataLen != 3) && |
723 | (tuple.TupleDataLen != 5), | ||
722 | "bfl tpl size"); | 724 | "bfl tpl size"); |
723 | sprom->boardflags_lo = tuple.TupleData[1] | | 725 | sprom->boardflags_lo = tuple.TupleData[1] | |
724 | ((u16)tuple.TupleData[2] << 8); | 726 | ((u16)tuple.TupleData[2] << 8); |
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 567fb944bd2a..f8778cde2183 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c | |||
@@ -1365,11 +1365,6 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan) | |||
1365 | init_completion(&mx3fbi->flip_cmpl); | 1365 | init_completion(&mx3fbi->flip_cmpl); |
1366 | disable_irq(ichan->eof_irq); | 1366 | disable_irq(ichan->eof_irq); |
1367 | dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq); | 1367 | dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq); |
1368 | ret = mx3fb_set_par(fbi); | ||
1369 | if (ret < 0) | ||
1370 | goto esetpar; | ||
1371 | |||
1372 | mx3fb_blank(FB_BLANK_UNBLANK, fbi); | ||
1373 | 1368 | ||
1374 | dev_info(dev, "registered, using mode %s\n", fb_mode); | 1369 | dev_info(dev, "registered, using mode %s\n", fb_mode); |
1375 | 1370 | ||
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 16d4f4c7d52b..924d79462780 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
@@ -1540,9 +1540,6 @@ static int sm501fb_init_fb(struct fb_info *fb, | |||
1540 | if (ret) | 1540 | if (ret) |
1541 | dev_err(info->dev, "check_var() failed on initial setup?\n"); | 1541 | dev_err(info->dev, "check_var() failed on initial setup?\n"); |
1542 | 1542 | ||
1543 | /* ensure we've activated our new configuration */ | ||
1544 | (fb->fbops->fb_set_par)(fb); | ||
1545 | |||
1546 | return 0; | 1543 | return 0; |
1547 | } | 1544 | } |
1548 | 1545 | ||
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 3a9b7a58a51d..92888aa90749 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -5,7 +5,11 @@ client generated ones by default (mount option "serverino" turned | |||
5 | on by default if server supports it). Add forceuid and forcegid | 5 | on by default if server supports it). Add forceuid and forcegid |
6 | mount options (so that when negotiating unix extensions specifying | 6 | mount options (so that when negotiating unix extensions specifying |
7 | which uid mounted does not immediately force the server's reported | 7 | which uid mounted does not immediately force the server's reported |
8 | uids to be overridden). Add support for scope moutn parm. | 8 | uids to be overridden). Add support for scope mount parm. Improve |
9 | hard link detection to use same inode for both. Do not set | ||
10 | read-only dos attribute on directories (for chmod) since Windows | ||
11 | explorer special cases this attribute bit for directories for | ||
12 | a different purpose. | ||
9 | 13 | ||
10 | Version 1.58 | 14 | Version 1.58 |
11 | ------------ | 15 | ------------ |
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index 4a4581cb2b5e..051caecf7d67 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c | |||
@@ -86,6 +86,9 @@ struct key_type cifs_spnego_key_type = { | |||
86 | /* strlen of ";user=" */ | 86 | /* strlen of ";user=" */ |
87 | #define USER_KEY_LEN 6 | 87 | #define USER_KEY_LEN 6 |
88 | 88 | ||
89 | /* strlen of ";pid=0x" */ | ||
90 | #define PID_KEY_LEN 7 | ||
91 | |||
89 | /* get a key struct with a SPNEGO security blob, suitable for session setup */ | 92 | /* get a key struct with a SPNEGO security blob, suitable for session setup */ |
90 | struct key * | 93 | struct key * |
91 | cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | 94 | cifs_get_spnego_key(struct cifsSesInfo *sesInfo) |
@@ -103,7 +106,8 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | |||
103 | IP_KEY_LEN + INET6_ADDRSTRLEN + | 106 | IP_KEY_LEN + INET6_ADDRSTRLEN + |
104 | MAX_MECH_STR_LEN + | 107 | MAX_MECH_STR_LEN + |
105 | UID_KEY_LEN + (sizeof(uid_t) * 2) + | 108 | UID_KEY_LEN + (sizeof(uid_t) * 2) + |
106 | USER_KEY_LEN + strlen(sesInfo->userName) + 1; | 109 | USER_KEY_LEN + strlen(sesInfo->userName) + |
110 | PID_KEY_LEN + (sizeof(pid_t) * 2) + 1; | ||
107 | 111 | ||
108 | spnego_key = ERR_PTR(-ENOMEM); | 112 | spnego_key = ERR_PTR(-ENOMEM); |
109 | description = kzalloc(desc_len, GFP_KERNEL); | 113 | description = kzalloc(desc_len, GFP_KERNEL); |
@@ -141,6 +145,9 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | |||
141 | dp = description + strlen(description); | 145 | dp = description + strlen(description); |
142 | sprintf(dp, ";user=%s", sesInfo->userName); | 146 | sprintf(dp, ";user=%s", sesInfo->userName); |
143 | 147 | ||
148 | dp = description + strlen(description); | ||
149 | sprintf(dp, ";pid=0x%x", current->pid); | ||
150 | |||
144 | cFYI(1, ("key description = %s", description)); | 151 | cFYI(1, ("key description = %s", description)); |
145 | spnego_key = request_key(&cifs_spnego_key_type, description, ""); | 152 | spnego_key = request_key(&cifs_spnego_key_type, description, ""); |
146 | 153 | ||
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 1403b5d86a73..6941c22398a6 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -327,7 +327,7 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl) | |||
327 | 327 | ||
328 | static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | 328 | static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, |
329 | struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, | 329 | struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, |
330 | struct inode *inode) | 330 | struct cifs_fattr *fattr) |
331 | { | 331 | { |
332 | int i; | 332 | int i; |
333 | int num_aces = 0; | 333 | int num_aces = 0; |
@@ -340,7 +340,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
340 | if (!pdacl) { | 340 | if (!pdacl) { |
341 | /* no DACL in the security descriptor, set | 341 | /* no DACL in the security descriptor, set |
342 | all the permissions for user/group/other */ | 342 | all the permissions for user/group/other */ |
343 | inode->i_mode |= S_IRWXUGO; | 343 | fattr->cf_mode |= S_IRWXUGO; |
344 | return; | 344 | return; |
345 | } | 345 | } |
346 | 346 | ||
@@ -357,7 +357,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
357 | /* reset rwx permissions for user/group/other. | 357 | /* reset rwx permissions for user/group/other. |
358 | Also, if num_aces is 0 i.e. DACL has no ACEs, | 358 | Also, if num_aces is 0 i.e. DACL has no ACEs, |
359 | user/group/other have no permissions */ | 359 | user/group/other have no permissions */ |
360 | inode->i_mode &= ~(S_IRWXUGO); | 360 | fattr->cf_mode &= ~(S_IRWXUGO); |
361 | 361 | ||
362 | acl_base = (char *)pdacl; | 362 | acl_base = (char *)pdacl; |
363 | acl_size = sizeof(struct cifs_acl); | 363 | acl_size = sizeof(struct cifs_acl); |
@@ -379,17 +379,17 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
379 | if (compare_sids(&(ppace[i]->sid), pownersid)) | 379 | if (compare_sids(&(ppace[i]->sid), pownersid)) |
380 | access_flags_to_mode(ppace[i]->access_req, | 380 | access_flags_to_mode(ppace[i]->access_req, |
381 | ppace[i]->type, | 381 | ppace[i]->type, |
382 | &(inode->i_mode), | 382 | &fattr->cf_mode, |
383 | &user_mask); | 383 | &user_mask); |
384 | if (compare_sids(&(ppace[i]->sid), pgrpsid)) | 384 | if (compare_sids(&(ppace[i]->sid), pgrpsid)) |
385 | access_flags_to_mode(ppace[i]->access_req, | 385 | access_flags_to_mode(ppace[i]->access_req, |
386 | ppace[i]->type, | 386 | ppace[i]->type, |
387 | &(inode->i_mode), | 387 | &fattr->cf_mode, |
388 | &group_mask); | 388 | &group_mask); |
389 | if (compare_sids(&(ppace[i]->sid), &sid_everyone)) | 389 | if (compare_sids(&(ppace[i]->sid), &sid_everyone)) |
390 | access_flags_to_mode(ppace[i]->access_req, | 390 | access_flags_to_mode(ppace[i]->access_req, |
391 | ppace[i]->type, | 391 | ppace[i]->type, |
392 | &(inode->i_mode), | 392 | &fattr->cf_mode, |
393 | &other_mask); | 393 | &other_mask); |
394 | 394 | ||
395 | /* memcpy((void *)(&(cifscred->aces[i])), | 395 | /* memcpy((void *)(&(cifscred->aces[i])), |
@@ -464,7 +464,7 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | |||
464 | 464 | ||
465 | /* Convert CIFS ACL to POSIX form */ | 465 | /* Convert CIFS ACL to POSIX form */ |
466 | static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | 466 | static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, |
467 | struct inode *inode) | 467 | struct cifs_fattr *fattr) |
468 | { | 468 | { |
469 | int rc; | 469 | int rc; |
470 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; | 470 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; |
@@ -472,7 +472,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
472 | char *end_of_acl = ((char *)pntsd) + acl_len; | 472 | char *end_of_acl = ((char *)pntsd) + acl_len; |
473 | __u32 dacloffset; | 473 | __u32 dacloffset; |
474 | 474 | ||
475 | if ((inode == NULL) || (pntsd == NULL)) | 475 | if (pntsd == NULL) |
476 | return -EIO; | 476 | return -EIO; |
477 | 477 | ||
478 | owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + | 478 | owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + |
@@ -497,7 +497,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
497 | 497 | ||
498 | if (dacloffset) | 498 | if (dacloffset) |
499 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, | 499 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, |
500 | group_sid_ptr, inode); | 500 | group_sid_ptr, fattr); |
501 | else | 501 | else |
502 | cFYI(1, ("no ACL")); /* BB grant all or default perms? */ | 502 | cFYI(1, ("no ACL")); /* BB grant all or default perms? */ |
503 | 503 | ||
@@ -508,7 +508,6 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
508 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, | 508 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, |
509 | sizeof(struct cifs_sid)); */ | 509 | sizeof(struct cifs_sid)); */ |
510 | 510 | ||
511 | |||
512 | return 0; | 511 | return 0; |
513 | } | 512 | } |
514 | 513 | ||
@@ -671,8 +670,9 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | |||
671 | } | 670 | } |
672 | 671 | ||
673 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ | 672 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ |
674 | void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, | 673 | void |
675 | const char *path, const __u16 *pfid) | 674 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, |
675 | struct inode *inode, const char *path, const __u16 *pfid) | ||
676 | { | 676 | { |
677 | struct cifs_ntsd *pntsd = NULL; | 677 | struct cifs_ntsd *pntsd = NULL; |
678 | u32 acllen = 0; | 678 | u32 acllen = 0; |
@@ -687,7 +687,7 @@ void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, | |||
687 | 687 | ||
688 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ | 688 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ |
689 | if (pntsd) | 689 | if (pntsd) |
690 | rc = parse_sec_desc(pntsd, acllen, inode); | 690 | rc = parse_sec_desc(pntsd, acllen, fattr); |
691 | if (rc) | 691 | if (rc) |
692 | cFYI(1, ("parse sec desc failed rc = %d", rc)); | 692 | cFYI(1, ("parse sec desc failed rc = %d", rc)); |
693 | 693 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 9f669f982c4d..44f30504b82d 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -308,7 +308,6 @@ cifs_alloc_inode(struct super_block *sb) | |||
308 | if (!cifs_inode) | 308 | if (!cifs_inode) |
309 | return NULL; | 309 | return NULL; |
310 | cifs_inode->cifsAttrs = 0x20; /* default */ | 310 | cifs_inode->cifsAttrs = 0x20; /* default */ |
311 | atomic_set(&cifs_inode->inUse, 0); | ||
312 | cifs_inode->time = 0; | 311 | cifs_inode->time = 0; |
313 | cifs_inode->write_behind_rc = 0; | 312 | cifs_inode->write_behind_rc = 0; |
314 | /* Until the file is open and we have gotten oplock | 313 | /* Until the file is open and we have gotten oplock |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 9570a0e8023f..6c170948300d 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -24,6 +24,19 @@ | |||
24 | 24 | ||
25 | #define ROOT_I 2 | 25 | #define ROOT_I 2 |
26 | 26 | ||
27 | /* | ||
28 | * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down | ||
29 | * so that it will fit. | ||
30 | */ | ||
31 | static inline ino_t | ||
32 | cifs_uniqueid_to_ino_t(u64 fileid) | ||
33 | { | ||
34 | ino_t ino = (ino_t) fileid; | ||
35 | if (sizeof(ino_t) < sizeof(u64)) | ||
36 | ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8; | ||
37 | return ino; | ||
38 | } | ||
39 | |||
27 | extern struct file_system_type cifs_fs_type; | 40 | extern struct file_system_type cifs_fs_type; |
28 | extern const struct address_space_operations cifs_addr_ops; | 41 | extern const struct address_space_operations cifs_addr_ops; |
29 | extern const struct address_space_operations cifs_addr_ops_smallbuf; | 42 | extern const struct address_space_operations cifs_addr_ops_smallbuf; |
@@ -100,5 +113,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
100 | extern const struct export_operations cifs_export_ops; | 113 | extern const struct export_operations cifs_export_ops; |
101 | #endif /* EXPERIMENTAL */ | 114 | #endif /* EXPERIMENTAL */ |
102 | 115 | ||
103 | #define CIFS_VERSION "1.59" | 116 | #define CIFS_VERSION "1.60" |
104 | #endif /* _CIFSFS_H */ | 117 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index e1225e6ded2f..63f6cdfa5638 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -364,13 +364,13 @@ struct cifsInodeInfo { | |||
364 | struct list_head openFileList; | 364 | struct list_head openFileList; |
365 | int write_behind_rc; | 365 | int write_behind_rc; |
366 | __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ | 366 | __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ |
367 | atomic_t inUse; /* num concurrent users (local openers cifs) of file*/ | ||
368 | unsigned long time; /* jiffies of last update/check of inode */ | 367 | unsigned long time; /* jiffies of last update/check of inode */ |
369 | bool clientCanCacheRead:1; /* read oplock */ | 368 | bool clientCanCacheRead:1; /* read oplock */ |
370 | bool clientCanCacheAll:1; /* read and writebehind oplock */ | 369 | bool clientCanCacheAll:1; /* read and writebehind oplock */ |
371 | bool oplockPending:1; | 370 | bool oplockPending:1; |
372 | bool delete_pending:1; /* DELETE_ON_CLOSE is set */ | 371 | bool delete_pending:1; /* DELETE_ON_CLOSE is set */ |
373 | u64 server_eof; /* current file size on server */ | 372 | u64 server_eof; /* current file size on server */ |
373 | u64 uniqueid; /* server inode number */ | ||
374 | struct inode vfs_inode; | 374 | struct inode vfs_inode; |
375 | }; | 375 | }; |
376 | 376 | ||
@@ -472,6 +472,32 @@ struct dfs_info3_param { | |||
472 | char *node_name; | 472 | char *node_name; |
473 | }; | 473 | }; |
474 | 474 | ||
475 | /* | ||
476 | * common struct for holding inode info when searching for or updating an | ||
477 | * inode with new info | ||
478 | */ | ||
479 | |||
480 | #define CIFS_FATTR_DFS_REFERRAL 0x1 | ||
481 | #define CIFS_FATTR_DELETE_PENDING 0x2 | ||
482 | #define CIFS_FATTR_NEED_REVAL 0x4 | ||
483 | |||
484 | struct cifs_fattr { | ||
485 | u32 cf_flags; | ||
486 | u32 cf_cifsattrs; | ||
487 | u64 cf_uniqueid; | ||
488 | u64 cf_eof; | ||
489 | u64 cf_bytes; | ||
490 | uid_t cf_uid; | ||
491 | gid_t cf_gid; | ||
492 | umode_t cf_mode; | ||
493 | dev_t cf_rdev; | ||
494 | unsigned int cf_nlink; | ||
495 | unsigned int cf_dtype; | ||
496 | struct timespec cf_atime; | ||
497 | struct timespec cf_mtime; | ||
498 | struct timespec cf_ctime; | ||
499 | }; | ||
500 | |||
475 | static inline void free_dfs_info_param(struct dfs_info3_param *param) | 501 | static inline void free_dfs_info_param(struct dfs_info3_param *param) |
476 | { | 502 | { |
477 | if (param) { | 503 | if (param) { |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index a785f69dbc9f..2d07f890a842 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -2328,19 +2328,7 @@ struct file_attrib_tag { | |||
2328 | typedef struct { | 2328 | typedef struct { |
2329 | __le32 NextEntryOffset; | 2329 | __le32 NextEntryOffset; |
2330 | __u32 ResumeKey; /* as with FileIndex - no need to convert */ | 2330 | __u32 ResumeKey; /* as with FileIndex - no need to convert */ |
2331 | __le64 EndOfFile; | 2331 | FILE_UNIX_BASIC_INFO basic; |
2332 | __le64 NumOfBytes; | ||
2333 | __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */ | ||
2334 | __le64 LastAccessTime; | ||
2335 | __le64 LastModificationTime; | ||
2336 | __le64 Uid; | ||
2337 | __le64 Gid; | ||
2338 | __le32 Type; | ||
2339 | __le64 DevMajor; | ||
2340 | __le64 DevMinor; | ||
2341 | __le64 UniqueId; | ||
2342 | __le64 Permissions; | ||
2343 | __le64 Nlinks; | ||
2344 | char FileName[1]; | 2332 | char FileName[1]; |
2345 | } __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */ | 2333 | } __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */ |
2346 | 2334 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index c419416a42ee..da8fbf565991 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -98,9 +98,13 @@ extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, | |||
98 | extern int cifs_posix_open(char *full_path, struct inode **pinode, | 98 | extern int cifs_posix_open(char *full_path, struct inode **pinode, |
99 | struct super_block *sb, int mode, int oflags, | 99 | struct super_block *sb, int mode, int oflags, |
100 | int *poplock, __u16 *pnetfid, int xid); | 100 | int *poplock, __u16 *pnetfid, int xid); |
101 | extern void posix_fill_in_inode(struct inode *tmp_inode, | 101 | extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, |
102 | FILE_UNIX_BASIC_INFO *pData, int isNewInode); | 102 | FILE_UNIX_BASIC_INFO *info, |
103 | extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); | 103 | struct cifs_sb_info *cifs_sb); |
104 | extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr); | ||
105 | extern struct inode *cifs_iget(struct super_block *sb, | ||
106 | struct cifs_fattr *fattr); | ||
107 | |||
104 | extern int cifs_get_inode_info(struct inode **pinode, | 108 | extern int cifs_get_inode_info(struct inode **pinode, |
105 | const unsigned char *search_path, | 109 | const unsigned char *search_path, |
106 | FILE_ALL_INFO *pfile_info, | 110 | FILE_ALL_INFO *pfile_info, |
@@ -108,8 +112,9 @@ extern int cifs_get_inode_info(struct inode **pinode, | |||
108 | extern int cifs_get_inode_info_unix(struct inode **pinode, | 112 | extern int cifs_get_inode_info_unix(struct inode **pinode, |
109 | const unsigned char *search_path, | 113 | const unsigned char *search_path, |
110 | struct super_block *sb, int xid); | 114 | struct super_block *sb, int xid); |
111 | extern void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, | 115 | extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, |
112 | const char *path, const __u16 *pfid); | 116 | struct cifs_fattr *fattr, struct inode *inode, |
117 | const char *path, const __u16 *pfid); | ||
113 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); | 118 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); |
114 | 119 | ||
115 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, | 120 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, |
@@ -215,7 +220,11 @@ struct cifs_unix_set_info_args { | |||
215 | dev_t device; | 220 | dev_t device; |
216 | }; | 221 | }; |
217 | 222 | ||
218 | extern int CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *pTcon, | 223 | extern int CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, |
224 | const struct cifs_unix_set_info_args *args, | ||
225 | u16 fid, u32 pid_of_opener); | ||
226 | |||
227 | extern int CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *pTcon, | ||
219 | char *fileName, | 228 | char *fileName, |
220 | const struct cifs_unix_set_info_args *args, | 229 | const struct cifs_unix_set_info_args *args, |
221 | const struct nls_table *nls_codepage, | 230 | const struct nls_table *nls_codepage, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 61007c627497..922f5fe2084c 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -5074,10 +5074,114 @@ SetAttrLgcyRetry: | |||
5074 | } | 5074 | } |
5075 | #endif /* temporarily unneeded SetAttr legacy function */ | 5075 | #endif /* temporarily unneeded SetAttr legacy function */ |
5076 | 5076 | ||
5077 | static void | ||
5078 | cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, | ||
5079 | const struct cifs_unix_set_info_args *args) | ||
5080 | { | ||
5081 | u64 mode = args->mode; | ||
5082 | |||
5083 | /* | ||
5084 | * Samba server ignores set of file size to zero due to bugs in some | ||
5085 | * older clients, but we should be precise - we use SetFileSize to | ||
5086 | * set file size and do not want to truncate file size to zero | ||
5087 | * accidently as happened on one Samba server beta by putting | ||
5088 | * zero instead of -1 here | ||
5089 | */ | ||
5090 | data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); | ||
5091 | data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); | ||
5092 | data_offset->LastStatusChange = cpu_to_le64(args->ctime); | ||
5093 | data_offset->LastAccessTime = cpu_to_le64(args->atime); | ||
5094 | data_offset->LastModificationTime = cpu_to_le64(args->mtime); | ||
5095 | data_offset->Uid = cpu_to_le64(args->uid); | ||
5096 | data_offset->Gid = cpu_to_le64(args->gid); | ||
5097 | /* better to leave device as zero when it is */ | ||
5098 | data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); | ||
5099 | data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); | ||
5100 | data_offset->Permissions = cpu_to_le64(mode); | ||
5101 | |||
5102 | if (S_ISREG(mode)) | ||
5103 | data_offset->Type = cpu_to_le32(UNIX_FILE); | ||
5104 | else if (S_ISDIR(mode)) | ||
5105 | data_offset->Type = cpu_to_le32(UNIX_DIR); | ||
5106 | else if (S_ISLNK(mode)) | ||
5107 | data_offset->Type = cpu_to_le32(UNIX_SYMLINK); | ||
5108 | else if (S_ISCHR(mode)) | ||
5109 | data_offset->Type = cpu_to_le32(UNIX_CHARDEV); | ||
5110 | else if (S_ISBLK(mode)) | ||
5111 | data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV); | ||
5112 | else if (S_ISFIFO(mode)) | ||
5113 | data_offset->Type = cpu_to_le32(UNIX_FIFO); | ||
5114 | else if (S_ISSOCK(mode)) | ||
5115 | data_offset->Type = cpu_to_le32(UNIX_SOCKET); | ||
5116 | } | ||
5117 | |||
5077 | int | 5118 | int |
5078 | CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | 5119 | CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, |
5079 | const struct cifs_unix_set_info_args *args, | 5120 | const struct cifs_unix_set_info_args *args, |
5080 | const struct nls_table *nls_codepage, int remap) | 5121 | u16 fid, u32 pid_of_opener) |
5122 | { | ||
5123 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | ||
5124 | FILE_UNIX_BASIC_INFO *data_offset; | ||
5125 | int rc = 0; | ||
5126 | u16 params, param_offset, offset, byte_count, count; | ||
5127 | |||
5128 | cFYI(1, ("Set Unix Info (via SetFileInfo)")); | ||
5129 | rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); | ||
5130 | |||
5131 | if (rc) | ||
5132 | return rc; | ||
5133 | |||
5134 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); | ||
5135 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); | ||
5136 | |||
5137 | params = 6; | ||
5138 | pSMB->MaxSetupCount = 0; | ||
5139 | pSMB->Reserved = 0; | ||
5140 | pSMB->Flags = 0; | ||
5141 | pSMB->Timeout = 0; | ||
5142 | pSMB->Reserved2 = 0; | ||
5143 | param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; | ||
5144 | offset = param_offset + params; | ||
5145 | |||
5146 | data_offset = (FILE_UNIX_BASIC_INFO *) | ||
5147 | ((char *)(&pSMB->hdr.Protocol) + offset); | ||
5148 | count = sizeof(FILE_UNIX_BASIC_INFO); | ||
5149 | |||
5150 | pSMB->MaxParameterCount = cpu_to_le16(2); | ||
5151 | /* BB find max SMB PDU from sess */ | ||
5152 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
5153 | pSMB->SetupCount = 1; | ||
5154 | pSMB->Reserved3 = 0; | ||
5155 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); | ||
5156 | byte_count = 3 /* pad */ + params + count; | ||
5157 | pSMB->DataCount = cpu_to_le16(count); | ||
5158 | pSMB->ParameterCount = cpu_to_le16(params); | ||
5159 | pSMB->TotalDataCount = pSMB->DataCount; | ||
5160 | pSMB->TotalParameterCount = pSMB->ParameterCount; | ||
5161 | pSMB->ParameterOffset = cpu_to_le16(param_offset); | ||
5162 | pSMB->DataOffset = cpu_to_le16(offset); | ||
5163 | pSMB->Fid = fid; | ||
5164 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | ||
5165 | pSMB->Reserved4 = 0; | ||
5166 | pSMB->hdr.smb_buf_length += byte_count; | ||
5167 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
5168 | |||
5169 | cifs_fill_unix_set_info(data_offset, args); | ||
5170 | |||
5171 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | ||
5172 | if (rc) | ||
5173 | cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); | ||
5174 | |||
5175 | /* Note: On -EAGAIN error only caller can retry on handle based calls | ||
5176 | since file handle passed in no longer valid */ | ||
5177 | |||
5178 | return rc; | ||
5179 | } | ||
5180 | |||
5181 | int | ||
5182 | CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | ||
5183 | const struct cifs_unix_set_info_args *args, | ||
5184 | const struct nls_table *nls_codepage, int remap) | ||
5081 | { | 5185 | { |
5082 | TRANSACTION2_SPI_REQ *pSMB = NULL; | 5186 | TRANSACTION2_SPI_REQ *pSMB = NULL; |
5083 | TRANSACTION2_SPI_RSP *pSMBr = NULL; | 5187 | TRANSACTION2_SPI_RSP *pSMBr = NULL; |
@@ -5086,7 +5190,6 @@ CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | |||
5086 | int bytes_returned = 0; | 5190 | int bytes_returned = 0; |
5087 | FILE_UNIX_BASIC_INFO *data_offset; | 5191 | FILE_UNIX_BASIC_INFO *data_offset; |
5088 | __u16 params, param_offset, offset, count, byte_count; | 5192 | __u16 params, param_offset, offset, count, byte_count; |
5089 | __u64 mode = args->mode; | ||
5090 | 5193 | ||
5091 | cFYI(1, ("In SetUID/GID/Mode")); | 5194 | cFYI(1, ("In SetUID/GID/Mode")); |
5092 | setPermsRetry: | 5195 | setPermsRetry: |
@@ -5137,38 +5240,8 @@ setPermsRetry: | |||
5137 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | 5240 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); |
5138 | pSMB->Reserved4 = 0; | 5241 | pSMB->Reserved4 = 0; |
5139 | pSMB->hdr.smb_buf_length += byte_count; | 5242 | pSMB->hdr.smb_buf_length += byte_count; |
5140 | /* Samba server ignores set of file size to zero due to bugs in some | ||
5141 | older clients, but we should be precise - we use SetFileSize to | ||
5142 | set file size and do not want to truncate file size to zero | ||
5143 | accidently as happened on one Samba server beta by putting | ||
5144 | zero instead of -1 here */ | ||
5145 | data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); | ||
5146 | data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); | ||
5147 | data_offset->LastStatusChange = cpu_to_le64(args->ctime); | ||
5148 | data_offset->LastAccessTime = cpu_to_le64(args->atime); | ||
5149 | data_offset->LastModificationTime = cpu_to_le64(args->mtime); | ||
5150 | data_offset->Uid = cpu_to_le64(args->uid); | ||
5151 | data_offset->Gid = cpu_to_le64(args->gid); | ||
5152 | /* better to leave device as zero when it is */ | ||
5153 | data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); | ||
5154 | data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); | ||
5155 | data_offset->Permissions = cpu_to_le64(mode); | ||
5156 | |||
5157 | if (S_ISREG(mode)) | ||
5158 | data_offset->Type = cpu_to_le32(UNIX_FILE); | ||
5159 | else if (S_ISDIR(mode)) | ||
5160 | data_offset->Type = cpu_to_le32(UNIX_DIR); | ||
5161 | else if (S_ISLNK(mode)) | ||
5162 | data_offset->Type = cpu_to_le32(UNIX_SYMLINK); | ||
5163 | else if (S_ISCHR(mode)) | ||
5164 | data_offset->Type = cpu_to_le32(UNIX_CHARDEV); | ||
5165 | else if (S_ISBLK(mode)) | ||
5166 | data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV); | ||
5167 | else if (S_ISFIFO(mode)) | ||
5168 | data_offset->Type = cpu_to_le32(UNIX_FIFO); | ||
5169 | else if (S_ISSOCK(mode)) | ||
5170 | data_offset->Type = cpu_to_le32(UNIX_SOCKET); | ||
5171 | 5243 | ||
5244 | cifs_fill_unix_set_info(data_offset, args); | ||
5172 | 5245 | ||
5173 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5246 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5174 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5247 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 7dc6b74f9def..4326ffd90fa9 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -188,6 +188,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
188 | FILE_UNIX_BASIC_INFO *presp_data; | 188 | FILE_UNIX_BASIC_INFO *presp_data; |
189 | __u32 posix_flags = 0; | 189 | __u32 posix_flags = 0; |
190 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 190 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
191 | struct cifs_fattr fattr; | ||
191 | 192 | ||
192 | cFYI(1, ("posix open %s", full_path)); | 193 | cFYI(1, ("posix open %s", full_path)); |
193 | 194 | ||
@@ -236,22 +237,21 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
236 | if (presp_data->Type == cpu_to_le32(-1)) | 237 | if (presp_data->Type == cpu_to_le32(-1)) |
237 | goto posix_open_ret; /* open ok, caller does qpathinfo */ | 238 | goto posix_open_ret; /* open ok, caller does qpathinfo */ |
238 | 239 | ||
239 | /* get new inode and set it up */ | ||
240 | if (!pinode) | 240 | if (!pinode) |
241 | goto posix_open_ret; /* caller does not need info */ | 241 | goto posix_open_ret; /* caller does not need info */ |
242 | 242 | ||
243 | cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb); | ||
244 | |||
245 | /* get new inode and set it up */ | ||
243 | if (*pinode == NULL) { | 246 | if (*pinode == NULL) { |
244 | __u64 unique_id = le64_to_cpu(presp_data->UniqueId); | 247 | *pinode = cifs_iget(sb, &fattr); |
245 | *pinode = cifs_new_inode(sb, &unique_id); | 248 | if (!*pinode) { |
249 | rc = -ENOMEM; | ||
250 | goto posix_open_ret; | ||
251 | } | ||
252 | } else { | ||
253 | cifs_fattr_to_inode(*pinode, &fattr); | ||
246 | } | 254 | } |
247 | /* else an inode was passed in. Update its info, don't create one */ | ||
248 | |||
249 | /* We do not need to close the file if new_inode fails since | ||
250 | the caller will retry qpathinfo as long as inode is null */ | ||
251 | if (*pinode == NULL) | ||
252 | goto posix_open_ret; | ||
253 | |||
254 | posix_fill_in_inode(*pinode, presp_data, 1); | ||
255 | 255 | ||
256 | cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); | 256 | cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); |
257 | 257 | ||
@@ -425,9 +425,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
425 | args.uid = NO_CHANGE_64; | 425 | args.uid = NO_CHANGE_64; |
426 | args.gid = NO_CHANGE_64; | 426 | args.gid = NO_CHANGE_64; |
427 | } | 427 | } |
428 | CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, | 428 | CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, |
429 | cifs_sb->local_nls, | 429 | cifs_sb->local_nls, |
430 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 430 | cifs_sb->mnt_cifs_flags & |
431 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
431 | } else { | 432 | } else { |
432 | /* BB implement mode setting via Windows security | 433 | /* BB implement mode setting via Windows security |
433 | descriptors e.g. */ | 434 | descriptors e.g. */ |
@@ -515,10 +516,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
515 | args.uid = NO_CHANGE_64; | 516 | args.uid = NO_CHANGE_64; |
516 | args.gid = NO_CHANGE_64; | 517 | args.gid = NO_CHANGE_64; |
517 | } | 518 | } |
518 | rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, | 519 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, |
519 | &args, cifs_sb->local_nls, | 520 | cifs_sb->local_nls, |
520 | cifs_sb->mnt_cifs_flags & | 521 | cifs_sb->mnt_cifs_flags & |
521 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 522 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
522 | 523 | ||
523 | if (!rc) { | 524 | if (!rc) { |
524 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 525 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
@@ -643,6 +644,15 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
643 | } | 644 | } |
644 | } | 645 | } |
645 | 646 | ||
647 | /* | ||
648 | * O_EXCL: optimize away the lookup, but don't hash the dentry. Let | ||
649 | * the VFS handle the create. | ||
650 | */ | ||
651 | if (nd->flags & LOOKUP_EXCL) { | ||
652 | d_instantiate(direntry, NULL); | ||
653 | return 0; | ||
654 | } | ||
655 | |||
646 | /* can not grab the rename sem here since it would | 656 | /* can not grab the rename sem here since it would |
647 | deadlock in the cases (beginning of sys_rename itself) | 657 | deadlock in the cases (beginning of sys_rename itself) |
648 | in which we already have the sb rename sem */ | 658 | in which we already have the sb rename sem */ |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 97ce4bf89d15..c34b7f8a217b 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -448,9 +448,9 @@ int cifs_open(struct inode *inode, struct file *file) | |||
448 | .mtime = NO_CHANGE_64, | 448 | .mtime = NO_CHANGE_64, |
449 | .device = 0, | 449 | .device = 0, |
450 | }; | 450 | }; |
451 | CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, | 451 | CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, |
452 | cifs_sb->local_nls, | 452 | cifs_sb->local_nls, |
453 | cifs_sb->mnt_cifs_flags & | 453 | cifs_sb->mnt_cifs_flags & |
454 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 454 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
455 | } | 455 | } |
456 | } | 456 | } |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 155c9e785d0c..18afe57b2461 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -77,239 +77,202 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | |||
77 | } | 77 | } |
78 | } | 78 | } |
79 | 79 | ||
80 | static void cifs_unix_info_to_inode(struct inode *inode, | 80 | /* populate an inode with info from a cifs_fattr struct */ |
81 | FILE_UNIX_BASIC_INFO *info, int force_uid_gid) | 81 | void |
82 | cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | ||
82 | { | 83 | { |
84 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | ||
83 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 85 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
84 | struct cifsInodeInfo *cifsInfo = CIFS_I(inode); | 86 | unsigned long oldtime = cifs_i->time; |
85 | __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes); | 87 | |
86 | __u64 end_of_file = le64_to_cpu(info->EndOfFile); | 88 | inode->i_atime = fattr->cf_atime; |
89 | inode->i_mtime = fattr->cf_mtime; | ||
90 | inode->i_ctime = fattr->cf_ctime; | ||
91 | inode->i_rdev = fattr->cf_rdev; | ||
92 | inode->i_nlink = fattr->cf_nlink; | ||
93 | inode->i_uid = fattr->cf_uid; | ||
94 | inode->i_gid = fattr->cf_gid; | ||
95 | |||
96 | /* if dynperm is set, don't clobber existing mode */ | ||
97 | if (inode->i_state & I_NEW || | ||
98 | !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) | ||
99 | inode->i_mode = fattr->cf_mode; | ||
100 | |||
101 | cifs_i->cifsAttrs = fattr->cf_cifsattrs; | ||
102 | cifs_i->uniqueid = fattr->cf_uniqueid; | ||
103 | |||
104 | if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL) | ||
105 | cifs_i->time = 0; | ||
106 | else | ||
107 | cifs_i->time = jiffies; | ||
108 | |||
109 | cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode, | ||
110 | oldtime, cifs_i->time)); | ||
87 | 111 | ||
88 | inode->i_atime = cifs_NTtimeToUnix(info->LastAccessTime); | 112 | cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; |
89 | inode->i_mtime = | 113 | |
90 | cifs_NTtimeToUnix(info->LastModificationTime); | 114 | /* |
91 | inode->i_ctime = cifs_NTtimeToUnix(info->LastStatusChange); | 115 | * Can't safely change the file size here if the client is writing to |
92 | inode->i_mode = le64_to_cpu(info->Permissions); | 116 | * it due to potential races. |
117 | */ | ||
118 | spin_lock(&inode->i_lock); | ||
119 | if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { | ||
120 | i_size_write(inode, fattr->cf_eof); | ||
121 | |||
122 | /* | ||
123 | * i_blocks is not related to (i_size / i_blksize), | ||
124 | * but instead 512 byte (2**9) size is required for | ||
125 | * calculating num blocks. | ||
126 | */ | ||
127 | inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9; | ||
128 | } | ||
129 | spin_unlock(&inode->i_lock); | ||
130 | |||
131 | cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL); | ||
132 | } | ||
133 | |||
134 | /* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */ | ||
135 | void | ||
136 | cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, | ||
137 | struct cifs_sb_info *cifs_sb) | ||
138 | { | ||
139 | memset(fattr, 0, sizeof(*fattr)); | ||
140 | fattr->cf_uniqueid = le64_to_cpu(info->UniqueId); | ||
141 | fattr->cf_bytes = le64_to_cpu(info->NumOfBytes); | ||
142 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); | ||
143 | |||
144 | fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); | ||
145 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime); | ||
146 | fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange); | ||
147 | fattr->cf_mode = le64_to_cpu(info->Permissions); | ||
93 | 148 | ||
94 | /* | 149 | /* |
95 | * Since we set the inode type below we need to mask off | 150 | * Since we set the inode type below we need to mask off |
96 | * to avoid strange results if bits set above. | 151 | * to avoid strange results if bits set above. |
97 | */ | 152 | */ |
98 | inode->i_mode &= ~S_IFMT; | 153 | fattr->cf_mode &= ~S_IFMT; |
99 | switch (le32_to_cpu(info->Type)) { | 154 | switch (le32_to_cpu(info->Type)) { |
100 | case UNIX_FILE: | 155 | case UNIX_FILE: |
101 | inode->i_mode |= S_IFREG; | 156 | fattr->cf_mode |= S_IFREG; |
157 | fattr->cf_dtype = DT_REG; | ||
102 | break; | 158 | break; |
103 | case UNIX_SYMLINK: | 159 | case UNIX_SYMLINK: |
104 | inode->i_mode |= S_IFLNK; | 160 | fattr->cf_mode |= S_IFLNK; |
161 | fattr->cf_dtype = DT_LNK; | ||
105 | break; | 162 | break; |
106 | case UNIX_DIR: | 163 | case UNIX_DIR: |
107 | inode->i_mode |= S_IFDIR; | 164 | fattr->cf_mode |= S_IFDIR; |
165 | fattr->cf_dtype = DT_DIR; | ||
108 | break; | 166 | break; |
109 | case UNIX_CHARDEV: | 167 | case UNIX_CHARDEV: |
110 | inode->i_mode |= S_IFCHR; | 168 | fattr->cf_mode |= S_IFCHR; |
111 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | 169 | fattr->cf_dtype = DT_CHR; |
112 | le64_to_cpu(info->DevMinor) & MINORMASK); | 170 | fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), |
171 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
113 | break; | 172 | break; |
114 | case UNIX_BLOCKDEV: | 173 | case UNIX_BLOCKDEV: |
115 | inode->i_mode |= S_IFBLK; | 174 | fattr->cf_mode |= S_IFBLK; |
116 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | 175 | fattr->cf_dtype = DT_BLK; |
117 | le64_to_cpu(info->DevMinor) & MINORMASK); | 176 | fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), |
177 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
118 | break; | 178 | break; |
119 | case UNIX_FIFO: | 179 | case UNIX_FIFO: |
120 | inode->i_mode |= S_IFIFO; | 180 | fattr->cf_mode |= S_IFIFO; |
181 | fattr->cf_dtype = DT_FIFO; | ||
121 | break; | 182 | break; |
122 | case UNIX_SOCKET: | 183 | case UNIX_SOCKET: |
123 | inode->i_mode |= S_IFSOCK; | 184 | fattr->cf_mode |= S_IFSOCK; |
185 | fattr->cf_dtype = DT_SOCK; | ||
124 | break; | 186 | break; |
125 | default: | 187 | default: |
126 | /* safest to call it a file if we do not know */ | 188 | /* safest to call it a file if we do not know */ |
127 | inode->i_mode |= S_IFREG; | 189 | fattr->cf_mode |= S_IFREG; |
190 | fattr->cf_dtype = DT_REG; | ||
128 | cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); | 191 | cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); |
129 | break; | 192 | break; |
130 | } | 193 | } |
131 | 194 | ||
132 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) && | 195 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) |
133 | !force_uid_gid) | 196 | fattr->cf_uid = cifs_sb->mnt_uid; |
134 | inode->i_uid = cifs_sb->mnt_uid; | ||
135 | else | 197 | else |
136 | inode->i_uid = le64_to_cpu(info->Uid); | 198 | fattr->cf_uid = le64_to_cpu(info->Uid); |
137 | 199 | ||
138 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) && | 200 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) |
139 | !force_uid_gid) | 201 | fattr->cf_gid = cifs_sb->mnt_gid; |
140 | inode->i_gid = cifs_sb->mnt_gid; | ||
141 | else | 202 | else |
142 | inode->i_gid = le64_to_cpu(info->Gid); | 203 | fattr->cf_gid = le64_to_cpu(info->Gid); |
143 | |||
144 | inode->i_nlink = le64_to_cpu(info->Nlinks); | ||
145 | |||
146 | cifsInfo->server_eof = end_of_file; | ||
147 | spin_lock(&inode->i_lock); | ||
148 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
149 | /* | ||
150 | * We can not safely change the file size here if the client | ||
151 | * is writing to it due to potential races. | ||
152 | */ | ||
153 | i_size_write(inode, end_of_file); | ||
154 | 204 | ||
155 | /* | 205 | fattr->cf_nlink = le64_to_cpu(info->Nlinks); |
156 | * i_blocks is not related to (i_size / i_blksize), | ||
157 | * but instead 512 byte (2**9) size is required for | ||
158 | * calculating num blocks. | ||
159 | */ | ||
160 | inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
161 | } | ||
162 | spin_unlock(&inode->i_lock); | ||
163 | } | 206 | } |
164 | 207 | ||
165 | |||
166 | /* | 208 | /* |
167 | * Needed to setup inode data for the directory which is the | 209 | * Fill a cifs_fattr struct with fake inode info. |
168 | * junction to the new submount (ie to setup the fake directory | ||
169 | * which represents a DFS referral) | ||
170 | */ | ||
171 | static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, | ||
172 | struct super_block *sb) | ||
173 | { | ||
174 | struct inode *pinode = NULL; | ||
175 | |||
176 | memset(pfnd_dat, 0, sizeof(FILE_UNIX_BASIC_INFO)); | ||
177 | |||
178 | /* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); | ||
179 | __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); | ||
180 | __u64 UniqueId = 0; */ | ||
181 | pfnd_dat->LastStatusChange = | ||
182 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
183 | pfnd_dat->LastAccessTime = | ||
184 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
185 | pfnd_dat->LastModificationTime = | ||
186 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
187 | pfnd_dat->Type = cpu_to_le32(UNIX_DIR); | ||
188 | pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU); | ||
189 | pfnd_dat->Nlinks = cpu_to_le64(2); | ||
190 | if (sb->s_root) | ||
191 | pinode = sb->s_root->d_inode; | ||
192 | if (pinode == NULL) | ||
193 | return; | ||
194 | |||
195 | /* fill in default values for the remaining based on root | ||
196 | inode since we can not query the server for this inode info */ | ||
197 | pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev)); | ||
198 | pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev)); | ||
199 | pfnd_dat->Uid = cpu_to_le64(pinode->i_uid); | ||
200 | pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); | ||
201 | } | ||
202 | |||
203 | /** | ||
204 | * cifs_new inode - create new inode, initialize, and hash it | ||
205 | * @sb - pointer to superblock | ||
206 | * @inum - if valid pointer and serverino is enabled, replace i_ino with val | ||
207 | * | ||
208 | * Create a new inode, initialize it for CIFS and hash it. Returns the new | ||
209 | * inode or NULL if one couldn't be allocated. | ||
210 | * | 210 | * |
211 | * If the share isn't mounted with "serverino" or inum is a NULL pointer then | 211 | * Needed to setup cifs_fattr data for the directory which is the |
212 | * we'll just use the inode number assigned by new_inode(). Note that this can | 212 | * junction to the new submount (ie to setup the fake directory |
213 | * mean i_ino collisions since the i_ino assigned by new_inode is not | 213 | * which represents a DFS referral). |
214 | * guaranteed to be unique. | ||
215 | */ | 214 | */ |
216 | struct inode * | 215 | void |
217 | cifs_new_inode(struct super_block *sb, __u64 *inum) | 216 | cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) |
218 | { | 217 | { |
219 | struct inode *inode; | 218 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
220 | |||
221 | inode = new_inode(sb); | ||
222 | if (inode == NULL) | ||
223 | return NULL; | ||
224 | |||
225 | /* | ||
226 | * BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we | ||
227 | * stop passing inum as ptr. Are there sanity checks we can use to | ||
228 | * ensure that the server is really filling in that field? Also, | ||
229 | * if serverino is disabled, perhaps we should be using iunique()? | ||
230 | */ | ||
231 | if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) | ||
232 | inode->i_ino = (unsigned long) *inum; | ||
233 | |||
234 | /* | ||
235 | * must set this here instead of cifs_alloc_inode since VFS will | ||
236 | * clobber i_flags | ||
237 | */ | ||
238 | if (sb->s_flags & MS_NOATIME) | ||
239 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | ||
240 | |||
241 | insert_inode_hash(inode); | ||
242 | 219 | ||
243 | return inode; | 220 | cFYI(1, ("creating fake fattr for DFS referral")); |
221 | |||
222 | memset(fattr, 0, sizeof(*fattr)); | ||
223 | fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU; | ||
224 | fattr->cf_uid = cifs_sb->mnt_uid; | ||
225 | fattr->cf_gid = cifs_sb->mnt_gid; | ||
226 | fattr->cf_atime = CURRENT_TIME; | ||
227 | fattr->cf_ctime = CURRENT_TIME; | ||
228 | fattr->cf_mtime = CURRENT_TIME; | ||
229 | fattr->cf_nlink = 2; | ||
230 | fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; | ||
244 | } | 231 | } |
245 | 232 | ||
246 | int cifs_get_inode_info_unix(struct inode **pinode, | 233 | int cifs_get_inode_info_unix(struct inode **pinode, |
247 | const unsigned char *full_path, struct super_block *sb, int xid) | 234 | const unsigned char *full_path, |
235 | struct super_block *sb, int xid) | ||
248 | { | 236 | { |
249 | int rc = 0; | 237 | int rc; |
250 | FILE_UNIX_BASIC_INFO find_data; | 238 | FILE_UNIX_BASIC_INFO find_data; |
251 | struct cifsTconInfo *pTcon; | 239 | struct cifs_fattr fattr; |
252 | struct inode *inode; | 240 | struct cifsTconInfo *tcon; |
253 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 241 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
254 | bool is_dfs_referral = false; | ||
255 | struct cifsInodeInfo *cifsInfo; | ||
256 | __u64 num_of_bytes; | ||
257 | __u64 end_of_file; | ||
258 | 242 | ||
259 | pTcon = cifs_sb->tcon; | 243 | tcon = cifs_sb->tcon; |
260 | cFYI(1, ("Getting info on %s", full_path)); | 244 | cFYI(1, ("Getting info on %s", full_path)); |
261 | 245 | ||
262 | /* could have done a find first instead but this returns more info */ | 246 | /* could have done a find first instead but this returns more info */ |
263 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, | 247 | rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, |
264 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 248 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
265 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 249 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
266 | if (rc == -EREMOTE && !is_dfs_referral) { | ||
267 | is_dfs_referral = true; | ||
268 | cFYI(DBG2, ("DFS ref")); | ||
269 | /* for DFS, server does not give us real inode data */ | ||
270 | fill_fake_finddataunix(&find_data, sb); | ||
271 | rc = 0; | ||
272 | } else if (rc) | ||
273 | goto cgiiu_exit; | ||
274 | 250 | ||
275 | num_of_bytes = le64_to_cpu(find_data.NumOfBytes); | 251 | if (!rc) { |
276 | end_of_file = le64_to_cpu(find_data.EndOfFile); | 252 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); |
253 | } else if (rc == -EREMOTE) { | ||
254 | cifs_create_dfs_fattr(&fattr, sb); | ||
255 | rc = 0; | ||
256 | } else { | ||
257 | return rc; | ||
258 | } | ||
277 | 259 | ||
278 | /* get new inode */ | ||
279 | if (*pinode == NULL) { | 260 | if (*pinode == NULL) { |
280 | __u64 unique_id = le64_to_cpu(find_data.UniqueId); | 261 | /* get new inode */ |
281 | *pinode = cifs_new_inode(sb, &unique_id); | 262 | *pinode = cifs_iget(sb, &fattr); |
282 | if (*pinode == NULL) { | 263 | if (!*pinode) |
283 | rc = -ENOMEM; | 264 | rc = -ENOMEM; |
284 | goto cgiiu_exit; | 265 | } else { |
285 | } | 266 | /* we already have inode, update it */ |
267 | cifs_fattr_to_inode(*pinode, &fattr); | ||
286 | } | 268 | } |
287 | 269 | ||
288 | inode = *pinode; | ||
289 | cifsInfo = CIFS_I(inode); | ||
290 | |||
291 | cFYI(1, ("Old time %ld", cifsInfo->time)); | ||
292 | cifsInfo->time = jiffies; | ||
293 | cFYI(1, ("New time %ld", cifsInfo->time)); | ||
294 | /* this is ok to set on every inode revalidate */ | ||
295 | atomic_set(&cifsInfo->inUse, 1); | ||
296 | |||
297 | cifs_unix_info_to_inode(inode, &find_data, 0); | ||
298 | |||
299 | if (num_of_bytes < end_of_file) | ||
300 | cFYI(1, ("allocation size less than end of file")); | ||
301 | cFYI(1, ("Size %ld and blocks %llu", | ||
302 | (unsigned long) inode->i_size, | ||
303 | (unsigned long long)inode->i_blocks)); | ||
304 | |||
305 | cifs_set_ops(inode, is_dfs_referral); | ||
306 | cgiiu_exit: | ||
307 | return rc; | 270 | return rc; |
308 | } | 271 | } |
309 | 272 | ||
310 | static int decode_sfu_inode(struct inode *inode, __u64 size, | 273 | static int |
311 | const unsigned char *path, | 274 | cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, |
312 | struct cifs_sb_info *cifs_sb, int xid) | 275 | struct cifs_sb_info *cifs_sb, int xid) |
313 | { | 276 | { |
314 | int rc; | 277 | int rc; |
315 | int oplock = 0; | 278 | int oplock = 0; |
@@ -321,10 +284,15 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
321 | 284 | ||
322 | pbuf = buf; | 285 | pbuf = buf; |
323 | 286 | ||
324 | if (size == 0) { | 287 | fattr->cf_mode &= ~S_IFMT; |
325 | inode->i_mode |= S_IFIFO; | 288 | |
289 | if (fattr->cf_eof == 0) { | ||
290 | fattr->cf_mode |= S_IFIFO; | ||
291 | fattr->cf_dtype = DT_FIFO; | ||
326 | return 0; | 292 | return 0; |
327 | } else if (size < 8) { | 293 | } else if (fattr->cf_eof < 8) { |
294 | fattr->cf_mode |= S_IFREG; | ||
295 | fattr->cf_dtype = DT_REG; | ||
328 | return -EINVAL; /* EOPNOTSUPP? */ | 296 | return -EINVAL; /* EOPNOTSUPP? */ |
329 | } | 297 | } |
330 | 298 | ||
@@ -336,42 +304,46 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
336 | if (rc == 0) { | 304 | if (rc == 0) { |
337 | int buf_type = CIFS_NO_BUFFER; | 305 | int buf_type = CIFS_NO_BUFFER; |
338 | /* Read header */ | 306 | /* Read header */ |
339 | rc = CIFSSMBRead(xid, pTcon, | 307 | rc = CIFSSMBRead(xid, pTcon, netfid, |
340 | netfid, | ||
341 | 24 /* length */, 0 /* offset */, | 308 | 24 /* length */, 0 /* offset */, |
342 | &bytes_read, &pbuf, &buf_type); | 309 | &bytes_read, &pbuf, &buf_type); |
343 | if ((rc == 0) && (bytes_read >= 8)) { | 310 | if ((rc == 0) && (bytes_read >= 8)) { |
344 | if (memcmp("IntxBLK", pbuf, 8) == 0) { | 311 | if (memcmp("IntxBLK", pbuf, 8) == 0) { |
345 | cFYI(1, ("Block device")); | 312 | cFYI(1, ("Block device")); |
346 | inode->i_mode |= S_IFBLK; | 313 | fattr->cf_mode |= S_IFBLK; |
314 | fattr->cf_dtype = DT_BLK; | ||
347 | if (bytes_read == 24) { | 315 | if (bytes_read == 24) { |
348 | /* we have enough to decode dev num */ | 316 | /* we have enough to decode dev num */ |
349 | __u64 mjr; /* major */ | 317 | __u64 mjr; /* major */ |
350 | __u64 mnr; /* minor */ | 318 | __u64 mnr; /* minor */ |
351 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | 319 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); |
352 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | 320 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); |
353 | inode->i_rdev = MKDEV(mjr, mnr); | 321 | fattr->cf_rdev = MKDEV(mjr, mnr); |
354 | } | 322 | } |
355 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { | 323 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { |
356 | cFYI(1, ("Char device")); | 324 | cFYI(1, ("Char device")); |
357 | inode->i_mode |= S_IFCHR; | 325 | fattr->cf_mode |= S_IFCHR; |
326 | fattr->cf_dtype = DT_CHR; | ||
358 | if (bytes_read == 24) { | 327 | if (bytes_read == 24) { |
359 | /* we have enough to decode dev num */ | 328 | /* we have enough to decode dev num */ |
360 | __u64 mjr; /* major */ | 329 | __u64 mjr; /* major */ |
361 | __u64 mnr; /* minor */ | 330 | __u64 mnr; /* minor */ |
362 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | 331 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); |
363 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | 332 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); |
364 | inode->i_rdev = MKDEV(mjr, mnr); | 333 | fattr->cf_rdev = MKDEV(mjr, mnr); |
365 | } | 334 | } |
366 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { | 335 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { |
367 | cFYI(1, ("Symlink")); | 336 | cFYI(1, ("Symlink")); |
368 | inode->i_mode |= S_IFLNK; | 337 | fattr->cf_mode |= S_IFLNK; |
338 | fattr->cf_dtype = DT_LNK; | ||
369 | } else { | 339 | } else { |
370 | inode->i_mode |= S_IFREG; /* file? */ | 340 | fattr->cf_mode |= S_IFREG; /* file? */ |
341 | fattr->cf_dtype = DT_REG; | ||
371 | rc = -EOPNOTSUPP; | 342 | rc = -EOPNOTSUPP; |
372 | } | 343 | } |
373 | } else { | 344 | } else { |
374 | inode->i_mode |= S_IFREG; /* then it is a file */ | 345 | fattr->cf_mode |= S_IFREG; /* then it is a file */ |
346 | fattr->cf_dtype = DT_REG; | ||
375 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | 347 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ |
376 | } | 348 | } |
377 | CIFSSMBClose(xid, pTcon, netfid); | 349 | CIFSSMBClose(xid, pTcon, netfid); |
@@ -381,9 +353,13 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
381 | 353 | ||
382 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ | 354 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ |
383 | 355 | ||
384 | static int get_sfu_mode(struct inode *inode, | 356 | /* |
385 | const unsigned char *path, | 357 | * Fetch mode bits as provided by SFU. |
386 | struct cifs_sb_info *cifs_sb, int xid) | 358 | * |
359 | * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ? | ||
360 | */ | ||
361 | static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | ||
362 | struct cifs_sb_info *cifs_sb, int xid) | ||
387 | { | 363 | { |
388 | #ifdef CONFIG_CIFS_XATTR | 364 | #ifdef CONFIG_CIFS_XATTR |
389 | ssize_t rc; | 365 | ssize_t rc; |
@@ -391,68 +367,80 @@ static int get_sfu_mode(struct inode *inode, | |||
391 | __u32 mode; | 367 | __u32 mode; |
392 | 368 | ||
393 | rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", | 369 | rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", |
394 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, | 370 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, |
395 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 371 | cifs_sb->mnt_cifs_flags & |
372 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
396 | if (rc < 0) | 373 | if (rc < 0) |
397 | return (int)rc; | 374 | return (int)rc; |
398 | else if (rc > 3) { | 375 | else if (rc > 3) { |
399 | mode = le32_to_cpu(*((__le32 *)ea_value)); | 376 | mode = le32_to_cpu(*((__le32 *)ea_value)); |
400 | inode->i_mode &= ~SFBITS_MASK; | 377 | fattr->cf_mode &= ~SFBITS_MASK; |
401 | cFYI(1, ("special bits 0%o org mode 0%o", mode, inode->i_mode)); | 378 | cFYI(1, ("special bits 0%o org mode 0%o", mode, |
402 | inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode; | 379 | fattr->cf_mode)); |
380 | fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode; | ||
403 | cFYI(1, ("special mode bits 0%o", mode)); | 381 | cFYI(1, ("special mode bits 0%o", mode)); |
404 | return 0; | ||
405 | } else { | ||
406 | return 0; | ||
407 | } | 382 | } |
383 | |||
384 | return 0; | ||
408 | #else | 385 | #else |
409 | return -EOPNOTSUPP; | 386 | return -EOPNOTSUPP; |
410 | #endif | 387 | #endif |
411 | } | 388 | } |
412 | 389 | ||
413 | /* | 390 | /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ |
414 | * Needed to setup inode data for the directory which is the | 391 | void |
415 | * junction to the new submount (ie to setup the fake directory | 392 | cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, |
416 | * which represents a DFS referral) | 393 | struct cifs_sb_info *cifs_sb, bool adjust_tz) |
417 | */ | ||
418 | static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat, | ||
419 | struct super_block *sb) | ||
420 | { | 394 | { |
421 | memset(pfnd_dat, 0, sizeof(FILE_ALL_INFO)); | 395 | memset(fattr, 0, sizeof(*fattr)); |
422 | 396 | fattr->cf_cifsattrs = le32_to_cpu(info->Attributes); | |
423 | /* __le64 pfnd_dat->AllocationSize = cpu_to_le64(0); | 397 | if (info->DeletePending) |
424 | __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); | 398 | fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING; |
425 | __u8 pfnd_dat->DeletePending = 0; | 399 | |
426 | __u8 pfnd_data->Directory = 0; | 400 | if (info->LastAccessTime) |
427 | __le32 pfnd_dat->EASize = 0; | 401 | fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); |
428 | __u64 pfnd_dat->IndexNumber = 0; | 402 | else |
429 | __u64 pfnd_dat->IndexNumber1 = 0; */ | 403 | fattr->cf_atime = CURRENT_TIME; |
430 | pfnd_dat->CreationTime = | 404 | |
431 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 405 | fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); |
432 | pfnd_dat->LastAccessTime = | 406 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); |
433 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 407 | |
434 | pfnd_dat->LastWriteTime = | 408 | if (adjust_tz) { |
435 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 409 | fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; |
436 | pfnd_dat->ChangeTime = | 410 | fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; |
437 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 411 | } |
438 | pfnd_dat->Attributes = cpu_to_le32(ATTR_DIRECTORY); | 412 | |
439 | pfnd_dat->NumberOfLinks = cpu_to_le32(2); | 413 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); |
414 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); | ||
415 | |||
416 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { | ||
417 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; | ||
418 | fattr->cf_dtype = DT_DIR; | ||
419 | } else { | ||
420 | fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; | ||
421 | fattr->cf_dtype = DT_REG; | ||
422 | |||
423 | /* clear write bits if ATTR_READONLY is set */ | ||
424 | if (fattr->cf_cifsattrs & ATTR_READONLY) | ||
425 | fattr->cf_mode &= ~(S_IWUGO); | ||
426 | } | ||
427 | |||
428 | fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); | ||
429 | |||
430 | fattr->cf_uid = cifs_sb->mnt_uid; | ||
431 | fattr->cf_gid = cifs_sb->mnt_gid; | ||
440 | } | 432 | } |
441 | 433 | ||
442 | int cifs_get_inode_info(struct inode **pinode, | 434 | int cifs_get_inode_info(struct inode **pinode, |
443 | const unsigned char *full_path, FILE_ALL_INFO *pfindData, | 435 | const unsigned char *full_path, FILE_ALL_INFO *pfindData, |
444 | struct super_block *sb, int xid, const __u16 *pfid) | 436 | struct super_block *sb, int xid, const __u16 *pfid) |
445 | { | 437 | { |
446 | int rc = 0; | 438 | int rc = 0, tmprc; |
447 | __u32 attr; | ||
448 | struct cifsInodeInfo *cifsInfo; | ||
449 | struct cifsTconInfo *pTcon; | 439 | struct cifsTconInfo *pTcon; |
450 | struct inode *inode; | ||
451 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 440 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
452 | char *buf = NULL; | 441 | char *buf = NULL; |
453 | bool adjustTZ = false; | 442 | bool adjustTZ = false; |
454 | bool is_dfs_referral = false; | 443 | struct cifs_fattr fattr; |
455 | umode_t default_mode; | ||
456 | 444 | ||
457 | pTcon = cifs_sb->tcon; | 445 | pTcon = cifs_sb->tcon; |
458 | cFYI(1, ("Getting info on %s", full_path)); | 446 | cFYI(1, ("Getting info on %s", full_path)); |
@@ -487,163 +475,82 @@ int cifs_get_inode_info(struct inode **pinode, | |||
487 | adjustTZ = true; | 475 | adjustTZ = true; |
488 | } | 476 | } |
489 | } | 477 | } |
490 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ | 478 | |
491 | if (rc == -EREMOTE) { | 479 | if (!rc) { |
492 | is_dfs_referral = true; | 480 | cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData, |
493 | fill_fake_finddata(pfindData, sb); | 481 | cifs_sb, adjustTZ); |
482 | } else if (rc == -EREMOTE) { | ||
483 | cifs_create_dfs_fattr(&fattr, sb); | ||
494 | rc = 0; | 484 | rc = 0; |
495 | } else if (rc) | 485 | } else { |
496 | goto cgii_exit; | 486 | goto cgii_exit; |
487 | } | ||
497 | 488 | ||
498 | attr = le32_to_cpu(pfindData->Attributes); | 489 | /* |
499 | 490 | * If an inode wasn't passed in, then get the inode number | |
500 | /* get new inode */ | 491 | * |
492 | * Is an i_ino of zero legal? Can we use that to check if the server | ||
493 | * supports returning inode numbers? Are there other sanity checks we | ||
494 | * can use to ensure that the server is really filling in that field? | ||
495 | * | ||
496 | * We can not use the IndexNumber field by default from Windows or | ||
497 | * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA | ||
498 | * CIFS spec claims that this value is unique within the scope of a | ||
499 | * share, and the windows docs hint that it's actually unique | ||
500 | * per-machine. | ||
501 | * | ||
502 | * There may be higher info levels that work but are there Windows | ||
503 | * server or network appliances for which IndexNumber field is not | ||
504 | * guaranteed unique? | ||
505 | */ | ||
501 | if (*pinode == NULL) { | 506 | if (*pinode == NULL) { |
502 | __u64 inode_num; | ||
503 | __u64 *pinum = &inode_num; | ||
504 | |||
505 | /* Is an i_ino of zero legal? Can we use that to check | ||
506 | if the server supports returning inode numbers? Are | ||
507 | there other sanity checks we can use to ensure that | ||
508 | the server is really filling in that field? */ | ||
509 | |||
510 | /* We can not use the IndexNumber field by default from | ||
511 | Windows or Samba (in ALL_INFO buf) but we can request | ||
512 | it explicitly. It may not be unique presumably if | ||
513 | the server has multiple devices mounted under one share */ | ||
514 | |||
515 | /* There may be higher info levels that work but are | ||
516 | there Windows server or network appliances for which | ||
517 | IndexNumber field is not guaranteed unique? */ | ||
518 | |||
519 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 507 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
520 | int rc1 = 0; | 508 | int rc1 = 0; |
521 | 509 | ||
522 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, | 510 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, |
523 | full_path, pinum, | 511 | full_path, &fattr.cf_uniqueid, |
524 | cifs_sb->local_nls, | 512 | cifs_sb->local_nls, |
525 | cifs_sb->mnt_cifs_flags & | 513 | cifs_sb->mnt_cifs_flags & |
526 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 514 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
527 | if (rc1) { | 515 | if (rc1) { |
528 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); | ||
529 | pinum = NULL; | ||
530 | /* BB EOPNOSUPP disable SERVER_INUM? */ | 516 | /* BB EOPNOSUPP disable SERVER_INUM? */ |
517 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); | ||
518 | fattr.cf_uniqueid = iunique(sb, ROOT_I); | ||
531 | } | 519 | } |
532 | } else { | 520 | } else { |
533 | pinum = NULL; | 521 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
534 | } | ||
535 | |||
536 | *pinode = cifs_new_inode(sb, pinum); | ||
537 | if (*pinode == NULL) { | ||
538 | rc = -ENOMEM; | ||
539 | goto cgii_exit; | ||
540 | } | 522 | } |
541 | } | ||
542 | inode = *pinode; | ||
543 | cifsInfo = CIFS_I(inode); | ||
544 | cifsInfo->cifsAttrs = attr; | ||
545 | cifsInfo->delete_pending = pfindData->DeletePending ? true : false; | ||
546 | cFYI(1, ("Old time %ld", cifsInfo->time)); | ||
547 | cifsInfo->time = jiffies; | ||
548 | cFYI(1, ("New time %ld", cifsInfo->time)); | ||
549 | |||
550 | /* blksize needs to be multiple of two. So safer to default to | ||
551 | blksize and blkbits set in superblock so 2**blkbits and blksize | ||
552 | will match rather than setting to: | ||
553 | (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ | ||
554 | |||
555 | /* Linux can not store file creation time so ignore it */ | ||
556 | if (pfindData->LastAccessTime) | ||
557 | inode->i_atime = cifs_NTtimeToUnix(pfindData->LastAccessTime); | ||
558 | else /* do not need to use current_fs_time - time not stored */ | ||
559 | inode->i_atime = CURRENT_TIME; | ||
560 | inode->i_mtime = cifs_NTtimeToUnix(pfindData->LastWriteTime); | ||
561 | inode->i_ctime = cifs_NTtimeToUnix(pfindData->ChangeTime); | ||
562 | cFYI(DBG2, ("Attributes came in as 0x%x", attr)); | ||
563 | if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { | ||
564 | inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; | ||
565 | inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; | ||
566 | } | ||
567 | |||
568 | /* get default inode mode */ | ||
569 | if (attr & ATTR_DIRECTORY) | ||
570 | default_mode = cifs_sb->mnt_dir_mode; | ||
571 | else | ||
572 | default_mode = cifs_sb->mnt_file_mode; | ||
573 | |||
574 | /* set permission bits */ | ||
575 | if (atomic_read(&cifsInfo->inUse) == 0 || | ||
576 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) | ||
577 | inode->i_mode = default_mode; | ||
578 | else { | ||
579 | /* just reenable write bits if !ATTR_READONLY */ | ||
580 | if ((inode->i_mode & S_IWUGO) == 0 && | ||
581 | (attr & ATTR_READONLY) == 0) | ||
582 | inode->i_mode |= (S_IWUGO & default_mode); | ||
583 | |||
584 | inode->i_mode &= ~S_IFMT; | ||
585 | } | ||
586 | /* clear write bits if ATTR_READONLY is set */ | ||
587 | if (attr & ATTR_READONLY) | ||
588 | inode->i_mode &= ~S_IWUGO; | ||
589 | |||
590 | /* set inode type */ | ||
591 | if ((attr & ATTR_SYSTEM) && | ||
592 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { | ||
593 | /* no need to fix endianness on 0 */ | ||
594 | if (pfindData->EndOfFile == 0) | ||
595 | inode->i_mode |= S_IFIFO; | ||
596 | else if (decode_sfu_inode(inode, | ||
597 | le64_to_cpu(pfindData->EndOfFile), | ||
598 | full_path, cifs_sb, xid)) | ||
599 | cFYI(1, ("unknown SFU file type\n")); | ||
600 | } else { | 523 | } else { |
601 | if (attr & ATTR_DIRECTORY) | 524 | fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid; |
602 | inode->i_mode |= S_IFDIR; | ||
603 | else | ||
604 | inode->i_mode |= S_IFREG; | ||
605 | } | 525 | } |
606 | 526 | ||
607 | cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile); | 527 | /* query for SFU type info if supported and needed */ |
608 | spin_lock(&inode->i_lock); | 528 | if (fattr.cf_cifsattrs & ATTR_SYSTEM && |
609 | if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) { | 529 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
610 | /* can not safely shrink the file size here if the | 530 | tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid); |
611 | client is writing to it due to potential races */ | 531 | if (tmprc) |
612 | i_size_write(inode, cifsInfo->server_eof); | 532 | cFYI(1, ("cifs_sfu_type failed: %d", tmprc)); |
613 | |||
614 | /* 512 bytes (2**9) is the fake blocksize that must be | ||
615 | used for this calculation */ | ||
616 | inode->i_blocks = (512 - 1 + le64_to_cpu( | ||
617 | pfindData->AllocationSize)) >> 9; | ||
618 | } | 533 | } |
619 | spin_unlock(&inode->i_lock); | ||
620 | 534 | ||
621 | inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); | ||
622 | |||
623 | /* BB fill in uid and gid here? with help from winbind? | ||
624 | or retrieve from NTFS stream extended attribute */ | ||
625 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 535 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
626 | /* fill in 0777 bits from ACL */ | 536 | /* fill in 0777 bits from ACL */ |
627 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 537 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
628 | cFYI(1, ("Getting mode bits from ACL")); | 538 | cFYI(1, ("Getting mode bits from ACL")); |
629 | acl_to_uid_mode(cifs_sb, inode, full_path, pfid); | 539 | cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); |
630 | } | 540 | } |
631 | #endif | 541 | #endif |
632 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | ||
633 | /* fill in remaining high mode bits e.g. SUID, VTX */ | ||
634 | get_sfu_mode(inode, full_path, cifs_sb, xid); | ||
635 | } else if (atomic_read(&cifsInfo->inUse) == 0) { | ||
636 | inode->i_uid = cifs_sb->mnt_uid; | ||
637 | inode->i_gid = cifs_sb->mnt_gid; | ||
638 | /* set so we do not keep refreshing these fields with | ||
639 | bad data after user has changed them in memory */ | ||
640 | atomic_set(&cifsInfo->inUse, 1); | ||
641 | } | ||
642 | |||
643 | cifs_set_ops(inode, is_dfs_referral); | ||
644 | |||
645 | 542 | ||
543 | /* fill in remaining high mode bits e.g. SUID, VTX */ | ||
544 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) | ||
545 | cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); | ||
646 | 546 | ||
547 | if (!*pinode) { | ||
548 | *pinode = cifs_iget(sb, &fattr); | ||
549 | if (!*pinode) | ||
550 | rc = -ENOMEM; | ||
551 | } else { | ||
552 | cifs_fattr_to_inode(*pinode, &fattr); | ||
553 | } | ||
647 | 554 | ||
648 | cgii_exit: | 555 | cgii_exit: |
649 | kfree(buf); | 556 | kfree(buf); |
@@ -695,33 +602,78 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | |||
695 | return full_path; | 602 | return full_path; |
696 | } | 603 | } |
697 | 604 | ||
605 | static int | ||
606 | cifs_find_inode(struct inode *inode, void *opaque) | ||
607 | { | ||
608 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | ||
609 | |||
610 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) | ||
611 | return 0; | ||
612 | |||
613 | return 1; | ||
614 | } | ||
615 | |||
616 | static int | ||
617 | cifs_init_inode(struct inode *inode, void *opaque) | ||
618 | { | ||
619 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | ||
620 | |||
621 | CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | /* Given fattrs, get a corresponding inode */ | ||
626 | struct inode * | ||
627 | cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) | ||
628 | { | ||
629 | unsigned long hash; | ||
630 | struct inode *inode; | ||
631 | |||
632 | cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); | ||
633 | |||
634 | /* hash down to 32-bits on 32-bit arch */ | ||
635 | hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); | ||
636 | |||
637 | inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); | ||
638 | |||
639 | /* we have fattrs in hand, update the inode */ | ||
640 | if (inode) { | ||
641 | cifs_fattr_to_inode(inode, fattr); | ||
642 | if (sb->s_flags & MS_NOATIME) | ||
643 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | ||
644 | if (inode->i_state & I_NEW) { | ||
645 | inode->i_ino = hash; | ||
646 | unlock_new_inode(inode); | ||
647 | } | ||
648 | } | ||
649 | |||
650 | return inode; | ||
651 | } | ||
652 | |||
698 | /* gets root inode */ | 653 | /* gets root inode */ |
699 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | 654 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) |
700 | { | 655 | { |
701 | int xid; | 656 | int xid; |
702 | struct cifs_sb_info *cifs_sb; | 657 | struct cifs_sb_info *cifs_sb; |
703 | struct inode *inode; | 658 | struct inode *inode = NULL; |
704 | long rc; | 659 | long rc; |
705 | char *full_path; | 660 | char *full_path; |
706 | 661 | ||
707 | inode = iget_locked(sb, ino); | 662 | cifs_sb = CIFS_SB(sb); |
708 | if (!inode) | ||
709 | return ERR_PTR(-ENOMEM); | ||
710 | if (!(inode->i_state & I_NEW)) | ||
711 | return inode; | ||
712 | |||
713 | cifs_sb = CIFS_SB(inode->i_sb); | ||
714 | full_path = cifs_build_path_to_root(cifs_sb); | 663 | full_path = cifs_build_path_to_root(cifs_sb); |
715 | if (full_path == NULL) | 664 | if (full_path == NULL) |
716 | return ERR_PTR(-ENOMEM); | 665 | return ERR_PTR(-ENOMEM); |
717 | 666 | ||
718 | xid = GetXid(); | 667 | xid = GetXid(); |
719 | if (cifs_sb->tcon->unix_ext) | 668 | if (cifs_sb->tcon->unix_ext) |
720 | rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, | 669 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); |
721 | xid); | ||
722 | else | 670 | else |
723 | rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb, | 671 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
724 | xid, NULL); | 672 | xid, NULL); |
673 | |||
674 | if (!inode) | ||
675 | return ERR_PTR(-ENOMEM); | ||
676 | |||
725 | if (rc && cifs_sb->tcon->ipc) { | 677 | if (rc && cifs_sb->tcon->ipc) { |
726 | cFYI(1, ("ipc connection - fake read inode")); | 678 | cFYI(1, ("ipc connection - fake read inode")); |
727 | inode->i_mode |= S_IFDIR; | 679 | inode->i_mode |= S_IFDIR; |
@@ -737,7 +689,6 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
737 | return ERR_PTR(rc); | 689 | return ERR_PTR(rc); |
738 | } | 690 | } |
739 | 691 | ||
740 | unlock_new_inode(inode); | ||
741 | 692 | ||
742 | kfree(full_path); | 693 | kfree(full_path); |
743 | /* can not call macro FreeXid here since in a void func | 694 | /* can not call macro FreeXid here since in a void func |
@@ -1063,44 +1014,6 @@ out_reval: | |||
1063 | return rc; | 1014 | return rc; |
1064 | } | 1015 | } |
1065 | 1016 | ||
1066 | void posix_fill_in_inode(struct inode *tmp_inode, | ||
1067 | FILE_UNIX_BASIC_INFO *pData, int isNewInode) | ||
1068 | { | ||
1069 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
1070 | loff_t local_size; | ||
1071 | struct timespec local_mtime; | ||
1072 | |||
1073 | cifsInfo->time = jiffies; | ||
1074 | atomic_inc(&cifsInfo->inUse); | ||
1075 | |||
1076 | /* save mtime and size */ | ||
1077 | local_mtime = tmp_inode->i_mtime; | ||
1078 | local_size = tmp_inode->i_size; | ||
1079 | |||
1080 | cifs_unix_info_to_inode(tmp_inode, pData, 1); | ||
1081 | cifs_set_ops(tmp_inode, false); | ||
1082 | |||
1083 | if (!S_ISREG(tmp_inode->i_mode)) | ||
1084 | return; | ||
1085 | |||
1086 | /* | ||
1087 | * No sense invalidating pages for new inode | ||
1088 | * since we we have not started caching | ||
1089 | * readahead file data yet. | ||
1090 | */ | ||
1091 | if (isNewInode) | ||
1092 | return; | ||
1093 | |||
1094 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | ||
1095 | (local_size == tmp_inode->i_size)) { | ||
1096 | cFYI(1, ("inode exists but unchanged")); | ||
1097 | } else { | ||
1098 | /* file may have changed on server */ | ||
1099 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
1100 | invalidate_remote_inode(tmp_inode); | ||
1101 | } | ||
1102 | } | ||
1103 | |||
1104 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | 1017 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) |
1105 | { | 1018 | { |
1106 | int rc = 0, tmprc; | 1019 | int rc = 0, tmprc; |
@@ -1109,6 +1022,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1109 | struct cifsTconInfo *pTcon; | 1022 | struct cifsTconInfo *pTcon; |
1110 | char *full_path = NULL; | 1023 | char *full_path = NULL; |
1111 | struct inode *newinode = NULL; | 1024 | struct inode *newinode = NULL; |
1025 | struct cifs_fattr fattr; | ||
1112 | 1026 | ||
1113 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); | 1027 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); |
1114 | 1028 | ||
@@ -1148,7 +1062,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1148 | cFYI(1, ("posix mkdir returned 0x%x", rc)); | 1062 | cFYI(1, ("posix mkdir returned 0x%x", rc)); |
1149 | d_drop(direntry); | 1063 | d_drop(direntry); |
1150 | } else { | 1064 | } else { |
1151 | __u64 unique_id; | ||
1152 | if (pInfo->Type == cpu_to_le32(-1)) { | 1065 | if (pInfo->Type == cpu_to_le32(-1)) { |
1153 | /* no return info, go query for it */ | 1066 | /* no return info, go query for it */ |
1154 | kfree(pInfo); | 1067 | kfree(pInfo); |
@@ -1162,20 +1075,15 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1162 | else | 1075 | else |
1163 | direntry->d_op = &cifs_dentry_ops; | 1076 | direntry->d_op = &cifs_dentry_ops; |
1164 | 1077 | ||
1165 | unique_id = le64_to_cpu(pInfo->UniqueId); | 1078 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); |
1166 | newinode = cifs_new_inode(inode->i_sb, &unique_id); | 1079 | newinode = cifs_iget(inode->i_sb, &fattr); |
1167 | if (newinode == NULL) { | 1080 | if (!newinode) { |
1168 | kfree(pInfo); | 1081 | kfree(pInfo); |
1169 | goto mkdir_get_info; | 1082 | goto mkdir_get_info; |
1170 | } | 1083 | } |
1171 | 1084 | ||
1172 | newinode->i_nlink = 2; | ||
1173 | d_instantiate(direntry, newinode); | 1085 | d_instantiate(direntry, newinode); |
1174 | 1086 | ||
1175 | /* we already checked in POSIXCreate whether | ||
1176 | frame was long enough */ | ||
1177 | posix_fill_in_inode(direntry->d_inode, | ||
1178 | pInfo, 1 /* NewInode */); | ||
1179 | #ifdef CONFIG_CIFS_DEBUG2 | 1087 | #ifdef CONFIG_CIFS_DEBUG2 |
1180 | cFYI(1, ("instantiated dentry %p %s to inode %p", | 1088 | cFYI(1, ("instantiated dentry %p %s to inode %p", |
1181 | direntry, direntry->d_name.name, newinode)); | 1089 | direntry, direntry->d_name.name, newinode)); |
@@ -1238,10 +1146,10 @@ mkdir_get_info: | |||
1238 | args.uid = NO_CHANGE_64; | 1146 | args.uid = NO_CHANGE_64; |
1239 | args.gid = NO_CHANGE_64; | 1147 | args.gid = NO_CHANGE_64; |
1240 | } | 1148 | } |
1241 | CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, | 1149 | CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, |
1242 | cifs_sb->local_nls, | 1150 | cifs_sb->local_nls, |
1243 | cifs_sb->mnt_cifs_flags & | 1151 | cifs_sb->mnt_cifs_flags & |
1244 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1152 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1245 | } else { | 1153 | } else { |
1246 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && | 1154 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && |
1247 | (mode & S_IWUGO) == 0) { | 1155 | (mode & S_IWUGO) == 0) { |
@@ -1622,6 +1530,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
1622 | if (!err) { | 1530 | if (!err) { |
1623 | generic_fillattr(dentry->d_inode, stat); | 1531 | generic_fillattr(dentry->d_inode, stat); |
1624 | stat->blksize = CIFS_MAX_MSGSIZE; | 1532 | stat->blksize = CIFS_MAX_MSGSIZE; |
1533 | stat->ino = CIFS_I(dentry->d_inode)->uniqueid; | ||
1625 | } | 1534 | } |
1626 | return err; | 1535 | return err; |
1627 | } | 1536 | } |
@@ -1786,6 +1695,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1786 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1695 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1787 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 1696 | struct cifsTconInfo *pTcon = cifs_sb->tcon; |
1788 | struct cifs_unix_set_info_args *args = NULL; | 1697 | struct cifs_unix_set_info_args *args = NULL; |
1698 | struct cifsFileInfo *open_file; | ||
1789 | 1699 | ||
1790 | cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", | 1700 | cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", |
1791 | direntry->d_name.name, attrs->ia_valid)); | 1701 | direntry->d_name.name, attrs->ia_valid)); |
@@ -1872,10 +1782,18 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1872 | args->ctime = NO_CHANGE_64; | 1782 | args->ctime = NO_CHANGE_64; |
1873 | 1783 | ||
1874 | args->device = 0; | 1784 | args->device = 0; |
1875 | rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, args, | 1785 | open_file = find_writable_file(cifsInode); |
1876 | cifs_sb->local_nls, | 1786 | if (open_file) { |
1877 | cifs_sb->mnt_cifs_flags & | 1787 | u16 nfid = open_file->netfid; |
1878 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1788 | u32 npid = open_file->pid; |
1789 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); | ||
1790 | atomic_dec(&open_file->wrtPending); | ||
1791 | } else { | ||
1792 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, | ||
1793 | cifs_sb->local_nls, | ||
1794 | cifs_sb->mnt_cifs_flags & | ||
1795 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1796 | } | ||
1879 | 1797 | ||
1880 | if (!rc) | 1798 | if (!rc) |
1881 | rc = inode_setattr(inode, attrs); | 1799 | rc = inode_setattr(inode, attrs); |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 86d0055dc529..f823a4a208a7 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -63,374 +63,123 @@ static inline void dump_cifs_file_struct(struct file *file, char *label) | |||
63 | } | 63 | } |
64 | #endif /* DEBUG2 */ | 64 | #endif /* DEBUG2 */ |
65 | 65 | ||
66 | /* Returns 1 if new inode created, 2 if both dentry and inode were */ | 66 | /* |
67 | /* Might check in the future if inode number changed so we can rehash inode */ | 67 | * Find the dentry that matches "name". If there isn't one, create one. If it's |
68 | static int | 68 | * a negative dentry or the uniqueid changed, then drop it and recreate it. |
69 | construct_dentry(struct qstr *qstring, struct file *file, | 69 | */ |
70 | struct inode **ptmp_inode, struct dentry **pnew_dentry, | 70 | static struct dentry * |
71 | __u64 *inum) | 71 | cifs_readdir_lookup(struct dentry *parent, struct qstr *name, |
72 | struct cifs_fattr *fattr) | ||
72 | { | 73 | { |
73 | struct dentry *tmp_dentry = NULL; | 74 | struct dentry *dentry, *alias; |
74 | struct super_block *sb = file->f_path.dentry->d_sb; | 75 | struct inode *inode; |
75 | int rc = 0; | 76 | struct super_block *sb = parent->d_inode->i_sb; |
77 | |||
78 | cFYI(1, ("For %s", name->name)); | ||
79 | |||
80 | dentry = d_lookup(parent, name); | ||
81 | if (dentry) { | ||
82 | /* FIXME: check for inode number changes? */ | ||
83 | if (dentry->d_inode != NULL) | ||
84 | return dentry; | ||
85 | d_drop(dentry); | ||
86 | dput(dentry); | ||
87 | } | ||
76 | 88 | ||
77 | cFYI(1, ("For %s", qstring->name)); | 89 | dentry = d_alloc(parent, name); |
78 | 90 | if (dentry == NULL) | |
79 | qstring->hash = full_name_hash(qstring->name, qstring->len); | 91 | return NULL; |
80 | tmp_dentry = d_lookup(file->f_path.dentry, qstring); | ||
81 | if (tmp_dentry) { | ||
82 | /* BB: overwrite old name? i.e. tmp_dentry->d_name and | ||
83 | * tmp_dentry->d_name.len?? | ||
84 | */ | ||
85 | cFYI(0, ("existing dentry with inode 0x%p", | ||
86 | tmp_dentry->d_inode)); | ||
87 | *ptmp_inode = tmp_dentry->d_inode; | ||
88 | if (*ptmp_inode == NULL) { | ||
89 | *ptmp_inode = cifs_new_inode(sb, inum); | ||
90 | if (*ptmp_inode == NULL) | ||
91 | return rc; | ||
92 | rc = 1; | ||
93 | } | ||
94 | } else { | ||
95 | tmp_dentry = d_alloc(file->f_path.dentry, qstring); | ||
96 | if (tmp_dentry == NULL) { | ||
97 | cERROR(1, ("Failed allocating dentry")); | ||
98 | *ptmp_inode = NULL; | ||
99 | return rc; | ||
100 | } | ||
101 | 92 | ||
102 | if (CIFS_SB(sb)->tcon->nocase) | 93 | inode = cifs_iget(sb, fattr); |
103 | tmp_dentry->d_op = &cifs_ci_dentry_ops; | 94 | if (!inode) { |
104 | else | 95 | dput(dentry); |
105 | tmp_dentry->d_op = &cifs_dentry_ops; | 96 | return NULL; |
97 | } | ||
106 | 98 | ||
107 | *ptmp_inode = cifs_new_inode(sb, inum); | 99 | if (CIFS_SB(sb)->tcon->nocase) |
108 | if (*ptmp_inode == NULL) | 100 | dentry->d_op = &cifs_ci_dentry_ops; |
109 | return rc; | 101 | else |
110 | rc = 2; | 102 | dentry->d_op = &cifs_dentry_ops; |
103 | |||
104 | alias = d_materialise_unique(dentry, inode); | ||
105 | if (alias != NULL) { | ||
106 | dput(dentry); | ||
107 | if (IS_ERR(alias)) | ||
108 | return NULL; | ||
109 | dentry = alias; | ||
111 | } | 110 | } |
112 | 111 | ||
113 | tmp_dentry->d_time = jiffies; | 112 | return dentry; |
114 | *pnew_dentry = tmp_dentry; | ||
115 | return rc; | ||
116 | } | 113 | } |
117 | 114 | ||
118 | static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | 115 | static void |
119 | char *buf, unsigned int *pobject_type, int isNewInode) | 116 | cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) |
120 | { | 117 | { |
121 | loff_t local_size; | 118 | fattr->cf_uid = cifs_sb->mnt_uid; |
122 | struct timespec local_mtime; | 119 | fattr->cf_gid = cifs_sb->mnt_gid; |
123 | |||
124 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
125 | struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); | ||
126 | __u32 attr; | ||
127 | __u64 allocation_size; | ||
128 | __u64 end_of_file; | ||
129 | umode_t default_mode; | ||
130 | |||
131 | /* save mtime and size */ | ||
132 | local_mtime = tmp_inode->i_mtime; | ||
133 | local_size = tmp_inode->i_size; | ||
134 | |||
135 | if (new_buf_type) { | ||
136 | FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf; | ||
137 | |||
138 | attr = le32_to_cpu(pfindData->ExtFileAttributes); | ||
139 | allocation_size = le64_to_cpu(pfindData->AllocationSize); | ||
140 | end_of_file = le64_to_cpu(pfindData->EndOfFile); | ||
141 | tmp_inode->i_atime = | ||
142 | cifs_NTtimeToUnix(pfindData->LastAccessTime); | ||
143 | tmp_inode->i_mtime = | ||
144 | cifs_NTtimeToUnix(pfindData->LastWriteTime); | ||
145 | tmp_inode->i_ctime = | ||
146 | cifs_NTtimeToUnix(pfindData->ChangeTime); | ||
147 | } else { /* legacy, OS2 and DOS style */ | ||
148 | int offset = cifs_sb->tcon->ses->server->timeAdj; | ||
149 | FIND_FILE_STANDARD_INFO *pfindData = | ||
150 | (FIND_FILE_STANDARD_INFO *)buf; | ||
151 | |||
152 | tmp_inode->i_mtime = cnvrtDosUnixTm(pfindData->LastWriteDate, | ||
153 | pfindData->LastWriteTime, | ||
154 | offset); | ||
155 | tmp_inode->i_atime = cnvrtDosUnixTm(pfindData->LastAccessDate, | ||
156 | pfindData->LastAccessTime, | ||
157 | offset); | ||
158 | tmp_inode->i_ctime = cnvrtDosUnixTm(pfindData->LastWriteDate, | ||
159 | pfindData->LastWriteTime, | ||
160 | offset); | ||
161 | attr = le16_to_cpu(pfindData->Attributes); | ||
162 | allocation_size = le32_to_cpu(pfindData->AllocationSize); | ||
163 | end_of_file = le32_to_cpu(pfindData->DataSize); | ||
164 | } | ||
165 | 120 | ||
166 | /* Linux can not store file creation time unfortunately so ignore it */ | 121 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { |
167 | 122 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; | |
168 | cifsInfo->cifsAttrs = attr; | 123 | fattr->cf_dtype = DT_DIR; |
169 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 124 | } else { |
170 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 125 | fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; |
171 | /* get more accurate mode via ACL - so force inode refresh */ | 126 | fattr->cf_dtype = DT_REG; |
172 | cifsInfo->time = 0; | ||
173 | } else | ||
174 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
175 | cifsInfo->time = jiffies; | ||
176 | |||
177 | /* treat dos attribute of read-only as read-only mode bit e.g. 555? */ | ||
178 | /* 2767 perms - indicate mandatory locking */ | ||
179 | /* BB fill in uid and gid here? with help from winbind? | ||
180 | or retrieve from NTFS stream extended attribute */ | ||
181 | if (atomic_read(&cifsInfo->inUse) == 0) { | ||
182 | tmp_inode->i_uid = cifs_sb->mnt_uid; | ||
183 | tmp_inode->i_gid = cifs_sb->mnt_gid; | ||
184 | } | ||
185 | |||
186 | if (attr & ATTR_DIRECTORY) | ||
187 | default_mode = cifs_sb->mnt_dir_mode; | ||
188 | else | ||
189 | default_mode = cifs_sb->mnt_file_mode; | ||
190 | |||
191 | /* set initial permissions */ | ||
192 | if ((atomic_read(&cifsInfo->inUse) == 0) || | ||
193 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) | ||
194 | tmp_inode->i_mode = default_mode; | ||
195 | else { | ||
196 | /* just reenable write bits if !ATTR_READONLY */ | ||
197 | if ((tmp_inode->i_mode & S_IWUGO) == 0 && | ||
198 | (attr & ATTR_READONLY) == 0) | ||
199 | tmp_inode->i_mode |= (S_IWUGO & default_mode); | ||
200 | |||
201 | tmp_inode->i_mode &= ~S_IFMT; | ||
202 | } | 127 | } |
203 | 128 | ||
204 | /* clear write bits if ATTR_READONLY is set */ | 129 | if (fattr->cf_cifsattrs & ATTR_READONLY) |
205 | if (attr & ATTR_READONLY) | 130 | fattr->cf_mode &= ~S_IWUGO; |
206 | tmp_inode->i_mode &= ~S_IWUGO; | ||
207 | 131 | ||
208 | /* set inode type */ | 132 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL && |
209 | if ((attr & ATTR_SYSTEM) && | 133 | fattr->cf_cifsattrs & ATTR_SYSTEM) { |
210 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { | 134 | if (fattr->cf_eof == 0) { |
211 | if (end_of_file == 0) { | 135 | fattr->cf_mode &= ~S_IFMT; |
212 | tmp_inode->i_mode |= S_IFIFO; | 136 | fattr->cf_mode |= S_IFIFO; |
213 | *pobject_type = DT_FIFO; | 137 | fattr->cf_dtype = DT_FIFO; |
214 | } else { | 138 | } else { |
215 | /* | 139 | /* |
216 | * trying to get the type can be slow, so just call | 140 | * trying to get the type and mode via SFU can be slow, |
217 | * this a regular file for now, and mark for reval | 141 | * so just call those regular files for now, and mark |
142 | * for reval | ||
218 | */ | 143 | */ |
219 | tmp_inode->i_mode |= S_IFREG; | 144 | fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; |
220 | *pobject_type = DT_REG; | ||
221 | cifsInfo->time = 0; | ||
222 | } | ||
223 | } else { | ||
224 | if (attr & ATTR_DIRECTORY) { | ||
225 | tmp_inode->i_mode |= S_IFDIR; | ||
226 | *pobject_type = DT_DIR; | ||
227 | } else { | ||
228 | tmp_inode->i_mode |= S_IFREG; | ||
229 | *pobject_type = DT_REG; | ||
230 | } | 145 | } |
231 | } | 146 | } |
147 | } | ||
232 | 148 | ||
233 | /* can not fill in nlink here as in qpathinfo version and Unx search */ | 149 | void |
234 | if (atomic_read(&cifsInfo->inUse) == 0) | 150 | cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, |
235 | atomic_set(&cifsInfo->inUse, 1); | 151 | struct cifs_sb_info *cifs_sb) |
236 | 152 | { | |
237 | cifsInfo->server_eof = end_of_file; | 153 | memset(fattr, 0, sizeof(*fattr)); |
238 | spin_lock(&tmp_inode->i_lock); | 154 | fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes); |
239 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | 155 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); |
240 | /* can not safely change the file size here if the | 156 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); |
241 | client is writing to it due to potential races */ | 157 | fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); |
242 | i_size_write(tmp_inode, end_of_file); | 158 | fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); |
243 | 159 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); | |
244 | /* 512 bytes (2**9) is the fake blocksize that must be used */ | 160 | |
245 | /* for this calculation, even though the reported blocksize is larger */ | 161 | cifs_fill_common_info(fattr, cifs_sb); |
246 | tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9; | ||
247 | } | ||
248 | spin_unlock(&tmp_inode->i_lock); | ||
249 | |||
250 | if (allocation_size < end_of_file) | ||
251 | cFYI(1, ("May be sparse file, allocation less than file size")); | ||
252 | cFYI(1, ("File Size %ld and blocks %llu", | ||
253 | (unsigned long)tmp_inode->i_size, | ||
254 | (unsigned long long)tmp_inode->i_blocks)); | ||
255 | if (S_ISREG(tmp_inode->i_mode)) { | ||
256 | cFYI(1, ("File inode")); | ||
257 | tmp_inode->i_op = &cifs_file_inode_ops; | ||
258 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { | ||
259 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
260 | tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; | ||
261 | else | ||
262 | tmp_inode->i_fop = &cifs_file_direct_ops; | ||
263 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
264 | tmp_inode->i_fop = &cifs_file_nobrl_ops; | ||
265 | else | ||
266 | tmp_inode->i_fop = &cifs_file_ops; | ||
267 | |||
268 | if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && | ||
269 | (cifs_sb->tcon->ses->server->maxBuf < | ||
270 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) | ||
271 | tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | ||
272 | else | ||
273 | tmp_inode->i_data.a_ops = &cifs_addr_ops; | ||
274 | |||
275 | if (isNewInode) | ||
276 | return; /* No sense invalidating pages for new inode | ||
277 | since have not started caching readahead file | ||
278 | data yet */ | ||
279 | |||
280 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | ||
281 | (local_size == tmp_inode->i_size)) { | ||
282 | cFYI(1, ("inode exists but unchanged")); | ||
283 | } else { | ||
284 | /* file may have changed on server */ | ||
285 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
286 | invalidate_remote_inode(tmp_inode); | ||
287 | } | ||
288 | } else if (S_ISDIR(tmp_inode->i_mode)) { | ||
289 | cFYI(1, ("Directory inode")); | ||
290 | tmp_inode->i_op = &cifs_dir_inode_ops; | ||
291 | tmp_inode->i_fop = &cifs_dir_ops; | ||
292 | } else if (S_ISLNK(tmp_inode->i_mode)) { | ||
293 | cFYI(1, ("Symbolic Link inode")); | ||
294 | tmp_inode->i_op = &cifs_symlink_inode_ops; | ||
295 | } else { | ||
296 | cFYI(1, ("Init special inode")); | ||
297 | init_special_inode(tmp_inode, tmp_inode->i_mode, | ||
298 | tmp_inode->i_rdev); | ||
299 | } | ||
300 | } | 162 | } |
301 | 163 | ||
302 | static void unix_fill_in_inode(struct inode *tmp_inode, | 164 | void |
303 | FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode) | 165 | cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info, |
166 | struct cifs_sb_info *cifs_sb) | ||
304 | { | 167 | { |
305 | loff_t local_size; | 168 | int offset = cifs_sb->tcon->ses->server->timeAdj; |
306 | struct timespec local_mtime; | ||
307 | |||
308 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
309 | struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); | ||
310 | |||
311 | __u32 type = le32_to_cpu(pfindData->Type); | ||
312 | __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes); | ||
313 | __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile); | ||
314 | cifsInfo->time = jiffies; | ||
315 | atomic_inc(&cifsInfo->inUse); | ||
316 | |||
317 | /* save mtime and size */ | ||
318 | local_mtime = tmp_inode->i_mtime; | ||
319 | local_size = tmp_inode->i_size; | ||
320 | |||
321 | tmp_inode->i_atime = | ||
322 | cifs_NTtimeToUnix(pfindData->LastAccessTime); | ||
323 | tmp_inode->i_mtime = | ||
324 | cifs_NTtimeToUnix(pfindData->LastModificationTime); | ||
325 | tmp_inode->i_ctime = | ||
326 | cifs_NTtimeToUnix(pfindData->LastStatusChange); | ||
327 | |||
328 | tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions); | ||
329 | /* since we set the inode type below we need to mask off type | ||
330 | to avoid strange results if bits above were corrupt */ | ||
331 | tmp_inode->i_mode &= ~S_IFMT; | ||
332 | if (type == UNIX_FILE) { | ||
333 | *pobject_type = DT_REG; | ||
334 | tmp_inode->i_mode |= S_IFREG; | ||
335 | } else if (type == UNIX_SYMLINK) { | ||
336 | *pobject_type = DT_LNK; | ||
337 | tmp_inode->i_mode |= S_IFLNK; | ||
338 | } else if (type == UNIX_DIR) { | ||
339 | *pobject_type = DT_DIR; | ||
340 | tmp_inode->i_mode |= S_IFDIR; | ||
341 | } else if (type == UNIX_CHARDEV) { | ||
342 | *pobject_type = DT_CHR; | ||
343 | tmp_inode->i_mode |= S_IFCHR; | ||
344 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), | ||
345 | le64_to_cpu(pfindData->DevMinor) & MINORMASK); | ||
346 | } else if (type == UNIX_BLOCKDEV) { | ||
347 | *pobject_type = DT_BLK; | ||
348 | tmp_inode->i_mode |= S_IFBLK; | ||
349 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), | ||
350 | le64_to_cpu(pfindData->DevMinor) & MINORMASK); | ||
351 | } else if (type == UNIX_FIFO) { | ||
352 | *pobject_type = DT_FIFO; | ||
353 | tmp_inode->i_mode |= S_IFIFO; | ||
354 | } else if (type == UNIX_SOCKET) { | ||
355 | *pobject_type = DT_SOCK; | ||
356 | tmp_inode->i_mode |= S_IFSOCK; | ||
357 | } else { | ||
358 | /* safest to just call it a file */ | ||
359 | *pobject_type = DT_REG; | ||
360 | tmp_inode->i_mode |= S_IFREG; | ||
361 | cFYI(1, ("unknown inode type %d", type)); | ||
362 | } | ||
363 | 169 | ||
364 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) | 170 | memset(fattr, 0, sizeof(*fattr)); |
365 | tmp_inode->i_uid = cifs_sb->mnt_uid; | 171 | fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate, |
366 | else | 172 | info->LastAccessTime, offset); |
367 | tmp_inode->i_uid = le64_to_cpu(pfindData->Uid); | 173 | fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate, |
368 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) | 174 | info->LastWriteTime, offset); |
369 | tmp_inode->i_gid = cifs_sb->mnt_gid; | 175 | fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate, |
370 | else | 176 | info->LastWriteTime, offset); |
371 | tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); | ||
372 | tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); | ||
373 | |||
374 | cifsInfo->server_eof = end_of_file; | ||
375 | spin_lock(&tmp_inode->i_lock); | ||
376 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
377 | /* can not safely change the file size here if the | ||
378 | client is writing to it due to potential races */ | ||
379 | i_size_write(tmp_inode, end_of_file); | ||
380 | |||
381 | /* 512 bytes (2**9) is the fake blocksize that must be used */ | ||
382 | /* for this calculation, not the real blocksize */ | ||
383 | tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
384 | } | ||
385 | spin_unlock(&tmp_inode->i_lock); | ||
386 | 177 | ||
387 | if (S_ISREG(tmp_inode->i_mode)) { | 178 | fattr->cf_cifsattrs = le16_to_cpu(info->Attributes); |
388 | cFYI(1, ("File inode")); | 179 | fattr->cf_bytes = le32_to_cpu(info->AllocationSize); |
389 | tmp_inode->i_op = &cifs_file_inode_ops; | 180 | fattr->cf_eof = le32_to_cpu(info->DataSize); |
390 | 181 | ||
391 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { | 182 | cifs_fill_common_info(fattr, cifs_sb); |
392 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
393 | tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; | ||
394 | else | ||
395 | tmp_inode->i_fop = &cifs_file_direct_ops; | ||
396 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
397 | tmp_inode->i_fop = &cifs_file_nobrl_ops; | ||
398 | else | ||
399 | tmp_inode->i_fop = &cifs_file_ops; | ||
400 | |||
401 | if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && | ||
402 | (cifs_sb->tcon->ses->server->maxBuf < | ||
403 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) | ||
404 | tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | ||
405 | else | ||
406 | tmp_inode->i_data.a_ops = &cifs_addr_ops; | ||
407 | |||
408 | if (isNewInode) | ||
409 | return; /* No sense invalidating pages for new inode | ||
410 | since we have not started caching readahead | ||
411 | file data for it yet */ | ||
412 | |||
413 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | ||
414 | (local_size == tmp_inode->i_size)) { | ||
415 | cFYI(1, ("inode exists but unchanged")); | ||
416 | } else { | ||
417 | /* file may have changed on server */ | ||
418 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
419 | invalidate_remote_inode(tmp_inode); | ||
420 | } | ||
421 | } else if (S_ISDIR(tmp_inode->i_mode)) { | ||
422 | cFYI(1, ("Directory inode")); | ||
423 | tmp_inode->i_op = &cifs_dir_inode_ops; | ||
424 | tmp_inode->i_fop = &cifs_dir_ops; | ||
425 | } else if (S_ISLNK(tmp_inode->i_mode)) { | ||
426 | cFYI(1, ("Symbolic Link inode")); | ||
427 | tmp_inode->i_op = &cifs_symlink_inode_ops; | ||
428 | /* tmp_inode->i_fop = *//* do not need to set to anything */ | ||
429 | } else { | ||
430 | cFYI(1, ("Special inode")); | ||
431 | init_special_inode(tmp_inode, tmp_inode->i_mode, | ||
432 | tmp_inode->i_rdev); | ||
433 | } | ||
434 | } | 183 | } |
435 | 184 | ||
436 | /* BB eventually need to add the following helper function to | 185 | /* BB eventually need to add the following helper function to |
@@ -872,7 +621,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, | |||
872 | len = strnlen(filename, PATH_MAX); | 621 | len = strnlen(filename, PATH_MAX); |
873 | } | 622 | } |
874 | 623 | ||
875 | *pinum = le64_to_cpu(pFindData->UniqueId); | 624 | *pinum = le64_to_cpu(pFindData->basic.UniqueId); |
876 | } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { | 625 | } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { |
877 | FILE_DIRECTORY_INFO *pFindData = | 626 | FILE_DIRECTORY_INFO *pFindData = |
878 | (FILE_DIRECTORY_INFO *)current_entry; | 627 | (FILE_DIRECTORY_INFO *)current_entry; |
@@ -932,11 +681,12 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, | |||
932 | int rc = 0; | 681 | int rc = 0; |
933 | struct qstr qstring; | 682 | struct qstr qstring; |
934 | struct cifsFileInfo *pCifsF; | 683 | struct cifsFileInfo *pCifsF; |
935 | unsigned int obj_type; | 684 | u64 inum; |
936 | __u64 inum; | 685 | ino_t ino; |
686 | struct super_block *sb; | ||
937 | struct cifs_sb_info *cifs_sb; | 687 | struct cifs_sb_info *cifs_sb; |
938 | struct inode *tmp_inode; | ||
939 | struct dentry *tmp_dentry; | 688 | struct dentry *tmp_dentry; |
689 | struct cifs_fattr fattr; | ||
940 | 690 | ||
941 | /* get filename and len into qstring */ | 691 | /* get filename and len into qstring */ |
942 | /* get dentry */ | 692 | /* get dentry */ |
@@ -954,60 +704,53 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, | |||
954 | if (rc != 0) | 704 | if (rc != 0) |
955 | return 0; | 705 | return 0; |
956 | 706 | ||
957 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 707 | sb = file->f_path.dentry->d_sb; |
708 | cifs_sb = CIFS_SB(sb); | ||
958 | 709 | ||
959 | qstring.name = scratch_buf; | 710 | qstring.name = scratch_buf; |
960 | rc = cifs_get_name_from_search_buf(&qstring, pfindEntry, | 711 | rc = cifs_get_name_from_search_buf(&qstring, pfindEntry, |
961 | pCifsF->srch_inf.info_level, | 712 | pCifsF->srch_inf.info_level, |
962 | pCifsF->srch_inf.unicode, cifs_sb, | 713 | pCifsF->srch_inf.unicode, cifs_sb, |
963 | max_len, | 714 | max_len, &inum /* returned */); |
964 | &inum /* returned */); | ||
965 | 715 | ||
966 | if (rc) | 716 | if (rc) |
967 | return rc; | 717 | return rc; |
968 | 718 | ||
969 | /* only these two infolevels return valid inode numbers */ | ||
970 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX || | ||
971 | pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO) | ||
972 | rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, | ||
973 | &inum); | ||
974 | else | ||
975 | rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, | ||
976 | NULL); | ||
977 | |||
978 | if ((tmp_inode == NULL) || (tmp_dentry == NULL)) | ||
979 | return -ENOMEM; | ||
980 | |||
981 | /* we pass in rc below, indicating whether it is a new inode, | ||
982 | so we can figure out whether to invalidate the inode cached | ||
983 | data if the file has changed */ | ||
984 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) | 719 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) |
985 | unix_fill_in_inode(tmp_inode, | 720 | cifs_unix_basic_to_fattr(&fattr, |
986 | (FILE_UNIX_INFO *)pfindEntry, | 721 | &((FILE_UNIX_INFO *) pfindEntry)->basic, |
987 | &obj_type, rc); | 722 | cifs_sb); |
988 | else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) | 723 | else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) |
989 | fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */, | 724 | cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *) |
990 | pfindEntry, &obj_type, rc); | 725 | pfindEntry, cifs_sb); |
991 | else | 726 | else |
992 | fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc); | 727 | cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *) |
728 | pfindEntry, cifs_sb); | ||
993 | 729 | ||
994 | if (rc) /* new inode - needs to be tied to dentry */ { | 730 | /* FIXME: make _to_fattr functions fill this out */ |
995 | d_instantiate(tmp_dentry, tmp_inode); | 731 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO) |
996 | if (rc == 2) | 732 | fattr.cf_uniqueid = inum; |
997 | d_rehash(tmp_dentry); | 733 | else |
998 | } | 734 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
999 | 735 | ||
736 | ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); | ||
737 | tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr); | ||
1000 | 738 | ||
1001 | rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, | 739 | rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, |
1002 | tmp_inode->i_ino, obj_type); | 740 | ino, fattr.cf_dtype); |
741 | |||
742 | /* | ||
743 | * we can not return filldir errors to the caller since they are | ||
744 | * "normal" when the stat blocksize is too small - we return remapped | ||
745 | * error instead | ||
746 | * | ||
747 | * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above | ||
748 | * case already. Why should we be clobbering other errors from it? | ||
749 | */ | ||
1003 | if (rc) { | 750 | if (rc) { |
1004 | cFYI(1, ("filldir rc = %d", rc)); | 751 | cFYI(1, ("filldir rc = %d", rc)); |
1005 | /* we can not return filldir errors to the caller | ||
1006 | since they are "normal" when the stat blocksize | ||
1007 | is too small - we return remapped error instead */ | ||
1008 | rc = -EOVERFLOW; | 752 | rc = -EOVERFLOW; |
1009 | } | 753 | } |
1010 | |||
1011 | dput(tmp_dentry); | 754 | dput(tmp_dentry); |
1012 | return rc; | 755 | return rc; |
1013 | } | 756 | } |
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index e73e2429a1b1..2ce29831feb6 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h | |||
@@ -99,7 +99,6 @@ enum rfkill_user_states { | |||
99 | #undef RFKILL_STATE_UNBLOCKED | 99 | #undef RFKILL_STATE_UNBLOCKED |
100 | #undef RFKILL_STATE_HARD_BLOCKED | 100 | #undef RFKILL_STATE_HARD_BLOCKED |
101 | 101 | ||
102 | #include <linux/types.h> | ||
103 | #include <linux/kernel.h> | 102 | #include <linux/kernel.h> |
104 | #include <linux/list.h> | 103 | #include <linux/list.h> |
105 | #include <linux/mutex.h> | 104 | #include <linux/mutex.h> |
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index 252b245cfcf4..4be57ab03478 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h | |||
@@ -132,6 +132,11 @@ do { \ | |||
132 | #endif /*__raw_spin_is_contended*/ | 132 | #endif /*__raw_spin_is_contended*/ |
133 | #endif | 133 | #endif |
134 | 134 | ||
135 | /* The lock does not imply full memory barrier. */ | ||
136 | #ifndef ARCH_HAS_SMP_MB_AFTER_LOCK | ||
137 | static inline void smp_mb__after_lock(void) { smp_mb(); } | ||
138 | #endif | ||
139 | |||
135 | /** | 140 | /** |
136 | * spin_unlock_wait - wait until the spinlock gets unlocked | 141 | * spin_unlock_wait - wait until the spinlock gets unlocked |
137 | * @lock: the spinlock in question. | 142 | * @lock: the spinlock in question. |
diff --git a/include/net/sock.h b/include/net/sock.h index 352f06bbd7a9..2c0da9239b95 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -54,6 +54,7 @@ | |||
54 | 54 | ||
55 | #include <linux/filter.h> | 55 | #include <linux/filter.h> |
56 | #include <linux/rculist_nulls.h> | 56 | #include <linux/rculist_nulls.h> |
57 | #include <linux/poll.h> | ||
57 | 58 | ||
58 | #include <asm/atomic.h> | 59 | #include <asm/atomic.h> |
59 | #include <net/dst.h> | 60 | #include <net/dst.h> |
@@ -1241,6 +1242,74 @@ static inline int sk_has_allocations(const struct sock *sk) | |||
1241 | return sk_wmem_alloc_get(sk) || sk_rmem_alloc_get(sk); | 1242 | return sk_wmem_alloc_get(sk) || sk_rmem_alloc_get(sk); |
1242 | } | 1243 | } |
1243 | 1244 | ||
1245 | /** | ||
1246 | * sk_has_sleeper - check if there are any waiting processes | ||
1247 | * @sk: socket | ||
1248 | * | ||
1249 | * Returns true if socket has waiting processes | ||
1250 | * | ||
1251 | * The purpose of the sk_has_sleeper and sock_poll_wait is to wrap the memory | ||
1252 | * barrier call. They were added due to the race found within the tcp code. | ||
1253 | * | ||
1254 | * Consider following tcp code paths: | ||
1255 | * | ||
1256 | * CPU1 CPU2 | ||
1257 | * | ||
1258 | * sys_select receive packet | ||
1259 | * ... ... | ||
1260 | * __add_wait_queue update tp->rcv_nxt | ||
1261 | * ... ... | ||
1262 | * tp->rcv_nxt check sock_def_readable | ||
1263 | * ... { | ||
1264 | * schedule ... | ||
1265 | * if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | ||
1266 | * wake_up_interruptible(sk->sk_sleep) | ||
1267 | * ... | ||
1268 | * } | ||
1269 | * | ||
1270 | * The race for tcp fires when the __add_wait_queue changes done by CPU1 stay | ||
1271 | * in its cache, and so does the tp->rcv_nxt update on CPU2 side. The CPU1 | ||
1272 | * could then endup calling schedule and sleep forever if there are no more | ||
1273 | * data on the socket. | ||
1274 | * | ||
1275 | * The sk_has_sleeper is always called right after a call to read_lock, so we | ||
1276 | * can use smp_mb__after_lock barrier. | ||
1277 | */ | ||
1278 | static inline int sk_has_sleeper(struct sock *sk) | ||
1279 | { | ||
1280 | /* | ||
1281 | * We need to be sure we are in sync with the | ||
1282 | * add_wait_queue modifications to the wait queue. | ||
1283 | * | ||
1284 | * This memory barrier is paired in the sock_poll_wait. | ||
1285 | */ | ||
1286 | smp_mb__after_lock(); | ||
1287 | return sk->sk_sleep && waitqueue_active(sk->sk_sleep); | ||
1288 | } | ||
1289 | |||
1290 | /** | ||
1291 | * sock_poll_wait - place memory barrier behind the poll_wait call. | ||
1292 | * @filp: file | ||
1293 | * @wait_address: socket wait queue | ||
1294 | * @p: poll_table | ||
1295 | * | ||
1296 | * See the comments in the sk_has_sleeper function. | ||
1297 | */ | ||
1298 | static inline void sock_poll_wait(struct file *filp, | ||
1299 | wait_queue_head_t *wait_address, poll_table *p) | ||
1300 | { | ||
1301 | if (p && wait_address) { | ||
1302 | poll_wait(filp, wait_address, p); | ||
1303 | /* | ||
1304 | * We need to be sure we are in sync with the | ||
1305 | * socket flags modification. | ||
1306 | * | ||
1307 | * This memory barrier is paired in the sk_has_sleeper. | ||
1308 | */ | ||
1309 | smp_mb(); | ||
1310 | } | ||
1311 | } | ||
1312 | |||
1244 | /* | 1313 | /* |
1245 | * Queue a received datagram if it will fit. Stream and sequenced | 1314 | * Queue a received datagram if it will fit. Stream and sequenced |
1246 | * protocols can't normally use this as they need to fit buffers in | 1315 | * protocols can't normally use this as they need to fit buffers in |
diff --git a/net/atm/common.c b/net/atm/common.c index c1c97936192c..8c4d843eb17f 100644 --- a/net/atm/common.c +++ b/net/atm/common.c | |||
@@ -92,7 +92,7 @@ static void vcc_sock_destruct(struct sock *sk) | |||
92 | static void vcc_def_wakeup(struct sock *sk) | 92 | static void vcc_def_wakeup(struct sock *sk) |
93 | { | 93 | { |
94 | read_lock(&sk->sk_callback_lock); | 94 | read_lock(&sk->sk_callback_lock); |
95 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 95 | if (sk_has_sleeper(sk)) |
96 | wake_up(sk->sk_sleep); | 96 | wake_up(sk->sk_sleep); |
97 | read_unlock(&sk->sk_callback_lock); | 97 | read_unlock(&sk->sk_callback_lock); |
98 | } | 98 | } |
@@ -110,7 +110,7 @@ static void vcc_write_space(struct sock *sk) | |||
110 | read_lock(&sk->sk_callback_lock); | 110 | read_lock(&sk->sk_callback_lock); |
111 | 111 | ||
112 | if (vcc_writable(sk)) { | 112 | if (vcc_writable(sk)) { |
113 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 113 | if (sk_has_sleeper(sk)) |
114 | wake_up_interruptible(sk->sk_sleep); | 114 | wake_up_interruptible(sk->sk_sleep); |
115 | 115 | ||
116 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 116 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
@@ -594,7 +594,7 @@ unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
594 | struct atm_vcc *vcc; | 594 | struct atm_vcc *vcc; |
595 | unsigned int mask; | 595 | unsigned int mask; |
596 | 596 | ||
597 | poll_wait(file, sk->sk_sleep, wait); | 597 | sock_poll_wait(file, sk->sk_sleep, wait); |
598 | mask = 0; | 598 | mask = 0; |
599 | 599 | ||
600 | vcc = ATM_SD(sock); | 600 | vcc = ATM_SD(sock); |
diff --git a/net/core/datagram.c b/net/core/datagram.c index 58abee1f1df1..b0fe69211eef 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -712,7 +712,7 @@ unsigned int datagram_poll(struct file *file, struct socket *sock, | |||
712 | struct sock *sk = sock->sk; | 712 | struct sock *sk = sock->sk; |
713 | unsigned int mask; | 713 | unsigned int mask; |
714 | 714 | ||
715 | poll_wait(file, sk->sk_sleep, wait); | 715 | sock_poll_wait(file, sk->sk_sleep, wait); |
716 | mask = 0; | 716 | mask = 0; |
717 | 717 | ||
718 | /* exceptional events? */ | 718 | /* exceptional events? */ |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 9675f312830d..df30feb2fc72 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -740,7 +740,7 @@ int netpoll_setup(struct netpoll *np) | |||
740 | np->name); | 740 | np->name); |
741 | break; | 741 | break; |
742 | } | 742 | } |
743 | cond_resched(); | 743 | msleep(1); |
744 | } | 744 | } |
745 | 745 | ||
746 | /* If carrier appears to come up instantly, we don't | 746 | /* If carrier appears to come up instantly, we don't |
diff --git a/net/core/sock.c b/net/core/sock.c index b0ba569bc973..6354863b1c68 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1715,7 +1715,7 @@ EXPORT_SYMBOL(sock_no_sendpage); | |||
1715 | static void sock_def_wakeup(struct sock *sk) | 1715 | static void sock_def_wakeup(struct sock *sk) |
1716 | { | 1716 | { |
1717 | read_lock(&sk->sk_callback_lock); | 1717 | read_lock(&sk->sk_callback_lock); |
1718 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1718 | if (sk_has_sleeper(sk)) |
1719 | wake_up_interruptible_all(sk->sk_sleep); | 1719 | wake_up_interruptible_all(sk->sk_sleep); |
1720 | read_unlock(&sk->sk_callback_lock); | 1720 | read_unlock(&sk->sk_callback_lock); |
1721 | } | 1721 | } |
@@ -1723,7 +1723,7 @@ static void sock_def_wakeup(struct sock *sk) | |||
1723 | static void sock_def_error_report(struct sock *sk) | 1723 | static void sock_def_error_report(struct sock *sk) |
1724 | { | 1724 | { |
1725 | read_lock(&sk->sk_callback_lock); | 1725 | read_lock(&sk->sk_callback_lock); |
1726 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1726 | if (sk_has_sleeper(sk)) |
1727 | wake_up_interruptible_poll(sk->sk_sleep, POLLERR); | 1727 | wake_up_interruptible_poll(sk->sk_sleep, POLLERR); |
1728 | sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); | 1728 | sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); |
1729 | read_unlock(&sk->sk_callback_lock); | 1729 | read_unlock(&sk->sk_callback_lock); |
@@ -1732,7 +1732,7 @@ static void sock_def_error_report(struct sock *sk) | |||
1732 | static void sock_def_readable(struct sock *sk, int len) | 1732 | static void sock_def_readable(struct sock *sk, int len) |
1733 | { | 1733 | { |
1734 | read_lock(&sk->sk_callback_lock); | 1734 | read_lock(&sk->sk_callback_lock); |
1735 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1735 | if (sk_has_sleeper(sk)) |
1736 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN | | 1736 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN | |
1737 | POLLRDNORM | POLLRDBAND); | 1737 | POLLRDNORM | POLLRDBAND); |
1738 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); | 1738 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); |
@@ -1747,7 +1747,7 @@ static void sock_def_write_space(struct sock *sk) | |||
1747 | * progress. --DaveM | 1747 | * progress. --DaveM |
1748 | */ | 1748 | */ |
1749 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { | 1749 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { |
1750 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1750 | if (sk_has_sleeper(sk)) |
1751 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT | | 1751 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT | |
1752 | POLLWRNORM | POLLWRBAND); | 1752 | POLLWRNORM | POLLWRBAND); |
1753 | 1753 | ||
diff --git a/net/dccp/output.c b/net/dccp/output.c index c0e88c16d088..c96119fda688 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -196,7 +196,7 @@ void dccp_write_space(struct sock *sk) | |||
196 | { | 196 | { |
197 | read_lock(&sk->sk_callback_lock); | 197 | read_lock(&sk->sk_callback_lock); |
198 | 198 | ||
199 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 199 | if (sk_has_sleeper(sk)) |
200 | wake_up_interruptible(sk->sk_sleep); | 200 | wake_up_interruptible(sk->sk_sleep); |
201 | /* Should agree with poll, otherwise some programs break */ | 201 | /* Should agree with poll, otherwise some programs break */ |
202 | if (sock_writeable(sk)) | 202 | if (sock_writeable(sk)) |
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 314a1b5c033c..94ca8eaace7d 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -311,7 +311,7 @@ unsigned int dccp_poll(struct file *file, struct socket *sock, | |||
311 | unsigned int mask; | 311 | unsigned int mask; |
312 | struct sock *sk = sock->sk; | 312 | struct sock *sk = sock->sk; |
313 | 313 | ||
314 | poll_wait(file, sk->sk_sleep, wait); | 314 | sock_poll_wait(file, sk->sk_sleep, wait); |
315 | if (sk->sk_state == DCCP_LISTEN) | 315 | if (sk->sk_state == DCCP_LISTEN) |
316 | return inet_csk_listen_poll(sk); | 316 | return inet_csk_listen_poll(sk); |
317 | 317 | ||
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 00a54b246dfe..63c2fa7b68c4 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -316,8 +316,8 @@ static inline void check_tnode(const struct tnode *tn) | |||
316 | 316 | ||
317 | static const int halve_threshold = 25; | 317 | static const int halve_threshold = 25; |
318 | static const int inflate_threshold = 50; | 318 | static const int inflate_threshold = 50; |
319 | static const int halve_threshold_root = 8; | 319 | static const int halve_threshold_root = 15; |
320 | static const int inflate_threshold_root = 15; | 320 | static const int inflate_threshold_root = 25; |
321 | 321 | ||
322 | 322 | ||
323 | static void __alias_free_mem(struct rcu_head *head) | 323 | static void __alias_free_mem(struct rcu_head *head) |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 7870a535dac6..91145244ea63 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -339,7 +339,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
339 | struct sock *sk = sock->sk; | 339 | struct sock *sk = sock->sk; |
340 | struct tcp_sock *tp = tcp_sk(sk); | 340 | struct tcp_sock *tp = tcp_sk(sk); |
341 | 341 | ||
342 | poll_wait(file, sk->sk_sleep, wait); | 342 | sock_poll_wait(file, sk->sk_sleep, wait); |
343 | if (sk->sk_state == TCP_LISTEN) | 343 | if (sk->sk_state == TCP_LISTEN) |
344 | return inet_csk_listen_poll(sk); | 344 | return inet_csk_listen_poll(sk); |
345 | 345 | ||
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 6be5f92d1094..49c15b48408e 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -306,7 +306,7 @@ static inline int iucv_below_msglim(struct sock *sk) | |||
306 | static void iucv_sock_wake_msglim(struct sock *sk) | 306 | static void iucv_sock_wake_msglim(struct sock *sk) |
307 | { | 307 | { |
308 | read_lock(&sk->sk_callback_lock); | 308 | read_lock(&sk->sk_callback_lock); |
309 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 309 | if (sk_has_sleeper(sk)) |
310 | wake_up_interruptible_all(sk->sk_sleep); | 310 | wake_up_interruptible_all(sk->sk_sleep); |
311 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 311 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
312 | read_unlock(&sk->sk_callback_lock); | 312 | read_unlock(&sk->sk_callback_lock); |
@@ -1256,7 +1256,7 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock, | |||
1256 | struct sock *sk = sock->sk; | 1256 | struct sock *sk = sock->sk; |
1257 | unsigned int mask = 0; | 1257 | unsigned int mask = 0; |
1258 | 1258 | ||
1259 | poll_wait(file, sk->sk_sleep, wait); | 1259 | sock_poll_wait(file, sk->sk_sleep, wait); |
1260 | 1260 | ||
1261 | if (sk->sk_state == IUCV_LISTEN) | 1261 | if (sk->sk_state == IUCV_LISTEN) |
1262 | return iucv_accept_poll(sk); | 1262 | return iucv_accept_poll(sk); |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 003cb470ac84..f49ef288e2e2 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -637,7 +637,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
637 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 637 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
638 | struct mesh_preq_queue *preq_node; | 638 | struct mesh_preq_queue *preq_node; |
639 | 639 | ||
640 | preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); | 640 | preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC); |
641 | if (!preq_node) { | 641 | if (!preq_node) { |
642 | printk(KERN_DEBUG "Mesh HWMP: could not allocate PREQ node\n"); | 642 | printk(KERN_DEBUG "Mesh HWMP: could not allocate PREQ node\n"); |
643 | return; | 643 | return; |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index b218b98fba7f..37771abd8f5a 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -66,7 +66,7 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix) | |||
66 | for (i = rix; i >= 0; i--) | 66 | for (i = rix; i >= 0; i--) |
67 | if (mi->r[i].rix == rix) | 67 | if (mi->r[i].rix == rix) |
68 | break; | 68 | break; |
69 | WARN_ON(mi->r[i].rix != rix); | 69 | WARN_ON(i < 0); |
70 | return i; | 70 | return i; |
71 | } | 71 | } |
72 | 72 | ||
@@ -181,6 +181,9 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
181 | break; | 181 | break; |
182 | 182 | ||
183 | ndx = rix_to_ndx(mi, ar[i].idx); | 183 | ndx = rix_to_ndx(mi, ar[i].idx); |
184 | if (ndx < 0) | ||
185 | continue; | ||
186 | |||
184 | mi->r[ndx].attempts += ar[i].count; | 187 | mi->r[ndx].attempts += ar[i].count; |
185 | 188 | ||
186 | if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) | 189 | if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) |
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index eac5e7bb7365..bfe493ebf27c 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
@@ -63,7 +63,7 @@ static void rxrpc_write_space(struct sock *sk) | |||
63 | _enter("%p", sk); | 63 | _enter("%p", sk); |
64 | read_lock(&sk->sk_callback_lock); | 64 | read_lock(&sk->sk_callback_lock); |
65 | if (rxrpc_writable(sk)) { | 65 | if (rxrpc_writable(sk)) { |
66 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 66 | if (sk_has_sleeper(sk)) |
67 | wake_up_interruptible(sk->sk_sleep); | 67 | wake_up_interruptible(sk->sk_sleep); |
68 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 68 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
69 | } | 69 | } |
@@ -588,7 +588,7 @@ static unsigned int rxrpc_poll(struct file *file, struct socket *sock, | |||
588 | unsigned int mask; | 588 | unsigned int mask; |
589 | struct sock *sk = sock->sk; | 589 | struct sock *sk = sock->sk; |
590 | 590 | ||
591 | poll_wait(file, sk->sk_sleep, wait); | 591 | sock_poll_wait(file, sk->sk_sleep, wait); |
592 | mask = 0; | 592 | mask = 0; |
593 | 593 | ||
594 | /* the socket is readable if there are any messages waiting on the Rx | 594 | /* the socket is readable if there are any messages waiting on the Rx |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 36d4e44d6233..fc3ebb906911 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -315,7 +315,7 @@ static void unix_write_space(struct sock *sk) | |||
315 | { | 315 | { |
316 | read_lock(&sk->sk_callback_lock); | 316 | read_lock(&sk->sk_callback_lock); |
317 | if (unix_writable(sk)) { | 317 | if (unix_writable(sk)) { |
318 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 318 | if (sk_has_sleeper(sk)) |
319 | wake_up_interruptible_sync(sk->sk_sleep); | 319 | wake_up_interruptible_sync(sk->sk_sleep); |
320 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 320 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
321 | } | 321 | } |
@@ -1985,7 +1985,7 @@ static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table | |||
1985 | struct sock *sk = sock->sk; | 1985 | struct sock *sk = sock->sk; |
1986 | unsigned int mask; | 1986 | unsigned int mask; |
1987 | 1987 | ||
1988 | poll_wait(file, sk->sk_sleep, wait); | 1988 | sock_poll_wait(file, sk->sk_sleep, wait); |
1989 | mask = 0; | 1989 | mask = 0; |
1990 | 1990 | ||
1991 | /* exceptional events? */ | 1991 | /* exceptional events? */ |
@@ -2022,7 +2022,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, | |||
2022 | struct sock *sk = sock->sk, *other; | 2022 | struct sock *sk = sock->sk, *other; |
2023 | unsigned int mask, writable; | 2023 | unsigned int mask, writable; |
2024 | 2024 | ||
2025 | poll_wait(file, sk->sk_sleep, wait); | 2025 | sock_poll_wait(file, sk->sk_sleep, wait); |
2026 | mask = 0; | 2026 | mask = 0; |
2027 | 2027 | ||
2028 | /* exceptional events? */ | 2028 | /* exceptional events? */ |
@@ -2053,7 +2053,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, | |||
2053 | other = unix_peer_get(sk); | 2053 | other = unix_peer_get(sk); |
2054 | if (other) { | 2054 | if (other) { |
2055 | if (unix_peer(other) != sk) { | 2055 | if (unix_peer(other) != sk) { |
2056 | poll_wait(file, &unix_sk(other)->peer_wait, | 2056 | sock_poll_wait(file, &unix_sk(other)->peer_wait, |
2057 | wait); | 2057 | wait); |
2058 | if (unix_recvq_full(other)) | 2058 | if (unix_recvq_full(other)) |
2059 | writable = 0; | 2059 | writable = 0; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 241bddd0b4f1..43bdb1372cae 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -447,6 +447,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
447 | 447 | ||
448 | rdev = __cfg80211_drv_from_info(info); | 448 | rdev = __cfg80211_drv_from_info(info); |
449 | if (IS_ERR(rdev)) { | 449 | if (IS_ERR(rdev)) { |
450 | mutex_unlock(&cfg80211_mutex); | ||
450 | result = PTR_ERR(rdev); | 451 | result = PTR_ERR(rdev); |
451 | goto unlock; | 452 | goto unlock; |
452 | } | 453 | } |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index e95b638b919f..f8e71b300001 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -366,7 +366,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
366 | found = rb_find_bss(dev, res); | 366 | found = rb_find_bss(dev, res); |
367 | 367 | ||
368 | if (found) { | 368 | if (found) { |
369 | kref_get(&found->ref); | ||
370 | found->pub.beacon_interval = res->pub.beacon_interval; | 369 | found->pub.beacon_interval = res->pub.beacon_interval; |
371 | found->pub.tsf = res->pub.tsf; | 370 | found->pub.tsf = res->pub.tsf; |
372 | found->pub.signal = res->pub.signal; | 371 | found->pub.signal = res->pub.signal; |