summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@kernel.bkbits.net>2003-06-04 09:24:39 -0700
committerDavid S. Miller <davem@kernel.bkbits.net>2003-06-04 09:24:39 -0700
commit84d58710feb87cde414ced92e55be2dff5660a4a (patch)
tree8c989ba054450e7ff199fe1a9ebcdc4ecea0b5e4
parentcbe7defa859ae2077f2b577a5540853b24868da8 (diff)
parent8a36b98fd0d80234db3675aca4d56e034b01d175 (diff)
Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5
into kernel.bkbits.net:/home/davem/net-2.5
-rw-r--r--Documentation/vm/hugetlbpage.txt13
-rw-r--r--arch/arm/kernel/process.c2
-rw-r--r--drivers/block/deadline-iosched.c11
-rw-r--r--drivers/md/md.c6
-rw-r--r--drivers/md/raid0.c19
-rw-r--r--drivers/md/raid1.c68
-rw-r--r--drivers/md/raid5.c2
-rw-r--r--drivers/media/radio/radio-cadet.c6
-rw-r--r--drivers/media/video/bw-qcam.c2
-rw-r--r--drivers/media/video/zr36120.c12
-rw-r--r--drivers/pnp/pnpbios/proc.c33
-rw-r--r--fs/aio.c20
-rw-r--r--fs/buffer.c3
-rw-r--r--fs/devfs/base.c7
-rw-r--r--fs/hugetlbfs/inode.c85
-rw-r--r--fs/jbd/journal.c2
-rw-r--r--fs/reiserfs/file.c2
-rw-r--r--fs/reiserfs/inode.c2
-rw-r--r--fs/reiserfs/journal.c150
-rw-r--r--fs/reiserfs/prints.c7
-rw-r--r--fs/reiserfs/super.c120
-rw-r--r--include/asm-alpha/thread_info.h2
-rw-r--r--include/asm-arm/thread_info.h2
-rw-r--r--include/asm-h8300/thread_info.h2
-rw-r--r--include/asm-i386/thread_info.h2
-rw-r--r--include/asm-m68k/thread_info.h4
-rw-r--r--include/asm-m68knommu/thread_info.h2
-rw-r--r--include/asm-parisc/thread_info.h2
-rw-r--r--include/asm-ppc/thread_info.h2
-rw-r--r--include/asm-ppc64/thread_info.h2
-rw-r--r--include/asm-s390/thread_info.h2
-rw-r--r--include/asm-sparc/thread_info.h2
-rw-r--r--include/asm-sparc64/thread_info.h4
-rw-r--r--include/asm-um/thread_info.h2
-rw-r--r--include/asm-v850/thread_info.h2
-rw-r--r--include/asm-x86_64/thread_info.h2
-rw-r--r--include/linux/aio.h6
-rw-r--r--include/linux/hugetlb.h6
-rw-r--r--include/linux/reiserfs_fs.h28
-rw-r--r--include/linux/reiserfs_fs_sb.h2
-rw-r--r--kernel/fork.c30
-rw-r--r--kernel/timer.c81
-rw-r--r--mm/filemap.c32
-rw-r--r--scripts/kconfig/conf.c8
-rw-r--r--scripts/kconfig/confdata.c3
-rw-r--r--scripts/kconfig/menu.c23
-rw-r--r--scripts/kconfig/symbol.c3
-rw-r--r--sound/oss/cmpci.c21
48 files changed, 484 insertions, 365 deletions
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index dfd6b007a8d4..f39e2bb310cb 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -67,15 +67,22 @@ If the user applications are going to request hugepages using mmap system
call, then it is required that system administrator mount a file system of
type hugetlbfs:
- mount none /mnt/huge -t hugetlbfs
+ mount none /mnt/huge -t hugetlbfs <uid=value> <gid=value> <mode=value>
This command mounts a (pseudo) filesystem of type hugetlbfs on the directory
-/mnt/huge. Any files created on /mnt/huge uses hugepages. An example is
-given at the end of this document.
+/mnt/huge. Any files created on /mnt/huge uses hugepages. The uid and gid
+options sets the owner and group of the root of the file system. By default
+the uid and gid of the current process are taken. The mode option sets the
+mode of root of file system to value & 0777. This value is given in octal.
+By default the value 0755 is picked. An example is given at the end of this
+document.
read and write system calls are not supported on files that reside on hugetlb
file systems.
+A regular chown, chgrp and chmod commands (with right permissions) could be
+used to change the file attributes on hugetlbfs.
+
Also, it is important to note that no such mount command is required if the
applications are going to use only shmat/shmget system calls. It is possible
for same or different applications to use any combination of mmaps and shm*
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index bf27843cf3dd..8cded6988447 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -239,7 +239,7 @@ static unsigned int nr_thread_info;
#define ll_alloc_task_struct() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
#define ll_free_task_struct(p) free_pages((unsigned long)(p),1)
-struct thread_info *alloc_thread_info(void)
+struct thread_info *alloc_thread_info(struct task_struct *task)
{
struct thread_info *thread = NULL;
diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c
index a36bc1161f59..adc8db4937c5 100644
--- a/drivers/block/deadline-iosched.c
+++ b/drivers/block/deadline-iosched.c
@@ -121,6 +121,15 @@ static inline void deadline_del_drq_hash(struct deadline_rq *drq)
__deadline_del_drq_hash(drq);
}
+static void
+deadline_remove_merge_hints(request_queue_t *q, struct deadline_rq *drq)
+{
+ deadline_del_drq_hash(drq);
+
+ if (q->last_merge == &drq->request->queuelist)
+ q->last_merge = NULL;
+}
+
static inline void
deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq)
{
@@ -310,7 +319,7 @@ static void deadline_remove_request(request_queue_t *q, struct request *rq)
struct deadline_data *dd = q->elevator.elevator_data;
list_del_init(&drq->fifo);
- deadline_del_drq_hash(drq);
+ deadline_remove_merge_hints(q, drq);
deadline_del_drq_rb(dd, drq);
}
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 34181a3be045..7106b0fa36a9 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2860,7 +2860,7 @@ static void *md_seq_start(struct seq_file *seq, loff_t *pos)
loff_t l = *pos;
mddev_t *mddev;
- if (l > 0x10000)
+ if (l >= 0x10000)
return NULL;
if (!l--)
/* header */
@@ -2875,7 +2875,9 @@ static void *md_seq_start(struct seq_file *seq, loff_t *pos)
return mddev;
}
spin_unlock(&all_mddevs_lock);
- return (void*)2;/* tail */
+ if (!l--)
+ return (void*)2;/* tail */
+ return NULL;
}
static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 9a96d8bd0fa2..195b87a5194b 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -85,10 +85,8 @@ static int create_strip_zones (mddev_t *mddev)
conf->devlist = kmalloc(sizeof(mdk_rdev_t*)*
conf->nr_strip_zones*mddev->raid_disks,
GFP_KERNEL);
- if (!conf->devlist) {
- kfree(conf);
+ if (!conf->devlist)
return 1;
- }
memset(conf->strip_zone, 0,sizeof(struct strip_zone)*
conf->nr_strip_zones);
@@ -193,8 +191,6 @@ static int create_strip_zones (mddev_t *mddev)
printk("raid0: done.\n");
return 0;
abort:
- kfree(conf->devlist);
- kfree(conf->strip_zone);
return 1;
}
@@ -235,6 +231,8 @@ static int raid0_run (mddev_t *mddev)
goto out;
mddev->private = (void *)conf;
+ conf->strip_zone = NULL;
+ conf->devlist = NULL;
if (create_strip_zones (mddev))
goto out_free_conf;
@@ -273,7 +271,7 @@ static int raid0_run (mddev_t *mddev)
nb_zone*sizeof(struct strip_zone*));
conf->hash_table = kmalloc (sizeof (struct strip_zone *)*nb_zone, GFP_KERNEL);
if (!conf->hash_table)
- goto out_free_zone_conf;
+ goto out_free_conf;
size = conf->strip_zone[cur].size;
for (i=0; i< nb_zone; i++) {
@@ -296,12 +294,11 @@ static int raid0_run (mddev_t *mddev)
blk_queue_merge_bvec(&mddev->queue, raid0_mergeable_bvec);
return 0;
-out_free_zone_conf:
- kfree(conf->strip_zone);
- conf->strip_zone = NULL;
-
out_free_conf:
- kfree (conf->devlist);
+ if (conf->strip_zone)
+ kfree(conf->strip_zone);
+ if (conf->devlist)
+ kfree (conf->devlist);
kfree(conf);
mddev->private = NULL;
out:
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 79cd5e4ca138..1c1ef07c83b2 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -462,7 +462,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
mirror_info_t *mirror;
r1bio_t *r1_bio;
struct bio *read_bio;
- int i, sum_bios = 0, disks = conf->raid_disks;
+ int i, disks = conf->raid_disks;
/*
* Register the new request and wait if the reconstruction
@@ -525,6 +525,9 @@ static int make_request(request_queue_t *q, struct bio * bio)
r1_bio->write_bios[i] = NULL;
}
spin_unlock_irq(&conf->device_lock);
+
+ atomic_set(&r1_bio->remaining, 1);
+ md_write_start(mddev);
for (i = 0; i < disks; i++) {
struct bio *mbio;
if (!r1_bio->write_bios[i])
@@ -539,37 +542,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
mbio->bi_rw = r1_bio->cmd;
mbio->bi_private = r1_bio;
- sum_bios++;
- }
- if (!sum_bios) {
- /*
- * If all mirrors are non-operational
- * then return an IO error:
- */
- md_write_end(mddev);
- raid_end_bio_io(r1_bio);
- return 0;
- }
- atomic_set(&r1_bio->remaining, sum_bios+1);
-
- /*
- * We have to be a bit careful about the semaphore above, thats
- * why we start the requests separately. Since generic_make_request()
- * can sleep, this is the safer solution. Imagine, raid1_end_request
- * decreasing the semaphore before we could have set it up ...
- * We could play tricks with the semaphore (presetting it and
- * correcting at the end if sum_bios is not 'n' but we have to
- * do raid1_end_request by hand if all requests finish until we had a
- * chance to set up the semaphore correctly ... lots of races).
- */
-
- md_write_start(mddev);
- for (i=disks; i--; ) {
- struct bio *mbio;
- mbio = r1_bio->write_bios[i];
- if (!mbio)
- continue;
-
+ atomic_inc(&r1_bio->remaining);
generic_make_request(mbio);
}
@@ -802,7 +775,7 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
{
conf_t *conf = mddev_to_conf(mddev);
- int i, sum_bios = 0;
+ int i;
int disks = conf->raid_disks;
struct bio *bio, *mbio;
@@ -849,7 +822,8 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
}
spin_unlock_irq(&conf->device_lock);
- for (i = 0; i < disks ; i++) {
+ atomic_set(&r1_bio->remaining, 1);
+ for (i = disks; i-- ; ) {
if (!r1_bio->write_bios[i])
continue;
mbio = bio_clone(bio, GFP_NOIO);
@@ -860,32 +834,14 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
mbio->bi_rw = WRITE;
mbio->bi_private = r1_bio;
- sum_bios++;
+ atomic_inc(&r1_bio->remaining);
+ md_sync_acct(conf->mirrors[i].rdev, mbio->bi_size >> 9);
+ generic_make_request(mbio);
}
- if (i != disks)
- BUG();
- atomic_set(&r1_bio->remaining, sum_bios);
-
- if (!sum_bios) {
- /*
- * Nowhere to write this to... I guess we
- * must be done
- */
- printk(KERN_ALERT "raid1: sync aborting as there is nowhere"
- " to write sector %llu\n",
- (unsigned long long)r1_bio->sector);
+ if (atomic_dec_and_test(&r1_bio->remaining)) {
md_done_sync(mddev, r1_bio->master_bio->bi_size >> 9, 0);
put_buf(r1_bio);
- return;
- }
- for (i = 0; i < disks ; i++) {
- mbio = r1_bio->write_bios[i];
- if (!mbio)
- continue;
-
- md_sync_acct(conf->mirrors[i].rdev, mbio->bi_size >> 9);
- generic_make_request(mbio);
}
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 172d2cd5e211..96b97ca34814 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -940,7 +940,7 @@ static void handle_stripe(struct stripe_head *sh)
/* and fail all 'written' */
bi = sh->dev[i].written;
sh->dev[i].written = NULL;
- while (bi && bi->bi_sector < dev->sector + STRIPE_SECTORS) {
+ while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
struct bio *bi2 = bi->bi_next;
clear_bit(BIO_UPTODATE, &bi->bi_flags);
if (--bi->bi_phys_segments == 0) {
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 68f21790076f..fd3f10015c92 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -389,9 +389,6 @@ static int cadet_do_ioctl(struct inode *inode, struct file *file,
v->flags|=VIDEO_TUNER_STEREO_ON;
}
v->flags|=cadet_getrds();
- if(copy_to_user(arg,&v, sizeof(v))) {
- return -EFAULT;
- }
break;
case 1:
strcpy(v->name,"AM");
@@ -402,9 +399,6 @@ static int cadet_do_ioctl(struct inode *inode, struct file *file,
v->mode=0;
v->mode|=VIDEO_MODE_AUTO;
v->signal=sigstrength;
- if(copy_to_user(arg,&v, sizeof(v))) {
- return -EFAULT;
- }
break;
}
return 0;
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index 66525c9cd90b..a2841f7451bb 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -723,8 +723,6 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
/* Good question.. its composite or SVHS so.. */
v->type = VIDEO_TYPE_CAMERA;
strcpy(v->name, "Camera");
- if(copy_to_user(arg, &v, sizeof(v)))
- return -EFAULT;
return 0;
}
case VIDIOCSCHAN:
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
index 99363f9065be..4bc486e51d7d 100644
--- a/drivers/media/video/zr36120.c
+++ b/drivers/media/video/zr36120.c
@@ -1693,12 +1693,12 @@ long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonb
for (x=0; optr+1<eptr && x<-done->w; x++)
{
unsigned char a = iptr[x*2];
- *optr++ = a;
- *optr++ = a;
+ __put_user(a, optr++);
+ __put_user(a, optr++);
}
/* and clear the rest of the line */
for (x*=2; optr<eptr && x<done->bpl; x++)
- *optr++ = 0;
+ __put_user(0, optr++);
/* next line */
iptr += done->bpl;
}
@@ -1715,10 +1715,10 @@ long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonb
{
/* copy to doubled data to userland */
for (x=0; optr<eptr && x<-done->w; x++)
- *optr++ = iptr[x*2];
+ __put_user(iptr[x*2], optr++);
/* and clear the rest of the line */
for (;optr<eptr && x<done->bpl; x++)
- *optr++ = 0;
+ __put_user(0, optr++);
/* next line */
iptr += done->bpl;
}
@@ -1727,7 +1727,7 @@ long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonb
/* API compliance:
* place the framenumber (half fieldnr) in the last long
*/
- ((ulong*)eptr)[-1] = done->fieldnr/2;
+ __put_user(done->fieldnr/2, ((ulong*)eptr)[-1]);
}
/* keep the engine running */
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
index 7b673d4e9e0b..a42fd2081012 100644
--- a/drivers/pnp/pnpbios/proc.c
+++ b/drivers/pnp/pnpbios/proc.c
@@ -29,6 +29,8 @@
#include <linux/pnpbios.h>
#include <linux/init.h>
+#include <asm/uaccess.h>
+
static struct proc_dir_entry *proc_pnp = NULL;
static struct proc_dir_entry *proc_pnp_boot = NULL;
@@ -178,18 +180,31 @@ static int proc_write_node(struct file *file, const char *buf,
struct pnp_bios_node *node;
int boot = (long)data >> 8;
u8 nodenum = (long)data;
+ int ret = count;
node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
- if (!node) return -ENOMEM;
- if ( pnp_bios_get_dev_node(&nodenum, boot, node) )
- return -EIO;
- if (count != node->size - sizeof(struct pnp_bios_node))
- return -EINVAL;
- memcpy(node->data, buf, count);
- if (pnp_bios_set_dev_node(node->handle, boot, node) != 0)
- return -EINVAL;
+ if (!node)
+ return -ENOMEM;
+ if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
+ ret = -EIO;
+ goto out;
+ }
+ if (count != node->size - sizeof(struct pnp_bios_node)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ if (copy_from_user(node->data, buf, count)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ if (pnp_bios_set_dev_node(node->handle, boot, node) != 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = count;
+out:
kfree(node);
- return count;
+ return ret;
}
int pnpbios_interface_attach_device(struct pnp_bios_node * node)
diff --git a/fs/aio.c b/fs/aio.c
index c5627b387b2e..ccbdeede79ff 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -252,7 +252,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
return ctx;
out_cleanup:
- atomic_sub(ctx->max_reqs, &aio_nr); /* undone by __put_ioctx */
+ atomic_sub(ctx->max_reqs, &aio_nr);
ctx->max_reqs = 0; /* prevent __put_ioctx from sub'ing aio_nr */
__put_ioctx(ctx);
return ERR_PTR(-EAGAIN);
@@ -405,9 +405,6 @@ static struct kiocb *__aio_get_req(struct kioctx *ctx)
list_add(&req->ki_list, &ctx->active_reqs);
get_ioctx(ctx);
ctx->reqs_active++;
- req->ki_user_obj = NULL;
- req->ki_ctx = ctx;
- req->ki_users = 1;
okay = 1;
}
kunmap_atomic(ring, KM_USER0);
@@ -949,7 +946,7 @@ asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t *ctxp)
goto out;
ret = -EINVAL;
- if (unlikely(ctx || !nr_events || (int)nr_events < 0)) {
+ if (unlikely(ctx || (int)nr_events <= 0)) {
pr_debug("EINVAL: io_setup: ctx or nr_events > max\n");
goto out;
}
@@ -984,9 +981,7 @@ asmlinkage long sys_io_destroy(aio_context_t ctx)
return -EINVAL;
}
-int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
- struct iocb *iocb));
-int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
+int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
struct iocb *iocb)
{
struct kiocb *req;
@@ -1098,7 +1093,7 @@ out_put_req:
* fail with -ENOSYS if not implemented.
*/
asmlinkage long sys_io_submit(aio_context_t ctx_id, long nr,
- struct iocb **iocbpp)
+ struct iocb __user **iocbpp)
{
struct kioctx *ctx;
long ret = 0;
@@ -1116,8 +1111,13 @@ asmlinkage long sys_io_submit(aio_context_t ctx_id, long nr,
return -EINVAL;
}
+ /*
+ * AKPM: should this return a partial result if some of the IOs were
+ * successfully submitted?
+ */
for (i=0; i<nr; i++) {
- struct iocb *user_iocb, tmp;
+ struct iocb __user *user_iocb;
+ struct iocb tmp;
if (unlikely(__get_user(user_iocb, iocbpp + i))) {
ret = -EFAULT;
diff --git a/fs/buffer.c b/fs/buffer.c
index abb476e7679e..c64523feade7 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -822,9 +822,6 @@ int __set_page_dirty_buffers(struct page *page)
goto out;
}
- if (!PageUptodate(page))
- buffer_error();
-
spin_lock(&mapping->private_lock);
if (page_has_buffers(page)) {
struct buffer_head *head = page_buffers(page);
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index 5e6374bc8d20..572bb3983f2d 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -1710,6 +1710,13 @@ void devfs_remove(const char *fmt, ...)
if (n < 64 && buf[0]) {
devfs_handle_t de = _devfs_find_entry(NULL, buf, 0);
+ if (!de) {
+ printk(KERN_ERR "%s: %s not found, cannot remove\n",
+ __FUNCTION__, buf);
+ dump_stack();
+ return;
+ }
+
write_lock(&de->parent->u.dir.lock);
_devfs_unregister(de->parent, de);
devfs_put(de);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index a1fe7e32422f..21839ef0ab06 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -48,9 +48,6 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
loff_t len;
int ret;
- if (!capable(CAP_IPC_LOCK))
- return -EPERM;
-
if (vma->vm_start & ~HPAGE_MASK)
return -EINVAL;
@@ -231,6 +228,7 @@ out_truncate:
spin_unlock(&inode_lock);
if (inode->i_data.nrpages)
truncate_hugepages(&inode->i_data, 0);
+
clear_inode(inode);
destroy_inode(inode);
}
@@ -317,7 +315,6 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
struct inode *inode = dentry->d_inode;
int error;
unsigned int ia_valid = attr->ia_valid;
- unsigned long dn_mask;
BUG_ON(!inode);
@@ -335,26 +332,21 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
if (error)
goto out;
attr->ia_valid &= ~ATTR_SIZE;
- error = inode_setattr(inode, attr);
}
- if (error)
- goto out;
- dn_mask = setattr_mask(ia_valid);
- if (dn_mask)
- dnotify_parent(dentry, dn_mask);
+ error = inode_setattr(inode, attr);
out:
return error;
}
-static struct inode *hugetlbfs_get_inode(struct super_block *sb,
- int mode, dev_t dev)
+static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
+ gid_t gid, int mode, dev_t dev)
{
struct inode * inode = new_inode(sb);
if (inode) {
inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
+ inode->i_uid = uid;
+ inode->i_gid = gid;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
inode->i_rdev = NODEV;
@@ -391,7 +383,8 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
static int hugetlbfs_mknod(struct inode *dir,
struct dentry *dentry, int mode, dev_t dev)
{
- struct inode * inode = hugetlbfs_get_inode(dir->i_sb, mode, dev);
+ struct inode * inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid,
+ current->fsgid, mode, dev);
int error = -ENOSPC;
if (inode) {
@@ -421,7 +414,8 @@ static int hugetlbfs_symlink(struct inode *dir,
struct inode *inode;
int error = -ENOSPC;
- inode = hugetlbfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
+ inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid,
+ current->fsgid, S_IFLNK|S_IRWXUGO, 0);
if (inode) {
int l = strlen(symname)+1;
error = page_symlink(inode, symname, l);
@@ -478,16 +472,68 @@ static struct super_operations hugetlbfs_ops = {
};
static int
-hugetlbfs_fill_super(struct super_block * sb, void * data, int silent)
+hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
+{
+ char *opt, *value;
+ int ret = 0;
+
+ if (!options)
+ goto out;
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt)
+ continue;
+
+ value = strchr(opt, '=');
+ if (!value || !*value) {
+ ret = -EINVAL;
+ goto out;
+ } else {
+ *value++ = '\0';
+ }
+
+ if (!strcmp(opt, "uid"))
+ pconfig->uid = simple_strtoul(value, &value, 0);
+ else if (!strcmp(opt, "gid"))
+ pconfig->gid = simple_strtoul(value, &value, 0);
+ else if (!strcmp(opt, "mode"))
+ pconfig->mode = simple_strtoul(value,&value,0) & 0777U;
+ else {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (*value) {
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+ return 0;
+out:
+ pconfig->uid = current->fsuid;
+ pconfig->gid = current->fsgid;
+ pconfig->mode = 0755;
+ return ret;
+}
+
+static int
+hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
{
struct inode * inode;
struct dentry * root;
+ int ret;
+ struct hugetlbfs_config config;
+ ret = hugetlbfs_parse_options(data, &config);
+ if (ret) {
+ printk("hugetlbfs: invalid mount options: %s.\n", data);
+ return ret;
+ }
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = HUGETLBFS_MAGIC;
sb->s_op = &hugetlbfs_ops;
- inode = hugetlbfs_get_inode(sb, S_IFDIR | 0755, 0);
+ inode = hugetlbfs_get_inode(sb, config.uid, config.gid,
+ S_IFDIR | config.mode, 0);
if (!inode)
return -ENOMEM;
@@ -548,7 +594,8 @@ struct file *hugetlb_zero_setup(size_t size)
goto out_dentry;
error = -ENOSPC;
- inode = hugetlbfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
+ inode = hugetlbfs_get_inode(root->d_sb, current->fsuid,
+ current->fsgid, S_IFREG | S_IRWXUGO, 0);
if (!inode)
goto out_file;
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 96e1d0bf490f..2e20ac0082ae 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -916,7 +916,7 @@ int journal_create(journal_t *journal)
__brelse(bh);
}
- fsync_bdev(journal->j_dev);
+ sync_blockdev(journal->j_dev);
jbd_debug(1, "JBD: journal cleared.\n");
/* OK, fill in the initial static fields in the new superblock */
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 9bdf8109430e..c6b25b1d1789 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -736,6 +736,7 @@ int reiserfs_prepare_file_region_for_write(
struct buffer_head *itembuf=NULL; // Buffer head that contains items that we are going to deal with
INITIALIZE_PATH(path); // path to item, that we are going to deal with.
__u32 * item=0; // pointer to item we are going to deal with
+ int item_pos=-1; /* Position in indirect item */
if ( num_pages < 1 ) {
@@ -807,7 +808,6 @@ int reiserfs_prepare_file_region_for_write(
reiserfs_write_lock(inode->i_sb); // We need that for at least search_by_key()
for ( i = 0; i < num_pages ; i++ ) {
- int item_pos=-1; /* Position in indirect item */
head = page_buffers(prepared_pages[i]);
/* For each buffer in the page */
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 31adb5bfe7d8..ea31e9061b45 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2109,11 +2109,13 @@ done:
* someone else could have locked them and sent them down the
* pipe without locking the page
*/
+ bh = head ;
do {
if (!buffer_uptodate(bh)) {
partial = 1;
break;
}
+ bh = bh->b_this_page;
} while(bh != head);
if (!partial)
SetPageUptodate(page);
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 2c6b2708515c..1ea5245db7e1 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -1368,10 +1368,10 @@ int journal_release_error(struct reiserfs_transaction_handle *th, struct super_b
/* compares description block with commit block. returns 1 if they differ, 0 if they are the same */
static int journal_compare_desc_commit(struct super_block *p_s_sb, struct reiserfs_journal_desc *desc,
struct reiserfs_journal_commit *commit) {
- if (le32_to_cpu(commit->j_trans_id) != le32_to_cpu(desc->j_trans_id) ||
- le32_to_cpu(commit->j_len) != le32_to_cpu(desc->j_len) ||
- le32_to_cpu(commit->j_len) > SB_JOURNAL_TRANS_MAX(p_s_sb) ||
- le32_to_cpu(commit->j_len) <= 0
+ if (get_commit_trans_id (commit) != get_desc_trans_id (desc) ||
+ get_commit_trans_len (commit) != get_desc_trans_len (desc) ||
+ get_commit_trans_len (commit) > SB_JOURNAL_TRANS_MAX(p_s_sb) ||
+ get_commit_trans_len (commit) <= 0
) {
return 1 ;
}
@@ -1391,18 +1391,18 @@ static int journal_transaction_is_valid(struct super_block *p_s_sb, struct buffe
return 0 ;
desc = (struct reiserfs_journal_desc *)d_bh->b_data ;
- if (le32_to_cpu(desc->j_len) > 0 && !memcmp(desc->j_magic, JOURNAL_DESC_MAGIC, 8)) {
- if (oldest_invalid_trans_id && *oldest_invalid_trans_id && le32_to_cpu(desc->j_trans_id) > *oldest_invalid_trans_id) {
+ if (get_desc_trans_len(desc) > 0 && !memcmp(get_journal_desc_magic (d_bh), JOURNAL_DESC_MAGIC, 8)) {
+ if (oldest_invalid_trans_id && *oldest_invalid_trans_id && get_desc_trans_id(desc) > *oldest_invalid_trans_id) {
reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-986: transaction "
"is valid returning because trans_id %d is greater than "
- "oldest_invalid %lu\n", le32_to_cpu(desc->j_trans_id),
+ "oldest_invalid %lu\n", get_desc_trans_id(desc),
*oldest_invalid_trans_id);
return 0 ;
}
- if (newest_mount_id && *newest_mount_id > le32_to_cpu(desc->j_mount_id)) {
+ if (newest_mount_id && *newest_mount_id > get_desc_mount_id (desc)) {
reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1087: transaction "
"is valid returning because mount_id %d is less than "
- "newest_mount_id %lu\n", desc->j_mount_id,
+ "newest_mount_id %lu\n", get_desc_mount_id (desc),
*newest_mount_id) ;
return -1 ;
}
@@ -1410,7 +1410,7 @@ static int journal_transaction_is_valid(struct super_block *p_s_sb, struct buffe
/* ok, we have a journal description block, lets see if the transaction was valid */
c_bh = journal_bread(p_s_sb, SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
- ((offset + le32_to_cpu(desc->j_len) + 1) % SB_ONDISK_JOURNAL_SIZE(p_s_sb))) ;
+ ((offset + get_desc_trans_len(desc) + 1) % SB_ONDISK_JOURNAL_SIZE(p_s_sb))) ;
if (!c_bh)
return 0 ;
commit = (struct reiserfs_journal_commit *)c_bh->b_data ;
@@ -1419,21 +1419,21 @@ static int journal_transaction_is_valid(struct super_block *p_s_sb, struct buffe
"journal_transaction_is_valid, commit offset %ld had bad "
"time %d or length %d\n",
c_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb),
- le32_to_cpu(commit->j_trans_id),
- le32_to_cpu(commit->j_len));
+ get_commit_trans_id (commit),
+ get_commit_trans_len(commit));
brelse(c_bh) ;
if (oldest_invalid_trans_id)
- *oldest_invalid_trans_id = le32_to_cpu(desc->j_trans_id) ;
+ *oldest_invalid_trans_id = get_desc_trans_id(desc) ;
reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1004: "
"transaction_is_valid setting oldest invalid trans_id "
- "to %d\n", le32_to_cpu(desc->j_trans_id)) ;
+ "to %d\n", get_desc_trans_id(desc)) ;
return -1;
}
brelse(c_bh) ;
reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1006: found valid "
"transaction start offset %lu, len %d id %d\n",
d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb),
- le32_to_cpu(desc->j_len), le32_to_cpu(desc->j_trans_id)) ;
+ get_desc_trans_len(desc), get_desc_trans_id(desc)) ;
return 1 ;
} else {
return 0 ;
@@ -1463,6 +1463,7 @@ static int journal_read_transaction(struct super_block *p_s_sb, unsigned long cu
struct buffer_head **real_blocks = NULL ;
unsigned long trans_offset ;
int i;
+ int trans_half;
d_bh = journal_bread(p_s_sb, cur_dblock) ;
if (!d_bh)
@@ -1472,24 +1473,24 @@ static int journal_read_transaction(struct super_block *p_s_sb, unsigned long cu
reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1037: "
"journal_read_transaction, offset %lu, len %d mount_id %d\n",
d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb),
- le32_to_cpu(desc->j_len), le32_to_cpu(desc->j_mount_id)) ;
- if (le32_to_cpu(desc->j_trans_id) < oldest_trans_id) {
+ get_desc_trans_len(desc), get_desc_mount_id(desc)) ;
+ if (get_desc_trans_id(desc) < oldest_trans_id) {
reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1039: "
"journal_read_trans skipping because %lu is too old\n",
cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb)) ;
brelse(d_bh) ;
return 1 ;
}
- if (le32_to_cpu(desc->j_mount_id) != newest_mount_id) {
+ if (get_desc_mount_id(desc) != newest_mount_id) {
reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1146: "
"journal_read_trans skipping because %d is != "
- "newest_mount_id %lu\n", le32_to_cpu(desc->j_mount_id),
+ "newest_mount_id %lu\n", get_desc_mount_id(desc),
newest_mount_id) ;
brelse(d_bh) ;
return 1 ;
}
c_bh = journal_bread(p_s_sb, SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
- ((trans_offset + le32_to_cpu(desc->j_len) + 1) %
+ ((trans_offset + get_desc_trans_len(desc) + 1) %
SB_ONDISK_JOURNAL_SIZE(p_s_sb))) ;
if (!c_bh) {
brelse(d_bh) ;
@@ -1500,30 +1501,31 @@ static int journal_read_transaction(struct super_block *p_s_sb, unsigned long cu
reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal_read_transaction, "
"commit offset %ld had bad time %d or length %d\n",
c_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb),
- le32_to_cpu(commit->j_trans_id), le32_to_cpu(commit->j_len));
+ get_commit_trans_id(commit), get_commit_trans_len(commit));
brelse(c_bh) ;
brelse(d_bh) ;
return 1;
}
- trans_id = le32_to_cpu(desc->j_trans_id) ;
+ trans_id = get_desc_trans_id(desc) ;
/* now we know we've got a good transaction, and it was inside the valid time ranges */
- log_blocks = reiserfs_kmalloc(le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), GFP_NOFS, p_s_sb) ;
- real_blocks = reiserfs_kmalloc(le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), GFP_NOFS, p_s_sb) ;
+ log_blocks = reiserfs_kmalloc(get_desc_trans_len(desc) * sizeof(struct buffer_head *), GFP_NOFS, p_s_sb) ;
+ real_blocks = reiserfs_kmalloc(get_desc_trans_len(desc) * sizeof(struct buffer_head *), GFP_NOFS, p_s_sb) ;
if (!log_blocks || !real_blocks) {
brelse(c_bh) ;
brelse(d_bh) ;
- reiserfs_kfree(log_blocks, le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), p_s_sb) ;
- reiserfs_kfree(real_blocks, le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), p_s_sb) ;
+ reiserfs_kfree(log_blocks, get_desc_trans_len(desc) * sizeof(struct buffer_head *), p_s_sb) ;
+ reiserfs_kfree(real_blocks, get_desc_trans_len(desc) * sizeof(struct buffer_head *), p_s_sb) ;
reiserfs_warning("journal-1169: kmalloc failed, unable to mount FS\n") ;
return -1 ;
}
/* get all the buffer heads */
- for(i = 0 ; i < le32_to_cpu(desc->j_len) ; i++) {
+ trans_half = journal_trans_half (p_s_sb->s_blocksize) ;
+ for(i = 0 ; i < get_desc_trans_len(desc) ; i++) {
log_blocks[i] = journal_getblk(p_s_sb, SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + (trans_offset + 1 + i) % SB_ONDISK_JOURNAL_SIZE(p_s_sb));
- if (i < JOURNAL_TRANS_HALF) {
+ if (i < trans_half) {
real_blocks[i] = sb_getblk(p_s_sb, le32_to_cpu(desc->j_realblock[i])) ;
} else {
- real_blocks[i] = sb_getblk(p_s_sb, le32_to_cpu(commit->j_realblock[i - JOURNAL_TRANS_HALF])) ;
+ real_blocks[i] = sb_getblk(p_s_sb, le32_to_cpu(commit->j_realblock[i - trans_half])) ;
}
/* make sure we don't try to replay onto log or reserved area */
if (is_block_in_log_or_reserved_area(p_s_sb, real_blocks[i]->b_blocknr)) {
@@ -1532,23 +1534,23 @@ static int journal_read_transaction(struct super_block *p_s_sb, unsigned long cu
brelse_array(real_blocks, i) ;
brelse(c_bh) ;
brelse(d_bh) ;
- reiserfs_kfree(log_blocks, le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), p_s_sb) ;
- reiserfs_kfree(real_blocks, le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), p_s_sb) ;
+ reiserfs_kfree(log_blocks, get_desc_trans_len(desc) * sizeof(struct buffer_head *), p_s_sb) ;
+ reiserfs_kfree(real_blocks, get_desc_trans_len(desc) * sizeof(struct buffer_head *), p_s_sb) ;
return -1 ;
}
}
/* read in the log blocks, memcpy to the corresponding real block */
- ll_rw_block(READ, le32_to_cpu(desc->j_len), log_blocks) ;
- for (i = 0 ; i < le32_to_cpu(desc->j_len) ; i++) {
+ ll_rw_block(READ, get_desc_trans_len(desc), log_blocks) ;
+ for (i = 0 ; i < get_desc_trans_len(desc) ; i++) {
wait_on_buffer(log_blocks[i]) ;
if (!buffer_uptodate(log_blocks[i])) {
reiserfs_warning("journal-1212: REPLAY FAILURE fsck required! buffer write failed\n") ;
- brelse_array(log_blocks + i, le32_to_cpu(desc->j_len) - i) ;
- brelse_array(real_blocks, le32_to_cpu(desc->j_len)) ;
+ brelse_array(log_blocks + i, get_desc_trans_len(desc) - i) ;
+ brelse_array(real_blocks, get_desc_trans_len(desc)) ;
brelse(c_bh) ;
brelse(d_bh) ;
- reiserfs_kfree(log_blocks, le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), p_s_sb) ;
- reiserfs_kfree(real_blocks, le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), p_s_sb) ;
+ reiserfs_kfree(log_blocks, get_desc_trans_len(desc) * sizeof(struct buffer_head *), p_s_sb) ;
+ reiserfs_kfree(real_blocks, get_desc_trans_len(desc) * sizeof(struct buffer_head *), p_s_sb) ;
return -1 ;
}
memcpy(real_blocks[i]->b_data, log_blocks[i]->b_data, real_blocks[i]->b_size) ;
@@ -1556,24 +1558,24 @@ static int journal_read_transaction(struct super_block *p_s_sb, unsigned long cu
brelse(log_blocks[i]) ;
}
/* flush out the real blocks */
- for (i = 0 ; i < le32_to_cpu(desc->j_len) ; i++) {
+ for (i = 0 ; i < get_desc_trans_len(desc) ; i++) {
set_buffer_dirty(real_blocks[i]) ;
ll_rw_block(WRITE, 1, real_blocks + i) ;
}
- for (i = 0 ; i < le32_to_cpu(desc->j_len) ; i++) {
+ for (i = 0 ; i < get_desc_trans_len(desc) ; i++) {
wait_on_buffer(real_blocks[i]) ;
if (!buffer_uptodate(real_blocks[i])) {
reiserfs_warning("journal-1226: REPLAY FAILURE, fsck required! buffer write failed\n") ;
- brelse_array(real_blocks + i, le32_to_cpu(desc->j_len) - i) ;
+ brelse_array(real_blocks + i, get_desc_trans_len(desc) - i) ;
brelse(c_bh) ;
brelse(d_bh) ;
- reiserfs_kfree(log_blocks, le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), p_s_sb) ;
- reiserfs_kfree(real_blocks, le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), p_s_sb) ;
+ reiserfs_kfree(log_blocks, get_desc_trans_len(desc) * sizeof(struct buffer_head *), p_s_sb) ;
+ reiserfs_kfree(real_blocks, get_desc_trans_len(desc) * sizeof(struct buffer_head *), p_s_sb) ;
return -1 ;
}
brelse(real_blocks[i]) ;
}
- cur_dblock = SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + ((trans_offset + le32_to_cpu(desc->j_len) + 2) % SB_ONDISK_JOURNAL_SIZE(p_s_sb)) ;
+ cur_dblock = SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + ((trans_offset + get_desc_trans_len(desc) + 2) % SB_ONDISK_JOURNAL_SIZE(p_s_sb)) ;
reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1095: setting journal "
"start to offset %ld\n",
cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb)) ;
@@ -1716,28 +1718,28 @@ static int journal_read(struct super_block *p_s_sb) {
if (ret == 1) {
desc = (struct reiserfs_journal_desc *)d_bh->b_data ;
if (oldest_start == 0) { /* init all oldest_ values */
- oldest_trans_id = le32_to_cpu(desc->j_trans_id) ;
+ oldest_trans_id = get_desc_trans_id(desc) ;
oldest_start = d_bh->b_blocknr ;
- newest_mount_id = le32_to_cpu(desc->j_mount_id) ;
+ newest_mount_id = get_desc_mount_id(desc) ;
reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1179: Setting "
"oldest_start to offset %lu, trans_id %lu\n",
oldest_start - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb),
oldest_trans_id) ;
- } else if (oldest_trans_id > le32_to_cpu(desc->j_trans_id)) {
+ } else if (oldest_trans_id > get_desc_trans_id(desc)) {
/* one we just read was older */
- oldest_trans_id = le32_to_cpu(desc->j_trans_id) ;
+ oldest_trans_id = get_desc_trans_id(desc) ;
oldest_start = d_bh->b_blocknr ;
reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1180: Resetting "
"oldest_start to offset %lu, trans_id %lu\n",
oldest_start - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb),
oldest_trans_id) ;
}
- if (newest_mount_id < le32_to_cpu(desc->j_mount_id)) {
- newest_mount_id = le32_to_cpu(desc->j_mount_id) ;
+ if (newest_mount_id < get_desc_mount_id(desc)) {
+ newest_mount_id = get_desc_mount_id(desc) ;
reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1299: Setting "
- "newest_mount_id to %d\n", le32_to_cpu(desc->j_mount_id));
+ "newest_mount_id to %d\n", get_desc_mount_id(desc));
}
- cur_dblock += le32_to_cpu(desc->j_len) + 2 ;
+ cur_dblock += get_desc_trans_len(desc) + 2 ;
} else {
cur_dblock++ ;
}
@@ -1964,13 +1966,6 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo
struct reiserfs_journal *journal;
char b[BDEVNAME_SIZE];
- if (sizeof(struct reiserfs_journal_commit) != 4096 ||
- sizeof(struct reiserfs_journal_desc) != 4096) {
- printk("journal-1249: commit or desc struct not 4096 %Zd %Zd\n", sizeof(struct reiserfs_journal_commit),
- sizeof(struct reiserfs_journal_desc)) ;
- return 1 ;
- }
-
journal = SB_JOURNAL(p_s_sb) = vmalloc(sizeof (struct reiserfs_journal)) ;
if (!journal) {
printk("journal-1256: unable to get memory for journal structure\n") ;
@@ -1989,6 +1984,16 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo
SB_BMAP_NR(p_s_sb) + 1 :
REISERFS_DISK_OFFSET_IN_BYTES / p_s_sb->s_blocksize + 2);
+ /* Sanity check to see is the standard journal fitting withing first bitmap
+ (actual for small blocksizes) */
+ if ( !SB_ONDISK_JOURNAL_DEVICE( p_s_sb ) &&
+ (SB_JOURNAL_1st_RESERVED_BLOCK(p_s_sb) + SB_ONDISK_JOURNAL_SIZE(p_s_sb) > p_s_sb->s_blocksize * 8) ) {
+ printk("journal-1393: journal does not fit for area addressed by first of bitmap blocks. "
+ "It starts at %u and its size is %u. Block size %ld\n",
+ SB_JOURNAL_1st_RESERVED_BLOCK(p_s_sb), SB_ONDISK_JOURNAL_SIZE(p_s_sb), p_s_sb->s_blocksize) ;
+ goto free_and_return;
+ }
+
if( journal_init_dev( p_s_sb, journal, j_dev_name ) != 0 ) {
printk( "sh-462: unable to initialize jornal device\n");
goto free_and_return;
@@ -2105,6 +2110,7 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo
SB_JOURNAL(p_s_sb)->j_cnode_free = SB_JOURNAL(p_s_sb)->j_cnode_free_list ? num_cnodes : 0 ;
SB_JOURNAL(p_s_sb)->j_cnode_used = 0 ;
SB_JOURNAL(p_s_sb)->j_must_wait = 0 ;
+
init_journal_hash(p_s_sb) ;
SB_JOURNAL_LIST(p_s_sb)[0].j_list_bitmap = get_list_bitmap(p_s_sb, SB_JOURNAL_LIST(p_s_sb)) ;
if (!(SB_JOURNAL_LIST(p_s_sb)[0].j_list_bitmap)) {
@@ -2882,6 +2888,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, struct super_b
int commit_now = flags & COMMIT_NOW ;
int wait_on_commit = flags & WAIT ;
struct reiserfs_super_block *rs ;
+ int trans_half ;
if (reiserfs_dont_log(th->t_super)) {
return 0 ;
@@ -2929,16 +2936,16 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, struct super_b
d_bh = journal_getblk(p_s_sb, SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + SB_JOURNAL(p_s_sb)->j_start) ;
set_buffer_uptodate(d_bh) ;
desc = (struct reiserfs_journal_desc *)(d_bh)->b_data ;
- memset(desc, 0, sizeof(struct reiserfs_journal_desc)) ;
- memcpy(desc->j_magic, JOURNAL_DESC_MAGIC, 8) ;
- desc->j_trans_id = cpu_to_le32(SB_JOURNAL(p_s_sb)->j_trans_id) ;
+ memset(d_bh->b_data, 0, d_bh->b_size) ;
+ memcpy(get_journal_desc_magic (d_bh), JOURNAL_DESC_MAGIC, 8) ;
+ set_desc_trans_id(desc, SB_JOURNAL(p_s_sb)->j_trans_id) ;
/* setup commit block. Don't write (keep it clean too) this one until after everyone else is written */
c_bh = journal_getblk(p_s_sb, SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
((SB_JOURNAL(p_s_sb)->j_start + SB_JOURNAL(p_s_sb)->j_len + 1) % SB_ONDISK_JOURNAL_SIZE(p_s_sb))) ;
commit = (struct reiserfs_journal_commit *)c_bh->b_data ;
- memset(commit, 0, sizeof(struct reiserfs_journal_commit)) ;
- commit->j_trans_id = cpu_to_le32(SB_JOURNAL(p_s_sb)->j_trans_id) ;
+ memset(c_bh->b_data, 0, c_bh->b_size) ;
+ set_commit_trans_id(commit, SB_JOURNAL(p_s_sb)->j_trans_id) ;
set_buffer_uptodate(c_bh) ;
/* init this journal list */
@@ -2963,6 +2970,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, struct super_b
/* for each real block, add it to the journal list hash,
** copy into real block index array in the commit or desc block
*/
+ trans_half = journal_trans_half(p_s_sb->s_blocksize) ;
for (i = 0, cn = SB_JOURNAL(p_s_sb)->j_first ; cn ; cn = cn->next, i++) {
if (test_bit(BH_JDirty, &cn->bh->b_state) ) {
jl_cn = get_cnode(p_s_sb) ;
@@ -2990,27 +2998,27 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, struct super_b
jl_cn->bh = cn->bh ;
jl_cn->jlist = SB_JOURNAL_LIST(p_s_sb) + SB_JOURNAL_LIST_INDEX(p_s_sb) ;
insert_journal_hash(SB_JOURNAL(p_s_sb)->j_list_hash_table, jl_cn) ;
- if (i < JOURNAL_TRANS_HALF) {
+ if (i < trans_half) {
desc->j_realblock[i] = cpu_to_le32(cn->bh->b_blocknr) ;
} else {
- commit->j_realblock[i - JOURNAL_TRANS_HALF] = cpu_to_le32(cn->bh->b_blocknr) ;
+ commit->j_realblock[i - trans_half] = cpu_to_le32(cn->bh->b_blocknr) ;
}
} else {
i-- ;
}
}
-
- desc->j_len = cpu_to_le32(SB_JOURNAL(p_s_sb)->j_len) ;
- desc->j_mount_id = cpu_to_le32(SB_JOURNAL(p_s_sb)->j_mount_id) ;
- desc->j_trans_id = cpu_to_le32(SB_JOURNAL(p_s_sb)->j_trans_id) ;
- commit->j_len = cpu_to_le32(SB_JOURNAL(p_s_sb)->j_len) ;
+
+ set_desc_trans_len(desc, SB_JOURNAL(p_s_sb)->j_len) ;
+ set_desc_mount_id(desc, SB_JOURNAL(p_s_sb)->j_mount_id) ;
+ set_desc_trans_id(desc, SB_JOURNAL(p_s_sb)->j_trans_id) ;
+ set_commit_trans_len(commit, SB_JOURNAL(p_s_sb)->j_len);
/* special check in case all buffers in the journal were marked for not logging */
if (SB_JOURNAL(p_s_sb)->j_len == 0) {
brelse(d_bh) ;
brelse(c_bh) ;
unlock_journal(p_s_sb) ;
-printk("journal-2020: do_journal_end: BAD desc->j_len is ZERO\n") ;
+ printk("journal-2020: do_journal_end: BAD desc->j_len is ZERO\n") ;
atomic_set(&(SB_JOURNAL(p_s_sb)->j_jlock), 0) ;
wake_up(&(SB_JOURNAL(p_s_sb)->j_join_wait)) ;
return 0 ;
diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c
index cbdf12c53f50..3a88a16caa7a 100644
--- a/fs/reiserfs/prints.c
+++ b/fs/reiserfs/prints.c
@@ -546,12 +546,13 @@ static int print_desc_block (struct buffer_head * bh)
{
struct reiserfs_journal_desc * desc;
- desc = (struct reiserfs_journal_desc *)(bh->b_data);
- if (memcmp(desc->j_magic, JOURNAL_DESC_MAGIC, 8))
+ if (memcmp(get_journal_desc_magic (bh), JOURNAL_DESC_MAGIC, 8))
return 1;
+ desc = (struct reiserfs_journal_desc *)(bh->b_data);
printk ("Desc block %llu (j_trans_id %d, j_mount_id %d, j_len %d)",
- (unsigned long long)bh->b_blocknr, desc->j_trans_id, desc->j_mount_id, desc->j_len);
+ (unsigned long long)bh->b_blocknr, get_desc_trans_id (desc), get_desc_mount_id (desc),
+ get_desc_trans_len (desc));
return 0;
}
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 4f16c0cd9f1e..8ff47e47a2e1 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -23,9 +23,6 @@
#include <linux/buffer_head.h>
#include <linux/vfs.h>
-#define REISERFS_OLD_BLOCKSIZE 4096
-#define REISERFS_SUPER_MAGIC_STRING_OFFSET_NJ 20
-
static struct file_system_type reiserfs_fs_type;
const char reiserfs_3_5_magic_string[] = REISERFS_SUPER_MAGIC_STRING;
@@ -500,8 +497,11 @@ static struct export_operations reiserfs_export_ops = {
mount options that have values rather than being toggles. */
typedef struct {
char * value;
- int bitmask; /* bit which is to be set in mount_options bitmask when this
- value is found, 0 is no bits are to be set */
+ int setmask; /* bitmask which is to set on mount_options bitmask when this
+ value is found, 0 is no bits are to be changed. */
+ int clrmask; /* bitmask which is to clear on mount_options bitmask when this
+ value is found, 0 is no bits are to be changed. This is
+ applied BEFORE setmask */
} arg_desc_t;
@@ -511,25 +511,30 @@ typedef struct {
char * option_name;
int arg_required; /* 0 if argument is not required, not 0 otherwise */
const arg_desc_t * values; /* list of values accepted by an option */
- int bitmask; /* bit which is to be set in mount_options bitmask when this
- option is selected, 0 is not bits are to be set */
+ int setmask; /* bitmask which is to set on mount_options bitmask when this
+ value is found, 0 is no bits are to be changed. */
+ int clrmask; /* bitmask which is to clear on mount_options bitmask when this
+ value is found, 0 is no bits are to be changed. This is
+ applied BEFORE setmask */
} opt_desc_t;
/* possible values for "-o block-allocator=" and bits which are to be set in
s_mount_opt of reiserfs specific part of in-core super block */
static const arg_desc_t balloc[] = {
- {"noborder", REISERFS_NO_BORDER},
- {"no_unhashed_relocation", REISERFS_NO_UNHASHED_RELOCATION},
- {"hashed_relocation", REISERFS_HASHED_RELOCATION},
- {"test4", REISERFS_TEST4},
- {NULL, -1}
+ {"noborder", 1<<REISERFS_NO_BORDER, 0},
+ {"border", 0, 1<<REISERFS_NO_BORDER},
+ {"no_unhashed_relocation", 1<<REISERFS_NO_UNHASHED_RELOCATION, 0},
+ {"hashed_relocation", 1<<REISERFS_HASHED_RELOCATION, 0},
+ {"test4", 1<<REISERFS_TEST4, 0},
+ {"notest4", 0, 1<<REISERFS_TEST4},
+ {NULL, 0, 0}
};
static const arg_desc_t tails[] = {
- {"on", REISERFS_LARGETAIL},
- {"off", -1},
- {"small", REISERFS_SMALLTAIL},
- {NULL, 0}
+ {"on", 1<<REISERFS_LARGETAIL, 1<<REISERFS_SMALLTAIL},
+ {"off", 0, (1<<REISERFS_LARGETAIL)|(1<<REISERFS_SMALLTAIL)},
+ {"small", 1<<REISERFS_SMALLTAIL, 1<<REISERFS_LARGETAIL},
+ {NULL, 0, 0}
};
int reiserfs_default_io_size = 128 * 1024; /* Default recommended I/O size is 128k.
@@ -571,16 +576,21 @@ static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * o
/* Ugly special case, probably we should redo options parser so that
it can understand several arguments for some options, also so that
it can fill several bitfields with option values. */
- reiserfs_parse_alloc_options( s, p + 6);
- return 0;
+ if ( reiserfs_parse_alloc_options( s, p + 6) ) {
+ return -1;
+ } else {
+ return 0;
+ }
}
/* for every option in the list */
for (opt = opts; opt->option_name; opt ++) {
if (!strncmp (p, opt->option_name, strlen (opt->option_name))) {
- if (bit_flags && opt->bitmask != -1)
- set_bit (opt->bitmask, bit_flags);
+ if (bit_flags) {
+ *bit_flags &= ~opt->clrmask;
+ *bit_flags |= opt->setmask;
+ }
break;
}
}
@@ -620,7 +630,7 @@ static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * o
}
if (!opt->values) {
- /* *opt_arg contains pointer to argument */
+ /* *=NULLopt_arg contains pointer to argument */
*opt_arg = p;
return opt->arg_required;
}
@@ -628,8 +638,10 @@ static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * o
/* values possible for this option are listed in opt->values */
for (arg = opt->values; arg->value; arg ++) {
if (!strcmp (p, arg->value)) {
- if (bit_flags && arg->bitmask != -1 )
- set_bit (arg->bitmask, bit_flags);
+ if (bit_flags) {
+ *bit_flags &= ~arg->clrmask;
+ *bit_flags |= arg->setmask;
+ }
return opt->arg_required;
}
}
@@ -638,7 +650,6 @@ static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * o
return -1;
}
-
/* returns 0 if something is wrong in option string, 1 - otherwise */
static int reiserfs_parse_options (struct super_block * s, char * options, /* string given via mount's -o */
unsigned long * mount_options,
@@ -652,18 +663,18 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
char * arg = NULL;
char * pos;
opt_desc_t opts[] = {
- {"tails", 't', tails, -1},
- {"notail", 0, 0, -1}, /* Compatibility stuff, so that -o notail
-for old setups still work */
- {"conv", 0, 0, REISERFS_CONVERT},
- {"attrs", 0, 0, REISERFS_ATTRS},
- {"nolog", 0, 0, -1},
- {"replayonly", 0, 0, REPLAYONLY},
- {"block-allocator", 'a', balloc, -1},
- {"resize", 'r', 0, -1},
- {"jdev", 'j', 0, -1},
- {"nolargeio", 'w', 0, -1},
- {NULL, 0, 0, -1}
+ {"tails", 't', tails, 0, 0}, /* Compatibility stuff, so that -o notail for old setups still work */
+ {"notail", 0, 0, 0, (1<<REISERFS_LARGETAIL)|(1<<REISERFS_SMALLTAIL)},
+ {"conv", 0, 0, 1<<REISERFS_CONVERT, 0},
+ {"attrs", 0, 0, 1<<REISERFS_ATTRS, 0},
+ {"noattrs", 0, 0, 0, 1<<REISERFS_ATTRS},
+ {"nolog", 0, 0, 0, 0}, /* This is unsupported */
+ {"replayonly", 0, 0, 1<<REPLAYONLY, 0},
+ {"block-allocator", 'a', balloc, 0, 0},
+ {"resize", 'r', 0, 0, 0},
+ {"jdev", 'j', 0, 0, 0},
+ {"nolargeio", 'w', 0, 0, 0},
+ {NULL, 0, 0, 0, 0}
};
*blocks = 0;
@@ -671,9 +682,6 @@ for old setups still work */
/* use default configuration: create tails, journaling on, no
conversion to newest format */
return 1;
- else
- /* Drop defaults to zeroes */
- *mount_options = 0;
for (pos = options; pos; ) {
c = reiserfs_getopt (s, &pos, opts, &arg, mount_options);
@@ -695,11 +703,25 @@ for old setups still work */
}
if ( c == 'w' ) {
- reiserfs_default_io_size = PAGE_SIZE;
+ char *p=0;
+ int val = simple_strtoul (arg, &p, 0);
+
+ if ( *p != '\0') {
+ printk ("reiserfs_parse_options: non-numeric value %s for nolargeio option\n", arg);
+ return 0;
+ }
+ if ( val )
+ reiserfs_default_io_size = PAGE_SIZE;
+ else
+ reiserfs_default_io_size = 128 * 1024;
}
if (c == 'j') {
if (arg && *arg && jdev_name) {
+ if ( *jdev_name ) { //Hm, already assigned?
+ printk("reiserfs_parse_options: journal device was already specified to be %s\n", *jdev_name);
+ return 0;
+ }
*jdev_name = arg;
}
}
@@ -731,14 +753,28 @@ static int reiserfs_remount (struct super_block * s, int * mount_flags, char * a
struct reiserfs_super_block * rs;
struct reiserfs_transaction_handle th ;
unsigned long blocks;
- unsigned long mount_options;
+ unsigned long mount_options = REISERFS_SB(s)->s_mount_opt;
+ unsigned long safe_mask = 0;
rs = SB_DISK_SUPER_BLOCK (s);
if (!reiserfs_parse_options(s, arg, &mount_options, &blocks, NULL))
return -EINVAL;
- handle_attrs( s );
+ handle_attrs(s);
+
+ /* Add options that are safe here */
+ safe_mask |= 1 << REISERFS_SMALLTAIL;
+ safe_mask |= 1 << REISERFS_LARGETAIL;
+ safe_mask |= 1 << REISERFS_NO_BORDER;
+ safe_mask |= 1 << REISERFS_NO_UNHASHED_RELOCATION;
+ safe_mask |= 1 << REISERFS_HASHED_RELOCATION;
+ safe_mask |= 1 << REISERFS_TEST4;
+ safe_mask |= 1 << REISERFS_ATTRS;
+
+ /* Update the bitmask, taking care to keep
+ * the bits we're not allowed to change here */
+ REISERFS_SB(s)->s_mount_opt = (REISERFS_SB(s)->s_mount_opt & ~safe_mask) | (mount_options & safe_mask);
if(blocks) {
int rc = reiserfs_resize(s, blocks);
diff --git a/include/asm-alpha/thread_info.h b/include/asm-alpha/thread_info.h
index f798b77816c9..1f19c2add410 100644
--- a/include/asm-alpha/thread_info.h
+++ b/include/asm-alpha/thread_info.h
@@ -51,7 +51,7 @@ register struct thread_info *__current_thread_info __asm__("$8");
/* Thread information allocation. */
#define THREAD_SIZE (2*PAGE_SIZE)
-#define alloc_thread_info() \
+#define alloc_thread_info(tsk) \
((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
#define get_thread_info(ti) get_task_struct((ti)->task)
diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
index 8ca864104452..60bec9ec8c79 100644
--- a/include/asm-arm/thread_info.h
+++ b/include/asm-arm/thread_info.h
@@ -84,7 +84,7 @@ static inline struct thread_info *current_thread_info(void)
#define THREAD_SIZE (8192)
-extern struct thread_info *alloc_thread_info(void);
+extern struct thread_info *alloc_thread_info(struct task_struct *task);
extern void free_thread_info(struct thread_info *);
#define get_thread_info(ti) get_task_struct((ti)->task)
diff --git a/include/asm-h8300/thread_info.h b/include/asm-h8300/thread_info.h
index 1c9b5b957021..d14102386280 100644
--- a/include/asm-h8300/thread_info.h
+++ b/include/asm-h8300/thread_info.h
@@ -65,7 +65,7 @@ static inline struct thread_info *current_thread_info(void)
}
/* thread information allocation */
-#define alloc_thread_info() ((struct thread_info *) \
+#define alloc_thread_info(tsk) ((struct thread_info *) \
__get_free_pages(GFP_KERNEL, 1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
#define get_thread_info(ti) get_task_struct((ti)->task)
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 0bf7210b8a85..a278e34aa158 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -87,7 +87,7 @@ static inline struct thread_info *current_thread_info(void)
/* thread information allocation */
#define THREAD_SIZE (2*PAGE_SIZE)
-#define alloc_thread_info() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
+#define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
#define get_thread_info(ti) get_task_struct((ti)->task)
#define put_thread_info(ti) put_task_struct((ti)->task)
diff --git a/include/asm-m68k/thread_info.h b/include/asm-m68k/thread_info.h
index 49988674166f..3d35213123b1 100644
--- a/include/asm-m68k/thread_info.h
+++ b/include/asm-m68k/thread_info.h
@@ -28,10 +28,10 @@ struct thread_info {
/* THREAD_SIZE should be 8k, so handle differently for 4k and 8k machines */
#if PAGE_SHIFT == 13 /* 8k machines */
-#define alloc_thread_info() ((struct thread_info *)__get_free_pages(GFP_KERNEL,0))
+#define alloc_thread_info(tsk) ((struct thread_info *)__get_free_pages(GFP_KERNEL,0))
#define free_thread_info(ti) free_pages((unsigned long)(ti),0)
#else /* otherwise assume 4k pages */
-#define alloc_thread_info() ((struct thread_info *)__get_free_pages(GFP_KERNEL,1))
+#define alloc_thread_info(tsk) ((struct thread_info *)__get_free_pages(GFP_KERNEL,1))
#define free_thread_info(ti) free_pages((unsigned long)(ti),1)
#endif /* PAGE_SHIFT == 13 */
diff --git a/include/asm-m68knommu/thread_info.h b/include/asm-m68knommu/thread_info.h
index 6447fc51e07a..f45b12a2cd17 100644
--- a/include/asm-m68knommu/thread_info.h
+++ b/include/asm-m68knommu/thread_info.h
@@ -65,7 +65,7 @@ static inline struct thread_info *current_thread_info(void)
}
/* thread information allocation */
-#define alloc_thread_info() ((struct thread_info *) \
+#define alloc_thread_info(tsk) ((struct thread_info *) \
__get_free_pages(GFP_KERNEL, 1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
#define get_thread_info(ti) get_task_struct((ti)->task)
diff --git a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h
index 57fb3ae6b022..c709d0049528 100644
--- a/include/asm-parisc/thread_info.h
+++ b/include/asm-parisc/thread_info.h
@@ -37,7 +37,7 @@ struct thread_info {
#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
#define THREAD_SHIFT (PAGE_SHIFT + THREAD_ORDER)
-#define alloc_thread_info() ((struct thread_info *) \
+#define alloc_thread_info(tsk) ((struct thread_info *) \
__get_free_pages(GFP_KERNEL, THREAD_ORDER))
#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER)
#define get_thread_info(ti) get_task_struct((ti)->task)
diff --git a/include/asm-ppc/thread_info.h b/include/asm-ppc/thread_info.h
index 5ee1cf139c9e..4d77601389f9 100644
--- a/include/asm-ppc/thread_info.h
+++ b/include/asm-ppc/thread_info.h
@@ -54,7 +54,7 @@ static inline struct thread_info *current_thread_info(void)
}
/* thread information allocation */
-#define alloc_thread_info() ((struct thread_info *) \
+#define alloc_thread_info(tsk) ((struct thread_info *) \
__get_free_pages(GFP_KERNEL, 1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
#define get_thread_info(ti) get_task_struct((ti)->task)
diff --git a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h
index 5b9083400848..345008a8a14b 100644
--- a/include/asm-ppc64/thread_info.h
+++ b/include/asm-ppc64/thread_info.h
@@ -52,7 +52,7 @@ struct thread_info {
#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
#define THREAD_SHIFT (PAGE_SHIFT + THREAD_ORDER)
-#define alloc_thread_info() ((struct thread_info *) \
+#define alloc_thread_info(tsk) ((struct thread_info *) \
__get_free_pages(GFP_KERNEL, THREAD_ORDER))
#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER)
#define get_thread_info(ti) get_task_struct((ti)->task)
diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h
index a46e8fd2c7ac..1e9a320899bb 100644
--- a/include/asm-s390/thread_info.h
+++ b/include/asm-s390/thread_info.h
@@ -68,7 +68,7 @@ static inline struct thread_info *current_thread_info(void)
}
/* thread information allocation */
-#define alloc_thread_info() ((struct thread_info *) \
+#define alloc_thread_info(tsk) ((struct thread_info *) \
__get_free_pages(GFP_KERNEL,THREAD_ORDER))
#define free_thread_info(ti) free_pages((unsigned long) (ti),THREAD_ORDER)
#define get_thread_info(ti) get_task_struct((ti)->task)
diff --git a/include/asm-sparc/thread_info.h b/include/asm-sparc/thread_info.h
index bc004d4c0e3b..94ef1063ed48 100644
--- a/include/asm-sparc/thread_info.h
+++ b/include/asm-sparc/thread_info.h
@@ -78,7 +78,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
#endif
BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info, void)
-#define alloc_thread_info() BTFIXUP_CALL(alloc_thread_info)()
+#define alloc_thread_info(tsk) BTFIXUP_CALL(alloc_thread_info)()
BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
#define free_thread_info(ti) BTFIXUP_CALL(free_thread_info)(ti)
diff --git a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h
index 298ce3e9027d..88dd8b32345a 100644
--- a/include/asm-sparc64/thread_info.h
+++ b/include/asm-sparc64/thread_info.h
@@ -142,10 +142,10 @@ register struct thread_info *current_thread_info_reg asm("g6");
/* thread information allocation */
#if PAGE_SHIFT == 13
-#define alloc_thread_info() ((struct thread_info *)__get_free_pages(GFP_KERNEL, 1))
+#define alloc_thread_info(tsk)((struct thread_info *)__get_free_pages(GFP_KERNEL, 1))
#define free_thread_info(ti) free_pages((unsigned long)(ti),1)
#else /* PAGE_SHIFT == 13 */
-#define alloc_thread_info() ((struct thread_info *)__get_free_pages(GFP_KERNEL, 0))
+#define alloc_thread_info(tsk)((struct thread_info *)__get_free_pages(GFP_KERNEL, 0))
#define free_thread_info(ti) free_pages((unsigned long)(ti),0)
#endif /* PAGE_SHIFT == 13 */
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index bd3f4fe40c6b..6a606bf0b684 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -49,7 +49,7 @@ static inline struct thread_info *current_thread_info(void)
/* thread information allocation */
#define THREAD_SIZE (4*PAGE_SIZE)
-#define alloc_thread_info() ((struct thread_info *) \
+#define alloc_thread_info(tsk) ((struct thread_info *) \
__get_free_pages(GFP_KERNEL,2))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 2)
#define get_thread_info(ti) get_task_struct((ti)->task)
diff --git a/include/asm-v850/thread_info.h b/include/asm-v850/thread_info.h
index 3e20d565d5bd..b5770136e433 100644
--- a/include/asm-v850/thread_info.h
+++ b/include/asm-v850/thread_info.h
@@ -54,7 +54,7 @@ struct thread_info {
*/
/* thread information allocation */
-#define alloc_thread_info() ((struct thread_info *) \
+#define alloc_thread_info(tsk) ((struct thread_info *) \
__get_free_pages(GFP_KERNEL, 1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
#define get_thread_info(ti) get_task_struct((ti)->task)
diff --git a/include/asm-x86_64/thread_info.h b/include/asm-x86_64/thread_info.h
index a4bbd2239afa..d9a9989c20d9 100644
--- a/include/asm-x86_64/thread_info.h
+++ b/include/asm-x86_64/thread_info.h
@@ -73,7 +73,7 @@ static inline struct thread_info *stack_thread_info(void)
}
/* thread information allocation */
-#define alloc_thread_info() \
+#define alloc_thread_info(tsk) \
((struct thread_info *) __get_free_pages(GFP_KERNEL,THREAD_ORDER))
#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER)
#define get_thread_info(ti) get_task_struct((ti)->task)
diff --git a/include/linux/aio.h b/include/linux/aio.h
index adbf5ea8bbe9..54507489d10d 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -41,9 +41,9 @@ struct kioctx;
#define kiocbClearKicked(iocb) clear_bit(KIF_KICKED, &(iocb)->ki_flags)
#define kiocbClearCancelled(iocb) clear_bit(KIF_CANCELLED, &(iocb)->ki_flags)
-#define kiocbIsLocked(iocb) test_bit(0, &(iocb)->ki_flags)
-#define kiocbIsKicked(iocb) test_bit(1, &(iocb)->ki_flags)
-#define kiocbIsCancelled(iocb) test_bit(2, &(iocb)->ki_flags)
+#define kiocbIsLocked(iocb) test_bit(KIF_LOCKED, &(iocb)->ki_flags)
+#define kiocbIsKicked(iocb) test_bit(KIF_KICKED, &(iocb)->ki_flags)
+#define kiocbIsCancelled(iocb) test_bit(KIF_CANCELLED, &(iocb)->ki_flags)
struct kiocb {
struct list_head ki_run_list;
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index a252f5ab3198..266762203a70 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -72,6 +72,12 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
#endif /* !CONFIG_HUGETLB_PAGE */
#ifdef CONFIG_HUGETLBFS
+struct hugetlbfs_config {
+ uid_t uid;
+ gid_t gid;
+ umode_t mode;
+};
+
extern struct file_operations hugetlbfs_file_operations;
extern struct vm_operations_struct hugetlb_vm_ops;
struct file *hugetlb_zero_setup(size_t);
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 319730b9ff5a..c8053e862da2 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1631,29 +1631,43 @@ struct reiserfs_iget_args {
/***************************************************************************/
/*#ifdef __KERNEL__*/
+#define get_journal_desc_magic(bh) (bh->b_data + bh->b_size - 12)
-/* journal.c see journal.c for all the comments here */
-
-#define JOURNAL_TRANS_HALF 1018 /* must be correct to keep the desc and commit structs at 4k */
+#define journal_trans_half(blocksize) \
+ ((blocksize - sizeof (struct reiserfs_journal_desc) + sizeof (__u32) - 12) / sizeof (__u32))
+/* journal.c see journal.c for all the comments here */
/* first block written in a commit. */
struct reiserfs_journal_desc {
__u32 j_trans_id ; /* id of commit */
__u32 j_len ; /* length of commit. len +1 is the commit block */
__u32 j_mount_id ; /* mount id of this trans*/
- __u32 j_realblock[JOURNAL_TRANS_HALF] ; /* real locations for each block */
- char j_magic[12] ;
+ __u32 j_realblock[1] ; /* real locations for each block */
} ;
+#define get_desc_trans_id(d) le32_to_cpu((d)->j_trans_id)
+#define get_desc_trans_len(d) le32_to_cpu((d)->j_len)
+#define get_desc_mount_id(d) le32_to_cpu((d)->j_mount_id)
+
+#define set_desc_trans_id(d,val) do { (d)->j_trans_id = cpu_to_le32 (val); } while (0)
+#define set_desc_trans_len(d,val) do { (d)->j_len = cpu_to_le32 (val); } while (0)
+#define set_desc_mount_id(d,val) do { (d)->j_mount_id = cpu_to_le32 (val); } while (0)
+
/* last block written in a commit */
struct reiserfs_journal_commit {
__u32 j_trans_id ; /* must match j_trans_id from the desc block */
__u32 j_len ; /* ditto */
- __u32 j_realblock[JOURNAL_TRANS_HALF] ; /* real locations for each block */
- char j_digest[16] ; /* md5 sum of all the blocks involved, including desc and commit. not used, kill it */
+ __u32 j_realblock[1] ; /* real locations for each block */
} ;
+#define get_commit_trans_id(c) le32_to_cpu((c)->j_trans_id)
+#define get_commit_trans_len(c) le32_to_cpu((c)->j_len)
+#define get_commit_mount_id(c) le32_to_cpu((c)->j_mount_id)
+
+#define set_commit_trans_id(c,val) do { (c)->j_trans_id = cpu_to_le32 (val); } while (0)
+#define set_commit_trans_len(c,val) do { (c)->j_len = cpu_to_le32 (val); } while (0)
+
/* this header block gets written whenever a transaction is considered fully flushed, and is more recent than the
** last fully flushed transaction. fully flushed means all the log blocks and all the real blocks are on disk,
** and this transaction does not need to be replayed.
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 69342d6868fc..f30f23b5c307 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -253,6 +253,8 @@ struct reiserfs_journal {
struct reiserfs_journal_cnode *j_list_hash_table[JOURNAL_HASH_SIZE] ; /* hash table for all the real buffer heads in all
the transactions */
struct list_head j_prealloc_list; /* list of inodes which have preallocated blocks */
+ unsigned long j_max_trans_size ;
+ unsigned long j_max_batch_size ;
};
#define JOURNAL_DESC_MAGIC "ReIsErLB" /* ick. magic string to find desc blocks in the journal */
diff --git a/kernel/fork.c b/kernel/fork.c
index 23c6d34f800f..7fe73cf41ac5 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -38,8 +38,6 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
-static kmem_cache_t *task_struct_cachep;
-
extern int copy_semundo(unsigned long clone_flags, struct task_struct *tsk);
extern void exit_semundo(struct task_struct *tsk);
@@ -74,7 +72,13 @@ int nr_processes(void)
return total;
}
-static void free_task_struct(struct task_struct *tsk)
+#ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
+# define alloc_task_struct() kmem_cache_alloc(task_struct_cachep, GFP_KERNEL)
+# define free_task_struct(tsk) kmem_cache_free(task_struct_cachep, (tsk))
+static kmem_cache_t *task_struct_cachep;
+#endif
+
+static void free_task(struct task_struct *tsk)
{
/*
* The task cache is effectively disabled right now.
@@ -84,14 +88,14 @@ static void free_task_struct(struct task_struct *tsk)
*/
if (tsk != current) {
free_thread_info(tsk->thread_info);
- kmem_cache_free(task_struct_cachep,tsk);
+ free_task_struct(tsk);
} else {
int cpu = get_cpu();
tsk = task_cache[cpu];
if (tsk) {
free_thread_info(tsk->thread_info);
- kmem_cache_free(task_struct_cachep,tsk);
+ free_task_struct(tsk);
}
task_cache[cpu] = current;
put_cpu();
@@ -106,7 +110,7 @@ void __put_task_struct(struct task_struct *tsk)
security_task_free(tsk);
free_uid(tsk->user);
- free_task_struct(tsk);
+ free_task(tsk);
}
void add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait)
@@ -186,6 +190,7 @@ int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync)
void __init fork_init(unsigned long mempages)
{
+#ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
/* create a slab on which task_structs can be allocated */
task_struct_cachep =
kmem_cache_create("task_struct",
@@ -193,6 +198,7 @@ void __init fork_init(unsigned long mempages)
SLAB_MUST_HWCACHE_ALIGN, NULL, NULL);
if (!task_struct_cachep)
panic("fork_init(): cannot create task_struct SLAB cache");
+#endif
/*
* The default maximum number of threads is set to a safe
@@ -222,13 +228,13 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
task_cache[cpu] = NULL;
put_cpu();
if (!tsk) {
- ti = alloc_thread_info();
- if (!ti)
+ tsk = alloc_task_struct();
+ if (!tsk)
return NULL;
- tsk = kmem_cache_alloc(task_struct_cachep, GFP_KERNEL);
- if (!tsk) {
- free_thread_info(ti);
+ ti = alloc_thread_info(tsk);
+ if (!ti) {
+ free_task_struct(tsk);
return NULL;
}
} else
@@ -1041,7 +1047,7 @@ bad_fork_cleanup_count:
atomic_dec(&p->user->processes);
free_uid(p->user);
bad_fork_free:
- free_task_struct(p);
+ free_task(p);
goto fork_out;
}
diff --git a/kernel/timer.c b/kernel/timer.c
index 1ec8f5370fc7..5c86834136e4 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1226,47 +1226,36 @@ void __init init_timers(void)
}
#ifdef CONFIG_TIME_INTERPOLATION
-
volatile unsigned long last_nsec_offset;
-
-struct time_interpolator *time_interpolator;
-
#ifndef __HAVE_ARCH_CMPXCHG
spinlock_t last_nsec_offset_lock = SPIN_LOCK_UNLOCKED;
#endif
-static struct {
- spinlock_t lock; /* lock protecting list */
- struct time_interpolator *list; /* list of registered interpolators */
-} ti_global = {
- .lock = SPIN_LOCK_UNLOCKED
-};
+struct time_interpolator *time_interpolator;
+struct time_interpolator *time_interpolator_list;
+spinlock_t time_interpolator_lock = SPIN_LOCK_UNLOCKED;
static inline int
is_better_time_interpolator(struct time_interpolator *new)
{
if (!time_interpolator)
return 1;
- return new->frequency > 2*time_interpolator->frequency
- || (unsigned long) new->drift < (unsigned long) time_interpolator->drift;
+ return new->frequency > 2*time_interpolator->frequency ||
+ (unsigned long)new->drift < (unsigned long)time_interpolator->drift;
}
void
register_time_interpolator(struct time_interpolator *ti)
{
- spin_lock(&ti_global.lock);
- {
- write_seqlock_irq(&xtime_lock);
- {
- if (is_better_time_interpolator(ti))
- time_interpolator = ti;
- }
- write_sequnlock_irq(&xtime_lock);
-
- ti->next = ti_global.list;
- ti_global.list = ti;
- }
- spin_unlock(&ti_global.lock);
+ spin_lock(&time_interpolator_lock);
+ write_seqlock_irq(&xtime_lock);
+ if (is_better_time_interpolator(ti))
+ time_interpolator = ti;
+ write_sequnlock_irq(&xtime_lock);
+
+ ti->next = time_interpolator_list;
+ time_interpolator_list = ti;
+ spin_unlock(&time_interpolator_lock);
}
void
@@ -1274,30 +1263,26 @@ unregister_time_interpolator(struct time_interpolator *ti)
{
struct time_interpolator *curr, **prev;
- spin_lock(&ti_global.lock);
- {
- prev = &ti_global.list;
- for (curr = *prev; curr; curr = curr->next) {
- if (curr == ti) {
- *prev = curr->next;
- break;
- }
- prev = &curr->next;
- }
- write_seqlock_irq(&xtime_lock);
- {
- if (ti == time_interpolator) {
- /* we lost the best time-interpolator: */
- time_interpolator = NULL;
- /* find the next-best interpolator */
- for (curr = ti_global.list; curr; curr = curr->next)
- if (is_better_time_interpolator(curr))
- time_interpolator = curr;
- }
+ spin_lock(&time_interpolator_lock);
+ prev = &time_interpolator_list;
+ for (curr = *prev; curr; curr = curr->next) {
+ if (curr == ti) {
+ *prev = curr->next;
+ break;
}
- write_sequnlock_irq(&xtime_lock);
+ prev = &curr->next;
}
- spin_unlock(&ti_global.lock);
-}
+ write_seqlock_irq(&xtime_lock);
+ if (ti == time_interpolator) {
+ /* we lost the best time-interpolator: */
+ time_interpolator = NULL;
+ /* find the next-best interpolator */
+ for (curr = time_interpolator_list; curr; curr = curr->next)
+ if (is_better_time_interpolator(curr))
+ time_interpolator = curr;
+ }
+ write_sequnlock_irq(&xtime_lock);
+ spin_unlock(&time_interpolator_lock);
+}
#endif /* CONFIG_TIME_INTERPOLATION */
diff --git a/mm/filemap.c b/mm/filemap.c
index 0db36521d5bb..1352d59d2ee4 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -81,8 +81,6 @@ void __remove_from_page_cache(struct page *page)
{
struct address_space *mapping = page->mapping;
- BUG_ON(PageDirty(page) && !PageSwapCache(page));
-
radix_tree_delete(&mapping->page_tree, page->index);
list_del(&page->list);
page->mapping = NULL;
@@ -1410,6 +1408,11 @@ void remove_suid(struct dentry *dentry)
}
}
+/*
+ * Copy as much as we can into the page and return the number of bytes which
+ * were sucessfully copied. If a fault is encountered then clear the page
+ * out to (offset+bytes) and return the number of bytes which were copied.
+ */
static inline size_t
filemap_copy_from_user(struct page *page, unsigned long offset,
const char __user *buf, unsigned bytes)
@@ -1427,30 +1430,42 @@ filemap_copy_from_user(struct page *page, unsigned long offset,
left = __copy_from_user(kaddr + offset, buf, bytes);
kunmap(page);
}
- return left ? 0 : bytes;
+ return bytes - left;
}
static size_t
__filemap_copy_from_user_iovec(char *vaddr,
const struct iovec *iov, size_t base, size_t bytes)
{
- size_t copied = 0;
+ size_t copied = 0, left = 0;
while (bytes) {
char __user *buf = iov->iov_base + base;
int copy = min(bytes, iov->iov_len - base);
base = 0;
- if (__copy_from_user(vaddr, buf, copy))
- break;
+ left = __copy_from_user(vaddr, buf, copy);
copied += copy;
bytes -= copy;
vaddr += copy;
iov++;
+
+ if (unlikely(left)) {
+ /* zero the rest of the target like __copy_from_user */
+ if (bytes)
+ memset(vaddr, 0, bytes);
+ break;
+ }
}
- return copied;
+ return copied - left;
}
+/*
+ * This has the same sideeffects and return value as filemap_copy_from_user().
+ * The difference is that on a fault we need to memset the remainder of the
+ * page (out to offset+bytes), to emulate filemap_copy_from_user()'s
+ * single-segment behaviour.
+ */
static inline size_t
filemap_copy_from_user_iovec(struct page *page, unsigned long offset,
const struct iovec *iov, size_t base, size_t bytes)
@@ -1718,8 +1733,7 @@ generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
copied = filemap_copy_from_user_iovec(page, offset,
cur_iov, iov_base, bytes);
flush_dcache_page(page);
- status = a_ops->commit_write(file, page, offset,
- offset + copied);
+ status = a_ops->commit_write(file, page, offset, offset+bytes);
if (likely(copied > 0)) {
if (!status)
status = copied;
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 93544343f932..323dd1c92bd9 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -286,10 +286,14 @@ static int conf_choice(struct menu *menu)
break;
}
} else {
- sym->user = sym->curr;
- if (sym->curr.tri == mod) {
+ switch (sym_get_tristate_value(sym)) {
+ case no:
+ return 1;
+ case mod:
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
return 0;
+ case yes:
+ break;
}
}
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index bf833ee23318..4d72008b8979 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -243,7 +243,8 @@ int conf_read(const char *name)
prop = sym_get_choice_prop(sym);
sym->flags &= ~SYMBOL_NEW;
for (e = prop->expr; e; e = e->left.expr)
- sym->flags |= e->right.sym->flags & SYMBOL_NEW;
+ if (e->right.sym->visible != no)
+ sym->flags |= e->right.sym->flags & SYMBOL_NEW;
}
sym_change_count = 1;
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index b97b02807f92..16317670a879 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -221,11 +221,18 @@ void menu_finalize(struct menu *parent)
for (menu = parent->list; menu; menu = menu->next) {
if (sym && sym_is_choice(sym) && menu->sym) {
menu->sym->flags |= SYMBOL_CHOICEVAL;
+ if (!menu->prompt)
+ fprintf(stderr, "%s:%d:warning: choice value must have a prompt\n",
+ menu->file->name, menu->lineno);
for (prop = menu->sym->prop; prop; prop = prop->next) {
- if (prop->type != P_DEFAULT)
- continue;
- fprintf(stderr, "%s:%d:warning: defaults for choice values not supported\n",
- prop->file->name, prop->lineno);
+ if (prop->type == P_PROMPT && prop->menu != menu) {
+ fprintf(stderr, "%s:%d:warning: choice values currently only support a single prompt\n",
+ prop->file->name, prop->lineno);
+
+ }
+ if (prop->type == P_DEFAULT)
+ fprintf(stderr, "%s:%d:warning: defaults for choice values not supported\n",
+ prop->file->name, prop->lineno);
}
current_entry = menu;
menu_set_type(sym->type);
@@ -311,14 +318,6 @@ bool menu_is_visible(struct menu *menu)
} else
visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
- if (sym && sym_is_choice(sym)) {
- for (child = menu->list; child; child = child->next)
- if (menu_is_visible(child))
- break;
- if (!child)
- return false;
- }
-
if (visible != no)
return true;
if (!sym || sym_get_tristate_value(menu->sym) == no)
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index e52ca16d3dd0..5c62b2c09a74 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -201,6 +201,9 @@ static struct symbol *sym_calc_choice(struct symbol *sym)
if (def_sym->visible != no)
return def_sym;
}
+
+ /* no choice? reset tristate value */
+ sym->curr.tri = no;
return NULL;
}
diff --git a/sound/oss/cmpci.c b/sound/oss/cmpci.c
index f9d784231635..7a163c32aacb 100644
--- a/sound/oss/cmpci.c
+++ b/sound/oss/cmpci.c
@@ -580,15 +580,17 @@ static void set_ac3(struct cm_state *s, unsigned rate)
spin_unlock_irqrestore(&s->lock, flags);
}
-static void trans_ac3(struct cm_state *s, void *dest, const char *source, int size)
+static int trans_ac3(struct cm_state *s, void *dest, const char *source, int size)
{
int i = size / 2;
+ int err;
unsigned long data;
unsigned long *dst = (unsigned long *) dest;
unsigned short *src = (unsigned short *)source;
do {
- data = (unsigned long) *src++;
+ if ((err = __get_user(data, src++)))
+ return err;
data <<= 12; // ok for 16-bit data
if (s->spdif_counter == 2 || s->spdif_counter == 3)
data |= 0x40000000; // indicate AC-3 raw data
@@ -605,6 +607,8 @@ static void trans_ac3(struct cm_state *s, void *dest, const char *source, int si
if (s->spdif_counter == 384)
s->spdif_counter = 0;
} while (--i);
+
+ return 0;
}
static void set_adc_rate_unlocked(struct cm_state *s, unsigned rate)
@@ -1655,13 +1659,16 @@ static ssize_t cm_write(struct file *file, const char *buffer, size_t count, lof
continue;
}
if (s->status & DO_AC3_SW) {
+ int err;
+
// clip exceeded data, caught by 033 and 037
if (swptr + 2 * cnt > s->dma_dac.dmasize)
cnt = (s->dma_dac.dmasize - swptr) / 2;
- trans_ac3(s, s->dma_dac.rawbuf + swptr, buffer, cnt);
+ if ((err = trans_ac3(s, s->dma_dac.rawbuf + swptr, buffer, cnt)))
+ return err;
swptr = (swptr + 2 * cnt) % s->dma_dac.dmasize;
} else if (s->status & DO_DUAL_DAC) {
- int i;
+ int i, err;
unsigned long *src, *dst0, *dst1;
src = (unsigned long *) buffer;
@@ -1669,8 +1676,10 @@ static ssize_t cm_write(struct file *file, const char *buffer, size_t count, lof
dst1 = (unsigned long *) (s->dma_adc.rawbuf + swptr);
// copy left/right sample at one time
for (i = 0; i <= cnt / 4; i++) {
- *dst0++ = *src++;
- *dst1++ = *src++;
+ if ((err = __get_user(*dst0++, src++)))
+ return err;
+ if ((err = __get_user(*dst1++, src++)))
+ return err;
}
swptr = (swptr + cnt) % s->dma_dac.dmasize;
} else {