struct snap_cache *snap_find_cache(kdev_t dev)
{
struct snap_cache *cache;
- struct list_head *lh, *tmp;
+ struct list_head *lh;
- lh = tmp = &(snap_caches[snap_cache_hash(dev)]);
+ lh = &(snap_caches[snap_cache_hash(dev)]);
list_for_each_entry(cache, lh, cache_chain) {
if ( cache->cache_dev == dev )
return cache;
}
return cache;
}
+/*walk through the cache structure*/
+int snap_cache_process(snap_cache_cb_t cb, void* in, unsigned long* out)
+{
+ int i = 0;
+
+ for (i = 0; i < CACHES_SIZE; i++) {
+ struct snap_cache *cache;
+ struct list_head *lh = &(snap_caches[i]);
+ list_for_each_entry(cache, lh, cache_chain) {
+ if (cb(cache, in, out))
+ goto exit;
+ }
+ }
+exit:
+ return 0;
+}
+
/* free a cache structure and all of the memory it is pointing to */
inline void snap_free_cache(struct snap_cache *cache)
if (filter_fops) {
if (filter_fops->read)
u_fops->read = filter_fops->read;
+ if (filter_fops->write)
+ u_fops->write = filter_fops->write;
}
if (filter_aops) {
if (filter_aops->readpage)
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/loop.h>
#include <linux/jbd.h>
#include <linux/ext3_fs.h>
#include <linux/snap.h>
sb->s_root->d_op,
¤tfs_dentry_ops);
sb->s_root->d_op = filter_c2udops(cache->cache_filter);
+ init_filter_data(sb->s_root->d_inode, 0);
}
/*
* Save a pointer to the snap_cache structure in the
}
return pos;
}
-
+static int snap_cache_lookup_ino_cb(struct snap_cache *cache, void *in, unsigned long *out)
+{
+ ino_t ino = *((unsigned long*)in);
+
+ if (cache) {
+ struct super_block *sb = cache->cache_sb;
+ kdev_t dev = sb->s_dev;
+
+ if (MAJOR(dev) != LOOP_MAJOR)
+ return 0;
+ if (sb->s_bdev->bd_op && sb->s_bdev->bd_op->ioctl) {
+ struct inode *inode = sb->s_bdev->bd_inode;
+ struct loop_info loop_info;
+
+ sb->s_bdev->bd_op->ioctl(inode, NULL, LOOP_GET_INFO,
+ (unsigned long)&loop_info);
+
+ if(loop_info.lo_inode == ino) {
+ *out = sb->s_dev;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
static int snapfs_path2dev(char *dev_path, kdev_t *dev)
{
struct dentry *dentry;
path_release(&nd);
return -ENODEV;
}
-
- *dev = kdev_t_to_nr(dentry->d_inode->i_rdev);
+ if (S_ISBLK(dentry->d_inode->i_mode)) {
+ *dev = kdev_t_to_nr(dentry->d_inode->i_rdev);
+ } else {
+ /*here we must walk through all the snap cache to
+ *find the loop device */
+ kdev_t tmp;
+
+ if (snap_cache_process(snap_cache_lookup_ino_cb,
+ &dentry->d_inode->i_ino,
+ (unsigned long*)&tmp))
+ return -EINVAL;
+ *dev = tmp;
+ }
path_release(&nd);
return 0;
}
" D open(O_DIRECTORY)\n"
" o open(O_RDONLY)\n"
" O open(O_CREAT|O_RDWR)\n"
+" L link\n"
+" l symlink\n"
" u unlink\n"
" U munmap\n"
" m mknod\n"
" M rw mmap to EOF (must open and stat prior)\n"
+" N rename\n"
" c close\n"
" _ wait for signal\n"
" R reference entire mmap-ed region\n"
void null_handler(int unused) { }
+static const char *
+pop_arg(int argc, char *argv[])
+{
+ static int cur_arg = 3;
+
+ if (cur_arg >= argc)
+ return NULL;
+
+ return argv[cur_arg++];
+}
+#define POP_ARG() (pop_arg(argc, argv))
+
int main(int argc, char **argv)
{
char *fname, *commands;
+ const char *newfile;
struct stat st;
size_t mmap_len, i;
unsigned char *mmap_ptr = NULL, junk = 0;
int fd = -1;
- if (argc != 3) {
+ if (argc < 3) {
fprintf(stderr, usage, argv[0]);
exit(1);
}
exit(1);
}
break;
+ case 'l':
+ newfile = POP_ARG();
+ if (!newfile)
+ newfile = fname;
+ if (symlink(fname, newfile)) {
+ perror("symlink()");
+ exit(1);
+ }
+ break;
+ case 'L':
+ newfile = POP_ARG();
+ if (!newfile)
+ newfile = fname;
+ if (link(fname, newfile)) {
+ perror("symlink()");
+ exit(1);
+ }
+ break;
case 'm':
if (mknod(fname, S_IFREG | 0644, 0) == -1) {
perror("mknod(S_IFREG|0644, 0)");
exit(1);
}
break;
+ case 'N':
+ newfile = POP_ARG();
+ if (!newfile)
+ newfile = fname;
+ if (rename (fname, newfile)) {
+ perror("rename()");
+ exit(1);
+ }
+ break;
case 'O':
fd = open(fname, O_CREAT|O_RDWR, 0644);
if (fd == -1) {