diff options
author | Eric Wong <normalperson@yhbt.net> | 2013-05-30 03:50:45 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2013-05-30 03:50:45 +0000 |
commit | 43ab652e15b4bd0b4cebfe7170c27f312eceb306 (patch) | |
tree | 36f50266ea4d2ab52b37392f8ee20f6c47ebd195 /file.c | |
parent | d1c18e26b0cc05009199f3997f0d57b07cdaa331 (diff) | |
download | cmogstored-iosem.tar.gz |
This is similar to the AIO channels functionality in Perlbal, but implemented using semaphores to optimize for the uncontended case.
Diffstat (limited to 'file.c')
-rw-r--r-- | file.c | 108 |
1 files changed, 89 insertions, 19 deletions
@@ -19,27 +19,53 @@ bool mog_open_expire_retry(struct mog_svc *svc) /* path must be a free()-able pointer */ struct mog_fd * -mog_file_open_read(struct mog_svc *svc, char *path) +mog_file_open_read(struct mog_svc *svc, uint32_t mog_devid, char *path) { struct mog_fd *mfd; struct mog_file *mfile; - int fd = mog_open_read(svc, path); - - if (fd < 0 && mog_open_expire_retry(svc)) - fd = mog_open_read(svc, path); - - if (fd < 0) return NULL; + int fd; + struct mog_dev *dev = mog_dev_for(svc, mog_devid, false); + + mog_dev_wait(dev); + fd = mog_open_read(svc, path); + + if (fd < 0) { + mog_dev_post(dev); + if (mog_open_expire_retry(svc)) { + mog_dev_wait(dev); + fd = mog_open_read(svc, path); + if (fd < 0) + mog_dev_post(dev); + } + if (fd < 0) + return NULL; + } mfd = mog_fd_init(fd, MOG_FD_TYPE_FILE); mfile = &mfd->as.file; memset(mfile, 0, sizeof(struct mog_file)); mfile->fsize = -1; + mfile->dev = dev; + mfile->dev_held = true; mfile->svc = svc; return mfd; } +int mog_stat_req(struct mog_svc *svc, uint32_t mog_devid, + const char *path, struct stat *sb) +{ + struct mog_dev *dev = mog_dev_for(svc, mog_devid, false); + int rc; + + mog_dev_wait(dev); + rc = mog_stat(svc, path, sb); + mog_dev_post(dev); + + return rc; +} + static int mkpath_open_put(struct mog_svc *svc, char *path, int flags) { int fd = mog_open_put(svc, path, flags); @@ -59,36 +85,80 @@ static int mkpath_open_put(struct mog_svc *svc, char *path, int flags) /* path must be a free()-able pointer */ struct mog_fd * -mog_file_open_put(struct mog_svc *svc, char *path, int flags) +mog_file_open_put(struct mog_svc *svc, uint32_t mog_devid, char *path, + int flags) { struct mog_fd *mfd; struct mog_file *mfile; - int fd = mkpath_open_put(svc, path, flags); - - if (fd < 0 && mog_open_expire_retry(svc)) - fd = mkpath_open_put(svc, path, flags); - - if (fd < 0) return NULL; - + int fd; + struct mog_dev *dev = mog_dev_for(svc, mog_devid, false); + + mog_dev_wait(dev); + fd = mkpath_open_put(svc, path, flags); + + if (fd < 0) { + mog_dev_post(dev); + if (mog_open_expire_retry(svc)) { + mog_dev_wait(dev); + fd = mkpath_open_put(svc, path, flags); + if (fd < 0) + mog_dev_post(dev); + } + if (fd < 0) + return NULL; + } mfd = mog_fd_init(fd, MOG_FD_TYPE_FILE); mfile = &mfd->as.file; memset(mfile, 0, sizeof(struct mog_file)); mfile->svc = svc; + mfile->dev = dev; + mfile->dev_held = true; return mfd; } +void mog_file_post(struct mog_fd *mfd) +{ + struct mog_file *file = &mfd->as.file; + + assert(file->dev_held); + file->dev_held = false; + mog_dev_post(file->dev); +} + +void mog_file_wait(struct mog_fd *mfd) +{ + struct mog_file *file = &mfd->as.file; + + assert(!file->dev_held); + file->dev_held = true; + mog_dev_wait(file->dev); +} + +void mog_file_ensure_wait(struct mog_fd *mfd) +{ + struct mog_file *file = &mfd->as.file; + + if (!file->dev_held) { + file->dev_held = true; + mog_dev_wait(file->dev); + } +} + void mog_file_close(struct mog_fd *mfd) { - struct mog_file *mfile = &mfd->as.file; + struct mog_file *file = &mfd->as.file; assert(mfd->fd_type == MOG_FD_TYPE_FILE && "mog_fd is not a file"); + if (file->dev_held) + mog_dev_post(file->dev); + /* all of these may already be NULL */ - free(mfile->path); - free(mfile->tmppath); - mog_digest_destroy(&mfile->digest); + free(file->path); + free(file->tmppath); + mog_digest_destroy(&file->digest); mog_fd_put(mfd); } |