From d23cd508d37c0fed10ff47b96b390e8711e5d0ce Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 15 Dec 2008 10:53:10 +0100 Subject: [PATCH] HOSTFS: Pass fcntl locks down to the hostfs Signed-off-by: Stefan Metzmacher --- fs/hostfs/hostfs.h | 7 +++++++ fs/hostfs/hostfs_kern.c | 36 ++++++++++++++++++++++++++++++++++++ fs/hostfs/hostfs_user.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 0 deletions(-) diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h index 2f34f8f..3f6fd35 100644 --- a/fs/hostfs/hostfs.h +++ b/fs/hostfs/hostfs.h @@ -88,5 +88,12 @@ extern int do_statfs(char *root, long *bsize_out, long long *blocks_out, long long *files_out, long long *ffree_out, void *fsid_out, int fsid_size, long *namelen_out, long *spare_out); +extern int getlk_file(int fd, unsigned char *type, + unsigned long long *start, + unsigned long long *end, + unsigned int *pid); +extern int setlk_file(int fd, unsigned char type, + unsigned long long start, + unsigned long long end); #endif diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 3a31451..8e61611 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -415,6 +415,41 @@ int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync) return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync); } +int hostfs_lock(struct file *filp, int cmd, struct file_lock *fl) +{ + struct inode *inode = filp->f_mapping->host; + int ret = -ENOLCK; + + printk("HOSTFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n", + filp->f_path.dentry->d_parent->d_name.name, + filp->f_path.dentry->d_name.name, + fl->fl_type, fl->fl_flags, + (long long)fl->fl_start, (long long)fl->fl_end); + + if (IS_GETLK(cmd)) { + unsigned char type; + unsigned long long start; + unsigned long long end; + unsigned int pid; + ret = getlk_file(HOSTFS_I(inode)->fd, + &type, &start, &end, &pid); + fl->fl_type = type; + if (type != F_UNLCK) { + fl->fl_flags = 0;/*???*/ + fl->fl_start = start; + fl->fl_end = end; + fl->fl_pid = pid; + } + } else { + ret = setlk_file(HOSTFS_I(inode)->fd, + fl->fl_type, + fl->fl_start, + fl->fl_end); + } + + return ret; +} + static const struct file_operations hostfs_file_fops = { .llseek = generic_file_llseek, .read = do_sync_read, @@ -426,6 +461,7 @@ static const struct file_operations hostfs_file_fops = { .open = hostfs_file_open, .release = NULL, .fsync = hostfs_fsync, + .lock = hostfs_lock, }; static const struct file_operations hostfs_dir_fops = { diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c index b79424f..da5122b 100644 --- a/fs/hostfs/hostfs_user.c +++ b/fs/hostfs/hostfs_user.c @@ -429,3 +429,48 @@ int do_statfs(char *root, long *bsize_out, long long *blocks_out, spare_out[4] = buf.f_spare[4]; return 0; } + +int getlk_file(int fd, unsigned char *type, + unsigned long long *start, + unsigned long long *end, + unsigned int *pid) +{ + struct flock lock; + int err; + + err = fcntl(fd, F_GETLK64, &lock); + if (err < 0) { + return -errno; + } + + *type = lock.l_type; + if (lock.l_type != F_UNLCK) { + *start = lock.l_start; + *end = lock.l_start + lock.l_len; + *pid = lock.l_pid; + } + + return 0; +} + +int setlk_file(int fd, unsigned char type, + unsigned long long start, + unsigned long long end) +{ + struct flock lock; + int err; + + lock.l_type = type; + lock.l_whence = SEEK_SET; + lock.l_start = start; + lock.l_len = end - start; + lock.l_pid = 0; + + err = fcntl(fd, F_SETLK64, &lock); + if (err < 0) { + return -errno; + } + + return 0; +} + -- 1.5.4.3