Changeset 04803bf in mainline for uspace/srv/bd/file_bd/file_bd.c


Ignore:
Timestamp:
2011-03-21T22:00:17Z (14 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
143932e
Parents:
b50b5af2 (diff), 7308e84 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes (needs fixes).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/bd/file_bd/file_bd.c

    rb50b5af2 r04803bf  
    4141#include <stdio.h>
    4242#include <unistd.h>
    43 #include <ipc/ipc.h>
    4443#include <ipc/bd.h>
    4544#include <async.h>
    4645#include <as.h>
    47 #include <fibril_sync.h>
     46#include <fibril_synch.h>
    4847#include <devmap.h>
    4948#include <sys/types.h>
     49#include <sys/typefmt.h>
    5050#include <errno.h>
    5151#include <bool.h>
    5252#include <task.h>
     53#include <macros.h>
    5354
    5455#define NAME "file_bd"
    5556
    56 static size_t comm_size;
     57#define DEFAULT_BLOCK_SIZE 512
     58
     59static size_t block_size;
     60static aoff64_t num_blocks;
    5761static FILE *img;
    5862
    59 static dev_handle_t dev_handle;
     63static devmap_handle_t devmap_handle;
    6064static fibril_mutex_t dev_lock;
    6165
     66static void print_usage(void);
    6267static int file_bd_init(const char *fname);
    6368static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
    64 static int file_bd_read(off_t blk_idx, size_t size, void *buf);
    65 static int file_bd_write(off_t blk_idx, size_t size, void *buf);
     69static int file_bd_read_blocks(uint64_t ba, size_t cnt, void *buf);
     70static int file_bd_write_blocks(uint64_t ba, size_t cnt, const void *buf);
    6671
    6772int main(int argc, char **argv)
    6873{
    6974        int rc;
     75        char *image_name;
     76        char *device_name;
    7077
    7178        printf(NAME ": File-backed block device driver\n");
    7279
    73         if (argc != 3) {
    74                 printf("Expected two arguments (image name, device name).\n");
     80        block_size = DEFAULT_BLOCK_SIZE;
     81
     82        ++argv; --argc;
     83        while (*argv != NULL && (*argv)[0] == '-') {
     84                /* Option */
     85                if (str_cmp(*argv, "-b") == 0) {
     86                        if (argc < 2) {
     87                                printf("Argument missing.\n");
     88                                print_usage();
     89                                return -1;
     90                        }
     91
     92                        rc = str_size_t(argv[1], NULL, 10, true, &block_size);
     93                        if (rc != EOK || block_size == 0) {
     94                                printf("Invalid block size '%s'.\n", argv[1]);
     95                                print_usage();
     96                                return -1;
     97                        }
     98                        ++argv; --argc;
     99                } else {
     100                        printf("Invalid option '%s'.\n", *argv);
     101                        print_usage();
     102                        return -1;
     103                }
     104                ++argv; --argc;
     105        }
     106
     107        if (argc < 2) {
     108                printf("Missing arguments.\n");
     109                print_usage();
    75110                return -1;
    76111        }
    77112
    78         if (file_bd_init(argv[1]) != EOK)
     113        image_name = argv[0];
     114        device_name = argv[1];
     115
     116        if (file_bd_init(image_name) != EOK)
    79117                return -1;
    80118
    81         rc = devmap_device_register(argv[2], &dev_handle);
     119        rc = devmap_device_register(device_name, &devmap_handle);
    82120        if (rc != EOK) {
    83                 devmap_hangup_phone(DEVMAP_DRIVER);
    84                 printf(NAME ": Unable to register device %s.\n",
    85                         argv[2]);
     121                printf(NAME ": Unable to register device '%s'.\n",
     122                        device_name);
    86123                return rc;
    87124        }
     
    95132}
    96133
     134static void print_usage(void)
     135{
     136        printf("Usage: " NAME " [-b <block_size>] <image_file> <device_name>\n");
     137}
     138
    97139static int file_bd_init(const char *fname)
    98140{
    99141        int rc;
     142        long img_size;
    100143
    101144        rc = devmap_driver_register(NAME, file_bd_connection);
     
    109152                return EINVAL;
    110153
     154        if (fseek(img, 0, SEEK_END) != 0) {
     155                fclose(img);
     156                return EIO;
     157        }
     158
     159        img_size = ftell(img);
     160        if (img_size < 0) {
     161                fclose(img);
     162                return EIO;
     163        }
     164
     165        num_blocks = img_size / block_size;
     166
    111167        fibril_mutex_initialize(&dev_lock);
    112168
     
    119175        ipc_callid_t callid;
    120176        ipc_call_t call;
    121         ipcarg_t method;
    122         int flags;
     177        sysarg_t method;
     178        size_t comm_size;
     179        unsigned int flags;
    123180        int retval;
    124         off_t idx;
    125         size_t size;
     181        uint64_t ba;
     182        size_t cnt;
    126183
    127184        /* Answer the IPC_M_CONNECT_ME_TO call. */
    128         ipc_answer_0(iid, EOK);
    129 
    130         if (!ipc_share_out_receive(&callid, &comm_size, &flags)) {
    131                 ipc_answer_0(callid, EHANGUP);
     185        async_answer_0(iid, EOK);
     186
     187        if (!async_share_out_receive(&callid, &comm_size, &flags)) {
     188                async_answer_0(callid, EHANGUP);
    132189                return;
    133190        }
     
    135192        fs_va = as_get_mappable_page(comm_size);
    136193        if (fs_va == NULL) {
    137                 ipc_answer_0(callid, EHANGUP);
     194                async_answer_0(callid, EHANGUP);
    138195                return;
    139196        }
    140197
    141         (void) ipc_share_out_finalize(callid, fs_va);
     198        (void) async_share_out_finalize(callid, fs_va);
    142199
    143200        while (1) {
    144201                callid = async_get_call(&call);
    145                 method = IPC_GET_METHOD(call);
     202                method = IPC_GET_IMETHOD(call);
    146203                switch (method) {
    147204                case IPC_M_PHONE_HUNGUP:
    148205                        /* The other side has hung up. */
    149                         ipc_answer_0(callid, EOK);
     206                        async_answer_0(callid, EOK);
    150207                        return;
    151                 case BD_READ_BLOCK:
    152                 case BD_WRITE_BLOCK:
    153                         idx = IPC_GET_ARG1(call);
    154                         size = IPC_GET_ARG2(call);
    155                         if (size > comm_size) {
    156                                 retval = EINVAL;
     208                case BD_READ_BLOCKS:
     209                        ba = MERGE_LOUP32(IPC_GET_ARG1(call),
     210                            IPC_GET_ARG2(call));
     211                        cnt = IPC_GET_ARG3(call);
     212                        if (cnt * block_size > comm_size) {
     213                                retval = ELIMIT;
    157214                                break;
    158215                        }
    159                         if (method == BD_READ_BLOCK)
    160                                 retval = file_bd_read(idx, size, fs_va);
    161                         else
    162                                 retval = file_bd_write(idx, size, fs_va);
     216                        retval = file_bd_read_blocks(ba, cnt, fs_va);
    163217                        break;
     218                case BD_WRITE_BLOCKS:
     219                        ba = MERGE_LOUP32(IPC_GET_ARG1(call),
     220                            IPC_GET_ARG2(call));
     221                        cnt = IPC_GET_ARG3(call);
     222                        if (cnt * block_size > comm_size) {
     223                                retval = ELIMIT;
     224                                break;
     225                        }
     226                        retval = file_bd_write_blocks(ba, cnt, fs_va);
     227                        break;
     228                case BD_GET_BLOCK_SIZE:
     229                        async_answer_1(callid, EOK, block_size);
     230                        continue;
     231                case BD_GET_NUM_BLOCKS:
     232                        async_answer_2(callid, EOK, LOWER32(num_blocks),
     233                            UPPER32(num_blocks));
     234                        continue;
    164235                default:
    165236                        retval = EINVAL;
    166237                        break;
    167238                }
    168                 ipc_answer_0(callid, retval);
    169         }
    170 }
    171 
    172 static int file_bd_read(off_t blk_idx, size_t size, void *buf)
     239                async_answer_0(callid, retval);
     240        }
     241}
     242
     243/** Read blocks from the device. */
     244static int file_bd_read_blocks(uint64_t ba, size_t cnt, void *buf)
    173245{
    174246        size_t n_rd;
     247        int rc;
     248
     249        /* Check whether access is within device address bounds. */
     250        if (ba + cnt > num_blocks) {
     251                printf(NAME ": Accessed blocks %" PRIuOFF64 "-%" PRIuOFF64 ", while "
     252                    "max block number is %" PRIuOFF64 ".\n", ba, ba + cnt - 1,
     253                    num_blocks - 1);
     254                return ELIMIT;
     255        }
    175256
    176257        fibril_mutex_lock(&dev_lock);
    177258
    178         fseek(img, blk_idx * size, SEEK_SET);
    179         n_rd = fread(buf, 1, size, img);
     259        clearerr(img);
     260        rc = fseek(img, ba * block_size, SEEK_SET);
     261        if (rc < 0) {
     262                fibril_mutex_unlock(&dev_lock);
     263                return EIO;
     264        }
     265
     266        n_rd = fread(buf, block_size, cnt, img);
    180267
    181268        if (ferror(img)) {
     
    186273        fibril_mutex_unlock(&dev_lock);
    187274
    188         if (n_rd < size)
    189                 return EINVAL;  /* Read beyond end of disk */
     275        if (n_rd < cnt)
     276                return EINVAL;  /* Read beyond end of device */
    190277
    191278        return EOK;
    192279}
    193280
    194 static int file_bd_write(off_t blk_idx, size_t size, void *buf)
     281/** Write blocks to the device. */
     282static int file_bd_write_blocks(uint64_t ba, size_t cnt, const void *buf)
    195283{
    196284        size_t n_wr;
     285        int rc;
     286
     287        /* Check whether access is within device address bounds. */
     288        if (ba + cnt > num_blocks) {
     289                printf(NAME ": Accessed blocks %" PRIuOFF64 "-%" PRIuOFF64 ", while "
     290                    "max block number is %" PRIuOFF64 ".\n", ba, ba + cnt - 1,
     291                    num_blocks - 1);
     292                return ELIMIT;
     293        }
    197294
    198295        fibril_mutex_lock(&dev_lock);
    199296
    200         fseek(img, blk_idx * size, SEEK_SET);
    201         n_wr = fread(buf, 1, size, img);
    202 
    203         if (ferror(img) || n_wr < size) {
     297        clearerr(img);
     298        rc = fseek(img, ba * block_size, SEEK_SET);
     299        if (rc < 0) {
     300                fibril_mutex_unlock(&dev_lock);
     301                return EIO;
     302        }
     303
     304        n_wr = fwrite(buf, block_size, cnt, img);
     305
     306        if (ferror(img) || n_wr < cnt) {
    204307                fibril_mutex_unlock(&dev_lock);
    205308                return EIO;     /* Write error */
     309        }
     310
     311        if (fflush(img) != 0) {
     312                fibril_mutex_unlock(&dev_lock);
     313                return EIO;
    206314        }
    207315
Note: See TracChangeset for help on using the changeset viewer.