#define OBD_MD_FLBLOCKS (0x00000020UL)
#define OBD_MD_FLBLKSZ (0x00000040UL)
#define OBD_MD_FLMODE (0x00000080UL)
-#define OBD_MD_FLUID (0x00000100UL)
-#define OBD_MD_FLGID (0x00000200UL)
-#define OBD_MD_FLFLAGS (0x00000400UL)
-#define OBD_MD_FLOBDFLG (0x00000800UL)
-#define OBD_MD_FLNLINK (0x00001000UL)
-#define OBD_MD_FLGENER (0x00002000UL)
-#define OBD_MD_FLINLINE (0x00004000UL)
-#define OBD_MD_FLOBDMD (0x00008000UL)
+#define OBD_MD_FLTYPE (0x00000100UL)
+#define OBD_MD_FLUID (0x00000200UL)
+#define OBD_MD_FLGID (0x00000400UL)
+#define OBD_MD_FLFLAGS (0x00000800UL)
+#define OBD_MD_FLOBDFLG (0x00001000UL)
+#define OBD_MD_FLNLINK (0x00002000UL)
+#define OBD_MD_FLGENER (0x00004000UL)
+#define OBD_MD_FLINLINE (0x00008000UL)
+#define OBD_MD_FLOBDMD (0x00010000UL)
#define OBD_MD_FLNOTOBD (~(OBD_MD_FLOBDMD | OBD_MD_FLOBDFLG | OBD_MD_FLBLOCKS))
/*
static __inline__ struct obdo *obdo_fromid(struct obd_conn *conn, obd_id id,
- obd_flag valid)
+ obd_mode mode, obd_flag valid)
{
struct obdo *oa;
int err;
}
oa->o_id = id;
+ oa->o_mode = mode;
oa->o_valid = valid;
if ((err = OBP(conn->oc_dev, getattr)(conn, oa))) {
obdo_free(oa);
static inline void iattr_from_obdo(struct iattr *attr, struct obdo *oa)
{
unsigned int ia_valid = oa->o_valid;
-
+
+ memset(attr, 0, sizeof(*attr));
if (ia_valid & OBD_MD_FLATIME) {
attr->ia_atime = oa->o_atime;
attr->ia_valid |= ATTR_ATIME;
extern struct obd_device obd_dev[MAX_OBD_DEVICES];
long filter_memory;
+#define FILTER_ROOTINO 2
+
+#define S_SHIFT 12
+
+static char * obd_type_by_mode[S_IFMT >> S_SHIFT] = {
+ [0] "",
+ [S_IFREG >> S_SHIFT] "R",
+ [S_IFDIR >> S_SHIFT] "D",
+ [S_IFCHR >> S_SHIFT] "C",
+ [S_IFBLK >> S_SHIFT] "B",
+ [S_IFIFO >> S_SHIFT] "F",
+ [S_IFSOCK >> S_SHIFT] "S",
+ [S_IFLNK >> S_SHIFT] "L"
+};
+
+static void filter_id(char *buf, obd_id id, obd_mode mode)
+{
+ sprintf(buf, "O/%s/%Ld",
+ obd_type_by_mode[(mode & S_IFMT) >> S_SHIFT],
+ id);
+}
+
void push_ctxt(struct run_ctxt *save, struct run_ctxt *new)
{
save->fs = get_fs();
struct inode *inode;
long rc;
int fd;
+ char rootid[128];
struct stat64 buf;
__u64 lastino = 2;
rc = sys_mkdir("O", 0700);
rc = sys_mkdir("P", 0700);
rc = sys_mkdir("D", 0700);
- rc = sys_mkdir("O/2", 0755);
+ rc = sys_mkdir("O/R", 0700); /* regular */
+ rc = sys_mkdir("O/D", 0700); /* directory */
+ rc = sys_mkdir("O/L", 0700); /* symbolic links */
+ rc = sys_mkdir("O/C", 0700); /* character devices */
+ rc = sys_mkdir("O/B", 0700); /* block devices */
+ rc = sys_mkdir("O/F", 0700); /* fifo's */
+ rc = sys_mkdir("O/S", 0700); /* sockets */
+
+ filter_id(rootid, FILTER_ROOTINO, S_IFDIR);
+ file = filp_open(rootid, O_RDWR | O_CREAT, 00755);
+ if (IS_ERR(file)) {
+ printk("OBD filter: cannot make root directory");
+ goto out;
+ }
+ filp_close(file, 0);
+ rc = sys_mkdir(rootid, 0755);
if ( (fd = sys_open("D/status", O_RDWR | O_CREAT, 0700)) == -1 ) {
printk("OBD filter: cannot create status file\n");
goto out;
obddev->u.filter.fo_lastino = lastino;
/* this is also the moment to steal operations */
- file = filp_open("D/status", O_RDONLY, 0);
+ file = filp_open("D/status", O_RDONLY | O_LARGEFILE, 0);
if (!file || IS_ERR(file)) {
EXIT;
goto out_close;
obddev->u.filter.fo_ctxt.fs = KERNEL_DS;
filter_prep(obddev);
-
+ spin_lock_init(&obddev->u.filter.fo_lock);
+
MOD_INC_USE_COUNT;
EXIT;
return 0;
}
+static __u64 filter_next_id(struct obd_device *obddev)
+{
+ __u64 id;
+ spin_lock(&obddev->u.filter.fo_lock);
+ obddev->u.filter.fo_lastino++;
+ id = obddev->u.filter.fo_lastino;
+ spin_unlock(&obddev->u.filter.fo_lock);
+ return id;
+}
+
static int filter_cleanup(struct obd_device * obddev)
{
struct super_block *sb;
{
struct file *file;
int error = 0;
- char id[16];
+ char id[24];
struct run_ctxt saved;
struct super_block *sb;
return NULL;
}
- sprintf(id, "O/%Ld", oa->o_id);
+ if ( ! (oa->o_mode & S_IFMT) ) {
+ printk("OBD filter_obj_open, no type (%Ld), mode %o!\n",
+ oa->o_id, oa->o_mode);
+ }
+ filter_id(id, oa->o_id, oa->o_mode);
push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
- file = filp_open(id , O_RDONLY, 0);
+ file = filp_open(id , O_RDONLY | O_LARGEFILE, 0);
pop_ctxt(&saved);
if (IS_ERR(file)) {
file = NULL;
}
CDEBUG(D_INODE, "opening obdo %s\n", id);
-
- if ( file ) {
- file->f_op = obddev->u.filter.fo_fop;
- file->f_dentry->d_inode->i_op = obddev->u.filter.fo_iop;
- file->f_dentry->d_inode->i_mapping->a_ops = obddev->u.filter.fo_aops;
- } else {
- printk("Error opening object %s, error %d\n", id, error);
- }
+
return file;
}
-static struct inode *inode_from_obdo(struct obd_device *obddev,
+static struct inode *filter_inode_from_obdo(struct obd_device *obddev,
struct obdo *oa)
{
struct file *file;
file = filter_obj_open(obddev, oa);
if ( !file ) {
- printk("inode_from_obdo failed\n");
+ printk("filter_inode_from_obdo failed\n");
return NULL;
}
static inline void filter_from_inode(struct obdo *oa, struct inode *inode)
{
+ int type = oa->o_mode & S_IFMT;
ENTRY;
CDEBUG(D_INFO, "src inode %ld, dst obdo %ld valid 0x%08x\n",
inode->i_ino, (long)oa->o_id, oa->o_valid);
obdo_from_inode(oa, inode);
+ oa->o_mode &= ~S_IFMT;
+ oa->o_mode |= type;
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
obd_rdev rdev = kdev_t_to_nr(inode->i_rdev);
return -EINVAL;
}
- if ( !(inode = inode_from_obdo(conn->oc_dev, oa)) ) {
+ if ( !(inode = filter_inode_from_obdo(conn->oc_dev, oa)) ) {
EXIT;
return -ENOENT;
}
return -EINVAL;
}
- inode = inode_from_obdo(conn->oc_dev, oa);
+ inode = filter_inode_from_obdo(conn->oc_dev, oa);
if ( !inode ) {
EXIT;
return -ENOENT;
}
iattr_from_obdo(&iattr, oa);
+ iattr.ia_mode &= ~S_IFMT;
+ iattr.ia_mode |= S_IFREG;
de.d_inode = inode;
if ( inode->i_op->setattr ) {
rc = inode->i_op->setattr(&de, &iattr);
{
char name[64];
struct run_ctxt saved;
+ struct file *file;
+ int mode;
struct obd_device *obddev = conn->oc_dev;
struct iattr;
- int rc;
ENTRY;
if (!gen_client(conn)) {
}
CDEBUG(D_IOCTL, "\n");
- conn->oc_dev->u.filter.fo_lastino++;
- oa->o_id = conn->oc_dev->u.filter.fo_lastino;
- sprintf(name, "O/%Ld", oa->o_id);
- push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
- CDEBUG(D_IOCTL, "\n");
- if (sys_mknod(name, 0100644, 0)) {
- printk("Error mknod obj %s\n", name);
+ oa->o_id = filter_next_id(conn->oc_dev);
+ if ( !(oa->o_mode && S_IFMT) ) {
+ printk("filter obd: no type!\n");
return -ENOENT;
}
- pop_ctxt(&saved);
- CDEBUG(D_IOCTL, "\n");
- rc = filter_setattr(conn, oa);
- if ( rc ) {
- EXIT;
- return -EINVAL;
+ filter_id(name, oa->o_id, oa->o_mode);
+ push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
+ mode = oa->o_mode;
+ mode &= ~S_IFMT;
+ mode |= S_IFREG;
+ file = filp_open(name, O_RDONLY | O_CREAT, mode);
+ pop_ctxt(&saved);
+ if (IS_ERR(file)) {
+ printk("Error mknod obj %s, err %ld\n", name, PTR_ERR(file));
+ return -ENOENT;
}
+ filp_close(file, 0);
CDEBUG(D_IOCTL, "\n");
/* Set flags for fields we have set in ext2_new_inode */
}
obddev = conn->oc_dev;
- inode = inode_from_obdo(obddev, oa);
+ inode = filter_inode_from_obdo(obddev, oa);
if (!inode) {
EXIT;
inode->i_mode = 010000;
iput(inode);
- sprintf(id, "O/%Ld", oa->o_id);
+ filter_id(id, oa->o_id, oa->o_mode);
push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
if (sys_unlink(id)) {
EXIT;
+ pop_ctxt(&saved);
return -EPERM;
}
pop_ctxt(&saved);
return 0;
}
+static int filter_truncate(struct obd_conn *conn, struct obdo *oa, obd_size count,
+ obd_off offset)
+{
+ int error;
+
+ error = filter_setattr(conn, oa);
+ oa->o_valid = OBD_MD_FLBLOCKS | OBD_MD_FLCTIME | OBD_MD_FLMTIME;
+
+ EXIT;
+ return error;
+}
+
/* buffer must lie in user memory here */
static int filter_read(struct obd_conn *conn, struct obdo *oa, char *buf,
obd_size *count, obd_off offset)
if ( keylen == strlen("root_ino") &&
memcmp(key, "root_ino", keylen) == 0 ){
*vallen = sizeof(int);
- *val = (void *)(int)
- obddev->u.filter.fo_sb->s_root->d_inode->i_ino;
+ *val = (void *)(int) FILTER_ROOTINO;
EXIT;
return 0;
}
o_read: filter_read,
o_write: filter_write,
o_brw: filter_pgcache_brw,
+ o_punch: filter_truncate,
#if 0
o_preallocate: ext2obd_preallocate_inodes,
- o_setattr: ext2obd_setattr,
- o_punch: ext2obd_punch,
o_migrate: ext2obd_migrate,
o_copy: gen_copy_data,
o_iterate: ext2obd_iterate
[EXT2_FT_SYMLINK] DT_LNK,
};
+static unsigned int obdfs_dt2fmt[DT_WHT + 1] = {
+ [EXT2_FT_UNKNOWN] 0,
+ [EXT2_FT_REG_FILE] S_IFREG,
+ [EXT2_FT_DIR] S_IFDIR,
+ [EXT2_FT_CHRDEV] S_IFCHR,
+ [EXT2_FT_BLKDEV] S_IFBLK,
+ [EXT2_FT_FIFO] S_IFIFO,
+ [EXT2_FT_SOCK] S_IFSOCK,
+ [EXT2_FT_SYMLINK] S_IFLNK
+};
+
#define S_SHIFT 12
static unsigned char ext2_type_by_mode[S_IFMT >> S_SHIFT] = {
[S_IFREG >> S_SHIFT] EXT2_FT_REG_FILE,
static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode)
{
- /* XXX
mode_t mode = inode->i_mode;
- if (EXT2_HAS_INCOMPAT_FEATURE(inode->i_sb, EXT2_FEATURE_INCOMPAT_FILETYPE))
- de->file_type = ext2_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
- else
- de->file_type = 0;
- */
- de->file_type = 0;
+ de->file_type = ext2_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
}
int
if (pos > inode->i_size - EXT2_DIR_REC_LEN(1))
goto done;
- //if (EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE))
- //types = ext2_filetype_table;
+ types = ext2_filetype_table;
for ( ; n < npages; n++, offset = 0) {
char *kaddr, *limit;
return de;
}
-ino_t ext2_inode_by_name(struct inode * dir, struct dentry *dentry)
+ino_t obdfs_inode_by_name(struct inode * dir, struct dentry *dentry, int *type)
{
ino_t res = 0;
struct ext2_dir_entry_2 * de;
de = ext2_find_entry (dir, dentry, &page);
if (de) {
res = le32_to_cpu(de->inode);
+ *type = obdfs_dt2fmt[de->file_type];
kunmap(page);
page_cache_release(page);
}
memcpy (de->name, name, namelen);
de->inode = cpu_to_le32(inode->i_ino);
ext2_set_de_type (de, inode);
+ CDEBUG(D_INODE, "type set to %o\n", de->file_type);
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
err = ext2_commit_chunk(page, from, to);