1.1 --- a/libfsserver/include/fsserver/ext2_file_operations.h Sun Aug 29 23:51:48 2021 +0200
1.2 +++ b/libfsserver/include/fsserver/ext2_file_operations.h Tue Aug 31 23:51:13 2021 +0200
1.3 @@ -30,6 +30,19 @@
1.4
1.5
1.6
1.7 +/* Directory iteration helper type. */
1.8 +
1.9 +class Ext2FileOperations;
1.10 +
1.11 +struct Ext2DirectoryIteration
1.12 +{
1.13 + Ext2FileOperations *ops;
1.14 + int (*func)(struct ext2_dir_entry *, int, int, char *, void *);
1.15 + void *priv_data;
1.16 +};
1.17 +
1.18 +
1.19 +
1.20 /* An Ext2 file operations collection. */
1.21
1.22 class Ext2FileOperations
1.23 @@ -70,6 +83,12 @@
1.24 void *priv_data);
1.25
1.26 long read_inode(ext2_ino_t ino_file, struct ext2_inode *inode);
1.27 +
1.28 + /* Callback method. */
1.29 +
1.30 + int directory_iterate_fn(struct ext2_dir_entry *dir_entry,
1.31 + int offset, int blocksize,
1.32 + char *buf, struct Ext2DirectoryIteration *priv_data);
1.33 };
1.34
1.35 // vim: tabstop=4 expandtab shiftwidth=4
2.1 --- a/libfsserver/lib/files/ext2_file_operations.cc Sun Aug 29 23:51:48 2021 +0200
2.2 +++ b/libfsserver/lib/files/ext2_file_operations.cc Tue Aug 31 23:51:13 2021 +0200
2.3 @@ -155,6 +155,54 @@
2.4 ext2fs_file_write(file, addr, size, NULL);
2.5 }
2.6
2.7 +/* Obtain information for the given inode. */
2.8 +
2.9 +long Ext2FileOperations::read_inode(ext2_ino_t ino, struct ext2_inode *inode)
2.10 +{
2.11 + std::lock_guard<std::mutex> guard(_lock);
2.12 +
2.13 + if (ext2fs_read_inode(_fs, ino, inode))
2.14 + return -L4_EIO;
2.15 +
2.16 + return L4_EOK;
2.17 +}
2.18 +
2.19 +
2.20 +
2.21 +/* Directory iteration support. */
2.22 +
2.23 +/* Callback function invoking the callback method. */
2.24 +
2.25 +static int _directory_iterate_fn(struct ext2_dir_entry *dir_entry,
2.26 + int offset, int blocksize, char *buf,
2.27 + void *priv_data)
2.28 +{
2.29 + struct Ext2DirectoryIteration *data = reinterpret_cast<struct Ext2DirectoryIteration *>(priv_data);
2.30 +
2.31 + return data->ops->directory_iterate_fn(dir_entry, offset, blocksize, buf, data);
2.32 +}
2.33 +
2.34 +/* Callback method invoking the actual callback, with control over locking. */
2.35 +
2.36 +int Ext2FileOperations::directory_iterate_fn(struct ext2_dir_entry *dir_entry,
2.37 + int offset, int blocksize,
2.38 + char *buf, struct Ext2DirectoryIteration *priv_data)
2.39 +{
2.40 + /* Release the lock to allow other operations to proceed. */
2.41 +
2.42 + _lock.unlock();
2.43 +
2.44 + /* Invoke the actual callback function. */
2.45 +
2.46 + struct Ext2DirectoryIteration *data = reinterpret_cast<struct Ext2DirectoryIteration *>(priv_data);
2.47 + int result = data->func(dir_entry, offset, blocksize, buf, data->priv_data);
2.48 +
2.49 + /* Acquire the lock and continue iteration. */
2.50 +
2.51 + _lock.lock();
2.52 + return result;
2.53 +}
2.54 +
2.55 /* Initiate iteration over a directory, with the given 'func' being called
2.56 with directory entry details for each entry. */
2.57
2.58 @@ -163,20 +211,30 @@
2.59 char *, void *),
2.60 void *priv_data)
2.61 {
2.62 - if (ext2fs_dir_iterate(_fs, dir, 0, 0, func, priv_data))
2.63 - return -L4_EIO;
2.64 + /* NOTE: Iteration should probably be interrupted if it appears that the
2.65 + directory has been modified and the structure of the data has
2.66 + been changed. This condition might then cause iteration to begin
2.67 + again, skipping ahead to the entry after the last visited entry. */
2.68
2.69 - return L4_EOK;
2.70 -}
2.71 + /* Acquire the lock for iteration to proceed safely. */
2.72 +
2.73 + _lock.lock();
2.74
2.75 -long Ext2FileOperations::read_inode(ext2_ino_t ino_file, struct ext2_inode *inode)
2.76 -{
2.77 - std::lock_guard<std::mutex> guard(_lock);
2.78 + /* Begin iteration using the given callback function to invoke a callback
2.79 + method in this object that will wrap the actual callback with locking
2.80 + operations. */
2.81 +
2.82 + struct Ext2DirectoryIteration data = {this, func, priv_data};
2.83 + int result = ext2fs_dir_iterate(_fs, dir, 0, 0, _directory_iterate_fn, &data);
2.84
2.85 - if (ext2fs_read_inode(_fs, ino_file, inode))
2.86 + /* Release the lock upon finishing iteration. */
2.87 +
2.88 + _lock.unlock();
2.89 +
2.90 + if (result)
2.91 return -L4_EIO;
2.92 -
2.93 - return L4_EOK;
2.94 + else
2.95 + return L4_EOK;
2.96 }
2.97
2.98 // vim: tabstop=4 expandtab shiftwidth=4