diff --git a/[refs] b/[refs] index 17839f213509..7047f8a37b82 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a152db71d962f405f7e9be5c818bddf6d1be50a7 +refs/heads/master: b4253f8fc1293cdbfb6a474394e1a66febb70e3d diff --git a/trunk/arch/alpha/kernel/osf_sys.c b/trunk/arch/alpha/kernel/osf_sys.c index 8509dad31204..6e943135f0e0 100644 --- a/trunk/arch/alpha/kernel/osf_sys.c +++ b/trunk/arch/alpha/kernel/osf_sys.c @@ -121,29 +121,24 @@ osf_filldir(void *__buf, const char *name, int namlen, loff_t offset, if (reclen > buf->count) return -EINVAL; d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { - buf->error = -EOVERFLOW; + if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) return -EOVERFLOW; - } if (buf->basep) { if (put_user(offset, buf->basep)) - goto Efault; + return -EFAULT; buf->basep = NULL; } dirent = buf->dirent; - if (put_user(d_ino, &dirent->d_ino) || - put_user(namlen, &dirent->d_namlen) || - put_user(reclen, &dirent->d_reclen) || - copy_to_user(dirent->d_name, name, namlen) || + put_user(d_ino, &dirent->d_ino); + put_user(namlen, &dirent->d_namlen); + put_user(reclen, &dirent->d_reclen); + if (copy_to_user(dirent->d_name, name, namlen) || put_user(0, dirent->d_name + namlen)) - goto Efault; + return -EFAULT; dirent = (void __user *)dirent + reclen; buf->dirent = dirent; buf->count -= reclen; return 0; -Efault: - buf->error = -EFAULT; - return -EFAULT; } asmlinkage int diff --git a/trunk/arch/parisc/hpux/fs.c b/trunk/arch/parisc/hpux/fs.c index 69ff671498e5..1263f00dc35d 100644 --- a/trunk/arch/parisc/hpux/fs.c +++ b/trunk/arch/parisc/hpux/fs.c @@ -84,28 +84,22 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset, if (reclen > buf->count) return -EINVAL; d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { - buf->error = -EOVERFLOW; + if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) return -EOVERFLOW; - } dirent = buf->previous; if (dirent) - if (put_user(offset, &dirent->d_off)) - goto Efault; + put_user(offset, &dirent->d_off); dirent = buf->current_dir; - if (put_user(d_ino, &dirent->d_ino) || - put_user(reclen, &dirent->d_reclen) || - put_user(namlen, &dirent->d_namlen) || - copy_to_user(dirent->d_name, name, namlen) || - put_user(0, dirent->d_name + namlen)) - goto Efault; buf->previous = dirent; - buf->current_dir = (void __user *)dirent + reclen; + put_user(d_ino, &dirent->d_ino); + put_user(reclen, &dirent->d_reclen); + put_user(namlen, &dirent->d_namlen); + copy_to_user(dirent->d_name, name, namlen); + put_user(0, dirent->d_name + namlen); + dirent = (void __user *)dirent + reclen; + buf->current_dir = dirent; buf->count -= reclen; return 0; -Efault: - buffer->error = -EFAULT; - return -EFAULT; } #undef NAME_OFFSET @@ -132,10 +126,8 @@ int hpux_getdents(unsigned int fd, struct hpux_dirent __user *dirent, unsigned i error = buf.error; lastdirent = buf.previous; if (lastdirent) { - if (put_user(file->f_pos, &lastdirent->d_off)) - error = -EFAULT; - else - error = count - buf.count; + put_user(file->f_pos, &lastdirent->d_off); + error = count - buf.count; } out_putf: diff --git a/trunk/arch/s390/kernel/vmlinux.lds.S b/trunk/arch/s390/kernel/vmlinux.lds.S index 607bd67a18ce..76c1e60c92f3 100644 --- a/trunk/arch/s390/kernel/vmlinux.lds.S +++ b/trunk/arch/s390/kernel/vmlinux.lds.S @@ -55,7 +55,7 @@ SECTIONS __start___ex_table = .; *(__ex_table) __stop___ex_table = .; - } :data + } .data : { /* Data */ DATA_DATA diff --git a/trunk/arch/sparc/Makefile b/trunk/arch/sparc/Makefile index 9592889a6fd0..6668e6037af6 100644 --- a/trunk/arch/sparc/Makefile +++ b/trunk/arch/sparc/Makefile @@ -52,24 +52,20 @@ endif export INIT_Y CORE_Y DRIVERS_Y NET_Y LIBS_Y HEAD_Y kallsyms.o # Default target -all: zImage +all: image boot := arch/sparc/boot -image zImage tftpboot.img: vmlinux +image tftpboot.img: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ archclean: $(Q)$(MAKE) $(clean)=$(boot) -# This is the image used for packaging -KBUILD_IMAGE := $(boot)/zImage - CLEAN_FILES += arch/$(ARCH)/boot/System.map # Don't use tabs in echo arguments. define archhelp echo '* image - kernel image ($(boot)/image)' - echo '* zImage - stripped kernel image ($(boot)/zImage)' echo ' tftpboot.img - image prepared for tftp' endef diff --git a/trunk/arch/sparc/boot/Makefile b/trunk/arch/sparc/boot/Makefile index 3e77a9f52248..22d331e1e941 100644 --- a/trunk/arch/sparc/boot/Makefile +++ b/trunk/arch/sparc/boot/Makefile @@ -19,9 +19,6 @@ quiet_cmd_sysmap = SYSMAP $(obj)/System.map cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap quiet_cmd_image = LD $@ cmd_image = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) -o $@ -quiet_cmd_strip = STRIP $@ - cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start $(obj)/image -o $@ - define rule_image $(if $($(quiet)cmd_image), \ @@ -52,9 +49,6 @@ LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds $(BTOBJS) \ $(obj)/image: $(obj)/btfix.o FORCE $(call if_changed_rule,image) -$(obj)/zImage: $(obj)/image - $(call if_changed,strip) - $(obj)/tftpboot.img: $(obj)/piggyback $(obj)/System.map $(obj)/image FORCE $(call if_changed,elftoaout) $(call if_changed,piggy) diff --git a/trunk/arch/sparc64/Kconfig b/trunk/arch/sparc64/Kconfig index 36b4b7ab9cfb..923a98959fa7 100644 --- a/trunk/arch/sparc64/Kconfig +++ b/trunk/arch/sparc64/Kconfig @@ -231,7 +231,6 @@ endmenu config NUMA bool "NUMA support" - depends on SMP config NODES_SHIFT int diff --git a/trunk/block/blk-core.c b/trunk/block/blk-core.c index 2cba5ef97b2b..4889eb86a39e 100644 --- a/trunk/block/blk-core.c +++ b/trunk/block/blk-core.c @@ -582,8 +582,6 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) q->sg_reserved_size = INT_MAX; - blk_set_cmd_filter_defaults(&q->cmd_filter); - /* * all done */ diff --git a/trunk/block/blk-tag.c b/trunk/block/blk-tag.c index ed5166fbc599..32667beb03ee 100644 --- a/trunk/block/blk-tag.c +++ b/trunk/block/blk-tag.c @@ -38,8 +38,7 @@ static int __blk_free_tags(struct blk_queue_tag *bqt) retval = atomic_dec_and_test(&bqt->refcnt); if (retval) { - BUG_ON(find_first_bit(bqt->tag_map, bqt->max_depth) < - bqt->max_depth); + BUG_ON(bqt->busy); kfree(bqt->tag_index); bqt->tag_index = NULL; @@ -148,6 +147,7 @@ static struct blk_queue_tag *__blk_queue_init_tags(struct request_queue *q, if (init_tag_map(q, tags, depth)) goto fail; + tags->busy = 0; atomic_set(&tags->refcnt, 1); return tags; fail: @@ -313,6 +313,7 @@ void blk_queue_end_tag(struct request_queue *q, struct request *rq) * unlock memory barrier semantics. */ clear_bit_unlock(tag, bqt->tag_map); + bqt->busy--; } EXPORT_SYMBOL(blk_queue_end_tag); @@ -367,6 +368,7 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq) bqt->tag_index[tag] = rq; blkdev_dequeue_request(rq); list_add(&rq->queuelist, &q->tag_busy_list); + bqt->busy++; return 0; } EXPORT_SYMBOL(blk_queue_start_tag); diff --git a/trunk/block/bsg.c b/trunk/block/bsg.c index 0aae8d7ba99c..5a68b09a69ba 100644 --- a/trunk/block/bsg.c +++ b/trunk/block/bsg.c @@ -45,6 +45,8 @@ struct bsg_device { char name[BUS_ID_SIZE]; int max_queue; unsigned long flags; + struct blk_scsi_cmd_filter *cmd_filter; + mode_t *f_mode; }; enum { @@ -172,8 +174,7 @@ static int bsg_io_schedule(struct bsg_device *bd) } static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq, - struct sg_io_v4 *hdr, struct bsg_device *bd, - int has_write_perm) + struct sg_io_v4 *hdr, struct bsg_device *bd) { if (hdr->request_len > BLK_MAX_CDB) { rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL); @@ -186,7 +187,8 @@ static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq, return -EFAULT; if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) { - if (blk_verify_command(&q->cmd_filter, rq->cmd, has_write_perm)) + if (blk_cmd_filter_verify_command(bd->cmd_filter, rq->cmd, + bd->f_mode)) return -EPERM; } else if (!capable(CAP_SYS_RAWIO)) return -EPERM; @@ -242,7 +244,7 @@ bsg_validate_sgv4_hdr(struct request_queue *q, struct sg_io_v4 *hdr, int *rw) * map sg_io_v4 to a request. */ static struct request * -bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, int has_write_perm) +bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr) { struct request_queue *q = bd->queue; struct request *rq, *next_rq = NULL; @@ -264,7 +266,7 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, int has_write_perm) rq = blk_get_request(q, rw, GFP_KERNEL); if (!rq) return ERR_PTR(-ENOMEM); - ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, bd, has_write_perm); + ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, bd); if (ret) goto out; @@ -566,6 +568,25 @@ static inline void bsg_set_block(struct bsg_device *bd, struct file *file) set_bit(BSG_F_BLOCK, &bd->flags); } +static void bsg_set_cmd_filter(struct bsg_device *bd, + struct file *file) +{ + struct inode *inode; + struct gendisk *disk; + + if (!file) + return; + + inode = file->f_dentry->d_inode; + if (!inode) + return; + + disk = inode->i_bdev->bd_disk; + + bd->cmd_filter = &disk->cmd_filter; + bd->f_mode = &file->f_mode; +} + /* * Check if the error is a "real" error that we should return. */ @@ -587,6 +608,7 @@ bsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) dprintk("%s: read %Zd bytes\n", bd->name, count); bsg_set_block(bd, file); + bsg_set_cmd_filter(bd, file); bytes_read = 0; ret = __bsg_read(buf, count, bd, NULL, &bytes_read); @@ -599,7 +621,7 @@ bsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) } static int __bsg_write(struct bsg_device *bd, const char __user *buf, - size_t count, ssize_t *bytes_written, int has_write_perm) + size_t count, ssize_t *bytes_written) { struct bsg_command *bc; struct request *rq; @@ -630,7 +652,7 @@ static int __bsg_write(struct bsg_device *bd, const char __user *buf, /* * get a request, fill in the blanks, and add to request queue */ - rq = bsg_map_hdr(bd, &bc->hdr, has_write_perm); + rq = bsg_map_hdr(bd, &bc->hdr); if (IS_ERR(rq)) { ret = PTR_ERR(rq); rq = NULL; @@ -661,11 +683,10 @@ bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) dprintk("%s: write %Zd bytes\n", bd->name, count); bsg_set_block(bd, file); + bsg_set_cmd_filter(bd, file); bytes_written = 0; - ret = __bsg_write(bd, buf, count, &bytes_written, - file->f_mode & FMODE_WRITE); - + ret = __bsg_write(bd, buf, count, &bytes_written); *ppos = bytes_written; /* @@ -771,6 +792,7 @@ static struct bsg_device *bsg_add_device(struct inode *inode, bd->queue = rq; bsg_set_block(bd, file); + bsg_set_cmd_filter(bd, file); atomic_set(&bd->ref_count, 1); mutex_lock(&bsg_mutex); @@ -921,7 +943,7 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (copy_from_user(&hdr, uarg, sizeof(hdr))) return -EFAULT; - rq = bsg_map_hdr(bd, &hdr, file->f_mode & FMODE_WRITE); + rq = bsg_map_hdr(bd, &hdr); if (IS_ERR(rq)) return PTR_ERR(rq); diff --git a/trunk/block/cmd-filter.c b/trunk/block/cmd-filter.c index 1d4026206ac2..eec4404fd357 100644 --- a/trunk/block/cmd-filter.c +++ b/trunk/block/cmd-filter.c @@ -20,14 +20,15 @@ #include #include #include +#include #include #include #include #include -int blk_verify_command(struct blk_cmd_filter *filter, - unsigned char *cmd, int has_write_perm) +int blk_cmd_filter_verify_command(struct blk_scsi_cmd_filter *filter, + unsigned char *cmd, mode_t *f_mode) { /* root can do any command. */ if (capable(CAP_SYS_RAWIO)) @@ -42,15 +43,34 @@ int blk_verify_command(struct blk_cmd_filter *filter, return 0; /* Write-safe commands require a writable open */ - if (test_bit(cmd[0], filter->write_ok) && has_write_perm) + if (test_bit(cmd[0], filter->write_ok) && (*f_mode & FMODE_WRITE)) return 0; return -EPERM; } +EXPORT_SYMBOL(blk_cmd_filter_verify_command); + +int blk_verify_command(struct file *file, unsigned char *cmd) +{ + struct gendisk *disk; + struct inode *inode; + + if (!file) + return -EINVAL; + + inode = file->f_dentry->d_inode; + if (!inode) + return -EINVAL; + + disk = inode->i_bdev->bd_disk; + + return blk_cmd_filter_verify_command(&disk->cmd_filter, + cmd, &file->f_mode); +} EXPORT_SYMBOL(blk_verify_command); /* and now, the sysfs stuff */ -static ssize_t rcf_cmds_show(struct blk_cmd_filter *filter, char *page, +static ssize_t rcf_cmds_show(struct blk_scsi_cmd_filter *filter, char *page, int rw) { char *npage = page; @@ -64,7 +84,8 @@ static ssize_t rcf_cmds_show(struct blk_cmd_filter *filter, char *page, for (i = 0; i < BLK_SCSI_MAX_CMDS; i++) { if (test_bit(i, okbits)) { - npage += sprintf(npage, "0x%02x", i); + sprintf(npage, "%02x", i); + npage += 2; if (i < BLK_SCSI_MAX_CMDS - 1) sprintf(npage++, " "); } @@ -76,65 +97,57 @@ static ssize_t rcf_cmds_show(struct blk_cmd_filter *filter, char *page, return npage - page; } -static ssize_t rcf_readcmds_show(struct blk_cmd_filter *filter, char *page) +static ssize_t rcf_readcmds_show(struct blk_scsi_cmd_filter *filter, char *page) { return rcf_cmds_show(filter, page, READ); } -static ssize_t rcf_writecmds_show(struct blk_cmd_filter *filter, +static ssize_t rcf_writecmds_show(struct blk_scsi_cmd_filter *filter, char *page) { return rcf_cmds_show(filter, page, WRITE); } -static ssize_t rcf_cmds_store(struct blk_cmd_filter *filter, +static ssize_t rcf_cmds_store(struct blk_scsi_cmd_filter *filter, const char *page, size_t count, int rw) { + ssize_t ret = 0; unsigned long okbits[BLK_SCSI_CMD_PER_LONG], *target_okbits; - int cmd, set; - char *p, *status; - - if (rw == READ) { - memcpy(&okbits, filter->read_ok, sizeof(okbits)); - target_okbits = filter->read_ok; - } else { - memcpy(&okbits, filter->write_ok, sizeof(okbits)); - target_okbits = filter->write_ok; - } - - while ((p = strsep((char **)&page, " ")) != NULL) { - set = 1; - - if (p[0] == '+') { - p++; - } else if (p[0] == '-') { - set = 0; - p++; - } - - cmd = simple_strtol(p, &status, 16); - + int cmd, status, len; + substring_t ss; + + memset(&okbits, 0, sizeof(okbits)); + + for (len = strlen(page); len > 0; len -= 3) { + if (len < 2) + break; + ss.from = (char *) page + ret; + ss.to = (char *) page + ret + 2; + ret += 3; + status = match_hex(&ss, &cmd); /* either of these cases means invalid input, so do nothing. */ - if ((status == p) || cmd >= BLK_SCSI_MAX_CMDS) + if (status || cmd >= BLK_SCSI_MAX_CMDS) return -EINVAL; - if (set) - __set_bit(cmd, okbits); - else - __clear_bit(cmd, okbits); + __set_bit(cmd, okbits); } - memcpy(target_okbits, okbits, sizeof(okbits)); + if (rw == READ) + target_okbits = filter->read_ok; + else + target_okbits = filter->write_ok; + + memmove(target_okbits, okbits, sizeof(okbits)); return count; } -static ssize_t rcf_readcmds_store(struct blk_cmd_filter *filter, +static ssize_t rcf_readcmds_store(struct blk_scsi_cmd_filter *filter, const char *page, size_t count) { return rcf_cmds_store(filter, page, count, READ); } -static ssize_t rcf_writecmds_store(struct blk_cmd_filter *filter, +static ssize_t rcf_writecmds_store(struct blk_scsi_cmd_filter *filter, const char *page, size_t count) { return rcf_cmds_store(filter, page, count, WRITE); @@ -142,8 +155,8 @@ static ssize_t rcf_writecmds_store(struct blk_cmd_filter *filter, struct rcf_sysfs_entry { struct attribute attr; - ssize_t (*show)(struct blk_cmd_filter *, char *); - ssize_t (*store)(struct blk_cmd_filter *, const char *, size_t); + ssize_t (*show)(struct blk_scsi_cmd_filter *, char *); + ssize_t (*store)(struct blk_scsi_cmd_filter *, const char *, size_t); }; static struct rcf_sysfs_entry rcf_readcmds_entry = { @@ -170,9 +183,9 @@ static ssize_t rcf_attr_show(struct kobject *kobj, struct attribute *attr, char *page) { struct rcf_sysfs_entry *entry = to_rcf(attr); - struct blk_cmd_filter *filter; + struct blk_scsi_cmd_filter *filter; - filter = container_of(kobj, struct blk_cmd_filter, kobj); + filter = container_of(kobj, struct blk_scsi_cmd_filter, kobj); if (entry->show) return entry->show(filter, page); @@ -184,7 +197,7 @@ rcf_attr_store(struct kobject *kobj, struct attribute *attr, const char *page, size_t length) { struct rcf_sysfs_entry *entry = to_rcf(attr); - struct blk_cmd_filter *filter; + struct blk_scsi_cmd_filter *filter; if (!capable(CAP_SYS_RAWIO)) return -EPERM; @@ -192,7 +205,7 @@ rcf_attr_store(struct kobject *kobj, struct attribute *attr, if (!entry->store) return -EINVAL; - filter = container_of(kobj, struct blk_cmd_filter, kobj); + filter = container_of(kobj, struct blk_scsi_cmd_filter, kobj); return entry->store(filter, page, length); } @@ -206,27 +219,114 @@ static struct kobj_type rcf_ktype = { .default_attrs = default_attrs, }; +#ifndef MAINTENANCE_IN_CMD +#define MAINTENANCE_IN_CMD 0xa3 +#endif + +static void rcf_set_defaults(struct blk_scsi_cmd_filter *filter) +{ + /* Basic read-only commands */ + __set_bit(TEST_UNIT_READY, filter->read_ok); + __set_bit(REQUEST_SENSE, filter->read_ok); + __set_bit(READ_6, filter->read_ok); + __set_bit(READ_10, filter->read_ok); + __set_bit(READ_12, filter->read_ok); + __set_bit(READ_16, filter->read_ok); + __set_bit(READ_BUFFER, filter->read_ok); + __set_bit(READ_DEFECT_DATA, filter->read_ok); + __set_bit(READ_CAPACITY, filter->read_ok); + __set_bit(READ_LONG, filter->read_ok); + __set_bit(INQUIRY, filter->read_ok); + __set_bit(MODE_SENSE, filter->read_ok); + __set_bit(MODE_SENSE_10, filter->read_ok); + __set_bit(LOG_SENSE, filter->read_ok); + __set_bit(START_STOP, filter->read_ok); + __set_bit(GPCMD_VERIFY_10, filter->read_ok); + __set_bit(VERIFY_16, filter->read_ok); + __set_bit(REPORT_LUNS, filter->read_ok); + __set_bit(SERVICE_ACTION_IN, filter->read_ok); + __set_bit(RECEIVE_DIAGNOSTIC, filter->read_ok); + __set_bit(MAINTENANCE_IN_CMD, filter->read_ok); + __set_bit(GPCMD_READ_BUFFER_CAPACITY, filter->read_ok); + + /* Audio CD commands */ + __set_bit(GPCMD_PLAY_CD, filter->read_ok); + __set_bit(GPCMD_PLAY_AUDIO_10, filter->read_ok); + __set_bit(GPCMD_PLAY_AUDIO_MSF, filter->read_ok); + __set_bit(GPCMD_PLAY_AUDIO_TI, filter->read_ok); + __set_bit(GPCMD_PAUSE_RESUME, filter->read_ok); + + /* CD/DVD data reading */ + __set_bit(GPCMD_READ_CD, filter->read_ok); + __set_bit(GPCMD_READ_CD_MSF, filter->read_ok); + __set_bit(GPCMD_READ_DISC_INFO, filter->read_ok); + __set_bit(GPCMD_READ_CDVD_CAPACITY, filter->read_ok); + __set_bit(GPCMD_READ_DVD_STRUCTURE, filter->read_ok); + __set_bit(GPCMD_READ_HEADER, filter->read_ok); + __set_bit(GPCMD_READ_TRACK_RZONE_INFO, filter->read_ok); + __set_bit(GPCMD_READ_SUBCHANNEL, filter->read_ok); + __set_bit(GPCMD_READ_TOC_PMA_ATIP, filter->read_ok); + __set_bit(GPCMD_REPORT_KEY, filter->read_ok); + __set_bit(GPCMD_SCAN, filter->read_ok); + __set_bit(GPCMD_GET_CONFIGURATION, filter->read_ok); + __set_bit(GPCMD_READ_FORMAT_CAPACITIES, filter->read_ok); + __set_bit(GPCMD_GET_EVENT_STATUS_NOTIFICATION, filter->read_ok); + __set_bit(GPCMD_GET_PERFORMANCE, filter->read_ok); + __set_bit(GPCMD_SEEK, filter->read_ok); + __set_bit(GPCMD_STOP_PLAY_SCAN, filter->read_ok); + + /* Basic writing commands */ + __set_bit(WRITE_6, filter->write_ok); + __set_bit(WRITE_10, filter->write_ok); + __set_bit(WRITE_VERIFY, filter->write_ok); + __set_bit(WRITE_12, filter->write_ok); + __set_bit(WRITE_VERIFY_12, filter->write_ok); + __set_bit(WRITE_16, filter->write_ok); + __set_bit(WRITE_LONG, filter->write_ok); + __set_bit(WRITE_LONG_2, filter->write_ok); + __set_bit(ERASE, filter->write_ok); + __set_bit(GPCMD_MODE_SELECT_10, filter->write_ok); + __set_bit(MODE_SELECT, filter->write_ok); + __set_bit(LOG_SELECT, filter->write_ok); + __set_bit(GPCMD_BLANK, filter->write_ok); + __set_bit(GPCMD_CLOSE_TRACK, filter->write_ok); + __set_bit(GPCMD_FLUSH_CACHE, filter->write_ok); + __set_bit(GPCMD_FORMAT_UNIT, filter->write_ok); + __set_bit(GPCMD_REPAIR_RZONE_TRACK, filter->write_ok); + __set_bit(GPCMD_RESERVE_RZONE_TRACK, filter->write_ok); + __set_bit(GPCMD_SEND_DVD_STRUCTURE, filter->write_ok); + __set_bit(GPCMD_SEND_EVENT, filter->write_ok); + __set_bit(GPCMD_SEND_KEY, filter->write_ok); + __set_bit(GPCMD_SEND_OPC, filter->write_ok); + __set_bit(GPCMD_SEND_CUE_SHEET, filter->write_ok); + __set_bit(GPCMD_SET_SPEED, filter->write_ok); + __set_bit(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, filter->write_ok); + __set_bit(GPCMD_LOAD_UNLOAD, filter->write_ok); + __set_bit(GPCMD_SET_STREAMING, filter->write_ok); +} + int blk_register_filter(struct gendisk *disk) { int ret; - struct blk_cmd_filter *filter = &disk->queue->cmd_filter; + struct blk_scsi_cmd_filter *filter = &disk->cmd_filter; struct kobject *parent = kobject_get(disk->holder_dir->parent); if (!parent) return -ENODEV; ret = kobject_init_and_add(&filter->kobj, &rcf_ktype, parent, - "%s", "cmd_filter"); + "%s", "cmd_filter"); if (ret < 0) return ret; + rcf_set_defaults(filter); return 0; } void blk_unregister_filter(struct gendisk *disk) { - struct blk_cmd_filter *filter = &disk->queue->cmd_filter; + struct blk_scsi_cmd_filter *filter = &disk->cmd_filter; kobject_put(&filter->kobj); kobject_put(disk->holder_dir->parent); diff --git a/trunk/block/scsi_ioctl.c b/trunk/block/scsi_ioctl.c index ec4b7f234626..12a5182173f6 100644 --- a/trunk/block/scsi_ioctl.c +++ b/trunk/block/scsi_ioctl.c @@ -105,96 +105,12 @@ static int sg_emulated_host(struct request_queue *q, int __user *p) return put_user(1, p); } -void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter) -{ - /* Basic read-only commands */ - __set_bit(TEST_UNIT_READY, filter->read_ok); - __set_bit(REQUEST_SENSE, filter->read_ok); - __set_bit(READ_6, filter->read_ok); - __set_bit(READ_10, filter->read_ok); - __set_bit(READ_12, filter->read_ok); - __set_bit(READ_16, filter->read_ok); - __set_bit(READ_BUFFER, filter->read_ok); - __set_bit(READ_DEFECT_DATA, filter->read_ok); - __set_bit(READ_CAPACITY, filter->read_ok); - __set_bit(READ_LONG, filter->read_ok); - __set_bit(INQUIRY, filter->read_ok); - __set_bit(MODE_SENSE, filter->read_ok); - __set_bit(MODE_SENSE_10, filter->read_ok); - __set_bit(LOG_SENSE, filter->read_ok); - __set_bit(START_STOP, filter->read_ok); - __set_bit(GPCMD_VERIFY_10, filter->read_ok); - __set_bit(VERIFY_16, filter->read_ok); - __set_bit(REPORT_LUNS, filter->read_ok); - __set_bit(SERVICE_ACTION_IN, filter->read_ok); - __set_bit(RECEIVE_DIAGNOSTIC, filter->read_ok); - __set_bit(MAINTENANCE_IN, filter->read_ok); - __set_bit(GPCMD_READ_BUFFER_CAPACITY, filter->read_ok); - - /* Audio CD commands */ - __set_bit(GPCMD_PLAY_CD, filter->read_ok); - __set_bit(GPCMD_PLAY_AUDIO_10, filter->read_ok); - __set_bit(GPCMD_PLAY_AUDIO_MSF, filter->read_ok); - __set_bit(GPCMD_PLAY_AUDIO_TI, filter->read_ok); - __set_bit(GPCMD_PAUSE_RESUME, filter->read_ok); - - /* CD/DVD data reading */ - __set_bit(GPCMD_READ_CD, filter->read_ok); - __set_bit(GPCMD_READ_CD_MSF, filter->read_ok); - __set_bit(GPCMD_READ_DISC_INFO, filter->read_ok); - __set_bit(GPCMD_READ_CDVD_CAPACITY, filter->read_ok); - __set_bit(GPCMD_READ_DVD_STRUCTURE, filter->read_ok); - __set_bit(GPCMD_READ_HEADER, filter->read_ok); - __set_bit(GPCMD_READ_TRACK_RZONE_INFO, filter->read_ok); - __set_bit(GPCMD_READ_SUBCHANNEL, filter->read_ok); - __set_bit(GPCMD_READ_TOC_PMA_ATIP, filter->read_ok); - __set_bit(GPCMD_REPORT_KEY, filter->read_ok); - __set_bit(GPCMD_SCAN, filter->read_ok); - __set_bit(GPCMD_GET_CONFIGURATION, filter->read_ok); - __set_bit(GPCMD_READ_FORMAT_CAPACITIES, filter->read_ok); - __set_bit(GPCMD_GET_EVENT_STATUS_NOTIFICATION, filter->read_ok); - __set_bit(GPCMD_GET_PERFORMANCE, filter->read_ok); - __set_bit(GPCMD_SEEK, filter->read_ok); - __set_bit(GPCMD_STOP_PLAY_SCAN, filter->read_ok); - - /* Basic writing commands */ - __set_bit(WRITE_6, filter->write_ok); - __set_bit(WRITE_10, filter->write_ok); - __set_bit(WRITE_VERIFY, filter->write_ok); - __set_bit(WRITE_12, filter->write_ok); - __set_bit(WRITE_VERIFY_12, filter->write_ok); - __set_bit(WRITE_16, filter->write_ok); - __set_bit(WRITE_LONG, filter->write_ok); - __set_bit(WRITE_LONG_2, filter->write_ok); - __set_bit(ERASE, filter->write_ok); - __set_bit(GPCMD_MODE_SELECT_10, filter->write_ok); - __set_bit(MODE_SELECT, filter->write_ok); - __set_bit(LOG_SELECT, filter->write_ok); - __set_bit(GPCMD_BLANK, filter->write_ok); - __set_bit(GPCMD_CLOSE_TRACK, filter->write_ok); - __set_bit(GPCMD_FLUSH_CACHE, filter->write_ok); - __set_bit(GPCMD_FORMAT_UNIT, filter->write_ok); - __set_bit(GPCMD_REPAIR_RZONE_TRACK, filter->write_ok); - __set_bit(GPCMD_RESERVE_RZONE_TRACK, filter->write_ok); - __set_bit(GPCMD_SEND_DVD_STRUCTURE, filter->write_ok); - __set_bit(GPCMD_SEND_EVENT, filter->write_ok); - __set_bit(GPCMD_SEND_KEY, filter->write_ok); - __set_bit(GPCMD_SEND_OPC, filter->write_ok); - __set_bit(GPCMD_SEND_CUE_SHEET, filter->write_ok); - __set_bit(GPCMD_SET_SPEED, filter->write_ok); - __set_bit(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, filter->write_ok); - __set_bit(GPCMD_LOAD_UNLOAD, filter->write_ok); - __set_bit(GPCMD_SET_STREAMING, filter->write_ok); -} -EXPORT_SYMBOL_GPL(blk_set_cmd_filter_defaults); - static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, struct sg_io_hdr *hdr, struct file *file) { if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len)) return -EFAULT; - if (blk_verify_command(&q->cmd_filter, rq->cmd, - file->f_mode & FMODE_WRITE)) + if (blk_verify_command(file, rq->cmd)) return -EPERM; /* @@ -382,7 +298,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q, struct gendisk *disk, struct scsi_ioctl_command __user *sic) { struct request *rq; - int err, write_perm = 0; + int err; unsigned int in_len, out_len, bytes, opcode, cmdlen; char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; @@ -424,11 +340,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q, if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) goto error; - /* scsi_ioctl passes NULL */ - if (file && (file->f_mode & FMODE_WRITE)) - write_perm = 1; - - err = blk_verify_command(&q->cmd_filter, rq->cmd, write_perm); + err = blk_verify_command(file, rq->cmd); if (err) goto error; diff --git a/trunk/drivers/block/pktcdvd.c b/trunk/drivers/block/pktcdvd.c index 29b7a648cc6e..158eed4d5161 100644 --- a/trunk/drivers/block/pktcdvd.c +++ b/trunk/drivers/block/pktcdvd.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -2797,9 +2798,14 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev) return ret; } -static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static long pkt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data; + struct inode *inode = file->f_path.dentry->d_inode; + struct pktcdvd_device *pd; + long ret; + + lock_kernel(); + pd = inode->i_bdev->bd_disk->private_data; VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, imajor(inode), iminor(inode)); @@ -2812,7 +2818,8 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u case CDROM_LAST_WRITTEN: case CDROM_SEND_PACKET: case SCSI_IOCTL_SEND_COMMAND: - return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); + ret = blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); + break; case CDROMEJECT: /* @@ -2821,14 +2828,15 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u */ if (pd->refcnt == 1) pkt_lock_door(pd, 0); - return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); + ret = blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); + break; default: VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd); - return -ENOTTY; + ret = -ENOTTY; } - - return 0; + unlock_kernel(); + return ret; } static int pkt_media_changed(struct gendisk *disk) @@ -2850,7 +2858,7 @@ static struct block_device_operations pktcdvd_ops = { .owner = THIS_MODULE, .open = pkt_open, .release = pkt_close, - .ioctl = pkt_ioctl, + .unlocked_ioctl = pkt_ioctl, .media_changed = pkt_media_changed, }; @@ -3015,7 +3023,8 @@ static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd) mutex_unlock(&ctl_mutex); } -static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static long pkt_ctl_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { void __user *argp = (void __user *)arg; struct pkt_ctrl_command ctrl_cmd; @@ -3032,16 +3041,22 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm case PKT_CTRL_CMD_SETUP: if (!capable(CAP_SYS_ADMIN)) return -EPERM; + lock_kernel(); ret = pkt_setup_dev(new_decode_dev(ctrl_cmd.dev), &pkt_dev); ctrl_cmd.pkt_dev = new_encode_dev(pkt_dev); + unlock_kernel(); break; case PKT_CTRL_CMD_TEARDOWN: if (!capable(CAP_SYS_ADMIN)) return -EPERM; + lock_kernel(); ret = pkt_remove_dev(new_decode_dev(ctrl_cmd.pkt_dev)); + unlock_kernel(); break; case PKT_CTRL_CMD_STATUS: + lock_kernel(); pkt_get_status(&ctrl_cmd); + unlock_kernel(); break; default: return -ENOTTY; @@ -3054,7 +3069,7 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm static const struct file_operations pkt_ctl_fops = { - .ioctl = pkt_ctl_ioctl, + .unlocked_ioctl = pkt_ctl_ioctl, .owner = THIS_MODULE, }; diff --git a/trunk/drivers/char/tty_io.c b/trunk/drivers/char/tty_io.c index daeb8f766971..a27160ba21d7 100644 --- a/trunk/drivers/char/tty_io.c +++ b/trunk/drivers/char/tty_io.c @@ -2498,7 +2498,7 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) /** * tty_do_resize - resize event * @tty: tty being resized - * @real_tty: real tty (not the same as tty if using a pty/tty pair) + * @real_tty: real tty (if using a pty/tty pair) * @rows: rows (character) * @cols: cols (character) * @@ -2512,8 +2512,7 @@ int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, struct pid *pgrp, *rpgrp; unsigned long flags; - /* For a PTY we need to lock the tty side */ - mutex_lock(&real_tty->termios_mutex); + mutex_lock(&tty->termios_mutex); if (!memcmp(ws, &tty->winsize, sizeof(*ws))) goto done; /* Get the PID values and reference them so we can @@ -2534,7 +2533,7 @@ int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, tty->winsize = *ws; real_tty->winsize = *ws; done: - mutex_unlock(&real_tty->termios_mutex); + mutex_unlock(&tty->termios_mutex); return 0; } diff --git a/trunk/drivers/char/tty_ioctl.c b/trunk/drivers/char/tty_ioctl.c index bf34e4597421..ea9fc5d03b99 100644 --- a/trunk/drivers/char/tty_ioctl.c +++ b/trunk/drivers/char/tty_ioctl.c @@ -937,14 +937,12 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, return 0; #endif case TIOCGSOFTCAR: - /* FIXME: for correctness we may need to take the termios - lock here - review */ - return put_user(C_CLOCAL(real_tty) ? 1 : 0, + return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg); case TIOCSSOFTCAR: if (get_user(arg, (unsigned int __user *) arg)) return -EFAULT; - return tty_change_softcar(real_tty, arg); + return tty_change_softcar(tty, arg); default: return -ENOIOCTLCMD; } diff --git a/trunk/drivers/gpu/drm/drm_irq.c b/trunk/drivers/gpu/drm/drm_irq.c index 53f0e5af1cc8..089c015c01d1 100644 --- a/trunk/drivers/gpu/drm/drm_irq.c +++ b/trunk/drivers/gpu/drm/drm_irq.c @@ -400,31 +400,27 @@ static void drm_locked_tasklet_func(unsigned long data) { struct drm_device *dev = (struct drm_device *)data; unsigned long irqflags; - void (*tasklet_func)(struct drm_device *); - + spin_lock_irqsave(&dev->tasklet_lock, irqflags); - tasklet_func = dev->locked_tasklet_func; - spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); - if (!tasklet_func || + if (!dev->locked_tasklet_func || !drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT)) { + spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); return; } dev->lock.lock_time = jiffies; atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); - spin_lock_irqsave(&dev->tasklet_lock, irqflags); - tasklet_func = dev->locked_tasklet_func; - dev->locked_tasklet_func = NULL; - spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); - - if (tasklet_func != NULL) - tasklet_func(dev); + dev->locked_tasklet_func(dev); drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT); + + dev->locked_tasklet_func = NULL; + + spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); } /** diff --git a/trunk/drivers/gpu/drm/drm_lock.c b/trunk/drivers/gpu/drm/drm_lock.c index a4caf95485d7..0998723cde79 100644 --- a/trunk/drivers/gpu/drm/drm_lock.c +++ b/trunk/drivers/gpu/drm/drm_lock.c @@ -105,19 +105,14 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) ret ? "interrupted" : "has lock"); if (ret) return ret; - /* don't set the block all signals on the master process for now - * really probably not the correct answer but lets us debug xkb - * xserver for now */ - if (!file_priv->master) { - sigemptyset(&dev->sigmask); - sigaddset(&dev->sigmask, SIGSTOP); - sigaddset(&dev->sigmask, SIGTSTP); - sigaddset(&dev->sigmask, SIGTTIN); - sigaddset(&dev->sigmask, SIGTTOU); - dev->sigdata.context = lock->context; - dev->sigdata.lock = dev->lock.hw_lock; - block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); - } + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock->context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); if (dev->driver->dma_ready && (lock->flags & _DRM_LOCK_READY)) dev->driver->dma_ready(dev); @@ -155,7 +150,6 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_lock *lock = data; unsigned long irqflags; - void (*tasklet_func)(struct drm_device *); if (lock->context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -164,11 +158,14 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) } spin_lock_irqsave(&dev->tasklet_lock, irqflags); - tasklet_func = dev->locked_tasklet_func; - dev->locked_tasklet_func = NULL; + + if (dev->locked_tasklet_func) { + dev->locked_tasklet_func(dev); + + dev->locked_tasklet_func = NULL; + } + spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); - if (tasklet_func != NULL) - tasklet_func(dev); atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); diff --git a/trunk/drivers/gpu/drm/radeon/r300_cmdbuf.c b/trunk/drivers/gpu/drm/radeon/r300_cmdbuf.c index 4b27d9abb7bc..702df45320f7 100644 --- a/trunk/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/trunk/drivers/gpu/drm/radeon/r300_cmdbuf.c @@ -77,9 +77,6 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, return -EFAULT; } - box.x2--; /* Hardware expects inclusive bottom-right corner */ - box.y2--; - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { box.x1 = (box.x1) & R300_CLIPRECT_MASK; @@ -98,8 +95,8 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, R300_CLIPRECT_MASK; box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK; - } + } OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) | (box.y1 << R300_CLIPRECT_Y_SHIFT)); OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) | @@ -139,18 +136,6 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, ADVANCE_RING(); } - /* flus cache and wait idle clean after cliprect change */ - BEGIN_RING(2); - OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); - OUT_RING(R300_RB3D_DC_FLUSH); - ADVANCE_RING(); - BEGIN_RING(2); - OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_RING(RADEON_WAIT_3D_IDLECLEAN); - ADVANCE_RING(); - /* set flush flag */ - dev_priv->track_flush |= RADEON_FLUSH_EMITED; - return 0; } @@ -181,13 +166,13 @@ void r300_init_reg_flags(struct drm_device *dev) ADD_RANGE(0x21DC, 1); ADD_RANGE(R300_VAP_UNKNOWN_221C, 1); ADD_RANGE(R300_VAP_CLIP_X_0, 4); - ADD_RANGE(R300_VAP_PVS_STATE_FLUSH_REG, 1); + ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1); ADD_RANGE(R300_VAP_UNKNOWN_2288, 1); ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2); ADD_RANGE(R300_VAP_PVS_CNTL_1, 3); ADD_RANGE(R300_GB_ENABLE, 1); ADD_RANGE(R300_GB_MSPOS0, 5); - ADD_RANGE(R300_TX_INVALTAGS, 1); + ADD_RANGE(R300_TX_CNTL, 1); ADD_RANGE(R300_TX_ENABLE, 1); ADD_RANGE(0x4200, 4); ADD_RANGE(0x4214, 1); @@ -403,28 +388,15 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv, if (sz * 16 > cmdbuf->bufsz) return -EINVAL; - /* VAP is very sensitive so we purge cache before we program it - * and we also flush its state before & after */ - BEGIN_RING(6); - OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); - OUT_RING(R300_RB3D_DC_FLUSH); - OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_RING(RADEON_WAIT_3D_IDLECLEAN); - OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0)); - OUT_RING(0); - ADVANCE_RING(); - /* set flush flag */ - dev_priv->track_flush |= RADEON_FLUSH_EMITED; - - BEGIN_RING(3 + sz * 4); + BEGIN_RING(5 + sz * 4); + /* Wait for VAP to come to senses.. */ + /* there is no need to emit it multiple times, (only once before VAP is programmed, + but this optimization is for later */ + OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0); OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr); OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1)); OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4); - ADVANCE_RING(); - BEGIN_RING(2); - OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0)); - OUT_RING(0); ADVANCE_RING(); cmdbuf->buf += sz * 16; @@ -452,15 +424,6 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv, OUT_RING_TABLE((int *)cmdbuf->buf, 8); ADVANCE_RING(); - BEGIN_RING(4); - OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); - OUT_RING(R300_RB3D_DC_FLUSH); - OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_RING(RADEON_WAIT_3D_IDLECLEAN); - ADVANCE_RING(); - /* set flush flag */ - dev_priv->track_flush |= RADEON_FLUSH_EMITED; - cmdbuf->buf += 8 * 4; cmdbuf->bufsz -= 8 * 4; @@ -580,23 +543,22 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, return 0; } -static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv, - drm_radeon_kcmd_buffer_t *cmdbuf) +static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf) { - u32 *cmd; - int count; - int expected_count; + u32 *cmd = (u32 *) cmdbuf->buf; + int count, ret; RING_LOCALS; - cmd = (u32 *) cmdbuf->buf; - count = (cmd[0]>>16) & 0x3fff; - expected_count = cmd[1] >> 16; - if (!(cmd[1] & R300_VAP_VF_CNTL__INDEX_SIZE_32bit)) - expected_count = (expected_count+1)/2; + count=(cmd[0]>>16) & 0x3fff; - if (count && count != expected_count) { - DRM_ERROR("3D_DRAW_INDX_2: packet size %i, expected %i\n", - count, expected_count); + if ((cmd[1] & 0x8000ffff) != 0x80000810) { + DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); + return -EINVAL; + } + ret = !radeon_check_offset(dev_priv, cmd[2]); + if (ret) { + DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); return -EINVAL; } @@ -608,50 +570,6 @@ static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv, cmdbuf->buf += (count+2)*4; cmdbuf->bufsz -= (count+2)*4; - if (!count) { - drm_r300_cmd_header_t header; - - if (cmdbuf->bufsz < 4*4 + sizeof(header)) { - DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n"); - return -EINVAL; - } - - header.u = *(unsigned int *)cmdbuf->buf; - - cmdbuf->buf += sizeof(header); - cmdbuf->bufsz -= sizeof(header); - cmd = (u32 *) cmdbuf->buf; - - if (header.header.cmd_type != R300_CMD_PACKET3 || - header.packet3.packet != R300_CMD_PACKET3_RAW || - cmd[0] != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) { - DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n"); - return -EINVAL; - } - - if ((cmd[1] & 0x8000ffff) != 0x80000810) { - DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); - return -EINVAL; - } - if (!radeon_check_offset(dev_priv, cmd[2])) { - DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); - return -EINVAL; - } - if (cmd[3] != expected_count) { - DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n", - cmd[3], expected_count); - return -EINVAL; - } - - BEGIN_RING(4); - OUT_RING(cmd[0]); - OUT_RING_TABLE((int *)(cmdbuf->buf + 4), 3); - ADVANCE_RING(); - - cmdbuf->buf += 4*4; - cmdbuf->bufsz -= 4*4; - } - return 0; } @@ -695,22 +613,11 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, case RADEON_CNTL_BITBLT_MULTI: return r300_emit_bitblt_multi(dev_priv, cmdbuf); - case RADEON_CP_INDX_BUFFER: - DRM_ERROR("packet3 INDX_BUFFER without preceding 3D_DRAW_INDX_2 is illegal.\n"); - return -EINVAL; - case RADEON_CP_3D_DRAW_IMMD_2: - /* triggers drawing using in-packet vertex data */ - case RADEON_CP_3D_DRAW_VBUF_2: - /* triggers drawing of vertex buffers setup elsewhere */ - dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | - RADEON_PURGE_EMITED); - break; - case RADEON_CP_3D_DRAW_INDX_2: - /* triggers drawing using indices to vertex buffer */ - /* whenever we send vertex we clear flush & purge */ - dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | - RADEON_PURGE_EMITED); - return r300_emit_draw_indx_2(dev_priv, cmdbuf); + case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ + return r300_emit_indx_buffer(dev_priv, cmdbuf); + case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ + case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ + case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ case RADEON_WAIT_FOR_IDLE: case RADEON_CP_NOP: /* these packets are safe */ @@ -806,53 +713,17 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv, */ static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv) { - uint32_t cache_z, cache_3d, cache_2d; RING_LOCALS; - cache_z = R300_ZC_FLUSH; - cache_2d = R300_RB2D_DC_FLUSH; - cache_3d = R300_RB3D_DC_FLUSH; - if (!(dev_priv->track_flush & RADEON_PURGE_EMITED)) { - /* we can purge, primitive where draw since last purge */ - cache_z |= R300_ZC_FREE; - cache_2d |= R300_RB2D_DC_FREE; - cache_3d |= R300_RB3D_DC_FREE; - } - - /* flush & purge zbuffer */ - BEGIN_RING(2); - OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); - OUT_RING(cache_z); - ADVANCE_RING(); - /* flush & purge 3d */ - BEGIN_RING(2); + BEGIN_RING(6); OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); - OUT_RING(cache_3d); - ADVANCE_RING(); - /* flush & purge texture */ - BEGIN_RING(2); - OUT_RING(CP_PACKET0(R300_TX_INVALTAGS, 0)); - OUT_RING(0); - ADVANCE_RING(); - /* FIXME: is this one really needed ? */ - BEGIN_RING(2); - OUT_RING(CP_PACKET0(R300_RB3D_AARESOLVE_CTL, 0)); - OUT_RING(0); - ADVANCE_RING(); - BEGIN_RING(2); - OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_RING(RADEON_WAIT_3D_IDLECLEAN); - ADVANCE_RING(); - /* flush & purge 2d through E2 as RB2D will trigger lockup */ - BEGIN_RING(4); - OUT_RING(CP_PACKET0(R300_DSTCACHE_CTLSTAT, 0)); - OUT_RING(cache_2d); - OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_RING(RADEON_WAIT_2D_IDLECLEAN | - RADEON_WAIT_HOST_IDLECLEAN); + OUT_RING(R300_RB3D_DSTCACHE_UNKNOWN_0A); + OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); + OUT_RING(R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE| + R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE); + OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0)); + OUT_RING(0x0); ADVANCE_RING(); - /* set flush & purge flags */ - dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED; } /** @@ -1034,7 +905,8 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, DRM_DEBUG("\n"); - /* pacify */ + /* See the comment above r300_emit_begin3d for why this call must be here, + * and what the cleanup gotos are for. */ r300_pacify(dev_priv); if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) { diff --git a/trunk/drivers/gpu/drm/radeon/r300_reg.h b/trunk/drivers/gpu/drm/radeon/r300_reg.h index ee6f811599a3..a6802f26afc4 100644 --- a/trunk/drivers/gpu/drm/radeon/r300_reg.h +++ b/trunk/drivers/gpu/drm/radeon/r300_reg.h @@ -317,7 +317,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * Therefore, I suspect writing zero to 0x2284 synchronizes the engine and * avoids bugs caused by still running shaders reading bad data from memory. */ -#define R300_VAP_PVS_STATE_FLUSH_REG 0x2284 +#define R300_VAP_PVS_WAITIDLE 0x2284 /* GUESS */ /* Absolutely no clue what this register is about. */ #define R300_VAP_UNKNOWN_2288 0x2288 @@ -513,7 +513,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* gap */ /* Zero to flush caches. */ -#define R300_TX_INVALTAGS 0x4100 +#define R300_TX_CNTL 0x4100 #define R300_TX_FLUSH 0x0 /* The upper enable bits are guessed, based on fglrx reported limits. */ @@ -1362,7 +1362,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */ #define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */ -#define R300_RB3D_AARESOLVE_CTL 0x4E88 /* gap */ /* Guess by Vladimir. diff --git a/trunk/drivers/gpu/drm/radeon/radeon_cp.c b/trunk/drivers/gpu/drm/radeon/radeon_cp.c index 3331f88dcfb6..f0de81a5689d 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_cp.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_cp.c @@ -40,7 +40,6 @@ #define RADEON_FIFO_DEBUG 0 static int radeon_do_cleanup_cp(struct drm_device * dev); -static void radeon_do_cp_start(drm_radeon_private_t * dev_priv); static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) { @@ -199,8 +198,23 @@ static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv) DRM_UDELAY(1); } } else { - /* don't flush or purge cache here or lockup */ - return 0; + /* 3D */ + tmp = RADEON_READ(R300_RB3D_DSTCACHE_CTLSTAT); + tmp |= RADEON_RB3D_DC_FLUSH_ALL; + RADEON_WRITE(R300_RB3D_DSTCACHE_CTLSTAT, tmp); + + /* 2D */ + tmp = RADEON_READ(R300_DSTCACHE_CTLSTAT); + tmp |= RADEON_RB3D_DC_FLUSH_ALL; + RADEON_WRITE(R300_DSTCACHE_CTLSTAT, tmp); + + for (i = 0; i < dev_priv->usec_timeout; i++) { + if (!(RADEON_READ(R300_DSTCACHE_CTLSTAT) + & RADEON_RB3D_DC_BUSY)) { + return 0; + } + DRM_UDELAY(1); + } } #if RADEON_FIFO_DEBUG @@ -223,9 +237,6 @@ static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries) return 0; DRM_UDELAY(1); } - DRM_INFO("wait for fifo failed status : 0x%08X 0x%08X\n", - RADEON_READ(RADEON_RBBM_STATUS), - RADEON_READ(R300_VAP_CNTL_STATUS)); #if RADEON_FIFO_DEBUG DRM_ERROR("failed!\n"); @@ -252,9 +263,6 @@ static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv) } DRM_UDELAY(1); } - DRM_INFO("wait idle failed status : 0x%08X 0x%08X\n", - RADEON_READ(RADEON_RBBM_STATUS), - RADEON_READ(R300_VAP_CNTL_STATUS)); #if RADEON_FIFO_DEBUG DRM_ERROR("failed!\n"); @@ -435,20 +443,14 @@ static void radeon_do_cp_start(drm_radeon_private_t * dev_priv) dev_priv->cp_running = 1; - BEGIN_RING(8); - /* isync can only be written through cp on r5xx write it here */ - OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0)); - OUT_RING(RADEON_ISYNC_ANY2D_IDLE3D | - RADEON_ISYNC_ANY3D_IDLE2D | - RADEON_ISYNC_WAIT_IDLEGUI | - RADEON_ISYNC_CPSCRATCH_IDLEGUI); + BEGIN_RING(6); + RADEON_PURGE_CACHE(); RADEON_PURGE_ZCACHE(); RADEON_WAIT_UNTIL_IDLE(); + ADVANCE_RING(); COMMIT_RING(); - - dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED; } /* Reset the Command Processor. This will not flush any pending diff --git a/trunk/drivers/gpu/drm/radeon/radeon_drv.h b/trunk/drivers/gpu/drm/radeon/radeon_drv.h index 099381693175..3f0eca957aa7 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_drv.h +++ b/trunk/drivers/gpu/drm/radeon/radeon_drv.h @@ -220,9 +220,6 @@ struct radeon_virt_surface { struct drm_file *file_priv; }; -#define RADEON_FLUSH_EMITED (1 < 0) -#define RADEON_PURGE_EMITED (1 < 1) - typedef struct drm_radeon_private { drm_radeon_ring_buffer_t ring; drm_radeon_sarea_t *sarea_priv; @@ -314,7 +311,6 @@ typedef struct drm_radeon_private { unsigned long fb_aper_offset; int num_gb_pipes; - int track_flush; } drm_radeon_private_t; typedef struct drm_radeon_buf_priv { @@ -697,6 +693,7 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev, #define R300_ZB_ZCACHE_CTLSTAT 0x4f18 # define R300_ZC_FLUSH (1 << 0) # define R300_ZC_FREE (1 << 1) +# define R300_ZC_FLUSH_ALL 0x3 # define R300_ZC_BUSY (1 << 31) #define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325c # define RADEON_RB3D_DC_FLUSH (3 << 0) @@ -704,8 +701,6 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev, # define RADEON_RB3D_DC_FLUSH_ALL 0xf # define RADEON_RB3D_DC_BUSY (1 << 31) #define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c -# define R300_RB3D_DC_FLUSH (2 << 0) -# define R300_RB3D_DC_FREE (2 << 2) # define R300_RB3D_DC_FINISH (1 << 4) #define RADEON_RB3D_ZSTENCILCNTL 0x1c2c # define RADEON_Z_TEST_MASK (7 << 4) @@ -1251,17 +1246,17 @@ do { \ OUT_RING(RADEON_RB3D_DC_FLUSH); \ } else { \ OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(R300_RB3D_DC_FLUSH); \ + OUT_RING(RADEON_RB3D_DC_FLUSH); \ } \ } while (0) #define RADEON_PURGE_CACHE() do { \ if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB3D_DC_FLUSH | RADEON_RB3D_DC_FREE); \ + OUT_RING(RADEON_RB3D_DC_FLUSH_ALL); \ } else { \ OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); \ + OUT_RING(RADEON_RB3D_DC_FLUSH_ALL); \ } \ } while (0) @@ -1278,10 +1273,10 @@ do { \ #define RADEON_PURGE_ZCACHE() do { \ if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB3D_ZC_FLUSH | RADEON_RB3D_ZC_FREE); \ + OUT_RING(RADEON_RB3D_ZC_FLUSH_ALL); \ } else { \ - OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); \ - OUT_RING(R300_ZC_FLUSH | R300_ZC_FREE); \ + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ + OUT_RING(R300_ZC_FLUSH_ALL); \ } \ } while (0) diff --git a/trunk/drivers/net/e1000/e1000_param.c b/trunk/drivers/net/e1000/e1000_param.c index 213437d13154..b9f90a5d3d4d 100644 --- a/trunk/drivers/net/e1000/e1000_param.c +++ b/trunk/drivers/net/e1000/e1000_param.c @@ -208,7 +208,7 @@ struct e1000_option { } r; struct { /* list_option info */ int nr; - const struct e1000_opt_list { int i; char *str; } *p; + struct e1000_opt_list { int i; char *str; } *p; } l; } arg; }; @@ -242,7 +242,7 @@ static int __devinit e1000_validate_option(unsigned int *value, break; case list_option: { int i; - const struct e1000_opt_list *ent; + struct e1000_opt_list *ent; for (i = 0; i < opt->arg.l.nr; i++) { ent = &opt->arg.l.p[i]; @@ -279,9 +279,7 @@ static void e1000_check_copper_options(struct e1000_adapter *adapter); void __devinit e1000_check_options(struct e1000_adapter *adapter) { - struct e1000_option opt; int bd = adapter->bd_number; - if (bd >= E1000_MAX_NIC) { DPRINTK(PROBE, NOTICE, "Warning: no configuration for board #%i\n", bd); @@ -289,21 +287,19 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } { /* Transmit Descriptor Count */ - struct e1000_tx_ring *tx_ring = adapter->tx_ring; - int i; - e1000_mac_type mac_type = adapter->hw.mac_type; - - opt = (struct e1000_option) { + struct e1000_option opt = { .type = range_option, .name = "Transmit Descriptors", .err = "using default of " __MODULE_STRING(E1000_DEFAULT_TXD), .def = E1000_DEFAULT_TXD, - .arg = { .r = { - .min = E1000_MIN_TXD, - .max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD - }} + .arg = { .r = { .min = E1000_MIN_TXD }} }; + struct e1000_tx_ring *tx_ring = adapter->tx_ring; + int i; + e1000_mac_type mac_type = adapter->hw.mac_type; + opt.arg.r.max = mac_type < e1000_82544 ? + E1000_MAX_TXD : E1000_MAX_82544_TXD; if (num_TxDescriptors > bd) { tx_ring->count = TxDescriptors[bd]; @@ -317,21 +313,19 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) tx_ring[i].count = tx_ring->count; } { /* Receive Descriptor Count */ - struct e1000_rx_ring *rx_ring = adapter->rx_ring; - int i; - e1000_mac_type mac_type = adapter->hw.mac_type; - - opt = (struct e1000_option) { + struct e1000_option opt = { .type = range_option, .name = "Receive Descriptors", .err = "using default of " __MODULE_STRING(E1000_DEFAULT_RXD), .def = E1000_DEFAULT_RXD, - .arg = { .r = { - .min = E1000_MIN_RXD, - .max = mac_type < e1000_82544 ? E1000_MAX_RXD : E1000_MAX_82544_RXD - }} + .arg = { .r = { .min = E1000_MIN_RXD }} }; + struct e1000_rx_ring *rx_ring = adapter->rx_ring; + int i; + e1000_mac_type mac_type = adapter->hw.mac_type; + opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD : + E1000_MAX_82544_RXD; if (num_RxDescriptors > bd) { rx_ring->count = RxDescriptors[bd]; @@ -345,7 +339,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) rx_ring[i].count = rx_ring->count; } { /* Checksum Offload Enable/Disable */ - opt = (struct e1000_option) { + struct e1000_option opt = { .type = enable_option, .name = "Checksum Offload", .err = "defaulting to Enabled", @@ -369,7 +363,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) { E1000_FC_FULL, "Flow Control Enabled" }, { E1000_FC_DEFAULT, "Flow Control Hardware Default" }}; - opt = (struct e1000_option) { + struct e1000_option opt = { .type = list_option, .name = "Flow Control", .err = "reading default settings from EEPROM", @@ -387,7 +381,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Transmit Interrupt Delay */ - opt = (struct e1000_option) { + struct e1000_option opt = { .type = range_option, .name = "Transmit Interrupt Delay", .err = "using default of " __MODULE_STRING(DEFAULT_TIDV), @@ -405,7 +399,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Transmit Absolute Interrupt Delay */ - opt = (struct e1000_option) { + struct e1000_option opt = { .type = range_option, .name = "Transmit Absolute Interrupt Delay", .err = "using default of " __MODULE_STRING(DEFAULT_TADV), @@ -423,7 +417,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Receive Interrupt Delay */ - opt = (struct e1000_option) { + struct e1000_option opt = { .type = range_option, .name = "Receive Interrupt Delay", .err = "using default of " __MODULE_STRING(DEFAULT_RDTR), @@ -441,7 +435,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Receive Absolute Interrupt Delay */ - opt = (struct e1000_option) { + struct e1000_option opt = { .type = range_option, .name = "Receive Absolute Interrupt Delay", .err = "using default of " __MODULE_STRING(DEFAULT_RADV), @@ -459,7 +453,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Interrupt Throttling Rate */ - opt = (struct e1000_option) { + struct e1000_option opt = { .type = range_option, .name = "Interrupt Throttling Rate (ints/sec)", .err = "using default of " __MODULE_STRING(DEFAULT_ITR), @@ -503,7 +497,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Smart Power Down */ - opt = (struct e1000_option) { + struct e1000_option opt = { .type = enable_option, .name = "PHY Smart Power Down", .err = "defaulting to Disabled", @@ -519,7 +513,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Kumeran Lock Loss Workaround */ - opt = (struct e1000_option) { + struct e1000_option opt = { .type = enable_option, .name = "Kumeran Lock Loss Workaround", .err = "defaulting to Enabled", @@ -584,18 +578,16 @@ static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter) static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter) { - struct e1000_option opt; unsigned int speed, dplx, an; int bd = adapter->bd_number; { /* Speed */ - static const struct e1000_opt_list speed_list[] = { - { 0, "" }, - { SPEED_10, "" }, - { SPEED_100, "" }, - { SPEED_1000, "" }}; + struct e1000_opt_list speed_list[] = {{ 0, "" }, + { SPEED_10, "" }, + { SPEED_100, "" }, + { SPEED_1000, "" }}; - opt = (struct e1000_option) { + struct e1000_option opt = { .type = list_option, .name = "Speed", .err = "parameter ignored", @@ -612,12 +604,11 @@ static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter) } } { /* Duplex */ - static const struct e1000_opt_list dplx_list[] = { - { 0, "" }, - { HALF_DUPLEX, "" }, - { FULL_DUPLEX, "" }}; + struct e1000_opt_list dplx_list[] = {{ 0, "" }, + { HALF_DUPLEX, "" }, + { FULL_DUPLEX, "" }}; - opt = (struct e1000_option) { + struct e1000_option opt = { .type = list_option, .name = "Duplex", .err = "parameter ignored", @@ -646,7 +637,7 @@ static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter) "parameter ignored\n"); adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT; } else { /* Autoneg */ - static const struct e1000_opt_list an_list[] = + struct e1000_opt_list an_list[] = #define AA "AutoNeg advertising " {{ 0x01, AA "10/HD" }, { 0x02, AA "10/FD" }, @@ -680,7 +671,7 @@ static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter) { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" }, { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }}; - opt = (struct e1000_option) { + struct e1000_option opt = { .type = list_option, .name = "AutoNeg", .err = "parameter ignored", diff --git a/trunk/drivers/s390/block/dcssblk.c b/trunk/drivers/s390/block/dcssblk.c index 711b3004b3e6..db85f1fb131e 100644 --- a/trunk/drivers/s390/block/dcssblk.c +++ b/trunk/drivers/s390/block/dcssblk.c @@ -384,10 +384,9 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char * get minor, add to list */ down_write(&dcssblk_devices_sem); - if (dcssblk_get_device_by_name(local_buf)) { - up_write(&dcssblk_devices_sem); + if (dcssblk_get_segment_by_name(local_buf)) { rc = -EEXIST; - goto unload_seg; + goto release_gd; } rc = dcssblk_assign_free_minor(dev_info); if (rc) { diff --git a/trunk/drivers/scsi/sg.c b/trunk/drivers/scsi/sg.c index 661f9f21650a..3d36270a8b4d 100644 --- a/trunk/drivers/scsi/sg.c +++ b/trunk/drivers/scsi/sg.c @@ -217,18 +217,6 @@ static int sg_last_dev(void); #define SZ_SG_IOVEC sizeof(sg_iovec_t) #define SZ_SG_REQ_INFO sizeof(sg_req_info_t) -static int sg_allow_access(struct file *filp, unsigned char *cmd) -{ - struct sg_fd *sfp = (struct sg_fd *)filp->private_data; - struct request_queue *q = sfp->parentdp->device->request_queue; - - if (sfp->parentdp->device->type == TYPE_SCANNER) - return 0; - - return blk_verify_command(&q->cmd_filter, - cmd, filp->f_mode & FMODE_WRITE); -} - static int sg_open(struct inode *inode, struct file *filp) { @@ -701,7 +689,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, sg_remove_request(sfp, srp); return -EFAULT; } - if (read_only && sg_allow_access(file, cmnd)) { + if (read_only && !blk_verify_command(file, cmnd)) { sg_remove_request(sfp, srp); return -EPERM; } @@ -805,7 +793,6 @@ sg_ioctl(struct inode *inode, struct file *filp, if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: %s, cmd=0x%x\n", sdp->disk->disk_name, (int) cmd_in)); read_only = (O_RDWR != (filp->f_flags & O_ACCMODE)); @@ -1074,7 +1061,7 @@ sg_ioctl(struct inode *inode, struct file *filp, if (copy_from_user(&opcode, siocp->data, 1)) return -EFAULT; - if (sg_allow_access(filp, &opcode)) + if (!blk_verify_command(filp, &opcode)) return -EPERM; } return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p); diff --git a/trunk/drivers/watchdog/s3c2410_wdt.c b/trunk/drivers/watchdog/s3c2410_wdt.c index 22715e3be5e7..27af55f193d2 100644 --- a/trunk/drivers/watchdog/s3c2410_wdt.c +++ b/trunk/drivers/watchdog/s3c2410_wdt.c @@ -374,7 +374,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev) } wdt_base = ioremap(res->start, size); - if (wdt_base == 0) { + if (wdt_base == NULL) { dev_err(dev, "failed to ioremap() region\n"); ret = -EINVAL; goto err_req; diff --git a/trunk/fs/9p/vfs_dir.c b/trunk/fs/9p/vfs_dir.c index e298fe194093..88e3787c6ea9 100644 --- a/trunk/fs/9p/vfs_dir.c +++ b/trunk/fs/9p/vfs_dir.c @@ -119,7 +119,6 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) const struct file_operations v9fs_dir_operations = { .read = generic_read_dir, - .llseek = generic_file_llseek, .readdir = v9fs_dir_readdir, .open = v9fs_file_open, .release = v9fs_dir_release, diff --git a/trunk/fs/Kconfig b/trunk/fs/Kconfig index abccb5dab9a8..f0427105a619 100644 --- a/trunk/fs/Kconfig +++ b/trunk/fs/Kconfig @@ -1930,16 +1930,6 @@ config CIFS_WEAK_PW_HASH If unsure, say N. -config CIFS_UPCALL - bool "Kerberos/SPNEGO advanced session setup" - depends on CIFS && KEYS - help - Enables an upcall mechanism for CIFS which accesses - userspace helper utilities to provide SPNEGO packaged (RFC 4178) - Kerberos tickets which are needed to mount to certain secure servers - (for which more secure Kerberos authentication is required). If - unsure, say N. - config CIFS_XATTR bool "CIFS extended attributes" depends on CIFS @@ -1992,6 +1982,16 @@ config CIFS_EXPERIMENTAL (which is disabled by default). See the file fs/cifs/README for more details. If unsure, say N. +config CIFS_UPCALL + bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" + depends on KEYS + help + Enables an upcall mechanism for CIFS which accesses + userspace helper utilities to provide SPNEGO packaged (RFC 4178) + Kerberos tickets which are needed to mount to certain secure servers + (for which more secure Kerberos authentication is required). If + unsure, say N. + config CIFS_DFS_UPCALL bool "DFS feature support (EXPERIMENTAL)" depends on CIFS_EXPERIMENTAL diff --git a/trunk/fs/adfs/dir.c b/trunk/fs/adfs/dir.c index 85a30e929800..fc1a8dc64d78 100644 --- a/trunk/fs/adfs/dir.c +++ b/trunk/fs/adfs/dir.c @@ -197,7 +197,6 @@ adfs_dir_lookup_byname(struct inode *inode, struct qstr *name, struct object_inf const struct file_operations adfs_dir_operations = { .read = generic_read_dir, - .llseek = generic_file_llseek, .readdir = adfs_readdir, .fsync = file_fsync, }; diff --git a/trunk/fs/affs/dir.c b/trunk/fs/affs/dir.c index 7b36904dbeac..6e3f282424b0 100644 --- a/trunk/fs/affs/dir.c +++ b/trunk/fs/affs/dir.c @@ -19,7 +19,6 @@ static int affs_readdir(struct file *, void *, filldir_t); const struct file_operations affs_dir_operations = { .read = generic_read_dir, - .llseek = generic_file_llseek, .readdir = affs_readdir, .fsync = file_fsync, }; diff --git a/trunk/fs/autofs4/root.c b/trunk/fs/autofs4/root.c index 2a41c2a7fc52..bcfb2dc0a61b 100644 --- a/trunk/fs/autofs4/root.c +++ b/trunk/fs/autofs4/root.c @@ -36,7 +36,6 @@ const struct file_operations autofs4_root_operations = { .release = dcache_dir_close, .read = generic_read_dir, .readdir = dcache_readdir, - .llseek = dcache_dir_lseek, .ioctl = autofs4_root_ioctl, }; @@ -45,7 +44,6 @@ const struct file_operations autofs4_dir_operations = { .release = dcache_dir_close, .read = generic_read_dir, .readdir = dcache_readdir, - .llseek = dcache_dir_lseek, }; const struct inode_operations autofs4_indirect_root_inode_operations = { diff --git a/trunk/fs/befs/linuxvfs.c b/trunk/fs/befs/linuxvfs.c index 740f53672a8a..02c6e62b72f8 100644 --- a/trunk/fs/befs/linuxvfs.c +++ b/trunk/fs/befs/linuxvfs.c @@ -66,7 +66,6 @@ static struct kmem_cache *befs_inode_cachep; static const struct file_operations befs_dir_operations = { .read = generic_read_dir, .readdir = befs_readdir, - .llseek = generic_file_llseek, }; static const struct inode_operations befs_dir_inode_operations = { diff --git a/trunk/fs/bio.c b/trunk/fs/bio.c index 3cba7ae34d75..8000e2fa16cb 100644 --- a/trunk/fs/bio.c +++ b/trunk/fs/bio.c @@ -469,21 +469,20 @@ static void bio_free_map_data(struct bio_map_data *bmd) kfree(bmd); } -static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count, - gfp_t gfp_mask) +static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count) { - struct bio_map_data *bmd = kmalloc(sizeof(*bmd), gfp_mask); + struct bio_map_data *bmd = kmalloc(sizeof(*bmd), GFP_KERNEL); if (!bmd) return NULL; - bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, gfp_mask); + bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, GFP_KERNEL); if (!bmd->iovecs) { kfree(bmd); return NULL; } - bmd->sgvecs = kmalloc(sizeof(struct sg_iovec) * iov_count, gfp_mask); + bmd->sgvecs = kmalloc(sizeof(struct sg_iovec) * iov_count, GFP_KERNEL); if (bmd->sgvecs) return bmd; @@ -492,8 +491,8 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count, return NULL; } -static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, - struct sg_iovec *iov, int iov_count, int uncopy) +static int __bio_copy_iov(struct bio *bio, struct sg_iovec *iov, int iov_count, + int uncopy) { int ret = 0, i; struct bio_vec *bvec; @@ -503,7 +502,7 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, __bio_for_each_segment(bvec, bio, i, 0) { char *bv_addr = page_address(bvec->bv_page); - unsigned int bv_len = iovecs[i].bv_len; + unsigned int bv_len = bvec->bv_len; while (bv_len && iov_idx < iov_count) { unsigned int bytes; @@ -555,7 +554,7 @@ int bio_uncopy_user(struct bio *bio) struct bio_map_data *bmd = bio->bi_private; int ret; - ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, bmd->nr_sgvecs, 1); + ret = __bio_copy_iov(bio, bmd->sgvecs, bmd->nr_sgvecs, 1); bio_free_map_data(bmd); bio_put(bio); @@ -597,7 +596,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, len += iov[i].iov_len; } - bmd = bio_alloc_map_data(nr_pages, iov_count, GFP_KERNEL); + bmd = bio_alloc_map_data(nr_pages, iov_count); if (!bmd) return ERR_PTR(-ENOMEM); @@ -634,7 +633,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, * success */ if (!write_to_vm) { - ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0); + ret = __bio_copy_iov(bio, iov, iov_count, 0); if (ret) goto cleanup; } @@ -943,22 +942,19 @@ static void bio_copy_kern_endio(struct bio *bio, int err) { struct bio_vec *bvec; const int read = bio_data_dir(bio) == READ; - struct bio_map_data *bmd = bio->bi_private; + char *p = bio->bi_private; int i; - char *p = bmd->sgvecs[0].iov_base; __bio_for_each_segment(bvec, bio, i, 0) { char *addr = page_address(bvec->bv_page); - int len = bmd->iovecs[i].bv_len; if (read && !err) - memcpy(p, addr, len); + memcpy(p, addr, bvec->bv_len); __free_page(bvec->bv_page); - p += len; + p += bvec->bv_len; } - bio_free_map_data(bmd); bio_put(bio); } @@ -982,21 +978,11 @@ struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len, const int nr_pages = end - start; struct bio *bio; struct bio_vec *bvec; - struct bio_map_data *bmd; int i, ret; - struct sg_iovec iov; - - iov.iov_base = data; - iov.iov_len = len; - - bmd = bio_alloc_map_data(nr_pages, 1, gfp_mask); - if (!bmd) - return ERR_PTR(-ENOMEM); - ret = -ENOMEM; bio = bio_alloc(gfp_mask, nr_pages); if (!bio) - goto out_bmd; + return ERR_PTR(-ENOMEM); while (len) { struct page *page; @@ -1030,18 +1016,14 @@ struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len, } } - bio->bi_private = bmd; + bio->bi_private = data; bio->bi_end_io = bio_copy_kern_endio; - - bio_set_map_data(bmd, bio, &iov, 1); return bio; cleanup: bio_for_each_segment(bvec, bio, i) __free_page(bvec->bv_page); bio_put(bio); -out_bmd: - bio_free_map_data(bmd); return ERR_PTR(ret); } diff --git a/trunk/fs/buffer.c b/trunk/fs/buffer.c index ac78d4c19b3b..38653e36e225 100644 --- a/trunk/fs/buffer.c +++ b/trunk/fs/buffer.c @@ -2926,17 +2926,14 @@ int submit_bh(int rw, struct buffer_head * bh) BUG_ON(!buffer_mapped(bh)); BUG_ON(!bh->b_end_io); - /* - * Mask in barrier bit for a write (could be either a WRITE or a - * WRITE_SYNC - */ - if (buffer_ordered(bh) && (rw & WRITE)) - rw |= WRITE_BARRIER; + if (buffer_ordered(bh) && (rw == WRITE)) + rw = WRITE_BARRIER; /* - * Only clear out a write error when rewriting + * Only clear out a write error when rewriting, should this + * include WRITE_SYNC as well? */ - if (test_set_buffer_req(bh) && (rw & WRITE)) + if (test_set_buffer_req(bh) && (rw == WRITE || rw == WRITE_BARRIER)) clear_buffer_write_io_error(bh); /* diff --git a/trunk/fs/cifs/CHANGES b/trunk/fs/cifs/CHANGES index f9e4ad97a79e..526041a52d35 100644 --- a/trunk/fs/cifs/CHANGES +++ b/trunk/fs/cifs/CHANGES @@ -8,8 +8,7 @@ architectures. Fix problems with preserving timestamps on copying open files (e.g. "cp -a") to Windows servers. For mkdir and create honor setgid bit on parent directory when server supports Unix Extensions but not POSIX create. Update cifs.upcall version to handle new Kerberos sec flags -(this requires update of cifs.upcall program from Samba). Fix memory leak -on dns_upcall (resolving DFS referralls). +(this requires update of cifs.upcall program from Samba). Version 1.53 ------------ diff --git a/trunk/fs/cifs/dns_resolve.c b/trunk/fs/cifs/dns_resolve.c index a2e0673e1b08..f730ef35499e 100644 --- a/trunk/fs/cifs/dns_resolve.c +++ b/trunk/fs/cifs/dns_resolve.c @@ -47,18 +47,11 @@ static int dns_resolver_instantiate(struct key *key, const void *data, return rc; } -static void -dns_resolver_destroy(struct key *key) -{ - kfree(key->payload.data); -} - struct key_type key_type_dns_resolver = { .name = "dns_resolver", .def_datalen = sizeof(struct in_addr), .describe = user_describe, .instantiate = dns_resolver_instantiate, - .destroy = dns_resolver_destroy, .match = user_match, }; diff --git a/trunk/fs/compat.c b/trunk/fs/compat.c index 075d0509970d..c9d1472e65c5 100644 --- a/trunk/fs/compat.c +++ b/trunk/fs/compat.c @@ -792,10 +792,8 @@ static int compat_fillonedir(void *__buf, const char *name, int namlen, if (buf->result) return -EINVAL; d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { - buf->result = -EOVERFLOW; + if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) return -EOVERFLOW; - } buf->result++; dirent = buf->dirent; if (!access_ok(VERIFY_WRITE, dirent, @@ -864,10 +862,8 @@ static int compat_filldir(void *__buf, const char *name, int namlen, if (reclen > buf->count) return -EINVAL; d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { - buf->error = -EOVERFLOW; + if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) return -EOVERFLOW; - } dirent = buf->previous; if (dirent) { if (__put_user(offset, &dirent->d_off)) diff --git a/trunk/fs/configfs/dir.c b/trunk/fs/configfs/dir.c index 8e93341f3e82..7a8db78a91d2 100644 --- a/trunk/fs/configfs/dir.c +++ b/trunk/fs/configfs/dir.c @@ -1311,18 +1311,16 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) * Ensure that no racing symlink() will make detach_prep() fail while * the new link is temporarily attached */ + mutex_lock(&configfs_symlink_mutex); + spin_lock(&configfs_dirent_lock); do { struct mutex *wait_mutex; - mutex_lock(&configfs_symlink_mutex); - spin_lock(&configfs_dirent_lock); ret = configfs_detach_prep(dentry, &wait_mutex); - if (ret) - configfs_detach_rollback(dentry); - spin_unlock(&configfs_dirent_lock); - mutex_unlock(&configfs_symlink_mutex); - if (ret) { + configfs_detach_rollback(dentry); + spin_unlock(&configfs_dirent_lock); + mutex_unlock(&configfs_symlink_mutex); if (ret != -EAGAIN) { config_item_put(parent_item); return ret; @@ -1331,8 +1329,13 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) /* Wait until the racing operation terminates */ mutex_lock(wait_mutex); mutex_unlock(wait_mutex); + + mutex_lock(&configfs_symlink_mutex); + spin_lock(&configfs_dirent_lock); } } while (ret == -EAGAIN); + spin_unlock(&configfs_dirent_lock); + mutex_unlock(&configfs_symlink_mutex); /* Get a working ref for the duration of this function */ item = configfs_get_config_item(dentry); diff --git a/trunk/fs/dcache.c b/trunk/fs/dcache.c index 80e93956aced..101663d15e9f 100644 --- a/trunk/fs/dcache.c +++ b/trunk/fs/dcache.c @@ -1236,7 +1236,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) * If no entry exists with the exact case name, allocate new dentry with * the exact case, and return the spliced entry. */ -struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode, +struct dentry *d_add_ci(struct inode *inode, struct dentry *dentry, struct qstr *name) { int error; diff --git a/trunk/fs/efs/namei.c b/trunk/fs/efs/namei.c index 291abb11e20e..3a404e7fad53 100644 --- a/trunk/fs/efs/namei.c +++ b/trunk/fs/efs/namei.c @@ -74,7 +74,8 @@ struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct namei } unlock_kernel(); - return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return NULL; } static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino, diff --git a/trunk/fs/ntfs/namei.c b/trunk/fs/ntfs/namei.c index 9e8a95be7a1e..e1781c8b1650 100644 --- a/trunk/fs/ntfs/namei.c +++ b/trunk/fs/ntfs/namei.c @@ -174,6 +174,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, // TODO: Consider moving this lot to a separate function! (AIA) handle_name: { + struct dentry *real_dent, *new_dent; MFT_RECORD *m; ntfs_attr_search_ctx *ctx; ntfs_inode *ni = NTFS_I(dent_inode); @@ -254,9 +255,93 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, } nls_name.hash = full_name_hash(nls_name.name, nls_name.len); - dent = d_add_ci(dent, dent_inode, &nls_name); + /* + * Note: No need for dent->d_lock lock as i_mutex is held on the + * parent inode. + */ + + /* Does a dentry matching the nls_name exist already? */ + real_dent = d_lookup(dent->d_parent, &nls_name); + /* If not, create it now. */ + if (!real_dent) { + real_dent = d_alloc(dent->d_parent, &nls_name); + kfree(nls_name.name); + if (!real_dent) { + err = -ENOMEM; + goto err_out; + } + new_dent = d_splice_alias(dent_inode, real_dent); + if (new_dent) + dput(real_dent); + else + new_dent = real_dent; + ntfs_debug("Done. (Created new dentry.)"); + return new_dent; + } kfree(nls_name.name); - return dent; + /* Matching dentry exists, check if it is negative. */ + if (real_dent->d_inode) { + if (unlikely(real_dent->d_inode != dent_inode)) { + /* This can happen because bad inodes are unhashed. */ + BUG_ON(!is_bad_inode(dent_inode)); + BUG_ON(!is_bad_inode(real_dent->d_inode)); + } + /* + * Already have the inode and the dentry attached, decrement + * the reference count to balance the ntfs_iget() we did + * earlier on. We found the dentry using d_lookup() so it + * cannot be disconnected and thus we do not need to worry + * about any NFS/disconnectedness issues here. + */ + iput(dent_inode); + ntfs_debug("Done. (Already had inode and dentry.)"); + return real_dent; + } + /* + * Negative dentry: instantiate it unless the inode is a directory and + * has a 'disconnected' dentry (i.e. IS_ROOT and DCACHE_DISCONNECTED), + * in which case d_move() that in place of the found dentry. + */ + if (!S_ISDIR(dent_inode->i_mode)) { + /* Not a directory; everything is easy. */ + d_instantiate(real_dent, dent_inode); + ntfs_debug("Done. (Already had negative file dentry.)"); + return real_dent; + } + spin_lock(&dcache_lock); + if (list_empty(&dent_inode->i_dentry)) { + /* + * Directory without a 'disconnected' dentry; we need to do + * d_instantiate() by hand because it takes dcache_lock which + * we already hold. + */ + list_add(&real_dent->d_alias, &dent_inode->i_dentry); + real_dent->d_inode = dent_inode; + spin_unlock(&dcache_lock); + security_d_instantiate(real_dent, dent_inode); + ntfs_debug("Done. (Already had negative directory dentry.)"); + return real_dent; + } + /* + * Directory with a 'disconnected' dentry; get a reference to the + * 'disconnected' dentry. + */ + new_dent = list_entry(dent_inode->i_dentry.next, struct dentry, + d_alias); + dget_locked(new_dent); + spin_unlock(&dcache_lock); + /* Do security vodoo. */ + security_d_instantiate(real_dent, dent_inode); + /* Move new_dent in place of real_dent. */ + d_move(new_dent, real_dent); + /* Balance the ntfs_iget() we did above. */ + iput(dent_inode); + /* Throw away real_dent. */ + dput(real_dent); + /* Use new_dent as the actual dentry. */ + ntfs_debug("Done. (Already had negative, disconnected directory " + "dentry.)"); + return new_dent; eio_err_out: ntfs_error(vol->sb, "Illegal file name attribute. Run chkdsk."); diff --git a/trunk/fs/ocfs2/cluster/netdebug.c b/trunk/fs/ocfs2/cluster/netdebug.c index 52276c02f710..d8bfa0eb41b2 100644 --- a/trunk/fs/ocfs2/cluster/netdebug.c +++ b/trunk/fs/ocfs2/cluster/netdebug.c @@ -138,20 +138,20 @@ static int nst_seq_show(struct seq_file *seq, void *v) " message id: %d\n" " message type: %u\n" " message key: 0x%08x\n" - " sock acquiry: %lu.%ld\n" - " send start: %lu.%ld\n" - " wait start: %lu.%ld\n", + " sock acquiry: %lu.%lu\n" + " send start: %lu.%lu\n" + " wait start: %lu.%lu\n", nst, (unsigned long)nst->st_task->pid, (unsigned long)nst->st_task->tgid, nst->st_task->comm, nst->st_node, nst->st_sc, nst->st_id, nst->st_msg_type, nst->st_msg_key, nst->st_sock_time.tv_sec, - (long)nst->st_sock_time.tv_usec, + (unsigned long)nst->st_sock_time.tv_usec, nst->st_send_time.tv_sec, - (long)nst->st_send_time.tv_usec, + (unsigned long)nst->st_send_time.tv_usec, nst->st_status_time.tv_sec, - (long)nst->st_status_time.tv_usec); + nst->st_status_time.tv_usec); } spin_unlock(&o2net_debug_lock); @@ -276,7 +276,7 @@ static void *sc_seq_next(struct seq_file *seq, void *v, loff_t *pos) return sc; /* unused, just needs to be null when done */ } -#define TV_SEC_USEC(TV) TV.tv_sec, (long)TV.tv_usec +#define TV_SEC_USEC(TV) TV.tv_sec, (unsigned long)TV.tv_usec static int sc_seq_show(struct seq_file *seq, void *v) { @@ -309,12 +309,12 @@ static int sc_seq_show(struct seq_file *seq, void *v) " remote node: %s\n" " page off: %zu\n" " handshake ok: %u\n" - " timer: %lu.%ld\n" - " data ready: %lu.%ld\n" - " advance start: %lu.%ld\n" - " advance stop: %lu.%ld\n" - " func start: %lu.%ld\n" - " func stop: %lu.%ld\n" + " timer: %lu.%lu\n" + " data ready: %lu.%lu\n" + " advance start: %lu.%lu\n" + " advance stop: %lu.%lu\n" + " func start: %lu.%lu\n" + " func stop: %lu.%lu\n" " func key: %u\n" " func type: %u\n", sc, diff --git a/trunk/fs/ocfs2/cluster/tcp.c b/trunk/fs/ocfs2/cluster/tcp.c index 2bcf706d9dd3..a27d61581bd6 100644 --- a/trunk/fs/ocfs2/cluster/tcp.c +++ b/trunk/fs/ocfs2/cluster/tcp.c @@ -143,8 +143,8 @@ static void o2net_sc_postpone_idle(struct o2net_sock_container *sc); static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc); #ifdef CONFIG_DEBUG_FS -static void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, - u32 msgkey, struct task_struct *task, u8 node) +void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, + u32 msgkey, struct task_struct *task, u8 node) { INIT_LIST_HEAD(&nst->st_net_debug_item); nst->st_task = task; @@ -153,61 +153,31 @@ static void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, nst->st_node = node; } -static void o2net_set_nst_sock_time(struct o2net_send_tracking *nst) +void o2net_set_nst_sock_time(struct o2net_send_tracking *nst) { do_gettimeofday(&nst->st_sock_time); } -static void o2net_set_nst_send_time(struct o2net_send_tracking *nst) +void o2net_set_nst_send_time(struct o2net_send_tracking *nst) { do_gettimeofday(&nst->st_send_time); } -static void o2net_set_nst_status_time(struct o2net_send_tracking *nst) +void o2net_set_nst_status_time(struct o2net_send_tracking *nst) { do_gettimeofday(&nst->st_status_time); } -static void o2net_set_nst_sock_container(struct o2net_send_tracking *nst, +void o2net_set_nst_sock_container(struct o2net_send_tracking *nst, struct o2net_sock_container *sc) { nst->st_sc = sc; } -static void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, u32 msg_id) +void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, u32 msg_id) { nst->st_id = msg_id; } - -#else /* CONFIG_DEBUG_FS */ - -static inline void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, - u32 msgkey, struct task_struct *task, u8 node) -{ -} - -static inline void o2net_set_nst_sock_time(struct o2net_send_tracking *nst) -{ -} - -static inline void o2net_set_nst_send_time(struct o2net_send_tracking *nst) -{ -} - -static inline void o2net_set_nst_status_time(struct o2net_send_tracking *nst) -{ -} - -static inline void o2net_set_nst_sock_container(struct o2net_send_tracking *nst, - struct o2net_sock_container *sc) -{ -} - -static inline void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, - u32 msg_id) -{ -} - #endif /* CONFIG_DEBUG_FS */ static inline int o2net_reconnect_delay(void) diff --git a/trunk/fs/ocfs2/cluster/tcp_internal.h b/trunk/fs/ocfs2/cluster/tcp_internal.h index 8d58cfe410b1..18307ff81b77 100644 --- a/trunk/fs/ocfs2/cluster/tcp_internal.h +++ b/trunk/fs/ocfs2/cluster/tcp_internal.h @@ -224,10 +224,42 @@ struct o2net_send_tracking { struct timeval st_send_time; struct timeval st_status_time; }; + +void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, + u32 msgkey, struct task_struct *task, u8 node); +void o2net_set_nst_sock_time(struct o2net_send_tracking *nst); +void o2net_set_nst_send_time(struct o2net_send_tracking *nst); +void o2net_set_nst_status_time(struct o2net_send_tracking *nst); +void o2net_set_nst_sock_container(struct o2net_send_tracking *nst, + struct o2net_sock_container *sc); +void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, u32 msg_id); + #else struct o2net_send_tracking { u32 dummy; }; + +static inline void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, + u32 msgkey, struct task_struct *task, u8 node) +{ +} +static inline void o2net_set_nst_sock_time(struct o2net_send_tracking *nst) +{ +} +static inline void o2net_set_nst_send_time(struct o2net_send_tracking *nst) +{ +} +static inline void o2net_set_nst_status_time(struct o2net_send_tracking *nst) +{ +} +static inline void o2net_set_nst_sock_container(struct o2net_send_tracking *nst, + struct o2net_sock_container *sc) +{ +} +static inline void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, + u32 msg_id) +{ +} #endif /* CONFIG_DEBUG_FS */ #endif /* O2CLUSTER_TCP_INTERNAL_H */ diff --git a/trunk/fs/ocfs2/dir.c b/trunk/fs/ocfs2/dir.c index 9cce563fd627..8a1875848080 100644 --- a/trunk/fs/ocfs2/dir.c +++ b/trunk/fs/ocfs2/dir.c @@ -1300,6 +1300,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, di->i_size = cpu_to_le64(sb->s_blocksize); di->i_ctime = di->i_mtime = cpu_to_le64(dir->i_ctime.tv_sec); di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(dir->i_ctime.tv_nsec); + dir->i_blocks = ocfs2_inode_sector_count(dir); /* * This should never fail as our extent list is empty and all @@ -1309,15 +1310,9 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, NULL); if (ret) { mlog_errno(ret); - goto out_commit; + goto out; } - /* - * Set i_blocks after the extent insert for the most up to - * date ip_clusters value. - */ - dir->i_blocks = ocfs2_inode_sector_count(dir); - ret = ocfs2_journal_dirty(handle, di_bh); if (ret) { mlog_errno(ret); @@ -1341,7 +1336,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, len, 0, NULL); if (ret) { mlog_errno(ret); - goto out_commit; + goto out; } } diff --git a/trunk/fs/ocfs2/journal.c b/trunk/fs/ocfs2/journal.c index c47bc2a809c2..7a37240f7a31 100644 --- a/trunk/fs/ocfs2/journal.c +++ b/trunk/fs/ocfs2/journal.c @@ -1418,13 +1418,13 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb) { unsigned int node_num; int status, i; - u32 gen; struct buffer_head *bh = NULL; struct ocfs2_dinode *di; /* This is called with the super block cluster lock, so we * know that the slot map can't change underneath us. */ + spin_lock(&osb->osb_lock); for (i = 0; i < osb->max_slots; i++) { /* Read journal inode to get the recovery generation */ status = ocfs2_read_journal_inode(osb, i, &bh, NULL); @@ -1433,31 +1433,23 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb) goto bail; } di = (struct ocfs2_dinode *)bh->b_data; - gen = ocfs2_get_recovery_generation(di); + osb->slot_recovery_generations[i] = + ocfs2_get_recovery_generation(di); brelse(bh); bh = NULL; - spin_lock(&osb->osb_lock); - osb->slot_recovery_generations[i] = gen; - mlog(0, "Slot %u recovery generation is %u\n", i, osb->slot_recovery_generations[i]); - if (i == osb->slot_num) { - spin_unlock(&osb->osb_lock); + if (i == osb->slot_num) continue; - } status = ocfs2_slot_to_node_num_locked(osb, i, &node_num); - if (status == -ENOENT) { - spin_unlock(&osb->osb_lock); + if (status == -ENOENT) continue; - } - if (__ocfs2_recovery_map_test(osb, node_num)) { - spin_unlock(&osb->osb_lock); + if (__ocfs2_recovery_map_test(osb, node_num)) continue; - } spin_unlock(&osb->osb_lock); /* Ok, we have a slot occupied by another node which @@ -1473,7 +1465,10 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb) mlog_errno(status); goto bail; } + + spin_lock(&osb->osb_lock); } + spin_unlock(&osb->osb_lock); status = 0; bail: diff --git a/trunk/fs/ocfs2/stackglue.c b/trunk/fs/ocfs2/stackglue.c index 07f348b8d721..10e149ae5e3a 100644 --- a/trunk/fs/ocfs2/stackglue.c +++ b/trunk/fs/ocfs2/stackglue.c @@ -97,14 +97,13 @@ static int ocfs2_stack_driver_request(const char *stack_name, goto out; } + /* Ok, the stack is pinned */ + p->sp_count++; active_stack = p; + rc = 0; out: - /* If we found it, pin it */ - if (!rc) - active_stack->sp_count++; - spin_unlock(&ocfs2_stack_lock); return rc; } diff --git a/trunk/fs/proc/generic.c b/trunk/fs/proc/generic.c index bca0f81eb687..4fb81e9c94e3 100644 --- a/trunk/fs/proc/generic.c +++ b/trunk/fs/proc/generic.c @@ -330,7 +330,6 @@ static unsigned int get_inode_number(void) spin_lock(&proc_inum_lock); ida_remove(&proc_inum_ida, i); spin_unlock(&proc_inum_lock); - return 0; } return PROC_DYNAMIC_FIRST + i; } diff --git a/trunk/fs/readdir.c b/trunk/fs/readdir.c index 93a7559bbfd8..4e026e5407fb 100644 --- a/trunk/fs/readdir.c +++ b/trunk/fs/readdir.c @@ -80,10 +80,8 @@ static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset if (buf->result) return -EINVAL; d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { - buf->result = -EOVERFLOW; + if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) return -EOVERFLOW; - } buf->result++; dirent = buf->dirent; if (!access_ok(VERIFY_WRITE, dirent, @@ -157,10 +155,8 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset, if (reclen > buf->count) return -EINVAL; d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { - buf->error = -EOVERFLOW; + if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) return -EOVERFLOW; - } dirent = buf->previous; if (dirent) { if (__put_user(offset, &dirent->d_off)) diff --git a/trunk/fs/seq_file.c b/trunk/fs/seq_file.c index bd20f7f5a933..5d54205e486b 100644 --- a/trunk/fs/seq_file.c +++ b/trunk/fs/seq_file.c @@ -108,9 +108,9 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) goto Done; } /* we need at least one record in buffer */ - pos = m->index; - p = m->op->start(m, &pos); while (1) { + pos = m->index; + p = m->op->start(m, &pos); err = PTR_ERR(p); if (!p || IS_ERR(p)) break; @@ -119,11 +119,6 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) break; if (unlikely(err)) m->count = 0; - if (unlikely(!m->count)) { - p = m->op->next(m, p, &pos); - m->index = pos; - continue; - } if (m->count < m->size) goto Fill; m->op->stop(m, p); @@ -133,8 +128,6 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) goto Enomem; m->count = 0; m->version = 0; - pos = m->index; - p = m->op->start(m, &pos); } m->op->stop(m, p); m->count = 0; diff --git a/trunk/fs/xfs/linux-2.6/xfs_file.c b/trunk/fs/xfs/linux-2.6/xfs_file.c index 5311c1acdd40..5f60363b9343 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_file.c +++ b/trunk/fs/xfs/linux-2.6/xfs_file.c @@ -475,7 +475,6 @@ const struct file_operations xfs_invis_file_operations = { const struct file_operations xfs_dir_file_operations = { .read = generic_read_dir, .readdir = xfs_file_readdir, - .llseek = generic_file_llseek, .unlocked_ioctl = xfs_file_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = xfs_file_compat_ioctl, diff --git a/trunk/fs/xfs/linux-2.6/xfs_iops.c b/trunk/fs/xfs/linux-2.6/xfs_iops.c index 095d271f3434..91bcd979242c 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_iops.c +++ b/trunk/fs/xfs/linux-2.6/xfs_iops.c @@ -355,7 +355,7 @@ xfs_vn_ci_lookup( /* else case-insensitive match... */ dname.name = ci_name.name; dname.len = ci_name.len; - dentry = d_add_ci(dentry, VFS_I(ip), &dname); + dentry = d_add_ci(VFS_I(ip), dentry, &dname); kmem_free(ci_name.name); return dentry; } diff --git a/trunk/include/linux/blkdev.h b/trunk/include/linux/blkdev.h index 44710d7e7bff..e61f22be4d0e 100644 --- a/trunk/include/linux/blkdev.h +++ b/trunk/include/linux/blkdev.h @@ -280,15 +280,6 @@ struct blk_queue_tag { atomic_t refcnt; /* map can be shared */ }; -#define BLK_SCSI_MAX_CMDS (256) -#define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8)) - -struct blk_cmd_filter { - unsigned long read_ok[BLK_SCSI_CMD_PER_LONG]; - unsigned long write_ok[BLK_SCSI_CMD_PER_LONG]; - struct kobject kobj; -}; - struct request_queue { /* @@ -407,7 +398,6 @@ struct request_queue #if defined(CONFIG_BLK_DEV_BSG) struct bsg_class_device bsg_dev; #endif - struct blk_cmd_filter cmd_filter; }; #define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */ @@ -817,6 +807,8 @@ extern void blk_put_queue(struct request_queue *); /* * tag stuff */ +#define blk_queue_tag_depth(q) ((q)->queue_tags->busy) +#define blk_queue_tag_queue(q) ((q)->queue_tags->busy < (q)->queue_tags->max_depth) #define blk_rq_tagged(rq) ((rq)->cmd_flags & REQ_QUEUED) extern int blk_queue_start_tag(struct request_queue *, struct request *); extern struct request *blk_queue_find_tag(struct request_queue *, int); @@ -841,11 +833,11 @@ extern int blkdev_issue_flush(struct block_device *, sector_t *); /* * command filter functions */ -extern int blk_verify_command(struct blk_cmd_filter *filter, - unsigned char *cmd, int has_write_perm); +extern int blk_verify_command(struct file *file, unsigned char *cmd); +extern int blk_cmd_filter_verify_command(struct blk_scsi_cmd_filter *filter, + unsigned char *cmd, mode_t *f_mode); extern int blk_register_filter(struct gendisk *disk); extern void blk_unregister_filter(struct gendisk *disk); -extern void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter); #define MAX_PHYS_SEGMENTS 128 #define MAX_HW_SEGMENTS 128 diff --git a/trunk/include/linux/dcache.h b/trunk/include/linux/dcache.h index efba1de629ac..07aa198f19ed 100644 --- a/trunk/include/linux/dcache.h +++ b/trunk/include/linux/dcache.h @@ -230,7 +230,7 @@ extern void d_delete(struct dentry *); extern struct dentry * d_alloc(struct dentry *, const struct qstr *); extern struct dentry * d_alloc_anon(struct inode *); extern struct dentry * d_splice_alias(struct inode *, struct dentry *); -extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *); +extern struct dentry * d_add_ci(struct inode *, struct dentry *, struct qstr *); extern void shrink_dcache_sb(struct super_block *); extern void shrink_dcache_parent(struct dentry *); extern void shrink_dcache_for_umount(struct super_block *); diff --git a/trunk/include/linux/genhd.h b/trunk/include/linux/genhd.h index be4f5e5bfe06..118216f1bd3c 100644 --- a/trunk/include/linux/genhd.h +++ b/trunk/include/linux/genhd.h @@ -110,6 +110,15 @@ struct hd_struct { #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 #define GENHD_FL_FAIL 64 +#define BLK_SCSI_MAX_CMDS (256) +#define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8)) + +struct blk_scsi_cmd_filter { + unsigned long read_ok[BLK_SCSI_CMD_PER_LONG]; + unsigned long write_ok[BLK_SCSI_CMD_PER_LONG]; + struct kobject kobj; +}; + struct gendisk { int major; /* major number of driver */ int first_minor; @@ -119,6 +128,7 @@ struct gendisk { struct hd_struct **part; /* [indexed by minor] */ struct block_device_operations *fops; struct request_queue *queue; + struct blk_scsi_cmd_filter cmd_filter; void *private_data; sector_t capacity; diff --git a/trunk/kernel/power/main.c b/trunk/kernel/power/main.c index 540b16b68565..0b7476f5d2a6 100644 --- a/trunk/kernel/power/main.c +++ b/trunk/kernel/power/main.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "power.h" @@ -311,7 +310,7 @@ static int suspend_enter(suspend_state_t state) */ int suspend_devices_and_enter(suspend_state_t state) { - int error, ftrace_save; + int error; if (!suspend_ops) return -ENOSYS; @@ -322,7 +321,6 @@ int suspend_devices_and_enter(suspend_state_t state) goto Close; } suspend_console(); - ftrace_save = __ftrace_enabled_save(); suspend_test_start(); error = device_suspend(PMSG_SUSPEND); if (error) { @@ -354,7 +352,6 @@ int suspend_devices_and_enter(suspend_state_t state) suspend_test_start(); device_resume(PMSG_RESUME); suspend_test_finish("resume devices"); - __ftrace_enabled_restore(ftrace_save); resume_console(); Close: if (suspend_ops->end) diff --git a/trunk/mm/slub.c b/trunk/mm/slub.c index fb486d5540f8..4f5b96149458 100644 --- a/trunk/mm/slub.c +++ b/trunk/mm/slub.c @@ -2312,7 +2312,7 @@ static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags, s->refcount = 1; #ifdef CONFIG_NUMA - s->remote_node_defrag_ratio = 1000; + s->remote_node_defrag_ratio = 100; #endif if (!init_kmem_cache_nodes(s, gfpflags & ~SLUB_DMA)) goto error; @@ -4058,7 +4058,7 @@ static ssize_t remote_node_defrag_ratio_store(struct kmem_cache *s, if (err) return err; - if (ratio <= 100) + if (ratio < 100) s->remote_node_defrag_ratio = ratio * 10; return length;