## Automatically generated incremental diff ## From: linux-2.5.67-bk9 ## To: linux-2.5.67-bk10 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.5.67-bk9/Makefile linux-2.5.67-bk10/Makefile --- linux-2.5.67-bk9/Makefile 2003-04-19 04:35:27.000000000 -0700 +++ linux-2.5.67-bk10/Makefile 2003-04-19 04:35:36.000000000 -0700 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 SUBLEVEL = 67 -EXTRAVERSION = -bk9 +EXTRAVERSION = -bk10 # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff -urN linux-2.5.67-bk9/arch/sparc64/kernel/ioctl32.c linux-2.5.67-bk10/arch/sparc64/kernel/ioctl32.c --- linux-2.5.67-bk9/arch/sparc64/kernel/ioctl32.c 2003-04-19 04:35:28.000000000 -0700 +++ linux-2.5.67-bk10/arch/sparc64/kernel/ioctl32.c 2003-04-19 04:35:36.000000000 -0700 @@ -54,9 +54,6 @@ #include #include #include -#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) -#include -#endif /* LVM */ #include #include @@ -2766,443 +2763,6 @@ return -EINVAL; } -#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) -/* Ugh, LVM. Pitty it was not cleaned up before accepted :((. */ -typedef struct { - uint8_t vg_name[NAME_LEN]; - uint32_t vg_number; - uint32_t vg_access; - uint32_t vg_status; - uint32_t lv_max; - uint32_t lv_cur; - uint32_t lv_open; - uint32_t pv_max; - uint32_t pv_cur; - uint32_t pv_act; - uint32_t dummy; - uint32_t vgda; - uint32_t pe_size; - uint32_t pe_total; - uint32_t pe_allocated; - uint32_t pvg_total; - u32 proc; - u32 pv[ABS_MAX_PV + 1]; - u32 lv[ABS_MAX_LV + 1]; - uint8_t vg_uuid[UUID_LEN+1]; /* volume group UUID */ - uint8_t dummy1[200]; -} vg32_t; - -typedef struct { - uint8_t id[2]; - uint16_t version; - lvm_disk_data_t pv_on_disk; - lvm_disk_data_t vg_on_disk; - lvm_disk_data_t pv_namelist_on_disk; - lvm_disk_data_t lv_on_disk; - lvm_disk_data_t pe_on_disk; - uint8_t pv_name[NAME_LEN]; - uint8_t vg_name[NAME_LEN]; - uint8_t system_id[NAME_LEN]; - kdev_t pv_dev; - uint32_t pv_number; - uint32_t pv_status; - uint32_t pv_allocatable; - uint32_t pv_size; - uint32_t lv_cur; - uint32_t pe_size; - uint32_t pe_total; - uint32_t pe_allocated; - uint32_t pe_stale; - u32 pe; - u32 inode; - uint8_t pv_uuid[UUID_LEN+1]; -} pv32_t; - -typedef struct { - char lv_name[NAME_LEN]; - u32 lv; -} lv_req32_t; - -typedef struct { - u32 lv_index; - u32 lv; - /* Transfer size because user space and kernel space differ */ - uint16_t size; -} lv_status_byindex_req32_t; - -typedef struct { - compat_dev_t dev; - u32 lv; -} lv_status_bydev_req32_t; - -typedef struct { - uint8_t lv_name[NAME_LEN]; - kdev_t old_dev; - kdev_t new_dev; - u32 old_pe; - u32 new_pe; -} le_remap_req32_t; - -typedef struct { - char pv_name[NAME_LEN]; - u32 pv; -} pv_status_req32_t; - -typedef struct { - uint8_t lv_name[NAME_LEN]; - uint8_t vg_name[NAME_LEN]; - uint32_t lv_access; - uint32_t lv_status; - uint32_t lv_open; - kdev_t lv_dev; - uint32_t lv_number; - uint32_t lv_mirror_copies; - uint32_t lv_recovery; - uint32_t lv_schedule; - uint32_t lv_size; - u32 lv_current_pe; - uint32_t lv_current_le; - uint32_t lv_allocated_le; - uint32_t lv_stripes; - uint32_t lv_stripesize; - uint32_t lv_badblock; - uint32_t lv_allocation; - uint32_t lv_io_timeout; - uint32_t lv_read_ahead; - /* delta to version 1 starts here */ - u32 lv_snapshot_org; - u32 lv_snapshot_prev; - u32 lv_snapshot_next; - u32 lv_block_exception; - uint32_t lv_remap_ptr; - uint32_t lv_remap_end; - uint32_t lv_chunk_size; - uint32_t lv_snapshot_minor; - char dummy[200]; -} lv32_t; - -typedef struct { - u32 hash[2]; - u32 rsector_org; - kdev_t rdev_org; - u32 rsector_new; - kdev_t rdev_new; -} lv_block_exception32_t; - -static void put_lv_t(lv_t *l) -{ - if (l->lv_current_pe) vfree(l->lv_current_pe); - if (l->lv_block_exception) vfree(l->lv_block_exception); - kfree(l); -} - -static lv_t *get_lv_t(u32 p, int *errp) -{ - int err, i; - u32 ptr1, ptr2; - size_t size; - lv_block_exception32_t __user *lbe32; - lv_block_exception_t *lbe; - lv32_t __user *ul = A(p); - lv_t *l = (lv_t *) kmalloc(sizeof(lv_t), GFP_KERNEL); - - if (!l) { - *errp = -ENOMEM; - return NULL; - } - memset(l, 0, sizeof(lv_t)); - err = copy_from_user(l, ul, (long)&((lv32_t *)0)->lv_current_pe); - err |= __copy_from_user(&l->lv_current_le, &ul->lv_current_le, - ((long)&ul->lv_snapshot_org) - ((long)&ul->lv_current_le)); - err |= __copy_from_user(&l->lv_remap_ptr, &ul->lv_remap_ptr, - ((long)&ul->dummy[0]) - ((long)&ul->lv_remap_ptr)); - err |= __get_user(ptr1, &ul->lv_current_pe); - err |= __get_user(ptr2, &ul->lv_block_exception); - if (err) { - kfree(l); - *errp = -EFAULT; - return NULL; - } - if (ptr1) { - size = l->lv_allocated_le * sizeof(pe_t); - l->lv_current_pe = vmalloc(size); - if (l->lv_current_pe) - err = copy_from_user(l->lv_current_pe, A(ptr1), size); - } - if (!err && ptr2) { - size = l->lv_remap_end * sizeof(lv_block_exception_t); - l->lv_block_exception = lbe = vmalloc(size); - if (l->lv_block_exception) { - lbe32 = A(ptr2); - memset(lbe, 0, size); - for (i = 0; i < l->lv_remap_end; i++, lbe++, lbe32++) { - err |= get_user(lbe->rsector_org, &lbe32->rsector_org); - err |= __get_user(lbe->rdev_org, &lbe32->rdev_org); - err |= __get_user(lbe->rsector_new, &lbe32->rsector_new); - err |= __get_user(lbe->rdev_new, &lbe32->rdev_new); - } - } - } - if (err || (ptr1 && !l->lv_current_pe) || (ptr2 && !l->lv_block_exception)) { - if (!err) - *errp = -ENOMEM; - else - *errp = -EFAULT; - put_lv_t(l); - return NULL; - } - return l; -} - -static int copy_lv_t(u32 ptr, lv_t *l) -{ - int err; - lv32_t __user *ul = A(ptr); - u32 ptr1; - size_t size; - - err = get_user(ptr1, &ul->lv_current_pe); - if (err) - return -EFAULT; - err = copy_to_user(ul, l, (long)&((lv32_t *)0)->lv_current_pe); - err |= __copy_to_user(&ul->lv_current_le, &l->lv_current_le, - ((long)&ul->lv_snapshot_org) - ((long)&ul->lv_current_le)); - err |= __copy_to_user(&ul->lv_remap_ptr, &l->lv_remap_ptr, - ((long)&ul->dummy[0]) - ((long)&ul->lv_remap_ptr)); - size = l->lv_allocated_le * sizeof(pe_t); - if (ptr1) - err |= __copy_to_user(A(ptr1), l->lv_current_pe, size); - return err ? -EFAULT : 0; -} - -static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - vg_t *v = NULL; - union { - lv_req_t lv_req; - le_remap_req_t le_remap; - lv_status_byindex_req_t lv_byindex; - lv_status_bydev_req_t lv_bydev; - pv_status_req_t pv_status; - } u; - pv_t p; - int err; - u32 ptr = 0; - int i; - mm_segment_t old_fs; - void *karg = &u; - - switch (cmd) { - case VG_STATUS: - v = kmalloc(sizeof(vg_t), GFP_KERNEL); - if (!v) - return -ENOMEM; - karg = v; - break; - - case VG_CREATE_OLD: - case VG_CREATE: - v = kmalloc(sizeof(vg_t), GFP_KERNEL); - if (!v) - return -ENOMEM; - if (copy_from_user(v, (void *)arg, (long)&((vg32_t *)0)->proc)) { - kfree(v); - return -EFAULT; - } - /* 'proc' field is unused, just NULL it out. */ - v->proc = NULL; - if (copy_from_user(v->vg_uuid, ((vg32_t *)arg)->vg_uuid, UUID_LEN+1)) { - kfree(v); - return -EFAULT; - } - - karg = v; - memset(v->pv, 0, sizeof(v->pv) + sizeof(v->lv)); - if (v->pv_max > ABS_MAX_PV || v->lv_max > ABS_MAX_LV) - return -EPERM; - for (i = 0; i < v->pv_max; i++) { - err = __get_user(ptr, &((vg32_t *)arg)->pv[i]); - if (err) - break; - if (ptr) { - v->pv[i] = kmalloc(sizeof(pv_t), GFP_KERNEL); - if (!v->pv[i]) { - err = -ENOMEM; - break; - } - err = copy_from_user(v->pv[i], A(ptr), - sizeof(pv32_t) - 8 - UUID_LEN+1); - if (err) { - err = -EFAULT; - break; - } - err = copy_from_user(&v->pv[i]->pv_uuid[0], - &((pv32_t __user *)A(ptr))->pv_uuid[0], - UUID_LEN+1); - if (err) { - err = -EFAULT; - break; - } - - v->pv[i]->pe = NULL; - v->pv[i]->bd = NULL; - } - } - if (!err) { - for (i = 0; i < v->lv_max; i++) { - err = __get_user(ptr, &((vg32_t *)arg)->lv[i]); - if (err) - break; - if (ptr) { - v->lv[i] = get_lv_t(ptr, &err); - if (err) - break; - } - } - } - break; - - case LV_CREATE: - case LV_EXTEND: - case LV_REDUCE: - case LV_REMOVE: - case LV_RENAME: - case LV_STATUS_BYNAME: - err = copy_from_user(&u.pv_status, arg, sizeof(u.pv_status.pv_name)); - if (err) - return -EFAULT; - if (cmd != LV_REMOVE) { - err = __get_user(ptr, &((lv_req32_t *)arg)->lv); - if (err) - return err; - u.lv_req.lv = get_lv_t(ptr, &err); - } else - u.lv_req.lv = NULL; - break; - - case LV_STATUS_BYINDEX: - err = get_user(u.lv_byindex.lv_index, - &((lv_status_byindex_req32_t *)arg)->lv_index); - err |= __get_user(ptr, &((lv_status_byindex_req32_t *)arg)->lv); - if (err) - return err; - u.lv_byindex.lv = get_lv_t(ptr, &err); - break; - - case LV_STATUS_BYDEV: - err = get_user(u.lv_bydev.dev, &((lv_status_bydev_req32_t *)arg)->dev); - err |= __get_user(ptr, &((lv_status_bydev_req32_t *)arg)->lv); - if (err) - return err; - u.lv_bydev.lv = get_lv_t(ptr, &err); - break; - - case VG_EXTEND: - err = copy_from_user(&p, (void *)arg, sizeof(pv32_t) - 8 - UUID_LEN+1); - if (err) - return -EFAULT; - err = copy_from_user(p.pv_uuid, ((pv32_t *)arg)->pv_uuid, UUID_LEN+1); - if (err) - return -EFAULT; - p.pe = NULL; - p.bd = NULL; - karg = &p; - break; - - case PV_CHANGE: - case PV_STATUS: - err = copy_from_user(&u.pv_status, arg, sizeof(u.lv_req.lv_name)); - if (err) - return -EFAULT; - err = __get_user(ptr, &((pv_status_req32_t *)arg)->pv); - if (err) - return err; - u.pv_status.pv = &p; - if (cmd == PV_CHANGE) { - err = copy_from_user(&p, A(ptr), - sizeof(pv32_t) - 8 - UUID_LEN+1); - if (err) - return -EFAULT; - p.pe = NULL; - p.bd = NULL; - } - break; - }; - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)karg); - set_fs (old_fs); - - switch (cmd) { - case VG_STATUS: - if (!err) { - if (copy_to_user((void *)arg, v, (long)&((vg32_t *)0)->proc) || - clear_user(&((vg32_t *)arg)->proc, sizeof(vg32_t) - (long)&((vg32_t *)0)->proc)) - err = -EFAULT; - } - if (copy_to_user(((vg32_t *)arg)->vg_uuid, v->vg_uuid, UUID_LEN+1)) { - err = -EFAULT; - } - kfree(v); - break; - - case VG_CREATE_OLD: - case VG_CREATE: - for (i = 0; i < v->pv_max; i++) { - if (v->pv[i]) - kfree(v->pv[i]); - } - for (i = 0; i < v->lv_max; i++) { - if (v->lv[i]) - put_lv_t(v->lv[i]); - } - kfree(v); - break; - - case LV_STATUS_BYNAME: - if (!err && u.lv_req.lv) - err = copy_lv_t(ptr, u.lv_req.lv); - /* Fall through */ - - case LV_CREATE: - case LV_EXTEND: - case LV_REDUCE: - if (u.lv_req.lv) - put_lv_t(u.lv_req.lv); - break; - - case LV_STATUS_BYINDEX: - if (u.lv_byindex.lv) { - if (!err) - err = copy_lv_t(ptr, u.lv_byindex.lv); - put_lv_t(u.lv_byindex.lv); - } - break; - - case LV_STATUS_BYDEV: - if (u.lv_bydev.lv) { - if (!err) - err = copy_lv_t(ptr, u.lv_bydev.lv); - put_lv_t(u.lv_byindex.lv); - } - break; - - case PV_STATUS: - if (!err) { - err = copy_to_user(A(ptr), &p, sizeof(pv32_t) - 8 - UUID_LEN+1); - if (err) - return -EFAULT; - err = copy_to_user(&((pv_t __user *)A(ptr))->pv_uuid[0], &p.pv_uuid[0], UUID_LEN + 1); - if (err) - return -EFAULT; - } - break; - }; - - return err; -} -#endif - #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) /* This really belongs in include/linux/drm.h -DaveM */ #include "../../../drivers/char/drm/drm.h" @@ -4887,28 +4447,6 @@ COMPATIBLE_IOCTL(ATMTCP_REMOVE) COMPATIBLE_IOCTL(ATMMPC_CTRL) COMPATIBLE_IOCTL(ATMMPC_DATA) -#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) -/* 0xfe - lvm */ -COMPATIBLE_IOCTL(VG_SET_EXTENDABLE) -COMPATIBLE_IOCTL(VG_STATUS_GET_COUNT) -COMPATIBLE_IOCTL(VG_STATUS_GET_NAMELIST) -COMPATIBLE_IOCTL(VG_REMOVE) -COMPATIBLE_IOCTL(VG_RENAME) -COMPATIBLE_IOCTL(VG_REDUCE) -COMPATIBLE_IOCTL(PE_LOCK_UNLOCK) -COMPATIBLE_IOCTL(PV_FLUSH) -COMPATIBLE_IOCTL(LVM_LOCK_LVM) -COMPATIBLE_IOCTL(LVM_GET_IOP_VERSION) -#ifdef LVM_TOTAL_RESET -COMPATIBLE_IOCTL(LVM_RESET) -#endif -COMPATIBLE_IOCTL(LV_SET_ACCESS) -COMPATIBLE_IOCTL(LV_SET_STATUS) -COMPATIBLE_IOCTL(LV_SET_ALLOCATION) -COMPATIBLE_IOCTL(LE_REMAP) -COMPATIBLE_IOCTL(LV_BMAP) -COMPATIBLE_IOCTL(LV_SNAPSHOT_USE_RATE) -#endif /* LVM */ #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID) @@ -5172,22 +4710,6 @@ HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl) HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl) HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) -#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) -HANDLE_IOCTL(VG_STATUS, do_lvm_ioctl) -HANDLE_IOCTL(VG_CREATE_OLD, do_lvm_ioctl) -HANDLE_IOCTL(VG_CREATE, do_lvm_ioctl) -HANDLE_IOCTL(VG_EXTEND, do_lvm_ioctl) -HANDLE_IOCTL(LV_CREATE, do_lvm_ioctl) -HANDLE_IOCTL(LV_REMOVE, do_lvm_ioctl) -HANDLE_IOCTL(LV_EXTEND, do_lvm_ioctl) -HANDLE_IOCTL(LV_REDUCE, do_lvm_ioctl) -HANDLE_IOCTL(LV_RENAME, do_lvm_ioctl) -HANDLE_IOCTL(LV_STATUS_BYNAME, do_lvm_ioctl) -HANDLE_IOCTL(LV_STATUS_BYINDEX, do_lvm_ioctl) -HANDLE_IOCTL(LV_STATUS_BYDEV, do_lvm_ioctl) -HANDLE_IOCTL(PV_CHANGE, do_lvm_ioctl) -HANDLE_IOCTL(PV_STATUS, do_lvm_ioctl) -#endif /* LVM */ #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version) HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique) diff -urN linux-2.5.67-bk9/arch/sparc64/kernel/sys_sunos32.c linux-2.5.67-bk10/arch/sparc64/kernel/sys_sunos32.c --- linux-2.5.67-bk9/arch/sparc64/kernel/sys_sunos32.c 2003-04-07 10:31:51.000000000 -0700 +++ linux-2.5.67-bk10/arch/sparc64/kernel/sys_sunos32.c 2003-04-19 04:35:36.000000000 -0700 @@ -800,15 +800,16 @@ } /* So stupid... */ -extern asmlinkage int sys32_wait4(compat_pid_t pid, - u32 stat_addr, int options, u32 ru); +extern long compat_sys_wait4(compat_pid_t, compat_uint_t *, int, + struct compat_rusage *); asmlinkage int sunos_wait4(compat_pid_t pid, u32 stat_addr, int options, u32 ru) { int ret; - ret = sys32_wait4((pid ? pid : ((compat_pid_t)-1)), - stat_addr, options, ru); + ret = compat_sys_wait4((pid ? pid : ((compat_pid_t)-1)), + (compat_uint_t *)A(stat_addr), options, + (struct compat_rusage *)A(ru)); return ret; } diff -urN linux-2.5.67-bk9/arch/sparc64/kernel/systbls.S linux-2.5.67-bk10/arch/sparc64/kernel/systbls.S --- linux-2.5.67-bk9/arch/sparc64/kernel/systbls.S 2003-04-19 04:35:28.000000000 -0700 +++ linux-2.5.67-bk10/arch/sparc64/kernel/systbls.S 2003-04-19 04:35:36.000000000 -0700 @@ -180,7 +180,7 @@ .word sys_listen, sunos_nosys, sunos_sigaction .word sunos_sigblock, sunos_sigsetmask, sys_sigpause .word sys32_sigstack, compat_sys_recvmsg, compat_sys_sendmsg - .word sunos_nosys, sys32_gettimeofday, sys32_getrusage + .word sunos_nosys, sys32_gettimeofday, compat_sys_getrusage .word sunos_getsockopt, sunos_nosys, sunos_readv .word sunos_writev, sys32_settimeofday, sys32_fchown16 .word sys_fchmod, sys32_recvfrom, sys32_setreuid16 @@ -189,8 +189,8 @@ .word sys32_sendto, sys_shutdown, sys_socketpair .word sys_mkdir, sys_rmdir, sys32_utimes .word sys32_sigreturn, sunos_nosys, sys_getpeername - .word sunos_gethostid, sunos_nosys, sys32_getrlimit - .word sys32_setrlimit, sunos_killpg, sunos_nosys + .word sunos_gethostid, sunos_nosys, compat_sys_getrlimit + .word compat_sys_setrlimit, sunos_killpg, sunos_nosys .word sunos_nosys, sunos_nosys /*150*/ .word sys_getsockname, sunos_nosys, sunos_nosys .word sys_poll, sunos_nosys, sunos_nosys diff -urN linux-2.5.67-bk9/drivers/block/cpqarray.c linux-2.5.67-bk10/drivers/block/cpqarray.c --- linux-2.5.67-bk9/drivers/block/cpqarray.c 2003-04-07 10:30:43.000000000 -0700 +++ linux-2.5.67-bk10/drivers/block/cpqarray.c 2003-04-19 04:35:36.000000000 -0700 @@ -400,7 +400,6 @@ sprintf(disk->disk_name, "ida/c%dd%d", i, j); disk->major = COMPAQ_SMART2_MAJOR + i; disk->first_minor = j<flags = GENHD_FL_DEVFS; disk->fops = &ida_fops; if (!drv->nr_blks) continue; @@ -1678,10 +1677,9 @@ return; } - if (!disk->de) { - disk->de = devfs_mk_dir("ida/c%dd%d", - ctlr, log_unit); - } + + sprintf(disk->devfs_name, "ida/c%dd%d", ctlr, log_unit); + info_p->phys_drives = sense_config_buf->ctlr_phys_drv; info_p->drv_assign_map diff -urN linux-2.5.67-bk9/drivers/block/loop.c linux-2.5.67-bk10/drivers/block/loop.c --- linux-2.5.67-bk9/drivers/block/loop.c 2003-04-07 10:31:46.000000000 -0700 +++ linux-2.5.67-bk10/drivers/block/loop.c 2003-04-19 04:35:36.000000000 -0700 @@ -120,13 +120,13 @@ return 0; } -static int none_status(struct loop_device *lo, struct loop_info *info) +static int none_status(struct loop_device *lo, const struct loop_info64 *info) { lo->lo_flags |= LO_FLAGS_BH_REMAP; return 0; } -static int xor_status(struct loop_device *lo, struct loop_info *info) +static int xor_status(struct loop_device *lo, const struct loop_info64 *info) { if (info->lo_encrypt_key_size <= 0) return -EINVAL; @@ -215,7 +215,8 @@ * The transfer failed, but we still write the data to * keep prepare/commit calls balanced. */ - printk(KERN_ERR "loop: transfer error block %llu\n", (unsigned long long)index); + printk(KERN_ERR "loop: transfer error block %llu\n", + (unsigned long long)index); memset(kaddr + offset, 0, size); } flush_dcache_page(page); @@ -270,7 +271,9 @@ int bsize; }; -static int lo_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size) +static int +lo_read_actor(read_descriptor_t *desc, struct page *page, + unsigned long offset, unsigned long size) { char *kaddr; unsigned long count = desc->count; @@ -284,7 +287,8 @@ kaddr = kmap(page); if (lo_do_transfer(lo, READ, kaddr + offset, p->data, size, IV)) { size = 0; - printk(KERN_ERR "loop: transfer error block %ld\n",page->index); + printk(KERN_ERR "loop: transfer error block %ld\n", + page->index); desc->error = -EINVAL; } kunmap(page); @@ -297,7 +301,7 @@ static int do_lo_receive(struct loop_device *lo, - struct bio_vec *bvec, int bsize, loff_t pos) + struct bio_vec *bvec, int bsize, loff_t pos) { struct lo_read_data cookie; struct file *file; @@ -330,8 +334,8 @@ return ret; } -static inline unsigned long loop_get_iv(struct loop_device *lo, - unsigned long sector) +static inline unsigned long +loop_get_iv(struct loop_device *lo, unsigned long sector) { int bs = lo->lo_blocksize; unsigned long offset, IV; @@ -358,6 +362,7 @@ } static int loop_end_io_transfer(struct bio *, unsigned int, int); + static void loop_put_buffer(struct bio *bio) { /* @@ -764,7 +769,8 @@ return err; } -static int loop_init_xfer(struct loop_device *lo, int type,struct loop_info *i) +static int +loop_init_xfer(struct loop_device *lo, int type, const struct loop_info64 *i) { int err = 0; if (type) { @@ -822,9 +828,9 @@ return 0; } -static int loop_set_status(struct loop_device *lo, struct loop_info *arg) +static int +loop_set_status(struct loop_device *lo, const struct loop_info64 *info) { - struct loop_info info; int err; unsigned int type; loff_t offset; @@ -834,23 +840,21 @@ return -EPERM; if (lo->lo_state != Lo_bound) return -ENXIO; - if (copy_from_user(&info, arg, sizeof (struct loop_info))) - return -EFAULT; - if ((unsigned int) info.lo_encrypt_key_size > LO_KEY_SIZE) + if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE) return -EINVAL; - type = info.lo_encrypt_type; + type = info->lo_encrypt_type; if (type >= MAX_LO_CRYPT || xfer_funcs[type] == NULL) return -EINVAL; - if (type == LO_CRYPT_XOR && info.lo_encrypt_key_size == 0) + if (type == LO_CRYPT_XOR && info->lo_encrypt_key_size == 0) return -EINVAL; err = loop_release_xfer(lo); if (!err) - err = loop_init_xfer(lo, type, &info); + err = loop_init_xfer(lo, type, info); offset = lo->lo_offset; - if (offset != info.lo_offset) { - lo->lo_offset = info.lo_offset; + if (offset != info->lo_offset) { + lo->lo_offset = info->lo_offset; if (figure_loop_size(lo)){ err = -EFBIG; lo->lo_offset = offset; @@ -860,51 +864,147 @@ if (err) return err; - strncpy(lo->lo_name, info.lo_name, LO_NAME_SIZE); + strncpy(lo->lo_name, info->lo_name, LO_NAME_SIZE); lo->transfer = xfer_funcs[type]->transfer; lo->ioctl = xfer_funcs[type]->ioctl; - lo->lo_encrypt_key_size = info.lo_encrypt_key_size; - lo->lo_init[0] = info.lo_init[0]; - lo->lo_init[1] = info.lo_init[1]; - if (info.lo_encrypt_key_size) { - memcpy(lo->lo_encrypt_key, info.lo_encrypt_key, - info.lo_encrypt_key_size); + lo->lo_encrypt_key_size = info->lo_encrypt_key_size; + lo->lo_init[0] = info->lo_init[0]; + lo->lo_init[1] = info->lo_init[1]; + if (info->lo_encrypt_key_size) { + memcpy(lo->lo_encrypt_key, info->lo_encrypt_key, + info->lo_encrypt_key_size); lo->lo_key_owner = current->uid; } return 0; } -static int loop_get_status(struct loop_device *lo, struct loop_info *arg) +static int +loop_get_status(struct loop_device *lo, struct loop_info64 *info) { struct file *file = lo->lo_backing_file; - struct loop_info info; struct kstat stat; int error; if (lo->lo_state != Lo_bound) return -ENXIO; - if (!arg) - return -EINVAL; error = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat); if (error) return error; - memset(&info, 0, sizeof(info)); - info.lo_number = lo->lo_number; - info.lo_device = stat.dev; - info.lo_inode = stat.ino; - info.lo_rdevice = lo->lo_device ? stat.rdev : stat.dev; - info.lo_offset = lo->lo_offset; - info.lo_flags = lo->lo_flags; - strncpy(info.lo_name, lo->lo_name, LO_NAME_SIZE); - info.lo_encrypt_type = lo->lo_encrypt_type; + memset(info, 0, sizeof(*info)); + info->lo_number = lo->lo_number; + info->lo_device = stat.dev; + info->lo_inode = stat.ino; + info->lo_rdevice = lo->lo_device ? stat.rdev : stat.dev; + info->lo_offset = lo->lo_offset; + info->lo_flags = lo->lo_flags; + strncpy(info->lo_name, lo->lo_name, LO_NAME_SIZE); + info->lo_encrypt_type = lo->lo_encrypt_type; if (lo->lo_encrypt_key_size && capable(CAP_SYS_ADMIN)) { - info.lo_encrypt_key_size = lo->lo_encrypt_key_size; - memcpy(info.lo_encrypt_key, lo->lo_encrypt_key, + info->lo_encrypt_key_size = lo->lo_encrypt_key_size; + memcpy(info->lo_encrypt_key, lo->lo_encrypt_key, lo->lo_encrypt_key_size); } - return copy_to_user(arg, &info, sizeof(info)) ? -EFAULT : 0; + return 0; +} + +static void +loop_info64_from_old(const struct loop_info *info, struct loop_info64 *info64) +{ + info64->lo_number = info->lo_number; + info64->lo_device = info->lo_device; + info64->lo_inode = info->lo_inode; + info64->lo_rdevice = info->lo_rdevice; + info64->lo_offset = info->lo_offset; + info64->lo_encrypt_type = info->lo_encrypt_type; + info64->lo_encrypt_key_size = info->lo_encrypt_key_size; + info64->lo_flags = info->lo_flags; + info64->lo_init[0] = info->lo_init[0]; + info64->lo_init[1] = info->lo_init[1]; + memcpy(info64->lo_name, info->lo_name, LO_NAME_SIZE); + memcpy(info64->lo_encrypt_key, info->lo_encrypt_key, LO_KEY_SIZE); +} + +static int +loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info) +{ + info->lo_number = info64->lo_number; + info->lo_device = info64->lo_device; + info->lo_inode = info64->lo_inode; + info->lo_rdevice = info64->lo_rdevice; + info->lo_offset = info64->lo_offset; + info->lo_encrypt_type = info64->lo_encrypt_type; + info->lo_encrypt_key_size = info64->lo_encrypt_key_size; + info->lo_flags = info64->lo_flags; + info->lo_init[0] = info64->lo_init[0]; + info->lo_init[1] = info64->lo_init[1]; + memcpy(info->lo_name, info64->lo_name, LO_NAME_SIZE); + memcpy(info->lo_encrypt_key,info64->lo_encrypt_key,LO_KEY_SIZE); + + /* error in case values were truncated */ + if (info->lo_device != info64->lo_device || + info->lo_rdevice != info64->lo_rdevice || + info->lo_inode != info64->lo_inode || + info->lo_offset != info64->lo_offset) + return -EOVERFLOW; + + return 0; +} + +static int +loop_set_status_old(struct loop_device *lo, const struct loop_info *arg) +{ + struct loop_info info; + struct loop_info64 info64; + + if (copy_from_user(&info, arg, sizeof (struct loop_info))) + return -EFAULT; + loop_info64_from_old(&info, &info64); + return loop_set_status(lo, &info64); +} + +static int +loop_set_status64(struct loop_device *lo, const struct loop_info64 *arg) +{ + struct loop_info64 info64; + + if (copy_from_user(&info64, arg, sizeof (struct loop_info64))) + return -EFAULT; + return loop_set_status(lo, &info64); +} + +static int +loop_get_status_old(struct loop_device *lo, struct loop_info *arg) { + struct loop_info info; + struct loop_info64 info64; + int err = 0; + + if (!arg) + err = -EINVAL; + if (!err) + err = loop_get_status(lo, &info64); + if (!err) + err = loop_info64_to_old(&info64, &info); + if (!err && copy_to_user(arg, &info, sizeof(info))) + err = -EFAULT; + + return err; +} + +static int +loop_get_status64(struct loop_device *lo, struct loop_info64 *arg) { + struct loop_info64 info64; + int err = 0; + + if (!arg) + err = -EINVAL; + if (!err) + err = loop_get_status(lo, &info64); + if (!err && copy_to_user(arg, &info64, sizeof(info64))) + err = -EFAULT; + + return err; } static int lo_ioctl(struct inode * inode, struct file * file, @@ -922,10 +1022,16 @@ err = loop_clr_fd(lo, inode->i_bdev); break; case LOOP_SET_STATUS: - err = loop_set_status(lo, (struct loop_info *) arg); + err = loop_set_status_old(lo, (struct loop_info *) arg); break; case LOOP_GET_STATUS: - err = loop_get_status(lo, (struct loop_info *) arg); + err = loop_get_status_old(lo, (struct loop_info *) arg); + break; + case LOOP_SET_STATUS64: + err = loop_set_status64(lo, (struct loop_info64 *) arg); + break; + case LOOP_GET_STATUS64: + err = loop_get_status64(lo, (struct loop_info64 *) arg); break; default: err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; diff -urN linux-2.5.67-bk9/drivers/cdrom/sbpcd.c linux-2.5.67-bk10/drivers/cdrom/sbpcd.c --- linux-2.5.67-bk9/drivers/cdrom/sbpcd.c 2003-04-07 10:30:44.000000000 -0700 +++ linux-2.5.67-bk10/drivers/cdrom/sbpcd.c 2003-04-19 04:35:36.000000000 -0700 @@ -5645,7 +5645,6 @@ int __init sbpcd_init(void) #endif { - char nbuff[16]; int i=0, j=0; int addr[2]={1, CDROM_PORT}; int port_index; @@ -5869,8 +5868,7 @@ disk->fops = &sbpcd_bdops; strcpy(disk->disk_name, sbpcd_infop->name); disk->flags = GENHD_FL_CD; - sprintf(nbuff, "sbp/c0t%d", p->drv_id); - disk->de = devfs_mk_dir(NULL, nbuff, NULL); + sprintf(disk->devfs_name, "sbp/c0t%d", p->drv_id); p->disk = disk; if (register_cdrom(sbpcd_infop)) { diff -urN linux-2.5.67-bk9/drivers/char/misc.c linux-2.5.67-bk10/drivers/char/misc.c --- linux-2.5.67-bk9/drivers/char/misc.c 2003-04-07 10:32:50.000000000 -0700 +++ linux-2.5.67-bk10/drivers/char/misc.c 2003-04-19 04:35:36.000000000 -0700 @@ -166,8 +166,8 @@ int misc_register(struct miscdevice * misc) { - static devfs_handle_t devfs_handle, dir; struct miscdevice *c; + char buf[256]; if (misc->next || misc->prev) return -EBUSY; @@ -195,14 +195,16 @@ } if (misc->minor < DYNAMIC_MINORS) misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); - if (!devfs_handle) - devfs_handle = devfs_mk_dir("misc"); - dir = strchr (misc->name, '/') ? NULL : devfs_handle; - misc->devfs_handle = - devfs_register (dir, misc->name, DEVFS_FL_NONE, - MISC_MAJOR, misc->minor, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, - misc->fops, NULL); + + + /* yuck, yet another stupid special-casing. We should rather + add ->devfs_name to avoid this mess. */ + snprintf(buf, sizeof(buf), strchr(misc->name, '/') ? + "%s" : "misc/%s", misc->name); + misc->devfs_handle = devfs_register(NULL, buf, 0, + MISC_MAJOR, misc->minor, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, + misc->fops, NULL); /* * Add it to the front, so that later devices can "override" diff -urN linux-2.5.67-bk9/drivers/ide/ide-cd.c linux-2.5.67-bk10/drivers/ide/ide-cd.c --- linux-2.5.67-bk9/drivers/ide/ide-cd.c 2003-04-07 10:31:13.000000000 -0700 +++ linux-2.5.67-bk10/drivers/ide/ide-cd.c 2003-04-19 04:35:36.000000000 -0700 @@ -3366,7 +3366,7 @@ DRIVER(drive)->busy++; g->minors = 1; g->minor_shift = 0; - g->de = drive->de; + strcpy(g->devfs_name, drive->devfs_name); g->driverfs_dev = &drive->gendev; g->flags = GENHD_FL_CD; if (ide_cdrom_setup(drive)) { diff -urN linux-2.5.67-bk9/drivers/ide/ide-disk.c linux-2.5.67-bk10/drivers/ide/ide-disk.c --- linux-2.5.67-bk9/drivers/ide/ide-disk.c 2003-04-07 10:31:06.000000000 -0700 +++ linux-2.5.67-bk10/drivers/ide/ide-disk.c 2003-04-19 04:35:36.000000000 -0700 @@ -1816,10 +1816,9 @@ DRIVER(drive)->busy--; g->minors = 1 << PARTN_BITS; g->minor_shift = PARTN_BITS; - g->de = drive->de; + strcpy(g->devfs_name, drive->devfs_name); g->driverfs_dev = &drive->gendev; g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0; - g->flags |= GENHD_FL_DEVFS; set_capacity(g, current_capacity(drive)); g->fops = &idedisk_ops; add_disk(g); diff -urN linux-2.5.67-bk9/drivers/ide/ide-floppy.c linux-2.5.67-bk10/drivers/ide/ide-floppy.c --- linux-2.5.67-bk9/drivers/ide/ide-floppy.c 2003-04-07 10:31:20.000000000 -0700 +++ linux-2.5.67-bk10/drivers/ide/ide-floppy.c 2003-04-19 04:35:36.000000000 -0700 @@ -2059,9 +2059,8 @@ g->minors = 1 << PARTN_BITS; g->minor_shift = PARTN_BITS; g->driverfs_dev = &drive->gendev; - g->de = drive->de; + strcpy(g->devfs_name, drive->devfs_name); g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0; - g->flags |= GENHD_FL_DEVFS; g->fops = &idefloppy_ops; add_disk(g); return 0; diff -urN linux-2.5.67-bk9/drivers/ide/ide-io.c linux-2.5.67-bk10/drivers/ide/ide-io.c --- linux-2.5.67-bk9/drivers/ide/ide-io.c 2003-04-07 10:32:26.000000000 -0700 +++ linux-2.5.67-bk10/drivers/ide/ide-io.c 2003-04-19 04:35:36.000000000 -0700 @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include diff -urN linux-2.5.67-bk9/drivers/ide/ide-probe.c linux-2.5.67-bk10/drivers/ide/ide-probe.c --- linux-2.5.67-bk9/drivers/ide/ide-probe.c 2003-04-19 04:35:28.000000000 -0700 +++ linux-2.5.67-bk10/drivers/ide/ide-probe.c 2003-04-19 04:35:36.000000000 -0700 @@ -1289,7 +1289,6 @@ for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t * drive = &hwif->drives[unit]; - char name[64]; ide_add_generic_settings(drive); snprintf(drive->gendev.bus_id,BUS_ID_SIZE,"%u.%u", hwif->index,unit); @@ -1298,13 +1297,12 @@ drive->gendev.parent = &hwif->gendev; drive->gendev.bus = &ide_bus_type; drive->gendev.driver_data = drive; - sprintf (name, "ide/host%d/bus%d/target%d/lun%d", - (hwif->channel && hwif->mate) ? - hwif->mate->index : hwif->index, - hwif->channel, unit, drive->lun); if (drive->present) { device_register(&drive->gendev); - drive->de = devfs_mk_dir(name); + sprintf(drive->devfs_name, "ide/host%d/bus%d/target%d/lun%d", + (hwif->channel && hwif->mate) ? + hwif->mate->index : hwif->index, + hwif->channel, unit, drive->lun); } } blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS, diff -urN linux-2.5.67-bk9/drivers/ide/ide-tape.c linux-2.5.67-bk10/drivers/ide/ide-tape.c --- linux-2.5.67-bk9/drivers/ide/ide-tape.c 2003-04-07 10:31:00.000000000 -0700 +++ linux-2.5.67-bk10/drivers/ide/ide-tape.c 2003-04-19 04:35:36.000000000 -0700 @@ -866,8 +866,6 @@ */ typedef struct { ide_drive_t *drive; - devfs_handle_t de_r, de_n; - /* * Since a typical character device operation requires more * than one packet command, we provide here enough memory @@ -6170,8 +6168,8 @@ DRIVER(drive)->busy = 0; (void) ide_unregister_subdriver(drive); drive->driver_data = NULL; - devfs_unregister(tape->de_r); - devfs_unregister(tape->de_n); + devfs_remove("%s/mt"); + devfs_remove("%s/mtn"); devfs_unregister_tape(drive->disk->number); kfree (tape); drive->disk->fops = ide_fops; @@ -6272,6 +6270,7 @@ static int idetape_attach (ide_drive_t *drive) { idetape_tape_t *tape; + char devfs_name[64]; int minor; if (!strstr("ide-tape", drive->driver_req)) @@ -6306,17 +6305,20 @@ ; idetape_setup(drive, tape, minor); idetape_chrdevs[minor].drive = drive; - tape->de_r = - devfs_register (drive->de, "mt", DEVFS_FL_DEFAULT, - HWIF(drive)->major, minor, - S_IFCHR | S_IRUGO | S_IWUGO, - &idetape_fops, NULL); - tape->de_n = - devfs_register (drive->de, "mtn", DEVFS_FL_DEFAULT, - HWIF(drive)->major, minor + 128, - S_IFCHR | S_IRUGO | S_IWUGO, - &idetape_fops, NULL); - drive->disk->number = devfs_register_tape(drive->de); + + sprintf(devfs_name, "%s/mt", drive->devfs_name); + tape->de_r = devfs_register (NULL, devfs_name, 0, + HWIF(drive)->major, minor, + S_IFCHR | S_IRUGO | S_IWUGO, + &idetape_fops, NULL); + + sprintf(devfs_name, "%s/mtn", drive->devfs_name); + tape->de_n = devfs_register (NULL, devfs_name, 0, + HWIF(drive)->major, minor + 128, + S_IFCHR | S_IRUGO | S_IWUGO, + &idetape_fops, NULL); + + drive->disk->number = devfs_register_tape(drive->devfs_name); drive->disk->fops = &idetape_block_ops; return 0; failed: diff -urN linux-2.5.67-bk9/drivers/ide/ide.c linux-2.5.67-bk10/drivers/ide/ide.c --- linux-2.5.67-bk9/drivers/ide/ide.c 2003-04-07 10:30:59.000000000 -0700 +++ linux-2.5.67-bk10/drivers/ide/ide.c 2003-04-19 04:35:36.000000000 -0700 @@ -650,9 +650,9 @@ */ for (i = 0; i < MAX_DRIVES; ++i) { drive = &hwif->drives[i]; - if (drive->de) { - devfs_unregister(drive->de); - drive->de = NULL; + if (drive->devfs_name[0] != '\0') { + devfs_remove(drive->devfs_name); + drive->devfs_name[0] = '\0'; } if (!drive->present) continue; diff -urN linux-2.5.67-bk9/drivers/s390/block/dasd.c linux-2.5.67-bk10/drivers/s390/block/dasd.c --- linux-2.5.67-bk9/drivers/s390/block/dasd.c 2003-04-19 04:35:30.000000000 -0700 +++ linux-2.5.67-bk10/drivers/s390/block/dasd.c 2003-04-19 04:35:38.000000000 -0700 @@ -157,9 +157,10 @@ #ifdef CONFIG_DEVFS_FS /* Add a proc directory and the dasd device entry to devfs. */ - device->gdp->de = devfs_mk_dir("dasd/%04x", + sprintf(device->gdp->devfs_name, "dasd/%04x", _ccw_device_get_device_number(device->cdev)); #endif + if (device->ro_flag) devfs_perm = S_IFBLK | S_IRUSR; else diff -urN linux-2.5.67-bk9/drivers/s390/block/dasd_genhd.c linux-2.5.67-bk10/drivers/s390/block/dasd_genhd.c --- linux-2.5.67-bk9/drivers/s390/block/dasd_genhd.c 2003-04-19 04:35:30.000000000 -0700 +++ linux-2.5.67-bk10/drivers/s390/block/dasd_genhd.c 2003-04-19 04:35:39.000000000 -0700 @@ -137,7 +137,6 @@ gdp->major = mi->major; gdp->first_minor = index << DASD_PARTN_BITS; gdp->fops = &dasd_device_operations; - gdp->flags |= GENHD_FL_DEVFS; /* * Set device name. diff -urN linux-2.5.67-bk9/drivers/scsi/osst.c linux-2.5.67-bk10/drivers/scsi/osst.c --- linux-2.5.67-bk9/drivers/scsi/osst.c 2003-04-07 10:31:18.000000000 -0700 +++ linux-2.5.67-bk10/drivers/scsi/osst.c 2003-04-19 04:35:40.000000000 -0700 @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -99,6 +100,8 @@ }; #endif +static char *osst_formats[ST_NBR_MODES] ={"", "l", "m", "a"}; + /* Some default definitions have been moved to osst_options.h */ #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE) #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE) @@ -5524,11 +5527,12 @@ write_unlock(&os_scsi_tapes_lock); for (mode = 0; mode < ST_NBR_MODES; ++mode) { - char name[8]; - static char *formats[ST_NBR_MODES] ={"", "l", "m", "a"}; - + char name[8], devfs_name[64]; + /* Rewind entry */ - sprintf (name, "ot%s", formats[mode]); + sprintf(name, "ot%s", osst_formats[mode]); + sprintf(devfs_name, "%s/ot%s", SDp->devfs_name, osst_formats[mode]); + sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s", SDp->sdev_driverfs_dev.bus_id, name); sprintf(tpnt->driverfs_dev_r[mode].name, "%s%s", @@ -5541,13 +5545,14 @@ device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_type); device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev); - tpnt->de_r[mode] = - devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, + devfs_register(NULL, devfs_name, 0, OSST_MAJOR, dev_num + (mode << 5), S_IFCHR | S_IRUGO | S_IWUGO, &osst_fops, NULL); /* No-rewind entry */ - sprintf (name, "ot%sn", formats[mode]); + sprintf (name, "ot%sn", osst_formats[mode]); + sprintf(devfs_name, "%s/ot%sn", SDp->devfs_name, osst_formats[mode]); + sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s", SDp->sdev_driverfs_dev.bus_id, name); sprintf(tpnt->driverfs_dev_n[mode].name, "%s%s", @@ -5561,13 +5566,12 @@ &dev_attr_type); device_create_file(&tpnt->driverfs_dev_n[mode], &dev_attr_kdev); - tpnt->de_n[mode] = - devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, + devfs_register(NULL, devfs_name, 0, OSST_MAJOR, dev_num + (mode << 5) + 128, S_IFCHR | S_IRUGO | S_IWUGO, &osst_fops, NULL); } - drive->number = devfs_register_tape (SDp->de); + drive->number = devfs_register_tape(SDp->devfs_name); printk(KERN_INFO "osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as %s\n", @@ -5595,10 +5599,8 @@ if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) { tpnt->device = NULL; for (mode = 0; mode < ST_NBR_MODES; ++mode) { - devfs_unregister (tpnt->de_r[mode]); - tpnt->de_r[mode] = NULL; - devfs_unregister (tpnt->de_n[mode]); - tpnt->de_n[mode] = NULL; + devfs_remove("%s/ot%s", SDp->devfs_name, osst_formats[mode]); + devfs_remove("%s/ot%sn", SDp->devfs_name, osst_formats[mode]); } devfs_unregister_tape(tpnt->drive->number); put_disk(tpnt->drive); diff -urN linux-2.5.67-bk9/drivers/scsi/osst.h linux-2.5.67-bk10/drivers/scsi/osst.h --- linux-2.5.67-bk9/drivers/scsi/osst.h 2003-04-07 10:31:54.000000000 -0700 +++ linux-2.5.67-bk10/drivers/scsi/osst.h 2003-04-19 04:35:40.000000000 -0700 @@ -5,9 +5,7 @@ #include #include #include -#ifdef CONFIG_DEVFS_FS -#include -#endif + /* FIXME - rename and use the following two types or delete them! * and the types really should go to st.h anyway... @@ -557,8 +555,6 @@ /* Mode characteristics */ ST_mode modes[ST_NBR_MODES]; int current_mode; - devfs_handle_t de_r[ST_NBR_MODES]; /* Rewind entries */ - devfs_handle_t de_n[ST_NBR_MODES]; /* No-rewind entries */ struct device driverfs_dev_r[ST_NBR_MODES]; struct device driverfs_dev_n[ST_NBR_MODES]; diff -urN linux-2.5.67-bk9/drivers/scsi/scsi.h linux-2.5.67-bk10/drivers/scsi/scsi.h --- linux-2.5.67-bk9/drivers/scsi/scsi.h 2003-04-19 04:35:30.000000000 -0700 +++ linux-2.5.67-bk10/drivers/scsi/scsi.h 2003-04-19 04:35:40.000000000 -0700 @@ -16,7 +16,6 @@ #define _SCSI_H #include /* for CONFIG_SCSI_LOGGING */ -#include /* some morons don't know struct pointers */ #include @@ -588,7 +587,7 @@ int access_count; /* Count of open channels/mounts */ void *hostdata; /* available to low-level driver */ - devfs_handle_t de; /* directory for the device */ + char devfs_name[256]; /* devfs junk */ char type; char scsi_level; unsigned char inquiry_len; /* valid bytes in 'inquiry' */ diff -urN linux-2.5.67-bk9/drivers/scsi/scsi_scan.c linux-2.5.67-bk10/drivers/scsi/scsi_scan.c --- linux-2.5.67-bk9/drivers/scsi/scsi_scan.c 2003-04-19 04:35:30.000000000 -0700 +++ linux-2.5.67-bk10/drivers/scsi/scsi_scan.c 2003-04-19 04:35:40.000000000 -0700 @@ -1244,7 +1244,7 @@ scsi_device_register(sdev); - sdev->de = devfs_mk_dir("scsi/host%d/bus%d/target%d/lun%d", + sprintf(sdev->devfs_name, "scsi/host%d/bus%d/target%d/lun%d", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); @@ -1733,7 +1733,7 @@ if (sdev->attached) return -EINVAL; - devfs_unregister(sdev->de); + devfs_remove(sdev->devfs_name); scsi_device_unregister(sdev); scsi_free_sdev(sdev); diff -urN linux-2.5.67-bk9/drivers/scsi/sd.c linux-2.5.67-bk10/drivers/scsi/sd.c --- linux-2.5.67-bk9/drivers/scsi/sd.c 2003-04-19 04:35:30.000000000 -0700 +++ linux-2.5.67-bk10/drivers/scsi/sd.c 2003-04-19 04:35:40.000000000 -0700 @@ -1327,7 +1327,6 @@ sdkp->disk = gd; sdkp->index = index; - gd->de = sdp->de; gd->major = sd_major(index >> 4); gd->first_minor = (index & 15) << 4; gd->minors = 16; @@ -1340,10 +1339,12 @@ sprintf(gd->disk_name, "sd%c", 'a' + index % 26); } + strcpy(gd->devfs_name, sdp->devfs_name); + sd_init_onedisk(sdkp, gd); gd->driverfs_dev = &sdp->sdev_driverfs_dev; - gd->flags = GENHD_FL_DRIVERFS | GENHD_FL_DEVFS; + gd->flags = GENHD_FL_DRIVERFS; if (sdp->removable) gd->flags |= GENHD_FL_REMOVABLE; gd->private_data = &sdkp->driver; diff -urN linux-2.5.67-bk9/drivers/scsi/sg.c linux-2.5.67-bk10/drivers/scsi/sg.c --- linux-2.5.67-bk9/drivers/scsi/sg.c 2003-04-07 10:31:14.000000000 -0700 +++ linux-2.5.67-bk10/drivers/scsi/sg.c 2003-04-19 04:35:40.000000000 -0700 @@ -182,7 +182,6 @@ wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */ int sg_tablesize; /* adapter's max scatter-gather table size */ Sg_fd *headfp; /* first open fd belonging to this device */ - devfs_handle_t de; volatile char detached; /* 0->attached, 1->detached pending removal */ volatile char exclude; /* opened for exclusive access */ char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */ @@ -1350,6 +1349,7 @@ struct gendisk *disk; Sg_device *sdp = NULL; unsigned long iflags; + char devfs_name[64]; int k, error; disk = alloc_disk(1); @@ -1447,10 +1447,13 @@ device_register(&sdp->sg_driverfs_dev); device_create_file(&sdp->sg_driverfs_dev, &dev_attr_type); device_create_file(&sdp->sg_driverfs_dev, &dev_attr_kdev); - sdp->de = devfs_register(scsidp->de, "generic", DEVFS_FL_DEFAULT, - SCSI_GENERIC_MAJOR, k, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, - &sg_fops, sdp); + + sprintf(devfs_name, "%s/generic", scsidp->devfs_name); + devfs_register(NULL, devfs_name, 0, + SCSI_GENERIC_MAJOR, k, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, + &sg_fops, sdp); + switch (scsidp->type) { case TYPE_DISK: case TYPE_MOD: @@ -1527,8 +1530,7 @@ write_unlock_irqrestore(&sg_dev_arr_lock, iflags); if (sdp) { - devfs_unregister(sdp->de); - sdp->de = NULL; + devfs_remove("%s/generic", scsidp->devfs_name); device_remove_file(&sdp->sg_driverfs_dev, &dev_attr_type); device_remove_file(&sdp->sg_driverfs_dev, &dev_attr_kdev); device_unregister(&sdp->sg_driverfs_dev); diff -urN linux-2.5.67-bk9/drivers/scsi/sr.c linux-2.5.67-bk10/drivers/scsi/sr.c --- linux-2.5.67-bk9/drivers/scsi/sr.c 2003-04-07 10:30:57.000000000 -0700 +++ linux-2.5.67-bk10/drivers/scsi/sr.c 2003-04-19 04:35:40.000000000 -0700 @@ -569,7 +569,7 @@ get_capabilities(cd); sr_vendor_init(cd); - disk->de = sdev->de; + strcpy(disk->devfs_name, sdev->devfs_name); disk->driverfs_dev = &sdev->sdev_driverfs_dev; register_cdrom(&cd->cdi); set_capacity(disk, cd->capacity); diff -urN linux-2.5.67-bk9/drivers/scsi/st.c linux-2.5.67-bk10/drivers/scsi/st.c --- linux-2.5.67-bk9/drivers/scsi/st.c 2003-04-19 04:35:30.000000000 -0700 +++ linux-2.5.67-bk10/drivers/scsi/st.c 2003-04-19 04:35:40.000000000 -0700 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -116,6 +117,7 @@ }; #endif +static char *st_formats[ST_NBR_MODES] ={"", "l", "m", "a"}; /* The default definitions have been moved to st_options.h */ @@ -3863,11 +3865,12 @@ write_unlock(&st_dev_arr_lock); for (mode = 0; mode < ST_NBR_MODES; ++mode) { - char name[8]; - static char *formats[ST_NBR_MODES] ={"", "l", "m", "a"}; + char name[8], devfs_name[64]; /* Rewind entry */ - sprintf (name, "mt%s", formats[mode]); + sprintf(name, "mt%s", st_formats[mode]); + sprintf(devfs_name, "%s/mt%s", SDp->devfs_name, st_formats[mode]); + sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s", SDp->sdev_driverfs_dev.bus_id, name); sprintf(tpnt->driverfs_dev_r[mode].name, "%s%s", @@ -3880,13 +3883,14 @@ device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_type); device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev); - tpnt->de_r[mode] = - devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, + devfs_register(NULL, devfs_name, 0, SCSI_TAPE_MAJOR, dev_num + (mode << 5), S_IFCHR | S_IRUGO | S_IWUGO, &st_fops, NULL); /* No-rewind entry */ - sprintf (name, "mt%sn", formats[mode]); + sprintf (name, "mt%sn", st_formats[mode]); + sprintf(devfs_name, "%s/mt%sn", SDp->devfs_name, st_formats[mode]); + sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s", SDp->sdev_driverfs_dev.bus_id, name); sprintf(tpnt->driverfs_dev_n[mode].name, "%s%s", @@ -3900,13 +3904,12 @@ &dev_attr_type); device_create_file(&tpnt->driverfs_dev_n[mode], &dev_attr_kdev); - tpnt->de_n[mode] = - devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, + devfs_register(NULL, devfs_name, 0, SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128, S_IFCHR | S_IRUGO | S_IWUGO, &st_fops, NULL); } - disk->number = devfs_register_tape(SDp->de); + disk->number = devfs_register_tape(SDp->devfs_name); printk(KERN_WARNING "Attached scsi tape %s at scsi%d, channel %d, id %d, lun %d\n", @@ -3939,10 +3942,8 @@ write_unlock(&st_dev_arr_lock); devfs_unregister_tape(tpnt->disk->number); for (mode = 0; mode < ST_NBR_MODES; ++mode) { - devfs_unregister (tpnt->de_r[mode]); - tpnt->de_r[mode] = NULL; - devfs_unregister (tpnt->de_n[mode]); - tpnt->de_n[mode] = NULL; + devfs_remove("%s/mt%s", SDp->devfs_name, st_formats[mode]); + devfs_remove("%s/mt%sn", SDp->devfs_name, st_formats[mode]); device_remove_file(&tpnt->driverfs_dev_r[mode], &dev_attr_type); device_remove_file(&tpnt->driverfs_dev_r[mode], diff -urN linux-2.5.67-bk9/drivers/scsi/st.h linux-2.5.67-bk10/drivers/scsi/st.h --- linux-2.5.67-bk9/drivers/scsi/st.h 2003-04-19 04:35:30.000000000 -0700 +++ linux-2.5.67-bk10/drivers/scsi/st.h 2003-04-19 04:35:40.000000000 -0700 @@ -5,7 +5,6 @@ #ifndef _SCSI_H #include "scsi.h" #endif -#include #include /* The tape buffer descriptor. */ @@ -104,8 +103,6 @@ /* Mode characteristics */ ST_mode modes[ST_NBR_MODES]; int current_mode; - devfs_handle_t de_r[ST_NBR_MODES]; /* Rewind entries */ - devfs_handle_t de_n[ST_NBR_MODES]; /* No-rewind entries */ struct device driverfs_dev_r[ST_NBR_MODES]; struct device driverfs_dev_n[ST_NBR_MODES]; diff -urN linux-2.5.67-bk9/fs/devfs/base.c linux-2.5.67-bk10/fs/devfs/base.c --- linux-2.5.67-bk9/fs/devfs/base.c 2003-04-19 04:35:31.000000000 -0700 +++ linux-2.5.67-bk10/fs/devfs/base.c 2003-04-19 04:35:41.000000000 -0700 @@ -1377,7 +1377,6 @@ * @uid: The user ID. * @gid: The group ID. * @fs_info: The filesystem info. - * @atomic: If TRUE, an atomic allocation is required. * * Returns %TRUE if an event was queued and devfsd woken up, else %FALSE. */ @@ -1423,7 +1422,7 @@ static void devfsd_notify (struct devfs_entry *de,unsigned short type) { devfsd_notify_de(de, type, de->mode, current->euid, - current->egid, &fs_info, 0); + current->egid, &fs_info); } @@ -1456,8 +1455,8 @@ dev_t devnum = 0, dev = MKDEV(major, minor); struct devfs_entry *de; - if (flags) - printk(KERN_ERR "%s called with flags != 0, please fix!\n"); + /* we don't accept any flags anymore. prototype will change soon. */ + WARN_ON(flags); if (name == NULL) { @@ -1748,7 +1747,7 @@ * else a negative error code. */ -int devfs_generate_path (devfs_handle_t de, char *path, int buflen) +static int devfs_generate_path (devfs_handle_t de, char *path, int buflen) { int pos; #define NAMEOF(de) ( (de)->mode ? (de)->name : (de)->u.name ) @@ -1868,7 +1867,6 @@ EXPORT_SYMBOL(devfs_mk_symlink); EXPORT_SYMBOL(devfs_mk_dir); EXPORT_SYMBOL(devfs_remove); -EXPORT_SYMBOL(devfs_generate_path); /** diff -urN linux-2.5.67-bk9/fs/devfs/util.c linux-2.5.67-bk10/fs/devfs/util.c --- linux-2.5.67-bk9/fs/devfs/util.c 2003-04-07 10:31:42.000000000 -0700 +++ linux-2.5.67-bk10/fs/devfs/util.c 2003-04-19 04:35:41.000000000 -0700 @@ -77,28 +77,18 @@ #define PRINTK(format, args...) \ {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);} +int devfs_register_tape(const char *name) +{ + char tname[32], dest[64]; + static unsigned int tape_counter; + unsigned int n = tape_counter++; -/* Private functions follow */ - -/** - * devfs_register_tape - Register a tape device in the "/dev/tapes" hierarchy. - * @de: Any tape device entry in the device directory. - */ + sprintf(dest, "../%s", name); + sprintf(tname, "tapes/tape%u", n); + devfs_mk_symlink(tname, dest); -int devfs_register_tape (devfs_handle_t de) -{ - int pos; - char name[32], dest[64]; - static unsigned int tape_counter; - int n = tape_counter++; - - pos = devfs_generate_path (de, dest + 3, sizeof dest - 3); - if (pos < 0) return -1; - strncpy (dest + pos, "../", 3); - sprintf (name, "tapes/tape%u", n); - devfs_mk_symlink (name, dest + pos); - return n; -} /* End Function devfs_register_tape */ + return n; +} EXPORT_SYMBOL(devfs_register_tape); void devfs_unregister_tape(int num) @@ -356,78 +346,71 @@ static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER; static struct unique_numspace cdrom_numspace = UNIQUE_NUMBERSPACE_INITIALISER; -void devfs_create_partitions(struct gendisk *dev) +void devfs_create_partitions(struct gendisk *disk) { - int pos = 0; - devfs_handle_t dir; - char dirname[64], symlink[16]; - - if (dev->flags & GENHD_FL_DEVFS) { - dir = dev->de; - if (!dir) /* Aware driver wants to block disc management */ - return; - pos = devfs_generate_path(dir, dirname + 3, sizeof dirname-3); - if (pos < 0) - return; - strncpy(dirname + pos, "../", 3); - } else { - /* Unaware driver: construct "real" directory */ - sprintf(dirname, "../%s/disc%d", dev->disk_name, - dev->first_minor >> dev->minor_shift); - dir = devfs_mk_dir(dirname + 3); - dev->de = dir; - } - dev->number = devfs_alloc_unique_number (&disc_numspace); - sprintf(symlink, "discs/disc%d", dev->number); - devfs_mk_symlink(symlink, dirname + pos); - dev->disk_de = devfs_register(dir, "disc", 0, - dev->major, dev->first_minor, - S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); + char dirname[64], diskname[64], symlink[16]; + + if (!disk->devfs_name) + sprintf(disk->devfs_name, "%s/disc%d", disk->disk_name, + disk->first_minor >> disk->minor_shift); + + devfs_mk_dir(disk->devfs_name); + disk->number = devfs_alloc_unique_number(&disc_numspace); + + sprintf(diskname, "%s/disc", disk->devfs_name); + devfs_register(NULL, diskname, 0, + disk->major, disk->first_minor, + S_IFBLK | S_IRUSR | S_IWUSR, + disk->fops, NULL); + + sprintf(symlink, "discs/disc%d", disk->number); + sprintf(dirname, "../%s", disk->devfs_name); + devfs_mk_symlink(symlink, dirname); + } -void devfs_create_cdrom(struct gendisk *dev) +void devfs_create_cdrom(struct gendisk *disk) { - char vname[23]; + char dirname[64], cdname[64], symlink[16]; - dev->number = devfs_alloc_unique_number(&cdrom_numspace); - sprintf(vname, "cdroms/cdrom%d", dev->number); - if (dev->de) { - int pos; - char rname[64]; - - dev->disk_de = devfs_register(dev->de, "cd", DEVFS_FL_DEFAULT, - dev->major, dev->first_minor, - S_IFBLK | S_IRUGO | S_IWUGO, - dev->fops, NULL); - - pos = devfs_generate_path(dev->disk_de, rname+3, sizeof(rname)-3); - if (pos >= 0) { - strncpy(rname + pos, "../", 3); - devfs_mk_symlink(vname, rname + pos); - } - } else { - dev->disk_de = devfs_register (NULL, vname, DEVFS_FL_DEFAULT, - dev->major, dev->first_minor, - S_IFBLK | S_IRUGO | S_IWUGO, - dev->fops, NULL); - } + if (!disk->devfs_name) + strcat(disk->devfs_name, disk->disk_name); + + devfs_mk_dir(disk->devfs_name); + disk->number = devfs_alloc_unique_number(&cdrom_numspace); + + sprintf(cdname, "%s/cd", disk->devfs_name); + devfs_register(NULL, cdname, 0, + disk->major, disk->first_minor, + S_IFBLK | S_IRUGO | S_IWUGO, + disk->fops, NULL); + + sprintf(symlink, "cdroms/cdrom%d", disk->number); + sprintf(dirname, "../%s", disk->devfs_name); + devfs_mk_symlink(symlink, dirname); } -void devfs_remove_partitions(struct gendisk *dev) +void devfs_register_partition(struct gendisk *dev, int part) { - devfs_unregister(dev->disk_de); - dev->disk_de = NULL; + char devname[64]; - if (dev->flags & GENHD_FL_CD) { - if (dev->de) - devfs_remove("cdroms/cdrom%d", dev->number); - devfs_dealloc_unique_number(&cdrom_numspace, dev->number); - } else { - devfs_remove("discs/disc%d", dev->number); - if (!(dev->flags & GENHD_FL_DEVFS)) { - devfs_unregister(dev->de); - dev->de = NULL; - } - devfs_dealloc_unique_number(&disc_numspace, dev->number); - } + sprintf(devname, "%s/part%d", dev->devfs_name, part); + devfs_register(NULL, devname, 0, + dev->major, dev->first_minor + part, + S_IFBLK | S_IRUSR | S_IWUSR, + dev->fops, NULL); +} + +void devfs_remove_partitions(struct gendisk *disk) +{ + devfs_remove("discs/disc%d", disk->number); + devfs_remove(disk->devfs_name); + devfs_dealloc_unique_number(&disc_numspace, disk->number); +} + +void devfs_remove_cdrom(struct gendisk *disk) +{ + devfs_remove("cdroms/cdrom%d", disk->number); + devfs_remove(disk->devfs_name); + devfs_dealloc_unique_number(&cdrom_numspace, disk->number); } diff -urN linux-2.5.67-bk9/fs/partitions/check.c linux-2.5.67-bk10/fs/partitions/check.c --- linux-2.5.67-bk9/fs/partitions/check.c 2003-04-19 04:35:31.000000000 -0700 +++ linux-2.5.67-bk10/fs/partitions/check.c 2003-04-19 04:35:41.000000000 -0700 @@ -94,25 +94,26 @@ char *disk_name(struct gendisk *hd, int part, char *buf) { - int pos; if (!part) { - if (hd->disk_de) { - pos = devfs_generate_path(hd->disk_de, buf, 64); - if (pos >= 0) - return buf + pos; - } - sprintf(buf, "%s", hd->disk_name); +#ifdef CONFIG_DEVFS_FS + if (hd->devfs_name) + sprintf(buf, "%s/%s", hd->devfs_name, + (hd->flags & GENHD_FL_CD) ? "cd" : "disc"); + else +#endif + sprintf(buf, "%s", hd->disk_name); } else { - if (hd->part[part-1].de) { - pos = devfs_generate_path(hd->part[part-1].de, buf, 64); - if (pos >= 0) - return buf + pos; - } +#ifdef CONFIG_DEVFS_FS + if (hd->devfs_name) + sprintf(buf, "%s/part%d", hd->devfs_name, part); + else +#endif if (isdigit(hd->disk_name[strlen(hd->disk_name)-1])) sprintf(buf, "%sp%d", hd->disk_name, part); else sprintf(buf, "%s%d", hd->disk_name, part); } + return buf; } @@ -120,21 +121,19 @@ check_partition(struct gendisk *hd, struct block_device *bdev) { struct parsed_partitions *state; - devfs_handle_t de = NULL; - char buf[64]; int i, res; state = kmalloc(sizeof(struct parsed_partitions), GFP_KERNEL); if (!state) return NULL; - if (hd->flags & GENHD_FL_DEVFS) - de = hd->de; - i = devfs_generate_path (de, buf, sizeof buf); - if (i >= 0) { - printk(KERN_INFO " /dev/%s:", buf + i); +#ifdef CONFIG_DEVFS_FS + if (hd->devfs_name) { + printk(KERN_INFO " /dev/%s:", hd->devfs_name); sprintf(state->name, "p"); - } else { + } +#endif + else { disk_name(hd, 0, state->name); printk(KERN_INFO " %s:", state->name); if (isdigit(state->name[strlen(state->name)-1])) @@ -156,26 +155,6 @@ return NULL; } -static void devfs_register_partition(struct gendisk *dev, int part) -{ -#ifdef CONFIG_DEVFS_FS - devfs_handle_t dir; - struct hd_struct *p = dev->part; - char devname[16]; - - if (p[part-1].de) - return; - dir = dev->de; - if (!dir) - return; - sprintf(devname, "part%d", part); - p[part-1].de = devfs_register (dir, devname, 0, - dev->major, dev->first_minor + part, - S_IFBLK | S_IRUSR | S_IWUSR, - dev->fops, NULL); -#endif -} - /* * sysfs bindings for partitions */ @@ -261,8 +240,7 @@ p->start_sect = 0; p->nr_sects = 0; p->reads = p->writes = p->read_sectors = p->write_sectors = 0; - devfs_unregister(p->de); - p->de = NULL; + devfs_remove("%s/part%d", disk->devfs_name, part); kobject_unregister(&p->kobj); } @@ -414,7 +392,10 @@ unlink_gendisk(disk); disk_stat_set_all(disk, 0); disk->stamp = disk->stamp_idle = 0; - devfs_remove_partitions(disk); + if (disk->flags & GENHD_FL_CD) + devfs_remove_cdrom(disk); + else + devfs_remove_partitions(disk); if (disk->driverfs_dev) { sysfs_remove_link(&disk->kobj, "device"); sysfs_remove_link(&disk->driverfs_dev->kobj, "block"); diff -urN linux-2.5.67-bk9/include/asm-alpha/posix_types.h linux-2.5.67-bk10/include/asm-alpha/posix_types.h --- linux-2.5.67-bk9/include/asm-alpha/posix_types.h 2003-04-07 10:32:13.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-alpha/posix_types.h 2003-04-19 04:35:41.000000000 -0700 @@ -40,6 +40,8 @@ typedef __kernel_uid_t __kernel_uid32_t; typedef __kernel_gid_t __kernel_gid32_t; +typedef unsigned int __kernel_old_dev_t; + #ifdef __KERNEL__ #ifndef __GNUC__ diff -urN linux-2.5.67-bk9/include/asm-arm/posix_types.h linux-2.5.67-bk10/include/asm-arm/posix_types.h --- linux-2.5.67-bk9/include/asm-arm/posix_types.h 2003-04-07 10:30:39.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-arm/posix_types.h 2003-04-19 04:35:41.000000000 -0700 @@ -45,6 +45,7 @@ typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -urN linux-2.5.67-bk9/include/asm-cris/posix_types.h linux-2.5.67-bk10/include/asm-cris/posix_types.h --- linux-2.5.67-bk9/include/asm-cris/posix_types.h 2003-04-07 10:30:46.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-cris/posix_types.h 2003-04-19 04:35:41.000000000 -0700 @@ -38,6 +38,7 @@ typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -urN linux-2.5.67-bk9/include/asm-i386/posix_types.h linux-2.5.67-bk10/include/asm-i386/posix_types.h --- linux-2.5.67-bk9/include/asm-i386/posix_types.h 2003-04-07 10:32:51.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-i386/posix_types.h 2003-04-19 04:35:41.000000000 -0700 @@ -33,6 +33,7 @@ typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -urN linux-2.5.67-bk9/include/asm-ia64/posix_types.h linux-2.5.67-bk10/include/asm-ia64/posix_types.h --- linux-2.5.67-bk9/include/asm-ia64/posix_types.h 2003-04-07 10:31:00.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-ia64/posix_types.h 2003-04-19 04:35:42.000000000 -0700 @@ -43,6 +43,8 @@ typedef __kernel_uid_t __kernel_uid32_t; typedef __kernel_gid_t __kernel_gid32_t; +typedef unsigned int __kernel_old_dev_t; + # ifdef __KERNEL__ # ifndef __GNUC__ diff -urN linux-2.5.67-bk9/include/asm-m68k/posix_types.h linux-2.5.67-bk10/include/asm-m68k/posix_types.h --- linux-2.5.67-bk9/include/asm-m68k/posix_types.h 2003-04-07 10:30:42.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-m68k/posix_types.h 2003-04-19 04:35:42.000000000 -0700 @@ -33,6 +33,7 @@ typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -urN linux-2.5.67-bk9/include/asm-mips/posix_types.h linux-2.5.67-bk10/include/asm-mips/posix_types.h --- linux-2.5.67-bk9/include/asm-mips/posix_types.h 2003-04-07 10:31:52.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-mips/posix_types.h 2003-04-19 04:35:42.000000000 -0700 @@ -39,6 +39,7 @@ typedef int __kernel_gid32_t; typedef __kernel_uid_t __kernel_old_uid_t; typedef __kernel_gid_t __kernel_old_gid_t; +typedef unsigned int __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -urN linux-2.5.67-bk9/include/asm-mips64/posix_types.h linux-2.5.67-bk10/include/asm-mips64/posix_types.h --- linux-2.5.67-bk9/include/asm-mips64/posix_types.h 2003-04-07 10:30:58.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-mips64/posix_types.h 2003-04-19 04:35:42.000000000 -0700 @@ -39,6 +39,7 @@ typedef int __kernel_gid32_t; typedef __kernel_uid_t __kernel_old_uid_t; typedef __kernel_gid_t __kernel_old_gid_t; +typedef unsigned int __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -urN linux-2.5.67-bk9/include/asm-parisc/posix_types.h linux-2.5.67-bk10/include/asm-parisc/posix_types.h --- linux-2.5.67-bk9/include/asm-parisc/posix_types.h 2003-04-07 10:32:27.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-parisc/posix_types.h 2003-04-19 04:35:42.000000000 -0700 @@ -45,6 +45,8 @@ typedef unsigned long long __kernel_ino64_t; #endif +typedef unsigned int __kernel_old_dev_t; + typedef struct { #if defined(__KERNEL__) || defined(__USE_ALL) int val[2]; diff -urN linux-2.5.67-bk9/include/asm-ppc/posix_types.h linux-2.5.67-bk10/include/asm-ppc/posix_types.h --- linux-2.5.67-bk9/include/asm-ppc/posix_types.h 2003-04-07 10:31:10.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-ppc/posix_types.h 2003-04-19 04:35:42.000000000 -0700 @@ -33,6 +33,7 @@ typedef unsigned int __kernel_old_uid_t; typedef unsigned int __kernel_old_gid_t; +typedef unsigned int __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -urN linux-2.5.67-bk9/include/asm-ppc64/posix_types.h linux-2.5.67-bk10/include/asm-ppc64/posix_types.h --- linux-2.5.67-bk9/include/asm-ppc64/posix_types.h 2003-04-07 10:33:03.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-ppc64/posix_types.h 2003-04-19 04:35:42.000000000 -0700 @@ -39,6 +39,7 @@ typedef unsigned int __kernel_old_uid_t; typedef unsigned int __kernel_old_gid_t; +typedef unsigned long __kernel_old_dev_t; typedef struct { int val[2]; diff -urN linux-2.5.67-bk9/include/asm-s390/posix_types.h linux-2.5.67-bk10/include/asm-s390/posix_types.h --- linux-2.5.67-bk9/include/asm-s390/posix_types.h 2003-04-19 04:35:31.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-s390/posix_types.h 2003-04-19 04:35:42.000000000 -0700 @@ -47,6 +47,7 @@ typedef unsigned int __kernel_gid32_t; typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; #else /* __s390x__ */ diff -urN linux-2.5.67-bk9/include/asm-sh/posix_types.h linux-2.5.67-bk10/include/asm-sh/posix_types.h --- linux-2.5.67-bk9/include/asm-sh/posix_types.h 2003-04-07 10:31:13.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-sh/posix_types.h 2003-04-19 04:35:42.000000000 -0700 @@ -31,6 +31,7 @@ typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff -urN linux-2.5.67-bk9/include/asm-sparc/posix_types.h linux-2.5.67-bk10/include/asm-sparc/posix_types.h --- linux-2.5.67-bk9/include/asm-sparc/posix_types.h 2003-04-07 10:31:00.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-sparc/posix_types.h 2003-04-19 04:35:42.000000000 -0700 @@ -31,6 +31,7 @@ typedef unsigned int __kernel_gid32_t; typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; typedef int __kernel_clockid_t; typedef int __kernel_timer_t; diff -urN linux-2.5.67-bk9/include/asm-sparc64/posix_types.h linux-2.5.67-bk10/include/asm-sparc64/posix_types.h --- linux-2.5.67-bk9/include/asm-sparc64/posix_types.h 2003-04-07 10:32:28.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-sparc64/posix_types.h 2003-04-19 04:35:42.000000000 -0700 @@ -34,6 +34,8 @@ typedef __kernel_uid_t __kernel_uid32_t; typedef __kernel_gid_t __kernel_gid32_t; +typedef unsigned int __kernel_old_dev_t; + /* Note this piece of asymmetry from the v9 ABI. */ typedef int __kernel_suseconds_t; diff -urN linux-2.5.67-bk9/include/asm-v850/posix_types.h linux-2.5.67-bk10/include/asm-v850/posix_types.h --- linux-2.5.67-bk9/include/asm-v850/posix_types.h 2003-04-19 04:35:31.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-v850/posix_types.h 2003-04-19 04:35:42.000000000 -0700 @@ -42,7 +42,7 @@ /* Some bogus code depends on this; we don't care. */ typedef __kernel_uid_t __kernel_old_uid_t; - +typedef unsigned int __kernel_old_dev_t; typedef struct { #if defined(__KERNEL__) || defined(__USE_ALL) diff -urN linux-2.5.67-bk9/include/asm-x86_64/posix_types.h linux-2.5.67-bk10/include/asm-x86_64/posix_types.h --- linux-2.5.67-bk9/include/asm-x86_64/posix_types.h 2003-04-07 10:32:55.000000000 -0700 +++ linux-2.5.67-bk10/include/asm-x86_64/posix_types.h 2003-04-19 04:35:42.000000000 -0700 @@ -22,8 +22,8 @@ typedef long __kernel_time_t; typedef long __kernel_suseconds_t; typedef long __kernel_clock_t; -typedef int __kernel_timer_t; -typedef int __kernel_clockid_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; typedef int __kernel_daddr_t; typedef char * __kernel_caddr_t; typedef unsigned short __kernel_uid16_t; @@ -42,6 +42,8 @@ typedef __kernel_uid_t __kernel_uid32_t; typedef __kernel_gid_t __kernel_gid32_t; +typedef unsigned long __kernel_old_dev_t; + #ifdef __KERNEL__ #undef __FD_SET diff -urN linux-2.5.67-bk9/include/linux/devfs_fs_kernel.h linux-2.5.67-bk10/include/linux/devfs_fs_kernel.h --- linux-2.5.67-bk9/include/linux/devfs_fs_kernel.h 2003-04-19 04:35:31.000000000 -0700 +++ linux-2.5.67-bk10/include/linux/devfs_fs_kernel.h 2003-04-19 04:35:42.000000000 -0700 @@ -31,13 +31,14 @@ __attribute__((format (printf, 1, 2))); extern void devfs_remove(const char *fmt, ...) __attribute__((format (printf, 1, 2))); -extern int devfs_generate_path (devfs_handle_t de, char *path, int buflen); -extern int devfs_register_tape (devfs_handle_t de); +extern int devfs_register_tape(const char *name); extern void devfs_unregister_tape(int num); extern void devfs_create_partitions(struct gendisk *dev); extern void devfs_create_cdrom(struct gendisk *dev); extern void devfs_remove_partitions(struct gendisk *dev); -extern void mount_devfs_fs (void); +extern void devfs_remove_cdrom(struct gendisk *dev); +extern void devfs_register_partition(struct gendisk *dev, int part); +extern void mount_devfs_fs(void); #else /* CONFIG_DEVFS_FS */ static inline devfs_handle_t devfs_register (devfs_handle_t dir, const char *name, @@ -64,11 +65,6 @@ static inline void devfs_remove(const char *fmt, ...) { } -static inline int devfs_generate_path (devfs_handle_t de, char *path, - int buflen) -{ - return -ENOSYS; -} static inline int devfs_register_tape (devfs_handle_t de) { return -1; @@ -85,6 +81,12 @@ static inline void devfs_remove_partitions(struct gendisk *dev) { } +static inline void devfs_remove_cdrom(struct gendisk *dev) +{ +} +static inline void devfs_register_partition(struct gendisk *dev, int part) +{ +} static inline void mount_devfs_fs (void) { return; diff -urN linux-2.5.67-bk9/include/linux/genhd.h linux-2.5.67-bk10/include/linux/genhd.h --- linux-2.5.67-bk9/include/linux/genhd.h 2003-04-07 10:30:43.000000000 -0700 +++ linux-2.5.67-bk10/include/linux/genhd.h 2003-04-19 04:35:42.000000000 -0700 @@ -55,12 +55,13 @@ } __attribute__((packed)); #ifdef __KERNEL__ -# include - +#include /* we don't need any devfs crap + here, but some of the implicitly + included headers. will clean + this mess up later. --hch */ struct hd_struct { sector_t start_sect; sector_t nr_sects; - devfs_handle_t de; /* primary (master) devfs entry */ struct kobject kobj; unsigned reads, read_sectors, writes, write_sectors; int policy; @@ -68,7 +69,6 @@ #define GENHD_FL_REMOVABLE 1 #define GENHD_FL_DRIVERFS 2 -#define GENHD_FL_DEVFS 4 #define GENHD_FL_CD 8 #define GENHD_FL_UP 16 @@ -96,9 +96,8 @@ sector_t capacity; int flags; - int number; /* devfs crap */ - devfs_handle_t de; /* more of the same */ - devfs_handle_t disk_de; /* piled higher and deeper */ + char devfs_name[64]; /* devfs crap */ + int number; /* more of the same */ struct device *driverfs_dev; struct kobject kobj; diff -urN linux-2.5.67-bk9/include/linux/ide.h linux-2.5.67-bk10/include/linux/ide.h --- linux-2.5.67-bk9/include/linux/ide.h 2003-04-07 10:31:04.000000000 -0700 +++ linux-2.5.67-bk10/include/linux/ide.h 2003-04-19 04:35:42.000000000 -0700 @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -699,7 +698,7 @@ struct hd_driveid *id; /* drive model identification info */ struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ struct ide_settings_s *settings;/* /proc/ide/ drive settings */ - devfs_handle_t de; /* directory for device */ + char devfs_name[64]; /* devfs crap */ struct hwif_s *hwif; /* actually (ide_hwif_t *) */ diff -urN linux-2.5.67-bk9/include/linux/if.h linux-2.5.67-bk10/include/linux/if.h --- linux-2.5.67-bk9/include/linux/if.h 2003-04-07 10:31:14.000000000 -0700 +++ linux-2.5.67-bk10/include/linux/if.h 2003-04-19 04:35:42.000000000 -0700 @@ -50,7 +50,7 @@ /* Private (from user) interface flags (netdevice->priv_flags). */ #define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */ - +#define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */ #define IF_GET_IFACE 0x0001 /* for querying only */ #define IF_GET_PROTO 0x0002 diff -urN linux-2.5.67-bk9/include/linux/if_vlan.h linux-2.5.67-bk10/include/linux/if_vlan.h --- linux-2.5.67-bk9/include/linux/if_vlan.h 2003-04-07 10:30:44.000000000 -0700 +++ linux-2.5.67-bk10/include/linux/if_vlan.h 2003-04-19 04:35:42.000000000 -0700 @@ -54,8 +54,8 @@ #define VLAN_VID_MASK 0xfff -/* found in af_inet.c */ -extern int (*vlan_ioctl_hook)(unsigned long arg); +/* found in socket.c */ +extern void vlan_ioctl_set(int (*hook)(unsigned long)); #define VLAN_NAME "vlan" diff -urN linux-2.5.67-bk9/include/linux/loop.h linux-2.5.67-bk10/include/linux/loop.h --- linux-2.5.67-bk9/include/linux/loop.h 2003-04-07 10:33:02.000000000 -0700 +++ linux-2.5.67-bk10/include/linux/loop.h 2003-04-19 04:35:42.000000000 -0700 @@ -1,8 +1,6 @@ #ifndef _LINUX_LOOP_H #define _LINUX_LOOP_H -#include - /* * include/linux/loop.h * @@ -74,34 +72,37 @@ #define LO_FLAGS_READ_ONLY 2 #define LO_FLAGS_BH_REMAP 4 -/* - * Note that this structure gets the wrong offsets when directly used - * from a glibc program, because glibc has a 32bit dev_t. - * Prevent people from shooting in their own foot. - */ -#if __GLIBC__ >= 2 && !defined(dev_t) -#error "Wrong dev_t in loop.h" -#endif - -/* - * This uses kdev_t because glibc currently has no appropiate - * conversion version for the loop ioctls. - * The situation is very unpleasant - */ +#include /* for __kernel_old_dev_t */ +#include /* for __u64 */ +/* Backwards compatibility version */ struct loop_info { - int lo_number; /* ioctl r/o */ - dev_t lo_device; /* ioctl r/o */ - unsigned long lo_inode; /* ioctl r/o */ - dev_t lo_rdevice; /* ioctl r/o */ - int lo_offset; - int lo_encrypt_type; - int lo_encrypt_key_size; /* ioctl w/o */ - int lo_flags; /* ioctl r/o */ - char lo_name[LO_NAME_SIZE]; - unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ - unsigned long lo_init[2]; - char reserved[4]; + int lo_number; /* ioctl r/o */ + __kernel_old_dev_t lo_device; /* ioctl r/o */ + unsigned long lo_inode; /* ioctl r/o */ + __kernel_old_dev_t lo_rdevice; /* ioctl r/o */ + int lo_offset; + int lo_encrypt_type; + int lo_encrypt_key_size; /* ioctl w/o */ + int lo_flags; /* ioctl r/o */ + char lo_name[LO_NAME_SIZE]; + unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ + unsigned long lo_init[2]; + char reserved[4]; +}; + +struct loop_info64 { + __u64 lo_device; /* ioctl r/o */ + __u64 lo_inode; /* ioctl r/o */ + __u64 lo_rdevice; /* ioctl r/o */ + __u64 lo_offset; + __u32 lo_number; /* ioctl r/o */ + __u32 lo_encrypt_type; + __u32 lo_encrypt_key_size; /* ioctl w/o */ + __u32 lo_flags; /* ioctl r/o */ + __u8 lo_name[LO_NAME_SIZE]; + __u8 lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ + __u64 lo_init[2]; }; /* @@ -125,7 +126,7 @@ int number; /* filter type */ int (*transfer)(struct loop_device *lo, int cmd, char *raw_buf, char *loop_buf, int size, sector_t real_block); - int (*init)(struct loop_device *, struct loop_info *); + int (*init)(struct loop_device *, const struct loop_info64 *); /* release is called from loop_unregister_transfer or clr_fd */ int (*release)(struct loop_device *); int (*ioctl)(struct loop_device *, int cmd, unsigned long arg); @@ -134,7 +135,7 @@ void (*unlock)(struct loop_device *); }; -int loop_register_transfer(struct loop_func_table *funcs); +int loop_register_transfer(struct loop_func_table *funcs); int loop_unregister_transfer(int number); #endif @@ -142,9 +143,11 @@ * IOCTL commands --- we will commandeer 0x4C ('L') */ -#define LOOP_SET_FD 0x4C00 -#define LOOP_CLR_FD 0x4C01 -#define LOOP_SET_STATUS 0x4C02 -#define LOOP_GET_STATUS 0x4C03 +#define LOOP_SET_FD 0x4C00 +#define LOOP_CLR_FD 0x4C01 +#define LOOP_SET_STATUS 0x4C02 +#define LOOP_GET_STATUS 0x4C03 +#define LOOP_SET_STATUS64 0x4C04 +#define LOOP_GET_STATUS64 0x4C05 #endif diff -urN linux-2.5.67-bk9/include/net/dn.h linux-2.5.67-bk10/include/net/dn.h --- linux-2.5.67-bk9/include/net/dn.h 2003-04-07 10:31:56.000000000 -0700 +++ linux-2.5.67-bk10/include/net/dn.h 2003-04-19 04:35:42.000000000 -0700 @@ -171,17 +171,17 @@ int iif; }; -static __inline__ dn_address dn_eth2dn(unsigned char *ethaddr) +static inline dn_address dn_eth2dn(unsigned char *ethaddr) { return ethaddr[4] | (ethaddr[5] << 8); } -static __inline__ dn_address dn_saddr2dn(struct sockaddr_dn *saddr) +static inline dn_address dn_saddr2dn(struct sockaddr_dn *saddr) { return *(dn_address *)saddr->sdn_nodeaddr; } -static __inline__ void dn_dn2eth(unsigned char *ethaddr, dn_address addr) +static inline void dn_dn2eth(unsigned char *ethaddr, dn_address addr) { ethaddr[0] = 0xAA; ethaddr[1] = 0x00; @@ -191,6 +191,19 @@ ethaddr[5] = (unsigned char)(addr >> 8); } +static inline void dn_sk_ports_copy(struct flowi *fl, struct dn_scp *scp) +{ + fl->uli_u.dnports.sport = scp->addrloc; + fl->uli_u.dnports.dport = scp->addrrem; + fl->uli_u.dnports.objnum = scp->addr.sdn_objnum; + if (fl->uli_u.dnports.objnum == 0) { + fl->uli_u.dnports.objnamel = scp->addr.sdn_objnamel; + memcpy(fl->uli_u.dnports.objname, scp->addr.sdn_objname, 16); + } +} + +extern unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu); + #define DN_MENUVER_ACC 0x01 #define DN_MENUVER_USR 0x02 #define DN_MENUVER_PRX 0x04 diff -urN linux-2.5.67-bk9/include/net/dn_dev.h linux-2.5.67-bk10/include/net/dn_dev.h --- linux-2.5.67-bk9/include/net/dn_dev.h 2003-04-07 10:30:34.000000000 -0700 +++ linux-2.5.67-bk10/include/net/dn_dev.h 2003-04-19 04:35:42.000000000 -0700 @@ -8,6 +8,7 @@ struct dn_ifaddr *ifa_next; struct dn_dev *ifa_dev; dn_address ifa_local; + dn_address ifa_address; unsigned char ifa_flags; unsigned char ifa_scope; char ifa_label[IFNAMSIZ]; @@ -171,7 +172,10 @@ extern struct net_device *dn_dev_get_default(void); extern int dn_dev_bind_default(dn_address *addr); -static __inline__ int dn_dev_islocal(struct net_device *dev, dn_address addr) +extern int register_dnaddr_notifier(struct notifier_block *nb); +extern int unregister_dnaddr_notifier(struct notifier_block *nb); + +static inline int dn_dev_islocal(struct net_device *dev, dn_address addr) { struct dn_dev *dn_db = dev->dn_ptr; struct dn_ifaddr *ifa; diff -urN linux-2.5.67-bk9/include/net/dn_fib.h linux-2.5.67-bk10/include/net/dn_fib.h --- linux-2.5.67-bk9/include/net/dn_fib.h 2003-04-07 10:31:20.000000000 -0700 +++ linux-2.5.67-bk10/include/net/dn_fib.h 2003-04-19 04:35:42.000000000 -0700 @@ -1,12 +1,6 @@ #ifndef _NET_DN_FIB_H #define _NET_DN_FIB_H -#include - -#ifdef CONFIG_DECNET_ROUTER - -#include - struct dn_kern_rta { void *rta_dst; @@ -23,15 +17,6 @@ struct rta_cacheinfo *rta_ci; }; -struct dn_fib_key { - dn_address src; - dn_address dst; - int iif; - int oif; - u32 fwmark; - unsigned char scope; -}; - struct dn_fib_res { struct dn_fib_rule *r; struct dn_fib_info *fi; @@ -60,16 +45,23 @@ unsigned fib_flags; int fib_protocol; dn_address fib_prefsrc; - u32 fib_priority; + __u32 fib_priority; + __u32 fib_metrics[RTAX_MAX]; +#define dn_fib_mtu fib_metrics[RTAX_MTU-1] +#define dn_fib_window fib_metrics[RTAX_WINDOW-1] +#define dn_fib_rtt fib_metrics[RTAX_RTT-1] +#define dn_fib_advmss fib_metrics[RTAX_ADVMSS-1] int fib_nhs; int fib_power; struct dn_fib_nh fib_nh[0]; -#define fib_dev fib_nh[0].nh_dev +#define dn_fib_dev fib_nh[0].nh_dev }; -#define DN_FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel]) #define DN_FIB_RES_RESET(res) ((res).nh_sel = 0) +#define DN_FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel]) + +#define DN_FIB_RES_PREFSRC(res) ((res).fi->fib_prefsrc ? : __dn_fib_res_prefsrc(&res)) #define DN_FIB_RES_GW(res) (DN_FIB_RES_NH(res).nh_gw) #define DN_FIB_RES_DEV(res) (DN_FIB_RES_NH(res).nh_dev) #define DN_FIB_RES_OIF(res) (DN_FIB_RES_NH(res).nh_oif) @@ -106,7 +98,7 @@ int (*delete)(struct dn_fib_table *t, struct rtmsg *r, struct dn_kern_rta *rta, struct nlmsghdr *n, struct netlink_skb_parms *req); - int (*lookup)(struct dn_fib_table *t, const struct dn_fib_key *key, + int (*lookup)(struct dn_fib_table *t, const struct flowi *fl, struct dn_fib_res *res); int (*flush)(struct dn_fib_table *t); #ifdef CONFIG_PROC_FS @@ -118,7 +110,7 @@ unsigned char data[0]; }; - +#ifdef CONFIG_DECNET_ROUTER /* * dn_fib.c */ @@ -132,11 +124,12 @@ struct dn_kern_rta *rta, const struct nlmsghdr *nlh, int *errp); extern int dn_fib_semantic_match(int type, struct dn_fib_info *fi, - const struct dn_fib_key *key, struct dn_fib_res *res); + const struct flowi *fl, + struct dn_fib_res *res); extern void dn_fib_release_info(struct dn_fib_info *fi); extern u16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type); extern void dn_fib_flush(void); -extern void dn_fib_select_multipath(const struct dn_fib_key *key, +extern void dn_fib_select_multipath(const struct flowi *fl, struct dn_fib_res *res); extern int dn_fib_sync_down(dn_address local, struct net_device *dev, int force); @@ -156,7 +149,9 @@ extern void dn_fib_rules_init(void); extern void dn_fib_rules_cleanup(void); extern void dn_fib_rule_put(struct dn_fib_rule *); -extern int dn_fib_lookup(struct dn_fib_key *key, struct dn_fib_res *res); +extern __u16 dn_fib_rules_policy(__u16 saddr, struct dn_fib_res *res, unsigned *flags); +extern unsigned dnet_addr_type(__u16 addr); +extern int dn_fib_lookup(const struct flowi *fl, struct dn_fib_res *res); /* * rtnetlink interface @@ -169,21 +164,15 @@ extern int dn_fib_rtm_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg); extern int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb); -#define DN_NUM_TABLES 255 -#define DN_MIN_TABLE 1 -#define DN_DEFAULT_TABLE 1 -#define DN_L1_TABLE 1 -#define DN_L2_TABLE 2 - extern void dn_fib_free_info(struct dn_fib_info *fi); -static __inline__ void dn_fib_info_put(struct dn_fib_info *fi) +static inline void dn_fib_info_put(struct dn_fib_info *fi) { if (atomic_dec_and_test(&fi->fib_clntref)) dn_fib_free_info(fi); } -static __inline__ void dn_fib_res_put(struct dn_fib_res *res) +static inline void dn_fib_res_put(struct dn_fib_res *res) { if (res->fi) dn_fib_info_put(res->fi); @@ -191,13 +180,23 @@ dn_fib_rule_put(res->r); } -static __inline__ u16 dnet_make_mask(int n) +extern struct dn_fib_table *dn_fib_tables[]; + +#else /* Endnode */ + +#define dn_fib_lookup(fl, res) (-ESRCH) +#define dn_fib_info_put(fi) do { } while(0) +#define dn_fib_select_multipath(fl, res) do { } while(0) +#define dn_fib_rules_policy(saddr,res,flags) (0) +#define dn_fib_res_put(res) do { } while(0) + +#endif /* CONFIG_DECNET_ROUTER */ + +static inline u16 dnet_make_mask(int n) { if (n) return htons(~((1<<(16-n))-1)); return 0; } -#endif /* CONFIG_DECNET_ROUTER */ - #endif /* _NET_DN_FIB_H */ diff -urN linux-2.5.67-bk9/include/net/dn_neigh.h linux-2.5.67-bk10/include/net/dn_neigh.h --- linux-2.5.67-bk9/include/net/dn_neigh.h 2003-04-07 10:31:19.000000000 -0700 +++ linux-2.5.67-bk10/include/net/dn_neigh.h 2003-04-19 04:35:42.000000000 -0700 @@ -18,7 +18,7 @@ extern void dn_neigh_init(void); extern void dn_neigh_cleanup(void); -extern struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, void *ptr); +extern struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, const void *ptr); extern int dn_neigh_router_hello(struct sk_buff *skb); extern int dn_neigh_endnode_hello(struct sk_buff *skb); extern void dn_neigh_pointopoint_hello(struct sk_buff *skb); diff -urN linux-2.5.67-bk9/include/net/dn_nsp.h linux-2.5.67-bk10/include/net/dn_nsp.h --- linux-2.5.67-bk9/include/net/dn_nsp.h 2003-04-07 10:32:18.000000000 -0700 +++ linux-2.5.67-bk10/include/net/dn_nsp.h 2003-04-19 04:35:42.000000000 -0700 @@ -204,4 +204,6 @@ return atomic_read(&sk->rmem_alloc) > (sk->rcvbuf >> 1); } +#define DN_MAX_NSP_DATA_HEADER (11) + #endif /* _NET_DN_NSP_H */ diff -urN linux-2.5.67-bk9/include/net/dn_route.h linux-2.5.67-bk10/include/net/dn_route.h --- linux-2.5.67-bk9/include/net/dn_route.h 2003-04-07 10:30:38.000000000 -0700 +++ linux-2.5.67-bk10/include/net/dn_route.h 2003-04-19 04:35:42.000000000 -0700 @@ -16,7 +16,7 @@ *******************************************************************************/ extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, int pri); -extern int dn_route_output(struct dst_entry **pprt, dn_address dst, dn_address src, int flags); +extern int dn_route_output_sock(struct dst_entry **pprt, struct flowi *, struct sock *sk, int flags); extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb); extern int dn_cache_getroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg); extern void dn_rt_cache_flush(int delay); @@ -59,10 +59,10 @@ #define DN_RT_INFO_BLKR 0x40 /* Blocking Requested */ /* - * The key structure is what we used to look up the route. + * The fl structure is what we used to look up the route. * The rt_saddr & rt_daddr entries are the same as key.saddr & key.daddr - * except for local input routes, where the rt_saddr = key.daddr and - * rt_daddr = key.saddr to allow the route to be used for returning + * except for local input routes, where the rt_saddr = fl.fld_dst and + * rt_daddr = fl.fld_src to allow the route to be used for returning * packets to the originating host. */ struct dn_route { @@ -70,19 +70,18 @@ struct dst_entry dst; struct dn_route *rt_next; } u; - struct { - unsigned short saddr; - unsigned short daddr; - int iif; - int oif; - u32 fwmark; - } key; - unsigned short rt_saddr; - unsigned short rt_daddr; - unsigned char rt_type; - unsigned char rt_scope; - unsigned char rt_protocol; - unsigned char rt_table; + + __u16 rt_saddr; + __u16 rt_daddr; + __u16 rt_gateway; + __u16 __padding; + __u16 rt_src_map; + __u16 rt_dst_map; + + unsigned rt_flags; + unsigned rt_type; + + struct flowi fl; }; extern void dn_route_init(void); @@ -110,32 +109,4 @@ kfree_skb(skb); } -static inline void dn_nsp_send(struct sk_buff *skb) -{ - struct sock *sk = skb->sk; - struct dn_scp *scp = DN_SK(sk); - struct dst_entry *dst; - - skb->h.raw = skb->data; - scp->stamp = jiffies; - - if ((dst = sk->dst_cache) && !dst->obsolete) { -try_again: - skb->dst = dst_clone(dst); - dst_output(skb); - return; - } - - dst_release(xchg(&sk->dst_cache, NULL)); - - if (dn_route_output(&sk->dst_cache, dn_saddr2dn(&scp->peer), dn_saddr2dn(&scp->addr), 0) == 0) { - dst = sk->dst_cache; - goto try_again; - } - - sk->err = EHOSTUNREACH; - if (!test_bit(SOCK_DEAD, &sk->flags)) - sk->state_change(sk); -} - #endif /* _NET_DN_ROUTE_H */ diff -urN linux-2.5.67-bk9/include/net/flow.h linux-2.5.67-bk10/include/net/flow.h --- linux-2.5.67-bk9/include/net/flow.h 2003-04-07 10:32:28.000000000 -0700 +++ linux-2.5.67-bk10/include/net/flow.h 2003-04-19 04:35:42.000000000 -0700 @@ -25,7 +25,18 @@ struct in6_addr * saddr; __u32 flowlabel; } ip6_u; + + struct { + __u16 daddr; + __u16 saddr; + __u32 fwmark; + __u8 scope; + } dn_u; } nl_u; +#define fld_dst nl_u.dn_u.daddr +#define fld_src nl_u.dn_u.saddr +#define fld_fwmark nl_u.dn_u.fwmark +#define fld_scope nl_u.dn_u.scope #define fl6_dst nl_u.ip6_u.daddr #define fl6_src nl_u.ip6_u.saddr #define fl6_flowlabel nl_u.ip6_u.flowlabel @@ -48,8 +59,20 @@ __u8 code; } icmpt; + struct { + __u16 sport; + __u16 dport; + __u8 objnum; + __u8 objnamel; /* Not 16 bits since max val is 16 */ + __u8 objname[16]; /* Not zero terminated */ + } dnports; + __u32 spi; } uli_u; +#define fl_ip_sport uli_u.ports.sport +#define fl_ip_dport uli_u.ports.dport +#define fl_icmp_type uli_u.icmpt.type +#define fl_icmp_code uli_u.icmpt.code +#define fl_ipsec_spi uli_u.spi }; - #endif diff -urN linux-2.5.67-bk9/include/net/route.h linux-2.5.67-bk10/include/net/route.h --- linux-2.5.67-bk9/include/net/route.h 2003-04-07 10:30:33.000000000 -0700 +++ linux-2.5.67-bk10/include/net/route.h 2003-04-19 04:35:42.000000000 -0700 @@ -173,13 +173,13 @@ static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport, struct sock *sk) { - if (sport != (*rp)->fl.uli_u.ports.sport || - dport != (*rp)->fl.uli_u.ports.dport) { + if (sport != (*rp)->fl.fl_ip_sport || + dport != (*rp)->fl.fl_ip_dport) { struct flowi fl; memcpy(&fl, &(*rp)->fl, sizeof(fl)); - fl.uli_u.ports.sport = sport; - fl.uli_u.ports.dport = dport; + fl.fl_ip_sport = sport; + fl.fl_ip_dport = dport; ip_rt_put(*rp); *rp = NULL; return ip_route_output_flow(rp, &fl, sk, 0); diff -urN linux-2.5.67-bk9/include/net/sock.h linux-2.5.67-bk10/include/net/sock.h --- linux-2.5.67-bk9/include/net/sock.h 2003-04-19 04:35:31.000000000 -0700 +++ linux-2.5.67-bk10/include/net/sock.h 2003-04-19 04:35:42.000000000 -0700 @@ -859,6 +859,9 @@ * schedule(); * SOCK_SLEEP_POST(sk) * + * N.B. These are now obsolete and were, afaik, only ever used in DECnet + * and when the last use of them in DECnet has gone, I'm intending to + * remove them. */ #define SOCK_SLEEP_PRE(sk) { struct task_struct *tsk = current; \ diff -urN linux-2.5.67-bk9/include/net/xfrm.h linux-2.5.67-bk10/include/net/xfrm.h --- linux-2.5.67-bk9/include/net/xfrm.h 2003-04-19 04:35:31.000000000 -0700 +++ linux-2.5.67-bk10/include/net/xfrm.h 2003-04-19 04:35:42.000000000 -0700 @@ -295,11 +295,11 @@ static inline u32 __flow_hash4(struct flowi *fl) { - u32 hash = fl->fl4_src ^ fl->uli_u.ports.sport; + u32 hash = fl->fl4_src ^ fl->fl_ip_sport; hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4); - hash ^= fl->fl4_dst ^ fl->uli_u.ports.dport; + hash ^= fl->fl4_dst ^ fl->fl_ip_dport; hash ^= (hash >> 10); hash ^= (hash >> 20); return hash & (XFRM_FLOWCACHE_HASH_SIZE-1); @@ -309,13 +309,13 @@ { u32 hash = fl->fl6_src->s6_addr32[2] ^ fl->fl6_src->s6_addr32[3] ^ - fl->uli_u.ports.sport; + fl->fl_ip_sport; hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4); hash ^= fl->fl6_dst->s6_addr32[2] ^ fl->fl6_dst->s6_addr32[3] ^ - fl->uli_u.ports.dport; + fl->fl_ip_dport; hash ^= (hash >> 10); hash ^= (hash >> 20); return hash & (XFRM_FLOWCACHE_HASH_SIZE-1); @@ -454,8 +454,8 @@ { return addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) && addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) && - !((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) && - !((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) && + !((fl->fl_ip_dport^sel->dport)&sel->dport_mask) && + !((fl->fl_ip_sport^sel->sport)&sel->sport_mask) && (fl->proto == sel->proto || !sel->proto) && (fl->oif == sel->ifindex || !sel->ifindex); } @@ -465,8 +465,8 @@ { return addr_match(fl->fl6_dst, &sel->daddr, sel->prefixlen_d) && addr_match(fl->fl6_src, &sel->saddr, sel->prefixlen_s) && - !((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) && - !((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) && + !((fl->fl_ip_dport^sel->dport)&sel->dport_mask) && + !((fl->fl_ip_sport^sel->sport)&sel->sport_mask) && (fl->proto == sel->proto || !sel->proto) && (fl->oif == sel->ifindex || !sel->ifindex); } diff -urN linux-2.5.67-bk9/net/8021q/vlan.c linux-2.5.67-bk10/net/8021q/vlan.c --- linux-2.5.67-bk9/net/8021q/vlan.c 2003-04-19 04:35:31.000000000 -0700 +++ linux-2.5.67-bk10/net/8021q/vlan.c 2003-04-19 04:35:43.000000000 -0700 @@ -49,6 +49,8 @@ static char vlan_buggyright[] = "David S. Miller "; static int vlan_device_event(struct notifier_block *, unsigned long, void *); +static int vlan_ioctl_handler(unsigned long); +static int unregister_vlan_dev(struct net_device *, unsigned short ); struct notifier_block vlan_notifier_block = { .notifier_call = vlan_device_event, @@ -100,11 +102,32 @@ /* Register us to receive netdevice events */ register_netdevice_notifier(&vlan_notifier_block); - vlan_ioctl_hook = vlan_ioctl_handler; + vlan_ioctl_set(vlan_ioctl_handler); return 0; } +/* Cleanup all vlan devices + * Note: devices that have been registered that but not + * brought up will exist but have no module ref count. + */ +static void __exit vlan_cleanup_devices(void) +{ + struct net_device *dev, *nxt; + + rtnl_lock(); + for (dev = dev_base; dev; dev = nxt) { + nxt = dev->next; + if (dev->priv_flags & IFF_802_1Q_VLAN) { + unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev, + VLAN_DEV_INFO(dev)->vlan_id); + + unregister_netdevice(dev); + } + } + rtnl_unlock(); +} + /* * Module 'remove' entry point. * o delete /proc/net/router directory and static entries. @@ -113,6 +136,14 @@ { int i; + vlan_ioctl_set(NULL); + + /* Un-register us from receiving netdevice events */ + unregister_netdevice_notifier(&vlan_notifier_block); + + dev_remove_pack(&vlan_packet_type); + vlan_cleanup_devices(); + /* This table must be empty if there are no module * references left. */ @@ -120,13 +151,9 @@ if (vlan_group_hash[i] != NULL) BUG(); } - - /* Un-register us from receiving netdevice events */ - unregister_netdevice_notifier(&vlan_notifier_block); - - dev_remove_pack(&vlan_packet_type); vlan_proc_cleanup(); - vlan_ioctl_hook = NULL; + + synchronize_net(); } module_init(vlan_proto_init); @@ -262,8 +289,6 @@ ret = 1; } - - module_put(THIS_MODULE); } } @@ -504,12 +529,6 @@ if (register_netdevice(new_dev)) goto out_free_newdev_priv; - /* NOTE: We have a reference to the real device, - * so hold on to the reference. May fail if we are being removed - */ - if (!try_module_get(THIS_MODULE)) - goto out_free_unregister; - /* So, got the sucker initialized, now lets place * it into our local structure. */ @@ -523,7 +542,7 @@ if (!grp) { /* need to add a new group */ grp = kmalloc(sizeof(struct vlan_group), GFP_KERNEL); if (!grp) - goto out_free_put; + goto out_free_unregister; /* printk(KERN_ALERT "VLAN REGISTER: Allocated new group.\n"); */ memset(grp, 0, sizeof(struct vlan_group)); @@ -551,8 +570,6 @@ printk(VLAN_DBG "Allocated new device successfully, returning.\n"); #endif return new_dev; -out_free_put: - module_put(THIS_MODULE); out_free_unregister: unregister_netdev(new_dev); @@ -658,7 +675,7 @@ * o execute requested action or pass command to the device driver * arg is really a void* to a vlan_ioctl_args structure. */ -int vlan_ioctl_handler(unsigned long arg) +static int vlan_ioctl_handler(unsigned long arg) { int err = 0; struct vlan_ioctl_args args; diff -urN linux-2.5.67-bk9/net/8021q/vlan.h linux-2.5.67-bk10/net/8021q/vlan.h --- linux-2.5.67-bk9/net/8021q/vlan.h 2003-04-07 10:31:55.000000000 -0700 +++ linux-2.5.67-bk10/net/8021q/vlan.h 2003-04-19 04:35:43.000000000 -0700 @@ -30,8 +30,6 @@ extern unsigned short vlan_name_type; -int vlan_ioctl_handler(unsigned long arg); - #define VLAN_GRP_HASH_SHIFT 5 #define VLAN_GRP_HASH_SIZE (1 << VLAN_GRP_HASH_SHIFT) #define VLAN_GRP_HASH_MASK (VLAN_GRP_HASH_SIZE - 1) diff -urN linux-2.5.67-bk9/net/bridge/br.c linux-2.5.67-bk10/net/bridge/br.c --- linux-2.5.67-bk9/net/bridge/br.c 2003-04-19 04:35:31.000000000 -0700 +++ linux-2.5.67-bk10/net/bridge/br.c 2003-04-19 04:35:43.000000000 -0700 @@ -21,7 +21,6 @@ #include #include #include -#include #include #include "br_private.h" @@ -31,16 +30,6 @@ int (*br_should_route_hook) (struct sk_buff **pskb) = NULL; -void br_dec_use_count() -{ - module_put(THIS_MODULE); -} - -void br_inc_use_count() -{ - try_module_get(THIS_MODULE); -} - static int __init br_init(void) { printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n"); @@ -67,15 +56,17 @@ br_netfilter_fini(); #endif unregister_netdevice_notifier(&br_device_notifier); - brioctl_set(NULL); br_handle_frame_hook = NULL; #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) - /* FIX ME. move into hook structure with ref count */ br_fdb_get_hook = NULL; br_fdb_put_hook = NULL; #endif + + br_cleanup_bridges(); + + synchronize_net(); } EXPORT_SYMBOL(br_should_route_hook); diff -urN linux-2.5.67-bk9/net/bridge/br_device.c linux-2.5.67-bk10/net/bridge/br_device.c --- linux-2.5.67-bk9/net/bridge/br_device.c 2003-04-07 10:30:33.000000000 -0700 +++ linux-2.5.67-bk10/net/bridge/br_device.c 2003-04-19 04:35:43.000000000 -0700 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "br_private.h" @@ -91,9 +92,9 @@ netif_start_queue(dev); br = dev->priv; - read_lock(&br->lock); + write_lock(&br->lock); br_stp_enable_bridge(br); - read_unlock(&br->lock); + write_unlock(&br->lock); return 0; } @@ -107,9 +108,9 @@ struct net_bridge *br; br = dev->priv; - read_lock(&br->lock); + write_lock(&br->lock); br_stp_disable_bridge(br); - read_unlock(&br->lock); + write_unlock(&br->lock); netif_stop_queue(dev); @@ -121,6 +122,11 @@ return -1; } +static void br_dev_destruct(struct net_device *dev) +{ + kfree(dev->priv); +} + void br_dev_setup(struct net_device *dev) { memset(dev->dev_addr, 0, ETH_ALEN); @@ -130,6 +136,8 @@ dev->hard_start_xmit = br_dev_xmit; dev->open = br_dev_open; dev->set_multicast_list = br_dev_set_multicast_list; + dev->destructor = br_dev_destruct; + dev->owner = THIS_MODULE; dev->stop = br_dev_stop; dev->accept_fastpath = br_dev_accept_fastpath; dev->tx_queue_len = 0; diff -urN linux-2.5.67-bk9/net/bridge/br_fdb.c linux-2.5.67-bk10/net/bridge/br_fdb.c --- linux-2.5.67-bk9/net/bridge/br_fdb.c 2003-04-07 10:30:40.000000000 -0700 +++ linux-2.5.67-bk10/net/bridge/br_fdb.c 2003-04-19 04:35:43.000000000 -0700 @@ -94,6 +94,7 @@ { struct net_bridge *br; int i; + int newhash = br_mac_hash(newaddr); br = p->br; write_lock_bh(&br->hash_lock); @@ -103,9 +104,11 @@ f = br->hash[i]; while (f != NULL) { if (f->dst == p && f->is_local) { - __hash_unlink(f); memcpy(f->addr.addr, newaddr, ETH_ALEN); - __hash_link(br, f, br_mac_hash(newaddr)); + if (newhash != i) { + __hash_unlink(f); + __hash_link(br, f, newhash); + } write_unlock_bh(&br->hash_lock); return; } @@ -212,21 +215,15 @@ for (i=0;ihash[i]; - while (f != NULL && num < maxnum) { + for (f = br->hash[i]; f != NULL && num < maxnum; + f = f->next_hash) { struct __fdb_entry ent; - int err; - struct net_bridge_fdb_entry *g; - struct net_bridge_fdb_entry **pp; - if (has_expired(br, f)) { - f = f->next_hash; + if (has_expired(br, f)) continue; - } if (offset) { offset--; - f = f->next_hash; continue; } @@ -234,37 +231,33 @@ atomic_inc(&f->use_count); read_unlock_bh(&br->hash_lock); - err = copy_to_user(walk, &ent, sizeof(struct __fdb_entry)); - read_lock_bh(&br->hash_lock); - - g = f->next_hash; - pp = f->pprev_hash; - br_fdb_put(f); + + if (copy_to_user(walk, &ent, sizeof(struct __fdb_entry))) + return -EFAULT; - if (err) - goto out_fault; + read_lock_bh(&br->hash_lock); + + /* entry was deleted during copy_to_user */ + if (atomic_dec_and_test(&f->use_count)) { + kfree(f); + num = -EAGAIN; + goto out; + } - if (g == NULL && pp == NULL) - goto out_disappeared; + /* entry changed address hash while copying */ + if (br_mac_hash(f->addr.addr) != i) { + num = -EAGAIN; + goto out; + } num++; walk++; - - f = g; } } out: read_unlock_bh(&br->hash_lock); return num; - - out_disappeared: - num = -EAGAIN; - goto out; - - out_fault: - num = -EFAULT; - goto out; } static __inline__ void __fdb_possibly_replace(struct net_bridge_fdb_entry *fdb, diff -urN linux-2.5.67-bk9/net/bridge/br_if.c linux-2.5.67-bk10/net/bridge/br_if.c --- linux-2.5.67-bk9/net/bridge/br_if.c 2003-04-19 04:35:31.000000000 -0700 +++ linux-2.5.67-bk10/net/bridge/br_if.c 2003-04-19 04:35:43.000000000 -0700 @@ -17,14 +17,13 @@ #include #include #include +#include #include #include +#include #include #include "br_private.h" -static struct net_bridge *bridge_list; -static spinlock_t bridge_lock = SPIN_LOCK_UNLOCKED; - static int br_initial_port_cost(struct net_device *dev) { if (!strncmp(dev->name, "lec", 3)) @@ -70,23 +69,6 @@ return 0; } -/* called with bridge_lock */ -static struct net_bridge **__find_br(char *name) -{ - struct net_bridge **b; - struct net_bridge *br; - - b = &bridge_list; - while ((br = *b) != NULL) { - if (!strncmp(br->dev.name, name, IFNAMSIZ)) - return b; - - b = &(br->next); - } - - return NULL; -} - static void del_ifs(struct net_bridge *br) { br_write_lock_bh(BR_NETPROTO_LOCK); @@ -97,7 +79,7 @@ br_write_unlock_bh(BR_NETPROTO_LOCK); } -static struct net_bridge *new_nb(char *name) +static struct net_bridge *new_nb(const char *name) { struct net_bridge *br; struct net_device *dev; @@ -112,6 +94,7 @@ strncpy(dev->name, name, IFNAMSIZ); dev->priv = br; + dev->priv_flags = IFF_EBRIDGE; ether_setup(dev); br_dev_setup(dev); @@ -178,56 +161,47 @@ return p; } -int br_add_bridge(char *name) +int br_add_bridge(const char *name) { struct net_bridge *br; + int ret; - if ((br = new_nb(name)) == NULL) + if ((br = new_nb(name)) == NULL) return -ENOMEM; - if (__dev_get_by_name(name) != NULL) { + ret = register_netdev(&br->dev); + if (ret) kfree(br); - return -EEXIST; - } - - spin_lock(&bridge_lock); - br->next = bridge_list; - bridge_list = br; - spin_unlock(&bridge_lock); - - br_inc_use_count(); - register_netdev(&br->dev); - - return 0; + return ret; } -int br_del_bridge(char *name) +int br_del_bridge(const char *name) { - struct net_bridge **b; - struct net_bridge *br; + struct net_device *dev; + int ret = 0; - spin_lock(&bridge_lock); - if ((b = __find_br(name)) == NULL) { - spin_unlock(&bridge_lock); - return -ENXIO; + dev = dev_get_by_name(name); + if (dev == NULL) + return -ENXIO; /* Could not find device */ + + if (!(dev->priv_flags & IFF_EBRIDGE)) { + /* Attempt to delete non bridge device! */ + ret = -EPERM; } - br = *b; - if (br->dev.flags & IFF_UP) { - spin_unlock(&bridge_lock); - return -EBUSY; + else if (dev->flags & IFF_UP) { + /* Not shutdown yet. */ + ret = -EBUSY; + } + + else { + del_ifs((struct net_bridge *) dev->priv); + + unregister_netdev(dev); } - *b = br->next; - spin_unlock(&bridge_lock); - - del_ifs(br); - - unregister_netdev(&br->dev); - kfree(br); - br_dec_use_count(); - - return 0; + dev_put(dev); + return ret; } int br_add_if(struct net_bridge *br, struct net_device *dev) @@ -278,24 +252,19 @@ int br_get_bridge_ifindices(int *indices, int num) { - struct net_bridge *br; - int i; - - spin_lock(&bridge_lock); - br = bridge_list; - for (i=0;idev.ifindex; - br = br->next; + rtnl_shlock(); + for (dev = dev_base; dev && i < num; dev = dev->next) { + if (dev->priv_flags & IFF_EBRIDGE) + indices[i++] = dev->ifindex; } - spin_unlock(&bridge_lock); + rtnl_shunlock(); return i; } -/* called under ioctl_lock */ void br_get_port_ifindices(struct net_bridge *br, int *ifindices) { struct net_bridge_port *p; @@ -308,3 +277,24 @@ } read_unlock(&br->lock); } + + +void __exit br_cleanup_bridges(void) +{ + struct net_device *dev, *nxt; + + rtnl_lock(); + for (dev = dev_base; dev; dev = nxt) { + nxt = dev->next; + if ((dev->priv_flags & IFF_EBRIDGE) + && dev->owner == THIS_MODULE) { + pr_debug("cleanup %s\n", dev->name); + + del_ifs((struct net_bridge *) dev->priv); + + unregister_netdevice(dev); + } + } + rtnl_unlock(); + +} diff -urN linux-2.5.67-bk9/net/bridge/br_private.h linux-2.5.67-bk10/net/bridge/br_private.h --- linux-2.5.67-bk9/net/bridge/br_private.h 2003-04-07 10:30:57.000000000 -0700 +++ linux-2.5.67-bk10/net/bridge/br_private.h 2003-04-19 04:35:43.000000000 -0700 @@ -79,7 +79,6 @@ struct net_bridge { - struct net_bridge *next; rwlock_t lock; struct net_bridge_port *port_list; struct net_device dev; @@ -115,10 +114,6 @@ extern struct notifier_block br_device_notifier; extern unsigned char bridge_ula[6]; -/* br.c */ -extern void br_dec_use_count(void); -extern void br_inc_use_count(void); - /* br_device.c */ extern void br_dev_setup(struct net_device *dev); extern int br_dev_xmit(struct sk_buff *skb, struct net_device *dev); @@ -156,8 +151,9 @@ int clone); /* br_if.c */ -extern int br_add_bridge(char *name); -extern int br_del_bridge(char *name); +extern int br_add_bridge(const char *name); +extern int br_del_bridge(const char *name); +extern void br_cleanup_bridges(void); extern int br_add_if(struct net_bridge *br, struct net_device *dev); extern int br_del_if(struct net_bridge *br, @@ -172,7 +168,6 @@ extern int br_handle_frame(struct sk_buff *skb); /* br_ioctl.c */ -extern void br_call_ioctl_atomic(void (*fn)(void)); extern int br_ioctl(struct net_bridge *br, unsigned int cmd, unsigned long arg0, diff -urN linux-2.5.67-bk9/net/bridge/br_stp_if.c linux-2.5.67-bk10/net/bridge/br_stp_if.c --- linux-2.5.67-bk9/net/bridge/br_stp_if.c 2003-04-07 10:32:31.000000000 -0700 +++ linux-2.5.67-bk10/net/bridge/br_stp_if.c 2003-04-19 04:35:43.000000000 -0700 @@ -85,7 +85,7 @@ p = p->next; } - del_timer(&br->tick); + del_timer_sync(&br->tick); } /* called under bridge lock */ diff -urN linux-2.5.67-bk9/net/decnet/TODO linux-2.5.67-bk10/net/decnet/TODO --- linux-2.5.67-bk9/net/decnet/TODO 2003-04-07 10:32:16.000000000 -0700 +++ linux-2.5.67-bk10/net/decnet/TODO 2003-04-19 04:35:43.000000000 -0700 @@ -26,25 +26,16 @@ o Start to hack together user level software and add more DECnet support in ifconfig for example. - o Test adding/deleting of routes - - o Test route lookup - - o Test /proc/net/decnet_route route listing works correctly (maybe I'll - change the format of this file... atm its very similar to the IPv4 route - file) - o Find all the commonality between DECnet and IPv4 routing code and extract it into a small library of routines. [probably a project for 2.7.xx] - o Test ip_gre tunneling works... it did the last time I tested it and it - will have to if I'm to test routing properly. - o Add the routing message grabbing netfilter module [written, tested, awaiting merge] - o Add perfect socket hashing - an idea suggested by Paul Koning [part written, - awaiting debugging and merge] + o Add perfect socket hashing - an idea suggested by Paul Koning. Currently + we have a half-way house scheme which seems to work reasonably well, but + the full scheme is still worth implementing, its not not top of my list + right now. o Add session control message flow control @@ -54,3 +45,5 @@ o AIO for DECnet + o Eliminate dn_db->parms.blksize + diff -urN linux-2.5.67-bk9/net/decnet/af_decnet.c linux-2.5.67-bk10/net/decnet/af_decnet.c --- linux-2.5.67-bk9/net/decnet/af_decnet.c 2003-04-07 10:31:24.000000000 -0700 +++ linux-2.5.67-bk10/net/decnet/af_decnet.c 2003-04-19 04:35:43.000000000 -0700 @@ -118,6 +118,7 @@ #include #include #include +#include #include #include #include @@ -146,6 +147,7 @@ #define DN_SK_HASH_SIZE (1 << DN_SK_HASH_SHIFT) #define DN_SK_HASH_MASK (DN_SK_HASH_SIZE - 1) + static kmem_cache_t *dn_sk_cachep; static struct proto_ops dn_proto_ops; static rwlock_t dn_hash_lock = RW_LOCK_UNLOCKED; @@ -273,7 +275,7 @@ if (hash == 0) { hash = addr->sdn_objnamel; - for(i = 0; i < addr->sdn_objnamel; i++) { + for(i = 0; i < dn_ntohs(addr->sdn_objnamel); i++) { hash ^= addr->sdn_objname[i]; hash ^= (hash << 3); } @@ -512,8 +514,7 @@ scp->services_loc = 1 | NSP_FC_NONE; scp->info_rem = 0; scp->info_loc = 0x03; /* NSP version 4.1 */ - scp->segsize_rem = 230; /* Default: Updated by remote segsize */ - scp->segsize_loc = 1450; /* Best guess for ethernet */ + scp->segsize_rem = 230 - DN_MAX_NSP_DATA_HEADER; /* Default: Updated by remote segsize */ scp->nonagle = 0; scp->multi_ireq = 1; scp->accept_mode = ACC_IMMED; @@ -788,8 +789,8 @@ return -EINVAL; #if 1 - if ((!capable(CAP_NET_BIND_SERVICE) && saddr->sdn_objnum) || - (saddr->sdn_flags & SDF_WILD)) + if (!capable(CAP_NET_BIND_SERVICE) && (saddr->sdn_objnum || + (saddr->sdn_flags & SDF_WILD))) return -EACCES; #else /* @@ -877,18 +878,18 @@ static int dn_confirm_accept(struct sock *sk, long *timeo, int allocation) { struct dn_scp *scp = DN_SK(sk); - DECLARE_WAITQUEUE(wait, current); + DEFINE_WAIT(wait); int err; if (scp->state != DN_CR) return -EINVAL; scp->state = DN_CC; + scp->segsize_loc = dst_path_metric(__sk_dst_get(sk), RTAX_ADVMSS); dn_send_conn_conf(sk, allocation); - add_wait_queue(sk->sleep, &wait); + prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE); for(;;) { - set_current_state(TASK_INTERRUPTIBLE); release_sock(sk); if (scp->state == DN_CC) *timeo = schedule_timeout(*timeo); @@ -905,16 +906,21 @@ err = -EAGAIN; if (!*timeo) break; + prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE); + } + finish_wait(sk->sleep, &wait); + if (err == 0) { + sk->socket->state = SS_CONNECTED; + } else if (scp->state != DN_CC) { + sk->socket->state = SS_UNCONNECTED; } - remove_wait_queue(sk->sleep, &wait); - current->state = TASK_RUNNING; return err; } static int dn_wait_run(struct sock *sk, long *timeo) { struct dn_scp *scp = DN_SK(sk); - DECLARE_WAITQUEUE(wait, current); + DEFINE_WAIT(wait); int err = 0; if (scp->state == DN_RUN) @@ -923,9 +929,8 @@ if (!*timeo) return -EALREADY; - add_wait_queue(sk->sleep, &wait); + prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE); for(;;) { - set_current_state(TASK_INTERRUPTIBLE); release_sock(sk); if (scp->state == DN_CI || scp->state == DN_CC) *timeo = schedule_timeout(*timeo); @@ -942,12 +947,14 @@ err = -ETIMEDOUT; if (!*timeo) break; + prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE); } - remove_wait_queue(sk->sleep, &wait); - current->state = TASK_RUNNING; + finish_wait(sk->sleep, &wait); out: if (err == 0) { sk->socket->state = SS_CONNECTED; + } else if (scp->state != DN_CI && scp->state != DN_CC) { + sk->socket->state = SS_UNCONNECTED; } return err; } @@ -957,6 +964,7 @@ struct socket *sock = sk->socket; struct dn_scp *scp = DN_SK(sk); int err = -EISCONN; + struct flowi fl; if (sock->state == SS_CONNECTED) goto out; @@ -995,12 +1003,17 @@ memcpy(&scp->peer, addr, sizeof(struct sockaddr_dn)); err = -EHOSTUNREACH; - if (dn_route_output(&sk->dst_cache, dn_saddr2dn(&scp->peer), - dn_saddr2dn(&scp->addr), flags & MSG_TRYHARD) < 0) + memset(&fl, 0, sizeof(fl)); + fl.oif = sk->bound_dev_if; + fl.fld_dst = dn_saddr2dn(&scp->peer); + fl.fld_src = dn_saddr2dn(&scp->addr); + dn_sk_ports_copy(&fl, scp); + if (dn_route_output_sock(&sk->dst_cache, &fl, sk, flags) < 0) goto out; - + sk->route_caps = sk->dst_cache->dev->features; sock->state = SS_CONNECTING; scp->state = DN_CI; + scp->segsize_loc = dst_path_metric(sk->dst_cache, RTAX_ADVMSS); dn_nsp_send_conninit(sk, NSP_CI); err = -EINPROGRESS; @@ -1077,13 +1090,12 @@ static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo) { - DECLARE_WAITQUEUE(wait, current); + DEFINE_WAIT(wait); struct sk_buff *skb = NULL; int err = 0; - add_wait_queue_exclusive(sk->sleep, &wait); + prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE); for(;;) { - set_current_state(TASK_INTERRUPTIBLE); release_sock(sk); skb = skb_dequeue(&sk->receive_queue); if (skb == NULL) { @@ -1102,9 +1114,10 @@ err = -EAGAIN; if (!*timeo) break; + prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE); } - remove_wait_queue(sk->sleep, &wait); - current->state = TASK_RUNNING; + finish_wait(sk->sleep, &wait); + return skb == NULL ? ERR_PTR(err) : skb; } @@ -1276,12 +1289,6 @@ release_sock(sk); return val; -#ifdef CONFIG_DECNET_ROUTER - case SIOCADDRT: - case SIOCDELRT: - return dn_fib_ioctl(sock, cmd, arg); -#endif /* CONFIG_DECNET_ROUTER */ - case TIOCOUTQ: amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); if (amount < 0) @@ -1888,6 +1895,64 @@ return 0; } +/* + * The DECnet spec requires the the "routing layer" accepts packets which + * are at least 230 bytes in size. This excludes any headers which the NSP + * layer might add, so we always assume that we'll be using the maximal + * length header on data packets. The variation in length is due to the + * inclusion (or not) of the two 16 bit acknowledgement fields so it doesn't + * make much practical difference. + */ +unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu) +{ + unsigned mss = 230 - DN_MAX_NSP_DATA_HEADER; + if (dev) { + struct dn_dev *dn_db = dev->dn_ptr; + mtu -= LL_RESERVED_SPACE(dev); + if (dn_db->use_long) + mtu -= 21; + else + mtu -= 6; + mtu -= DN_MAX_NSP_DATA_HEADER; + } else { + /* + * 21 = long header, 16 = guess at MAC header length + */ + mtu -= (21 + DN_MAX_NSP_DATA_HEADER + 16); + } + if (mtu > mss) + mss = mtu; + return mss; +} + +static inline unsigned int dn_current_mss(struct sock *sk, int flags) +{ + struct dst_entry *dst = __sk_dst_get(sk); + struct dn_scp *scp = DN_SK(sk); + int mss_now = min_t(int, scp->segsize_loc, scp->segsize_rem); + + /* Other data messages are limited to 16 bytes per packet */ + if (flags & MSG_OOB) + return 16; + + /* This works out the maximum size of segment we can send out */ + if (dst) { + u32 mtu = dst_pmtu(dst); + mss_now = min_t(int, dn_mss_from_pmtu(dst->dev, mtu), mss_now); + } + + return mss_now; +} + +static int dn_error(struct sock *sk, int flags, int err) +{ + if (err == -EPIPE) + err = sock_error(sk) ? : -EPIPE; + if (err == -EPIPE && !(flags & MSG_NOSIGNAL)) + send_sig(SIGPIPE, current, 0); + return err; +} + static int dn_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size) { @@ -1902,9 +1967,6 @@ struct sockaddr_dn *addr = (struct sockaddr_dn *)msg->msg_name; struct sk_buff *skb = NULL; struct dn_skb_cb *cb; - unsigned char msgflg; - unsigned char *ptr; - unsigned short ack; int len; unsigned char fctype; long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); @@ -1915,17 +1977,26 @@ if (addr_len && (addr_len != sizeof(struct sockaddr_dn))) return -EINVAL; + /* + * The only difference between stream sockets and sequenced packet + * sockets is that the stream sockets always behave as if MSG_EOR + * has been set. + */ + if (sock->type == SOCK_STREAM) { + if (flags & MSG_EOR) + return -EINVAL; + flags |= MSG_EOR; + } + lock_sock(sk); err = dn_check_state(sk, addr, addr_len, &timeo, flags); if (err) - goto out; + goto out_err; if (sk->shutdown & SEND_SHUTDOWN) { - if (!(flags & MSG_NOSIGNAL)) - send_sig(SIGPIPE, current, 0); err = -EPIPE; - goto out; + goto out_err; } if ((flags & MSG_TRYHARD) && sk->dst_cache) @@ -1934,20 +2005,9 @@ mss = scp->segsize_rem; fctype = scp->services_rem & NSP_FC_MASK; - if (sk->dst_cache && sk->dst_cache->neighbour) { - struct dn_neigh *dn = (struct dn_neigh *)sk->dst_cache->neighbour; - if (dn->blksize < (mss + 11)) - mss = dn->blksize - 11; - } - - /* - * The only difference between SEQPACKET & STREAM sockets under DECnet - * is that SEQPACKET sockets set the MSG_EOR flag for the last - * session control message segment. - */ + mss = dn_current_mss(sk, flags); if (flags & MSG_OOB) { - mss = 16; queue = &scp->other_xmit_queue; if (size > mss) { err = -EMSGSIZE; @@ -2008,7 +2068,7 @@ cb = DN_SKB_CB(skb); - ptr = skb_put(skb, 9); + skb_reserve(skb, DN_MAX_NSP_DATA_HEADER); if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { err = -EFAULT; @@ -2016,45 +2076,26 @@ } if (flags & MSG_OOB) { - cb->segnum = scp->numoth; - seq_add(&scp->numoth, 1); - msgflg = 0x30; - ack = (scp->numoth_rcv & 0x0FFF) | 0x8000; - scp->ackxmt_oth = scp->numoth_rcv; + cb->nsp_flags = 0x30; if (fctype != NSP_FC_NONE) scp->flowrem_oth--; } else { - cb->segnum = scp->numdat; - seq_add(&scp->numdat, 1); - msgflg = 0x00; - if (sock->type == SOCK_STREAM) - msgflg = 0x60; + cb->nsp_flags = 0x00; if (scp->seg_total == 0) - msgflg |= 0x20; + cb->nsp_flags |= 0x20; scp->seg_total += len; if (((sent + len) == size) && (flags & MSG_EOR)) { - msgflg |= 0x40; + cb->nsp_flags |= 0x40; scp->seg_total = 0; if (fctype == NSP_FC_SCMC) scp->flowrem_dat--; } - ack = (scp->numdat_rcv & 0x0FFF) | 0x8000; - scp->ackxmt_dat = scp->numdat_rcv; if (fctype == NSP_FC_SRC) scp->flowrem_dat--; } - *ptr++ = msgflg; - *(__u16 *)ptr = scp->addrrem; - ptr += 2; - *(__u16 *)ptr = scp->addrloc; - ptr += 2; - *(__u16 *)ptr = dn_htons(ack); - ptr += 2; - *(__u16 *)ptr = dn_htons(cb->segnum); - sent += len; dn_nsp_queue_xmit(sk, skb, sk->allocation, flags & MSG_OOB); skb = NULL; @@ -2070,6 +2111,11 @@ release_sock(sk); return sent ? sent : err; + +out_err: + err = dn_error(sk, flags, err); + release_sock(sk); + return err; } static int dn_device_event(struct notifier_block *this, unsigned long event, @@ -2215,10 +2261,8 @@ .sendpage = sock_no_sendpage, }; -#ifdef CONFIG_SYSCTL void dn_register_sysctl(void); void dn_unregister_sysctl(void); -#endif MODULE_DESCRIPTION("The Linux DECnet Network Protocol"); @@ -2226,7 +2270,7 @@ MODULE_LICENSE("GPL"); -static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.5.40s (C) 1995-2002 Linux DECnet Project Team\n"; +static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.5.67s (C) 1995-2003 Linux DECnet Project Team\n"; static int __init decnet_init(void) { @@ -2253,9 +2297,7 @@ dn_fib_init(); #endif /* CONFIG_DECNET_ROUTER */ -#ifdef CONFIG_SYSCTL dn_register_sysctl(); -#endif /* CONFIG_SYSCTL */ /* * Prevent DECnet module unloading until its fixed properly. @@ -2273,9 +2315,7 @@ sock_unregister(AF_DECnet); dev_remove_pack(&dn_dix_packet_type); -#ifdef CONFIG_SYSCTL dn_unregister_sysctl(); -#endif /* CONFIG_SYSCTL */ unregister_netdevice_notifier(&dn_dev_notifier); diff -urN linux-2.5.67-bk9/net/decnet/dn_dev.c linux-2.5.67-bk10/net/decnet/dn_dev.c --- linux-2.5.67-bk9/net/decnet/dn_dev.c 2003-04-07 10:31:01.000000000 -0700 +++ linux-2.5.67-bk10/net/decnet/dn_dev.c 2003-04-19 04:35:43.000000000 -0700 @@ -36,9 +36,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -61,6 +63,7 @@ static rwlock_t dndev_lock = RW_LOCK_UNLOCKED; static struct net_device *decnet_default_device; +static struct notifier_block *dnaddr_chain; static struct dn_dev *dn_dev_create(struct net_device *dev, int *err); static void dn_dev_delete(struct net_device *dev); @@ -478,7 +481,7 @@ } rtmsg_ifa(RTM_DELADDR, ifa1); - + notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1); if (destroy) { dn_dev_free_ifa(ifa1); @@ -513,6 +516,7 @@ dn_db->ifa_list = ifa; rtmsg_ifa(RTM_NEWADDR, ifa); + notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); return 0; } @@ -609,7 +613,7 @@ dn_dev_del_ifa(dn_db, ifap, 0); } - ifa->ifa_local = dn_saddr2dn(sdn); + ifa->ifa_local = ifa->ifa_address = dn_saddr2dn(sdn); ret = dn_dev_set_ifa(dev, ifa); } @@ -686,7 +690,10 @@ if ((ifa = dn_dev_alloc_ifa()) == NULL) return -ENOBUFS; + if (!rta[IFA_ADDRESS - 1]) + rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1]; memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL-1]), 2); + memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS-1]), 2); ifa->ifa_flags = ifm->ifa_flags; ifa->ifa_scope = ifm->ifa_scope; ifa->ifa_dev = dn_db; @@ -716,7 +723,10 @@ ifm->ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT; ifm->ifa_scope = ifa->ifa_scope; ifm->ifa_index = ifa->ifa_dev->dev->ifindex; - RTA_PUT(skb, IFA_LOCAL, 2, &ifa->ifa_local); + if (ifa->ifa_address) + RTA_PUT(skb, IFA_ADDRESS, 2, &ifa->ifa_address); + if (ifa->ifa_local) + RTA_PUT(skb, IFA_LOCAL, 2, &ifa->ifa_local); if (ifa->ifa_label[0]) RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label); nlh->nlmsg_len = skb->tail - b; @@ -758,10 +768,7 @@ s_idx = cb->args[0]; s_dn_idx = dn_idx = cb->args[1]; read_lock(&dev_base_lock); - for(dev = dev_base, idx = 0; dev; dev = dev->next) { - if ((dn_db = dev->dn_ptr) == NULL) - continue; - idx++; + for(dev = dev_base, idx = 0; dev; dev = dev->next, idx++) { if (idx < s_idx) continue; if (idx > s_idx) @@ -773,7 +780,10 @@ if (dn_idx < s_dn_idx) continue; - if (dn_dev_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWADDR) <= 0) + if (dn_dev_fill_ifaddr(skb, ifa, + NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, + RTM_NEWADDR) <= 0) goto done; } } @@ -872,8 +882,6 @@ } -#ifdef CONFIG_DECNET_ROUTER - #define DRDELAY (5 * HZ) static int dn_am_i_a_router(struct dn_neigh *dn, struct dn_dev *dn_db, struct dn_ifaddr *ifa) @@ -981,12 +989,6 @@ else dn_send_router_hello(dev, ifa); } -#else -static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa) -{ - dn_send_endnode_hello(dev, ifa); -} -#endif #if 0 static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa) @@ -1175,7 +1177,7 @@ if ((ifa = dn_dev_alloc_ifa()) == NULL) return; - ifa->ifa_local = addr; + ifa->ifa_local = ifa->ifa_address = addr; ifa->ifa_flags = 0; ifa->ifa_scope = RT_SCOPE_UNIVERSE; strcpy(ifa->ifa_label, dev->name); @@ -1274,6 +1276,15 @@ rtnl_unlock(); } +int register_dnaddr_notifier(struct notifier_block *nb) +{ + return notifier_chain_register(&dnaddr_chain, nb); +} + +int unregister_dnaddr_notifier(struct notifier_block *nb) +{ + return notifier_chain_unregister(&dnaddr_chain, nb); +} #ifdef CONFIG_DECNET_SIOCGIFCONF /* @@ -1390,43 +1401,21 @@ static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] = { - { NULL, NULL, }, - { NULL, NULL, }, - { NULL, NULL, }, - { NULL, NULL, }, - - { dn_dev_rtm_newaddr, NULL, }, - { dn_dev_rtm_deladdr, NULL, }, - { NULL, dn_dev_dump_ifaddr, }, - { NULL, NULL, }, + [4] = { .doit = dn_dev_rtm_newaddr, }, + [5] = { .doit = dn_dev_rtm_deladdr, }, + [6] = { .dumpit = dn_dev_dump_ifaddr, }, #ifdef CONFIG_DECNET_ROUTER - { dn_fib_rtm_newroute, NULL, }, - { dn_fib_rtm_delroute, NULL, }, - { dn_cache_getroute, dn_fib_dump, }, - { NULL, NULL, }, + [8] = { .doit = dn_fib_rtm_newroute, }, + [9] = { .doit = dn_fib_rtm_delroute, }, + [10] = { .doit = dn_cache_getroute, .dumpit = dn_fib_dump, }, + [16] = { .doit = dn_fib_rtm_newrule, }, + [17] = { .doit = dn_fib_rtm_delrule, }, + [18] = { .dumpit = dn_fib_dump_rules, }, #else - { NULL, NULL, }, - { NULL, NULL, }, - { dn_cache_getroute, dn_cache_dump, }, - { NULL, NULL, }, + [10] = { .doit = dn_cache_getroute, .dumpit = dn_cache_dump, }, #endif - { NULL, NULL, }, - { NULL, NULL, }, - { NULL, NULL, }, - { NULL, NULL, }, -#ifdef CONFIG_DECNET_ROUTER - { dn_fib_rtm_newrule, NULL, }, - { dn_fib_rtm_delrule, NULL, }, - { NULL, dn_fib_dump_rules, }, - { NULL, NULL, } -#else - { NULL, NULL, }, - { NULL, NULL, }, - { NULL, NULL, }, - { NULL, NULL, } -#endif }; #ifdef MODULE diff -urN linux-2.5.67-bk9/net/decnet/dn_fib.c linux-2.5.67-bk10/net/decnet/dn_fib.c --- linux-2.5.67-bk9/net/decnet/dn_fib.c 2003-04-07 10:33:03.000000000 -0700 +++ linux-2.5.67-bk10/net/decnet/dn_fib.c 2003-04-19 04:35:43.000000000 -0700 @@ -12,6 +12,9 @@ * Alexey Kuznetsov : SMP locking changes * Steve Whitehouse : Rewrote it... Well to be more correct, I * copied most of it from the ipv4 fib code. + * Steve Whitehouse : Updated it in style and fixed a few bugs + * which were fixed in the ipv4 code since + * this code was copied from it. * */ #include @@ -31,12 +34,14 @@ #include #include #include +#include #include #include #include #include #include +#define RT_MIN_TABLE 1 #define for_fib_info() { struct dn_fib_info *fi;\ for(fi = dn_fib_info_list; fi; fi = fi->fib_next) @@ -52,7 +57,7 @@ extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb); - +static spinlock_t dn_fib_multipath_lock = SPIN_LOCK_UNLOCKED; static struct dn_fib_info *dn_fib_info_list; static rwlock_t dn_fib_info_lock = RW_LOCK_UNLOCKED; int dn_fib_info_cnt; @@ -62,18 +67,18 @@ int error; u8 scope; } dn_fib_props[RTA_MAX+1] = { - { 0, RT_SCOPE_NOWHERE }, /* RTN_UNSPEC */ - { 0, RT_SCOPE_UNIVERSE }, /* RTN_UNICAST */ - { 0, RT_SCOPE_HOST }, /* RTN_LOCAL */ - { -EINVAL, RT_SCOPE_NOWHERE }, /* RTN_BROADCAST */ - { -EINVAL, RT_SCOPE_NOWHERE }, /* RTN_ANYCAST */ - { -EINVAL, RT_SCOPE_NOWHERE }, /* RTN_MULTICAST */ - { -EINVAL, RT_SCOPE_UNIVERSE }, /* RTN_BLACKHOLE */ - { -EHOSTUNREACH, RT_SCOPE_UNIVERSE }, /* RTN_UNREACHABLE */ - { -EACCES, RT_SCOPE_UNIVERSE }, /* RTN_PROHIBIT */ - { -EAGAIN, RT_SCOPE_UNIVERSE }, /* RTN_THROW */ - { -EINVAL, RT_SCOPE_NOWHERE }, /* RTN_NAT */ - { -EINVAL, RT_SCOPE_NOWHERE } /* RTN_XRESOLVE */ + { .error = 0, .scope = RT_SCOPE_NOWHERE }, /* RTN_UNSPEC */ + { .error = 0, .scope = RT_SCOPE_UNIVERSE }, /* RTN_UNICAST */ + { .error = 0, .scope = RT_SCOPE_HOST }, /* RTN_LOCAL */ + { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_BROADCAST */ + { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_ANYCAST */ + { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_MULTICAST */ + { .error = -EINVAL, .scope = RT_SCOPE_UNIVERSE }, /* RTN_BLACKHOLE */ + { .error = -EHOSTUNREACH, .scope = RT_SCOPE_UNIVERSE }, /* RTN_UNREACHABLE */ + { .error = -EACCES, .scope = RT_SCOPE_UNIVERSE }, /* RTN_PROHIBIT */ + { .error = -EAGAIN, .scope = RT_SCOPE_UNIVERSE }, /* RTN_THROW */ + { .error = 0, .scope = RT_SCOPE_NOWHERE }, /* RTN_NAT */ + { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE } /* RTN_XRESOLVE */ }; void dn_fib_free_info(struct dn_fib_info *fi) @@ -108,7 +113,7 @@ write_unlock(&dn_fib_info_lock); } -static __inline__ int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi) +static inline int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi) { const struct dn_fib_nh *onh = ofi->fib_nh; @@ -124,7 +129,7 @@ return 0; } -static __inline__ struct dn_fib_info *dn_fib_find_info(const struct dn_fib_info *nfi) +static inline struct dn_fib_info *dn_fib_find_info(const struct dn_fib_info *nfi) { for_fib_info() { if (fi->fib_nhs != nfi->fib_nhs) @@ -132,6 +137,7 @@ if (nfi->fib_protocol == fi->fib_protocol && nfi->fib_prefsrc == fi->fib_prefsrc && nfi->fib_priority == fi->fib_priority && + memcmp(nfi->fib_metrics, fi->fib_metrics, sizeof(fi->fib_metrics)) == 0 && ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 && (nfi->fib_nhs == 0 || dn_fib_nh_comp(fi, nfi) == 0)) return fi; @@ -195,14 +201,18 @@ int err; if (nh->nh_gw) { - struct dn_fib_key key; + struct flowi fl; struct dn_fib_res res; + memset(&fl, 0, sizeof(fl)); + if (nh->nh_flags&RTNH_F_ONLINK) { struct net_device *dev; if (r->rtm_scope >= RT_SCOPE_LINK) return -EINVAL; + if (dnet_addr_type(nh->nh_gw) != RTN_UNICAST) + return -EINVAL; if ((dev = __dev_get_by_index(nh->nh_oif)) == NULL) return -ENODEV; if (!(dev->flags&IFF_UP)) @@ -213,23 +223,33 @@ return 0; } - memset(&key, 0, sizeof(key)); - key.dst = nh->nh_gw; - key.oif = nh->nh_oif; - key.scope = r->rtm_scope + 1; + memset(&fl, 0, sizeof(fl)); + fl.fld_dst = nh->nh_gw; + fl.oif = nh->nh_oif; + fl.fld_scope = r->rtm_scope + 1; - if (key.scope < RT_SCOPE_LINK) - key.scope = RT_SCOPE_LINK; + if (fl.fld_scope < RT_SCOPE_LINK) + fl.fld_scope = RT_SCOPE_LINK; - if ((err = dn_fib_lookup(&key, &res)) != 0) + if ((err = dn_fib_lookup(&fl, &res)) != 0) return err; + err = -EINVAL; + if (res.type != RTN_UNICAST && res.type != RTN_LOCAL) + goto out; nh->nh_scope = res.scope; nh->nh_oif = DN_FIB_RES_OIF(res); nh->nh_dev = DN_FIB_RES_DEV(res); - if (nh->nh_dev) - atomic_inc(&nh->nh_dev->refcnt); + if (nh->nh_dev == NULL) + goto out; + atomic_inc(&nh->nh_dev->refcnt); + err = -ENETDOWN; + if (!(nh->nh_dev->flags & IFF_UP)) + goto out; + err = 0; +out: dn_fib_res_put(&res); + return err; } else { struct net_device *dev; @@ -277,6 +297,20 @@ fi->fib_flags = r->rtm_flags; if (rta->rta_priority) fi->fib_priority = *rta->rta_priority; + if (rta->rta_mx) { + int attrlen = RTA_PAYLOAD(rta->rta_mx); + struct rtattr *attr = RTA_DATA(rta->rta_mx); + + while(RTA_OK(attr, attrlen)) { + unsigned flavour = attr->rta_type; + if (flavour) { + if (flavour > RTAX_MAX) + goto err_inval; + fi->fib_metrics[flavour-1] = *(unsigned*)RTA_DATA(attr); + } + attr = RTA_NEXT(attr, attrlen); + } + } if (rta->rta_prefsrc) memcpy(&fi->fib_prefsrc, rta->rta_prefsrc, 2); @@ -297,6 +331,13 @@ nh->nh_weight = 1; } + if (r->rtm_type == RTN_NAT) { + if (rta->rta_gw == NULL || nhs != 1 || rta->rta_oif) + goto err_inval; + memcpy(&fi->fib_nh->nh_gw, rta->rta_gw, 2); + goto link_it; + } + if (dn_fib_props[r->rtm_type].error) { if (rta->rta_gw || rta->rta_oif || rta->rta_mp) goto err_inval; @@ -324,14 +365,12 @@ } endfor_nexthops(fi) } -#if I_GET_AROUND_TO_FIXING_PREFSRC if (fi->fib_prefsrc) { if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL || memcmp(&fi->fib_prefsrc, rta->rta_dst, 2)) - if (dn_addr_type(fi->fib_prefsrc) != RTN_LOCAL) + if (dnet_addr_type(fi->fib_prefsrc) != RTN_LOCAL) goto err_inval; } -#endif link_it: if ((ofi = dn_fib_find_info(fi)) != NULL) { @@ -366,12 +405,53 @@ return NULL; } +int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowi *fl, struct dn_fib_res *res) +{ + int err = dn_fib_props[type].error; + + if (err == 0) { + if (fi->fib_flags & RTNH_F_DEAD) + return 1; + + res->fi = fi; + + switch(type) { + case RTN_NAT: + DN_FIB_RES_RESET(*res); + atomic_inc(&fi->fib_clntref); + return 0; + case RTN_UNICAST: + case RTN_LOCAL: + for_nexthops(fi) { + if (nh->nh_flags & RTNH_F_DEAD) + continue; + if (!fl->oif || fl->oif == nh->nh_oif) + break; + } + if (nhsel < fi->fib_nhs) { + res->nh_sel = nhsel; + atomic_inc(&fi->fib_clntref); + return 0; + } + endfor_nexthops(fi); + res->fi = NULL; + return 1; + default: + if (net_ratelimit()) + printk("DECnet: impossible routing event : dn_fib_semantic_match type=%d\n", type); + res->fi = NULL; + return -EINVAL; + } + } + return err; +} -void dn_fib_select_multipath(const struct dn_fib_key *key, struct dn_fib_res *res) +void dn_fib_select_multipath(const struct flowi *fl, struct dn_fib_res *res) { struct dn_fib_info *fi = res->fi; int w; + spin_lock_bh(&dn_fib_multipath_lock); if (fi->fib_power <= 0) { int power = 0; change_nexthops(fi) { @@ -381,6 +461,11 @@ } } endfor_nexthops(fi); fi->fib_power = power; + if (power < 0) { + spin_unlock_bh(&dn_fib_multipath_lock); + res->nh_sel = 0; + return; + } } w = jiffies % fi->fib_power; @@ -391,16 +476,16 @@ nh->nh_power--; fi->fib_power--; res->nh_sel = nhsel; + spin_unlock_bh(&dn_fib_multipath_lock); return; } } } endfor_nexthops(fi); - - printk(KERN_DEBUG "DECnet: BUG! dn_fib_select_multipath\n"); + res->nh_sel = 0; + spin_unlock_bh(&dn_fib_multipath_lock); } - /* * Punt to user via netlink for example, but for now * we just drop it. @@ -475,9 +560,9 @@ s_t = cb->args[0]; if (s_t == 0) - s_t = cb->args[0] = DN_MIN_TABLE; + s_t = cb->args[0] = RT_MIN_TABLE; - for(t = s_t; t < DN_NUM_TABLES; t++) { + for(t = s_t; t <= RT_TABLE_MAX; t++) { if (t < s_t) continue; if (t > s_t) @@ -494,6 +579,125 @@ return skb->len; } +static void fib_magic(int cmd, int type, __u16 dst, int dst_len, struct dn_ifaddr *ifa) +{ + struct dn_fib_table *tb; + struct { + struct nlmsghdr nlh; + struct rtmsg rtm; + } req; + struct dn_kern_rta rta; + + memset(&req.rtm, 0, sizeof(req.rtm)); + memset(&rta, 0, sizeof(rta)); + + if (type == RTN_UNICAST) + tb = dn_fib_get_table(RT_MIN_TABLE, 1); + else + tb = dn_fib_get_table(RT_TABLE_LOCAL, 1); + + if (tb == NULL) + return; + + req.nlh.nlmsg_len = sizeof(req); + req.nlh.nlmsg_type = cmd; + req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND; + req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_seq = 0; + + req.rtm.rtm_dst_len = dst_len; + req.rtm.rtm_table = tb->n; + req.rtm.rtm_protocol = RTPROT_KERNEL; + req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST); + req.rtm.rtm_type = type; + + rta.rta_dst = &dst; + rta.rta_prefsrc = &ifa->ifa_local; + rta.rta_oif = &ifa->ifa_dev->dev->ifindex; + + if (cmd == RTM_NEWROUTE) + tb->insert(tb, &req.rtm, &rta, &req.nlh, NULL); + else + tb->delete(tb, &req.rtm, &rta, &req.nlh, NULL); +} + +static void dn_fib_add_ifaddr(struct dn_ifaddr *ifa) +{ + + fib_magic(RTM_NEWROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa); + +#if 0 + if (!(dev->flags&IFF_UP)) + return; + /* In the future, we will want to add default routes here */ + +#endif +} + +static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa) +{ + int found_it = 0; + struct net_device *dev; + struct dn_dev *dn_db; + struct dn_ifaddr *ifa2; + + ASSERT_RTNL(); + + /* Scan device list */ + read_lock(&dev_base_lock); + for(dev = dev_base; dev; dev = dev->next) { + dn_db = dev->dn_ptr; + if (dn_db == NULL) + continue; + for(ifa2 = dn_db->ifa_list; ifa2; ifa2 = ifa2->ifa_next) { + if (ifa2->ifa_local == ifa->ifa_local) { + found_it = 1; + break; + } + } + } + read_unlock(&dev_base_lock); + + if (found_it == 0) { + fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa); + + if (dnet_addr_type(ifa->ifa_local) != RTN_LOCAL) { + if (dn_fib_sync_down(ifa->ifa_local, NULL, 0)) + dn_fib_flush(); + } + } +} + +static void dn_fib_disable_addr(struct net_device *dev, int force) +{ + if (dn_fib_sync_down(0, dev, force)) + dn_fib_flush(); + dn_rt_cache_flush(0); + neigh_ifdown(&dn_neigh_table, dev); +} + +static int dn_fib_dnaddr_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct dn_ifaddr *ifa = (struct dn_ifaddr *)ptr; + + switch(event) { + case NETDEV_UP: + dn_fib_add_ifaddr(ifa); + dn_fib_sync_up(ifa->ifa_dev->dev); + dn_rt_cache_flush(-1); + break; + case NETDEV_DOWN: + dn_fib_del_ifaddr(ifa); + if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) { + dn_fib_disable_addr(ifa->ifa_dev->dev, 1); + } else { + dn_rt_cache_flush(-1); + } + break; + } + return NOTIFY_DONE; +} + int dn_fib_sync_down(dn_address local, struct net_device *dev, int force) { int ret = 0; @@ -520,9 +724,11 @@ dead++; else if (nh->nh_dev == dev && nh->nh_scope != scope) { + spin_lock_bh(&dn_fib_multipath_lock); nh->nh_flags |= RTNH_F_DEAD; fi->fib_power -= nh->nh_power; nh->nh_power = 0; + spin_unlock_bh(&dn_fib_multipath_lock); dead++; } } endfor_nexthops(fi) @@ -556,11 +762,13 @@ if (nh->nh_dev != dev || dev->dn_ptr == NULL) continue; alive++; + spin_lock_bh(&dn_fib_multipath_lock); nh->nh_power = 0; nh->nh_flags &= ~RTNH_F_DEAD; + spin_unlock_bh(&dn_fib_multipath_lock); } endfor_nexthops(fi); - if (alive == fi->fib_nhs) { + if (alive > 0) { fi->fib_flags &= ~RTNH_F_DEAD; ret++; } @@ -574,7 +782,7 @@ struct dn_fib_table *tb; int id; - for(id = DN_NUM_TABLES; id > 0; id--) { + for(id = RT_TABLE_MAX; id > 0; id--) { if ((tb = dn_fib_get_table(id, 0)) == NULL) continue; flushed += tb->flush(tb); @@ -584,21 +792,6 @@ dn_rt_cache_flush(-1); } -int dn_fib_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - switch(cmd) { - case SIOCADDRT: - case SIOCDELRT: - return 0; - } - - return -EINVAL; -} - #ifdef CONFIG_PROC_FS static int decnet_rt_get_info(char *buffer, char **start, off_t offset, int length) @@ -620,7 +813,7 @@ } - for(i = DN_MIN_TABLE; (i <= DN_NUM_TABLES) && (count > 0); i++) { + for(i = RT_MIN_TABLE; (i <= RT_TABLE_MAX) && (count > 0); i++) { if ((tb = dn_fib_get_table(i, 0)) != NULL) { int n = tb->get_info(tb, ptr, first, count); count -= n; @@ -638,12 +831,18 @@ } #endif /* CONFIG_PROC_FS */ +static struct notifier_block dn_fib_dnaddr_notifier = { + .notifier_call = dn_fib_dnaddr_event, +}; + void __exit dn_fib_cleanup(void) { proc_net_remove("decnet_route"); dn_fib_table_cleanup(); dn_fib_rules_cleanup(); + + unregister_dnaddr_notifier(&dn_fib_dnaddr_notifier); } @@ -656,6 +855,8 @@ dn_fib_table_init(); dn_fib_rules_init(); + + register_dnaddr_notifier(&dn_fib_dnaddr_notifier); } diff -urN linux-2.5.67-bk9/net/decnet/dn_neigh.c linux-2.5.67-bk10/net/decnet/dn_neigh.c --- linux-2.5.67-bk9/net/decnet/dn_neigh.c 2003-04-07 10:31:58.000000000 -0700 +++ linux-2.5.67-bk10/net/decnet/dn_neigh.c 2003-04-19 04:35:43.000000000 -0700 @@ -20,6 +20,7 @@ * Steve Whitehouse : Fixed neighbour states (for now anyway). * Steve Whitehouse : Made error_report functions dummies. This * is not the right place to return skbs. + * Steve Whitehouse : Convert to seq_file * */ @@ -33,9 +34,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -160,7 +163,20 @@ return -EINVAL; } - dn->blksize = 230; + /* + * Make an estimate of the remote block size by assuming that its + * two less then the device mtu, which it true for ethernet (and + * other things which support long format headers) since there is + * an extra length field (of 16 bits) which isn't part of the + * ethernet headers and which the DECnet specs won't admit is part + * of the DECnet routing headers either. + * + * If we over estimate here its no big deal, the NSP negotiations + * will prevent us from sending packets which are too large for the + * remote node to handle. In any case this figure is normally updated + * by a hello message in most cases. + */ + dn->blksize = dev->mtu - 2; return 0; } @@ -330,7 +346,7 @@ * basically does a neigh_lookup(), but without comparing the device * field. This is required for the On-Ethernet cache */ -struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, void *ptr) +struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, const void *ptr) { struct neighbour *neigh; u32 hash_val; @@ -466,8 +482,6 @@ return 0; } - -#ifdef CONFIG_DECNET_ROUTER static char *dn_find_slot(char *base, int max, int priority) { int i; @@ -526,78 +540,200 @@ return t; } -#endif /* CONFIG_DECNET_ROUTER */ - #ifdef CONFIG_PROC_FS -static int dn_neigh_get_info(char *buffer, char **start, off_t offset, int length) + +struct dn_neigh_iter_state { + int bucket; +}; + +static struct neighbour *neigh_get_first(struct seq_file *seq) { - int len = 0; - off_t pos = 0; - off_t begin = 0; - struct neighbour *n; - int i; - char buf[DN_ASCBUF_LEN]; + struct dn_neigh_iter_state *state = seq->private; + struct neighbour *n = NULL; + + for(state->bucket = 0; + state->bucket <= NEIGH_HASHMASK; + ++state->bucket) { + n = dn_neigh_table.hash_buckets[state->bucket]; + if (n) + break; + } - len += sprintf(buffer + len, "Addr Flags State Use Blksize Dev\n"); + return n; +} - for(i=0;i <= NEIGH_HASHMASK; i++) { - read_lock_bh(&dn_neigh_table.lock); - n = dn_neigh_table.hash_buckets[i]; - for(; n != NULL; n = n->next) { - struct dn_neigh *dn = (struct dn_neigh *)n; - - read_lock(&n->lock); - len += sprintf(buffer+len, "%-7s %s%s%s %02x %02d %07ld %-8s\n", - dn_addr2asc(dn_ntohs(dn->addr), buf), - (dn->flags&DN_NDFLAG_R1) ? "1" : "-", - (dn->flags&DN_NDFLAG_R2) ? "2" : "-", - (dn->flags&DN_NDFLAG_P3) ? "3" : "-", - dn->n.nud_state, - atomic_read(&dn->n.refcnt), - dn->blksize, - (dn->n.dev) ? dn->n.dev->name : "?"); - read_unlock(&n->lock); - - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - - if (pos > offset + length) { - read_unlock_bh(&dn_neigh_table.lock); - goto done; - } - } +static struct neighbour *neigh_get_next(struct seq_file *seq, + struct neighbour *n) +{ + struct dn_neigh_iter_state *state = seq->private; + + n = n->next; +try_again: + if (n) + goto out; + if (++state->bucket > NEIGH_HASHMASK) + goto out; + n = dn_neigh_table.hash_buckets[state->bucket]; + goto try_again; +out: + return n; +} + +static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos) +{ + struct neighbour *n = neigh_get_first(seq); + + if (n) + while(*pos && (n = neigh_get_next(seq, n))) + --*pos; + return *pos ? NULL : n; +} + +static void *dn_neigh_get_idx(struct seq_file *seq, loff_t pos) +{ + void *rc; + read_lock_bh(&dn_neigh_table.lock); + rc = neigh_get_idx(seq, &pos); + if (!rc) { read_unlock_bh(&dn_neigh_table.lock); } + return rc; +} -done: +static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos) +{ + return *pos ? dn_neigh_get_idx(seq, *pos - 1) : (void*)1; +} + +static void *dn_neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + void *rc; - *start = buffer + (offset - begin); - len -= offset - begin; - if (len > length) len = length; + if (v == (void*)1) { + rc = dn_neigh_get_idx(seq, 0); + goto out; + } - return len; + rc = neigh_get_next(seq, v); + if (rc) + goto out; + read_unlock_bh(&dn_neigh_table.lock); +out: + ++*pos; + return rc; +} + +static void dn_neigh_seq_stop(struct seq_file *seq, void *v) +{ + if (v && v != (void*)1) + read_unlock_bh(&dn_neigh_table.lock); } +static inline void dn_neigh_format_entry(struct seq_file *seq, + struct neighbour *n) +{ + struct dn_neigh *dn = (struct dn_neigh *)n; + char buf[DN_ASCBUF_LEN]; + + read_lock(&n->lock); + seq_printf(seq, "%-7s %s%s%s %02x %02d %07ld %-8s\n", + dn_addr2asc(dn_ntohs(dn->addr), buf), + (dn->flags&DN_NDFLAG_R1) ? "1" : "-", + (dn->flags&DN_NDFLAG_R2) ? "2" : "-", + (dn->flags&DN_NDFLAG_P3) ? "3" : "-", + dn->n.nud_state, + atomic_read(&dn->n.refcnt), + dn->blksize, + (dn->n.dev) ? dn->n.dev->name : "?"); + read_unlock(&n->lock); +} + +static int dn_neigh_seq_show(struct seq_file *seq, void *v) +{ + if (v == (void*)1) { + seq_puts(seq, "Addr Flags State Use Blksize Dev\n"); + } else { + dn_neigh_format_entry(seq, v); + } + + return 0; +} + +static struct seq_operations dn_neigh_seq_ops = { + .start = dn_neigh_seq_start, + .next = dn_neigh_seq_next, + .stop = dn_neigh_seq_stop, + .show = dn_neigh_seq_show, +}; + +static int dn_neigh_seq_open(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + int rc = -ENOMEM; + struct dn_neigh_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); + + if (!s) + goto out; + + rc = seq_open(file, &dn_neigh_seq_ops); + if (rc) + goto out_kfree; + + seq = file->private_data; + seq->private = s; + memset(s, 0, sizeof(*s)); +out: + return rc; +out_kfree: + kfree(s); + goto out; +} + +static int dn_seq_release(struct inode *inode, struct file *file) +{ + struct seq_file *seq = (struct seq_file *)file->private_data; + + kfree(seq->private); + seq->private = NULL; + return seq_release(inode, file); +} + +static struct file_operations dn_neigh_seq_fops = { + .open = dn_neigh_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = dn_seq_release, +}; + +static int __init dn_neigh_proc_init(void) +{ + int rc = 0; + struct proc_dir_entry *p = create_proc_entry("decnet_neigh", S_IRUGO, proc_net); + if (p) + p->proc_fops = &dn_neigh_seq_fops; + else + rc = -ENOMEM; + return rc; +} + +#else +static int __init dn_neigh_proc_init(void) +{ + return 0; +} #endif void __init dn_neigh_init(void) { neigh_table_init(&dn_neigh_table); -#ifdef CONFIG_PROC_FS - proc_net_create("decnet_neigh",0,dn_neigh_get_info); -#endif /* CONFIG_PROC_FS */ + dn_neigh_proc_init(); } void __exit dn_neigh_cleanup(void) { - proc_net_remove("decnet_neigh"); neigh_table_clear(&dn_neigh_table); } diff -urN linux-2.5.67-bk9/net/decnet/dn_nsp_in.c linux-2.5.67-bk10/net/decnet/dn_nsp_in.c --- linux-2.5.67-bk9/net/decnet/dn_nsp_in.c 2003-04-07 10:31:02.000000000 -0700 +++ linux-2.5.67-bk10/net/decnet/dn_nsp_in.c 2003-04-19 04:35:43.000000000 -0700 @@ -434,7 +434,15 @@ sk->state_change(sk); } - dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC); + /* + * It appears that its possible for remote machines to send disc + * init messages with no port identifier if we are in the CI and + * possibly also the CD state. Obviously we shouldn't reply with + * a message if we don't know what the end point is. + */ + if (scp->addrrem) { + dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC); + } scp->persist_fxn = dn_destroy_timer; scp->persist = dn_nsp_persist(sk); diff -urN linux-2.5.67-bk9/net/decnet/dn_nsp_out.c linux-2.5.67-bk10/net/decnet/dn_nsp_out.c --- linux-2.5.67-bk9/net/decnet/dn_nsp_out.c 2003-04-07 10:32:54.000000000 -0700 +++ linux-2.5.67-bk10/net/decnet/dn_nsp_out.c 2003-04-19 04:35:43.000000000 -0700 @@ -21,6 +21,7 @@ * Paul Koning: Connect Confirm message fix. * Eduardo Serrat: Fix to stop dn_nsp_do_disc() sending malformed packets. * Steve Whitehouse: dn_nsp_output() and friends needed a spring clean + * Steve Whitehouse: Moved dn_nsp_send() in here from route.h */ /****************************************************************************** @@ -63,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +73,41 @@ static int nsp_backoff[NSP_MAXRXTSHIFT + 1] = { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; +static void dn_nsp_send(struct sk_buff *skb) +{ + struct sock *sk = skb->sk; + struct dn_scp *scp = DN_SK(sk); + struct dst_entry *dst; + struct flowi fl; + + skb->h.raw = skb->data; + scp->stamp = jiffies; + + dst = sk_dst_check(sk, 0); + if (dst) { +try_again: + skb->dst = dst; + dst_output(skb); + return; + } + + memset(&fl, 0, sizeof(fl)); + fl.oif = sk->bound_dev_if; + fl.fld_src = dn_saddr2dn(&scp->addr); + fl.fld_dst = dn_saddr2dn(&scp->peer); + dn_sk_ports_copy(&fl, scp); + if (dn_route_output_sock(&sk->dst_cache, &fl, sk, 0) == 0) { + dst = sk_dst_get(sk); + sk->route_caps = dst->dev->features; + goto try_again; + } + + sk->err = EHOSTUNREACH; + if (!test_bit(SOCK_DEAD, &sk->flags)) + sk->state_change(sk); +} + + /* * If sk == NULL, then we assume that we are supposed to be making * a routing layer skb. If sk != NULL, then we are supposed to be @@ -356,12 +393,33 @@ return ptr; } +static unsigned short *dn_nsp_mk_data_header(struct sock *sk, struct sk_buff *skb, int oth) +{ + struct dn_scp *scp = DN_SK(sk); + struct dn_skb_cb *cb = DN_SKB_CB(skb); + unsigned short *ptr = dn_mk_ack_header(sk, skb, cb->nsp_flags, 11, oth); + + if (unlikely(oth)) { + cb->segnum = scp->numoth; + seq_add(&scp->numoth, 1); + } else { + cb->segnum = scp->numdat; + seq_add(&scp->numdat, 1); + } + *(ptr++) = dn_htons(cb->segnum); + + return ptr; +} + void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, int gfp, int oth) { struct dn_scp *scp = DN_SK(sk); struct dn_skb_cb *cb = DN_SKB_CB(skb); unsigned long t = ((scp->nsp_srtt >> 2) + scp->nsp_rttvar) >> 1; + cb->xmit_count = 0; + dn_nsp_mk_data_header(sk, skb, oth); + /* * Slow start: If we have been idle for more than * one RTT, then reset window to min size. @@ -369,10 +427,6 @@ if ((jiffies - scp->stamp) > t) scp->snd_window = NSP_MIN_WINDOW; - /* printk(KERN_DEBUG "Window: %lu\n", scp->snd_window); */ - - cb->xmit_count = 0; - if (oth) skb_queue_tail(&scp->other_xmit_queue, skb); else @@ -630,19 +684,15 @@ { struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb; - unsigned short *segnum; unsigned char *ptr; int gfp = GFP_ATOMIC; - if ((skb = dn_alloc_skb(sk, 13, gfp)) == NULL) + if ((skb = dn_alloc_skb(sk, DN_MAX_NSP_DATA_HEADER + 2, gfp)) == NULL) return; - skb_reserve(skb, 13); - segnum = dn_mk_ack_header(sk, skb, 0x10, 13, 1); - *segnum = dn_htons(scp->numoth); - DN_SKB_CB(skb)->segnum = scp->numoth; - seq_add(&scp->numoth, 1); - ptr = (unsigned char *)(segnum + 1); + skb_reserve(skb, DN_MAX_NSP_DATA_HEADER); + ptr = skb_put(skb, 2); + DN_SKB_CB(skb)->nsp_flags = 0x10; *ptr++ = lsflags; *ptr = fcval; diff -urN linux-2.5.67-bk9/net/decnet/dn_route.c linux-2.5.67-bk10/net/decnet/dn_route.c --- linux-2.5.67-bk9/net/decnet/dn_route.c 2003-04-07 10:32:51.000000000 -0700 +++ linux-2.5.67-bk10/net/decnet/dn_route.c 2003-04-19 04:35:43.000000000 -0700 @@ -37,7 +37,8 @@ * backlog congestion level return codes. * Steve Whitehouse : Fixed bug where routes were set up with * no ref count on net devices. - * + * Steve Whitehouse : RCU for the route cache + * Steve Whitehouse : Preparations for the flow cache */ /****************************************************************************** @@ -65,17 +66,19 @@ #include #include #include +#include #include -#include #include #include #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -86,7 +89,7 @@ struct dn_rt_hash_bucket { struct dn_route *chain; - rwlock_t lock; + spinlock_t lock; } __attribute__((__aligned__(8))); extern struct neigh_table dn_neigh_table; @@ -134,6 +137,18 @@ return dn_rt_hash_mask & (unsigned)tmp; } +static inline void dnrt_free(struct dn_route *rt) +{ + call_rcu(&rt->u.dst.rcu_head, (void (*)(void *))dst_free, &rt->u.dst); +} + +static inline void dnrt_drop(struct dn_route *rt) +{ + if (rt) + dst_release(&rt->u.dst); + call_rcu(&rt->u.dst.rcu_head, (void (*)(void *))dst_free, &rt->u.dst); +} + static void SMP_TIMER_NAME(dn_dst_check_expire)(unsigned long dummy) { int i; @@ -144,7 +159,7 @@ for(i = 0; i <= dn_rt_hash_mask; i++) { rtp = &dn_rt_hash_table[i].chain; - write_lock(&dn_rt_hash_table[i].lock); + spin_lock(&dn_rt_hash_table[i].lock); while((rt=*rtp) != NULL) { if (atomic_read(&rt->u.dst.__refcnt) || (now - rt->u.dst.lastuse) < expire) { @@ -153,9 +168,9 @@ } *rtp = rt->u.rt_next; rt->u.rt_next = NULL; - dst_free(&rt->u.dst); + dnrt_free(rt); } - write_unlock(&dn_rt_hash_table[i].lock); + spin_unlock(&dn_rt_hash_table[i].lock); if ((jiffies - now) > 0) break; @@ -175,7 +190,7 @@ for(i = 0; i <= dn_rt_hash_mask; i++) { - write_lock_bh(&dn_rt_hash_table[i].lock); + spin_lock_bh(&dn_rt_hash_table[i].lock); rtp = &dn_rt_hash_table[i].chain; while((rt=*rtp) != NULL) { @@ -186,10 +201,10 @@ } *rtp = rt->u.rt_next; rt->u.rt_next = NULL; - dst_free(&rt->u.dst); + dnrt_drop(rt); break; } - write_unlock_bh(&dn_rt_hash_table[i].lock); + spin_unlock_bh(&dn_rt_hash_table[i].lock); } return 0; @@ -216,19 +231,53 @@ return; } -static void dn_insert_route(struct dn_route *rt, unsigned hash) +static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) { + return memcmp(&fl1->nl_u.dn_u, &fl2->nl_u.dn_u, sizeof(fl1->nl_u.dn_u)) == 0 && + fl1->oif == fl2->oif && + fl1->iif == fl2->iif; +} + +static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp) +{ + struct dn_route *rth, **rthp; unsigned long now = jiffies; - write_lock_bh(&dn_rt_hash_table[hash].lock); + rthp = &dn_rt_hash_table[hash].chain; + + spin_lock_bh(&dn_rt_hash_table[hash].lock); + while((rth = *rthp) != NULL) { + if (compare_keys(&rth->fl, &rt->fl)) { + /* Put it first */ + *rthp = rth->u.rt_next; + smp_wmb(); + rth->u.rt_next = dn_rt_hash_table[hash].chain; + smp_wmb(); + dn_rt_hash_table[hash].chain = rth; + + rth->u.dst.__use++; + dst_hold(&rth->u.dst); + rth->u.dst.lastuse = now; + spin_unlock_bh(&dn_rt_hash_table[hash].lock); + + dnrt_drop(rt); + *rp = rth; + return 0; + } + rthp = &rth->u.rt_next; + } + + smp_wmb(); rt->u.rt_next = dn_rt_hash_table[hash].chain; + smp_wmb(); dn_rt_hash_table[hash].chain = rt; dst_hold(&rt->u.dst); rt->u.dst.__use++; rt->u.dst.lastuse = now; - - write_unlock_bh(&dn_rt_hash_table[hash].lock); + spin_unlock_bh(&dn_rt_hash_table[hash].lock); + *rp = rt; + return 0; } void SMP_TIMER_NAME(dn_run_flush)(unsigned long dummy) @@ -237,7 +286,7 @@ struct dn_route *rt, *next; for(i = 0; i < dn_rt_hash_mask; i++) { - write_lock_bh(&dn_rt_hash_table[i].lock); + spin_lock_bh(&dn_rt_hash_table[i].lock); if ((rt = xchg(&dn_rt_hash_table[i].chain, NULL)) == NULL) goto nothing_to_declare; @@ -249,7 +298,7 @@ } nothing_to_declare: - write_unlock_bh(&dn_rt_hash_table[i].lock); + spin_unlock_bh(&dn_rt_hash_table[i].lock); } } @@ -628,51 +677,50 @@ return err; } -#ifdef CONFIG_DECNET_ROUTER static int dn_forward(struct sk_buff *skb) { struct dn_skb_cb *cb = DN_SKB_CB(skb); struct dst_entry *dst = skb->dst; - struct neighbour *neigh; + struct dn_dev *dn_db = dst->dev->dn_ptr; + struct dn_route *rt; + struct neighbour *neigh = dst->neighbour; + int header_len; #ifdef CONFIG_NETFILTER struct net_device *dev = skb->dev; #endif - int err = -EINVAL; - if ((neigh = dst->neighbour) == NULL) - goto error; + if (skb->pkt_type != PACKET_HOST) + goto drop; + + /* Ensure that we have enough space for headers */ + rt = (struct dn_route *)skb->dst; + header_len = dn_db->use_long ? 21 : 6; + if (skb_cow(skb, LL_RESERVED_SPACE(rt->u.dst.dev)+header_len)) + goto drop; /* * Hop count exceeded. */ - err = NET_RX_DROP; if (++cb->hops > 30) goto drop; - skb->dev = dst->dev; + skb->dev = rt->u.dst.dev; /* * If packet goes out same interface it came in on, then set * the Intra-Ethernet bit. This has no effect for short * packets, so we don't need to test for them here. */ - if (cb->iif == dst->dev->ifindex) + cb->rt_flags &= ~DN_RT_F_IE; + if (rt->rt_flags | RTCF_DOREDIRECT) cb->rt_flags |= DN_RT_F_IE; - else - cb->rt_flags &= ~DN_RT_F_IE; return NF_HOOK(PF_DECnet, NF_DN_FORWARD, skb, dev, skb->dev, neigh->output); - -error: - if (net_ratelimit()) - printk(KERN_DEBUG "dn_forward: This should not happen\n"); drop: kfree_skb(skb); - - return err; + return NET_RX_DROP; } -#endif /* * Drop packet. This is used for endnodes and for @@ -703,182 +751,450 @@ return NET_RX_BAD; } -static int dn_route_output_slow(struct dst_entry **pprt, dn_address dst, dn_address src, int flags) +static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) { + struct dn_fib_info *fi = res->fi; + struct net_device *dev = rt->u.dst.dev; + struct neighbour *n; + unsigned mss; + + if (fi) { + if (DN_FIB_RES_GW(*res) && + DN_FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) + rt->rt_gateway = DN_FIB_RES_GW(*res); + memcpy(rt->u.dst.metrics, fi->fib_metrics, + sizeof(rt->u.dst.metrics)); + } + rt->rt_type = res->type; + + if (dev != NULL && rt->u.dst.neighbour == NULL) { + n = __neigh_lookup_errno(&dn_neigh_table, &rt->rt_gateway, dev); + if (IS_ERR(n)) + return PTR_ERR(n); + rt->u.dst.neighbour = n; + } + + if (rt->u.dst.metrics[RTAX_MTU-1] == 0 || + rt->u.dst.metrics[RTAX_MTU-1] > rt->u.dst.dev->mtu) + rt->u.dst.metrics[RTAX_MTU-1] = rt->u.dst.dev->mtu; + mss = dn_mss_from_pmtu(dev, dst_pmtu(&rt->u.dst)); + if (rt->u.dst.metrics[RTAX_ADVMSS-1] == 0 || + rt->u.dst.metrics[RTAX_ADVMSS-1] > mss) + rt->u.dst.metrics[RTAX_ADVMSS-1] = mss; + return 0; +} + +static inline int dn_match_addr(__u16 addr1, __u16 addr2) +{ + __u16 tmp = dn_ntohs(addr1) ^ dn_ntohs(addr2); + int match = 16; + while(tmp) + tmp >>= 1, match--; + return match; +} + +static __u16 dnet_select_source(const struct net_device *dev, __u16 daddr, int scope) +{ + __u16 saddr = 0; + struct dn_dev *dn_db = dev->dn_ptr; + struct dn_ifaddr *ifa; + int best_match = 0; + int ret; + + read_lock(&dev_base_lock); + for(ifa = dn_db->ifa_list; ifa; ifa = ifa->ifa_next) { + if (ifa->ifa_scope > scope) + continue; + if (!daddr) { + saddr = ifa->ifa_local; + break; + } + ret = dn_match_addr(daddr, ifa->ifa_local); + if (ret > best_match) + saddr = ifa->ifa_local; + if (best_match == 0) + saddr = ifa->ifa_local; + } + read_unlock(&dev_base_lock); + + return saddr; +} + +static inline __u16 __dn_fib_res_prefsrc(struct dn_fib_res *res) +{ + return dnet_select_source(DN_FIB_RES_DEV(*res), DN_FIB_RES_GW(*res), res->scope); +} + +static inline __u16 dn_fib_rules_map_destination(__u16 daddr, struct dn_fib_res *res) +{ + __u16 mask = dnet_make_mask(res->prefixlen); + return (daddr&~mask)|res->fi->fib_nh->nh_gw; +} + +static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *oldflp, int try_hard) +{ + struct flowi fl = { .nl_u = { .dn_u = + { .daddr = oldflp->fld_dst, + .saddr = oldflp->fld_src, + .scope = RT_SCOPE_UNIVERSE, +#ifdef CONFIG_DECNET_ROUTE_FWMARK + .fwmark = oldflp->fld_fwmark +#endif + } }, + .iif = loopback_dev.ifindex, + .oif = oldflp->oif }; struct dn_route *rt = NULL; - struct net_device *dev = NULL; + struct net_device *dev_out = NULL; struct neighbour *neigh = NULL; - struct dn_dev *dn_db; unsigned hash; - -#ifdef CONFIG_DECNET_ROUTER - struct dn_fib_key key; - struct dn_fib_res res; + unsigned flags = 0; + struct dn_fib_res res = { .fi = NULL, .type = RTN_UNICAST }; int err; + int free_res = 0; + __u16 gateway = 0; - key.src = src; - key.dst = dst; - key.iif = 0; - key.oif = 0; - key.fwmark = 0; - key.scope = RT_SCOPE_UNIVERSE; - - if ((err = dn_fib_lookup(&key, &res)) == 0) { - switch(res.type) { - case RTN_UNICAST: - /* - * This method of handling multipath - * routes is a hack and will change. - * It works for now though. - */ - if (res.fi->fib_nhs) - dn_fib_select_multipath(&key, &res); - neigh = __neigh_lookup(&dn_neigh_table, &DN_FIB_RES_GW(res), DN_FIB_RES_DEV(res), 1); - err = -ENOBUFS; - if (!neigh) - break; - err = 0; - break; - case RTN_UNREACHABLE: - err = -EHOSTUNREACH; - break; - default: - err = -EINVAL; + if (decnet_debug_level & 16) + printk(KERN_DEBUG + "dn_route_output_slow: dst=%04x src=%04x mark=%d" + " iif=%d oif=%d\n", oldflp->fld_dst, oldflp->fld_src, + oldflp->fld_fwmark, loopback_dev.ifindex, oldflp->oif); + + /* If we have an output interface, verify its a DECnet device */ + if (oldflp->oif) { + dev_out = dev_get_by_index(oldflp->oif); + err = -ENODEV; + if (dev_out && dev_out->dn_ptr == NULL) { + dev_put(dev_out); + dev_out = NULL; } - dn_fib_res_put(&res); - if (err < 0) - return err; - goto got_route; + if (dev_out == NULL) + goto out; } - if (err != -ESRCH) - return err; -#endif + /* If we have a source address, verify that its a local address */ + if (oldflp->fld_src) { + err = -EADDRNOTAVAIL; + + if (dev_out) { + if (dn_dev_islocal(dev_out, oldflp->fld_src)) + goto source_ok; + dev_put(dev_out); + goto out; + } + read_lock(&dev_base_lock); + for(dev_out = dev_base; dev_out; dev_out = dev_out->next) { + if (!dev_out->dn_ptr) + continue; + if (dn_dev_islocal(dev_out, oldflp->fld_src)) + break; + } + read_unlock(&dev_base_lock); + if (dev_out == NULL) + goto out; + dev_hold(dev_out); +source_ok: + } - /* Look in On-Ethernet cache first */ - if (!(flags & MSG_TRYHARD)) { - if ((neigh = dn_neigh_lookup(&dn_neigh_table, &dst)) != NULL) - goto got_route; + /* No destination? Assume its local */ + if (!fl.fld_dst) { + fl.fld_dst = fl.fld_src; +#if 0 + if (!fl.fld_dst) + /* grab an address from loopback? */ +#endif + err = -EADDRNOTAVAIL; + if (dev_out) + dev_put(dev_out); + if (!fl.fld_dst) + goto out; + dev_out = &loopback_dev; + dev_hold(dev_out); + fl.oif = loopback_dev.ifindex; + res.type = RTN_LOCAL; + goto make_route; } - dev = dn_dev_get_default(); - if (dev == NULL) - return -EINVAL; + if (decnet_debug_level & 16) + printk(KERN_DEBUG + "dn_route_output_slow: initial checks complete." + " dst=%o4x src=%04x oif=%d try_hard=%d\n", fl.fld_dst, + fl.fld_src, fl.oif, try_hard); - dn_db = dev->dn_ptr; + /* + * N.B. If the kernel is compiled without router support then + * dn_fib_lookup() will evaluate to non-zero so this if () block + * will always be executed. + */ + err = -ESRCH; + if (try_hard || (err = dn_fib_lookup(&fl, &res)) != 0) { + struct dn_dev *dn_db; + if (err != -ESRCH) + goto out; + /* + * Here the fallback is basically the standard algorithm for + * routing in endnodes which is described in the DECnet routing + * docs + * + * If we are not trying hard, look in neighbour cache. + * The result is tested to ensure that if a specific output + * device/source address was requested, then we honour that + * here + */ + if (!try_hard) { + neigh = dn_neigh_lookup(&dn_neigh_table, &fl.fld_dst); + if (neigh) { + if ((oldflp->oif && + (neigh->dev->ifindex != oldflp->oif)) || + (oldflp->fld_src && + (!dn_dev_islocal(neigh->dev, + oldflp->fld_src)))) { + neigh_release(neigh); + neigh = NULL; + } else { + if (dev_out) + dev_put(dev_out); + if (dn_dev_islocal(neigh->dev, fl.fld_dst)) { + dev_out = &loopback_dev; + res.type = RTN_LOCAL; + } else { + dev_out = neigh->dev; + } + dev_hold(dev_out); + goto select_source; + } + } + } - /* Check to see if its one of our own local addresses */ - if (dn_dev_islocal(dev, dst)) { - struct net_device *lo = &loopback_dev; - if (lo->dn_ptr) { - neigh = __neigh_lookup(&dn_neigh_table, &dst, lo, 1); - if (neigh) - goto got_route; - } - if (net_ratelimit()) - printk("dn_route_output_slow: Dest is local interface address, but loopback device is not up\n"); - dev_put(dev); - return -EINVAL; + /* Not there? Perhaps its a local address */ + if (dev_out == NULL) + dev_out = dn_dev_get_default(); + err = -ENODEV; + if (dev_out == NULL) + goto out; + dn_db = dev_out->dn_ptr; + /* Possible improvement - check all devices for local addr */ + if (dn_dev_islocal(dev_out, fl.fld_dst)) { + dev_put(dev_out); + dev_out = &loopback_dev; + dev_hold(dev_out); + res.type = RTN_LOCAL; + goto select_source; + } + /* Not local either.... try sending it to the default router */ + neigh = neigh_clone(dn_db->router); + BUG_ON(neigh && neigh->dev != dev_out); + + /* Ok then, we assume its directly connected and move on */ +select_source: + if (neigh) + gateway = ((struct dn_neigh *)neigh)->addr; + if (gateway == 0) + gateway = fl.fld_dst; + if (fl.fld_src == 0) { + fl.fld_src = dnet_select_source(dev_out, gateway, + res.type == RTN_LOCAL ? + RT_SCOPE_HOST : + RT_SCOPE_LINK); + if (fl.fld_src == 0 && res.type != RTN_LOCAL) + goto e_addr; + } + fl.oif = dev_out->ifindex; + goto make_route; } + free_res = 1; - /* Try default router */ - if ((neigh = neigh_clone(dn_db->router)) != NULL) - goto got_route; - - /* Send to default device (and hope for the best) if above fail */ - if ((neigh = __neigh_lookup(&dn_neigh_table, &dst, dev, 1)) != NULL) - goto got_route; - - dev_put(dev); - return -EINVAL; - -got_route: - if (dev) - dev_put(dev); + if (res.type == RTN_NAT) + goto e_inval; - if ((rt = dst_alloc(&dn_dst_ops)) == NULL) { - neigh_release(neigh); - return -EINVAL; - } + if (res.type == RTN_LOCAL) { + if (!fl.fld_src) + fl.fld_src = fl.fld_dst; + if (dev_out) + dev_put(dev_out); + dev_out = &loopback_dev; + dev_hold(dev_out); + fl.oif = dev_out->ifindex; + if (res.fi) + dn_fib_info_put(res.fi); + res.fi = NULL; + goto make_route; + } + + if (res.fi->fib_nhs > 1 && fl.oif == 0) + dn_fib_select_multipath(&fl, &res); + + /* + * We could add some logic to deal with default routes here and + * get rid of some of the special casing above. + */ - dn_db = (struct dn_dev *)neigh->dev->dn_ptr; + if (!fl.fld_src) + fl.fld_src = DN_FIB_RES_PREFSRC(res); - rt->key.saddr = src; - rt->rt_saddr = src; - rt->key.daddr = dst; - rt->rt_daddr = dst; - rt->key.oif = neigh ? neigh->dev->ifindex : -1; - rt->key.iif = 0; - rt->key.fwmark = 0; + if (dev_out) + dev_put(dev_out); + dev_out = DN_FIB_RES_DEV(res); + dev_hold(dev_out); + fl.oif = dev_out->ifindex; + gateway = DN_FIB_RES_GW(res); + +make_route: + if (dev_out->flags & IFF_LOOPBACK) + flags |= RTCF_LOCAL; + + rt = dst_alloc(&dn_dst_ops); + if (rt == NULL) + goto e_nobufs; + + atomic_set(&rt->u.dst.__refcnt, 1); + rt->u.dst.flags = DST_HOST; + + rt->fl.fld_src = oldflp->fld_src; + rt->fl.fld_dst = oldflp->fld_dst; + rt->fl.oif = oldflp->oif; + rt->fl.iif = 0; +#ifdef CONFIG_DECNET_ROUTE_FWMARK + rt->fl.fld_fwmark = flp->fld_fwmark; +#endif + + rt->rt_saddr = fl.fld_src; + rt->rt_daddr = fl.fld_dst; + rt->rt_gateway = gateway ? gateway : fl.fld_dst; + + rt->rt_dst_map = fl.fld_dst; + rt->rt_src_map = fl.fld_src; + rt->u.dst.dev = dev_out; + dev_hold(dev_out); rt->u.dst.neighbour = neigh; - rt->u.dst.dev = neigh ? neigh->dev : NULL; - if (rt->u.dst.dev) - dev_hold(rt->u.dst.dev); - rt->u.dst.lastuse = jiffies; - rt->u.dst.output = dn_output; - rt->u.dst.input = dn_rt_bug; + neigh = NULL; - if (neigh->dev->flags & IFF_LOOPBACK) - rt->u.dst.input = dn_nsp_rx; + rt->u.dst.lastuse = jiffies; + rt->u.dst.output = dn_output; + rt->u.dst.input = dn_rt_bug; + rt->rt_flags = flags; + if (flags & RTCF_LOCAL) + rt->u.dst.output = dn_nsp_rx; + + if (dn_rt_set_next_hop(rt, &res)) + goto e_neighbour; + + hash = dn_hash(rt->fl.fld_src, rt->fl.fld_dst); + dn_insert_route(rt, hash, (struct dn_route **)pprt); + err = 0; - hash = dn_hash(rt->key.saddr, rt->key.daddr); - dn_insert_route(rt, hash); - *pprt = &rt->u.dst; +done: + if (neigh) + neigh_release(neigh); + if (free_res) + dn_fib_res_put(&res); + if (dev_out) + dev_put(dev_out); +out: + return err; - return 0; +e_addr: + err = -EADDRNOTAVAIL; + goto done; +e_inval: + err = -EINVAL; + goto done; +e_nobufs: + err = -ENOBUFS; + goto done; +e_neighbour: + dst_free(&rt->u.dst); + goto e_nobufs; } -int dn_route_output(struct dst_entry **pprt, dn_address dst, dn_address src, int flags) + +/* + * N.B. The flags may be moved into the flowi at some future stage. + */ +static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *flp, int flags) { - unsigned hash = dn_hash(src, dst); + unsigned hash = dn_hash(flp->fld_src, flp->fld_dst); struct dn_route *rt = NULL; if (!(flags & MSG_TRYHARD)) { - read_lock_bh(&dn_rt_hash_table[hash].lock); + rcu_read_lock(); for(rt = dn_rt_hash_table[hash].chain; rt; rt = rt->u.rt_next) { - if ((dst == rt->key.daddr) && - (src == rt->key.saddr) && - (rt->key.iif == 0) && - (rt->key.oif != 0)) { + read_barrier_depends(); + if ((flp->fld_dst == rt->fl.fld_dst) && + (flp->fld_src == rt->fl.fld_src) && +#ifdef CONFIG_DECNET_ROUTE_FWMARK + (flp->fld_fwmark == rt->fl.fld_fwmark) && +#endif + (rt->fl.iif == 0) && + (rt->fl.oif == flp->oif)) { rt->u.dst.lastuse = jiffies; dst_hold(&rt->u.dst); rt->u.dst.__use++; - read_unlock_bh(&dn_rt_hash_table[hash].lock); + rcu_read_unlock(); *pprt = &rt->u.dst; return 0; } } - read_unlock_bh(&dn_rt_hash_table[hash].lock); + rcu_read_unlock(); + } + + return dn_route_output_slow(pprt, flp, flags); +} + +static int dn_route_output_key(struct dst_entry **pprt, struct flowi *flp, int flags) +{ + int err; + + err = __dn_route_output_key(pprt, flp, flags); + if (err == 0 && flp->proto) { + err = xfrm_lookup(pprt, flp, NULL, 0); } + return err; +} + +int dn_route_output_sock(struct dst_entry **pprt, struct flowi *fl, struct sock *sk, int flags) +{ + int err; - return dn_route_output_slow(pprt, dst, src, flags); + err = __dn_route_output_key(pprt, fl, flags & MSG_TRYHARD); + if (err == 0 && fl->proto) { + err = xfrm_lookup(pprt, fl, sk, !(flags & MSG_DONTWAIT)); + } + return err; } static int dn_route_input_slow(struct sk_buff *skb) { struct dn_route *rt = NULL; struct dn_skb_cb *cb = DN_SKB_CB(skb); - struct net_device *dev = skb->dev; + struct net_device *in_dev = skb->dev; + struct net_device *out_dev = NULL; struct dn_dev *dn_db; struct neighbour *neigh = NULL; - int (*dnrt_input)(struct sk_buff *skb); - int (*dnrt_output)(struct sk_buff *skb); - u32 fwmark = 0; unsigned hash; - dn_address saddr = cb->src; - dn_address daddr = cb->dst; -#ifdef CONFIG_DECNET_ROUTER - struct dn_fib_key key; - struct dn_fib_res res; - int err; + int flags = 0; + __u16 gateway = 0; + struct flowi fl = { .nl_u = { .dn_u = + { .daddr = cb->dst, + .saddr = cb->src, + .scope = RT_SCOPE_UNIVERSE, +#ifdef CONFIG_DECNET_ROUTE_FWMARK + .fwmark = skb->fwmark #endif + } }, + .iif = skb->dev->ifindex }; + struct dn_fib_res res = { .fi = NULL, .type = RTN_UNREACHABLE }; + int err = -EINVAL; + int free_res = 0; - if (dev == NULL) - return -EINVAL; + dev_hold(in_dev); - if ((dn_db = dev->dn_ptr) == NULL) - return -EINVAL; + if ((dn_db = in_dev->dn_ptr) == NULL) + goto out; + + /* Zero source addresses are not allowed */ + if (fl.fld_src == 0) + goto out; /* * In this case we've just received a packet from a source @@ -887,122 +1203,183 @@ * other nasties. Loopback packets already have the dst attached * so this only affects packets which have originated elsewhere. */ - if (dn_dev_islocal(dev, cb->src)) - return -ENOTUNIQ; - - /* - * Default is to create a drop everything entry - */ - dnrt_input = dn_blackhole; - dnrt_output = dn_rt_bug; - - /* - * Is the destination us ? - */ - if (!dn_dev_islocal(dev, cb->dst)) - goto non_local_input; - - /* - * Local input... find source of skb - */ - dnrt_input = dn_nsp_rx; - dnrt_output = dn_output; - saddr = cb->dst; - daddr = cb->src; - - if ((neigh = neigh_lookup(&dn_neigh_table, &cb->src, dev)) != NULL) - goto add_entry; - - if (dn_db->router && ((neigh = neigh_clone(dn_db->router)) != NULL)) - goto add_entry; - - neigh = neigh_create(&dn_neigh_table, &cb->src, dev); - if (!IS_ERR(neigh)) { - if (dev->type == ARPHRD_ETHER) - memcpy(neigh->ha, skb->mac.ethernet->h_source, ETH_ALEN); - goto add_entry; - } - - return PTR_ERR(neigh); + err = -ENOTUNIQ; + if (dn_dev_islocal(in_dev, cb->src)) + goto out; -non_local_input: + err = dn_fib_lookup(&fl, &res); + if (err) { + if (err != -ESRCH) + goto out; + /* + * Is the destination us ? + */ + if (!dn_dev_islocal(in_dev, cb->dst)) + goto e_inval; -#ifdef CONFIG_DECNET_ROUTER - /* - * Destination is another node... find next hop in - * routing table here. - */ + res.type = RTN_LOCAL; + flags |= RTCF_DIRECTSRC; + } else { + __u16 src_map = fl.fld_src; + free_res = 1; - key.src = cb->src; - key.dst = cb->dst; - key.iif = dev->ifindex; - key.oif = 0; - key.scope = RT_SCOPE_UNIVERSE; + out_dev = DN_FIB_RES_DEV(res); + if (out_dev == NULL) { + if (net_ratelimit()) + printk(KERN_CRIT "Bug in dn_route_input_slow() " + "No output device\n"); + goto e_inval; + } + dev_hold(out_dev); -#ifdef CONFIG_DECNET_ROUTE_FWMARK - key.fwmark = skb->nfmark; -#else - key.fwmark = 0; -#endif + if (res.r) + src_map = dn_fib_rules_policy(fl.fld_src, &res, &flags); - if ((err = dn_fib_lookup(&key, &res)) == 0) { - switch(res.type) { - case RTN_UNICAST: - if (res.fi->fib_nhs) - dn_fib_select_multipath(&key, &res); - neigh = __neigh_lookup(&dn_neigh_table, &DN_FIB_RES_GW(res), DN_FIB_RES_DEV(res), 1); - err = -ENOBUFS; - if (!neigh) - break; - err = 0; - dnrt_input = dn_forward; - fwmark = key.fwmark; - break; - case RTN_UNREACHABLE: - dnrt_input = dn_blackhole; - fwmark = key.fwmark; - break; - default: - err = -EINVAL; + gateway = DN_FIB_RES_GW(res); + if (res.type == RTN_NAT) { + fl.fld_dst = dn_fib_rules_map_destination(fl.fld_dst, &res); + dn_fib_res_put(&res); + free_res = 0; + if (dn_fib_lookup(&fl, &res)) + goto e_inval; + free_res = 1; + if (res.type != RTN_UNICAST) + goto e_inval; + flags |= RTCF_DNAT; + gateway = fl.fld_dst; } - dn_fib_res_put(&res); - if (err < 0) - return err; - goto add_entry; + fl.fld_src = src_map; } - return err; - -#endif /* CONFIG_DECNET_ROUTER */ - -add_entry: + switch(res.type) { + case RTN_UNICAST: + /* + * Forwarding check here, we only check for forwarding + * being turned off, if you want to only forward intra + * area, its up to you to set the routing tables up + * correctly. + */ + if (dn_db->parms.forwarding == 0) + goto e_inval; + + if (res.fi->fib_nhs > 1 && fl.oif == 0) + dn_fib_select_multipath(&fl, &res); + + /* + * Check for out_dev == in_dev. We use the RTCF_DOREDIRECT + * flag as a hint to set the intra-ethernet bit when + * forwarding. If we've got NAT in operation, we don't do + * this optimisation. + */ + if (out_dev == in_dev && !(flags & RTCF_NAT)) + flags |= RTCF_DOREDIRECT; + + case RTN_BLACKHOLE: + case RTN_UNREACHABLE: + break; + case RTN_LOCAL: + flags |= RTCF_LOCAL; + fl.fld_src = cb->dst; + fl.fld_dst = cb->src; + + /* Routing tables gave us a gateway */ + if (gateway) + goto make_route; + + /* Packet was intra-ethernet, so we know its on-link */ + if (cb->rt_flags | DN_RT_F_IE) { + gateway = cb->src; + flags |= RTCF_DIRECTSRC; + goto make_route; + } - if ((rt = dst_alloc(&dn_dst_ops)) == NULL) { - neigh_release(neigh); - return -EINVAL; - } + /* Use the default router if there is one */ + neigh = neigh_clone(dn_db->router); + if (neigh) { + gateway = ((struct dn_neigh *)neigh)->addr; + goto make_route; + } - rt->key.saddr = cb->src; - rt->rt_saddr = saddr; - rt->key.daddr = cb->dst; - rt->rt_daddr = daddr; - rt->key.oif = 0; - rt->key.iif = dev->ifindex; - rt->key.fwmark = fwmark; + /* Close eyes and pray */ + gateway = cb->src; + flags |= RTCF_DIRECTSRC; + goto make_route; + default: + goto e_inval; + } + +make_route: + rt = dst_alloc(&dn_dst_ops); + if (rt == NULL) + goto e_nobufs; + + rt->rt_saddr = fl.fld_src; + rt->rt_daddr = fl.fld_dst; + rt->rt_gateway = fl.fld_dst; + if (gateway) + rt->rt_gateway = gateway; + rt->rt_dst_map = fl.fld_dst; + rt->rt_src_map = fl.fld_src; + + rt->fl.fld_src = cb->src; + rt->fl.fld_dst = cb->dst; + rt->fl.oif = 0; + rt->fl.iif = in_dev->ifindex; + rt->fl.fld_fwmark = fl.fld_fwmark; + rt->u.dst.flags = DST_HOST; rt->u.dst.neighbour = neigh; - rt->u.dst.dev = neigh ? neigh->dev : NULL; + rt->u.dst.dev = out_dev; + rt->u.dst.lastuse = jiffies; + rt->u.dst.output = dn_rt_bug; + switch(res.type) { + case RTN_UNICAST: + rt->u.dst.input = dn_forward; + break; + case RTN_LOCAL: + rt->u.dst.output = dn_output; + rt->u.dst.input = dn_nsp_rx; + rt->u.dst.dev = in_dev; + flags |= RTCF_LOCAL; + break; + default: + case RTN_UNREACHABLE: + case RTN_BLACKHOLE: + rt->u.dst.input = dn_blackhole; + } + rt->rt_flags = flags; if (rt->u.dst.dev) dev_hold(rt->u.dst.dev); - rt->u.dst.lastuse = jiffies; - rt->u.dst.output = dnrt_output; - rt->u.dst.input = dnrt_input; - hash = dn_hash(rt->key.saddr, rt->key.daddr); - dn_insert_route(rt, hash); - skb->dst = (struct dst_entry *)rt; + if (dn_rt_set_next_hop(rt, &res)) + goto e_neighbour; - return 0; + hash = dn_hash(rt->fl.fld_src, rt->fl.fld_dst); + dn_insert_route(rt, hash, (struct dn_route **)&skb->dst); + err = 0; + +done: + if (neigh) + neigh_release(neigh); + if (free_res) + dn_fib_res_put(&res); + dev_put(in_dev); + if (out_dev) + dev_put(out_dev); +out: + return err; + +e_inval: + err = -EINVAL; + goto done; + +e_nobufs: + err = -ENOBUFS; + goto done; + +e_neighbour: + dst_free(&rt->u.dst); + goto done; } int dn_route_input(struct sk_buff *skb) @@ -1014,24 +1391,25 @@ if (skb->dst) return 0; - read_lock(&dn_rt_hash_table[hash].lock); + rcu_read_lock(); for(rt = dn_rt_hash_table[hash].chain; rt != NULL; rt = rt->u.rt_next) { - if ((rt->key.saddr == cb->src) && - (rt->key.daddr == cb->dst) && - (rt->key.oif == 0) && + read_barrier_depends(); + if ((rt->fl.fld_src == cb->src) && + (rt->fl.fld_dst == cb->dst) && + (rt->fl.oif == 0) && #ifdef CONFIG_DECNET_ROUTE_FWMARK - (rt->key.fwmark == skb->nfmark) && + (rt->fl.fld_fwmark == skb->nfmark) && #endif - (rt->key.iif == cb->iif)) { + (rt->fl.iif == cb->iif)) { rt->u.dst.lastuse = jiffies; dst_hold(&rt->u.dst); rt->u.dst.__use++; - read_unlock(&dn_rt_hash_table[hash].lock); + rcu_read_unlock(); skb->dst = (struct dst_entry *)rt; return 0; } } - read_unlock(&dn_rt_hash_table[hash].lock); + rcu_read_unlock(); return dn_route_input_slow(skb); } @@ -1042,29 +1420,51 @@ struct rtmsg *r; struct nlmsghdr *nlh; unsigned char *b = skb->tail; + struct rta_cacheinfo ci; nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r)); r = NLMSG_DATA(nlh); - nlh->nlmsg_flags = nowait ? NLM_F_MULTI : 0; + nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0; r->rtm_family = AF_DECnet; r->rtm_dst_len = 16; - r->rtm_src_len = 16; + r->rtm_src_len = 0; r->rtm_tos = 0; - r->rtm_table = 0; - r->rtm_type = 0; - r->rtm_flags = 0; + r->rtm_table = RT_TABLE_MAIN; + r->rtm_type = rt->rt_type; + r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; r->rtm_scope = RT_SCOPE_UNIVERSE; r->rtm_protocol = RTPROT_UNSPEC; + if (rt->rt_flags & RTCF_NOTIFY) + r->rtm_flags |= RTM_F_NOTIFY; RTA_PUT(skb, RTA_DST, 2, &rt->rt_daddr); - RTA_PUT(skb, RTA_SRC, 2, &rt->rt_saddr); + if (rt->fl.fld_src) { + r->rtm_src_len = 16; + RTA_PUT(skb, RTA_SRC, 2, &rt->fl.fld_src); + } if (rt->u.dst.dev) RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->u.dst.dev->ifindex); - if (dst_metric(&rt->u.dst, RTAX_WINDOW)) - RTA_PUT(skb, RTAX_WINDOW, sizeof(unsigned), - &rt->u.dst.metrics[RTAX_WINDOW - 1]); - if (dst_metric(&rt->u.dst, RTAX_RTT)) - RTA_PUT(skb, RTAX_RTT, sizeof(unsigned), - &rt->u.dst.metrics[RTAX_RTT]); + /* + * Note to self - change this if input routes reverse direction when + * they deal only with inputs and not with replies like they do + * currently. + */ + RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_saddr); + if (rt->rt_daddr != rt->rt_gateway) + RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway); + if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) + goto rtattr_failure; + ci.rta_lastuse = jiffies - rt->u.dst.lastuse; + ci.rta_used = rt->u.dst.__use; + ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt); + if (rt->u.dst.expires) + ci.rta_expires = rt->u.dst.expires - jiffies; + else + ci.rta_expires = 0; + ci.rta_error = rt->u.dst.error; + ci.rta_id = ci.rta_ts = ci.rta_tsage = 0; + RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); + if (rt->fl.iif) + RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif); nlh->nlmsg_len = skb->tail - b; return skb->len; @@ -1081,13 +1481,14 @@ int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg) { struct rtattr **rta = arg; + struct rtmsg *rtm = NLMSG_DATA(nlh); struct dn_route *rt = NULL; struct dn_skb_cb *cb; - dn_address dst = 0; - dn_address src = 0; - int iif = 0; int err; struct sk_buff *skb; + struct flowi fl; + + memset(&fl, 0, sizeof(fl)); skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (skb == NULL) @@ -1096,15 +1497,15 @@ cb = DN_SKB_CB(skb); if (rta[RTA_SRC-1]) - memcpy(&src, RTA_DATA(rta[RTA_SRC-1]), 2); + memcpy(&fl.fld_src, RTA_DATA(rta[RTA_SRC-1]), 2); if (rta[RTA_DST-1]) - memcpy(&dst, RTA_DATA(rta[RTA_DST-1]), 2); + memcpy(&fl.fld_dst, RTA_DATA(rta[RTA_DST-1]), 2); if (rta[RTA_IIF-1]) - memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int)); + memcpy(&fl.iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int)); - if (iif) { + if (fl.iif) { struct net_device *dev; - if ((dev = dev_get_by_index(iif)) == NULL) { + if ((dev = dev_get_by_index(fl.iif)) == NULL) { kfree_skb(skb); return -ENODEV; } @@ -1115,25 +1516,31 @@ } skb->protocol = __constant_htons(ETH_P_DNA_RT); skb->dev = dev; - cb->src = src; - cb->dst = dst; + cb->src = fl.fld_src; + cb->dst = fl.fld_dst; local_bh_disable(); err = dn_route_input(skb); local_bh_enable(); memset(cb, 0, sizeof(struct dn_skb_cb)); rt = (struct dn_route *)skb->dst; + if (!err && -rt->u.dst.error) + err = rt->u.dst.error; } else { - err = dn_route_output((struct dst_entry **)&rt, dst, src, 0); + int oif = 0; + if (rta[RTA_OIF - 1]) + memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int)); + fl.oif = oif; + err = dn_route_output_key((struct dst_entry **)&rt, &fl, 0); } - if (!err && rt->u.dst.error) - err = rt->u.dst.error; if (skb->dev) dev_put(skb->dev); skb->dev = NULL; if (err) goto out_free; skb->dst = &rt->u.dst; + if (rtm->rtm_flags & RTM_F_NOTIFY) + rt->rt_flags |= RTCF_NOTIFY; NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; @@ -1177,20 +1584,21 @@ continue; if (h > s_h) s_idx = 0; - read_lock_bh(&dn_rt_hash_table[h].lock); + rcu_read_lock(); for(rt = dn_rt_hash_table[h].chain, idx = 0; rt; rt = rt->u.rt_next, idx++) { + read_barrier_depends(); if (idx < s_idx) continue; skb->dst = dst_clone(&rt->u.dst); if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) { dst_release(xchg(&skb->dst, NULL)); - read_unlock_bh(&dn_rt_hash_table[h].lock); + rcu_read_unlock(); goto done; } dst_release(xchg(&skb->dst, NULL)); } - read_unlock_bh(&dn_rt_hash_table[h].lock); + rcu_read_unlock(); } done: @@ -1211,9 +1619,10 @@ char buf1[DN_ASCBUF_LEN], buf2[DN_ASCBUF_LEN]; for(i = 0; i <= dn_rt_hash_mask; i++) { - read_lock_bh(&dn_rt_hash_table[i].lock); + rcu_read_lock(); rt = dn_rt_hash_table[i].chain; for(; rt != NULL; rt = rt->u.rt_next) { + read_barrier_depends(); len += sprintf(buffer + len, "%-8s %-7s %-7s %04d %04d %04d\n", rt->u.dst.dev ? rt->u.dst.dev->name : "*", dn_addr2asc(dn_ntohs(rt->rt_daddr), buf1), @@ -1234,7 +1643,7 @@ if (pos > offset + length) break; } - read_unlock_bh(&dn_rt_hash_table[i].lock); + rcu_read_unlock(); if (pos > offset + length) break; } @@ -1298,7 +1707,7 @@ dn_rt_hash_mask--; for(i = 0; i <= dn_rt_hash_mask; i++) { - dn_rt_hash_table[i].lock = RW_LOCK_UNLOCKED; + dn_rt_hash_table[i].lock = SPIN_LOCK_UNLOCKED; dn_rt_hash_table[i].chain = NULL; } diff -urN linux-2.5.67-bk9/net/decnet/dn_rules.c linux-2.5.67-bk10/net/decnet/dn_rules.c --- linux-2.5.67-bk9/net/decnet/dn_rules.c 2003-04-07 10:32:18.000000000 -0700 +++ linux-2.5.67-bk10/net/decnet/dn_rules.c 2003-04-19 04:35:43.000000000 -0700 @@ -26,10 +26,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -48,6 +50,7 @@ dn_address r_srcmask; dn_address r_dst; dn_address r_dstmask; + dn_address r_srcmap; u8 r_flags; #ifdef CONFIG_DECNET_ROUTE_FWMARK u32 r_fwmark; @@ -60,7 +63,7 @@ static struct dn_fib_rule default_rule = { .r_clntref = ATOMIC_INIT(2), .r_preference = 0x7fff, - .r_table = DN_DEFAULT_TABLE, + .r_table = RT_TABLE_MAIN, .r_action = RTN_UNICAST }; @@ -150,6 +153,8 @@ memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 2); if (rta[RTA_DST-1]) memcpy(&new_r->r_dst, RTA_DATA(rta[RTA_DST-1]), 2); + if (rta[RTA_GATEWAY-1]) + memcpy(&new_r->r_srcmap, RTA_DATA(rta[RTA_GATEWAY-1]), 2); new_r->r_src_len = rtm->rtm_src_len; new_r->r_dst_len = rtm->rtm_dst_len; new_r->r_srcmask = dnet_make_mask(rtm->rtm_src_len); @@ -198,12 +203,12 @@ } -int dn_fib_lookup(struct dn_fib_key *key, struct dn_fib_res *res) +int dn_fib_lookup(const struct flowi *flp, struct dn_fib_res *res) { struct dn_fib_rule *r, *policy; struct dn_fib_table *tb; - dn_address saddr = key->src; - dn_address daddr = key->dst; + dn_address saddr = flp->fld_src; + dn_address daddr = flp->fld_dst; int err; read_lock(&dn_fib_rules_lock); @@ -211,13 +216,14 @@ if (((saddr^r->r_src) & r->r_srcmask) || ((daddr^r->r_dst) & r->r_dstmask) || #ifdef CONFIG_DECNET_ROUTE_FWMARK - (r->r_fwmark && r->r_fwmark != key->fwmark) || + (r->r_fwmark && r->r_fwmark != flp->fld_fwmark) || #endif - (r->r_ifindex && r->r_ifindex != key->iif)) + (r->r_ifindex && r->r_ifindex != flp->iif)) continue; switch(r->r_action) { case RTN_UNICAST: + case RTN_NAT: policy = r; break; case RTN_UNREACHABLE: @@ -234,7 +240,7 @@ if ((tb = dn_fib_get_table(r->r_table, 0)) == NULL) continue; - err = tb->lookup(tb, key, res); + err = tb->lookup(tb, flp, res); if (err == 0) { res->r = policy; if (policy) @@ -252,6 +258,42 @@ return -ESRCH; } +unsigned dnet_addr_type(__u16 addr) +{ + struct flowi fl = { .nl_u = { .dn_u = { .daddr = addr } } }; + struct dn_fib_res res; + unsigned ret = RTN_UNICAST; + struct dn_fib_table *tb = dn_fib_tables[RT_TABLE_LOCAL]; + + res.r = NULL; + + if (tb) { + if (!tb->lookup(tb, &fl, &res)) { + ret = res.type; + dn_fib_res_put(&res); + } + } + return ret; +} + +__u16 dn_fib_rules_policy(__u16 saddr, struct dn_fib_res *res, unsigned *flags) +{ + struct dn_fib_rule *r = res->r; + + if (r->r_action == RTN_NAT) { + int addrtype = dnet_addr_type(r->r_srcmap); + + if (addrtype == RTN_NAT) { + saddr = (saddr&~r->r_srcmask)|r->r_srcmap; + *flags |= RTCF_SNAT; + } else if (addrtype == RTN_LOCAL || r->r_srcmap == 0) { + saddr = r->r_srcmap; + *flags |= RTCF_MASQ; + } + } + return saddr; +} + static void dn_fib_rules_detach(struct net_device *dev) { struct dn_fib_rule *r; @@ -330,6 +372,8 @@ RTA_PUT(skb, RTA_IIF, IFNAMSIZ, &r->r_ifname); if (r->r_preference) RTA_PUT(skb, RTA_PRIORITY, 4, &r->r_preference); + if (r->r_srcmap) + RTA_PUT(skb, RTA_GATEWAY, 2, &r->r_srcmap); nlh->nlmsg_len = skb->tail - b; return skb->len; diff -urN linux-2.5.67-bk9/net/decnet/dn_table.c linux-2.5.67-bk10/net/decnet/dn_table.c --- linux-2.5.67-bk9/net/decnet/dn_table.c 2003-04-07 10:30:58.000000000 -0700 +++ linux-2.5.67-bk10/net/decnet/dn_table.c 2003-04-19 04:35:43.000000000 -0700 @@ -30,6 +30,7 @@ #include /* RTF_xxx */ #include #include +#include #include #include #include @@ -45,7 +46,7 @@ u32 dz_hashmask; #define DZ_HASHMASK(dz) ((dz)->dz_hashmask) int dz_order; - u32 dz_mask; + u16 dz_mask; #define DZ_MASK(dz) ((dz)->dz_mask) }; @@ -73,53 +74,53 @@ #define DN_FIB_SCAN_KEY(f, fp, key) \ for( ; ((f) = *(fp)) != NULL && dn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_next) +#define RT_TABLE_MIN 1 static rwlock_t dn_fib_tables_lock = RW_LOCK_UNLOCKED; -static struct dn_fib_table *dn_fib_tables[DN_NUM_TABLES + 1]; +struct dn_fib_table *dn_fib_tables[RT_TABLE_MAX + 1]; static kmem_cache_t *dn_hash_kmem; static int dn_fib_hash_zombies; -static __inline__ dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz) +static inline dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz) { - u32 h = ntohs(key.datum)>>(16 - dz->dz_order); + u16 h = ntohs(key.datum)>>(16 - dz->dz_order); h ^= (h >> 10); h ^= (h >> 6); - h ^= (h >> 3); h &= DZ_HASHMASK(dz); return *(dn_fib_idx_t *)&h; } -static __inline__ dn_fib_key_t dz_key(u16 dst, struct dn_zone *dz) +static inline dn_fib_key_t dz_key(u16 dst, struct dn_zone *dz) { dn_fib_key_t k; k.datum = dst & DZ_MASK(dz); return k; } -static __inline__ struct dn_fib_node **dn_chain_p(dn_fib_key_t key, struct dn_zone *dz) +static inline struct dn_fib_node **dn_chain_p(dn_fib_key_t key, struct dn_zone *dz) { return &dz->dz_hash[dn_hash(key, dz).datum]; } -static __inline__ struct dn_fib_node *dz_chain(dn_fib_key_t key, struct dn_zone *dz) +static inline struct dn_fib_node *dz_chain(dn_fib_key_t key, struct dn_zone *dz) { return dz->dz_hash[dn_hash(key, dz).datum]; } -static __inline__ int dn_key_eq(dn_fib_key_t a, dn_fib_key_t b) +static inline int dn_key_eq(dn_fib_key_t a, dn_fib_key_t b) { return a.datum == b.datum; } -static __inline__ int dn_key_leq(dn_fib_key_t a, dn_fib_key_t b) +static inline int dn_key_leq(dn_fib_key_t a, dn_fib_key_t b) { return a.datum <= b.datum; } -static __inline__ void dn_rebuild_zone(struct dn_zone *dz, - struct dn_fib_node **old_ht, - int old_divisor) +static inline void dn_rebuild_zone(struct dn_zone *dz, + struct dn_fib_node **old_ht, + int old_divisor) { int i; struct dn_fib_node *f, **fp, *next; @@ -290,6 +291,8 @@ rtm->rtm_protocol = fi->fib_protocol; if (fi->fib_priority) RTA_PUT(skb, RTA_PRIORITY, 4, &fi->fib_priority); + if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0) + goto rtattr_failure; if (fi->fib_nhs == 1) { if (fi->fib_nh->nh_gw) RTA_PUT(skb, RTA_GATEWAY, 2, &fi->fib_nh->nh_gw); @@ -654,7 +657,7 @@ return -ESRCH; } -static __inline__ int dn_flush_list(struct dn_fib_node **fp, int z, struct dn_hash *table) +static inline int dn_flush_list(struct dn_fib_node **fp, int z, struct dn_hash *table) { int found = 0; struct dn_fib_node *f; @@ -696,8 +699,7 @@ return found; } -static int dn_fib_table_lookup(struct dn_fib_table *tb, const struct dn_fib_key * -key, struct dn_fib_res *res) +static int dn_fib_table_lookup(struct dn_fib_table *tb, const struct flowi *flp, struct dn_fib_res *res) { int err; struct dn_zone *dz; @@ -706,25 +708,29 @@ read_lock(&dn_fib_tables_lock); for(dz = t->dh_zone_list; dz; dz = dz->dz_next) { struct dn_fib_node *f; - dn_fib_key_t k = dz_key(key->dst, dz); + dn_fib_key_t k = dz_key(flp->fld_dst, dz); for(f = dz_chain(k, dz); f; f = f->fn_next) { - if (!dn_key_leq(k, f->fn_key)) - break; - else - continue; + if (!dn_key_eq(k, f->fn_key)) { + if (dn_key_leq(k, f->fn_key)) + break; + else + continue; + } f->fn_state |= DN_S_ACCESSED; if (f->fn_state&DN_S_ZOMBIE) continue; - if (f->fn_scope < key->scope) + + if (f->fn_scope < flp->fld_scope) continue; - err = dn_fib_semantic_match(f->fn_type, DN_FIB_INFO(f), key, res); + err = dn_fib_semantic_match(f->fn_type, DN_FIB_INFO(f), flp, res); + if (err == 0) { res->type = f->fn_type; - res->scope = f->fn_scope; + res->scope = f->fn_scope; res->prefixlen = dz->dz_order; goto out; } @@ -763,7 +769,7 @@ if (fi) { len = sprintf(buffer, "%s\t%04x\t%04x\t%04x\t%d\t%u\t%d\t%04x\t%d\t%u\t%u", - fi->fib_dev ? fi->fib_dev->name : "*", prefix, + fi->dn_fib_dev ? fi->dn_fib_dev->name : "*", prefix, fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority, mask, 0, 0, 0); } else { @@ -823,10 +829,10 @@ { struct dn_fib_table *t; - if (n < DN_MIN_TABLE) + if (n < RT_TABLE_MIN) return NULL; - if (n > DN_NUM_TABLES) + if (n > RT_TABLE_MAX) return NULL; if (dn_fib_tables[n]) @@ -839,7 +845,7 @@ printk(KERN_DEBUG "DECnet: BUG! Attempt to create routing table from interrupt\n"); return NULL; } - if ((t = kmalloc(sizeof(struct dn_fib_table), GFP_KERNEL)) == NULL) + if ((t = kmalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash), GFP_KERNEL)) == NULL) return NULL; memset(t, 0, sizeof(struct dn_fib_table)); @@ -853,6 +859,7 @@ t->get_info = dn_fib_table_get_info; #endif t->dump = dn_fib_table_dump; + memset(t->data, 0, sizeof(struct dn_hash)); dn_fib_tables[n] = t; return t; @@ -876,7 +883,7 @@ { int id; - for(id = DN_MIN_TABLE; id <= DN_NUM_TABLES; id++) + for(id = RT_TABLE_MIN; id <= RT_TABLE_MAX; id++) if (dn_fib_tables[id] == NULL) return dn_fib_get_table(id, 1); return NULL; @@ -894,7 +901,7 @@ { int i; - for (i = 0; i < DN_NUM_TABLES + 1; ++i) + for (i = RT_TABLE_MIN; i <= RT_TABLE_MAX; ++i) dn_fib_del_tree(i); return; diff -urN linux-2.5.67-bk9/net/decnet/dn_timer.c linux-2.5.67-bk10/net/decnet/dn_timer.c --- linux-2.5.67-bk9/net/decnet/dn_timer.c 2003-04-07 10:31:46.000000000 -0700 +++ linux-2.5.67-bk10/net/decnet/dn_timer.c 2003-04-19 04:35:43.000000000 -0700 @@ -23,6 +23,7 @@ #include #include #include +#include #include /* diff -urN linux-2.5.67-bk9/net/decnet/sysctl_net_decnet.c linux-2.5.67-bk10/net/decnet/sysctl_net_decnet.c --- linux-2.5.67-bk9/net/decnet/sysctl_net_decnet.c 2003-04-07 10:30:57.000000000 -0700 +++ linux-2.5.67-bk10/net/decnet/sysctl_net_decnet.c 2003-04-19 04:35:43.000000000 -0700 @@ -20,6 +20,7 @@ #include #include #include +#include #include diff -urN linux-2.5.67-bk9/net/ipv4/xfrm4_policy.c linux-2.5.67-bk10/net/ipv4/xfrm4_policy.c --- linux-2.5.67-bk9/net/ipv4/xfrm4_policy.c 2003-04-19 04:35:32.000000000 -0700 +++ linux-2.5.67-bk10/net/ipv4/xfrm4_policy.c 2003-04-19 04:35:43.000000000 -0700 @@ -180,8 +180,8 @@ if (pskb_may_pull(skb, xprth + 4 - skb->data)) { u16 *ports = (u16 *)xprth; - fl->uli_u.ports.sport = ports[0]; - fl->uli_u.ports.dport = ports[1]; + fl->fl_ip_sport = ports[0]; + fl->fl_ip_dport = ports[1]; } break; @@ -189,7 +189,7 @@ if (pskb_may_pull(skb, xprth + 4 - skb->data)) { u32 *ehdr = (u32 *)xprth; - fl->uli_u.spi = ehdr[0]; + fl->fl_ipsec_spi = ehdr[0]; } break; @@ -197,7 +197,7 @@ if (pskb_may_pull(skb, xprth + 8 - skb->data)) { u32 *ah_hdr = (u32*)xprth; - fl->uli_u.spi = ah_hdr[1]; + fl->fl_ipsec_spi = ah_hdr[1]; } break; @@ -205,11 +205,11 @@ if (pskb_may_pull(skb, xprth + 4 - skb->data)) { u16 *ipcomp_hdr = (u16 *)xprth; - fl->uli_u.spi = ntohl(ntohs(ipcomp_hdr[1])); + fl->fl_ipsec_spi = ntohl(ntohs(ipcomp_hdr[1])); } break; default: - fl->uli_u.spi = 0; + fl->fl_ipsec_spi = 0; break; }; } else { diff -urN linux-2.5.67-bk9/net/ipv4/xfrm4_state.c linux-2.5.67-bk10/net/ipv4/xfrm4_state.c --- linux-2.5.67-bk9/net/ipv4/xfrm4_state.c 2003-04-07 10:30:38.000000000 -0700 +++ linux-2.5.67-bk10/net/ipv4/xfrm4_state.c 2003-04-19 04:35:43.000000000 -0700 @@ -20,9 +20,9 @@ { x->sel.daddr.a4 = fl->fl4_dst; x->sel.saddr.a4 = fl->fl4_src; - x->sel.dport = fl->uli_u.ports.dport; + x->sel.dport = fl->fl_ip_dport; x->sel.dport_mask = ~0; - x->sel.sport = fl->uli_u.ports.sport; + x->sel.sport = fl->fl_ip_sport; x->sel.sport_mask = ~0; x->sel.prefixlen_d = 32; x->sel.prefixlen_s = 32; diff -urN linux-2.5.67-bk9/net/ipv6/datagram.c linux-2.5.67-bk10/net/ipv6/datagram.c --- linux-2.5.67-bk9/net/ipv6/datagram.c 2003-04-07 10:30:41.000000000 -0700 +++ linux-2.5.67-bk10/net/ipv6/datagram.c 2003-04-19 04:35:43.000000000 -0700 @@ -91,7 +91,7 @@ serr->ee.ee_info = info; serr->ee.ee_data = 0; serr->addr_offset = (u8*)&iph->daddr - skb->nh.raw; - serr->port = fl->uli_u.ports.dport; + serr->port = fl->fl_ip_dport; skb->h.raw = skb->tail; __skb_pull(skb, skb->tail - skb->data); diff -urN linux-2.5.67-bk9/net/ipv6/icmp.c linux-2.5.67-bk10/net/ipv6/icmp.c --- linux-2.5.67-bk9/net/ipv6/icmp.c 2003-04-19 04:35:32.000000000 -0700 +++ linux-2.5.67-bk10/net/ipv6/icmp.c 2003-04-19 04:35:43.000000000 -0700 @@ -313,12 +313,12 @@ } fl.proto = IPPROTO_ICMPV6; - fl.nl_u.ip6_u.daddr = &hdr->saddr; - fl.nl_u.ip6_u.saddr = saddr; + fl.fl6_dst = &hdr->saddr; + fl.fl6_src = saddr; fl.oif = iif; fl.fl6_flowlabel = 0; - fl.uli_u.icmpt.type = type; - fl.uli_u.icmpt.code = code; + fl.fl_icmp_type = type; + fl.fl_icmp_code = code; icmpv6_xmit_lock(); @@ -387,12 +387,12 @@ msg.daddr = &skb->nh.ipv6h->saddr; fl.proto = IPPROTO_ICMPV6; - fl.nl_u.ip6_u.daddr = msg.daddr; - fl.nl_u.ip6_u.saddr = saddr; + fl.fl6_dst = msg.daddr; + fl.fl6_src = saddr; fl.oif = skb->dev->ifindex; fl.fl6_flowlabel = 0; - fl.uli_u.icmpt.type = ICMPV6_ECHO_REPLY; - fl.uli_u.icmpt.code = 0; + fl.fl_icmp_type = ICMPV6_ECHO_REPLY; + fl.fl_icmp_code = 0; icmpv6_xmit_lock(); diff -urN linux-2.5.67-bk9/net/ipv6/ip6_output.c linux-2.5.67-bk10/net/ipv6/ip6_output.c --- linux-2.5.67-bk9/net/ipv6/ip6_output.c 2003-04-19 04:35:32.000000000 -0700 +++ linux-2.5.67-bk10/net/ipv6/ip6_output.c 2003-04-19 04:35:43.000000000 -0700 @@ -147,8 +147,8 @@ fl.fl6_src = &iph->saddr; fl.oif = skb->sk ? skb->sk->bound_dev_if : 0; fl.fl6_flowlabel = 0; - fl.uli_u.ports.dport = 0; - fl.uli_u.ports.sport = 0; + fl.fl_ip_dport = 0; + fl.fl_ip_sport = 0; dst = ip6_route_output(skb->sk, &fl); @@ -188,7 +188,7 @@ struct ipv6_txoptions *opt) { struct ipv6_pinfo *np = sk ? inet6_sk(sk) : NULL; - struct in6_addr *first_hop = fl->nl_u.ip6_u.daddr; + struct in6_addr *first_hop = fl->fl6_dst; struct dst_entry *dst = skb->dst; struct ipv6hdr *hdr; u8 proto = fl->proto; @@ -243,7 +243,7 @@ hdr->nexthdr = proto; hdr->hop_limit = hlimit; - ipv6_addr_copy(&hdr->saddr, fl->nl_u.ip6_u.saddr); + ipv6_addr_copy(&hdr->saddr, fl->fl6_src); ipv6_addr_copy(&hdr->daddr, first_hop); mtu = dst_pmtu(dst); @@ -308,8 +308,8 @@ hdr->hop_limit = hlimit; hdr->nexthdr = fl->proto; - ipv6_addr_copy(&hdr->saddr, fl->nl_u.ip6_u.saddr); - ipv6_addr_copy(&hdr->daddr, fl->nl_u.ip6_u.daddr); + ipv6_addr_copy(&hdr->saddr, fl->fl6_src); + ipv6_addr_copy(&hdr->daddr, fl->fl6_dst); return hdr; } @@ -526,7 +526,7 @@ fl->fl6_dst = rt0->addr; } - if (!fl->oif && ipv6_addr_is_multicast(fl->nl_u.ip6_u.daddr)) + if (!fl->oif && ipv6_addr_is_multicast(fl->fl6_dst)) fl->oif = np->mcast_oif; dst = __sk_dst_check(sk, np->dst_cookie); @@ -703,7 +703,7 @@ * cleanup */ out: - ip6_dst_store(sk, dst, fl->nl_u.ip6_u.daddr == &np->daddr ? &np->daddr : NULL); + ip6_dst_store(sk, dst, fl->fl6_dst == &np->daddr ? &np->daddr : NULL); if (err > 0) err = np->recverr ? net_xmit_errno(err) : 0; return err; diff -urN linux-2.5.67-bk9/net/ipv6/ndisc.c linux-2.5.67-bk10/net/ipv6/ndisc.c --- linux-2.5.67-bk9/net/ipv6/ndisc.c 2003-04-19 04:35:32.000000000 -0700 +++ linux-2.5.67-bk10/net/ipv6/ndisc.c 2003-04-19 04:35:43.000000000 -0700 @@ -405,8 +405,8 @@ fl->fl6_src = saddr; fl->fl6_dst = daddr; fl->proto = IPPROTO_ICMPV6; - fl->uli_u.icmpt.type = type; - fl->uli_u.icmpt.code = 0; + fl->fl_icmp_type = type; + fl->fl_icmp_code = 0; } static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, diff -urN linux-2.5.67-bk9/net/ipv6/raw.c linux-2.5.67-bk10/net/ipv6/raw.c --- linux-2.5.67-bk9/net/ipv6/raw.c 2003-04-19 04:35:32.000000000 -0700 +++ linux-2.5.67-bk10/net/ipv6/raw.c 2003-04-19 04:35:43.000000000 -0700 @@ -622,8 +622,8 @@ fl.fl6_dst = daddr; if (fl.fl6_src == NULL && !ipv6_addr_any(&np->saddr)) fl.fl6_src = &np->saddr; - fl.uli_u.icmpt.type = 0; - fl.uli_u.icmpt.code = 0; + fl.fl_icmp_type = 0; + fl.fl_icmp_code = 0; if (raw_opt->checksum) { struct rawv6_fakehdr hdr; diff -urN linux-2.5.67-bk9/net/ipv6/route.c linux-2.5.67-bk10/net/ipv6/route.c --- linux-2.5.67-bk9/net/ipv6/route.c 2003-04-19 04:35:32.000000000 -0700 +++ linux-2.5.67-bk10/net/ipv6/route.c 2003-04-19 04:35:43.000000000 -0700 @@ -449,13 +449,12 @@ int strict; int attempts = 3; - strict = ipv6_addr_type(fl->nl_u.ip6_u.daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL); + strict = ipv6_addr_type(fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL); relookup: read_lock_bh(&rt6_lock); - fn = fib6_lookup(&ip6_routing_table, fl->nl_u.ip6_u.daddr, - fl->nl_u.ip6_u.saddr); + fn = fib6_lookup(&ip6_routing_table, fl->fl6_dst, fl->fl6_src); restart: rt = fn->leaf; @@ -477,9 +476,8 @@ if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { read_unlock_bh(&rt6_lock); - rt = rt6_cow(rt, fl->nl_u.ip6_u.daddr, - fl->nl_u.ip6_u.saddr); - + rt = rt6_cow(rt, fl->fl6_dst, fl->fl6_src); + if (rt->u.dst.error != -EEXIST || --attempts <= 0) goto out2; @@ -1585,15 +1583,11 @@ skb->mac.raw = skb->data; skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); - fl.proto = 0; - fl.nl_u.ip6_u.daddr = NULL; - fl.nl_u.ip6_u.saddr = NULL; - fl.uli_u.icmpt.type = 0; - fl.uli_u.icmpt.code = 0; + memset(&fl, 0, sizeof(fl)); if (rta[RTA_SRC-1]) - fl.nl_u.ip6_u.saddr = (struct in6_addr*)RTA_DATA(rta[RTA_SRC-1]); + fl.fl6_src = (struct in6_addr*)RTA_DATA(rta[RTA_SRC-1]); if (rta[RTA_DST-1]) - fl.nl_u.ip6_u.daddr = (struct in6_addr*)RTA_DATA(rta[RTA_DST-1]); + fl.fl6_dst = (struct in6_addr*)RTA_DATA(rta[RTA_DST-1]); if (rta[RTA_IIF-1]) memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int)); @@ -1617,8 +1611,7 @@ NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; err = rt6_fill_node(skb, rt, - fl.nl_u.ip6_u.daddr, - fl.nl_u.ip6_u.saddr, + fl.fl6_dst, fl.fl6_src, iif, RTM_NEWROUTE, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, nlh); diff -urN linux-2.5.67-bk9/net/ipv6/tcp_ipv6.c linux-2.5.67-bk10/net/ipv6/tcp_ipv6.c --- linux-2.5.67-bk9/net/ipv6/tcp_ipv6.c 2003-04-19 04:35:32.000000000 -0700 +++ linux-2.5.67-bk10/net/ipv6/tcp_ipv6.c 2003-04-19 04:35:43.000000000 -0700 @@ -670,12 +670,12 @@ fl.fl6_dst = &np->daddr; fl.fl6_src = saddr; fl.oif = sk->bound_dev_if; - fl.uli_u.ports.dport = usin->sin6_port; - fl.uli_u.ports.sport = inet->sport; + fl.fl_ip_dport = usin->sin6_port; + fl.fl_ip_sport = inet->sport; if (np->opt && np->opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; - fl.nl_u.ip6_u.daddr = rt0->addr; + fl.fl6_dst = rt0->addr; } if (!fl.fl6_src) @@ -796,11 +796,11 @@ for now. */ fl.proto = IPPROTO_TCP; - fl.nl_u.ip6_u.daddr = &np->daddr; - fl.nl_u.ip6_u.saddr = &np->saddr; + fl.fl6_dst = &np->daddr; + fl.fl6_src = &np->saddr; fl.oif = sk->bound_dev_if; - fl.uli_u.ports.dport = inet->dport; - fl.uli_u.ports.sport = inet->sport; + fl.fl_ip_dport = inet->dport; + fl.fl_ip_sport = inet->sport; dst = ip6_route_output(sk, &fl); } else @@ -881,12 +881,12 @@ int err = -1; fl.proto = IPPROTO_TCP; - fl.nl_u.ip6_u.daddr = &req->af.v6_req.rmt_addr; - fl.nl_u.ip6_u.saddr = &req->af.v6_req.loc_addr; + fl.fl6_dst = &req->af.v6_req.rmt_addr; + fl.fl6_src = &req->af.v6_req.loc_addr; fl.fl6_flowlabel = 0; fl.oif = req->af.v6_req.iif; - fl.uli_u.ports.dport = req->rmt_port; - fl.uli_u.ports.sport = inet_sk(sk)->sport; + fl.fl_ip_dport = req->rmt_port; + fl.fl_ip_sport = inet_sk(sk)->sport; if (dst == NULL) { opt = np->opt; @@ -901,7 +901,7 @@ if (opt && opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; - fl.nl_u.ip6_u.daddr = rt0->addr; + fl.fl6_dst = rt0->addr; } dst = ip6_route_output(sk, &fl); @@ -917,7 +917,7 @@ &req->af.v6_req.loc_addr, &req->af.v6_req.rmt_addr, csum_partial((char *)th, skb->len, skb->csum)); - fl.nl_u.ip6_u.daddr = &req->af.v6_req.rmt_addr; + fl.fl6_dst = &req->af.v6_req.rmt_addr; err = ip6_xmit(sk, skb, &fl, opt); if (err == NET_XMIT_CN) err = 0; @@ -1019,19 +1019,18 @@ buff->csum = csum_partial((char *)t1, sizeof(*t1), 0); - fl.nl_u.ip6_u.daddr = &skb->nh.ipv6h->saddr; - fl.nl_u.ip6_u.saddr = &skb->nh.ipv6h->daddr; + fl.fl6_dst = &skb->nh.ipv6h->saddr; + fl.fl6_src = &skb->nh.ipv6h->daddr; fl.fl6_flowlabel = 0; - t1->check = csum_ipv6_magic(fl.nl_u.ip6_u.saddr, - fl.nl_u.ip6_u.daddr, + t1->check = csum_ipv6_magic(fl.fl6_src, fl.fl6_dst, sizeof(*t1), IPPROTO_TCP, buff->csum); fl.proto = IPPROTO_TCP; fl.oif = tcp_v6_iif(skb); - fl.uli_u.ports.dport = t1->dest; - fl.uli_u.ports.sport = t1->source; + fl.fl_ip_dport = t1->dest; + fl.fl_ip_sport = t1->source; /* sk = NULL, but it is safe for now. RST socket required. */ buff->dst = ip6_route_output(NULL, &fl); @@ -1084,19 +1083,18 @@ buff->csum = csum_partial((char *)t1, tot_len, 0); - fl.nl_u.ip6_u.daddr = &skb->nh.ipv6h->saddr; - fl.nl_u.ip6_u.saddr = &skb->nh.ipv6h->daddr; + fl.fl6_dst = &skb->nh.ipv6h->saddr; + fl.fl6_src = &skb->nh.ipv6h->daddr; fl.fl6_flowlabel = 0; - t1->check = csum_ipv6_magic(fl.nl_u.ip6_u.saddr, - fl.nl_u.ip6_u.daddr, + t1->check = csum_ipv6_magic(fl.fl6_src, fl.fl6_dst, tot_len, IPPROTO_TCP, buff->csum); fl.proto = IPPROTO_TCP; fl.oif = tcp_v6_iif(skb); - fl.uli_u.ports.dport = t1->dest; - fl.uli_u.ports.sport = t1->source; + fl.fl_ip_dport = t1->dest; + fl.fl_ip_sport = t1->source; buff->dst = ip6_route_output(NULL, &fl); @@ -1335,16 +1333,16 @@ if (dst == NULL) { fl.proto = IPPROTO_TCP; - fl.nl_u.ip6_u.daddr = &req->af.v6_req.rmt_addr; + fl.fl6_dst = &req->af.v6_req.rmt_addr; if (opt && opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; - fl.nl_u.ip6_u.daddr = rt0->addr; + fl.fl6_dst = rt0->addr; } - fl.nl_u.ip6_u.saddr = &req->af.v6_req.loc_addr; + fl.fl6_src = &req->af.v6_req.loc_addr; fl.fl6_flowlabel = 0; fl.oif = sk->bound_dev_if; - fl.uli_u.ports.dport = req->rmt_port; - fl.uli_u.ports.sport = inet_sk(sk)->sport; + fl.fl_ip_dport = req->rmt_port; + fl.fl_ip_sport = inet_sk(sk)->sport; dst = ip6_route_output(sk, &fl); } @@ -1732,16 +1730,16 @@ struct flowi fl; fl.proto = IPPROTO_TCP; - fl.nl_u.ip6_u.daddr = &np->daddr; - fl.nl_u.ip6_u.saddr = &np->saddr; + fl.fl6_dst = &np->daddr; + fl.fl6_src = &np->saddr; fl.fl6_flowlabel = np->flow_label; fl.oif = sk->bound_dev_if; - fl.uli_u.ports.dport = inet->dport; - fl.uli_u.ports.sport = inet->sport; + fl.fl_ip_dport = inet->dport; + fl.fl_ip_sport = inet->sport; if (np->opt && np->opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; - fl.nl_u.ip6_u.daddr = rt0->addr; + fl.fl6_dst = rt0->addr; } dst = ip6_route_output(sk, &fl); @@ -1774,12 +1772,12 @@ fl.fl6_flowlabel = np->flow_label; IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel); fl.oif = sk->bound_dev_if; - fl.uli_u.ports.sport = inet->sport; - fl.uli_u.ports.dport = inet->dport; + fl.fl_ip_sport = inet->sport; + fl.fl_ip_dport = inet->dport; if (np->opt && np->opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; - fl.nl_u.ip6_u.daddr = rt0->addr; + fl.fl6_dst = rt0->addr; } dst = __sk_dst_check(sk, np->dst_cookie); @@ -1799,7 +1797,7 @@ skb->dst = dst_clone(dst); /* Restore final destination back after routing done */ - fl.nl_u.ip6_u.daddr = &np->daddr; + fl.fl6_dst = &np->daddr; return ip6_xmit(sk, skb, &fl, np->opt); } diff -urN linux-2.5.67-bk9/net/ipv6/udp.c linux-2.5.67-bk10/net/ipv6/udp.c --- linux-2.5.67-bk9/net/ipv6/udp.c 2003-04-19 04:35:32.000000000 -0700 +++ linux-2.5.67-bk10/net/ipv6/udp.c 2003-04-19 04:35:43.000000000 -0700 @@ -352,8 +352,8 @@ fl.fl6_dst = &np->daddr; fl.fl6_src = &saddr; fl.oif = sk->bound_dev_if; - fl.uli_u.ports.dport = inet->dport; - fl.uli_u.ports.sport = inet->sport; + fl.fl_ip_dport = inet->dport; + fl.fl_ip_sport = inet->sport; if (!fl.oif && (addr_type&IPV6_ADDR_MULTICAST)) fl.oif = np->mcast_oif; @@ -936,8 +936,8 @@ fl.fl6_dst = daddr; if (fl.fl6_src == NULL && !ipv6_addr_any(&np->saddr)) fl.fl6_src = &np->saddr; - fl.uli_u.ports.dport = udh.uh.dest; - fl.uli_u.ports.sport = udh.uh.source; + fl.fl_ip_dport = udh.uh.dest; + fl.fl_ip_sport = udh.uh.source; err = ip6_build_xmit(sk, udpv6_getfrag, &udh, &fl, len, opt, hlimit, msg->msg_flags); diff -urN linux-2.5.67-bk9/net/ipv6/xfrm6_policy.c linux-2.5.67-bk10/net/ipv6/xfrm6_policy.c --- linux-2.5.67-bk9/net/ipv6/xfrm6_policy.c 2003-04-19 04:35:32.000000000 -0700 +++ linux-2.5.67-bk10/net/ipv6/xfrm6_policy.c 2003-04-19 04:35:43.000000000 -0700 @@ -195,8 +195,8 @@ if (pskb_may_pull(skb, skb->nh.raw + offset + 4 - skb->data)) { u16 *ports = (u16 *)exthdr; - fl->uli_u.ports.sport = ports[0]; - fl->uli_u.ports.dport = ports[1]; + fl->fl_ip_sport = ports[0]; + fl->fl_ip_dport = ports[1]; } return; @@ -205,7 +205,7 @@ case IPPROTO_ESP: case IPPROTO_COMP: default: - fl->uli_u.spi = 0; + fl->fl_ipsec_spi = 0; return; }; } diff -urN linux-2.5.67-bk9/net/ipv6/xfrm6_state.c linux-2.5.67-bk10/net/ipv6/xfrm6_state.c --- linux-2.5.67-bk9/net/ipv6/xfrm6_state.c 2003-04-07 10:31:05.000000000 -0700 +++ linux-2.5.67-bk10/net/ipv6/xfrm6_state.c 2003-04-19 04:35:43.000000000 -0700 @@ -27,9 +27,9 @@ * to current session. */ memcpy(&x->sel.daddr, fl->fl6_dst, sizeof(struct in6_addr)); memcpy(&x->sel.saddr, fl->fl6_src, sizeof(struct in6_addr)); - x->sel.dport = fl->uli_u.ports.dport; + x->sel.dport = fl->fl_ip_dport; x->sel.dport_mask = ~0; - x->sel.sport = fl->uli_u.ports.sport; + x->sel.sport = fl->fl_ip_sport; x->sel.sport_mask = ~0; x->sel.prefixlen_d = 128; x->sel.prefixlen_s = 128; diff -urN linux-2.5.67-bk9/net/netsyms.c linux-2.5.67-bk10/net/netsyms.c --- linux-2.5.67-bk9/net/netsyms.c 2003-04-19 04:35:32.000000000 -0700 +++ linux-2.5.67-bk10/net/netsyms.c 2003-04-19 04:35:43.000000000 -0700 @@ -228,7 +228,7 @@ #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) EXPORT_SYMBOL(dev_change_flags); #endif -EXPORT_SYMBOL(vlan_ioctl_hook); +EXPORT_SYMBOL(vlan_ioctl_set); EXPORT_SYMBOL(scm_detach_fds); diff -urN linux-2.5.67-bk9/net/sctp/ipv6.c linux-2.5.67-bk10/net/sctp/ipv6.c --- linux-2.5.67-bk9/net/sctp/ipv6.c 2003-04-19 04:35:32.000000000 -0700 +++ linux-2.5.67-bk10/net/sctp/ipv6.c 2003-04-19 04:35:43.000000000 -0700 @@ -165,8 +165,8 @@ fl.oif = transport->saddr.v6.sin6_scope_id; else fl.oif = sk->bound_dev_if; - fl.uli_u.ports.sport = inet_sk(sk)->sport; - fl.uli_u.ports.dport = transport->ipaddr.v6.sin6_port; + fl.fl_ip_sport = inet_sk(sk)->sport; + fl.fl_ip_dport = transport->ipaddr.v6.sin6_port; if (np->opt && np->opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; diff -urN linux-2.5.67-bk9/net/socket.c linux-2.5.67-bk10/net/socket.c --- linux-2.5.67-bk9/net/socket.c 2003-04-19 04:35:32.000000000 -0700 +++ linux-2.5.67-bk10/net/socket.c 2003-04-19 04:35:43.000000000 -0700 @@ -714,6 +714,11 @@ } +/* + * Atomic setting of ioctl hooks to avoid race + * with module unload. + */ + static DECLARE_MUTEX(br_ioctl_mutex); static int (*br_ioctl_hook)(unsigned long arg) = NULL; @@ -724,8 +729,15 @@ up(&br_ioctl_mutex); } +static DECLARE_MUTEX(vlan_ioctl_mutex); +static int (*vlan_ioctl_hook)(unsigned long arg); -int (*vlan_ioctl_hook)(unsigned long arg); +void vlan_ioctl_set(int (*hook)(unsigned long)) +{ + down(&vlan_ioctl_mutex); + vlan_ioctl_hook = hook; + up(&vlan_ioctl_mutex); +} #ifdef CONFIG_DLCI extern int dlci_ioctl(unsigned int, void *); @@ -789,8 +801,10 @@ if (!vlan_ioctl_hook) request_module("8021q"); #endif + down(&vlan_ioctl_mutex); if (vlan_ioctl_hook) err = vlan_ioctl_hook(arg); + up(&vlan_ioctl_mutex); break; case SIOCGIFDIVERT: case SIOCSIFDIVERT: diff -urN linux-2.5.67-bk9/scripts/kconfig/gconf.c linux-2.5.67-bk10/scripts/kconfig/gconf.c --- linux-2.5.67-bk9/scripts/kconfig/gconf.c 2003-04-07 10:32:51.000000000 -0700 +++ linux-2.5.67-bk10/scripts/kconfig/gconf.c 2003-04-19 04:35:43.000000000 -0700 @@ -64,7 +64,7 @@ enum { COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE, COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF, - COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, + COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD, COL_NUMBER }; @@ -295,7 +295,8 @@ G_TYPE_POINTER, GDK_TYPE_COLOR, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); model2 = GTK_TREE_MODEL(tree2); for (parents[0] = NULL, i = 1; i < 256; i++) @@ -308,7 +309,8 @@ G_TYPE_POINTER, GDK_TYPE_COLOR, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); model1 = GTK_TREE_MODEL(tree1); } @@ -370,7 +372,8 @@ renderer, "active", COL_BTNACT, "inconsistent", COL_BTNINC, - "visible", COL_BTNVIS, NULL); + "visible", COL_BTNVIS, + "radio", COL_BTNRAD, NULL); /*g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(renderer_toggled), NULL); */ renderer = gtk_cell_renderer_text_new(); @@ -1219,6 +1222,8 @@ struct symbol *def_sym = sym_get_choice_value(sym); struct menu *def_menu = NULL; + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + for (child = menu->list; child; child = child->next) { if (menu_is_visible(child) && child->sym == def_sym) @@ -1229,6 +1234,8 @@ row[COL_VALUE] = g_strdup(menu_get_prompt(def_menu)); } + if(sym->flags & SYMBOL_CHOICEVAL) + row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); stype = sym_get_type(sym); switch (stype) { @@ -1307,6 +1314,7 @@ COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]), COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]), COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]), + COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]), -1); g_object_unref(pix);