Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
996395f2
Commit
996395f2
authored
Oct 28, 2002
by
Alexander Viro
Committed by
James Bottomley
Oct 28, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] mtdblock_ro fixes (based on patch from rmk)
* compile fixes * switched to private queue * set ->queue
parent
0ffbe56a
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
172 additions
and
165 deletions
+172
-165
drivers/mtd/mtdblock_ro.c
drivers/mtd/mtdblock_ro.c
+172
-165
No files found.
drivers/mtd/mtdblock_ro.c
View file @
996395f2
/*
* $Id: mtdblock_ro.c,v 1.
9 2001/10/02 15:05:11 dwmw2
Exp $
* $Id: mtdblock_ro.c,v 1.
13 2002/03/11 16:03:29 sioux
Exp $
*
* Read-only
version of the mtdblock device, without the
*
read/erase/modify/writeback stuff
* Read-only
flash, read-write RAM version of the mtdblock device,
*
without caching.
*/
#ifdef MTDBLOCK_DEBUG
...
...
@@ -21,216 +21,226 @@
#define LOCAL_END_REQUEST
#define MAJOR_NR MTD_BLOCK_MAJOR
#define DEVICE_NAME "mtdblock"
#define DEVICE_NR(device) (device)
#include <linux/blk.h>
#define RQFUNC_ARG request_queue_t *q
#ifdef MTDBLOCK_DEBUG
static
int
debug
=
MTDBLOCK_DEBUG
;
MODULE_PARM
(
debug
,
"i"
);
#endif
static
struct
gendisk
*
mtd_disks
[
MAX_MTD_DEVICES
];
struct
mtdro_dev
{
struct
gendisk
*
disk
;
struct
mtd_info
*
mtd
;
int
open
;
};
static
struct
mtdro_dev
mtd_dev
[
MAX_MTD_DEVICES
];
static
DECLARE_MUTEX
(
mtd_sem
);
static
struct
request_queue
mtdro_queue
;
static
spinlock_t
mtdro_lock
=
SPIN_LOCK_UNLOCKED
;
static
int
mtdblock_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
mtd_info
*
mtd
=
NULL
;
int
dev
=
minor
(
inode
->
i_rdev
);
struct
gendisk
*
disk
=
mtd_disks
[
dev
];
struct
mtdro_dev
*
mdev
=
inode
->
i_bdev
->
bd_disk
->
private_data
;
int
ret
=
0
;
DEBUG
(
1
,
"mtdblock_open
\n
"
);
mtd
=
get_mtd_device
(
NULL
,
dev
);
if
(
!
mtd
)
return
-
EINVAL
;
if
(
MTD_ABSENT
==
mtd
->
type
)
{
put_mtd_device
(
mtd
);
return
-
EINVAL
;
down
(
&
mtd_sem
);
if
(
mdev
->
mtd
==
NULL
)
{
mdev
->
mtd
=
get_mtd_device
(
NULL
,
minor
(
inode
->
i_rdev
));
if
(
!
mdev
->
mtd
||
mdev
->
mtd
->
type
==
MTD_ABSENT
)
{
if
(
mdev
->
mtd
)
put_mtd_device
(
mdev
->
mtd
);
ret
=
-
ENODEV
;
}
}
set_capacity
(
disk
,
mtd
->
size
>>
9
);
add_disk
(
disk
);
if
(
ret
==
0
)
{
set_device_ro
(
inode
->
i_rdev
,
!
(
mdev
->
mtd
->
flags
&
MTD_CAP_RAM
));
mdev
->
open
++
;
}
up
(
&
mtd_sem
);
DEBUG
(
1
,
"
ok
\n
"
);
DEBUG
(
1
,
"
%s
\n
"
,
ret
?
"ok"
:
"nodev
"
);
return
0
;
return
ret
;
}
static
release_t
mtdblock_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
int
dev
;
struct
mtd_info
*
mtd
;
struct
mtdro_dev
*
mdev
=
inode
->
i_bdev
->
bd_disk
->
private_data
;
DEBUG
(
1
,
"mtdblock_release
\n
"
);
if
(
inode
==
NULL
)
release_return
(
-
ENODEV
);
dev
=
minor
(
inode
->
i_rdev
);
mtd
=
__get_mtd_device
(
NULL
,
dev
);
if
(
!
mtd
)
{
printk
(
KERN_WARNING
"MTD device is absent on mtd_release!
\n
"
);
release_return
(
-
ENODEV
);
}
down
(
&
mtd_sem
);
if
(
mdev
->
open
--
==
0
)
{
struct
mtd_info
*
mtd
=
mdev
->
mtd
;
del_gendisk
(
mtd_disks
[
dev
]);
if
(
mtd
->
sync
)
mtd
->
sync
(
mtd
);
mdev
->
mtd
=
NULL
;
if
(
mtd
->
sync
)
mtd
->
sync
(
mtd
);
put_mtd_device
(
mtd
);
put_mtd_device
(
mtd
);
}
up
(
&
mtd_sem
);
DEBUG
(
1
,
"ok
\n
"
);
release_return
(
0
);
}
static
inline
void
mtdblock_end_request
(
struct
request
*
req
,
int
uptodate
)
static
void
mtdblock_request
(
request_queue_t
*
q
)
{
if
(
end_that_request_first
(
req
,
uptodate
,
req
->
hard_cur_sectors
))
return
;
blkdev_dequeue_request
(
req
);
end_that_request_last
(
req
);
}
static
void
mtdblock_request
(
RQFUNC_ARG
)
{
struct
request
*
current_request
;
unsigned
int
res
=
0
;
struct
mtd_info
*
mtd
;
while
(
1
)
{
/* Grab the Request and unlink it from the request list, we
will execute a return if we are done. */
if
(
blk_queue_empty
(
QUEUE
))
return
;
current_request
=
CURRENT
;
if
(
minor
(
current_request
->
rq_dev
)
>=
MAX_MTD_DEVICES
)
{
printk
(
"mtd: Unsupported device!
\n
"
);
mtdblock_end_request
(
current_request
,
0
);
continue
;
}
// Grab our MTD structure
mtd
=
__get_mtd_device
(
NULL
,
minor
(
current_request
->
rq_dev
));
if
(
!
mtd
)
{
printk
(
"MTD device %s doesn't appear to exist any more
\n
"
,
kdevname
(
DEVICE_NR
(
CURRENT
->
rq_dev
)));
mtdblock_end_request
(
current_request
,
0
);
}
if
(
current_request
->
sector
<<
9
>
mtd
->
size
||
(
current_request
->
sector
+
current_request
->
nr_sectors
)
<<
9
>
mtd
->
size
)
{
printk
(
"mtd: Attempt to read past end of device!
\n
"
);
printk
(
"size: %x, sector: %lx, nr_sectors %lx
\n
"
,
mtd
->
size
,
current_request
->
sector
,
current_request
->
nr_sectors
);
mtdblock_end_request
(
current_request
,
0
);
continue
;
}
while
(
!
blk_queue_empty
(
q
))
{
struct
request
*
req
=
elv_next_request
(
q
);
struct
mtdro_dev
*
mdev
=
req
->
rq_disk
->
private_data
;
struct
mtd_info
*
mtd
=
mdev
->
mtd
;
unsigned
int
res
;
if
(
!
(
req
->
flags
&
REQ_CMD
))
{
res
=
0
;
goto
end_req
;
}
if
((
req
->
sector
+
req
->
current_nr_sectors
)
>
(
mtd
->
size
>>
9
))
{
printk
(
"mtd: Attempt to read past end of device!
\n
"
);
printk
(
"size: %x, sector: %lx, nr_sectors: %x
\n
"
,
mtd
->
size
,
req
->
sector
,
req
->
current_nr_sectors
);
res
=
0
;
goto
end_req
;
}
/* Remove the request we are handling from the request list so nobody messes
with it */
/* Now drop the lock that the ll_rw_blk functions grabbed for us
and process the request. This is necessary due to the extreme time
we spend processing it. */
spin_unlock_irq
(
&
io_request_lock
);
// Handle the request
switch
(
current_request
->
cmd
)
{
size_t
retlen
;
case
READ
:
if
(
MTD_READ
(
mtd
,
current_request
->
sector
<<
9
,
current_request
->
nr_sectors
<<
9
,
&
retlen
,
current_request
->
buffer
)
==
0
)
res
=
1
;
else
res
=
0
;
break
;
case
WRITE
:
/* printk("mtdblock_request WRITE sector=%d(%d)\n",current_request->sector,
current_request->nr_sectors);
*/
// Read only device
if
((
mtd
->
flags
&
MTD_CAP_RAM
)
==
0
)
{
res
=
0
;
break
;
}
// Do the writ
e
if
(
MTD_WRITE
(
mtd
,
current_request
->
sector
<<
9
,
current_request
->
nr_sectors
<<
9
,
&
retlen
,
current_request
->
buffer
)
==
0
)
res
=
1
;
else
res
=
0
;
break
;
// Shouldn't happen
default:
printk
(
"mtd: unknown request
\n
"
);
break
;
}
// Grab the lock and re-thread the item onto the linked list
spin_lock_irq
(
&
io_request_lock
);
mtdblock_end_request
(
current_request
,
res
);
}
/* Now drop the lock that the ll_rw_blk functions grabbed for
us and process the request. This is necessary due to the
extreme time we spend processing it. */
spin_unlock_irq
(
q
->
queue_lock
);
/* Handle the request */
switch
(
rq_data_dir
(
req
))
{
size_t
retlen
;
case
READ
:
if
(
MTD_READ
(
mtd
,
req
->
sector
<<
9
,
req
->
current_nr_sectors
<<
9
,
&
retlen
,
req
->
buffer
)
==
0
)
res
=
1
;
else
res
=
0
;
break
;
case
WRITE
:
/* printk("mtdblock_request WRITE sector=%d(%d)\n",
req->sector, req->current_nr_sectors);
*/
/* Read only device */
if
((
mtd
->
flags
&
MTD_CAP_RAM
)
==
0
)
{
res
=
0
;
break
;
}
/* Do the write */
if
(
MTD_WRITE
(
mtd
,
req
->
sector
<<
9
,
req
->
current_nr_sectors
<<
9
,
&
retlen
,
req
->
buffer
)
==
0
)
res
=
1
;
els
e
res
=
0
;
break
;
/* Shouldn't happen */
default:
printk
(
"mtd: unknown request
\n
"
)
;
res
=
0
;
break
;
}
/* Grab the lock and re-thread the item onto the linked list */
spin_lock_irq
(
q
->
queue_lock
)
;
end_req:
if
(
!
end_that_request_first
(
req
,
res
,
req
->
hard_cur_sectors
))
{
blkdev_dequeue_request
(
req
);
end_that_request_last
(
req
);
}
}
}
static
int
mtdblock_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
mtd_info
*
mtd
;
mtd
=
__get_mtd_device
(
NULL
,
minor
(
inode
->
i_rdev
));
struct
mtdro_dev
*
mdev
=
inode
->
i_bdev
->
bd_disk
->
private_data
;
if
(
!
mtd
||
cmd
!=
BLKFLSBUF
)
if
(
cmd
!=
BLKFLSBUF
)
return
-
EINVAL
;
fsync_bdev
(
inode
->
i_bdev
);
invalidate_bdev
(
inode
->
i_bdev
,
0
);
if
(
mtd
->
sync
)
mtd
->
sync
(
mtd
);
if
(
mdev
->
mtd
->
sync
)
mdev
->
mtd
->
sync
(
mdev
->
mtd
);
return
0
;
}
static
struct
block_device_operations
mtd_fops
=
{
static
struct
block_device_operations
mtd_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
mtdblock_open
,
.
release
=
mtdblock_release
,
.
ioctl
=
mtdblock_ioctl
};
int
__init
init_mtdblock
(
void
)
/* Called with mtd_table_mutex held. */
static
void
mtd_notify_add
(
struct
mtd_info
*
mtd
)
{
int
err
=
-
ENOMEM
;
int
i
;
struct
gendisk
*
disk
;
for
(
i
=
0
;
i
<
MAX_MTD_DEVICES
;
i
++
)
{
struct
gendisk
*
disk
=
alloc_disk
(
1
);
if
(
!
disk
)
goto
out
;
if
(
!
mtd
||
mtd
->
type
==
MTD_ABSENT
||
mtd
->
index
>=
MAX_MTD_DEVICES
)
return
;
disk
=
alloc_disk
(
1
);
if
(
disk
)
{
disk
->
major
=
MAJOR_NR
;
disk
->
first_minor
=
i
;
sprintf
(
disk
->
disk_name
,
"mtdblock%d"
,
i
);
disk
->
first_minor
=
mtd
->
index
;
disk
->
fops
=
&
mtd_fops
;
mtd_disks
[
i
]
=
disk
;
sprintf
(
disk
->
disk_name
,
"mtdblock%d"
,
mtd
->
index
);
mtd_dev
[
mtd
->
index
].
disk
=
disk
;
set_capacity
(
disk
,
mtd
->
size
/
512
);
disk
->
queue
=
&
mtdro_queue
;
disk
->
private_data
=
&
mtd_dev
[
mtd
->
index
];
add_disk
(
disk
);
}
}
/* Called with mtd_table_mutex held. */
static
void
mtd_notify_remove
(
struct
mtd_info
*
mtd
)
{
struct
mtdro_dev
*
mdev
;
struct
gendisk
*
disk
;
if
(
!
mtd
||
mtd
->
type
==
MTD_ABSENT
||
mtd
->
index
>=
MAX_MTD_DEVICES
)
return
;
mdev
=
&
mtd_dev
[
mtd
->
index
];
disk
=
mdev
->
disk
;
mdev
->
disk
=
NULL
;
if
(
disk
)
{
del_gendisk
(
disk
);
put_disk
(
disk
);
}
}
static
struct
mtd_notifier
notifier
=
{
.
add
=
mtd_notify_add
,
.
remove
=
mtd_notify_remove
,
};
int
__init
init_mtdblock
(
void
)
{
int
err
;
if
(
register_blkdev
(
MAJOR_NR
,
DEVICE_NAME
,
&
mtd_fops
))
{
printk
(
KERN_NOTICE
"Can't allocate major number %d for Memory Technology Devices.
\n
"
,
...
...
@@ -239,21 +249,18 @@ int __init init_mtdblock(void)
goto
out
;
}
blk_init_queue
(
BLK_DEFAULT_QUEUE
(
MAJOR_NR
),
&
mtdblock_request
);
return
0
;
out:
while
(
i
--
)
put_disk
(
mtd_disks
[
i
]);
blk_init_queue
(
&
mtdro_queue
,
&
mtdblock_request
,
&
mtdro_lock
);
register_mtd_user
(
&
notifier
);
err
=
0
;
out:
return
err
;
}
static
void
__exit
cleanup_mtdblock
(
void
)
{
int
i
;
unregister_mtd_user
(
&
notifier
)
;
unregister_blkdev
(
MAJOR_NR
,
DEVICE_NAME
);
blk_cleanup_queue
(
BLK_DEFAULT_QUEUE
(
MAJOR_NR
));
for
(
i
=
0
;
i
<
MAX_MTD_DEVICES
;
i
++
)
put_disk
(
mtd_disks
[
i
]);
blk_cleanup_queue
(
&
mtdro_queue
);
}
module_init
(
init_mtdblock
);
...
...
@@ -262,4 +269,4 @@ module_exit(cleanup_mtdblock);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Erwin Authried <eauth@softsys.co.at> et al."
);
MODULE_DESCRIPTION
(
"Simple
read-only
block device emulation access to MTD devices"
);
MODULE_DESCRIPTION
(
"Simple
uncached
block device emulation access to MTD devices"
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment