[PATCH] introduce fmode_t, do annotations

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
diff --git a/block/bsg.c b/block/bsg.c
index 034112b..2d36b12 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -173,7 +173,7 @@
 
 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)
+				fmode_t has_write_perm)
 {
 	if (hdr->request_len > BLK_MAX_CDB) {
 		rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL);
@@ -242,7 +242,7 @@
  * 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, fmode_t has_write_perm)
 {
 	struct request_queue *q = bd->queue;
 	struct request *rq, *next_rq = NULL;
@@ -601,7 +601,8 @@
 }
 
 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,
+		       fmode_t has_write_perm)
 {
 	struct bsg_command *bc;
 	struct request *rq;
diff --git a/block/cmd-filter.c b/block/cmd-filter.c
index e669aed..504b275 100644
--- a/block/cmd-filter.c
+++ b/block/cmd-filter.c
@@ -27,7 +27,7 @@
 #include <linux/cdrom.h>
 
 int blk_verify_command(struct blk_cmd_filter *filter,
-		       unsigned char *cmd, int has_write_perm)
+		       unsigned char *cmd, fmode_t has_write_perm)
 {
 	/* root can do any command. */
 	if (capable(CAP_SYS_RAWIO))
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index c34272a..c525905 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -384,7 +384,8 @@
 		  struct gendisk *disk, struct scsi_ioctl_command __user *sic)
 {
 	struct request *rq;
-	int err, write_perm = 0;
+	int err;
+	fmode_t write_perm = 0;
 	unsigned int in_len, out_len, bytes, opcode, cmdlen;
 	char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
 
@@ -428,7 +429,7 @@
 
 	/* scsi_ioctl passes NULL */
 	if (file && (file->f_mode & FMODE_WRITE))
-		write_perm = 1;
+		write_perm = FMODE_WRITE;
 
 	err = blk_verify_command(&q->cmd_filter, rq->cmd, write_perm);
 	if (err)
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 7516baf..d19c5a9 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1560,9 +1560,9 @@
 	if (fd_ref[drive] && old_dev != system)
 		return -EBUSY;
 
-	if (filp && filp->f_mode & 3) {
+	if (filp && filp->f_mode & (FMODE_READ|FMODE_WRITE)) {
 		check_disk_change(inode->i_bdev);
-		if (filp->f_mode & 2 ) {
+		if (filp->f_mode & FMODE_WRITE ) {
 			int wrprot;
 
 			get_fdc(drive);
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 432cf40..e1db285 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1826,9 +1826,9 @@
 	if (filp->f_flags & O_NDELAY)
 		return 0;
 
-	if (filp->f_mode & 3) {
+	if (filp->f_mode & (FMODE_READ|FMODE_WRITE)) {
 		check_disk_change(inode->i_bdev);
-		if (filp->f_mode & 2) {
+		if (filp->f_mode & FMODE_WRITE) {
 			if (p->wpstat) {
 				if (p->ref < 0)
 					p->ref = 0;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 2cea27a..ae3ef894 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3761,14 +3761,14 @@
 		UFDCS->rawcmd = 2;
 
 	if (!(filp->f_flags & O_NDELAY)) {
-		if (filp->f_mode & 3) {
+		if (filp->f_mode & (FMODE_READ|FMODE_WRITE)) {
 			UDRS->last_checked = 0;
 			check_disk_change(inode->i_bdev);
 			if (UTESTF(FD_DISK_CHANGED))
 				goto out;
 		}
 		res = -EROFS;
-		if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
+		if ((filp->f_mode & FMODE_WRITE) && !(UTESTF(FD_DISK_WRITABLE)))
 			goto out;
 	}
 	mutex_unlock(&open_lock);
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index e7fe6ca..a902d84 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -305,7 +305,7 @@
 	if (pf->media_status == PF_NM)
 		return -ENODEV;
 
-	if ((pf->media_status == PF_RO) && (file->f_mode & 2))
+	if ((pf->media_status == PF_RO) && (file->f_mode & FMODE_WRITE))
 		return -EROFS;
 
 	pf->access++;
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 5ae2296..1e4006e 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -667,7 +667,7 @@
 		goto out;
 
 	err = -EROFS;
-	if ((!(tape->flags & PT_WRITE_OK)) && (file->f_mode & 2))
+	if ((!(tape->flags & PT_WRITE_OK)) && (file->f_mode & FMODE_WRITE))
 		goto out;
 
 	if (!(iminor(inode) & 128))
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 195ca7c..4d581e8 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2320,7 +2320,7 @@
 /*
  * called at open time.
  */
-static int pkt_open_dev(struct pktcdvd_device *pd, int write)
+static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
 {
 	int ret;
 	long lba;
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index 730ccea..a53ca54 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -908,13 +908,13 @@
 		return -EBUSY;
 
 	if (err == 0 && (filp->f_flags & O_NDELAY) == 0
-	    && (filp->f_mode & 3)) {
+	    && (filp->f_mode & (FMODE_READ|FMODE_WRITE))) {
 		check_disk_change(inode->i_bdev);
 		if (fs->ejected)
 			err = -ENXIO;
 	}
 
-	if (err == 0 && (filp->f_mode & 2)) {
+	if (err == 0 && (filp->f_mode & FMODE_WRITE)) {
 		if (fs->write_prot < 0)
 			fs->write_prot = swim3_readbit(fs, WRITE_PROT);
 		if (fs->write_prot)
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 39f6357..8054ee8 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -338,7 +338,7 @@
 
 	if ((nvram_open_cnt && (file->f_flags & O_EXCL)) ||
 	    (nvram_open_mode & NVRAM_EXCL) ||
-	    ((file->f_mode & 2) && (nvram_open_mode & NVRAM_WRITE))) {
+	    ((file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE))) {
 		spin_unlock(&nvram_state_lock);
 		unlock_kernel();
 		return -EBUSY;
@@ -346,7 +346,7 @@
 
 	if (file->f_flags & O_EXCL)
 		nvram_open_mode |= NVRAM_EXCL;
-	if (file->f_mode & 2)
+	if (file->f_mode & FMODE_WRITE)
 		nvram_open_mode |= NVRAM_WRITE;
 	nvram_open_cnt++;
 
@@ -366,7 +366,7 @@
 	/* if only one instance is open, clear the EXCL bit */
 	if (nvram_open_mode & NVRAM_EXCL)
 		nvram_open_mode &= ~NVRAM_EXCL;
-	if (file->f_mode & 2)
+	if (file->f_mode & FMODE_WRITE)
 		nvram_open_mode &= ~NVRAM_WRITE;
 
 	spin_unlock(&nvram_state_lock);
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c
index 409e4c1..0d5f505 100644
--- a/drivers/ide/ide-floppy_ioctl.c
+++ b/drivers/ide/ide-floppy_ioctl.c
@@ -250,7 +250,7 @@
 	case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
 		return ide_floppy_get_format_capacities(drive, argp);
 	case IDEFLOPPY_IOCTL_FORMAT_START:
-		if (!(file->f_mode & 2))
+		if (!(file->f_mode & FMODE_WRITE))
 			return -EPERM;
 		return ide_floppy_format_unit(drive, (int __user *)argp);
 	case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c
index d44898f..d367473 100644
--- a/drivers/ide/ide-gd.c
+++ b/drivers/ide/ide-gd.c
@@ -202,7 +202,7 @@
 			goto out_put_idkp;
 		}
 
-		if ((drive->dev_flags & IDE_DFLAG_WP) && (filp->f_mode & 2)) {
+		if ((drive->dev_flags & IDE_DFLAG_WP) && (filp->f_mode & FMODE_WRITE)) {
 			ret = -EROFS;
 			goto out_put_idkp;
 		}
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index dca401d..777c948 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -988,9 +988,9 @@
 	return r;
 }
 
-static inline int get_mode(struct dm_ioctl *param)
+static inline fmode_t get_mode(struct dm_ioctl *param)
 {
-	int mode = FMODE_READ | FMODE_WRITE;
+	fmode_t mode = FMODE_READ | FMODE_WRITE;
 
 	if (param->flags & DM_READONLY_FLAG)
 		mode = FMODE_READ;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index a740a69..7c8671b 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -43,7 +43,7 @@
 	 * device.  This should be a combination of FMODE_READ
 	 * and FMODE_WRITE.
 	 */
-	int mode;
+	fmode_t mode;
 
 	/* a list of devices used by this table */
 	struct list_head devices;
@@ -217,7 +217,7 @@
 	return 0;
 }
 
-int dm_table_create(struct dm_table **result, int mode,
+int dm_table_create(struct dm_table **result, fmode_t mode,
 		    unsigned num_targets, struct mapped_device *md)
 {
 	struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL);
@@ -395,7 +395,7 @@
  * careful to leave things as they were if we fail to reopen the
  * device.
  */
-static int upgrade_mode(struct dm_dev_internal *dd, int new_mode,
+static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode,
 			struct mapped_device *md)
 {
 	int r;
@@ -421,7 +421,7 @@
  */
 static int __table_get_device(struct dm_table *t, struct dm_target *ti,
 			      const char *path, sector_t start, sector_t len,
-			      int mode, struct dm_dev **result)
+			      fmode_t mode, struct dm_dev **result)
 {
 	int r;
 	dev_t uninitialized_var(dev);
@@ -537,7 +537,7 @@
 EXPORT_SYMBOL_GPL(dm_set_device_limits);
 
 int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
-		  sector_t len, int mode, struct dm_dev **result)
+		  sector_t len, fmode_t mode, struct dm_dev **result)
 {
 	int r = __table_get_device(ti->table, ti, path,
 				   start, len, mode, result);
@@ -887,7 +887,7 @@
 	return &t->devices;
 }
 
-int dm_table_get_mode(struct dm_table *t)
+fmode_t dm_table_get_mode(struct dm_table *t)
 {
 	return t->mode;
 }
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 963840e..bcffeda 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -96,7 +96,7 @@
 		return -ENODEV;
 
 	/* You can't open the RO devices RW */
-	if ((file->f_mode & 2) && (minor & 1))
+	if ((file->f_mode & FMODE_WRITE) && (minor & 1))
 		return -EACCES;
 
 	lock_kernel();
@@ -114,7 +114,7 @@
 	}
 
 	/* You can't open it RW if it's not a writeable device */
-	if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) {
+	if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {
 		put_mtd_device(mtd);
 		ret = -EACCES;
 		goto out;
@@ -144,7 +144,7 @@
 	DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
 
 	/* Only sync if opened RW */
-	if ((file->f_mode & 2) && mtd->sync)
+	if ((file->f_mode & FMODE_WRITE) && mtd->sync)
 		mtd->sync(mtd);
 
 	put_mtd_device(mtd);
@@ -443,7 +443,7 @@
 	{
 		struct erase_info *erase;
 
-		if(!(file->f_mode & 2))
+		if(!(file->f_mode & FMODE_WRITE))
 			return -EPERM;
 
 		erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
@@ -497,7 +497,7 @@
 		struct mtd_oob_buf __user *user_buf = argp;
 	        uint32_t retlen;
 
-		if(!(file->f_mode & 2))
+		if(!(file->f_mode & FMODE_WRITE))
 			return -EPERM;
 
 		if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
diff --git a/drivers/parisc/eisa_eeprom.c b/drivers/parisc/eisa_eeprom.c
index 5ac2079..685d94e 100644
--- a/drivers/parisc/eisa_eeprom.c
+++ b/drivers/parisc/eisa_eeprom.c
@@ -86,7 +86,7 @@
 {
 	cycle_kernel_lock();
 
-	if (file->f_mode & 2)
+	if (file->f_mode & FMODE_WRITE)
 		return -EINVAL;
    
 	return 0;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 218408e..8897f3b 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -840,7 +840,7 @@
  * to be used for internal purposes.  If you ever need it - reconsider
  * your API.
  */
-struct block_device *open_by_devnum(dev_t dev, unsigned mode)
+struct block_device *open_by_devnum(dev_t dev, fmode_t mode)
 {
 	struct block_device *bdev = bdget(dev);
 	int err = -ENOMEM;
@@ -975,7 +975,7 @@
 }
 EXPORT_SYMBOL(bd_set_size);
 
-static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags,
+static int __blkdev_get(struct block_device *bdev, fmode_t mode, unsigned flags,
 			int for_part);
 static int __blkdev_put(struct block_device *bdev, int for_part);
 
@@ -1104,7 +1104,7 @@
 	return ret;
 }
 
-static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags,
+static int __blkdev_get(struct block_device *bdev, fmode_t mode, unsigned flags,
 			int for_part)
 {
 	/*
@@ -1123,7 +1123,7 @@
 	return do_open(bdev, &fake_file, for_part);
 }
 
-int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags)
+int blkdev_get(struct block_device *bdev, fmode_t mode, unsigned flags)
 {
 	return __blkdev_get(bdev, mode, flags, 0);
 }
@@ -1315,7 +1315,7 @@
 struct block_device *open_bdev_excl(const char *path, int flags, void *holder)
 {
 	struct block_device *bdev;
-	mode_t mode = FMODE_READ;
+	fmode_t mode = FMODE_READ;
 	int error = 0;
 
 	bdev = lookup_bdev(path);
diff --git a/fs/fifo.c b/fs/fifo.c
index 987bf94..f8f97b8 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -51,7 +51,7 @@
 	filp->f_mode &= (FMODE_READ | FMODE_WRITE);
 
 	switch (filp->f_mode) {
-	case 1:
+	case FMODE_READ:
 	/*
 	 *  O_RDONLY
 	 *  POSIX.1 says that O_NONBLOCK means return with the FIFO
@@ -76,7 +76,7 @@
 		}
 		break;
 	
-	case 2:
+	case FMODE_WRITE:
 	/*
 	 *  O_WRONLY
 	 *  POSIX.1 says that O_NONBLOCK means return -1 with
@@ -98,7 +98,7 @@
 		}
 		break;
 	
-	case 3:
+	case FMODE_READ | FMODE_WRITE:
 	/*
 	 *  O_RDWR
 	 *  POSIX.1 leaves this case "undefined" when O_NONBLOCK is set.
diff --git a/fs/file_table.c b/fs/file_table.c
index f45a449..efc06fa 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -161,7 +161,7 @@
  * code should be moved into this function.
  */
 struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry,
-		mode_t mode, const struct file_operations *fop)
+		fmode_t mode, const struct file_operations *fop)
 {
 	struct file *file;
 	struct path;
@@ -193,7 +193,7 @@
  * of this should be moving to alloc_file().
  */
 int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry,
-	   mode_t mode, const struct file_operations *fop)
+	   fmode_t mode, const struct file_operations *fop)
 {
 	int error = 0;
 	file->f_path.dentry = dentry;
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index d6ecabf..7f34f43 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -20,7 +20,7 @@
 struct hostfs_inode_info {
 	char *host_filename;
 	int fd;
-	int mode;
+	fmode_t mode;
 	struct inode vfs_inode;
 };
 
@@ -373,7 +373,8 @@
 int hostfs_file_open(struct inode *ino, struct file *file)
 {
 	char *name;
-	int mode = 0, r = 0, w = 0, fd;
+	fmode_t mode = 0;
+	int r = 0, w = 0, fd;
 
 	mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
 	if ((mode & HOSTFS_I(ino)->mode) == mode)
diff --git a/fs/locks.c b/fs/locks.c
index 5eb259e..2045748 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1580,7 +1580,8 @@
 	cmd &= ~LOCK_NB;
 	unlock = (cmd == LOCK_UN);
 
-	if (!unlock && !(cmd & LOCK_MAND) && !(filp->f_mode & 3))
+	if (!unlock && !(cmd & LOCK_MAND) &&
+	    !(filp->f_mode & (FMODE_READ|FMODE_WRITE)))
 		goto out_putf;
 
 	error = flock_make_lock(filp, &lock, cmd);
diff --git a/fs/open.c b/fs/open.c
index 5596049..83cdb9d 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -798,7 +798,7 @@
 	int error;
 
 	f->f_flags = flags;
-	f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK |
+	f->f_mode = (__force fmode_t)((flags+1) & O_ACCMODE) | FMODE_LSEEK |
 				FMODE_PREAD | FMODE_PWRITE;
 	inode = dentry->d_inode;
 	if (f->f_mode & FMODE_WRITE) {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index b5918ae..486cf3f 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1712,9 +1712,9 @@
 	file = fcheck_files(files, fd);
 	if (!file)
 		goto out_unlock;
-	if (file->f_mode & 1)
+	if (file->f_mode & FMODE_READ)
 		inode->i_mode |= S_IRUSR | S_IXUSR;
-	if (file->f_mode & 2)
+	if (file->f_mode & FMODE_WRITE)
 		inode->i_mode |= S_IWUSR | S_IXUSR;
 	spin_unlock(&files->file_lock);
 	put_files_struct(files);
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index c21df71..b89d193 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -2593,7 +2593,7 @@
 {
 	int result;
 	dev_t jdev;
-	int blkdev_mode = FMODE_READ | FMODE_WRITE;
+	fmode_t blkdev_mode = FMODE_READ | FMODE_WRITE;
 	char b[BDEVNAME_SIZE];
 
 	result = 0;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index b4fe68f..a4413ec 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -910,7 +910,8 @@
 * command filter functions
 */
 extern int blk_verify_command(struct blk_cmd_filter *filter,
-			      unsigned char *cmd, int has_write_perm);
+			      unsigned char *cmd, fmode_t has_write_perm);
+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
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 08d7835..3f8d4e7 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -85,7 +85,7 @@
 
 struct dm_dev {
 	struct block_device *bdev;
-	int mode;
+	fmode_t mode;
 	char name[16];
 };
 
@@ -95,7 +95,7 @@
  * FIXME: too many arguments.
  */
 int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
-		  sector_t len, int mode, struct dm_dev **result);
+		  sector_t len, fmode_t mode, struct dm_dev **result);
 void dm_put_device(struct dm_target *ti, struct dm_dev *d);
 
 /*
@@ -223,7 +223,7 @@
 /*
  * First create an empty table.
  */
-int dm_table_create(struct dm_table **result, int mode,
+int dm_table_create(struct dm_table **result, fmode_t mode,
 		    unsigned num_targets, struct mapped_device *md);
 
 /*
@@ -254,7 +254,7 @@
  */
 sector_t dm_table_get_size(struct dm_table *t);
 unsigned int dm_table_get_num_targets(struct dm_table *t);
-int dm_table_get_mode(struct dm_table *t);
+fmode_t dm_table_get_mode(struct dm_table *t);
 struct mapped_device *dm_table_get_md(struct dm_table *t);
 
 /*
diff --git a/include/linux/file.h b/include/linux/file.h
index a20259e..335a0a5c 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -19,10 +19,10 @@
 struct vfsmount;
 struct dentry;
 extern int init_file(struct file *, struct vfsmount *mnt,
-		struct dentry *dentry, mode_t mode,
+		struct dentry *dentry, fmode_t mode,
 		const struct file_operations *fop);
 extern struct file *alloc_file(struct vfsmount *, struct dentry *dentry,
-		mode_t mode, const struct file_operations *fop);
+		fmode_t mode, const struct file_operations *fop);
 
 static inline void fput_light(struct file *file, int fput_needed)
 {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a6a625b..60a7a58 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -63,18 +63,18 @@
 #define MAY_ACCESS 16
 #define MAY_OPEN 32
 
-#define FMODE_READ 1
-#define FMODE_WRITE 2
+#define FMODE_READ ((__force fmode_t)1)
+#define FMODE_WRITE ((__force fmode_t)2)
 
 /* Internal kernel extensions */
-#define FMODE_LSEEK	4
-#define FMODE_PREAD	8
+#define FMODE_LSEEK	((__force fmode_t)4)
+#define FMODE_PREAD	((__force fmode_t)8)
 #define FMODE_PWRITE	FMODE_PREAD	/* These go hand in hand */
 
 /* File is being opened for execution. Primary users of this flag are
    distributed filesystems that can use it to achieve correct ETXTBUSY
    behavior for cross-node execution/opening_for_writing of files */
-#define FMODE_EXEC	16
+#define FMODE_EXEC	((__force fmode_t)16)
 
 #define RW_MASK		1
 #define RWA_MASK	2
@@ -825,7 +825,7 @@
 	const struct file_operations	*f_op;
 	atomic_long_t		f_count;
 	unsigned int 		f_flags;
-	mode_t			f_mode;
+	fmode_t			f_mode;
 	loff_t			f_pos;
 	struct fown_struct	f_owner;
 	unsigned int		f_uid, f_gid;
@@ -1714,7 +1714,7 @@
 extern void bd_set_size(struct block_device *, loff_t size);
 extern void bd_forget(struct inode *inode);
 extern void bdput(struct block_device *);
-extern struct block_device *open_by_devnum(dev_t, unsigned);
+extern struct block_device *open_by_devnum(dev_t, fmode_t);
 #else
 static inline void bd_forget(struct inode *inode) {}
 #endif
@@ -1729,7 +1729,7 @@
 			       struct gendisk *disk, unsigned cmd,
 			       unsigned long arg);
 extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long);
-extern int blkdev_get(struct block_device *, mode_t, unsigned);
+extern int blkdev_get(struct block_device *, fmode_t, unsigned);
 extern int blkdev_put(struct block_device *);
 extern int bd_claim(struct block_device *, void *);
 extern void bd_release(struct block_device *);
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index a895131..00fbd5b 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -188,7 +188,7 @@
 	struct dentry *dentry = file->f_path.dentry;
 	struct inode *inode = dentry->d_inode;
 	const char *name = dentry->d_name.name;
-	mode_t mode = file->f_mode;
+	fmode_t mode = file->f_mode;
 	u32 mask = (mode & FMODE_WRITE) ? IN_CLOSE_WRITE : IN_CLOSE_NOWRITE;
 
 	if (S_ISDIR(inode->i_mode))
diff --git a/include/linux/types.h b/include/linux/types.h
index f24f7be..1d98330 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -190,6 +190,7 @@
 
 #ifdef __KERNEL__
 typedef unsigned __bitwise__ gfp_t;
+typedef unsigned __bitwise__ fmode_t;
 
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
 typedef u64 phys_addr_t;
diff --git a/ipc/shm.c b/ipc/shm.c
index 0add3fa..867e5d6 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -817,7 +817,7 @@
 	struct ipc_namespace *ns;
 	struct shm_file_data *sfd;
 	struct path path;
-	mode_t f_mode;
+	fmode_t f_mode;
 
 	err = -EINVAL;
 	if (shmid < 0)
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 1af62b8..e178366 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2283,7 +2283,7 @@
 	int idx, err;
 	struct snd_pcm_oss_file *pcm_oss_file;
 	struct snd_pcm_substream *substream;
-	unsigned int f_mode = file->f_mode;
+	fmode_t f_mode = file->f_mode;
 
 	if (rpcm_oss_file)
 		*rpcm_oss_file = NULL;
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c
index 23018a7..81e1f44 100644
--- a/sound/oss/au1550_ac97.c
+++ b/sound/oss/au1550_ac97.c
@@ -93,7 +93,7 @@
 	spinlock_t      lock;
 	struct mutex open_mutex;
 	struct mutex sem;
-	mode_t          open_mode;
+	fmode_t          open_mode;
 	wait_queue_head_t open_wait;
 
 	struct dmabuf {
diff --git a/sound/oss/dmasound/dmasound.h b/sound/oss/dmasound/dmasound.h
index d978b00..1cb13fe 100644
--- a/sound/oss/dmasound/dmasound.h
+++ b/sound/oss/dmasound/dmasound.h
@@ -129,7 +129,7 @@
     int (*mixer_ioctl)(u_int, u_long);	/* optional */
     int (*write_sq_setup)(void);	/* optional */
     int (*read_sq_setup)(void);		/* optional */
-    int (*sq_open)(mode_t);		/* optional */
+    int (*sq_open)(fmode_t);		/* optional */
     int (*state_info)(char *, size_t);	/* optional */
     void (*abort_read)(void);		/* optional */
     int min_dsp_speed;
@@ -235,7 +235,7 @@
      */
     int active;
     wait_queue_head_t action_queue, open_queue, sync_queue;
-    int open_mode;
+    fmode_t open_mode;
     int busy, syncing, xruns, died;
 };
 
diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c
index 285239d..4d45bd6 100644
--- a/sound/oss/dmasound/dmasound_atari.c
+++ b/sound/oss/dmasound/dmasound_atari.c
@@ -143,7 +143,7 @@
 static int TTMixerIoctl(u_int cmd, u_long arg);
 static int FalconMixerIoctl(u_int cmd, u_long arg);
 static int AtaWriteSqSetup(void);
-static int AtaSqOpen(mode_t mode);
+static int AtaSqOpen(fmode_t mode);
 static int TTStateInfo(char *buffer, size_t space);
 static int FalconStateInfo(char *buffer, size_t space);
 
@@ -1461,7 +1461,7 @@
 	return 0 ;
 }
 
-static int AtaSqOpen(mode_t mode)
+static int AtaSqOpen(fmode_t mode)
 {
 	write_sq_ignore_int = 1;
 	return 0 ;
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
index 95fc5c6..b8239f3 100644
--- a/sound/oss/dmasound/dmasound_core.c
+++ b/sound/oss/dmasound/dmasound_core.c
@@ -212,7 +212,7 @@
 #endif /* MODULE */
 
 /* control over who can modify resources shared between play/record */
-static mode_t shared_resource_owner;
+static fmode_t shared_resource_owner;
 static int shared_resources_initialised;
 
     /*
@@ -668,7 +668,7 @@
 
 #if 0 /* blocking open() */
 static inline void sq_wake_up(struct sound_queue *sq, struct file *file,
-			      mode_t mode)
+			      fmode_t mode)
 {
 	if (file->f_mode & mode) {
 		sq->busy = 0; /* CHECK: IS THIS OK??? */
@@ -677,7 +677,7 @@
 }
 #endif
 
-static int sq_open2(struct sound_queue *sq, struct file *file, mode_t mode,
+static int sq_open2(struct sound_queue *sq, struct file *file, fmode_t mode,
 		    int numbufs, int bufsize)
 {
 	int rc = 0;
@@ -891,10 +891,10 @@
    is the owner - if we have problems.
 */
 
-static int shared_resources_are_mine(mode_t md)
+static int shared_resources_are_mine(fmode_t md)
 {
 	if (shared_resource_owner)
-		return (shared_resource_owner & md ) ;
+		return (shared_resource_owner & md) != 0;
 	else {
 		shared_resource_owner = md ;
 		return 1 ;
diff --git a/sound/oss/msnd.h b/sound/oss/msnd.h
index 61b3955..c8be47e 100644
--- a/sound/oss/msnd.h
+++ b/sound/oss/msnd.h
@@ -211,7 +211,7 @@
 
 	/* State variables */
 	enum { msndClassic, msndPinnacle } type;
-	mode_t mode;
+	fmode_t mode;
 	unsigned long flags;
 #define F_RESETTING			0
 #define F_HAVEDIGITAL			1
diff --git a/sound/oss/sound_config.h b/sound/oss/sound_config.h
index 1a00a32..55271fb 100644
--- a/sound/oss/sound_config.h
+++ b/sound/oss/sound_config.h
@@ -110,24 +110,16 @@
 #define OPEN_WRITE	PCM_ENABLE_OUTPUT
 #define OPEN_READWRITE	(OPEN_READ|OPEN_WRITE)
 
-#if OPEN_READ == FMODE_READ && OPEN_WRITE == FMODE_WRITE
-
 static inline int translate_mode(struct file *file)
 {
-	return file->f_mode;
+	if (OPEN_READ == (__force int)FMODE_READ &&
+	    OPEN_WRITE == (__force int)FMODE_WRITE)
+		return (__force int)(file->f_mode & (FMODE_READ | FMODE_WRITE));
+	else
+		return ((file->f_mode & FMODE_READ) ? OPEN_READ : 0) |
+			((file->f_mode & FMODE_WRITE) ? OPEN_WRITE : 0);
 }
 
-#else
-
-static inline int translate_mode(struct file *file)
-{
-	return ((file->f_mode & FMODE_READ) ? OPEN_READ : 0) |
-		((file->f_mode & FMODE_WRITE) ? OPEN_WRITE : 0);
-}
-
-#endif
-
-
 #include "sound_calls.h"
 #include "dev_table.h"
 
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c
index 044453a..41562ec 100644
--- a/sound/oss/swarm_cs4297a.c
+++ b/sound/oss/swarm_cs4297a.c
@@ -295,7 +295,7 @@
 	struct mutex open_mutex;
 	struct mutex open_sem_adc;
 	struct mutex open_sem_dac;
-	mode_t open_mode;
+	fmode_t open_mode;
 	wait_queue_head_t open_wait;
 	wait_queue_head_t open_wait_adc;
 	wait_queue_head_t open_wait_dac;
diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c
index dcbb3f7..78b8acc 100644
--- a/sound/oss/vwsnd.c
+++ b/sound/oss/vwsnd.c
@@ -1509,7 +1509,7 @@
 	struct mutex open_mutex;
 	struct mutex io_mutex;
 	struct mutex mix_mutex;
-	mode_t		open_mode;
+	fmode_t		open_mode;
 	wait_queue_head_t open_wait;
 
 	lithium_t	lith;