return res;
}
-#define OBD_MD_FLMODE (1UL<<1)
-#define OBD_MD_FLUID (1UL<<2)
-#define OBD_MD_FLGID (1UL<<3)
-#define OBD_MD_FLSIZE (1UL<<4)
-#define OBD_MD_FLATIME (1UL<<5)
-#define OBD_MD_FLMTIME (1UL<<6)
-#define OBD_MD_FLCTIME (1UL<<7)
-#define OBD_MD_FLFLAGS (1UL<<8)
-#define OBD_MD_FLBLOCKS (1UL<<9)
-#define OBD_MD_FLOBDMD (1UL<<10)
+#define OBD_MD_NO (1UL) /* negates meaning of all flags */
+#define OBD_MD_ALL (OBD_MD_NO) /* passing NO with no other flags == ALL */
+#define OBD_MD_FLMODE (1UL<<1)
+#define OBD_MD_FLUID (1UL<<2)
+#define OBD_MD_FLGID (1UL<<3)
+#define OBD_MD_FLSIZE (1UL<<4)
+#define OBD_MD_FLATIME (1UL<<5)
+#define OBD_MD_FLMTIME (1UL<<6)
+#define OBD_MD_FLCTIME (1UL<<7)
+#define OBD_MD_FLFLAGS (1UL<<8)
+#define OBD_MD_FLBLOCKS (1UL<<9)
+#define OBD_MD_FLOBDMD (1UL<<10)
static __inline__ void obdo_cpy_md(obdattr *dst, obdattr *src, int mask)
{
+ /* If the OBD_MD_NO flag is set, then we copy all EXCEPT those
+ * fields given by the flags. The default is to copy the field
+ * given by the flags.
+ */
+ if (mask & OBD_MD_NO)
+ mask = ~mask;
+
CDEBUG(D_INODE, "flags %x\n", mask);
- if ( ! (mask & OBD_MD_FLMODE) )
+ if ( mask & OBD_MD_FLMODE )
dst->i_mode = src->i_mode;
- if ( ! (mask & OBD_MD_FLUID) )
+ if ( mask & OBD_MD_FLUID )
dst->i_uid = src->i_uid;
- if ( ! (mask & OBD_MD_FLGID) )
+ if ( mask & OBD_MD_FLGID )
dst->i_gid = src->i_gid;
- if ( ! (mask & OBD_MD_FLSIZE) )
+ if ( mask & OBD_MD_FLSIZE )
dst->i_size = src->i_size;
- if ( ! (mask & OBD_MD_FLATIME) )
+ if ( mask & OBD_MD_FLATIME )
dst->i_atime = src->i_atime;
- if ( ! (mask & OBD_MD_FLMTIME) )
+ if ( mask & OBD_MD_FLMTIME )
dst->i_mtime = src->i_mtime;
- if ( ! (mask & OBD_MD_FLCTIME) )
+ if ( mask & OBD_MD_FLCTIME )
dst->i_ctime = src->i_ctime;
- if ( ! (mask & OBD_MD_FLFLAGS) )
+ if ( mask & OBD_MD_FLFLAGS )
dst->i_flags = src->i_flags;
/* allocation of space */
- if ( ! (mask & OBD_MD_FLBLOCKS) )
+ if ( mask & OBD_MD_FLBLOCKS )
dst->i_blocks = src->i_blocks;
- if ( ! (mask & OBD_MD_FLOBDMD) && !src->i_blocks ) {
+ if ( mask & OBD_MD_FLOBDMD && src->i_blocks == 0 ) {
CDEBUG(D_IOCTL, "copying inline data: ino %ld\n", dst->i_ino);
memcpy(&dst->u.ext2_i.i_data, &src->u.ext2_i.i_data,
sizeof(src->u.ext2_i.i_data));
} else {
- CDEBUG(D_INODE, "XXXX cpy_obdmd: ino %ld iblocks not 0!\n", src->i_ino);
+ CDEBUG(D_INODE, "XXXX cpy_obdmd: ino %ld iblocks not 0!\n",
+ src->i_ino);
}
}
+
static __inline__ int obdo_cmp_md(obdattr *dst, obdattr *src, int mask)
{
int res = 1;
- if ( ! (mask & OBD_MD_FLMODE) )
+
+ /* If the OBD_MD_NO flag is set, then we copy all EXCEPT those
+ * fields given by the flags. The default is to copy the field
+ * given by the flags.
+ */
+ if (mask & OBD_MD_NO)
+ mask = ~mask;
+
+ if ( mask & OBD_MD_FLMODE )
res = (res && (dst->i_mode == src->i_mode));
- if ( ! (mask & OBD_MD_FLUID) )
+ if ( mask & OBD_MD_FLUID )
res = (res && (dst->i_uid == src->i_uid));
- if ( ! (mask & OBD_MD_FLGID) )
+ if ( mask & OBD_MD_FLGID )
res = (res && (dst->i_gid == src->i_gid));
- if ( ! (mask & OBD_MD_FLSIZE) )
+ if ( mask & OBD_MD_FLSIZE )
res = (res && (dst->i_size == src->i_size));
- if ( ! (mask & OBD_MD_FLATIME) )
+ if ( mask & OBD_MD_FLATIME )
res = (res && (dst->i_atime == src->i_atime));
- if ( ! (mask & OBD_MD_FLMTIME) )
+ if ( mask & OBD_MD_FLMTIME )
res = (res && (dst->i_mtime == src->i_mtime));
- if ( ! (mask & OBD_MD_FLCTIME) )
+ if ( mask & OBD_MD_FLCTIME )
res = (res && (dst->i_ctime == src->i_ctime));
- if ( ! (mask & OBD_MD_FLFLAGS) )
+ if ( mask & OBD_MD_FLFLAGS )
res = (res && (dst->i_flags == src->i_flags));
/* allocation of space */
- if ( ! (mask & OBD_MD_FLBLOCKS) )
+ if ( mask & OBD_MD_FLBLOCKS )
res = (res && (dst->i_blocks == src->i_blocks));
return res;
}
inline struct obd_conn *child_conn(struct obd_conn *conn);
-int snap_deleteino(objid id, void *data);
-int snap_restoreino(objid id, void *data);
+int snap_deleteobj(objid id, void *data);
+int snap_restoreobj(objid id, void *data);
+int snap_printobj(objid id, void *data);
int snap_iocontrol(int cmd, struct obd_conn *conn, int len, void *karg, void *uarg);
#endif
void obdfs_read_inode(struct inode *inode);
-/* file.c */
-ssize_t obdfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos);
-
-
/* rw.c */
+int obdfs_readpage(struct dentry *dentry, struct page *page);
+int obdfs_writepage(struct dentry *dentry, struct page *page);
struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create, int locked);
int obdfs_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf);
int obdfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry);
int obdfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry);
/* dir.c */
-int obdfs_readdir(struct file * filp, void * dirent, filldir_t filldir);
int obdfs_check_dir_entry (const char * function, struct inode * dir,
struct ext2_dir_entry_2 * de,
struct page * page,
struct obdfs_inode_info;
-extern struct file_operations obdfs_file_ops;
-extern struct inode_operations obdfs_inode_ops;
+extern struct file_operations obdfs_file_operations;
+extern struct inode_operations obdfs_file_inode_operations;
+extern struct inode_operations obdfs_dir_inode_operations;
extern struct inode_operations obdfs_symlink_inode_operations;
static inline struct obd_ops *iops(struct inode *i)
umount /mnt/obd
rmmod obdfs
-./obdcontrol -f << EOF
+../class/obdcontrol -f << EOF
cleanup
detach
quit
print "type $type (len $len), datalen $datalen ($cl)\n";
my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data);
+ # XXX We need to fix this up so that after the objects in this snapshot
+ # are deleted, the snapshot itself is also removed from the table.
my $rc = ioctl(DEV_OBD, &OBD_SNAP_DELETE, $packed);
if (!defined $rc) {
}
-# FIXME the parameter to snaprestore SHOULD be the snapshot number of the
-# snapshot to be restored, and this routine should handle all of the
-# removal of intervening snapshots and changing the snaptable to have
-# the "restored" snapshot as current and move the previous current.
+# XXX the parameter to snaprestore SHOULD be the snapshot number of the
+# snapshot to be restored, and this routine should handle all of the
+# removal of intervening snapshots and changing the snaptable to have
+# the "restored" snapshot as current and move the previous current.
sub SnapRestore {
if (!defined($::client_id)) {
print "You must first ``connect''.\n";
#! /bin/bash
-dd if=/dev/zero of=/tmp/fs bs=1k count=10000
+dd if=/dev/zero of=/tmp/fs bs=1k count=10k
-insmod loop
+#insmod loop
losetup /dev/loop0 /tmp/fs
mke2fs -b 4096 /dev/loop0
#include <asm/uaccess.h>
-#include <asm/uaccess.h>
-
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/obd_support.h>
#include <linux/obdfs.h>
-#if 0
static ssize_t obdfs_dir_read (struct file * filp, char * buf,
size_t count, loff_t *ppos)
{
return -EISDIR;
}
-#endif
+
+static int obdfs_readdir(struct file *, void *, filldir_t);
+
+struct file_operations obdfs_dir_operations = {
+ NULL, /* lseek - default */
+ obdfs_dir_read, /* read */
+ NULL, /* write - bad */
+ obdfs_readdir, /* readdir */
+ NULL, /* poll - default */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* flush */
+ NULL, /* no special release code */
+ NULL, /* fsync */
+ NULL, /* fasync */
+ NULL, /* check_media_change */
+ NULL /* revalidate */
+};
+
+struct inode_operations obdfs_dir_inode_operations = {
+ &obdfs_dir_operations, /* default directory file-ops */
+ obdfs_create, /* create */
+ obdfs_lookup, /* lookup */
+ obdfs_link, /* link */
+ obdfs_unlink, /* unlink */
+ obdfs_symlink, /* symlink */
+ obdfs_mkdir, /* mkdir */
+ obdfs_rmdir, /* rmdir */
+ obdfs_mknod, /* mknod */
+ obdfs_rename, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* get_block */
+ obdfs_readpage, /* readpage */
+ obdfs_writepage, /* writepage */
+ NULL, /* truncate */
+ NULL, /* permission */
+ NULL /* revalidate */
+};
int obdfs_check_dir_entry (const char * function, struct inode * dir,
struct ext2_dir_entry_2 * de,
}
-int obdfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
+static int obdfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
int error = 0;
unsigned long offset;
* not the directory has been modified
* during the copy operation.
*/
- /* XXX unsigned long version = inode->i_version;
+ /* XXX
+ unsigned long version = inode->i_version;
*/
error = filldir(dirent, de->name,
de->name_len,
/*
* Write to a file (through the page cache).
*/
-ssize_t obdfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+static ssize_t
+obdfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
ssize_t retval;
CDEBUG(D_INODE, "Writing inode %ld, %d bytes, offset %ld\n", file->f_dentry->d_inode->i_ino, count, (long)*ppos);
EXIT;
return retval;
}
+
+struct file_operations obdfs_file_operations = {
+ NULL, /* lseek - default */
+ generic_file_read, /* read */
+ obdfs_file_write, /* write */
+ NULL, /* readdir - bad */
+ NULL, /* poll - default */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* flush */
+ NULL, /* no special release code */
+ NULL, /* fsync */
+ NULL, /* fasync */
+ NULL, /* check_media_change */
+ NULL /* revalidate */
+};
+
+struct inode_operations obdfs_file_inode_operations = {
+ &obdfs_file_operations, /* default directory file-ops */
+ obdfs_create, /* create */
+ obdfs_lookup, /* lookup */
+ obdfs_link, /* link */
+ obdfs_unlink, /* unlink */
+ obdfs_symlink, /* symlink */
+ obdfs_mkdir, /* mkdir */
+ obdfs_rmdir, /* rmdir */
+ obdfs_mknod, /* mknod */
+ obdfs_rename, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* get_block */
+ obdfs_readpage, /* readpage */
+ obdfs_writepage, /* writepage */
+ NULL, /* truncate */
+ NULL, /* permission */
+ NULL /* revalidate */
+};
+
* itself (as a parameter - res_dir). It does NOT read the inode of the
* entry - you'll have to do that yourself if you want to.
*/
-struct page * obdfs_find_entry (struct inode * dir,
+static struct page * obdfs_find_entry (struct inode * dir,
const char * const name, int namelen,
struct ext2_dir_entry_2 ** res_dir, int lock)
{
/* do minimal checking `by hand' */
int de_len;
CDEBUG(D_INODE, "Entry %p len %d, page at %#lx - %#lx , offset %lx\n",
- de, le16_to_cpu(de->rec_len), page_address(page), page_address(page) +
- PAGE_SIZE, offset);
+ de, le16_to_cpu(de->rec_len), page_address(page),
+ page_address(page) + PAGE_SIZE, offset);
if ((char *) de + namelen <= dlimit &&
ext2_match (namelen, name, de)) {
return NULL;
}
CDEBUG(D_INODE, "Testing for enough space at de %p\n", de);
- if ( (le32_to_cpu(de->inode) == 0 &&
- le16_to_cpu(de->rec_len) >= rec_len) ||
- (le16_to_cpu(de->rec_len) >=
- EXT2_DIR_REC_LEN(de->name_len) + rec_len)) {
+ if ( (le32_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) ||
+ (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(de->name_len) + rec_len)) {
offset += le16_to_cpu(de->rec_len);
CDEBUG(D_INODE, "Found enough space de %p, offset %#lx\n", de, offset);
if (le32_to_cpu(de->inode)) {
/*
* Display all dentries holding the specified inode.
*/
+#if 0
static void show_dentry(struct list_head * dlist, int subdirs)
{
struct list_head *tmp = dlist;
unhashed);
}
}
+#endif
/*
return err;
}
- inode->i_op = &obdfs_inode_ops;
+ inode->i_op = &obdfs_file_inode_operations;
inode->i_mode = mode;
mark_inode_dirty(inode);
page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
{
- struct inode * child;
- struct page *page, *child_page;
+ struct inode * inode;
+ struct page *page, *inode_page;
struct ext2_dir_entry_2 * de;
int err;
ino_t ino;
ino = iops(dir)->o_create(iid(dir), 0, &err);
if ( ino == -1 )
return -1;
- child = iget(dir->i_sb, ino);
- if (!child)
+ inode = iget(dir->i_sb, ino);
+ if (!inode)
return err;
- child->i_op = &obdfs_inode_ops;
- child->i_blocks = 0;
- child_page = obdfs_getpage(child, 0, 1, LOCKED);
- if (!child_page) {
- child->i_nlink--; /* is this nlink == 0? */
- mark_inode_dirty(child);
- iput (child);
+ inode->i_op = &obdfs_dir_inode_operations;
+ inode->i_blocks = 0;
+ inode_page = obdfs_getpage(inode, 0, 1, LOCKED);
+ if (!inode_page) {
+ inode->i_nlink--; /* is this nlink == 0? */
+ mark_inode_dirty(inode);
+ iput (inode);
return err;
}
/* create . and .. */
- de = (struct ext2_dir_entry_2 *) page_address(child_page);
- de->inode = cpu_to_le32(child->i_ino);
+ de = (struct ext2_dir_entry_2 *) page_address(inode_page);
+ de->inode = cpu_to_le32(inode->i_ino);
de->name_len = 1;
de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len));
strcpy (de->name, ".");
strcpy (de->name, "..");
ext2_set_de_type(dir->i_sb, de, S_IFDIR);
- iops(dir)->o_brw(WRITE, iid(dir), child, child_page, 1);
- child->i_blocks = PAGE_SIZE/child->i_sb->s_blocksize;
- child->i_size = PAGE_SIZE;
- UnlockPage(child_page);
- page_cache_release(child_page);
-
- child->i_nlink = 2;
- child->i_mode = S_IFDIR | mode;
+ iops(dir)->o_brw(WRITE, iid(dir), inode, inode_page, 1);
+ inode->i_blocks = PAGE_SIZE/inode->i_sb->s_blocksize;
+ inode->i_size = PAGE_SIZE;
+ UnlockPage(inode_page);
+ page_cache_release(inode_page);
+
+ inode->i_nlink = 2;
+ inode->i_mode = S_IFDIR | mode;
if (dir->i_mode & S_ISGID)
- child->i_mode |= S_ISGID;
- mark_inode_dirty(child);
+ inode->i_mode |= S_ISGID;
+ mark_inode_dirty(inode);
/* now deal with the parent */
page = obdfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
goto out_no_entry;
}
- de->inode = cpu_to_le32(child->i_ino);
+ de->inode = cpu_to_le32(inode->i_ino);
ext2_set_de_type(dir->i_sb, de, S_IFDIR);
dir->i_version = ++event;
iops(dir)->o_brw(WRITE, iid(dir), dir, page, 1);
UnlockPage(page);
page_cache_release(page);
- d_instantiate(dentry, child);
+ d_instantiate(dentry, inode);
err = 0;
out:
EXIT;
return err;
out_no_entry:
- child->i_nlink = 0;
- mark_inode_dirty(child);
- iput (child);
+ inode->i_nlink = 0;
+ mark_inode_dirty(inode);
+ iput (inode);
EXIT;
goto out;
}
struct page *page;
struct ext2_dir_entry_2 * de;
- ENTRY;
+ ENTRY;
retval = -ENOENT;
page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED);
EXIT;
return err;
}
-
inode->i_mode = S_IFLNK | S_IRWXUGO;
inode->i_op = &obdfs_symlink_inode_operations;
for (l = 0; l < inode->i_sb->s_blocksize - 1 &&
while (i < inode->i_sb->s_blocksize - 1 && (c = *(symname++)))
link[i++] = c;
link[i] = 0;
- /* if (name_page) { */
+ if (name_page) {
iops(inode)->o_brw(WRITE, iid(inode), inode, name_page, 1);
PDEBUG(name_page, "symlink");
UnlockPage(name_page);
page_cache_release(name_page);
- /* } */
+ }
inode->i_size = i;
mark_inode_dirty(inode);
}
/* returns the page unlocked, but with a reference */
-static int obdfs_writepage(struct dentry *dentry, struct page *page)
+int obdfs_writepage(struct dentry *dentry, struct page *page)
{
struct inode *inode = dentry->d_inode;
int rc;
}
-struct file_operations obdfs_file_ops = {
- NULL, /* lseek - default */
- generic_file_read, /* read */
- obdfs_file_write, /* write - bad */
- obdfs_readdir, /* readdir */
- NULL, /* poll - default */
- NULL, /* ioctl */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* flush */
- NULL, /* no special release code */
- NULL, /* fsync */
- NULL, /* fasync */
- NULL, /* check_media_change */
- NULL /* revalidate */
-};
-
-struct inode_operations obdfs_inode_ops = {
- &obdfs_file_ops, /* default directory file-ops */
- obdfs_create, /* create */
- obdfs_lookup, /* lookup */
- obdfs_link, /* link */
- obdfs_unlink, /* unlink */
- obdfs_symlink, /* symlink */
- obdfs_mkdir, /* mkdir */
- obdfs_rmdir, /* rmdir */
- obdfs_mknod, /* mknod */
- obdfs_rename, /* rename */
- obdfs_readlink, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- obdfs_readpage, /* readpage */
- obdfs_writepage,/* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
-};
EXIT;
}
-extern struct inode_operations obdfs_inode_ops;
-
/* all filling in of inodes postponed until lookup */
void obdfs_read_inode(struct inode *inode)
{
printk("obdfs_read_inode: obd_getattr fails (%d)\n", error);
return;
}
- CDEBUG(D_INODE, "ino %ld, COWFL %x\n", inode->i_ino, inode->i_flags & 0x0010000);
+ CDEBUG(D_INODE, "ino %ld, mode: %o\n", inode->i_ino, inode->i_mode);
IDEBUG(inode);
- inode->i_op = &obdfs_inode_ops;
+ if (S_ISREG(inode->i_mode))
+ inode->i_op = &obdfs_file_inode_operations;
+ else if (S_ISDIR(inode->i_mode))
+ inode->i_op = &obdfs_dir_inode_operations;
+ else if (S_ISLNK(inode->i_mode))
+ inode->i_op = &obdfs_symlink_inode_operations;
+ else
+ /* XXX what do we pass here??? */
+ init_special_inode(inode, inode->i_mode, 0 /* XXX XXX */ );
return;
}
#include <linux/obd_support.h> /* for ENTRY and EXIT only */
#include <linux/obdfs.h>
+/*
static int obdfs_readlink (struct dentry *, char *, int);
static struct dentry *obdfs_follow_link(struct dentry *, struct dentry *, unsigned int);
+*/
/*
* symlinks can't do much...
NULL /* revalidate */
};
-static struct dentry * obdfs_follow_link(struct dentry * dentry,
+/* static */
+struct dentry * obdfs_follow_link(struct dentry * dentry,
struct dentry *base,
unsigned int follow)
{
return base;
}
-static int obdfs_readlink (struct dentry * dentry, char * buffer, int buflen)
+/* static */
+int obdfs_readlink (struct dentry * dentry, char * buffer, int buflen)
{
struct inode *inode = dentry->d_inode;
struct page *page = NULL;