From 69886e676e89534953b12df77382504a7731f7bb Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 27 Feb 2015 22:55:20 +0100 Subject: hostfs: hostfs_file_open: Switch to data locking model Instead of serializing hostfs_file_open() we can use a per inode mutex to protect ->mode. Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index fd62cae0fdcb..104d58d2c78c 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -24,6 +24,7 @@ struct hostfs_inode_info { int fd; fmode_t mode; struct inode vfs_inode; + struct mutex open_mutex; }; static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode) @@ -225,6 +226,7 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb) hi->fd = -1; hi->mode = 0; inode_init_once(&hi->vfs_inode); + mutex_init(&hi->open_mutex); return &hi->vfs_inode; } @@ -295,7 +297,6 @@ static int hostfs_readdir(struct file *file, struct dir_context *ctx) static int hostfs_file_open(struct inode *ino, struct file *file) { - static DEFINE_MUTEX(open_mutex); char *name; fmode_t mode = 0; int err; @@ -324,15 +325,15 @@ retry: if (fd < 0) return fd; - mutex_lock(&open_mutex); + mutex_lock(&HOSTFS_I(ino)->open_mutex); /* somebody else had handled it first? */ if ((mode & HOSTFS_I(ino)->mode) == mode) { - mutex_unlock(&open_mutex); + mutex_unlock(&HOSTFS_I(ino)->open_mutex); return 0; } if ((mode | HOSTFS_I(ino)->mode) != mode) { mode |= HOSTFS_I(ino)->mode; - mutex_unlock(&open_mutex); + mutex_unlock(&HOSTFS_I(ino)->open_mutex); close_file(&fd); goto retry; } @@ -342,12 +343,12 @@ retry: err = replace_file(fd, HOSTFS_I(ino)->fd); close_file(&fd); if (err < 0) { - mutex_unlock(&open_mutex); + mutex_unlock(&HOSTFS_I(ino)->open_mutex); return err; } } HOSTFS_I(ino)->mode = mode; - mutex_unlock(&open_mutex); + mutex_unlock(&HOSTFS_I(ino)->open_mutex); return 0; } -- cgit v1.2.3 From af9556586a906106453ff7df8bcacf795b2b7d0a Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 27 Feb 2015 22:56:28 +0100 Subject: hostfs: hostfs_file_open: Fix a fd leak in hostfs_file_open In case of a race between to callers of hostfs_file_open() it can happen that a file describtor is leaked. Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 104d58d2c78c..112ba5aa0848 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -329,6 +329,7 @@ retry: /* somebody else had handled it first? */ if ((mode & HOSTFS_I(ino)->mode) == mode) { mutex_unlock(&HOSTFS_I(ino)->open_mutex); + close_file(&fd); return 0; } if ((mode | HOSTFS_I(ino)->mode) != mode) { -- cgit v1.2.3 From 4c6dcafc691bbd1e3258b623121d8859d3213ae9 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 2 Mar 2015 00:09:33 +0100 Subject: hostfs: Allow fsync on directories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Historically hostfs did not open directories on the host filesystem for performance and memory reasons. But it turned out that this optimization has a drawback. Calling fsync() on a hostfs directory returns immediately with -EINVAL as fsync is not implemented. While this is behavior is strictly speaking correct common userspace like dpkg(1) stumbles over that and makes it impossible to use hostfs as root filesystem. The fix is easy, wire up the existing host open/fsync functions to the directory file operations. Reported-by: Daniel Gröber Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 112ba5aa0848..92b008f564a4 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -295,7 +295,7 @@ static int hostfs_readdir(struct file *file, struct dir_context *ctx) return 0; } -static int hostfs_file_open(struct inode *ino, struct file *file) +static int hostfs_open(struct inode *ino, struct file *file) { char *name; fmode_t mode = 0; @@ -386,7 +386,7 @@ static const struct file_operations hostfs_file_fops = { .write_iter = generic_file_write_iter, .write = new_sync_write, .mmap = generic_file_mmap, - .open = hostfs_file_open, + .open = hostfs_open, .release = hostfs_file_release, .fsync = hostfs_fsync, }; @@ -395,6 +395,8 @@ static const struct file_operations hostfs_dir_fops = { .llseek = generic_file_llseek, .iterate = hostfs_readdir, .read = generic_read_dir, + .open = hostfs_open, + .fsync = hostfs_fsync, }; static int hostfs_writepage(struct page *page, struct writeback_control *wbc) -- cgit v1.2.3 From 2ad2dca6fd28cf24ed64110a8b374fc838838c81 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 2 Mar 2015 00:10:25 +0100 Subject: hostfs: Handle bogus st.mode Make sure that we return EIO if one passes an invalid st.mode into hostfs. Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 92b008f564a4..8163aac81c21 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -534,11 +534,13 @@ static int read_name(struct inode *ino, char *name) init_special_inode(ino, st.mode & S_IFMT, rdev); ino->i_op = &hostfs_iops; break; - - default: + case S_IFREG: ino->i_op = &hostfs_iops; ino->i_fop = &hostfs_file_fops; ino->i_mapping->a_ops = &hostfs_aops; + break; + default: + return -EIO; } ino->i_ino = st.ino; -- cgit v1.2.3 From 41761ddfaecb30e1f0ecac4ce568e3e641d10bec Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 3 Mar 2015 21:40:55 +0100 Subject: hostfs: Make hostfs_readpage more readable ...to make life easier for future readers of that code. Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 8163aac81c21..67e556cbfd82 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -439,25 +439,27 @@ static int hostfs_readpage(struct file *file, struct page *page) { char *buffer; long long start; - int err = 0; + int bytes_read, ret; start = (long long) page->index << PAGE_CACHE_SHIFT; buffer = kmap(page); - err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer, + bytes_read = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer, PAGE_CACHE_SIZE); - if (err < 0) + if (bytes_read < 0) { + ret = bytes_read; goto out; + } - memset(&buffer[err], 0, PAGE_CACHE_SIZE - err); + memset(buffer + bytes_read, 0, PAGE_CACHE_SIZE - bytes_read); flush_dcache_page(page); SetPageUptodate(page); if (PageError(page)) ClearPageError(page); - err = 0; + ret = 0; out: kunmap(page); unlock_page(page); - return err; + return ret; } static int hostfs_write_begin(struct file *file, struct address_space *mapping, -- cgit v1.2.3 From aad50b1e06081de0e4ff25335ab6f52e58bfcef1 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 3 Mar 2015 23:41:52 +0100 Subject: hostfs: Add a BUG_ON to detect behavior changes of dentry_path_raw() hostfs' __dentry_name() relies on the fact that dentry_path_raw() will place the path name at the end of the provided buffer. While this is okay, add a BUG_ON() to detect behavior changes as soon as possible. Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 67e556cbfd82..3082a7e715dd 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -93,6 +93,13 @@ static char *__dentry_name(struct dentry *dentry, char *name) __putname(name); return NULL; } + + /* + * This function relies on the fact that dentry_path_raw() will place + * the path name at the end of the provided buffer. + */ + BUG_ON(p + strlen(p) + 1 != name + PATH_MAX); + strlcpy(name, root, PATH_MAX); if (len > p - name) { __putname(name); -- cgit v1.2.3 From c278e81b8a0291f5adce43c4613ad569d76dc384 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 3 Mar 2015 23:42:25 +0100 Subject: hostfs: Remove open coded strcpy() Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 3082a7e715dd..7260f162db41 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -105,11 +105,10 @@ static char *__dentry_name(struct dentry *dentry, char *name) __putname(name); return NULL; } - if (p > name + len) { - char *s = name + len; - while ((*s++ = *p++) != '\0') - ; - } + + if (p > name + len) + strcpy(name + len, p); + return name; } -- cgit v1.2.3 From 7c9509924c711d45d7932548d2c632f44f64e7e3 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 3 Mar 2015 23:55:49 +0100 Subject: hostfs: Use __getname() in follow_link Be consistent with all other functions in hostfs and just use __getname(). Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 7260f162db41..c60d886230ef 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -142,21 +142,19 @@ static char *follow_link(char *link) int len, n; char *name, *resolved, *end; - len = 64; - while (1) { + name = __getname(); + if (!name) { n = -ENOMEM; - name = kmalloc(len, GFP_KERNEL); - if (name == NULL) - goto out; - - n = hostfs_do_readlink(link, name, len); - if (n < len) - break; - len *= 2; - kfree(name); + goto out_free; } + + n = hostfs_do_readlink(link, name, PATH_MAX); if (n < 0) goto out_free; + else if (n == PATH_MAX) { + n = -E2BIG; + goto out_free; + } if (*name == '/') return name; @@ -175,13 +173,12 @@ static char *follow_link(char *link) } sprintf(resolved, "%s%s", link, name); - kfree(name); + __putname(name); kfree(link); return resolved; out_free: - kfree(name); - out: + __putname(name); return ERR_PTR(n); } -- cgit v1.2.3 From 7f74a6687992f29c14b98a7bc8d5d924d5883434 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 4 Mar 2015 00:00:54 +0100 Subject: hostfs: Report append flag in ->show_options() hostfs has an "append" mount option. Report it. Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index c60d886230ef..06b3e3f47c0e 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -262,6 +262,9 @@ static int hostfs_show_options(struct seq_file *seq, struct dentry *root) if (strlen(root_path) > offset) seq_printf(seq, ",%s", root_path + offset); + if (append) + seq_puts(seq, ",append"); + return 0; } -- cgit v1.2.3 From 112a5da717f86250bc6be2c63e7af174be7c5507 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 4 Mar 2015 00:05:11 +0100 Subject: hostfs: Remove superfluous test in hostfs_open() Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 06b3e3f47c0e..8bbceae5ed03 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -318,9 +318,7 @@ retry: if (mode & FMODE_READ) r = 1; if (mode & FMODE_WRITE) - w = 1; - if (w) - r = 1; + r = w = 1; name = dentry_name(file->f_path.dentry); if (name == NULL) -- cgit v1.2.3 From a9d1958b4b9a688becceda44938baac99a62fbd7 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 4 Mar 2015 22:39:48 +0100 Subject: hostfs: hostfs_open: Reset open flags upon each retry ...otherwise we might end up with an incorrect mode mode. Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 8bbceae5ed03..80ced3dc84ae 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -315,6 +315,8 @@ static int hostfs_open(struct inode *ino, struct file *file) mode |= HOSTFS_I(ino)->mode; retry: + r = w = 0; + if (mode & FMODE_READ) r = 1; if (mode & FMODE_WRITE) -- cgit v1.2.3 From bd1052a245c004068a7123aa077c576be64639e4 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 4 Mar 2015 00:06:38 +0100 Subject: hostfs: Remove superfluous initializations in hostfs_open() Only initialize what we really need. Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 80ced3dc84ae..cf80a30058b0 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -304,9 +304,9 @@ static int hostfs_readdir(struct file *file, struct dir_context *ctx) static int hostfs_open(struct inode *ino, struct file *file) { char *name; - fmode_t mode = 0; + fmode_t mode; int err; - int r = 0, w = 0, fd; + int r, w, fd; mode = file->f_mode & (FMODE_READ | FMODE_WRITE); if ((mode & HOSTFS_I(ino)->mode) == mode) -- cgit v1.2.3 From b86b413a321105cb75373b48fd7ba53fcbc7ec4c Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 4 Mar 2015 12:44:03 +0100 Subject: hostfs: Set page flags in hostfs_readpage() correctly In case of an error set the page error flag and clear the up-to-date flag. If the read was successful clear the error flag unconditionally. Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index cf80a30058b0..f1547479e62e 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -445,24 +445,26 @@ static int hostfs_readpage(struct file *file, struct page *page) { char *buffer; long long start; - int bytes_read, ret; + int bytes_read, ret = 0; start = (long long) page->index << PAGE_CACHE_SHIFT; buffer = kmap(page); bytes_read = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer, PAGE_CACHE_SIZE); if (bytes_read < 0) { + ClearPageUptodate(page); + SetPageError(page); ret = bytes_read; goto out; } memset(buffer + bytes_read, 0, PAGE_CACHE_SIZE - bytes_read); - flush_dcache_page(page); + ClearPageError(page); SetPageUptodate(page); - if (PageError(page)) ClearPageError(page); - ret = 0; + out: + flush_dcache_page(page); kunmap(page); unlock_page(page); return ret; -- cgit v1.2.3 From af6aa1b9cad7350d675fe3523ab062e0e4c829cb Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 4 Mar 2015 20:58:39 +0100 Subject: hostfs: Use page_offset() The kernel offers a helper function for that, use it. Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs_kern.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index f1547479e62e..f82f98a517f7 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -410,7 +410,7 @@ static int hostfs_writepage(struct page *page, struct writeback_control *wbc) struct address_space *mapping = page->mapping; struct inode *inode = mapping->host; char *buffer; - unsigned long long base; + loff_t base = page_offset(page); int count = PAGE_CACHE_SIZE; int end_index = inode->i_size >> PAGE_CACHE_SHIFT; int err; @@ -419,7 +419,6 @@ static int hostfs_writepage(struct page *page, struct writeback_control *wbc) count = inode->i_size & (PAGE_CACHE_SIZE-1); buffer = kmap(page); - base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT; err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count); if (err != count) { @@ -444,10 +443,9 @@ static int hostfs_writepage(struct page *page, struct writeback_control *wbc) static int hostfs_readpage(struct file *file, struct page *page) { char *buffer; - long long start; + loff_t start = page_offset(page); int bytes_read, ret = 0; - start = (long long) page->index << PAGE_CACHE_SHIFT; buffer = kmap(page); bytes_read = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer, PAGE_CACHE_SIZE); -- cgit v1.2.3 From b98b91029cf8a6defc6311d4018c44f3b05fbec7 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 4 Mar 2015 23:44:54 +0100 Subject: hostfs: No need to box and later unbox the file mode There is really no point in having a function with 10 arguments. Reported-by: Daniel Walter Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs.h | 3 +-- fs/hostfs/hostfs_kern.c | 5 +---- fs/hostfs/hostfs_user.c | 17 +++-------------- 3 files changed, 5 insertions(+), 20 deletions(-) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h index 4fcd40d6f308..493262e43443 100644 --- a/fs/hostfs/hostfs.h +++ b/fs/hostfs/hostfs.h @@ -77,8 +77,7 @@ extern int write_file(int fd, unsigned long long *offset, const char *buf, int len); extern int lseek_file(int fd, long long offset, int whence); extern int fsync_file(int fd, int datasync); -extern int file_create(char *name, int ur, int uw, int ux, int gr, - int gw, int gx, int or, int ow, int ox); +extern int file_create(char *name, int mode); extern int set_attr(const char *file, struct hostfs_iattr *attrs, int fd); extern int make_symlink(const char *from, const char *to); extern int unlink_file(const char *file); diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index f82f98a517f7..e77da44a235c 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -582,10 +582,7 @@ static int hostfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, if (name == NULL) goto out_put; - fd = file_create(name, - mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR, - mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP, - mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH); + fd = file_create(name, mode & S_IFMT); if (fd < 0) error = fd; else diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c index 9765dab95cbd..34ab81b21c93 100644 --- a/fs/hostfs/hostfs_user.c +++ b/fs/hostfs/hostfs_user.c @@ -175,21 +175,10 @@ void close_dir(void *stream) closedir(stream); } -int file_create(char *name, int ur, int uw, int ux, int gr, - int gw, int gx, int or, int ow, int ox) +int file_create(char *name, int mode) { - int mode, fd; - - mode = 0; - mode |= ur ? S_IRUSR : 0; - mode |= uw ? S_IWUSR : 0; - mode |= ux ? S_IXUSR : 0; - mode |= gr ? S_IRGRP : 0; - mode |= gw ? S_IWGRP : 0; - mode |= gx ? S_IXGRP : 0; - mode |= or ? S_IROTH : 0; - mode |= ow ? S_IWOTH : 0; - mode |= ox ? S_IXOTH : 0; + int fd; + fd = open64(name, O_CREAT | O_RDWR, mode); if (fd < 0) return -errno; -- cgit v1.2.3 From 0c9bd6365d0b278728359843b8303047ddedb831 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 24 Mar 2015 15:47:38 +0100 Subject: um: hostfs: Reduce number of syscalls in readdir Currently hostfs issues every time a seekdir(), in fact it has to do this only upon the first call. Also telldir() can be omitted as we can obtain the directory offset from readdir(). Signed-off-by: Richard Weinberger --- fs/hostfs/hostfs.h | 3 ++- fs/hostfs/hostfs_kern.c | 1 + fs/hostfs/hostfs_user.c | 12 +++++++++--- 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'fs/hostfs') diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h index 493262e43443..91e19f9dffe5 100644 --- a/fs/hostfs/hostfs.h +++ b/fs/hostfs/hostfs.h @@ -66,7 +66,8 @@ extern int stat_file(const char *path, struct hostfs_stat *p, int fd); extern int access_file(char *path, int r, int w, int x); extern int open_file(char *path, int r, int w, int append); extern void *open_dir(char *path, int *err_out); -extern char *read_dir(void *stream, unsigned long long *pos, +extern void seek_dir(void *stream, unsigned long long pos); +extern char *read_dir(void *stream, unsigned long long *pos_out, unsigned long long *ino_out, int *len_out, unsigned int *type_out); extern void close_file(void *stream); diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index e77da44a235c..d0a2f68a0eea 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -292,6 +292,7 @@ static int hostfs_readdir(struct file *file, struct dir_context *ctx) if (dir == NULL) return -error; next = ctx->pos; + seek_dir(dir, next); while ((name = read_dir(dir, &next, &ino, &len, &type)) != NULL) { if (!dir_emit(ctx, name, len, ino, type)) break; diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c index 34ab81b21c93..9c1e0f019880 100644 --- a/fs/hostfs/hostfs_user.c +++ b/fs/hostfs/hostfs_user.c @@ -97,21 +97,27 @@ void *open_dir(char *path, int *err_out) return dir; } -char *read_dir(void *stream, unsigned long long *pos, +void seek_dir(void *stream, unsigned long long pos) +{ + DIR *dir = stream; + + seekdir(dir, pos); +} + +char *read_dir(void *stream, unsigned long long *pos_out, unsigned long long *ino_out, int *len_out, unsigned int *type_out) { DIR *dir = stream; struct dirent *ent; - seekdir(dir, *pos); ent = readdir(dir); if (ent == NULL) return NULL; *len_out = strlen(ent->d_name); *ino_out = ent->d_ino; *type_out = ent->d_type; - *pos = telldir(dir); + *pos_out = ent->d_off; return ent->d_name; } -- cgit v1.2.3