Commit b14ebcfc authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://thebsh.namesys.com/bk/reiser3-linux-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents cb7ada82 16b39f5f
...@@ -247,6 +247,17 @@ ChangeLog ...@@ -247,6 +247,17 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.0.24:
- Small internal cleanups.
- Support for sendfile system call. (Christoph Hellwig)
2.0.23:
- Massive internal locking changes to mft record locking. Fixes
various race conditions and deadlocks.
- Fix ntfs over loopback for compressed files by adding an
optimization barrier. (gcc was screwing up otherwise ?)
Thanks go to Christoph Hellwig for pointing these two out:
- Remove now unused function fs/ntfs/malloc.h::vmalloc_nofs().
- Fix ntfs_free() for ia64 and parisc.
2.0.22: 2.0.22:
- Small internal cleanups. - Small internal cleanups.
2.0.21: 2.0.21:
......
...@@ -138,7 +138,7 @@ typedef struct actcapi_ncpd { ...@@ -138,7 +138,7 @@ typedef struct actcapi_ncpd {
typedef struct actcapi_msg { typedef struct actcapi_msg {
actcapi_msghdr hdr; actcapi_msghdr hdr;
union msg { union {
__u16 manuf_msg; __u16 manuf_msg;
struct manufacturer_req_net { struct manufacturer_req_net {
__u16 manuf_msg; __u16 manuf_msg;
......
...@@ -564,8 +564,8 @@ isdn_audio_eval_dtmf(modem_info * info) ...@@ -564,8 +564,8 @@ isdn_audio_eval_dtmf(modem_info * info)
ISDN_AUDIO_SKB_LOCK(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0;
save_flags(flags); save_flags(flags);
cli(); cli();
di = info->isdn_driver; di = isdn_slot_driver(info->isdn_slot);
ch = info->isdn_channel; ch = isdn_slot_channel(info->isdn_slot);
__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
dev->drv[di]->rcvcount[ch] += 2; dev->drv[di]->rcvcount[ch] += 2;
restore_flags(flags); restore_flags(flags);
...@@ -685,8 +685,8 @@ isdn_audio_put_dle_code(modem_info * info, u_char code) ...@@ -685,8 +685,8 @@ isdn_audio_put_dle_code(modem_info * info, u_char code)
ISDN_AUDIO_SKB_LOCK(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0;
save_flags(flags); save_flags(flags);
cli(); cli();
di = info->isdn_driver; di = isdn_slot_driver(info->isdn_slot);
ch = info->isdn_channel; ch = isdn_slot_channel(info->isdn_slot);
__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
dev->drv[di]->rcvcount[ch] += 2; dev->drv[di]->rcvcount[ch] += 2;
restore_flags(flags); restore_flags(flags);
......
This diff is collapsed.
...@@ -23,6 +23,32 @@ ...@@ -23,6 +23,32 @@
#undef ISDN_DEBUG_NET_DUMP #undef ISDN_DEBUG_NET_DUMP
#undef ISDN_DEBUG_NET_DIAL #undef ISDN_DEBUG_NET_DIAL
#undef ISDN_DEBUG_NET_ICALL #undef ISDN_DEBUG_NET_ICALL
#undef ISDN_DEBUG_STATCALLB
#undef ISDN_DEBUG_COMMAND
#ifdef ISDN_DEBUG_NET_DIAL
#define dbg_net_dial(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_net_dial(arg...) do {} while (0)
#endif
#ifdef ISDN_DEBUG_NET_ICALL
#define dbg_net_icall(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_net_icall(arg...) do {} while (0)
#endif
#ifdef ISDN_DEBUG_STATCALLB
#define dbg_statcallb(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_statcallb(arg...) do {} while (0)
#endif
#define isdn_BUG() \
do { printk(KERN_WARNING "ISDN Bug at %s:%d\n", __FILE__, __LINE__); \
} while(0)
#define HERE printk("%s:%d (%s)\n", __FILE__, __LINE__, __FUNCTION__)
/* Prototypes */ /* Prototypes */
extern void isdn_MOD_INC_USE_COUNT(void); extern void isdn_MOD_INC_USE_COUNT(void);
...@@ -30,20 +56,50 @@ extern void isdn_MOD_DEC_USE_COUNT(void); ...@@ -30,20 +56,50 @@ extern void isdn_MOD_DEC_USE_COUNT(void);
extern void isdn_lock_drivers(void); extern void isdn_lock_drivers(void);
extern void isdn_unlock_drivers(void); extern void isdn_unlock_drivers(void);
extern void isdn_free_channel(int di, int ch, int usage); extern void isdn_free_channel(int di, int ch, int usage);
extern void isdn_all_eaz(int di, int ch);
extern int isdn_command(isdn_ctrl *);
extern int isdn_dc2minor(int di, int ch); extern int isdn_dc2minor(int di, int ch);
extern void isdn_info_update(void); extern void isdn_info_update(void);
extern char *isdn_map_eaz2msn(char *msn, int di); extern char *isdn_map_eaz2msn(char *msn, int di);
extern void isdn_timer_ctrl(int tf, int onoff); extern void isdn_timer_ctrl(int tf, int onoff);
extern void isdn_unexclusive_channel(int di, int ch); extern void isdn_unexclusive_channel(int di, int ch);
extern int isdn_getnum(char **); extern int isdn_getnum(char **);
extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
extern int isdn_get_free_channel(int, int, int, int, int, char *);
extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
extern int register_isdn(isdn_if * i);
extern int isdn_msncmp( const char *, const char *); extern int isdn_msncmp( const char *, const char *);
extern int isdn_add_channels(driver *, int, int, int); extern int isdn_add_channels(driver *, int, int, int);
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
extern void isdn_dumppkt(char *, u_char *, int, int); extern void isdn_dumppkt(char *, u_char *, int, int);
#else
static inline void isdn_dumppkt(char *s, u_char *d, int l, int m) { }
#endif #endif
struct dial_info {
int l2_proto;
int l3_proto;
struct T30_s *fax;
unsigned char si1;
unsigned char si2;
unsigned char *msn;
unsigned char *phone;
};
extern struct list_head isdn_net_devs;
extern int isdn_get_free_slot(int, int, int, int, int, char *);
extern void isdn_slot_free(int slot, int usage);
extern void isdn_slot_all_eaz(int slot);
extern int isdn_slot_command(int slot, int cmd, isdn_ctrl *);
extern int isdn_slot_dial(int slot, struct dial_info *dial);
extern char *isdn_slot_map_eaz2msn(int slot, char *msn);
extern int isdn_slot_write(int slot, struct sk_buff *);
extern int isdn_slot_readbchan(int slot, u_char *, u_char *, int);
extern int isdn_slot_hdrlen(int slot);
extern int isdn_slot_driver(int slot);
extern int isdn_slot_channel(int slot);
extern int isdn_slot_usage(int slot);
extern void isdn_slot_set_usage(int slot, int usage);
extern char *isdn_slot_num(int slot);
extern int isdn_slot_m_idx(int slot);
extern void isdn_slot_set_m_idx(int slot, int midx);
extern void isdn_slot_set_rx_netdev(int sl, isdn_net_dev *nd);
extern void isdn_slot_set_st_netdev(int sl, isdn_net_dev *nd);
extern isdn_net_dev *isdn_slot_rx_netdev(int sl);
extern isdn_net_dev *isdn_slot_st_netdev(int sl);
This diff is collapsed.
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
#define CISCO_SLARP_REPLY 1 #define CISCO_SLARP_REPLY 1
#define CISCO_SLARP_KEEPALIVE 2 #define CISCO_SLARP_KEEPALIVE 2
extern char *isdn_net_new(char *, struct net_device *); extern int isdn_net_new(char *, struct net_device *);
extern char *isdn_net_newslave(char *); extern int isdn_net_newslave(char *);
extern int isdn_net_rm(char *); extern int isdn_net_rm(char *);
extern int isdn_net_rmall(void); extern int isdn_net_rmall(void);
extern int isdn_net_stat_callback(int, isdn_ctrl *); extern int isdn_net_stat_callback(int, isdn_ctrl *);
...@@ -44,7 +44,6 @@ extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *); ...@@ -44,7 +44,6 @@ extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *);
extern int isdn_net_delphone(isdn_net_ioctl_phone *); extern int isdn_net_delphone(isdn_net_ioctl_phone *);
extern int isdn_net_find_icall(int, int, int, setup_parm *); extern int isdn_net_find_icall(int, int, int, setup_parm *);
extern void isdn_net_hangup(struct net_device *); extern void isdn_net_hangup(struct net_device *);
extern void isdn_net_dial(void);
extern void isdn_net_autohup(void); extern void isdn_net_autohup(void);
extern int isdn_net_force_hangup(char *); extern int isdn_net_force_hangup(char *);
extern int isdn_net_force_dial(char *); extern int isdn_net_force_dial(char *);
...@@ -131,7 +130,7 @@ static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp) ...@@ -131,7 +130,7 @@ static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp)
if (master_lp->netdev->queue == lp) { if (master_lp->netdev->queue == lp) {
master_lp->netdev->queue = lp->next; master_lp->netdev->queue = lp->next;
if (lp->next == lp) { /* last in queue */ if (lp->next == lp) { /* last in queue */
master_lp->netdev->queue = master_lp->netdev->local; master_lp->netdev->queue = &master_lp->netdev->local;
} }
} }
lp->next = lp->last = lp; /* (re)set own pointers */ lp->next = lp->last = lp; /* (re)set own pointers */
......
...@@ -165,14 +165,15 @@ isdn_ppp_bind(isdn_net_local * lp) ...@@ -165,14 +165,15 @@ isdn_ppp_bind(isdn_net_local * lp)
save_flags(flags); save_flags(flags);
cli(); cli();
if (lp->pppbind < 0) { /* device bounded to ippp device ? */ if (lp->pppbind < 0) { /* device bounded to ippp device ? */
isdn_net_dev *net_dev = dev->netdev; struct list_head *l;
char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */ char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */
memset(exclusive, 0, ISDN_MAX_CHANNELS); memset(exclusive, 0, ISDN_MAX_CHANNELS);
while (net_dev) { /* step through net devices to find exclusive minors */ /* step through net devices to find exclusive minors */
isdn_net_local *lp = net_dev->local; list_for_each(l, &isdn_net_devs) {
isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
isdn_net_local *lp = &p->local;
if (lp->pppbind >= 0) if (lp->pppbind >= 0)
exclusive[lp->pppbind] = 1; exclusive[lp->pppbind] = 1;
net_dev = net_dev->next;
} }
/* /*
* search a free device / slot * search a free device / slot
...@@ -804,11 +805,11 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off) ...@@ -804,11 +805,11 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
if (proto != PPP_LCP) if (proto != PPP_LCP)
lp->huptimer = 0; lp->huptimer = 0;
if (lp->isdn_device < 0 || lp->isdn_channel < 0) { if (lp->isdn_slot < 0) {
retval = 0; retval = 0;
goto out; goto out;
} }
if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) && if ((dev->drv[isdn_slot_driver(lp->isdn_slot)]->flags & DRV_FLAG_RUNNING) &&
lp->dialstate == 0 && lp->dialstate == 0 &&
(lp->flags & ISDN_NET_CONNECTED)) { (lp->flags & ISDN_NET_CONNECTED)) {
unsigned short hl; unsigned short hl;
...@@ -818,7 +819,7 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off) ...@@ -818,7 +819,7 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
* sk_buff. old call to dev_alloc_skb only reserved * sk_buff. old call to dev_alloc_skb only reserved
* 16 bytes, now we are looking what the driver want * 16 bytes, now we are looking what the driver want
*/ */
hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; hl = isdn_slot_hdrlen(lp->isdn_slot);
skb = alloc_skb(hl+count, GFP_ATOMIC); skb = alloc_skb(hl+count, GFP_ATOMIC);
if (!skb) { if (!skb) {
printk(KERN_WARNING "isdn_ppp_write: out of memory!\n"); printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
...@@ -974,7 +975,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf ...@@ -974,7 +975,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
int slot; int slot;
int proto; int proto;
if (net_dev->local->master) if (net_dev->local.master)
BUG(); // we're called with the master device always BUG(); // we're called with the master device always
slot = lp->ppp_slot; slot = lp->ppp_slot;
...@@ -1077,12 +1078,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff ...@@ -1077,12 +1078,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
case PPP_VJC_UNCOMP: case PPP_VJC_UNCOMP:
if (is->debug & 0x20) if (is->debug & 0x20)
printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n"); printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
if (net_dev->local->ppp_slot < 0) { if (net_dev->local.ppp_slot < 0) {
printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n", printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n",
net_dev->local->ppp_slot); net_dev->local.ppp_slot);
goto drop_packet; goto drop_packet;
} }
if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) { if (slhc_remember(ippp_table[net_dev->local.ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n"); printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
goto drop_packet; goto drop_packet;
} }
...@@ -1103,12 +1104,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff ...@@ -1103,12 +1104,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
} }
skb_put(skb, skb_old->len + 128); skb_put(skb, skb_old->len + 128);
memcpy(skb->data, skb_old->data, skb_old->len); memcpy(skb->data, skb_old->data, skb_old->len);
if (net_dev->local->ppp_slot < 0) { if (net_dev->local.ppp_slot < 0) {
printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n", printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n",
net_dev->local->ppp_slot); net_dev->local.ppp_slot);
goto drop_packet; goto drop_packet;
} }
pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp, pkt_len = slhc_uncompress(ippp_table[net_dev->local.ppp_slot]->slcomp,
skb->data, skb_old->len); skb->data, skb_old->len);
kfree_skb(skb_old); kfree_skb(skb_old);
if (pkt_len < 0) if (pkt_len < 0)
...@@ -1144,7 +1145,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff ...@@ -1144,7 +1145,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
return; return;
drop_packet: drop_packet:
net_dev->local->stats.rx_dropped++; net_dev->local.stats.rx_dropped++;
kfree_skb(skb); kfree_skb(skb);
} }
...@@ -1263,7 +1264,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -1263,7 +1264,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
* sk_buff. old call to dev_alloc_skb only reserved * sk_buff. old call to dev_alloc_skb only reserved
* 16 bytes, now we are looking what the driver want. * 16 bytes, now we are looking what the driver want.
*/ */
hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + IPPP_MAX_HEADER; hl = isdn_slot_hdrlen(lp->isdn_slot) + IPPP_MAX_HEADER;;
/* /*
* Note: hl might still be insufficient because the method * Note: hl might still be insufficient because the method
* above does not account for a possibible MPPP slave channel * above does not account for a possibible MPPP slave channel
...@@ -1976,7 +1977,7 @@ isdn_ppp_dial_slave(char *name) ...@@ -1976,7 +1977,7 @@ isdn_ppp_dial_slave(char *name)
if (!(ndev = isdn_net_findif(name))) if (!(ndev = isdn_net_findif(name)))
return 1; return 1;
lp = ndev->local; lp = &ndev->local;
if (!(lp->flags & ISDN_NET_CONNECTED)) if (!(lp->flags & ISDN_NET_CONNECTED))
return 5; return 5;
...@@ -2007,7 +2008,7 @@ isdn_ppp_hangup_slave(char *name) ...@@ -2007,7 +2008,7 @@ isdn_ppp_hangup_slave(char *name)
if (!(ndev = isdn_net_findif(name))) if (!(ndev = isdn_net_findif(name)))
return 1; return 1;
lp = ndev->local; lp = &ndev->local;
if (!(lp->flags & ISDN_NET_CONNECTED)) if (!(lp->flags & ISDN_NET_CONNECTED))
return 5; return 5;
...@@ -2094,7 +2095,7 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, ...@@ -2094,7 +2095,7 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
isdn_net_local *lp = is->lp; isdn_net_local *lp = is->lp;
/* Alloc large enough skb */ /* Alloc large enough skb */
hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; hl = isdn_slot_hdrlen(lp->isdn_slot);
skb = alloc_skb(len + hl + 16,GFP_ATOMIC); skb = alloc_skb(len + hl + 16,GFP_ATOMIC);
if(!skb) { if(!skb) {
printk(KERN_WARNING printk(KERN_WARNING
......
This diff is collapsed.
...@@ -105,7 +105,7 @@ extern void isdn_tty_modem_escape(void); ...@@ -105,7 +105,7 @@ extern void isdn_tty_modem_escape(void);
extern void isdn_tty_modem_ring(void); extern void isdn_tty_modem_ring(void);
extern void isdn_tty_carrier_timeout(void); extern void isdn_tty_carrier_timeout(void);
extern void isdn_tty_modem_xmit(void); extern void isdn_tty_modem_xmit(void);
extern int isdn_tty_modem_init(void); extern int isdn_tty_init(void);
extern void isdn_tty_readmodem(void); extern void isdn_tty_readmodem(void);
extern int isdn_tty_find_icall(int, int, setup_parm *); extern int isdn_tty_find_icall(int, int, setup_parm *);
extern void isdn_tty_cleanup_xmit(modem_info *); extern void isdn_tty_cleanup_xmit(modem_info *);
...@@ -119,3 +119,6 @@ extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *); ...@@ -119,3 +119,6 @@ extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *); extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *);
extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *); extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *);
#endif #endif
extern int isdn_tty_init(void);
extern void isdn_tty_exit(void);
...@@ -74,7 +74,7 @@ isdn_tty_fax_modem_result(int code, modem_info * info) ...@@ -74,7 +74,7 @@ isdn_tty_fax_modem_result(int code, modem_info * info)
case 2: /* +FCON */ case 2: /* +FCON */
/* Append CPN, if enabled */ /* Append CPN, if enabled */
if ((m->mdmreg[REG_CPNFCON] & BIT_CPNFCON) && if ((m->mdmreg[REG_CPNFCON] & BIT_CPNFCON) &&
(!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) { (!(isdn_slot_usage(info->isdn_slot) & ISDN_USAGE_OUTGOING))) {
sprintf(rs, "/%s", m->cpn); sprintf(rs, "/%s", m->cpn);
isdn_tty_at_cout(rs, info); isdn_tty_at_cout(rs, info);
} }
...@@ -360,12 +360,11 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info) ...@@ -360,12 +360,11 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
default: default:
PARSE_ERROR1; PARSE_ERROR1;
} }
c.command = ISDN_CMD_FAXCMD;
#ifdef ISDN_TTY_FAX_CMD_DEBUG #ifdef ISDN_TTY_FAX_CMD_DEBUG
printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n", printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n",
c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]); c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]);
#endif #endif
if (info->isdn_driver < 0) { if (info->isdn_slot < 0) {
save_flags(flags); save_flags(flags);
cli(); cli();
if ((c.parm.aux.subcmd == AT_EQ_VALUE) || if ((c.parm.aux.subcmd == AT_EQ_VALUE) ||
...@@ -374,32 +373,21 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info) ...@@ -374,32 +373,21 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
PARSE_ERROR1; PARSE_ERROR1;
} }
/* get a temporary connection to the first free fax driver */ /* get a temporary connection to the first free fax driver */
i = isdn_get_free_channel(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX, i = isdn_get_free_slot(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX,
ISDN_PROTO_L3_FCLASS1, -1, -1, "00"); ISDN_PROTO_L3_FCLASS1, -1, -1, "00");
if (i < 0) { if (i < 0) {
restore_flags(flags); restore_flags(flags);
PARSE_ERROR1; PARSE_ERROR1;
} }
info->isdn_driver = dev->drvmap[i]; info->isdn_slot = i;
info->isdn_channel = dev->chanmap[i]; isdn_slot_set_m_idx(i, info->line);
info->drv_index = i; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &c);
dev->m_idx[i] = info->line; isdn_slot_free(info->isdn_slot, ISDN_USAGE_FAX);
c.driver = info->isdn_driver; isdn_slot_set_m_idx(i, -1);
c.arg = info->isdn_channel; info->isdn_slot = -1;
isdn_command(&c);
isdn_free_channel(info->isdn_driver, info->isdn_channel,
ISDN_USAGE_FAX);
info->isdn_driver = -1;
info->isdn_channel = -1;
if (info->drv_index >= 0) {
dev->m_idx[info->drv_index] = -1;
info->drv_index = -1;
}
restore_flags(flags); restore_flags(flags);
} else { } else {
c.driver = info->isdn_driver; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &c);
c.arg = info->isdn_channel;
isdn_command(&c);
} }
return 1; return 1;
} }
...@@ -800,10 +788,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) ...@@ -800,10 +788,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
printk(KERN_DEBUG "isdn_tty: Fax FDR\n"); printk(KERN_DEBUG "isdn_tty: Fax FDR\n");
#endif #endif
f->code = ISDN_TTY_FAX_DR; f->code = ISDN_TTY_FAX_DR;
cmd.driver = info->isdn_driver; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd);
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_FAXCMD;
isdn_command(&cmd);
if (f->phase == ISDN_FAX_PHASE_B) { if (f->phase == ISDN_FAX_PHASE_B) {
f->phase = ISDN_FAX_PHASE_C; f->phase = ISDN_FAX_PHASE_C;
} else if (f->phase == ISDN_FAX_PHASE_D) { } else if (f->phase == ISDN_FAX_PHASE_D) {
...@@ -855,10 +840,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) ...@@ -855,10 +840,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
#endif #endif
if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) { if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) {
f->code = ISDN_TTY_FAX_DT; f->code = ISDN_TTY_FAX_DT;
cmd.driver = info->isdn_driver; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd);
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_FAXCMD;
isdn_command(&cmd);
if (f->phase == ISDN_FAX_PHASE_D) { if (f->phase == ISDN_FAX_PHASE_D) {
f->phase = ISDN_FAX_PHASE_C; f->phase = ISDN_FAX_PHASE_C;
isdn_tty_fax_modem_result(7, info); /* CONNECT */ isdn_tty_fax_modem_result(7, info); /* CONNECT */
...@@ -913,10 +895,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) ...@@ -913,10 +895,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
PARSE_ERROR1; PARSE_ERROR1;
f->fet = par; f->fet = par;
f->code = ISDN_TTY_FAX_ET; f->code = ISDN_TTY_FAX_ET;
cmd.driver = info->isdn_driver; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd);
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_FAXCMD;
isdn_command(&cmd);
#ifdef ISDN_TTY_FAX_STAT_DEBUG #ifdef ISDN_TTY_FAX_STAT_DEBUG
printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par); printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par);
#endif #endif
......
...@@ -515,14 +515,12 @@ isdn_v110_encode(isdn_v110_stream * v, struct sk_buff *skb) ...@@ -515,14 +515,12 @@ isdn_v110_encode(isdn_v110_stream * v, struct sk_buff *skb)
} }
int int
isdn_v110_stat_callback(int idx, isdn_ctrl * c) isdn_v110_stat_callback(struct isdn_v110 *iv110, isdn_ctrl *c)
{ {
isdn_v110_stream *v = NULL; isdn_v110_stream *v = NULL;
int i; int i;
int ret; int ret;
if (idx < 0)
return 0;
switch (c->command) { switch (c->command) {
case ISDN_STAT_BSENT: case ISDN_STAT_BSENT:
/* Keep the send-queue of the driver filled /* Keep the send-queue of the driver filled
...@@ -531,9 +529,9 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c) ...@@ -531,9 +529,9 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
* send down an Idle-Frame (or an Sync-Frame, if * send down an Idle-Frame (or an Sync-Frame, if
* v->SyncInit != 0). * v->SyncInit != 0).
*/ */
if (!(v = dev->v110[idx])) if (!(v = iv110->v110))
return 0; return 0;
atomic_inc(&dev->v110use[idx]); atomic_inc(&iv110->v110use);
if (v->skbidle > 0) { if (v->skbidle > 0) {
v->skbidle--; v->skbidle--;
ret = 1; ret = 1;
...@@ -560,38 +558,38 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c) ...@@ -560,38 +558,38 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
} else } else
break; break;
} }
atomic_dec(&dev->v110use[idx]); atomic_dec(&iv110->v110use);
return ret; return ret;
case ISDN_STAT_DHUP: case ISDN_STAT_DHUP:
case ISDN_STAT_BHUP: case ISDN_STAT_BHUP:
while (1) { while (1) {
atomic_inc(&dev->v110use[idx]); atomic_inc(&iv110->v110use);
if (atomic_dec_and_test(&dev->v110use[idx])) { if (atomic_dec_and_test(&iv110->v110use)) {
isdn_v110_close(dev->v110[idx]); isdn_v110_close(iv110->v110);
dev->v110[idx] = NULL; iv110->v110 = NULL;
break; break;
} }
sti(); sti();
} }
break; break;
case ISDN_STAT_BCONN: case ISDN_STAT_BCONN:
if (dev->v110emu[idx] && (dev->v110[idx] == NULL)) { if (iv110->v110emu && (iv110->v110 == NULL)) {
int hdrlen = dev->drv[c->driver]->interface->hl_hdrlen; int hdrlen = dev->drv[c->driver]->interface->hl_hdrlen;
int maxsize = dev->drv[c->driver]->interface->maxbufsize; int maxsize = dev->drv[c->driver]->interface->maxbufsize;
atomic_inc(&dev->v110use[idx]); atomic_inc(&iv110->v110use);
switch (dev->v110emu[idx]) { switch (iv110->v110emu) {
case ISDN_PROTO_L2_V11096: case ISDN_PROTO_L2_V11096:
dev->v110[idx] = isdn_v110_open(V110_9600, hdrlen, maxsize); iv110->v110 = isdn_v110_open(V110_9600, hdrlen, maxsize);
break; break;
case ISDN_PROTO_L2_V11019: case ISDN_PROTO_L2_V11019:
dev->v110[idx] = isdn_v110_open(V110_19200, hdrlen, maxsize); iv110->v110 = isdn_v110_open(V110_19200, hdrlen, maxsize);
break; break;
case ISDN_PROTO_L2_V11038: case ISDN_PROTO_L2_V11038:
dev->v110[idx] = isdn_v110_open(V110_38400, hdrlen, maxsize); iv110->v110 = isdn_v110_open(V110_38400, hdrlen, maxsize);
break; break;
default:; default:;
} }
if ((v = dev->v110[idx])) { if ((v = iv110->v110)) {
while (v->SyncInit) { while (v->SyncInit) {
struct sk_buff *skb = isdn_v110_sync(v); struct sk_buff *skb = isdn_v110_sync(v);
if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) { if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) {
...@@ -603,8 +601,8 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c) ...@@ -603,8 +601,8 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
v->skbidle++; v->skbidle++;
} }
} else } else
printk(KERN_WARNING "isdn_v110: Couldn't open stream for chan %d\n", idx); printk(KERN_WARNING "isdn_v110: Couldn't open stream\n");
atomic_dec(&dev->v110use[idx]); atomic_dec(&iv110->v110use);
} }
break; break;
default: default:
......
...@@ -9,8 +9,14 @@ ...@@ -9,8 +9,14 @@
* *
*/ */
#ifndef _isdn_v110_h_ #ifndef ISDN_V110_H
#define _isdn_v110_h_ #define ISDN_V110_H
struct isdn_v110 {
int v110emu; /* V.110 emulator-mode 0=none */
atomic_t v110use; /* Usage-Semaphore for stream */
isdn_v110_stream *v110; /* V.110 private data */
};
/* /*
* isdn_v110_encode will take raw data and encode it using V.110 * isdn_v110_encode will take raw data and encode it using V.110
...@@ -23,7 +29,7 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *); ...@@ -23,7 +29,7 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *);
*/ */
extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *); extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *);
extern int isdn_v110_stat_callback(int, isdn_ctrl *); extern int isdn_v110_stat_callback(struct isdn_v110 *v110, isdn_ctrl *);
extern void isdn_v110_close(isdn_v110_stream * v); extern void isdn_v110_close(isdn_v110_stream * v);
#endif #endif
...@@ -757,6 +757,10 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller) ...@@ -757,6 +757,10 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller)
int i; int i;
static char nphone[30]; static char nphone[30];
if (!card) {
printk("BUG!!!\n");
return "";
}
switch (card->ptype) { switch (card->ptype) {
case ISDN_PTYPE_EURO: case ISDN_PTYPE_EURO:
if (caller) { if (caller) {
...@@ -775,7 +779,7 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller) ...@@ -775,7 +779,7 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller)
return (&phone[strlen(phone) - 1]); return (&phone[strlen(phone) - 1]);
break; break;
} }
return ("\0"); return "";
} }
/* /*
...@@ -882,7 +886,7 @@ isdnloop_parse_cmd(isdnloop_card * card) ...@@ -882,7 +886,7 @@ isdnloop_parse_cmd(isdnloop_card * card)
isdnloop_vstphone(card, cmd.parm.setup.eazmsn, 1), isdnloop_vstphone(card, cmd.parm.setup.eazmsn, 1),
cmd.parm.setup.si1, cmd.parm.setup.si1,
cmd.parm.setup.si2, cmd.parm.setup.si2,
isdnloop_vstphone(card->rcard[ch], isdnloop_vstphone(card->rcard[ch - 1],
cmd.parm.setup.phone, 0)); cmd.parm.setup.phone, 0));
isdnloop_fake(card->rcard[ch - 1], buf, card->rch[ch - 1] + 1); isdnloop_fake(card->rcard[ch - 1], buf, card->rch[ch - 1] + 1);
/* Fall through */ /* Fall through */
......
...@@ -2,6 +2,36 @@ ToDo: ...@@ -2,6 +2,36 @@ ToDo:
- Find and fix bugs. - Find and fix bugs.
- Enable NFS exporting of NTFS. - Enable NFS exporting of NTFS.
2.0.24 - Cleanups.
- Treat BUG_ON() as ASSERT() not VERIFY(), i.e. do not use side effects
inside BUG_ON(). (Adam J. Richter)
- Split logical OR expressions inside BUG_ON() into individual BUG_ON()
calls for improved debugging. (Adam J. Richter)
- Add errors flag to the ntfs volume state, accessed via
NVol{,Set,Clear}Errors(vol).
- Do not allow read-write remounts of read-only volumes with errors.
- Clarify comment for ntfs file operation sendfile which was added by
Christoph Hellwig a while ago (just using generic_file_sendfile())
to say that ntfs ->sendfile is only used for the case where the
source data is on the ntfs partition and the destination is
somewhere else, i.e. nothing we need to concern ourselves with.
- Add generic_file_write() as our ntfs file write operation.
2.0.23 - Major bug fixes (races, deadlocks, non-i386 architectures).
- Massive internal locking changes to mft record locking. Fixes lock
recursion and replaces the mrec_lock read/write semaphore with a
mutex. Also removes the now superfluous mft_count. This fixes several
race conditions and deadlocks, especially in the future write code.
- Fix ntfs over loopback for compressed files by adding an
optimization barrier. (gcc was screwing up otherwise ?)
- Miscellaneous cleanups all over the code and a fix or two in error
handling code paths.
Thanks go to Christoph Hellwig for pointing out the following two:
- Remove now unused function fs/ntfs/malloc.h::vmalloc_nofs().
- Fix ntfs_free() for ia64 and parisc by checking for VMALLOC_END, too.
2.0.22 - Cleanups, mainly to ntfs_readdir(), and use C99 initializers. 2.0.22 - Cleanups, mainly to ntfs_readdir(), and use C99 initializers.
- Change fs/ntfs/dir.c::ntfs_reddir() to only read/write ->f_pos once - Change fs/ntfs/dir.c::ntfs_reddir() to only read/write ->f_pos once
......
...@@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o ...@@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o
ntfs-objs := aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o \ ntfs-objs := aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o \
mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o
EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.22\" EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.24\"
ifeq ($(CONFIG_NTFS_DEBUG),y) ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG EXTRA_CFLAGS += -DDEBUG
......
...@@ -106,8 +106,6 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate) ...@@ -106,8 +106,6 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
if (!NInoMstProtected(ni)) { if (!NInoMstProtected(ni)) {
if (likely(page_uptodate && !PageError(page))) if (likely(page_uptodate && !PageError(page)))
SetPageUptodate(page); SetPageUptodate(page);
unlock_page(page);
return;
} else { } else {
char *addr; char *addr;
unsigned int i, recs, nr_err; unsigned int i, recs, nr_err;
...@@ -332,6 +330,8 @@ static int ntfs_read_block(struct page *page) ...@@ -332,6 +330,8 @@ static int ntfs_read_block(struct page *page)
* for it to be read in before we can do the copy. * for it to be read in before we can do the copy.
* *
* Return 0 on success and -errno on error. * Return 0 on success and -errno on error.
*
* WARNING: Do not make this function static! It is used by mft.c!
*/ */
int ntfs_readpage(struct file *file, struct page *page) int ntfs_readpage(struct file *file, struct page *page)
{ {
...@@ -372,8 +372,8 @@ int ntfs_readpage(struct file *file, struct page *page) ...@@ -372,8 +372,8 @@ int ntfs_readpage(struct file *file, struct page *page)
else else
base_ni = ni->_INE(base_ntfs_ino); base_ni = ni->_INE(base_ntfs_ino);
/* Map, pin and lock the mft record for reading. */ /* Map, pin and lock the mft record. */
mrec = map_mft_record(READ, base_ni); mrec = map_mft_record(base_ni);
if (unlikely(IS_ERR(mrec))) { if (unlikely(IS_ERR(mrec))) {
err = PTR_ERR(mrec); err = PTR_ERR(mrec);
goto err_out; goto err_out;
...@@ -416,7 +416,7 @@ int ntfs_readpage(struct file *file, struct page *page) ...@@ -416,7 +416,7 @@ int ntfs_readpage(struct file *file, struct page *page)
put_unm_err_out: put_unm_err_out:
put_attr_search_ctx(ctx); put_attr_search_ctx(ctx);
unm_err_out: unm_err_out:
unmap_mft_record(READ, base_ni); unmap_mft_record(base_ni);
err_out: err_out:
unlock_page(page); unlock_page(page);
return err; return err;
......
...@@ -110,7 +110,8 @@ static inline run_list_element *ntfs_rl_realloc(run_list_element *rl, ...@@ -110,7 +110,8 @@ static inline run_list_element *ntfs_rl_realloc(run_list_element *rl,
static inline BOOL ntfs_are_rl_mergeable(run_list_element *dst, static inline BOOL ntfs_are_rl_mergeable(run_list_element *dst,
run_list_element *src) run_list_element *src)
{ {
BUG_ON(!dst || !src); BUG_ON(!dst);
BUG_ON(!src);
if ((dst->lcn < 0) || (src->lcn < 0)) /* Are we merging holes? */ if ((dst->lcn < 0) || (src->lcn < 0)) /* Are we merging holes? */
return FALSE; return FALSE;
...@@ -192,7 +193,8 @@ static inline run_list_element *ntfs_rl_append(run_list_element *dst, ...@@ -192,7 +193,8 @@ static inline run_list_element *ntfs_rl_append(run_list_element *dst,
BOOL right; BOOL right;
int magic; int magic;
BUG_ON(!dst || !src); BUG_ON(!dst);
BUG_ON(!src);
/* First, check if the right hand end needs merging. */ /* First, check if the right hand end needs merging. */
right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1); right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
...@@ -258,7 +260,8 @@ static inline run_list_element *ntfs_rl_insert(run_list_element *dst, ...@@ -258,7 +260,8 @@ static inline run_list_element *ntfs_rl_insert(run_list_element *dst,
BOOL hole = FALSE; /* Following a hole */ BOOL hole = FALSE; /* Following a hole */
int magic; int magic;
BUG_ON(!dst || !src); BUG_ON(!dst);
BUG_ON(!src);
/* disc => Discontinuity between the end of @dst and the start of @src. /* disc => Discontinuity between the end of @dst and the start of @src.
* This means we might need to insert a hole. * This means we might need to insert a hole.
...@@ -362,7 +365,8 @@ static inline run_list_element *ntfs_rl_replace(run_list_element *dst, ...@@ -362,7 +365,8 @@ static inline run_list_element *ntfs_rl_replace(run_list_element *dst,
BOOL right; BOOL right;
int magic; int magic;
BUG_ON(!dst || !src); BUG_ON(!dst);
BUG_ON(!src);
/* First, merge the left and right ends, if necessary. */ /* First, merge the left and right ends, if necessary. */
right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1); right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
...@@ -423,7 +427,8 @@ static inline run_list_element *ntfs_rl_replace(run_list_element *dst, ...@@ -423,7 +427,8 @@ static inline run_list_element *ntfs_rl_replace(run_list_element *dst,
static inline run_list_element *ntfs_rl_split(run_list_element *dst, int dsize, static inline run_list_element *ntfs_rl_split(run_list_element *dst, int dsize,
run_list_element *src, int ssize, int loc) run_list_element *src, int ssize, int loc)
{ {
BUG_ON(!dst || !src); BUG_ON(!dst);
BUG_ON(!src);
/* Space required: @dst size + @src size + one new hole. */ /* Space required: @dst size + @src size + one new hole. */
dst = ntfs_rl_realloc(dst, dsize, dsize + ssize + 1); dst = ntfs_rl_realloc(dst, dsize, dsize + ssize + 1);
...@@ -948,7 +953,7 @@ int map_run_list(ntfs_inode *ni, VCN vcn) ...@@ -948,7 +953,7 @@ int map_run_list(ntfs_inode *ni, VCN vcn)
else else
base_ni = ni->_INE(base_ntfs_ino); base_ni = ni->_INE(base_ntfs_ino);
mrec = map_mft_record(READ, base_ni); mrec = map_mft_record(base_ni);
if (IS_ERR(mrec)) if (IS_ERR(mrec))
return PTR_ERR(mrec); return PTR_ERR(mrec);
ctx = get_attr_search_ctx(base_ni, mrec); ctx = get_attr_search_ctx(base_ni, mrec);
...@@ -979,7 +984,7 @@ int map_run_list(ntfs_inode *ni, VCN vcn) ...@@ -979,7 +984,7 @@ int map_run_list(ntfs_inode *ni, VCN vcn)
put_attr_search_ctx(ctx); put_attr_search_ctx(ctx);
err_out: err_out:
unmap_mft_record(READ, base_ni); unmap_mft_record(base_ni);
return err; return err;
} }
...@@ -1671,7 +1676,7 @@ void reinit_attr_search_ctx(attr_search_context *ctx) ...@@ -1671,7 +1676,7 @@ void reinit_attr_search_ctx(attr_search_context *ctx)
return; return;
} /* Attribute list. */ } /* Attribute list. */
if (ctx->ntfs_ino != ctx->base_ntfs_ino) if (ctx->ntfs_ino != ctx->base_ntfs_ino)
unmap_mft_record(READ, ctx->ntfs_ino); unmap_mft_record(ctx->ntfs_ino);
init_attr_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec); init_attr_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec);
return; return;
} }
...@@ -1704,7 +1709,7 @@ attr_search_context *get_attr_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec) ...@@ -1704,7 +1709,7 @@ attr_search_context *get_attr_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
void put_attr_search_ctx(attr_search_context *ctx) void put_attr_search_ctx(attr_search_context *ctx)
{ {
if (ctx->base_ntfs_ino && ctx->ntfs_ino != ctx->base_ntfs_ino) if (ctx->base_ntfs_ino && ctx->ntfs_ino != ctx->base_ntfs_ino)
unmap_mft_record(READ, ctx->ntfs_ino); unmap_mft_record(ctx->ntfs_ino);
kmem_cache_free(ntfs_attr_ctx_cache, ctx); kmem_cache_free(ntfs_attr_ctx_cache, ctx);
return; return;
} }
......
...@@ -467,7 +467,8 @@ int ntfs_read_compressed_block(struct page *page) ...@@ -467,7 +467,8 @@ int ntfs_read_compressed_block(struct page *page)
* Bad things happen if we get here for anything that is not an * Bad things happen if we get here for anything that is not an
* unnamed $DATA attribute. * unnamed $DATA attribute.
*/ */
BUG_ON(ni->type != AT_DATA || ni->name_len); BUG_ON(ni->type != AT_DATA);
BUG_ON(ni->name_len);
pages = kmalloc(nr_pages * sizeof(struct page *), GFP_NOFS); pages = kmalloc(nr_pages * sizeof(struct page *), GFP_NOFS);
...@@ -608,8 +609,27 @@ int ntfs_read_compressed_block(struct page *page) ...@@ -608,8 +609,27 @@ int ntfs_read_compressed_block(struct page *page)
if (buffer_uptodate(tbh)) if (buffer_uptodate(tbh))
continue; continue;
wait_on_buffer(tbh); wait_on_buffer(tbh);
if (unlikely(!buffer_uptodate(tbh))) /*
goto read_err; * We need an optimization barrier here, otherwise we start
* hitting the below fixup code when accessing a loopback
* mounted ntfs partition. This indicates either there is a
* race condition in the loop driver or, more likely, gcc
* overoptimises the code without the barrier and it doesn't
* do the Right Thing(TM).
*/
barrier();
if (unlikely(!buffer_uptodate(tbh))) {
ntfs_warning(vol->sb, "Buffer is unlocked but not "
"uptodate! Unplugging the disk queue "
"and rescheduling.");
get_bh(tbh);
blk_run_queues();
schedule();
put_bh(tbh);
if (unlikely(!buffer_uptodate(tbh)))
goto read_err;
ntfs_warning(vol->sb, "Buffer is now uptodate. Good.");
}
} }
/* /*
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment