ext2obd works (except _write and _read which aren't that important).
struct obd_conn_info {
- unsigned int conn_id; /* handle */
+ unsigned int conn_id; /* handle */
};
struct obd_type {
- struct list_head typ_chain;
- struct obd_ops *typ_ops;
- char *typ_name;
- int typ_refcnt;
+ struct list_head typ_chain;
+ struct obd_ops *typ_ops;
+ char *typ_name;
+ int typ_refcnt;
};
-#define OBD_MAGIC 0xffff0000
-#define OBD_MAGIC_MASK 0xffff0000
+#define OBD_MAGIC 0xffff0000
+#define OBD_MAGIC_MASK 0xffff0000
* ======== OBD type Declarations ===========
*/
-typedef uint64_t obd_id;
-typedef uint64_t obd_gr;
-typedef uint64_t obd_time;
-typedef uint64_t obd_size;
-typedef uint64_t obd_off;
-typedef uint64_t obd_blocks;
-typedef uint32_t obd_blksize;
-typedef uint32_t obd_mode;
-typedef uint32_t obd_uid;
-typedef uint32_t obd_gid;
-typedef uint32_t obd_flag;
-typedef uint32_t obd_count;
-
-#define OBD_FL_INLINEDATA (0x00000001UL)
-#define OBD_FL_OBDMDEXISTS (0x00000002UL)
-
-#define OBD_INLINESZ 60
-#define OBD_OBDMDSZ 60
+typedef uint64_t obd_id;
+typedef uint64_t obd_gr;
+typedef uint64_t obd_time;
+typedef uint64_t obd_size;
+typedef uint64_t obd_off;
+typedef uint64_t obd_blocks;
+typedef uint32_t obd_blksize;
+typedef uint32_t obd_mode;
+typedef uint32_t obd_uid;
+typedef uint32_t obd_gid;
+typedef uint32_t obd_flag;
+typedef uint32_t obd_count;
+
+#define OBD_FL_INLINEDATA (0x00000001UL)
+#define OBD_FL_OBDMDEXISTS (0x00000002UL)
+
+#define OBD_INLINESZ 60
+#define OBD_OBDMDSZ 60
/* Note: 64-bit types are 64-bit aligned in structure */
struct obdo {
- obd_id o_id;
- obd_gr o_gr;
- obd_time o_atime;
- obd_time o_mtime;
- obd_time o_ctime;
- obd_size o_size;
- obd_blocks o_blocks;
- obd_blksize o_blksize;
- obd_mode o_mode;
- obd_uid o_uid;
- obd_gid o_gid;
- obd_flag o_flags;
- obd_flag o_obdflags;
- obd_count o_nlink;
- obd_count o_generation;
- obd_flag o_valid; /* hot fields in this obdo */
- char o_inline[OBD_INLINESZ];
- char o_obdmd[OBD_OBDMDSZ];
- struct list_head o_list;
- struct obd_ops *o_op;
+ obd_id o_id;
+ obd_gr o_gr;
+ obd_time o_atime;
+ obd_time o_mtime;
+ obd_time o_ctime;
+ obd_size o_size;
+ obd_blocks o_blocks;
+ obd_blksize o_blksize;
+ obd_mode o_mode;
+ obd_uid o_uid;
+ obd_gid o_gid;
+ obd_flag o_flags;
+ obd_flag o_obdflags;
+ obd_count o_nlink;
+ obd_count o_generation;
+ obd_flag o_valid; /* hot fields in this obdo */
+ char o_inline[OBD_INLINESZ];
+ char o_obdmd[OBD_OBDMDSZ];
+ struct list_head o_list;
+ struct obd_ops *o_op;
};
-#define OBD_MD_FLALL (~0UL)
-#define OBD_MD_FLID (0x00000001UL)
-#define OBD_MD_FLATIME (0x00000002UL)
-#define OBD_MD_FLMTIME (0x00000004UL)
-#define OBD_MD_FLCTIME (0x00000008UL)
-#define OBD_MD_FLSIZE (0x00000010UL)
-#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_FLNOTOBD (~(OBD_MD_FLOBDMD | OBD_MD_FLOBDFLG | OBD_MD_FLBLOCKS))
+#define OBD_MD_FLALL (~0UL)
+#define OBD_MD_FLID (0x00000001UL)
+#define OBD_MD_FLATIME (0x00000002UL)
+#define OBD_MD_FLMTIME (0x00000004UL)
+#define OBD_MD_FLCTIME (0x00000008UL)
+#define OBD_MD_FLSIZE (0x00000010UL)
+#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_FLNOTOBD (~(OBD_MD_FLOBDMD | OBD_MD_FLOBDFLG | OBD_MD_FLBLOCKS))
/*
* ======== OBD Device Declarations ===========
*/
-#define OBD_PSDEV_MAJOR 186
-#define MAX_OBD_DEVICES 8
-#define MAX_MULTI 16
+#define OBD_PSDEV_MAJOR 186
+#define MAX_OBD_DEVICES 8
+#define MAX_MULTI 16
extern struct obd_device obd_dev[MAX_OBD_DEVICES];
#define OBD_SET_UP 0x2
struct obd_conn {
- struct obd_device *oc_dev;
- uint32_t oc_id;
+ struct obd_device *oc_dev;
+ uint32_t oc_id;
};
/* corresponds to one of the obdx */
struct obd_device {
- struct obd_type *obd_type;
- int obd_minor;
- int obd_flags;
- int obd_refcnt;
- int obd_multi_count;
- struct obd_conn obd_multi_conn[MAX_MULTI];
- unsigned int obd_gen_last_id;
- unsigned long obd_gen_prealloc_quota;
- struct list_head obd_gen_clients;
- union {
- struct ext2_obd ext2;
- struct raid1_obd raid1;
- struct snap_obd snap;
- struct rpc_obd rpc;
- /* struct fc_obd fc; */
- } u;
+ struct obd_type *obd_type;
+ int obd_minor;
+ int obd_flags;
+ int obd_refcnt;
+ int obd_multi_count;
+ struct obd_conn obd_multi_conn[MAX_MULTI];
+ unsigned int obd_gen_last_id;
+ unsigned long obd_gen_prealloc_quota;
+ struct list_head obd_gen_clients;
+ union {
+ struct ext2_obd ext2;
+ struct raid1_obd raid1;
+ struct snap_obd snap;
+ struct rpc_obd rpc;
+ /* struct fc_obd fc; */
+ } u;
};
/*
* ======== OBD Operations Declarations ===========
*/
-#define OBD_BRW_READ (READ)
-#define OBD_BRW_WRITE (WRITE)
-#define OBD_BRW_RWMASK (READ | WRITE)
-#define OBD_BRW_CREATE (0x00000010UL)
+#define OBD_BRW_READ (READ)
+#define OBD_BRW_WRITE (WRITE)
+#define OBD_BRW_RWMASK (READ | WRITE)
+#define OBD_BRW_CREATE (0x00000010UL)
struct obd_ops {
- int (*o_iocontrol)(int cmd, struct obd_conn *, int len, void *karg,
- void *uarg);
- int (*o_get_info)(struct obd_conn *, obd_count keylen, void *key,
- obd_count *vallen, void **val);
- int (*o_set_info)(struct obd_conn *, obd_count keylen, void *key,
- obd_count vallen, void *val);
- int (*o_attach)(struct obd_device *dev, obd_count len, void *data);
- int (*o_detach)(struct obd_device *dev);
- int (*o_setup) (struct obd_device *dev, obd_count len, void *data);
- int (*o_cleanup)(struct obd_device *dev);
- int (*o_connect)(struct obd_conn *conn);
- int (*o_disconnect)(struct obd_conn *conn);
- int (*o_statfs)(struct obd_conn *conn, struct statfs *statfs);
- int (*o_preallocate)(struct obd_conn *, obd_count *req, obd_id *ids);
- int (*o_create)(struct obd_conn *conn, struct obdo *oa);
- int (*o_destroy)(struct obd_conn *conn, struct obdo *oa);
- int (*o_setattr)(struct obd_conn *conn, struct obdo *oa);
- int (*o_getattr)(struct obd_conn *conn, struct obdo *oa);
- int (*o_read)(struct obd_conn *conn, struct obdo *oa, char *buf,
- obd_size *count, obd_off offset);
- int (*o_write)(struct obd_conn *conn, struct obdo *oa, char *buf,
- obd_size *count, obd_off offset);
- int (*o_brw)(int rw, struct obd_conn *conn, obd_count num_oa,
- struct obdo **oa, obd_count *oa_bufs, char **buf,
- obd_size *count, obd_off *offset, obd_flag *flags);
- int (*o_punch)(struct obd_conn *conn, struct obdo *tgt, obd_size count,
- obd_off offset);
- int (*o_sync)(struct obd_conn *conn, struct obdo *tgt, obd_size count,
- obd_off offset);
- int (*o_migrate)(struct obd_conn *conn, struct obdo *dst,
- struct obdo *src, obd_size count, obd_off offset);
- int (*o_copy)(struct obd_conn *dstconn, struct obdo *dst,
- struct obd_conn *srconn, struct obdo *src,
- obd_size count, obd_off offset);
- int (*o_iterate)(struct obd_conn *conn, int (*)(obd_id, obd_gr, void *),
- obd_id *startid, obd_gr group, void *data);
+ int (*o_iocontrol)(int cmd, struct obd_conn *, int len, void *karg,
+ void *uarg);
+ int (*o_get_info)(struct obd_conn *, obd_count keylen, void *key,
+ obd_count *vallen, void **val);
+ int (*o_set_info)(struct obd_conn *, obd_count keylen, void *key,
+ obd_count vallen, void *val);
+ int (*o_attach)(struct obd_device *dev, obd_count len, void *data);
+ int (*o_detach)(struct obd_device *dev);
+ int (*o_setup) (struct obd_device *dev, obd_count len, void *data);
+ int (*o_cleanup)(struct obd_device *dev);
+ int (*o_connect)(struct obd_conn *conn);
+ int (*o_disconnect)(struct obd_conn *conn);
+ int (*o_statfs)(struct obd_conn *conn, struct statfs *statfs);
+ int (*o_preallocate)(struct obd_conn *, obd_count *req, obd_id *ids);
+ int (*o_create)(struct obd_conn *conn, struct obdo *oa);
+ int (*o_destroy)(struct obd_conn *conn, struct obdo *oa);
+ int (*o_setattr)(struct obd_conn *conn, struct obdo *oa);
+ int (*o_getattr)(struct obd_conn *conn, struct obdo *oa);
+ int (*o_read)(struct obd_conn *conn, struct obdo *oa, char *buf,
+ obd_size *count, obd_off offset);
+ int (*o_write)(struct obd_conn *conn, struct obdo *oa, char *buf,
+ obd_size *count, obd_off offset);
+ int (*o_brw)(int rw, struct obd_conn *conn, obd_count num_oa,
+ struct obdo **oa, obd_count *oa_bufs, char **buf,
+ obd_size *count, obd_off *offset, obd_flag *flags);
+ int (*o_punch)(struct obd_conn *conn, struct obdo *tgt, obd_size count,
+ obd_off offset);
+ int (*o_sync)(struct obd_conn *conn, struct obdo *tgt, obd_size count,
+ obd_off offset);
+ int (*o_migrate)(struct obd_conn *conn, struct obdo *dst,
+ struct obdo *src, obd_size count, obd_off offset);
+ int (*o_copy)(struct obd_conn *dstconn, struct obdo *dst,
+ struct obd_conn *srconn, struct obdo *src,
+ obd_size count, obd_off offset);
+ int (*o_iterate)(struct obd_conn *conn, int (*)(obd_id, obd_gr, void *),
+ obd_id *startid, obd_gr group, void *data);
};
-#define OBT(dev) dev->obd_type->typ_ops
-#define OBP(dev,op) dev->obd_type->typ_ops->o_ ## op
+#define OBT(dev) dev->obd_type->typ_ops
+#define OBP(dev,op) dev->obd_type->typ_ops->o_ ## op
/* This value is not arbitrarily chosen. KIO_STATIC_PAGES from linux/iobuf.h */
-#define MAX_IOVEC (KIO_STATIC_PAGES - 1)
+#define MAX_IOVEC (KIO_STATIC_PAGES - 1)
/*
static inline int obdo_has_inline(struct obdo *obdo)
{
- return (obdo->o_valid & OBD_MD_FLINLINE &&
- obdo->o_obdflags & OBD_FL_INLINEDATA);
+ return (obdo->o_valid & OBD_MD_FLINLINE &&
+ obdo->o_obdflags & OBD_FL_INLINEDATA);
};
static inline int obdo_has_obdmd(struct obdo *obdo)
{
- return (obdo->o_valid & OBD_MD_FLOBDMD &&
- obdo->o_obdflags & OBD_FL_OBDMDEXISTS);
+ return (obdo->o_valid & OBD_MD_FLOBDMD &&
+ obdo->o_obdflags & OBD_FL_OBDMDEXISTS);
};
/* support routines */
static __inline__ struct obdo *obdo_alloc(void)
{
- struct obdo *oa = NULL;
+ struct obdo *oa = NULL;
- oa = kmem_cache_alloc(obdo_cachep, SLAB_KERNEL);
- memset(oa, 0, sizeof (*oa));
+ oa = kmem_cache_alloc(obdo_cachep, SLAB_KERNEL);
+ memset(oa, 0, sizeof (*oa));
- return oa;
+ return oa;
}
static __inline__ void obdo_free(struct obdo *oa)
{
- if ( !oa )
- return;
- kmem_cache_free(obdo_cachep, oa);
+ if ( !oa )
+ return;
+ kmem_cache_free(obdo_cachep, oa);
}
static __inline__ struct obdo *obdo_fromid(struct obd_conn *conn, obd_id id,
- obd_flag valid)
+ obd_flag valid)
{
- struct obdo *oa;
- int err;
-
- ENTRY;
- oa = obdo_alloc();
- if ( !oa ) {
- EXIT;
- return ERR_PTR(-ENOMEM);
- }
- memset(oa, 0, sizeof(*oa));
- oa->o_id = id;
- oa->o_valid = valid;
- if ((err = OBP(conn->oc_dev, getattr)(conn, oa))) {
- obdo_free(oa);
- EXIT;
- return ERR_PTR(err);
- }
- EXIT;
- return oa;
+ struct obdo *oa;
+ int err;
+
+ ENTRY;
+ oa = obdo_alloc();
+ if ( !oa ) {
+ EXIT;
+ return ERR_PTR(-ENOMEM);
+ }
+ memset(oa, 0, sizeof(*oa));
+ oa->o_id = id;
+ oa->o_valid = valid;
+ if ((err = OBP(conn->oc_dev, getattr)(conn, oa))) {
+ obdo_free(oa);
+ EXIT;
+ return ERR_PTR(err);
+ }
+ EXIT;
+ return oa;
}
static inline void obdo_from_iattr(struct obdo *oa, struct iattr *attr)
{
- unsigned int ia_valid = attr->ia_valid;
-
- if (ia_valid & ATTR_ATIME) {
- oa->o_atime = attr->ia_atime;
- oa->o_valid |= OBD_MD_FLATIME;
- }
- if (ia_valid & ATTR_MTIME) {
- oa->o_mtime = attr->ia_mtime;
- oa->o_valid |= OBD_MD_FLMTIME;
- }
- if (ia_valid & ATTR_CTIME) {
- oa->o_ctime = attr->ia_ctime;
- oa->o_valid |= OBD_MD_FLCTIME;
- }
- if (ia_valid & ATTR_SIZE) {
- oa->o_size = attr->ia_size;
- oa->o_valid |= OBD_MD_FLSIZE;
- }
- if (ia_valid & ATTR_MODE) {
- oa->o_mode = attr->ia_mode;
- oa->o_valid |= OBD_MD_FLMODE;
- if (!in_group_p(oa->o_gid) && !capable(CAP_FSETID))
- oa->o_mode &= ~S_ISGID;
- }
- if (ia_valid & ATTR_UID)
- {
- oa->o_uid = attr->ia_uid;
- oa->o_valid |= OBD_MD_FLUID;
- }
- if (ia_valid & ATTR_GID) {
- oa->o_gid = attr->ia_gid;
- oa->o_valid |= OBD_MD_FLGID;
- }
+ unsigned int ia_valid = attr->ia_valid;
+
+ if (ia_valid & ATTR_ATIME) {
+ oa->o_atime = attr->ia_atime;
+ oa->o_valid |= OBD_MD_FLATIME;
+ }
+ if (ia_valid & ATTR_MTIME) {
+ oa->o_mtime = attr->ia_mtime;
+ oa->o_valid |= OBD_MD_FLMTIME;
+ }
+ if (ia_valid & ATTR_CTIME) {
+ oa->o_ctime = attr->ia_ctime;
+ oa->o_valid |= OBD_MD_FLCTIME;
+ }
+ if (ia_valid & ATTR_SIZE) {
+ oa->o_size = attr->ia_size;
+ oa->o_valid |= OBD_MD_FLSIZE;
+ }
+ if (ia_valid & ATTR_MODE) {
+ oa->o_mode = attr->ia_mode;
+ oa->o_valid |= OBD_MD_FLMODE;
+ if (!in_group_p(oa->o_gid) && !capable(CAP_FSETID))
+ oa->o_mode &= ~S_ISGID;
+ }
+ if (ia_valid & ATTR_UID)
+ {
+ oa->o_uid = attr->ia_uid;
+ oa->o_valid |= OBD_MD_FLUID;
+ }
+ if (ia_valid & ATTR_GID) {
+ oa->o_gid = attr->ia_gid;
+ oa->o_valid |= OBD_MD_FLGID;
+ }
}
static __inline__ void obdo_cpy_md(struct obdo *dst, struct obdo *src)
{
- CDEBUG(D_INFO, "src obdo %Ld valid 0x%x, dst obdo %Ld\n",
- src->o_id, src->o_valid, dst->o_id);
- if ( src->o_valid & OBD_MD_FLATIME )
- dst->o_atime = src->o_atime;
- if ( src->o_valid & OBD_MD_FLMTIME )
- dst->o_mtime = src->o_mtime;
- if ( src->o_valid & OBD_MD_FLCTIME )
- dst->o_ctime = src->o_ctime;
- if ( src->o_valid & OBD_MD_FLSIZE )
- dst->o_size = src->o_size;
- if ( src->o_valid & OBD_MD_FLBLOCKS ) /* allocation of space */
- dst->o_blocks = src->o_blocks;
- if ( src->o_valid & OBD_MD_FLBLKSZ )
- dst->o_blksize = src->o_blksize;
- if ( src->o_valid & OBD_MD_FLMODE )
- dst->o_mode = src->o_mode;
- if ( src->o_valid & OBD_MD_FLUID )
- dst->o_uid = src->o_uid;
- if ( src->o_valid & OBD_MD_FLGID )
- dst->o_gid = src->o_gid;
- if ( src->o_valid & OBD_MD_FLFLAGS )
- dst->o_flags = src->o_flags;
- /*
- if ( src->o_valid & OBD_MD_FLOBDFLG )
- dst->o_obdflags = src->o_obdflags;
- */
- if ( src->o_valid & OBD_MD_FLNLINK )
- dst->o_nlink = src->o_nlink;
- if ( src->o_valid & OBD_MD_FLGENER )
- dst->o_generation = src->o_generation;
- if ( src->o_valid & OBD_MD_FLINLINE &&
- src->o_obdflags & OBD_FL_INLINEDATA) {
- memcpy(dst->o_inline, src->o_inline, sizeof(src->o_inline));
- dst->o_obdflags |= OBD_FL_INLINEDATA;
- }
- if ( src->o_valid & OBD_MD_FLOBDMD &&
- src->o_obdflags & OBD_FL_OBDMDEXISTS) {
- memcpy(dst->o_obdmd, src->o_obdmd, sizeof(src->o_obdmd));
- dst->o_obdflags |= OBD_FL_OBDMDEXISTS;
- }
-
- dst->o_valid |= src->o_valid;
+ CDEBUG(D_INODE, "src obdo %Ld valid 0x%x, dst obdo %Ld\n",
+ src->o_id, src->o_valid, dst->o_id);
+ if ( src->o_valid & OBD_MD_FLATIME )
+ dst->o_atime = src->o_atime;
+ if ( src->o_valid & OBD_MD_FLMTIME )
+ dst->o_mtime = src->o_mtime;
+ if ( src->o_valid & OBD_MD_FLCTIME )
+ dst->o_ctime = src->o_ctime;
+ if ( src->o_valid & OBD_MD_FLSIZE )
+ dst->o_size = src->o_size;
+ if ( src->o_valid & OBD_MD_FLBLOCKS ) /* allocation of space */
+ dst->o_blocks = src->o_blocks;
+ if ( src->o_valid & OBD_MD_FLBLKSZ )
+ dst->o_blksize = src->o_blksize;
+ if ( src->o_valid & OBD_MD_FLMODE )
+ dst->o_mode = src->o_mode;
+ if ( src->o_valid & OBD_MD_FLUID )
+ dst->o_uid = src->o_uid;
+ if ( src->o_valid & OBD_MD_FLGID )
+ dst->o_gid = src->o_gid;
+ if ( src->o_valid & OBD_MD_FLFLAGS )
+ dst->o_flags = src->o_flags;
+ /*
+ if ( src->o_valid & OBD_MD_FLOBDFLG )
+ dst->o_obdflags = src->o_obdflags;
+ */
+ if ( src->o_valid & OBD_MD_FLNLINK )
+ dst->o_nlink = src->o_nlink;
+ if ( src->o_valid & OBD_MD_FLGENER )
+ dst->o_generation = src->o_generation;
+ if ( src->o_valid & OBD_MD_FLINLINE &&
+ src->o_obdflags & OBD_FL_INLINEDATA) {
+ memcpy(dst->o_inline, src->o_inline, sizeof(src->o_inline));
+ dst->o_obdflags |= OBD_FL_INLINEDATA;
+ }
+ if ( src->o_valid & OBD_MD_FLOBDMD &&
+ src->o_obdflags & OBD_FL_OBDMDEXISTS) {
+ memcpy(dst->o_obdmd, src->o_obdmd, sizeof(src->o_obdmd));
+ dst->o_obdflags |= OBD_FL_OBDMDEXISTS;
+ }
+
+ dst->o_valid |= src->o_valid;
}
static __inline__ void obdo_from_inode(struct obdo *dst, struct inode *src)
{
- if ( dst->o_valid & OBD_MD_FLID )
- dst->o_id = src->i_ino;
- if ( dst->o_valid & OBD_MD_FLATIME )
- dst->o_atime = src->i_atime;
- if ( dst->o_valid & OBD_MD_FLMTIME )
- dst->o_mtime = src->i_mtime;
- if ( dst->o_valid & OBD_MD_FLCTIME )
- dst->o_ctime = src->i_ctime;
- if ( dst->o_valid & OBD_MD_FLSIZE )
- dst->o_size = src->i_size;
- if ( dst->o_valid & OBD_MD_FLBLOCKS ) /* allocation of space */
- dst->o_blocks = src->i_blocks;
- if ( dst->o_valid & OBD_MD_FLBLKSZ )
- dst->o_blksize = src->i_blksize;
- if ( dst->o_valid & OBD_MD_FLMODE )
- dst->o_mode = src->i_mode;
- if ( dst->o_valid & OBD_MD_FLUID )
- dst->o_uid = src->i_uid;
- if ( dst->o_valid & OBD_MD_FLGID )
- dst->o_gid = src->i_gid;
- if ( dst->o_valid & OBD_MD_FLFLAGS )
- dst->o_flags = src->i_flags;
- if ( dst->o_valid & OBD_MD_FLNLINK )
- dst->o_nlink = src->i_nlink;
- if ( dst->o_valid & OBD_MD_FLGENER )
- dst->o_generation = src->i_generation;
+ if ( dst->o_valid & OBD_MD_FLID )
+ dst->o_id = src->i_ino;
+ if ( dst->o_valid & OBD_MD_FLATIME )
+ dst->o_atime = src->i_atime;
+ if ( dst->o_valid & OBD_MD_FLMTIME )
+ dst->o_mtime = src->i_mtime;
+ if ( dst->o_valid & OBD_MD_FLCTIME )
+ dst->o_ctime = src->i_ctime;
+ if ( dst->o_valid & OBD_MD_FLSIZE )
+ dst->o_size = src->i_size;
+ if ( dst->o_valid & OBD_MD_FLBLOCKS ) /* allocation of space */
+ dst->o_blocks = src->i_blocks;
+ if ( dst->o_valid & OBD_MD_FLBLKSZ )
+ dst->o_blksize = src->i_blksize;
+ if ( dst->o_valid & OBD_MD_FLMODE )
+ dst->o_mode = src->i_mode;
+ if ( dst->o_valid & OBD_MD_FLUID )
+ dst->o_uid = src->i_uid;
+ if ( dst->o_valid & OBD_MD_FLGID )
+ dst->o_gid = src->i_gid;
+ if ( dst->o_valid & OBD_MD_FLFLAGS )
+ dst->o_flags = src->i_flags;
+ if ( dst->o_valid & OBD_MD_FLNLINK )
+ dst->o_nlink = src->i_nlink;
+ if ( dst->o_valid & OBD_MD_FLGENER )
+ dst->o_generation = src->i_generation;
}
static __inline__ void obdo_to_inode(struct inode *dst, struct obdo *src)
{
- if ( src->o_valid & OBD_MD_FLID )
- dst->i_ino = src->o_id;
- if ( src->o_valid & OBD_MD_FLATIME )
- dst->i_atime = src->o_atime;
- if ( src->o_valid & OBD_MD_FLMTIME )
- dst->i_mtime = src->o_mtime;
- if ( src->o_valid & OBD_MD_FLCTIME )
- dst->i_ctime = src->o_ctime;
- if ( src->o_valid & OBD_MD_FLSIZE )
- dst->i_size = src->o_size;
- if ( src->o_valid & OBD_MD_FLBLOCKS ) /* allocation of space */
- dst->i_blocks = src->o_blocks;
- if ( src->o_valid & OBD_MD_FLBLKSZ )
- dst->i_blksize = src->o_blksize;
- if ( src->o_valid & OBD_MD_FLMODE )
- dst->i_mode = src->o_mode;
- if ( src->o_valid & OBD_MD_FLUID )
- dst->i_uid = src->o_uid;
- if ( src->o_valid & OBD_MD_FLGID )
- dst->i_gid = src->o_gid;
- if ( src->o_valid & OBD_MD_FLFLAGS )
- dst->i_flags = src->o_flags;
- if ( src->o_valid & OBD_MD_FLNLINK )
- dst->i_nlink = src->o_nlink;
- if ( src->o_valid & OBD_MD_FLGENER )
- dst->i_generation = src->o_generation;
+ if ( src->o_valid & OBD_MD_FLID )
+ dst->i_ino = src->o_id;
+ if ( src->o_valid & OBD_MD_FLATIME )
+ dst->i_atime = src->o_atime;
+ if ( src->o_valid & OBD_MD_FLMTIME )
+ dst->i_mtime = src->o_mtime;
+ if ( src->o_valid & OBD_MD_FLCTIME )
+ dst->i_ctime = src->o_ctime;
+ if ( src->o_valid & OBD_MD_FLSIZE )
+ dst->i_size = src->o_size;
+ if ( src->o_valid & OBD_MD_FLBLOCKS ) /* allocation of space */
+ dst->i_blocks = src->o_blocks;
+ if ( src->o_valid & OBD_MD_FLBLKSZ )
+ dst->i_blksize = src->o_blksize;
+ if ( src->o_valid & OBD_MD_FLMODE )
+ dst->i_mode = src->o_mode;
+ if ( src->o_valid & OBD_MD_FLUID )
+ dst->i_uid = src->o_uid;
+ if ( src->o_valid & OBD_MD_FLGID )
+ dst->i_gid = src->o_gid;
+ if ( src->o_valid & OBD_MD_FLFLAGS )
+ dst->i_flags = src->o_flags;
+ if ( src->o_valid & OBD_MD_FLNLINK )
+ dst->i_nlink = src->o_nlink;
+ if ( src->o_valid & OBD_MD_FLGENER )
+ dst->i_generation = src->o_generation;
}
/* returns FALSE if comparison (by flags) is same, TRUE if changed */
static __inline__ int obdo_cmp_md(struct obdo *dst, struct obdo *src,
- obd_flag compare)
+ obd_flag compare)
{
- int res = 0;
-
- if ( compare & OBD_MD_FLATIME )
- res = (res || (dst->o_atime != src->o_atime));
- if ( compare & OBD_MD_FLMTIME )
- res = (res || (dst->o_mtime != src->o_mtime));
- if ( compare & OBD_MD_FLCTIME )
- res = (res || (dst->o_ctime != src->o_ctime));
- if ( compare & OBD_MD_FLSIZE )
- res = (res || (dst->o_size != src->o_size));
- if ( compare & OBD_MD_FLBLOCKS ) /* allocation of space */
- res = (res || (dst->o_blocks != src->o_blocks));
- if ( compare & OBD_MD_FLBLKSZ )
- res = (res || (dst->o_blksize != src->o_blksize));
- if ( compare & OBD_MD_FLMODE )
- res = (res || (dst->o_mode != src->o_mode));
- if ( compare & OBD_MD_FLUID )
- res = (res || (dst->o_uid != src->o_uid));
- if ( compare & OBD_MD_FLGID )
- res = (res || (dst->o_gid != src->o_gid));
- if ( compare & OBD_MD_FLFLAGS )
- res = (res || (dst->o_flags != src->o_flags));
- if ( compare & OBD_MD_FLNLINK )
- res = (res || (dst->o_nlink != src->o_nlink));
- if ( compare & OBD_MD_FLGENER )
- res = (res || (dst->o_generation != src->o_generation));
- /* XXX Don't know if thses should be included here - wasn't previously
- if ( compare & OBD_MD_FLINLINE )
- res = (res || memcmp(dst->o_inline, src->o_inline));
- if ( compare & OBD_MD_FLOBDMD )
- res = (res || memcmp(dst->o_obdmd, src->o_obdmd));
- */
- return res;
+ int res = 0;
+
+ if ( compare & OBD_MD_FLATIME )
+ res = (res || (dst->o_atime != src->o_atime));
+ if ( compare & OBD_MD_FLMTIME )
+ res = (res || (dst->o_mtime != src->o_mtime));
+ if ( compare & OBD_MD_FLCTIME )
+ res = (res || (dst->o_ctime != src->o_ctime));
+ if ( compare & OBD_MD_FLSIZE )
+ res = (res || (dst->o_size != src->o_size));
+ if ( compare & OBD_MD_FLBLOCKS ) /* allocation of space */
+ res = (res || (dst->o_blocks != src->o_blocks));
+ if ( compare & OBD_MD_FLBLKSZ )
+ res = (res || (dst->o_blksize != src->o_blksize));
+ if ( compare & OBD_MD_FLMODE )
+ res = (res || (dst->o_mode != src->o_mode));
+ if ( compare & OBD_MD_FLUID )
+ res = (res || (dst->o_uid != src->o_uid));
+ if ( compare & OBD_MD_FLGID )
+ res = (res || (dst->o_gid != src->o_gid));
+ if ( compare & OBD_MD_FLFLAGS )
+ res = (res || (dst->o_flags != src->o_flags));
+ if ( compare & OBD_MD_FLNLINK )
+ res = (res || (dst->o_nlink != src->o_nlink));
+ if ( compare & OBD_MD_FLGENER )
+ res = (res || (dst->o_generation != src->o_generation));
+ /* XXX Don't know if thses should be included here - wasn't previously
+ if ( compare & OBD_MD_FLINLINE )
+ res = (res || memcmp(dst->o_inline, src->o_inline));
+ if ( compare & OBD_MD_FLOBDMD )
+ res = (res || memcmp(dst->o_obdmd, src->o_obdmd));
+ */
+ return res;
}
int obd_unregister_type(char *nm);
struct obd_client {
- struct list_head cli_chain;
- struct obd_device *cli_obd;
- unsigned int cli_id;
- unsigned long cli_prealloc_quota;
- struct list_head cli_prealloc_inodes;
+ struct list_head cli_chain;
+ struct obd_device *cli_obd;
+ unsigned int cli_id;
+ unsigned long cli_prealloc_quota;
+ struct list_head cli_prealloc_inodes;
};
struct obd_prealloc_inode {
- struct list_head obd_prealloc_chain;
- unsigned long inode;
+ struct list_head obd_prealloc_chain;
+ unsigned long inode;
};
/* generic operations shared by various OBD types */
struct obd_client *gen_client(struct obd_conn *);
int gen_cleanup(struct obd_device *obddev);
int gen_copy_data(struct obd_conn *dst_conn, struct obdo *dst,
- struct obd_conn *src_conn, struct obdo *src,
- obd_size count, obd_off offset);
+ struct obd_conn *src_conn, struct obdo *src,
+ obd_size count, obd_off offset);
* ======== OBD IOCL Declarations ===========
*/
struct oic_generic {
- uint32_t att_connid;
- int att_typelen;
- void *att_type;
- int att_datalen;
- void *att_data;
+ uint32_t att_connid;
+ int att_typelen;
+ void *att_type;
+ int att_datalen;
+ void *att_data;
};
/* for preallocation */
struct oic_prealloc_s {
- uint32_t conn_id;
- uint32_t alloc; /* user sets it to the number of inodes
- * requesting to be preallocated. kernel
- * sets it to the actual number of
- * succesfully preallocated inodes */
- obd_id ids[32]; /* actual inode numbers */
+ uint32_t conn_id;
+ uint32_t alloc; /* user sets it to the number of inodes
+ * requesting to be preallocated. kernel
+ * sets it to the actual number of
+ * succesfully preallocated inodes */
+ obd_id ids[32]; /* actual inode numbers */
};
/* for getattr, setattr, create, destroy */
struct oic_attr_s {
- uint32_t conn_id;
- struct obdo obdo;
+ uint32_t conn_id;
+ struct obdo obdo;
};
/* for copy, migrate */
struct ioc_mv_s {
- uint32_t src_conn_id;
- struct obdo src;
- uint32_t dst_conn_id;
- struct obdo dst;
+ uint32_t src_conn_id;
+ struct obdo src;
+ uint32_t dst_conn_id;
+ struct obdo dst;
};
/* for read/write */
struct oic_rw_s {
- uint32_t conn_id;
- struct obdo obdo;
- char *buf;
- obd_size count;
- obd_off offset;
+ uint32_t conn_id;
+ struct obdo obdo;
+ char *buf;
+ obd_size count;
+ obd_off offset;
};
/* for punch, sync */
struct oic_range_s {
- uint32_t conn_id;
- struct obdo obdo;
- obd_size count;
- obd_off offset;
+ uint32_t conn_id;
+ struct obdo obdo;
+ obd_size count;
+ obd_off offset;
};
extern void obd_sysctl_init (void);
extern void obd_sysctl_clean (void);
-#define CHKCONN(conn) do { if (!gen_client(conn)) {\
- printk("%s %d invalid client %u\n", __FILE__, __LINE__, \
- conn->oc_id);\
- return -EINVAL; }} while (0)
+#define CHKCONN(conn) do { if (!gen_client(conn)) {\
+ printk("%s %d invalid client %u\n", __FILE__, __LINE__, \
+ conn->oc_id);\
+ return -EINVAL; }} while (0)
#endif
struct ext2_obd {
- struct super_block * ext2_sb;
+ struct super_block * ext2_sb;
};
unsigned long ext2_count_free_blocks (struct super_block * sb);
int ext2_group_sparse(int group);
struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
- unsigned int block_group,
- struct buffer_head ** bh);
+ unsigned int block_group,
+ struct buffer_head ** bh);
/* bitmap.c */
unsigned long ext2_count_free(struct buffer_head * map, unsigned int numchars);
extern struct inode_operations ext2_file_inode_operations;
/* fsync.c */
-int ext2_sync_file(struct file * file, struct dentry *dentry);
+int ext2_sync_file(struct file * file, struct dentry *dentry, int);
/* ialloc.c */
void ext2_free_inode (struct inode * inode);
-struct inode * ext2_new_inode (const struct inode * dir, int mode,
- int * err);
+struct inode * ext2_new_inode (const struct inode * dir, int );
unsigned long ext2_count_free_inodes (struct super_block * sb);
void ext2_check_inodes_bitmap (struct super_block * sb);
int load_inode_bitmap (struct super_block * sb,
- unsigned int block_group);
+ unsigned int block_group);
/* inode.c */
-inline long ext2_block_map (struct inode * inode, long block);
+int ext2_bmap(struct address_space *mapping, long block);
+int ext2_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create);
/* super.c */
extern struct super_operations ext2_sops;
int obd_remount (struct super_block * sb, int * flags, char * data);
struct super_block * ext2_read_super (struct super_block * sb, void * data,
- int silent);
+ int silent);
/* punch.c */
void ext2_truncate (struct inode * inode);
int ext2_punch (struct inode * inode, loff_t start, size_t count);
-static inline struct page *addr_to_page(char *buf)
-{
- unsigned long addr = (unsigned long)buf;
- unsigned long map_nr;
-
-#ifdef CONFIG_DISCONTIGMEM
- if (addr == 0) return;
-#endif
- map_nr = MAP_NR(addr);
- if (map_nr < max_mapnr)
- return mem_map + map_nr;
- else
- return 0;
-}
-
#endif
#endif
struct raid1_obd {
- unsigned int raid1_count; /* how many replicas */
- /* devices to replicate on */
- struct obd_device *raid1_devlist[MAX_RAID1];
- /* connections we make */
- struct obd_conn_info raid1_connections[MAX_RAID1];
- struct list_head raid1_clients; /* clients we have */
+ unsigned int raid1_count; /* how many replicas */
+ /* devices to replicate on */
+ struct obd_device *raid1_devlist[MAX_RAID1];
+ /* connections we make */
+ struct obd_conn_info raid1_connections[MAX_RAID1];
+ struct list_head raid1_clients; /* clients we have */
};
unsigned long ext2_count_free_blocks (struct super_block * sb);
int ext2_group_sparse(int group);
struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
- unsigned int block_group,
- struct buffer_head ** bh);
+ unsigned int block_group,
+ struct buffer_head ** bh);
/* bitmap.c */
unsigned long ext2_count_free(struct buffer_head * map, unsigned int numchars);
/* ialloc.c */
extern void ext2_free_inode (struct inode * inode);
-extern struct inode * ext2_new_inode (const struct inode * dir, int mode,
- int * err);
+extern struct inode * ext2_new_inode (const struct inode * dir, int mode);
extern unsigned long ext2_count_free_inodes (struct super_block * sb);
extern void ext2_check_inodes_bitmap (struct super_block * sb);
extern int load_inode_bitmap (struct super_block * sb,
- unsigned int block_group);
+ unsigned int block_group);
/* inode.c */
void obd_read_inode (struct inode * inode);
int obd_remount (struct super_block * sb, int * flags, char * data);
struct super_block * ext2_read_super (struct super_block * sb, void * data,
- int silent);
+ int silent);
/* truncate.c */
void obd_truncate (struct inode * inode);
#ifndef __OBD_RPC_H
#define __OBD_RPC_H
+#include <linux/sunrpc/svc.h>
#define OBD_TGT_VERSION 001
#define OBD_TGT_TCP 0x1
struct obd_target {
- struct sockaddr_in tgt_addr;
- int tgt_flags;
- int tgt_timeo;
- int tgt_retrans;
- int tgt_hostnamelen;
- char tgt_hostname[0];
-
+ struct sockaddr_in tgt_addr;
+ int tgt_flags;
+ int tgt_timeo;
+ int tgt_retrans;
+ int tgt_hostnamelen;
+ char tgt_hostname[0];
+
};
struct rpc_obd {
- struct rpc_clnt * handle; /* RPC client handle */
- struct sockaddr_in addr;
- int flags; /* various flags */
- int timeo;
- int retrans;
- int rsize; /* read size */
- int wsize; /* write size */
- unsigned int bsize; /* server block size */
- char * hostname; /* remote hostname */
+ struct rpc_clnt * handle; /* RPC client handle */
+ struct sockaddr_in addr;
+ int flags; /* various flags */
+ int timeo;
+ int retrans;
+ int rsize; /* read size */
+ int wsize; /* write size */
+ unsigned int bsize; /* server block size */
+ char * hostname; /* remote hostname */
};
-#define OBD_PROGRAM 300001
-#define OBD_VERSION 1
-#define OBDPROC_NULL 0
-#define OBDPROC_ECHOINT 1
+#define OBD_PROGRAM 300001
+#define OBD_VERSION 1
+#define OBDPROC_NULL 0
+#define OBDPROC_ECHOINT 1
#ifdef OBD_NEED_XDR_TYPES
struct obd_echoint_in {
- __u32 in;
+ __u32 in;
};
struct obd_echoint_out {
- __u32 out;
+ __u32 out;
};
#define CMD(cmd) (( cmd == READ ) ? "read" : "write")
/* debugging masks */
-#define D_PSDEV 0x001 /* debug information from psdev.c */
+#define D_PSDEV 0x001 /* debug information from psdev.c */
#define D_INODE 0x002
#define D_SUPER 0x004
#define D_SNAP 0x008
#define D_UNUSED4 0x010
-#define D_WARNING 0x020 /* misc warnings */
-#define D_EXT2 0x040 /* anything from ext2_debug */
-#define D_MALLOC 0x080 /* print malloc, free information */
-#define D_CACHE 0x100 /* cache-related items */
-#define D_INFO 0x200 /* general information, especially from interface.c */
-#define D_IOCTL 0x400 /* ioctl related information */
-#define D_BLOCKS 0x800 /* ext2 block allocation */
-#define D_RPC 0x1000 /* rpc communications */
+#define D_WARNING 0x020 /* misc warnings */
+#define D_EXT2 0x040 /* anything from ext2_debug */
+#define D_MALLOC 0x080 /* print malloc, free information */
+#define D_CACHE 0x100 /* cache-related items */
+#define D_INFO 0x200 /* general information, especially from interface.c */
+#define D_IOCTL 0x400 /* ioctl related information */
+#define D_BLOCKS 0x800 /* ext2 block allocation */
+#define D_RPC 0x1000 /* rpc communications */
#define D_PUNCH 0x2000
#define CDEBUG(mask, format, a...) \
- do { \
- if (obd_debug_level & mask) { \
- printk("(%s:%d):", __FUNCTION__, __LINE__); \
- printk(format, ## a); } \
- } while (0)
+ do { \
+ if (obd_debug_level & mask) { \
+ printk("(%s:%d):", __FUNCTION__, __LINE__); \
+ printk(format, ## a); } \
+ } while (0)
-#define ENTRY if (obd_print_entry) \
- printk(KERN_INFO "Process %d entered %s\n", current->pid, __FUNCTION__)
+#define ENTRY if (obd_print_entry) \
+ printk(KERN_INFO "Process %d entered %s\n", current->pid, __FUNCTION__)
-#define EXIT if (obd_print_entry) \
- printk(KERN_INFO "Process %d leaving %s [%d]\n", current->pid, \
- __FUNCTION__, __LINE__)
+#define EXIT if (obd_print_entry) \
+ printk(KERN_INFO "Process %d leaving %s [%d]\n", current->pid, \
+ __FUNCTION__, __LINE__)
/* Inode common information printed out (used by obdfs and ext2obd inodes) */
-#define ICDEBUG(inode) { \
- CDEBUG(D_INFO, \
- "ino %ld, atm %ld, mtm %ld, ctm %ld, size %Ld, blocks %ld\n",\
- inode->i_ino, inode->i_atime, inode->i_mtime, inode->i_ctime,\
- inode->i_size, inode->i_blocks); \
- CDEBUG(D_INFO, "mode %o, uid %d, gid %d, nlnk %d, count %d\n", \
- inode->i_mode, inode->i_uid, inode->i_gid, inode->i_nlink,\
- inode->i_count); \
+#define ICDEBUG(inode) { \
+ CDEBUG(D_INFO, \
+ "ino %ld, atm %ld, mtm %ld, ctm %ld, size %Ld, blocks %ld\n",\
+ inode->i_ino, inode->i_atime, inode->i_mtime, inode->i_ctime,\
+ inode->i_size, inode->i_blocks); \
+ CDEBUG(D_INFO, "mode %o, uid %d, gid %d, nlnk %d, count %d\n", \
+ inode->i_mode, inode->i_uid, inode->i_gid, inode->i_nlink,\
+ atomic_read(&inode->i_count)); \
}
/* Ext2 inode information */
-#define EXDEBUG(inode) { \
- ICDEBUG(inode); \
- CDEBUG(D_INFO, "ext2 blocks: %d %d %d %d %d %d %d %d\n", \
- inode->u.ext2_i.i_data[0], inode->u.ext2_i.i_data[1], \
- inode->u.ext2_i.i_data[2], inode->u.ext2_i.i_data[3], \
- inode->u.ext2_i.i_data[4], inode->u.ext2_i.i_data[5], \
- inode->u.ext2_i.i_data[6], inode->u.ext2_i.i_data[7]); \
+#define EXDEBUG(inode) { \
+ ICDEBUG(inode); \
+ CDEBUG(D_INFO, "ext2 blocks: %d %d %d %d %d %d %d %d\n", \
+ inode->u.ext2_i.i_data[0], inode->u.ext2_i.i_data[1], \
+ inode->u.ext2_i.i_data[2], inode->u.ext2_i.i_data[3], \
+ inode->u.ext2_i.i_data[4], inode->u.ext2_i.i_data[5], \
+ inode->u.ext2_i.i_data[6], inode->u.ext2_i.i_data[7]); \
}
/* OBDFS inode information */
-#define OIDEBUG(inode) { \
- ICDEBUG(inode); \
- CDEBUG(D_INFO,"oinfo: flags 0x%08x\n", obdfs_i2info(inode)->oi_flags);\
- /* obdfs_print_plist(inode); */ \
+#define OIDEBUG(inode) { \
+ ICDEBUG(inode); \
+ CDEBUG(D_INFO,"oinfo: flags 0x%08x\n", obdfs_i2info(inode)->oi_flags);\
+ /* obdfs_print_plist(inode); */ \
}
-#define ODEBUG(obdo) { \
- CDEBUG(D_INFO, "id %ld, atm %ld, mtm %ld, ctm %ld, " \
- "size %ld, blocks %ld\n", \
- (long)(obdo)->o_id, (long)(obdo)->o_atime, \
- (long)(obdo)->o_mtime, (long)(obdo)->o_ctime, \
- (long)(obdo)->o_size, (long)(obdo)->o_blocks); \
- CDEBUG(D_INFO, " mode %o, uid %d, gid %d, flg 0x%0x, " \
- "obdflg 0x%0x, nlnk %d, valid 0x%0x\n", \
- (obdo)->o_mode, (obdo)->o_uid, (obdo)->o_gid, (obdo)->o_flags,\
- (obdo)->o_obdflags, (obdo)->o_nlink, (obdo)->o_valid); \
+#define ODEBUG(obdo) { \
+ CDEBUG(D_INFO, "id %ld, atm %ld, mtm %ld, ctm %ld, " \
+ "size %ld, blocks %ld\n", \
+ (long)(obdo)->o_id, (long)(obdo)->o_atime, \
+ (long)(obdo)->o_mtime, (long)(obdo)->o_ctime, \
+ (long)(obdo)->o_size, (long)(obdo)->o_blocks); \
+ CDEBUG(D_INFO, " mode %o, uid %d, gid %d, flg 0x%0x, " \
+ "obdflg 0x%0x, nlnk %d, valid 0x%0x\n", \
+ (obdo)->o_mode, (obdo)->o_uid, (obdo)->o_gid, (obdo)->o_flags,\
+ (obdo)->o_obdflags, (obdo)->o_nlink, (obdo)->o_valid); \
}
-#define PDEBUG(page,msg) { \
- if (page){ \
- char *uptodate = (Page_Uptodate(page)) ? "upto" : "outof";\
- char *locked = (PageLocked(page)) ? "" : "un"; \
- char *buffer = page->buffers ? "buffer" : ""; \
- int count = page_count(page); \
- long index = page->index; \
- CDEBUG(D_CACHE, "%s: ** off %ld, %sdate, %slocked, flag %ld,"\
- " cnt %d page 0x%p pages %ld virt %lx %s**\n", \
- msg, index, uptodate, locked, page->flags, count,\
- page, page->mapping ? page->mapping->nrpages : -1,\
- page->virtual, buffer); \
- } else \
- CDEBUG(D_CACHE, "** %s: no page\n", msg); \
+#define PDEBUG(page,msg) { \
+ if (page){ \
+ char *uptodate = (Page_Uptodate(page)) ? "upto" : "outof";\
+ char *locked = (PageLocked(page)) ? "" : "un"; \
+ char *buffer = page->buffers ? "buffer" : ""; \
+ int count = page_count(page); \
+ long index = page->index; \
+ CDEBUG(D_CACHE, "%s: ** off %ld, %sdate, %slocked, flag %ld,"\
+ " cnt %d page 0x%p pages %ld virt %lx %s**\n", \
+ msg, index, uptodate, locked, page->flags, count,\
+ page, page->mapping ? page->mapping->nrpages : -1,\
+ page->virtual, buffer); \
+ } else \
+ CDEBUG(D_CACHE, "** %s: no page\n", msg); \
}
#if 0
static inline struct inode *obd_iget(struct super_block *sb, unsigned long ino)
{
- struct inode *inode;
-
- if ((inode = iget(sb, ino)) == NULL)
- CDEBUG(D_INODE, "NULL in iget for %ld\n", ino);
- else
- obd_inodes++;
- return inode;
+ struct inode *inode;
+
+ if ((inode = iget(sb, ino)) == NULL)
+ CDEBUG(D_INODE, "NULL in iget for %ld\n", ino);
+ else
+ obd_inodes++;
+ return inode;
}
static inline void obd_iput(struct inode *inode)
{
- if (inode == NULL)
- CDEBUG(D_INODE, "NULL in iput\n");
- else
- obd_inodes--;
+ if (inode == NULL)
+ CDEBUG(D_INODE, "NULL in iput\n");
+ else
+ obd_inodes--;
}
#endif
-#define OBD_ALLOC(ptr, cast, size) \
-do { \
- if (size <= 4096) { \
- ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL); \
- CDEBUG(D_MALLOC, "kmalloced: %d at %x.\n", \
- (int) size, (int) ptr); \
- } else { \
- ptr = (cast)vmalloc((unsigned long) size); \
- CDEBUG(D_MALLOC, "vmalloced: %d at %x.\n", \
- (int) size, (int) ptr); \
- } \
- if (ptr == 0) { \
- printk("kernel malloc returns 0 at %s:%d\n", \
- __FILE__, __LINE__); \
- } else { \
- memset(ptr, 0, size); \
- obd_memory += size; \
- } \
+#define OBD_ALLOC(ptr, cast, size) \
+do { \
+ if (size <= 4096) { \
+ ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL); \
+ CDEBUG(D_MALLOC, "kmalloced: %d at %x.\n", \
+ (int) size, (int) ptr); \
+ } else { \
+ ptr = (cast)vmalloc((unsigned long) size); \
+ CDEBUG(D_MALLOC, "vmalloced: %d at %x.\n", \
+ (int) size, (int) ptr); \
+ } \
+ if (ptr == 0) { \
+ printk("kernel malloc returns 0 at %s:%d\n", \
+ __FILE__, __LINE__); \
+ } else { \
+ memset(ptr, 0, size); \
+ obd_memory += size; \
+ } \
} while (0)
-#define OBD_FREE(ptr,size) \
-do { \
- if (size <= 4096) { \
- kfree_s((ptr), (size)); \
- CDEBUG(D_MALLOC, "kfreed: %d at %x.\n", \
- (int) size, (int) ptr); \
- } else { \
- vfree((ptr)); \
- CDEBUG(D_MALLOC, "vfreed: %d at %x.\n", \
- (int) size, (int) ptr); \
- } \
- obd_memory -= size; \
+#define OBD_FREE(ptr,size) \
+do { \
+ if (size <= 4096) { \
+ kfree((ptr)); \
+ CDEBUG(D_MALLOC, "kfreed: %d at %x.\n", \
+ (int) size, (int) ptr); \
+ } else { \
+ vfree((ptr)); \
+ CDEBUG(D_MALLOC, "vfreed: %d at %x.\n", \
+ (int) size, (int) ptr); \
+ } \
+ obd_memory -= size; \
} while (0)
/*
- * An implementation of a loadable kernel mode driver providing
- * multiple kernel/user space bidirectional communications links.
+ * An implementation of a loadable kernel mode driver providing
+ * multiple kernel/user space bidirectional communications links.
*
- * Author: Alan Cox <alan@cymru.net>
+ * Author: Alan Cox <alan@cymru.net>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
*
* Adapted to become the Linux 2.0 Coda pseudo device
* Peter Braam <braam@maths.ox.ac.uk>
#include <linux/obd_class.h>
static int obd_init_magic;
-int obd_print_entry = 0;
-int obd_debug_level = ~D_INFO;
+int obd_print_entry = 1;
+int obd_debug_level = ~0;
long obd_memory = 0;
struct obd_device obd_dev[MAX_OBD_DEVICES];
struct list_head obd_types;
/* called when opening /dev/obdNNN */
static int obd_class_open(struct inode * inode, struct file * file)
{
- int dev;
+ int dev;
ENTRY;
- if (!inode)
- return -EINVAL;
- dev = MINOR(inode->i_rdev);
- if (dev >= MAX_OBD_DEVICES)
- return -ENODEV;
- obd_dev[dev].obd_refcnt++;
- CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
- obd_dev[dev].obd_refcnt);
+ if (!inode)
+ return -EINVAL;
+ dev = MINOR(inode->i_rdev);
+ if (dev >= MAX_OBD_DEVICES)
+ return -ENODEV;
+ obd_dev[dev].obd_refcnt++;
+ CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
+ obd_dev[dev].obd_refcnt);
MOD_INC_USE_COUNT;
EXIT;
/* called when closing /dev/obdNNN */
static int obd_class_release(struct inode * inode, struct file * file)
{
- int dev;
+ int dev;
ENTRY;
- if (!inode)
- return -EINVAL;
- dev = MINOR(inode->i_rdev);
- if (dev >= MAX_OBD_DEVICES)
- return -ENODEV;
- fsync_dev(inode->i_rdev);
- if (obd_dev[dev].obd_refcnt <= 0)
- printk(KERN_ALERT __FUNCTION__ ": refcount(%d) <= 0\n",
- obd_dev[dev].obd_refcnt);
- obd_dev[dev].obd_refcnt--;
-
- CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
- obd_dev[dev].obd_refcnt);
+ if (!inode)
+ return -EINVAL;
+ dev = MINOR(inode->i_rdev);
+ if (dev >= MAX_OBD_DEVICES)
+ return -ENODEV;
+ fsync_dev(inode->i_rdev);
+ if (obd_dev[dev].obd_refcnt <= 0)
+ printk(KERN_ALERT __FUNCTION__ ": refcount(%d) <= 0\n",
+ obd_dev[dev].obd_refcnt);
+ obd_dev[dev].obd_refcnt--;
+
+ CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
+ obd_dev[dev].obd_refcnt);
MOD_DEC_USE_COUNT;
EXIT;
/* support function */
static struct obd_type *obd_nm_to_type(char *nm)
{
- struct list_head *tmp;
- struct obd_type *type;
- CDEBUG(D_INFO, "SEARCH %s\n", nm);
-
- tmp = &obd_types;
- while ( (tmp = tmp->next) != &obd_types ) {
- type = list_entry(tmp, struct obd_type, typ_chain);
- CDEBUG(D_INFO, "TYP %s\n", type->typ_name);
- if (strlen(type->typ_name) == strlen(nm) &&
- strcmp(type->typ_name, nm) == 0 ) {
- return type;
- }
- }
- return NULL;
+ struct list_head *tmp;
+ struct obd_type *type;
+ CDEBUG(D_INFO, "SEARCH %s\n", nm);
+
+ tmp = &obd_types;
+ while ( (tmp = tmp->next) != &obd_types ) {
+ type = list_entry(tmp, struct obd_type, typ_chain);
+ CDEBUG(D_INFO, "TYP %s\n", type->typ_name);
+ if (strlen(type->typ_name) == strlen(nm) &&
+ strcmp(type->typ_name, nm) == 0 ) {
+ return type;
+ }
+ }
+ return NULL;
}
static int getdata(int len, void **data)
{
- void *tmp = NULL;
-
- if (!len) {
- *data = NULL;
- return 0;
- }
-
- CDEBUG(D_MALLOC, "len %d, add %p\n", len, *data);
-
- OBD_ALLOC(tmp, void *, len);
- if ( !tmp )
- return -ENOMEM;
-
- memset(tmp, 0, len);
- if ( copy_from_user(tmp, *data, len)) {
- OBD_FREE(tmp, len);
- return -EFAULT;
- }
- *data = tmp;
-
- return 0;
+ void *tmp = NULL;
+
+ if (!len) {
+ *data = NULL;
+ return 0;
+ }
+
+ CDEBUG(D_MALLOC, "len %d, add %p\n", len, *data);
+
+ OBD_ALLOC(tmp, void *, len);
+ if ( !tmp )
+ return -ENOMEM;
+
+ memset(tmp, 0, len);
+ if ( copy_from_user(tmp, *data, len)) {
+ OBD_FREE(tmp, len);
+ return -EFAULT;
+ }
+ *data = tmp;
+
+ return 0;
}
/* to control /dev/obdNNN */
static int obd_class_ioctl (struct inode * inode, struct file * filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- struct obd_device *obddev;
- /* NOTE this must be larger than any of the ioctl data structs */
- char buf[1024];
- void *tmp_buf = buf;
- struct obd_conn conn;
- int err, dev;
- long int cli_id; /* connect, disconnect */
-
- if (!inode) {
- CDEBUG(D_IOCTL, "invalid inode\n");
- return -EINVAL;
- }
-
- dev = MINOR(inode->i_rdev);
- if (dev > MAX_OBD_DEVICES)
- return -ENODEV;
- obddev = &obd_dev[dev];
- conn.oc_dev = obddev;
-
- switch (cmd) {
- case TCGETS:
- return -EINVAL;
- case OBD_IOC_ATTACH: {
- struct obd_type *type;
- struct oic_generic *input = tmp_buf;
- char *nm;
-
- ENTRY;
- /* have we attached a type to this device */
- if ( obddev->obd_type ||
- (obddev->obd_flags & OBD_ATTACHED) ){
- CDEBUG(D_IOCTL,
- "OBD Device %d already attached to type %s.\n",
- dev, obddev->obd_type->typ_name);
- EXIT;
- return -EBUSY;
- }
-
- /* get data structures */
- err = copy_from_user(input, (void *)arg, sizeof(*input));
- if ( err ) {
- EXIT;
- return err;
- }
-
- err = getdata(input->att_typelen + 1, &input->att_type);
- if ( err ) {
- EXIT;
- return err;
- }
-
- /* find the type */
- nm = input->att_type;
- type = obd_nm_to_type(nm);
+ struct obd_device *obddev;
+ /* NOTE this must be larger than any of the ioctl data structs */
+ char buf[1024];
+ void *tmp_buf = buf;
+ struct obd_conn conn;
+ int err, dev;
+ long int cli_id; /* connect, disconnect */
+
+ if (!inode) {
+ CDEBUG(D_IOCTL, "invalid inode\n");
+ return -EINVAL;
+ }
+
+ dev = MINOR(inode->i_rdev);
+ if (dev > MAX_OBD_DEVICES)
+ return -ENODEV;
+ obddev = &obd_dev[dev];
+ conn.oc_dev = obddev;
+
+ switch (cmd) {
+ case TCGETS:
+ return -EINVAL;
+ case OBD_IOC_ATTACH: {
+ struct obd_type *type;
+ struct oic_generic *input = tmp_buf;
+ char *nm;
+
+ ENTRY;
+ /* have we attached a type to this device */
+ if ( obddev->obd_type ||
+ (obddev->obd_flags & OBD_ATTACHED) ){
+ CDEBUG(D_IOCTL,
+ "OBD Device %d already attached to type %s.\n",
+ dev, obddev->obd_type->typ_name);
+ EXIT;
+ return -EBUSY;
+ }
+
+ /* get data structures */
+ err = copy_from_user(input, (void *)arg, sizeof(*input));
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ err = getdata(input->att_typelen + 1, &input->att_type);
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ /* find the type */
+ nm = input->att_type;
+ type = obd_nm_to_type(nm);
#ifdef CONFIG_KMOD
- if ( !type ) {
- if ( !request_module(nm) ) {
- CDEBUG(D_PSDEV, "Loaded module '%s'\n", nm);
- type = obd_nm_to_type(nm);
- } else {
- CDEBUG(D_PSDEV, "Can't load module '%s'\n", nm);
- }
- }
+ if ( !type ) {
+ if ( !request_module(nm) ) {
+ CDEBUG(D_PSDEV, "Loaded module '%s'\n", nm);
+ type = obd_nm_to_type(nm);
+ } else {
+ CDEBUG(D_PSDEV, "Can't load module '%s'\n", nm);
+ }
+ }
#endif
- OBD_FREE(input->att_type, input->att_typelen + 1);
- if ( !type ) {
- printk(__FUNCTION__ ": unknown obd type dev %d\n",
- dev);
- EXIT;
- return -EINVAL;
- }
- obddev->obd_type = type;
-
- /* get the attach data */
- err = getdata(input->att_datalen, &input->att_data);
- if ( err ) {
- EXIT;
- return err;
- }
-
- INIT_LIST_HEAD(&obddev->obd_gen_clients);
- obddev->obd_multi_count = 0;
-
- CDEBUG(D_IOCTL, "Attach %d, datalen %d, type %s\n",
- dev, input->att_datalen, obddev->obd_type->typ_name);
- /* maybe we are done */
- if ( !OBT(obddev) || !OBP(obddev, attach) ) {
- obddev->obd_flags |= OBD_ATTACHED;
- type->typ_refcnt++;
- CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
- type->typ_refcnt);
- if (input->att_data)
- OBD_FREE(input->att_data, input->att_datalen);
- MOD_INC_USE_COUNT;
- EXIT;
- return 0;
- }
-
- /* do the attach */
- err = OBP(obddev, attach)(obddev, input->att_datalen,
- input->att_data);
- if (input->att_data)
- OBD_FREE(input->att_data, input->att_datalen);
-
- if ( err ) {
- obddev->obd_flags &= ~OBD_ATTACHED;
- obddev->obd_type = NULL;
- EXIT;
- } else {
- obddev->obd_flags |= OBD_ATTACHED;
- type->typ_refcnt++;
- CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
- type->typ_refcnt);
- MOD_INC_USE_COUNT;
- EXIT;
- }
- return err;
- }
-
- case OBD_IOC_DETACH: {
-
- ENTRY;
- if (obddev->obd_flags & OBD_SET_UP) {
- EXIT;
- return -EBUSY;
- }
- if (! (obddev->obd_flags & OBD_ATTACHED) ) {
- CDEBUG(D_IOCTL, "Device not attached\n");
- EXIT;
- return -ENODEV;
- }
- if ( !list_empty(&obddev->obd_gen_clients) ) {
- CDEBUG(D_IOCTL, "Device has connected clients\n");
- EXIT;
- return -EBUSY;
- }
-
- CDEBUG(D_PSDEV, "Detach %d, type %s\n", dev,
- obddev->obd_type->typ_name);
- obddev->obd_flags &= ~OBD_ATTACHED;
- obddev->obd_type->typ_refcnt--;
- CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
- obddev->obd_type->typ_refcnt);
- obddev->obd_type = NULL;
- MOD_DEC_USE_COUNT;
- EXIT;
- return 0;
- }
-
- case OBD_IOC_SETUP: {
- struct ioc_setup {
- int setup_datalen;
- void *setup_data;
- } *setup;
- setup = tmp_buf;
-
- ENTRY;
- /* have we attached a type to this device */
- if (!(obddev->obd_flags & OBD_ATTACHED)) {
- CDEBUG(D_IOCTL, "Device not attached\n");
- EXIT;
- return -ENODEV;
- }
-
- /* has this been done already? */
- if ( obddev->obd_flags & OBD_SET_UP ) {
- CDEBUG(D_IOCTL, "Device %d already setup (type %s)\n",
- dev, obddev->obd_type->typ_name);
- EXIT;
- return -EBUSY;
- }
-
- /* get main structure */
- err = copy_from_user(setup, (void *) arg, sizeof(*setup));
- if (err) {
- EXIT;
- return err;
- }
-
- err = getdata(setup->setup_datalen, &setup->setup_data);
- if (err) {
- EXIT;
- return err;
- }
-
- /* do the setup */
- CDEBUG(D_PSDEV, "Setup %d, type %s\n", dev,
- obddev->obd_type->typ_name);
- if ( !OBT(obddev) || !OBP(obddev, setup) ) {
- obddev->obd_type->typ_refcnt++;
- CDEBUG(D_PSDEV, "Dev %d refcount now %d\n",
- dev, obddev->obd_type->typ_refcnt);
- if (setup->setup_data)
- OBD_FREE(setup->setup_data,
- setup->setup_datalen);
- obddev->obd_flags |= OBD_SET_UP;
- EXIT;
- return 0;
- }
-
- err = OBP(obddev, setup)(obddev, setup->setup_datalen,
- setup->setup_data);
-
- if ( err ) {
- obddev->obd_flags &= ~OBD_SET_UP;
- EXIT;
- } else {
- obddev->obd_type->typ_refcnt++;
- CDEBUG(D_PSDEV, "Dev %d refcount now %d\n",
- dev, obddev->obd_type->typ_refcnt);
- obddev->obd_flags |= OBD_SET_UP;
- EXIT;
- }
- if (setup->setup_data)
- OBD_FREE(setup->setup_data, setup->setup_datalen);
- return err;
- }
- case OBD_IOC_CLEANUP: {
- ENTRY;
- /* has this minor been registered? */
- if (!obddev->obd_type) {
- CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
- EXIT;
- return -ENODEV;
- }
-
- if ( !obddev->obd_type->typ_refcnt ) {
- CDEBUG(D_IOCTL, "dev %d has refcount (%d)!\n",
- dev, obddev->obd_type->typ_refcnt);
- EXIT;
- return -EBUSY;
- }
-
- if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
- (!(obddev->obd_flags & OBD_ATTACHED))) {
- CDEBUG(D_IOCTL, "device not attached or set up\n");
- EXIT;
- return -ENODEV;
- }
-
- if ( !OBT(obddev) || !OBP(obddev, cleanup) )
- goto cleanup_out;
-
- /* cleanup has no argument */
- err = OBP(obddev, cleanup)(obddev);
- if ( err ) {
- EXIT;
- return err;
- }
-
- cleanup_out:
- obddev->obd_flags &= ~OBD_SET_UP;
- obddev->obd_type->typ_refcnt--;
- CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
- obddev->obd_type->typ_refcnt);
- EXIT;
- return 0;
- }
- case OBD_IOC_CONNECT:
- {
- if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
- (!(obddev->obd_flags & OBD_ATTACHED))) {
- CDEBUG(D_IOCTL, "Device not attached or set up\n");
- return -ENODEV;
- }
-
- if ( !OBT(obddev) || !OBP(obddev, connect) )
- return -EOPNOTSUPP;
-
- err = OBP(obddev, connect)(&conn);
- if ( err )
- return err;
-
- return copy_to_user((int *)arg, &conn.oc_id,
- sizeof(uint32_t));
- }
- case OBD_IOC_DISCONNECT:
- /* frees data structures */
- /* has this minor been registered? */
- if (!obddev->obd_type)
- return -ENODEV;
-
- get_user(cli_id, (int *) arg);
- conn.oc_id = cli_id;
-
- if ( !OBT(obddev) || !OBP(obddev, disconnect))
- return -EOPNOTSUPP;
-
- OBP(obddev, disconnect)(&conn);
- return 0;
-
- case OBD_IOC_SYNC: {
- struct oic_range_s *range = tmp_buf;
-
- if (!obddev->obd_type)
- return -ENODEV;
-
- err = copy_from_user(range, (const void *)arg, sizeof(*range));
-
- if ( err ) {
- EXIT;
- return err;
- }
-
- if ( !OBT(obddev) || !OBP(obddev, sync) ) {
- err = -EOPNOTSUPP;
- EXIT;
- return err;
- }
-
- /* XXX sync needs to be tested/verified */
- err = OBP(obddev, sync)(&conn, &range->obdo, range->count,
- range->offset);
-
- if ( err ) {
- EXIT;
- return err;
- }
-
- return put_user(err, (int *) arg);
- }
- case OBD_IOC_CREATE: {
- struct oic_attr_s *attr = tmp_buf;
-
- err = copy_from_user(attr, (const void *)arg, sizeof(*attr));
- if (err) {
- EXIT;
- return err;
- }
-
- /* has this minor been registered? */
- if ( !(obddev->obd_flags & OBD_ATTACHED) ||
- !(obddev->obd_flags & OBD_SET_UP)) {
- CDEBUG(D_IOCTL, "Device not attached or set up\n");
- return -ENODEV;
- }
- conn.oc_id = attr->conn_id;
-
- if ( !OBT(obddev) || !OBP(obddev, create) )
- return -EOPNOTSUPP;
-
- err = OBP(obddev, create)(&conn, &attr->obdo);
- if (err) {
- EXIT;
- return err;
- }
-
- err = copy_to_user((int *)arg, attr, sizeof(*attr));
- EXIT;
- return err;
- }
-
- case OBD_IOC_DESTROY: {
- struct oic_attr_s *attr = tmp_buf;
-
- /* has this minor been registered? */
- if (!obddev->obd_type)
- return -ENODEV;
-
- err = copy_from_user(attr, (int *)arg, sizeof(*attr));
- if ( err ) {
- EXIT;
- return err;
- }
-
- if ( !OBT(obddev) || !OBP(obddev, destroy) )
- return -EOPNOTSUPP;
-
- conn.oc_id = attr->conn_id;
- err = OBP(obddev, destroy)(&conn, &attr->obdo);
- EXIT;
- return err;
- }
-
- case OBD_IOC_SETATTR: {
- struct oic_attr_s *attr = tmp_buf;
-
- /* has this minor been registered? */
- if (!obddev->obd_type)
- return -ENODEV;
-
- err = copy_from_user(attr, (int *)arg, sizeof(*attr));
- if (err)
- return err;
-
- if ( !OBT(obddev) || !OBP(obddev, setattr) )
- return -EOPNOTSUPP;
-
- conn.oc_id = attr->conn_id;
- err = OBP(obddev, setattr)(&conn, &attr->obdo);
- EXIT;
- return err;
- }
-
- case OBD_IOC_GETATTR: {
- struct oic_attr_s *attr = tmp_buf;
-
- err = copy_from_user(attr, (int *)arg, sizeof(*attr));
- if (err)
- return err;
-
- conn.oc_id = attr->conn_id;
- ODEBUG(&attr->obdo);
- err = OBP(obddev, getattr)(&conn, &attr->obdo);
- if ( err ) {
- EXIT;
- return err;
- }
-
- err = copy_to_user((int *)arg, attr, sizeof(*attr));
- EXIT;
- return err;
- }
-
- case OBD_IOC_READ: {
- int err;
- struct oic_rw_s *rw_s = tmp_buf; /* read, write ioctl str */
-
- err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s));
- if ( err ) {
- EXIT;
- return err;
- }
-
- conn.oc_id = rw_s->conn_id;
-
- if ( !OBT(obddev) || !OBP(obddev, read) ) {
- err = -EOPNOTSUPP;
- EXIT;
- return err;
- }
-
-
- err = OBP(obddev, read)(&conn, &rw_s->obdo, rw_s->buf,
- &rw_s->count, rw_s->offset);
-
- ODEBUG(&rw_s->obdo);
- CDEBUG(D_INFO, "READ: conn %d, count %Ld, offset %Ld, '%s'\n",
- rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf);
- if ( err ) {
- EXIT;
- return err;
- }
-
- err = copy_to_user((int*)arg, &rw_s->count, sizeof(rw_s->count));
- EXIT;
- return err;
- }
-
- case OBD_IOC_WRITE: {
- struct oic_rw_s *rw_s = tmp_buf; /* read, write ioctl str */
-
- err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s));
- if ( err ) {
- EXIT;
- return err;
- }
-
- conn.oc_id = rw_s->conn_id;
-
- if ( !OBT(obddev) || !OBP(obddev, write) ) {
- err = -EOPNOTSUPP;
- return err;
- }
-
- CDEBUG(D_INFO, "WRITE: conn %d, count %Ld, offset %Ld, '%s'\n",
- rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf);
- err = OBP(obddev, write)(&conn, &rw_s->obdo, rw_s->buf,
- &rw_s->count, rw_s->offset);
- ODEBUG(&rw_s->obdo);
- if ( err ) {
- EXIT;
- return err;
- }
-
- err = copy_to_user((int *)arg, &rw_s->count,
- sizeof(rw_s->count));
- EXIT;
- return err;
- }
- case OBD_IOC_PREALLOCATE: {
- struct oic_prealloc_s *prealloc = tmp_buf;
-
- /* has this minor been registered? */
- if (!obddev->obd_type)
- return -ENODEV;
-
- err = copy_from_user(prealloc, (int *)arg, sizeof(*prealloc));
- if (err)
- return -EFAULT;
-
- if ( !(obddev->obd_flags & OBD_ATTACHED) ||
- !(obddev->obd_flags & OBD_SET_UP)) {
- CDEBUG(D_IOCTL, "Device not attached or set up\n");
- return -ENODEV;
- }
-
- if ( !OBT(obddev) || !OBP(obddev, preallocate) )
- return -EOPNOTSUPP;
-
- conn.oc_id = prealloc->conn_id;
- err = OBP(obddev, preallocate)(&conn, &prealloc->alloc,
- prealloc->ids);
- if ( err ) {
- EXIT;
- return err;
- }
-
- err =copy_to_user((int *)arg, prealloc, sizeof(*prealloc));
- EXIT;
- return err;
- }
- case OBD_IOC_STATFS: {
- struct statfs *tmp;
- unsigned int conn_id;
- struct statfs buf;
-
- /* has this minor been registered? */
- if (!obddev->obd_type)
- return -ENODEV;
-
- tmp = (void *)arg + sizeof(unsigned int);
- get_user(conn_id, (int *) arg);
-
- if ( !OBT(obddev) || !OBP(obddev, statfs) )
- return -EOPNOTSUPP;
-
- conn.oc_id = conn_id;
- err = OBP(obddev, statfs)(&conn, &buf);
- if ( err ) {
- EXIT;
- return err;
- }
- err = copy_to_user(tmp, &buf, sizeof(buf));
- EXIT;
- return err;
-
- }
- case OBD_IOC_COPY: {
- struct ioc_mv_s *mvdata = tmp_buf;
-
- if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
- (!(obddev->obd_flags & OBD_ATTACHED))) {
- CDEBUG(D_IOCTL, "Device not attached or set up\n");
- return -ENODEV;
- }
-
- /* get main structure */
- err = copy_from_user(mvdata, (void *) arg, sizeof(*mvdata));
- if (err) {
- EXIT;
- return err;
- }
-
- if ( !OBT(obddev) || !OBP(obddev, copy) )
- return -EOPNOTSUPP;
-
- /* do the partition */
- CDEBUG(D_INFO, "Copy %d, type %s dst %Ld src %Ld\n", dev,
- obddev->obd_type->typ_name, mvdata->dst.o_id,
- mvdata->src.o_id);
-
- conn.oc_id = mvdata->src_conn_id;
-
- err = OBP(obddev, copy)(&conn, &mvdata->dst,
- &conn, &mvdata->src,
- mvdata->src.o_size, 0);
- return err;
- }
-
- case OBD_IOC_MIGR: {
- struct ioc_mv_s *mvdata = tmp_buf;
-
- if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
- (!(obddev->obd_flags & OBD_ATTACHED))) {
- CDEBUG(D_IOCTL, "Device not attached or set up\n");
- return -ENODEV;
- }
-
- err = copy_from_user(mvdata, (void *) arg, sizeof(*mvdata));
- if (err) {
- EXIT;
- return err;
- }
-
- CDEBUG(D_INFO, "Migrate copying %d bytes\n", sizeof(*mvdata));
-
- if ( !OBT(obddev) || !OBP(obddev, migrate) )
- return -EOPNOTSUPP;
-
- /* do the partition */
- CDEBUG(D_INFO, "Migrate %d, type %s conn %d src %Ld dst %Ld\n",
- dev, obddev->obd_type->typ_name, mvdata->src_conn_id,
- mvdata->src.o_id, mvdata->dst.o_id);
-
- conn.oc_id = mvdata->src_conn_id;
- err = OBP(obddev, migrate)(&conn, &mvdata->dst, &mvdata->src,
- mvdata->src.o_size, 0);
-
- return err;
- }
- case OBD_IOC_PUNCH: {
- struct oic_rw_s *rw_s = tmp_buf; /* read, write ioctl str */
-
- err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s));
- if ( err ) {
- EXIT;
- return err;
- }
-
- conn.oc_id = rw_s->conn_id;
-
- if ( !OBT(obddev) || !OBP(obddev, punch) ) {
- err = -EOPNOTSUPP;
- return err;
- }
-
- CDEBUG(D_INFO, "PUNCH: conn %d, count %Ld, offset %Ld\n",
- rw_s->conn_id, rw_s->count, rw_s->offset);
- err = OBP(obddev, punch)(&conn, &rw_s->obdo, rw_s->count,
- rw_s->offset);
- ODEBUG(&rw_s->obdo);
- if ( err ) {
- EXIT;
- return err;
- }
- EXIT;
- return err;
- }
-
- default: {
- struct obd_type *type;
- struct oic_generic input;
- char *nm;
- void *karg;
-
- /* get data structures */
- err = copy_from_user(&input, (void *)arg, sizeof(input));
- if ( err ) {
- EXIT;
- return err;
- }
-
- err = getdata(input.att_typelen + 1, &input.att_type);
- if ( err ) {
- EXIT;
- return err;
- }
-
- /* find the type */
- nm = input.att_type;
- type = obd_nm_to_type(nm);
+ OBD_FREE(input->att_type, input->att_typelen + 1);
+ if ( !type ) {
+ printk(__FUNCTION__ ": unknown obd type dev %d\n",
+ dev);
+ EXIT;
+ return -EINVAL;
+ }
+ obddev->obd_type = type;
+
+ /* get the attach data */
+ err = getdata(input->att_datalen, &input->att_data);
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ INIT_LIST_HEAD(&obddev->obd_gen_clients);
+ obddev->obd_multi_count = 0;
+
+ CDEBUG(D_IOCTL, "Attach %d, datalen %d, type %s\n",
+ dev, input->att_datalen, obddev->obd_type->typ_name);
+ /* maybe we are done */
+ if ( !OBT(obddev) || !OBP(obddev, attach) ) {
+ obddev->obd_flags |= OBD_ATTACHED;
+ type->typ_refcnt++;
+ CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
+ type->typ_refcnt);
+ if (input->att_data)
+ OBD_FREE(input->att_data, input->att_datalen);
+ MOD_INC_USE_COUNT;
+ EXIT;
+ return 0;
+ }
+
+ /* do the attach */
+ err = OBP(obddev, attach)(obddev, input->att_datalen,
+ input->att_data);
+ if (input->att_data)
+ OBD_FREE(input->att_data, input->att_datalen);
+
+ if ( err ) {
+ obddev->obd_flags &= ~OBD_ATTACHED;
+ obddev->obd_type = NULL;
+ EXIT;
+ } else {
+ obddev->obd_flags |= OBD_ATTACHED;
+ type->typ_refcnt++;
+ CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
+ type->typ_refcnt);
+ MOD_INC_USE_COUNT;
+ EXIT;
+ }
+ return err;
+ }
+
+ case OBD_IOC_DETACH: {
+
+ ENTRY;
+ if (obddev->obd_flags & OBD_SET_UP) {
+ EXIT;
+ return -EBUSY;
+ }
+ if (! (obddev->obd_flags & OBD_ATTACHED) ) {
+ CDEBUG(D_IOCTL, "Device not attached\n");
+ EXIT;
+ return -ENODEV;
+ }
+ if ( !list_empty(&obddev->obd_gen_clients) ) {
+ CDEBUG(D_IOCTL, "Device has connected clients\n");
+ EXIT;
+ return -EBUSY;
+ }
+
+ CDEBUG(D_PSDEV, "Detach %d, type %s\n", dev,
+ obddev->obd_type->typ_name);
+ obddev->obd_flags &= ~OBD_ATTACHED;
+ obddev->obd_type->typ_refcnt--;
+ CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
+ obddev->obd_type->typ_refcnt);
+ obddev->obd_type = NULL;
+ MOD_DEC_USE_COUNT;
+ EXIT;
+ return 0;
+ }
+
+ case OBD_IOC_SETUP: {
+ struct ioc_setup {
+ int setup_datalen;
+ void *setup_data;
+ } *setup;
+ setup = tmp_buf;
+
+ ENTRY;
+ /* have we attached a type to this device */
+ if (!(obddev->obd_flags & OBD_ATTACHED)) {
+ CDEBUG(D_IOCTL, "Device not attached\n");
+ EXIT;
+ return -ENODEV;
+ }
+
+ /* has this been done already? */
+ if ( obddev->obd_flags & OBD_SET_UP ) {
+ CDEBUG(D_IOCTL, "Device %d already setup (type %s)\n",
+ dev, obddev->obd_type->typ_name);
+ EXIT;
+ return -EBUSY;
+ }
+
+ /* get main structure */
+ err = copy_from_user(setup, (void *) arg, sizeof(*setup));
+ if (err) {
+ EXIT;
+ return err;
+ }
+
+ err = getdata(setup->setup_datalen, &setup->setup_data);
+ if (err) {
+ EXIT;
+ return err;
+ }
+
+ /* do the setup */
+ CDEBUG(D_PSDEV, "Setup %d, type %s\n", dev,
+ obddev->obd_type->typ_name);
+ if ( !OBT(obddev) || !OBP(obddev, setup) ) {
+ obddev->obd_type->typ_refcnt++;
+ CDEBUG(D_PSDEV, "Dev %d refcount now %d\n",
+ dev, obddev->obd_type->typ_refcnt);
+ if (setup->setup_data)
+ OBD_FREE(setup->setup_data,
+ setup->setup_datalen);
+ obddev->obd_flags |= OBD_SET_UP;
+ EXIT;
+ return 0;
+ }
+
+ err = OBP(obddev, setup)(obddev, setup->setup_datalen,
+ setup->setup_data);
+
+ if ( err ) {
+ obddev->obd_flags &= ~OBD_SET_UP;
+ EXIT;
+ } else {
+ obddev->obd_type->typ_refcnt++;
+ CDEBUG(D_PSDEV, "Dev %d refcount now %d\n",
+ dev, obddev->obd_type->typ_refcnt);
+ obddev->obd_flags |= OBD_SET_UP;
+ EXIT;
+ }
+ if (setup->setup_data)
+ OBD_FREE(setup->setup_data, setup->setup_datalen);
+ return err;
+ }
+ case OBD_IOC_CLEANUP: {
+ ENTRY;
+ /* has this minor been registered? */
+ if (!obddev->obd_type) {
+ CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
+ EXIT;
+ return -ENODEV;
+ }
+
+ if ( !obddev->obd_type->typ_refcnt ) {
+ CDEBUG(D_IOCTL, "dev %d has refcount (%d)!\n",
+ dev, obddev->obd_type->typ_refcnt);
+ EXIT;
+ return -EBUSY;
+ }
+
+ if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
+ (!(obddev->obd_flags & OBD_ATTACHED))) {
+ CDEBUG(D_IOCTL, "device not attached or set up\n");
+ EXIT;
+ return -ENODEV;
+ }
+
+ if ( !OBT(obddev) || !OBP(obddev, cleanup) )
+ goto cleanup_out;
+
+ /* cleanup has no argument */
+ err = OBP(obddev, cleanup)(obddev);
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ cleanup_out:
+ obddev->obd_flags &= ~OBD_SET_UP;
+ obddev->obd_type->typ_refcnt--;
+ CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
+ obddev->obd_type->typ_refcnt);
+ EXIT;
+ return 0;
+ }
+ case OBD_IOC_CONNECT:
+ {
+ if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
+ (!(obddev->obd_flags & OBD_ATTACHED))) {
+ CDEBUG(D_IOCTL, "Device not attached or set up\n");
+ return -ENODEV;
+ }
+
+ if ( !OBT(obddev) || !OBP(obddev, connect) )
+ return -EOPNOTSUPP;
+
+ err = OBP(obddev, connect)(&conn);
+ if ( err )
+ return err;
+
+ return copy_to_user((int *)arg, &conn.oc_id,
+ sizeof(uint32_t));
+ }
+ case OBD_IOC_DISCONNECT:
+ /* frees data structures */
+ /* has this minor been registered? */
+ if (!obddev->obd_type)
+ return -ENODEV;
+
+ get_user(cli_id, (int *) arg);
+ conn.oc_id = cli_id;
+
+ if ( !OBT(obddev) || !OBP(obddev, disconnect))
+ return -EOPNOTSUPP;
+
+ OBP(obddev, disconnect)(&conn);
+ return 0;
+
+ case OBD_IOC_SYNC: {
+ struct oic_range_s *range = tmp_buf;
+
+ if (!obddev->obd_type)
+ return -ENODEV;
+
+ err = copy_from_user(range, (const void *)arg, sizeof(*range));
+
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ if ( !OBT(obddev) || !OBP(obddev, sync) ) {
+ err = -EOPNOTSUPP;
+ EXIT;
+ return err;
+ }
+
+ /* XXX sync needs to be tested/verified */
+ err = OBP(obddev, sync)(&conn, &range->obdo, range->count,
+ range->offset);
+
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ return put_user(err, (int *) arg);
+ }
+ case OBD_IOC_CREATE: {
+ struct oic_attr_s *attr = tmp_buf;
+
+ err = copy_from_user(attr, (const void *)arg, sizeof(*attr));
+ if (err) {
+ EXIT;
+ return err;
+ }
+
+ /* has this minor been registered? */
+ if ( !(obddev->obd_flags & OBD_ATTACHED) ||
+ !(obddev->obd_flags & OBD_SET_UP)) {
+ CDEBUG(D_IOCTL, "Device not attached or set up\n");
+ return -ENODEV;
+ }
+ conn.oc_id = attr->conn_id;
+
+ if ( !OBT(obddev) || !OBP(obddev, create) )
+ return -EOPNOTSUPP;
+
+ err = OBP(obddev, create)(&conn, &attr->obdo);
+ if (err) {
+ EXIT;
+ return err;
+ }
+
+ err = copy_to_user((int *)arg, attr, sizeof(*attr));
+ EXIT;
+ return err;
+ }
+
+ case OBD_IOC_DESTROY: {
+ struct oic_attr_s *attr = tmp_buf;
+
+ /* has this minor been registered? */
+ if (!obddev->obd_type)
+ return -ENODEV;
+
+ err = copy_from_user(attr, (int *)arg, sizeof(*attr));
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ if ( !OBT(obddev) || !OBP(obddev, destroy) )
+ return -EOPNOTSUPP;
+
+ conn.oc_id = attr->conn_id;
+ err = OBP(obddev, destroy)(&conn, &attr->obdo);
+ EXIT;
+ return err;
+ }
+
+ case OBD_IOC_SETATTR: {
+ struct oic_attr_s *attr = tmp_buf;
+
+ /* has this minor been registered? */
+ if (!obddev->obd_type)
+ return -ENODEV;
+
+ err = copy_from_user(attr, (int *)arg, sizeof(*attr));
+ if (err)
+ return err;
+
+ if ( !OBT(obddev) || !OBP(obddev, setattr) )
+ return -EOPNOTSUPP;
+
+ conn.oc_id = attr->conn_id;
+ err = OBP(obddev, setattr)(&conn, &attr->obdo);
+ EXIT;
+ return err;
+ }
+
+ case OBD_IOC_GETATTR: {
+ struct oic_attr_s *attr = tmp_buf;
+
+ err = copy_from_user(attr, (int *)arg, sizeof(*attr));
+ if (err)
+ return err;
+
+ conn.oc_id = attr->conn_id;
+ ODEBUG(&attr->obdo);
+ err = OBP(obddev, getattr)(&conn, &attr->obdo);
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ err = copy_to_user((int *)arg, attr, sizeof(*attr));
+ EXIT;
+ return err;
+ }
+
+ case OBD_IOC_READ: {
+ int err;
+ struct oic_rw_s *rw_s = tmp_buf; /* read, write ioctl str */
+
+ err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s));
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ conn.oc_id = rw_s->conn_id;
+
+ if ( !OBT(obddev) || !OBP(obddev, read) ) {
+ err = -EOPNOTSUPP;
+ EXIT;
+ return err;
+ }
+
+
+ err = OBP(obddev, read)(&conn, &rw_s->obdo, rw_s->buf,
+ &rw_s->count, rw_s->offset);
+
+ ODEBUG(&rw_s->obdo);
+ CDEBUG(D_INFO, "READ: conn %d, count %Ld, offset %Ld, '%s'\n",
+ rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf);
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ err = copy_to_user((int*)arg, &rw_s->count, sizeof(rw_s->count));
+ EXIT;
+ return err;
+ }
+
+ case OBD_IOC_WRITE: {
+ struct oic_rw_s *rw_s = tmp_buf; /* read, write ioctl str */
+
+ err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s));
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ conn.oc_id = rw_s->conn_id;
+
+ if ( !OBT(obddev) || !OBP(obddev, write) ) {
+ err = -EOPNOTSUPP;
+ return err;
+ }
+
+ CDEBUG(D_INFO, "WRITE: conn %d, count %Ld, offset %Ld, '%s'\n",
+ rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf);
+
+ err = OBP(obddev, write)(&conn, &rw_s->obdo, rw_s->buf,
+ &rw_s->count, rw_s->offset);
+ ODEBUG(&rw_s->obdo);
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ err = copy_to_user((int *)arg, &rw_s->count,
+ sizeof(rw_s->count));
+ EXIT;
+ return err;
+ }
+ case OBD_IOC_PREALLOCATE: {
+ struct oic_prealloc_s *prealloc = tmp_buf;
+
+ /* has this minor been registered? */
+ if (!obddev->obd_type)
+ return -ENODEV;
+
+ err = copy_from_user(prealloc, (int *)arg, sizeof(*prealloc));
+ if (err)
+ return -EFAULT;
+
+ if ( !(obddev->obd_flags & OBD_ATTACHED) ||
+ !(obddev->obd_flags & OBD_SET_UP)) {
+ CDEBUG(D_IOCTL, "Device not attached or set up\n");
+ return -ENODEV;
+ }
+
+ if ( !OBT(obddev) || !OBP(obddev, preallocate) )
+ return -EOPNOTSUPP;
+
+ conn.oc_id = prealloc->conn_id;
+ err = OBP(obddev, preallocate)(&conn, &prealloc->alloc,
+ prealloc->ids);
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ err =copy_to_user((int *)arg, prealloc, sizeof(*prealloc));
+ EXIT;
+ return err;
+ }
+ case OBD_IOC_STATFS: {
+ struct statfs *tmp;
+ unsigned int conn_id;
+ struct statfs buf;
+
+ /* has this minor been registered? */
+ if (!obddev->obd_type)
+ return -ENODEV;
+
+ tmp = (void *)arg + sizeof(unsigned int);
+ get_user(conn_id, (int *) arg);
+
+ if ( !OBT(obddev) || !OBP(obddev, statfs) )
+ return -EOPNOTSUPP;
+
+ conn.oc_id = conn_id;
+ err = OBP(obddev, statfs)(&conn, &buf);
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+ err = copy_to_user(tmp, &buf, sizeof(buf));
+ EXIT;
+ return err;
+
+ }
+ case OBD_IOC_COPY: {
+ struct ioc_mv_s *mvdata = tmp_buf;
+
+ if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
+ (!(obddev->obd_flags & OBD_ATTACHED))) {
+ CDEBUG(D_IOCTL, "Device not attached or set up\n");
+ return -ENODEV;
+ }
+
+ /* get main structure */
+ err = copy_from_user(mvdata, (void *) arg, sizeof(*mvdata));
+ if (err) {
+ EXIT;
+ return err;
+ }
+
+ if ( !OBT(obddev) || !OBP(obddev, copy) )
+ return -EOPNOTSUPP;
+
+ /* do the partition */
+ CDEBUG(D_INFO, "Copy %d, type %s dst %Ld src %Ld\n", dev,
+ obddev->obd_type->typ_name, mvdata->dst.o_id,
+ mvdata->src.o_id);
+
+ conn.oc_id = mvdata->src_conn_id;
+
+ err = OBP(obddev, copy)(&conn, &mvdata->dst,
+ &conn, &mvdata->src,
+ mvdata->src.o_size, 0);
+ return err;
+ }
+
+ case OBD_IOC_MIGR: {
+ struct ioc_mv_s *mvdata = tmp_buf;
+
+ if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
+ (!(obddev->obd_flags & OBD_ATTACHED))) {
+ CDEBUG(D_IOCTL, "Device not attached or set up\n");
+ return -ENODEV;
+ }
+
+ err = copy_from_user(mvdata, (void *) arg, sizeof(*mvdata));
+ if (err) {
+ EXIT;
+ return err;
+ }
+
+ CDEBUG(D_INFO, "Migrate copying %d bytes\n", sizeof(*mvdata));
+
+ if ( !OBT(obddev) || !OBP(obddev, migrate) )
+ return -EOPNOTSUPP;
+
+ /* do the partition */
+ CDEBUG(D_INFO, "Migrate %d, type %s conn %d src %Ld dst %Ld\n",
+ dev, obddev->obd_type->typ_name, mvdata->src_conn_id,
+ mvdata->src.o_id, mvdata->dst.o_id);
+
+ conn.oc_id = mvdata->src_conn_id;
+ err = OBP(obddev, migrate)(&conn, &mvdata->dst, &mvdata->src,
+ mvdata->src.o_size, 0);
+
+ return err;
+ }
+ case OBD_IOC_PUNCH: {
+ struct oic_rw_s *rw_s = tmp_buf; /* read, write ioctl str */
+
+ err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s));
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ conn.oc_id = rw_s->conn_id;
+
+ if ( !OBT(obddev) || !OBP(obddev, punch) ) {
+ err = -EOPNOTSUPP;
+ return err;
+ }
+
+ CDEBUG(D_INFO, "PUNCH: conn %d, count %Ld, offset %Ld\n",
+ rw_s->conn_id, rw_s->count, rw_s->offset);
+ err = OBP(obddev, punch)(&conn, &rw_s->obdo, rw_s->count,
+ rw_s->offset);
+ ODEBUG(&rw_s->obdo);
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+ EXIT;
+ return err;
+ }
+
+ default: {
+ struct obd_type *type;
+ struct oic_generic input;
+ char *nm;
+ void *karg;
+
+ /* get data structures */
+ err = copy_from_user(&input, (void *)arg, sizeof(input));
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ err = getdata(input.att_typelen + 1, &input.att_type);
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ /* find the type */
+ nm = input.att_type;
+ type = obd_nm_to_type(nm);
#ifdef CONFIG_KMOD
- if ( !type ) {
- if ( !request_module(nm) ) {
- CDEBUG(D_PSDEV, "Loaded module '%s'\n", nm);
- type = obd_nm_to_type(nm);
- } else {
- CDEBUG(D_PSDEV, "Can't load module '%s'\n", nm);
- }
- }
+ if ( !type ) {
+ if ( !request_module(nm) ) {
+ CDEBUG(D_PSDEV, "Loaded module '%s'\n", nm);
+ type = obd_nm_to_type(nm);
+ } else {
+ CDEBUG(D_PSDEV, "Can't load module '%s'\n", nm);
+ }
+ }
#endif
- OBD_FREE(input.att_type, input.att_typelen + 1);
- if ( !type ) {
- printk(__FUNCTION__ ": unknown obd type dev %d\n", dev);
- EXIT;
- return -EINVAL;
- }
-
- if ( !type->typ_ops || !type->typ_ops->o_iocontrol ) {
- EXIT;
- return -EOPNOTSUPP;
- }
- conn.oc_id = input.att_connid;
-
- CDEBUG(D_INFO, "Calling ioctl %x for type %s, len %d\n",
- cmd, type->typ_name, input.att_datalen);
-
- /* get the generic data */
- karg = input.att_data;
- err = getdata(input.att_datalen, &karg);
- if ( err ) {
- EXIT;
- return err;
- }
-
- err = type->typ_ops->o_iocontrol(cmd, &conn, input.att_datalen,
- karg, input.att_data);
- OBD_FREE(karg, input.att_datalen);
-
- EXIT;
- return err;
- }
- }
+ OBD_FREE(input.att_type, input.att_typelen + 1);
+ if ( !type ) {
+ printk(__FUNCTION__ ": unknown obd type dev %d\n", dev);
+ EXIT;
+ return -EINVAL;
+ }
+
+ if ( !type->typ_ops || !type->typ_ops->o_iocontrol ) {
+ EXIT;
+ return -EOPNOTSUPP;
+ }
+ conn.oc_id = input.att_connid;
+
+ CDEBUG(D_INFO, "Calling ioctl %x for type %s, len %d\n",
+ cmd, type->typ_name, input.att_datalen);
+
+ /* get the generic data */
+ karg = input.att_data;
+ err = getdata(input.att_datalen, &karg);
+ if ( err ) {
+ EXIT;
+ return err;
+ }
+
+ err = type->typ_ops->o_iocontrol(cmd, &conn, input.att_datalen,
+ karg, input.att_data);
+ OBD_FREE(karg, input.att_datalen);
+
+ EXIT;
+ return err;
+ }
+ }
} /* obd_class_ioctl */
/* Driver interface done, utility functions follow */
int obd_register_type(struct obd_ops *ops, char *nm)
{
- struct obd_type *type;
-
-
- if (obd_init_magic != 0x11223344) {
- printk(__FUNCTION__ ": bad magic for type\n");
- EXIT;
- return -EINVAL;
- }
-
- if ( obd_nm_to_type(nm) ) {
- CDEBUG(D_IOCTL, "Type %s already registered\n", nm);
- EXIT;
- return -EEXIST;
- }
-
- OBD_ALLOC(type, struct obd_type * , sizeof(*type));
- if ( !type ) {
- EXIT;
- return -ENOMEM;
- }
- memset(type, 0, sizeof(*type));
- INIT_LIST_HEAD(&type->typ_chain);
- MOD_INC_USE_COUNT;
- list_add(&type->typ_chain, obd_types.next);
- type->typ_ops = ops;
- type->typ_name = nm;
- EXIT;
- return 0;
+ struct obd_type *type;
+
+
+ if (obd_init_magic != 0x11223344) {
+ printk(__FUNCTION__ ": bad magic for type\n");
+ EXIT;
+ return -EINVAL;
+ }
+
+ if ( obd_nm_to_type(nm) ) {
+ CDEBUG(D_IOCTL, "Type %s already registered\n", nm);
+ EXIT;
+ return -EEXIST;
+ }
+
+ OBD_ALLOC(type, struct obd_type * , sizeof(*type));
+ if ( !type ) {
+ EXIT;
+ return -ENOMEM;
+ }
+ memset(type, 0, sizeof(*type));
+ INIT_LIST_HEAD(&type->typ_chain);
+ MOD_INC_USE_COUNT;
+ list_add(&type->typ_chain, obd_types.next);
+ type->typ_ops = ops;
+ type->typ_name = nm;
+ EXIT;
+ return 0;
}
-
+
int obd_unregister_type(char *nm)
{
- struct obd_type *type = obd_nm_to_type(nm);
-
- if ( !type ) {
- MOD_DEC_USE_COUNT;
- printk(KERN_INFO __FUNCTION__ ": unknown obd type\n");
- EXIT;
- return -EINVAL;
- }
-
- if ( type->typ_refcnt ) {
- MOD_DEC_USE_COUNT;
- printk(KERN_ALERT __FUNCTION__ ":type %s has refcount "
- "(%d)\n", nm, type->typ_refcnt);
- EXIT;
- return -EBUSY;
- }
-
- list_del(&type->typ_chain);
- OBD_FREE(type, sizeof(*type));
- MOD_DEC_USE_COUNT;
- return 0;
+ struct obd_type *type = obd_nm_to_type(nm);
+
+ if ( !type ) {
+ MOD_DEC_USE_COUNT;
+ printk(KERN_INFO __FUNCTION__ ": unknown obd type\n");
+ EXIT;
+ return -EINVAL;
+ }
+
+ if ( type->typ_refcnt ) {
+ MOD_DEC_USE_COUNT;
+ printk(KERN_ALERT __FUNCTION__ ":type %s has refcount "
+ "(%d)\n", nm, type->typ_refcnt);
+ EXIT;
+ return -EBUSY;
+ }
+
+ list_del(&type->typ_chain);
+ OBD_FREE(type, sizeof(*type));
+ MOD_DEC_USE_COUNT;
+ return 0;
} /* obd_unregister_type */
/* declare character device */
static struct file_operations obd_psdev_fops = {
- NULL, /* llseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* presto_psdev_readdir */
- NULL, /* poll */
- obd_class_ioctl, /* ioctl */
- NULL, /* presto_psdev_mmap */
- obd_class_open, /* open */
- NULL,
- obd_class_release, /* release */
- NULL, /* fsync */
- NULL, /* fasync */
- NULL /* lock */
+ ioctl: obd_class_ioctl, /* ioctl */
+ open: obd_class_open, /* open */
+ release: obd_class_release, /* release */
};
int init_obd(void)
{
- int err;
- int i;
-
- printk(KERN_INFO "OBD class driver v0.01, braam@stelias.com\n");
-
- INIT_LIST_HEAD(&obd_types);
-
- if (register_chrdev(OBD_PSDEV_MAJOR,"obd_psdev",
- &obd_psdev_fops)) {
- printk(KERN_ERR __FUNCTION__ ": unable to get major %d\n",
- OBD_PSDEV_MAJOR);
- return -EIO;
- }
-
- for (i = 0; i < MAX_OBD_DEVICES; i++) {
- memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
- obd_dev[i].obd_minor = i;
- INIT_LIST_HEAD(&obd_dev[i].obd_gen_clients);
- }
-
- err = obd_init_obdo_cache();
- if (err)
- return err;
- obd_sysctl_init();
- obd_init_magic = 0x11223344;
- return 0;
+ int err;
+ int i;
+
+ printk(KERN_INFO "OBD class driver v0.01, braam@stelias.com\n");
+
+ INIT_LIST_HEAD(&obd_types);
+
+ if (register_chrdev(OBD_PSDEV_MAJOR,"obd_psdev",
+ &obd_psdev_fops)) {
+ printk(KERN_ERR __FUNCTION__ ": unable to get major %d\n",
+ OBD_PSDEV_MAJOR);
+ return -EIO;
+ }
+
+ for (i = 0; i < MAX_OBD_DEVICES; i++) {
+ memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
+ obd_dev[i].obd_minor = i;
+ INIT_LIST_HEAD(&obd_dev[i].obd_gen_clients);
+ }
+
+ err = obd_init_obdo_cache();
+ if (err)
+ return err;
+ obd_sysctl_init();
+ obd_init_magic = 0x11223344;
+ return 0;
}
EXPORT_SYMBOL(obd_register_type);
#ifdef MODULE
int init_module(void)
{
- return init_obd();
+ return init_obd();
}
void cleanup_module(void)
{
- int i;
+ int i;
ENTRY;
unregister_chrdev(OBD_PSDEV_MAJOR, "obd_psdev");
- for (i = 0; i < MAX_OBD_DEVICES; i++) {
- struct obd_device *obddev = &obd_dev[i];
- if ( obddev->obd_type &&
- (obddev->obd_flags & OBD_SET_UP) &&
- OBT(obddev) && OBP(obddev, detach) ) {
- /* XXX should this call generic detach otherwise? */
- OBP(obddev, detach)(obddev);
- }
- }
-
- obd_cleanup_obdo_cache();
- obd_sysctl_clean();
- CDEBUG(D_MALLOC, "CLASS mem used %ld\n", obd_memory);
- obd_init_magic = 0;
- EXIT;
+ for (i = 0; i < MAX_OBD_DEVICES; i++) {
+ struct obd_device *obddev = &obd_dev[i];
+ if ( obddev->obd_type &&
+ (obddev->obd_flags & OBD_SET_UP) &&
+ OBT(obddev) && OBP(obddev, detach) ) {
+ /* XXX should this call generic detach otherwise? */
+ OBP(obddev, detach)(obddev);
+ }
+ }
+
+ obd_cleanup_obdo_cache();
+ obd_sysctl_clean();
+ CDEBUG(D_MALLOC, "CLASS mem used %ld\n", obd_memory);
+ obd_init_magic = 0;
+ EXIT;
}
#endif
*
*/
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/locks.h>
-#include <linux/unistd.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
+#include <linux/mm.h>
#include <linux/fs.h>
-#include <linux/stat.h>
+#include <linux/sched.h>
#include <asm/uaccess.h>
-#include <linux/vmalloc.h>
-#include <asm/segment.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/smp_lock.h>
#include <linux/obd_support.h>
#include <linux/obd_class.h>
int obd_init_obdo_cache(void)
{
- ENTRY;
- if (obdo_cachep == NULL) {
- CDEBUG(D_CACHE, "allocating obdo_cache\n");
- obdo_cachep = kmem_cache_create("obdo_cache",
- sizeof(struct obdo),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
- if (obdo_cachep == NULL) {
- EXIT;
- return -ENOMEM;
- } else {
- CDEBUG(D_CACHE, "allocated cache at %p\n", obdo_cachep);
- }
- } else {
- CDEBUG(D_CACHE, "using existing cache at %p\n", obdo_cachep);
- }
- EXIT;
- return 0;
+ ENTRY;
+ if (obdo_cachep == NULL) {
+ CDEBUG(D_CACHE, "allocating obdo_cache\n");
+ obdo_cachep = kmem_cache_create("obdo_cache",
+ sizeof(struct obdo),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (obdo_cachep == NULL) {
+ EXIT;
+ return -ENOMEM;
+ } else {
+ CDEBUG(D_CACHE, "allocated cache at %p\n", obdo_cachep);
+ }
+ } else {
+ CDEBUG(D_CACHE, "using existing cache at %p\n", obdo_cachep);
+ }
+ EXIT;
+ return 0;
}
void obd_cleanup_obdo_cache(void)
{
- ENTRY;
- if (obdo_cachep != NULL) {
- CDEBUG(D_CACHE, "destroying obdo_cache at %p\n", obdo_cachep);
- if (kmem_cache_destroy(obdo_cachep))
- printk(KERN_WARNING __FUNCTION__
- ": unable to free cache\n");
- } else
- printk(KERN_INFO __FUNCTION__
- ": called with NULL cache pointer\n");
-
- obdo_cachep = NULL;
- EXIT;
+ ENTRY;
+ if (obdo_cachep != NULL) {
+ CDEBUG(D_CACHE, "destroying obdo_cache at %p\n", obdo_cachep);
+ if (kmem_cache_destroy(obdo_cachep))
+ printk(KERN_WARNING __FUNCTION__
+ ": unable to free cache\n");
+ } else
+ printk(KERN_INFO __FUNCTION__
+ ": called with NULL cache pointer\n");
+
+ obdo_cachep = NULL;
+ EXIT;
}
/* map connection to client */
struct obd_client *gen_client(struct obd_conn *conn)
{
- struct obd_device * obddev = conn->oc_dev;
- struct list_head * lh, * next;
- struct obd_client * cli;
-
- lh = next = &obddev->obd_gen_clients;
- while ((lh = lh->next) != &obddev->obd_gen_clients) {
- cli = list_entry(lh, struct obd_client, cli_chain);
-
- if (cli->cli_id == conn->oc_id)
- return cli;
- }
-
- return NULL;
+ struct obd_device * obddev = conn->oc_dev;
+ struct list_head * lh, * next;
+ struct obd_client * cli;
+
+ lh = next = &obddev->obd_gen_clients;
+ while ((lh = lh->next) != &obddev->obd_gen_clients) {
+ cli = list_entry(lh, struct obd_client, cli_chain);
+
+ if (cli->cli_id == conn->oc_id)
+ return cli;
+ }
+
+ return NULL;
} /* obd_client */
/* a connection defines a context in which preallocation can be managed. */
int gen_connect (struct obd_conn *conn)
{
- struct obd_client * cli;
-
- OBD_ALLOC(cli, struct obd_client *, sizeof(struct obd_client));
- if ( !cli ) {
- printk(__FUNCTION__ ": no memory! (minor %d)\n",
- conn->oc_dev->obd_minor);
- return -ENOMEM;
- }
-
- INIT_LIST_HEAD(&cli->cli_prealloc_inodes);
- /* XXX this should probably spinlocked? */
- cli->cli_id = ++conn->oc_dev->obd_gen_last_id;
- cli->cli_prealloc_quota = 0;
- cli->cli_obd = conn->oc_dev;
- list_add(&(cli->cli_chain), conn->oc_dev->obd_gen_clients.prev);
-
- CDEBUG(D_INFO, "connect: new ID %u\n", cli->cli_id);
- conn->oc_id = cli->cli_id;
- return 0;
+ struct obd_client * cli;
+
+ OBD_ALLOC(cli, struct obd_client *, sizeof(struct obd_client));
+ if ( !cli ) {
+ printk(__FUNCTION__ ": no memory! (minor %d)\n",
+ conn->oc_dev->obd_minor);
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&cli->cli_prealloc_inodes);
+ /* XXX this should probably spinlocked? */
+ cli->cli_id = ++conn->oc_dev->obd_gen_last_id;
+ cli->cli_prealloc_quota = 0;
+ cli->cli_obd = conn->oc_dev;
+ list_add(&(cli->cli_chain), conn->oc_dev->obd_gen_clients.prev);
+
+ CDEBUG(D_INFO, "connect: new ID %u\n", cli->cli_id);
+ conn->oc_id = cli->cli_id;
+ return 0;
} /* gen_obd_connect */
int gen_disconnect(struct obd_conn *conn)
{
- struct obd_client * cli;
- ENTRY;
+ struct obd_client * cli;
+ ENTRY;
- if (!(cli = gen_client(conn))) {
- CDEBUG(D_IOCTL, "disconnect: attempting to free "
- "nonexistent client %u\n", conn->oc_id);
- return -EINVAL;
- }
+ if (!(cli = gen_client(conn))) {
+ CDEBUG(D_IOCTL, "disconnect: attempting to free "
+ "nonexistent client %u\n", conn->oc_id);
+ return -EINVAL;
+ }
- list_del(&(cli->cli_chain));
- OBD_FREE(cli, sizeof(struct obd_client));
+ list_del(&(cli->cli_chain));
+ OBD_FREE(cli, sizeof(struct obd_client));
- CDEBUG(D_INFO, "disconnect: ID %u\n", conn->oc_id);
+ CDEBUG(D_INFO, "disconnect: ID %u\n", conn->oc_id);
- EXIT;
- return 0;
+ EXIT;
+ return 0;
} /* gen_obd_disconnect */
*/
int gen_multi_setup(struct obd_device *obddev, uint32_t len, void *data)
{
- int i;
-
- for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
- int rc;
- struct obd_conn *ch_conn = &obddev->obd_multi_conn[i];
- rc = OBP(ch_conn->oc_dev, connect)(ch_conn);
-
- if ( rc != 0 ) {
- int j;
-
- for (j = --i; j >= 0; --j) {
- ch_conn = &obddev->obd_multi_conn[i];
- OBP(ch_conn->oc_dev, disconnect)(ch_conn);
- }
- return -EINVAL;
- }
- }
- return 0;
+ int i;
+
+ for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
+ int rc;
+ struct obd_conn *ch_conn = &obddev->obd_multi_conn[i];
+ rc = OBP(ch_conn->oc_dev, connect)(ch_conn);
+
+ if ( rc != 0 ) {
+ int j;
+
+ for (j = --i; j >= 0; --j) {
+ ch_conn = &obddev->obd_multi_conn[i];
+ OBP(ch_conn->oc_dev, disconnect)(ch_conn);
+ }
+ return -EINVAL;
+ }
+ }
+ return 0;
}
#if 0
int gen_multi_attach(struct obd_device *obddev, int len, void *data)
{
- int i;
- int count;
- struct obd_device *rdev = obddev->obd_multi_dev[0];
-
- count = len/sizeof(int);
- obddev->obd_multi_count = count;
- for (i=0 ; i<count ; i++) {
- rdev = &obd_dev[*((int *)data + i)];
- rdev = rdev + 1;
- CDEBUG(D_INFO, "OBD RAID1: replicator %d is of type %s\n", i,
- (rdev + i)->obd_type->typ_name);
- }
- return 0;
+ int i;
+ int count;
+ struct obd_device *rdev = obddev->obd_multi_dev[0];
+
+ count = len/sizeof(int);
+ obddev->obd_multi_count = count;
+ for (i=0 ; i<count ; i++) {
+ rdev = &obd_dev[*((int *)data + i)];
+ rdev = rdev + 1;
+ CDEBUG(D_INFO, "OBD RAID1: replicator %d is of type %s\n", i,
+ (rdev + i)->obd_type->typ_name);
+ }
+ return 0;
}
#endif
*/
int gen_multi_cleanup(struct obd_device *obddev)
{
- int i;
-
- for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
- struct obd_conn *ch_conn = &obddev->obd_multi_conn[i];
- int rc;
- rc = OBP(ch_conn->oc_dev, disconnect)(ch_conn);
-
- if ( rc != 0 ) {
- printk(KERN_WARNING __FUNCTION__
- ": disconnect failure %d\n",
- ch_conn->oc_dev->obd_minor);
- }
- }
- return 0;
+ int i;
+
+ for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
+ struct obd_conn *ch_conn = &obddev->obd_multi_conn[i];
+ int rc;
+ rc = OBP(ch_conn->oc_dev, disconnect)(ch_conn);
+
+ if ( rc != 0 ) {
+ printk(KERN_WARNING __FUNCTION__
+ ": disconnect failure %d\n",
+ ch_conn->oc_dev->obd_minor);
+ }
+ }
+ return 0;
} /* gen_multi_cleanup_device */
*/
int gen_cleanup(struct obd_device * obddev)
{
- struct list_head * lh, * tmp;
- struct obd_client * cli;
-
- ENTRY;
-
- lh = tmp = &obddev->obd_gen_clients;
- while ((tmp = tmp->next) != lh) {
- cli = list_entry(tmp, struct obd_client, cli_chain);
- CDEBUG(D_INFO, "Disconnecting obd_connection %d, at %p\n",
- cli->cli_id, cli);
- }
- return 0;
+ struct list_head * lh, * tmp;
+ struct obd_client * cli;
+
+ ENTRY;
+
+ lh = tmp = &obddev->obd_gen_clients;
+ while ((tmp = tmp->next) != lh) {
+ cli = list_entry(tmp, struct obd_client, cli_chain);
+ CDEBUG(D_INFO, "Disconnecting obd_connection %d, at %p\n",
+ cli->cli_id, cli);
+ }
+ return 0;
} /* sim_cleanup_device */
void ___wait_on_page(struct page *page)
}
int gen_copy_data(struct obd_conn *dst_conn, struct obdo *dst,
- struct obd_conn *src_conn, struct obdo *src,
- obd_size count, obd_off offset)
+ struct obd_conn *src_conn, struct obdo *src,
+ obd_size count, obd_off offset)
{
- struct page *page;
- unsigned long index = 0;
- int err = 0;
-
- ENTRY;
- CDEBUG(D_INFO, "src: ino %Ld blocks %Ld, size %Ld, dst: ino %Ld\n",
- src->o_id, src->o_blocks, src->o_size, dst->o_id);
- page = alloc_page(GFP_USER);
- if ( !page ) {
- EXIT;
- return -ENOMEM;
- }
-
- lck_page(page);
-
- /* XXX with brw vector I/O, we could batch up reads and writes here,
- * all we need to do is allocate multiple pages to handle the I/Os
- * and arrays to handle the request parameters.
- */
- while (index < ((src->o_size + PAGE_SIZE - 1) >> PAGE_SHIFT)) {
- obd_count num_oa = 1;
- obd_count num_buf = 1;
- char *buf;
- obd_size brw_count = PAGE_SIZE;
- obd_off brw_offset = (page->index) << PAGE_SHIFT;
- obd_flag flagr = 0;
- obd_flag flagw = OBD_BRW_CREATE;
-
- page->index = index;
- buf = (char *)page_address(page);
- err = OBP(src_conn->oc_dev, brw)(READ, src_conn, num_oa, &src,
- &num_buf, &buf, &brw_count,
- &brw_offset, &flagr);
-
- if ( err ) {
- EXIT;
- break;
- }
- CDEBUG(D_INFO, "Read page %ld ...\n", page->index);
-
- err = OBP(dst_conn->oc_dev, brw)(WRITE, dst_conn, num_oa, &dst,
- &num_buf, &buf, &brw_count,
- &brw_offset, &flagw);
-
- /* XXX should handle dst->o_size, dst->o_blocks here */
- if ( err ) {
- EXIT;
- break;
- }
-
- CDEBUG(D_INFO, "Wrote page %ld ...\n", page->index);
-
- index++;
- }
- dst->o_size = src->o_size;
- dst->o_blocks = src->o_blocks;
- dst->o_valid |= (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS);
- UnlockPage(page);
- __free_page(page);
-
- EXIT;
- return err;
+ struct page *page;
+ unsigned long index = 0;
+ int err = 0;
+
+ ENTRY;
+ CDEBUG(D_INFO, "src: ino %Ld blocks %Ld, size %Ld, dst: ino %Ld\n",
+ src->o_id, src->o_blocks, src->o_size, dst->o_id);
+ page = alloc_page(GFP_USER);
+ if ( !page ) {
+ EXIT;
+ return -ENOMEM;
+ }
+
+ lck_page(page);
+
+ /* XXX with brw vector I/O, we could batch up reads and writes here,
+ * all we need to do is allocate multiple pages to handle the I/Os
+ * and arrays to handle the request parameters.
+ */
+ while (index < ((src->o_size + PAGE_SIZE - 1) >> PAGE_SHIFT)) {
+ obd_count num_oa = 1;
+ obd_count num_buf = 1;
+ char *buf;
+ obd_size brw_count = PAGE_SIZE;
+ obd_off brw_offset = (page->index) << PAGE_SHIFT;
+ obd_flag flagr = 0;
+ obd_flag flagw = OBD_BRW_CREATE;
+
+ page->index = index;
+ buf = (char *)page_address(page);
+ err = OBP(src_conn->oc_dev, brw)(READ, src_conn, num_oa, &src,
+ &num_buf, &buf, &brw_count,
+ &brw_offset, &flagr);
+
+ if ( err ) {
+ EXIT;
+ break;
+ }
+ CDEBUG(D_INFO, "Read page %ld ...\n", page->index);
+
+ err = OBP(dst_conn->oc_dev, brw)(WRITE, dst_conn, num_oa, &dst,
+ &num_buf, &buf, &brw_count,
+ &brw_offset, &flagw);
+
+ /* XXX should handle dst->o_size, dst->o_blocks here */
+ if ( err ) {
+ EXIT;
+ break;
+ }
+
+ CDEBUG(D_INFO, "Wrote page %ld ...\n", page->index);
+
+ index++;
+ }
+ dst->o_size = src->o_size;
+ dst->o_blocks = src->o_blocks;
+ dst->o_valid |= (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS);
+ UnlockPage(page);
+ __free_page(page);
+
+ EXIT;
+ return err;
}
+#include <linux/autoconf.h>
+#include <linux/sysctl.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/sysctl.h>
static int index = 0;
static int obd_sctl_vars( ctl_table * table, int write, struct file *
- filp, void * buffer, size_t * lenp );
+ filp, void * buffer, size_t * lenp );
static int obd_sctl_reset( ctl_table * table, int write, struct file
- * filp, void * buffer, size_t * lenp );
+ * filp, void * buffer, size_t * lenp );
-#define OBD_SYSCTL 1
+#define OBD_SYSCTL 300
-#define OBD_DEBUG 1 /* control debugging */
-#define OBD_ENTRY 2 /* control enter/leave pattern */
+#define OBD_DEBUG 1 /* control debugging */
+#define OBD_ENTRY 2 /* control enter/leave pattern */
#define OBD_TIMEOUT 3 /* timeout on upcalls to become intrble */
#define OBD_HARD 4 /* mount type "hard" or "soft" */
#define OBD_VARS 5
#define OBD_VARS_SLOT 2
static ctl_table obd_table[] = {
- {OBD_DEBUG, "debug", &obd_debug_level, sizeof(int), 0644, NULL, &proc_dointvec},
- {OBD_ENTRY, "trace", &obd_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
- {OBD_VARS, "vars", &vars[0], sizeof(int), 0644, NULL, &proc_dointvec},
- {OBD_INDEX, "index", &index, sizeof(int), 0644, NULL, &obd_sctl_vars},
- {OBD_RESET, "reset", NULL, 0, 0644, NULL, &obd_sctl_reset},
- { 0 }
+ {OBD_DEBUG, "debug", &obd_debug_level, sizeof(int), 0644, NULL, &proc_dointvec},
+ {OBD_ENTRY, "trace", &obd_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
+ {OBD_VARS, "vars", &vars[0], sizeof(int), 0644, NULL, &proc_dointvec},
+ {OBD_INDEX, "index", &index, sizeof(int), 0644, NULL, &obd_sctl_vars},
+ {OBD_RESET, "reset", NULL, 0, 0644, NULL, &obd_sctl_reset},
+ { 0 }
};
-#if 0
-static ctl_table jukebox_table[] = {
+static ctl_table parent_table[] = {
{OBD_SYSCTL, "obd", NULL, 0, 0555, obd_table},
{0}
};
-#endif
void obd_sysctl_init (void)
{
#ifdef CONFIG_SYSCTL
- if ( !obd_table_header )
- obd_table_header = register_sysctl_table(jukebox_table, 0);
+ if ( !obd_table_header )
+ obd_table_header = register_sysctl_table(parent_table, 0);
#endif
}
void obd_sysctl_clean (void)
{
#ifdef CONFIG_SYSCTL
- if ( obd_table_header )
- unregister_sysctl_table(obd_table_header);
- obd_table_header = NULL;
+ if ( obd_table_header )
+ unregister_sysctl_table(obd_table_header);
+ obd_table_header = NULL;
#endif
}
int obd_sctl_reset (ctl_table * table, int write,
- struct file * filp, void * buffer,
- size_t * lenp)
+ struct file * filp, void * buffer,
+ size_t * lenp)
{
- if ( write ) {
- /* do something here */
- vars[0]=0;
- vars[1]=0;
- }
-
- *lenp = 0;
- return 0;
+ if ( write ) {
+ /* do something here */
+ vars[0]=0;
+ vars[1]=0;
+ }
+
+ *lenp = 0;
+ return 0;
}
int obd_sctl_vars (ctl_table * table, int write,
- struct file * filp, void * buffer,
- size_t * lenp)
+ struct file * filp, void * buffer,
+ size_t * lenp)
{
- int rc;
+ int rc;
- rc = proc_dointvec(table, write, filp, buffer, lenp);
+ rc = proc_dointvec(table, write, filp, buffer, lenp);
- if ( rc )
- return rc;
+ if ( rc )
+ return rc;
- if ( index < 0 || index > 1 ) {
- printk(KERN_WARNING __FUNCTION__ "Illegal index %d!\n", index);
- index = 0;
- } else {
- obd_table[OBD_VARS_SLOT].data = &vars[index];
- }
+ if ( index < 0 || index > 1 ) {
+ printk(KERN_WARNING __FUNCTION__ "Illegal index %d!\n", index);
+ index = 0;
+ } else {
+ obd_table[OBD_VARS_SLOT].data = &vars[index];
+ }
- return rc;
+ return rc;
}
#define nr_free_buffer_pages() 32768
struct {
- int nfract; /* Percentage of buffer cache dirty to
- activate bdflush */
- int ndirty; /* Maximum number of dirty blocks to write out per
- wake-cycle */
- int nrefill; /* Number of clean buffers to try to obtain
- each time we call refill */
- int nref_dirt; /* Dirty buffer threshold for activating bdflush
- when trying to refill buffers. */
- int interval; /* jiffies delay between pupdate flushes */
- int age_buffer; /* Time for normal buffer to age before we flush it */
- int age_super; /* Time for superblock to age before we flush it */
+ int nfract; /* Percentage of buffer cache dirty to
+ activate bdflush */
+ int ndirty; /* Maximum number of dirty blocks to write out per
+ wake-cycle */
+ int nrefill; /* Number of clean buffers to try to obtain
+ each time we call refill */
+ int nref_dirt; /* Dirty buffer threshold for activating bdflush
+ when trying to refill buffers. */
+ int interval; /* jiffies delay between pupdate flushes */
+ int age_buffer; /* Time for normal buffer to age before we flush it */
+ int age_super; /* Time for superblock to age before we flush it */
} pupd_prm = {40, 1024, 64, 256, 1*HZ, 30*HZ, 5*HZ };
/* Called with the superblock list lock held */
static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo,
- int nr_slots, struct page **pages, char **bufs,
- obd_size *counts, obd_off *offsets,
- obd_flag *flag, unsigned long check_time)
+ int nr_slots, struct page **pages, char **bufs,
+ obd_size *counts, obd_off *offsets,
+ obd_flag *flag, unsigned long check_time)
{
- struct list_head *page_list = obdfs_iplist(inode);
- struct list_head *tmp;
- int num = 0;
-
- ENTRY;
-
- tmp = page_list;
- /* Traverse list in reverse order, so we do FIFO, not LIFO order */
- while ( (tmp = tmp->prev) != page_list && num < nr_slots ) {
- struct obdfs_pgrq *req;
- struct page *page;
-
- req = list_entry(tmp, struct obdfs_pgrq, rq_plist);
- page = req->rq_page;
-
-
- if (req->rq_jiffies > check_time)
- break; /* pages are in chronological order */
-
- /* Only allocate the obdo if we will actually do I/O here */
- if ( !*obdo ) {
- OIDEBUG(inode);
- *obdo = obdo_fromid(IID(inode), inode->i_ino,
- OBD_MD_FLNOTOBD);
- if ( IS_ERR(*obdo) ) {
- int err = PTR_ERR(*obdo);
- *obdo = NULL;
-
- EXIT;
- return err;
- }
-
- /* FIXME revisit fromid & from_inode */
- obdfs_from_inode(*obdo, inode);
- *flag = OBD_BRW_CREATE;
- }
-
- /* Remove request from list before write to avoid conflict.
- * Note that obdfs_pgrq_del() also deletes the request.
- */
- obdfs_pgrq_del(req);
- if ( !page ) {
- CDEBUG(D_CACHE, "no page \n");
- continue;
- }
-
- bufs[num] = (char *)page_address(page);
- pages[num] = page;
- counts[num] = PAGE_SIZE;
- offsets[num] = ((obd_off)page->index) << PAGE_SHIFT;
- CDEBUG(D_INFO, "ENQ inode %ld, page %p addr %p to vector\n",
- inode->i_ino, page, (char *)page_address(page));
- num++;
- }
-
- if (!list_empty(page_list))
- CDEBUG(D_INFO, "inode %ld list not empty\n", inode->i_ino);
- CDEBUG(D_INFO, "added %d page(s) to vector\n", num);
-
- EXIT;
- return num;
+ struct list_head *page_list = obdfs_iplist(inode);
+ struct list_head *tmp;
+ int num = 0;
+
+ ENTRY;
+
+ tmp = page_list;
+ /* Traverse list in reverse order, so we do FIFO, not LIFO order */
+ while ( (tmp = tmp->prev) != page_list && num < nr_slots ) {
+ struct obdfs_pgrq *req;
+ struct page *page;
+
+ req = list_entry(tmp, struct obdfs_pgrq, rq_plist);
+ page = req->rq_page;
+
+
+ if (req->rq_jiffies > check_time)
+ break; /* pages are in chronological order */
+
+ /* Only allocate the obdo if we will actually do I/O here */
+ if ( !*obdo ) {
+ OIDEBUG(inode);
+ *obdo = obdo_fromid(IID(inode), inode->i_ino,
+ OBD_MD_FLNOTOBD);
+ if ( IS_ERR(*obdo) ) {
+ int err = PTR_ERR(*obdo);
+ *obdo = NULL;
+
+ EXIT;
+ return err;
+ }
+
+ /* FIXME revisit fromid & from_inode */
+ obdfs_from_inode(*obdo, inode);
+ *flag = OBD_BRW_CREATE;
+ }
+
+ /* Remove request from list before write to avoid conflict.
+ * Note that obdfs_pgrq_del() also deletes the request.
+ */
+ obdfs_pgrq_del(req);
+ if ( !page ) {
+ CDEBUG(D_CACHE, "no page \n");
+ continue;
+ }
+
+ bufs[num] = (char *)page_address(page);
+ pages[num] = page;
+ counts[num] = PAGE_SIZE;
+ offsets[num] = ((obd_off)page->index) << PAGE_SHIFT;
+ CDEBUG(D_INFO, "ENQ inode %ld, page %p addr %p to vector\n",
+ inode->i_ino, page, (char *)page_address(page));
+ num++;
+ }
+
+ if (!list_empty(page_list))
+ CDEBUG(D_INFO, "inode %ld list not empty\n", inode->i_ino);
+ CDEBUG(D_INFO, "added %d page(s) to vector\n", num);
+
+ EXIT;
+ return num;
} /* obdfs_enqueue_pages */
/* Dequeue cached pages for a dying inode without writing them to disk. */
void obdfs_dequeue_pages(struct inode *inode)
{
- struct list_head *tmp;
-
- ENTRY;
- obd_down(&obdfs_i2sbi(inode)->osi_list_mutex);
- tmp = obdfs_islist(inode);
- if ( list_empty(tmp) ) {
- CDEBUG(D_INFO, "no dirty pages for inode %ld\n", inode->i_ino);
- obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
- EXIT;
- return;
- }
-
- /* take it out of the super list */
- list_del(tmp);
- INIT_LIST_HEAD(obdfs_islist(inode));
-
- tmp = obdfs_iplist(inode);
- while ( (tmp = tmp->prev) != obdfs_iplist(inode) ) {
- struct obdfs_pgrq *req;
- struct page *page;
-
- req = list_entry(tmp, struct obdfs_pgrq, rq_plist);
- page = req->rq_page;
- /* take it out of the list and free */
- obdfs_pgrq_del(req);
- /* now put the page away */
- put_page(page);
- }
-
- obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
-
- /* decrement inode reference for page cache */
- inode->i_count--;
- EXIT;
+ struct list_head *tmp;
+
+ ENTRY;
+ obd_down(&obdfs_i2sbi(inode)->osi_list_mutex);
+ tmp = obdfs_islist(inode);
+ if ( list_empty(tmp) ) {
+ CDEBUG(D_INFO, "no dirty pages for inode %ld\n", inode->i_ino);
+ obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
+ EXIT;
+ return;
+ }
+
+ /* take it out of the super list */
+ list_del(tmp);
+ INIT_LIST_HEAD(obdfs_islist(inode));
+
+ tmp = obdfs_iplist(inode);
+ while ( (tmp = tmp->prev) != obdfs_iplist(inode) ) {
+ struct obdfs_pgrq *req;
+ struct page *page;
+
+ req = list_entry(tmp, struct obdfs_pgrq, rq_plist);
+ page = req->rq_page;
+ /* take it out of the list and free */
+ obdfs_pgrq_del(req);
+ /* now put the page away */
+ put_page(page);
+ }
+
+ obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
+
+ /* decrement inode reference for page cache */
+ atomic_dec(&inode->i_count);
+ EXIT;
}
/* Remove writeback requests for the superblock */
int obdfs_flush_reqs(struct list_head *inode_list, unsigned long check_time)
{
- struct list_head *tmp;
- unsigned long max_io, total_io = 0;
- obd_count num_io;
- obd_count num_obdos;
- struct inode *inodes[MAX_IOVEC]; /* write data back to these */
- struct page *pages[MAX_IOVEC]; /* call put_page on these */
- struct obdo *obdos[MAX_IOVEC];
- char *bufs[MAX_IOVEC];
- obd_size counts[MAX_IOVEC];
- obd_off offsets[MAX_IOVEC];
- obd_flag flags[MAX_IOVEC];
- obd_count bufs_per_obdo[MAX_IOVEC];
- int err = 0;
- struct obdfs_sb_info *sbi;
-
- ENTRY;
- if (!inode_list) {
- CDEBUG(D_INODE, "no list\n");
- EXIT;
- return 0;
- }
-
- sbi = list_entry(inode_list, struct obdfs_sb_info, osi_inodes);
-
- obd_down(&sbi->osi_list_mutex);
- if ( list_empty(inode_list) ) {
- CDEBUG(D_INFO, "list empty\n");
- obd_up(&sbi->osi_list_mutex);
- EXIT;
- return 0;
- }
-
- /* If we are forcing a write, write out all dirty pages */
- max_io = check_time == ~0UL ? 1<<31 : pupd_prm.ndirty;
- CDEBUG(D_INFO, "max_io = %lu\n", max_io);
-
- /* Add each inode's dirty pages to a write vector, and write it.
- * Traverse list in reverse order, so we do FIFO, not LIFO order
- */
+ struct list_head *tmp;
+ unsigned long max_io, total_io = 0;
+ obd_count num_io;
+ obd_count num_obdos;
+ struct inode *inodes[MAX_IOVEC]; /* write data back to these */
+ struct page *pages[MAX_IOVEC]; /* call put_page on these */
+ struct obdo *obdos[MAX_IOVEC];
+ char *bufs[MAX_IOVEC];
+ obd_size counts[MAX_IOVEC];
+ obd_off offsets[MAX_IOVEC];
+ obd_flag flags[MAX_IOVEC];
+ obd_count bufs_per_obdo[MAX_IOVEC];
+ int err = 0;
+ struct obdfs_sb_info *sbi;
+
+ ENTRY;
+ if (!inode_list) {
+ CDEBUG(D_INODE, "no list\n");
+ EXIT;
+ return 0;
+ }
+
+ sbi = list_entry(inode_list, struct obdfs_sb_info, osi_inodes);
+
+ obd_down(&sbi->osi_list_mutex);
+ if ( list_empty(inode_list) ) {
+ CDEBUG(D_INFO, "list empty\n");
+ obd_up(&sbi->osi_list_mutex);
+ EXIT;
+ return 0;
+ }
+
+ /* If we are forcing a write, write out all dirty pages */
+ max_io = check_time == ~0UL ? 1<<31 : pupd_prm.ndirty;
+ CDEBUG(D_INFO, "max_io = %lu\n", max_io);
+
+ /* Add each inode's dirty pages to a write vector, and write it.
+ * Traverse list in reverse order, so we do FIFO, not LIFO order
+ */
again:
- tmp = inode_list;
- num_io = 0;
- num_obdos = 0;
- while ( (tmp = tmp->prev) != inode_list && total_io < max_io) {
- struct obdfs_inode_info *ii;
- struct inode *inode;
- int res;
-
- ii = list_entry(tmp, struct obdfs_inode_info, oi_inodes);
- inode = list_entry(ii, struct inode, u);
- inodes[num_obdos] = inode;
- obdos[num_obdos] = NULL;
- CDEBUG(D_INFO, "checking inode %ld pages\n", inode->i_ino);
-
- /* Make sure we reference "inode" and not "inodes[num_obdos]",
- * as num_obdos will change after the loop is run.
- */
- if (!list_empty(obdfs_iplist(inode))) {
- res = obdfs_enqueue_pages(inode, &obdos[num_obdos],
- MAX_IOVEC - num_io,
- &pages[num_io], &bufs[num_io],
- &counts[num_io],
- &offsets[num_io],
- &flags[num_obdos],
- check_time);
- CDEBUG(D_INFO, "FLUSH inode %ld, pages flushed: %d\n",
- inode->i_ino, res);
- if ( res < 0 ) {
- CDEBUG(D_INODE,
- "fatal: unable to enqueue inode %ld (err %d)\n",
- inode->i_ino, res);
- /* XXX Move bad inode to end of list so we can
- * continue with flushing list. This is a
- * temporary measure to avoid machine lockups.
- * Maybe if we have -ENOENT, simply discard.
- */
- list_del(tmp);
- list_add(tmp, inode_list);
- err = res;
- EXIT;
- goto BREAK;
- }
- if (res == 0)
- continue;
-
- num_io += res;
- total_io += res;
- bufs_per_obdo[num_obdos] = res;
- num_obdos++;
-
- if ( num_io == MAX_IOVEC ) {
- obd_up(&sbi->osi_list_mutex);
- err = obdfs_do_vec_wr(inodes, num_io, num_obdos,
- obdos, bufs_per_obdo,
- pages, bufs, counts,
- offsets, flags);
- if ( err ) {
- CDEBUG(D_INODE,
- "fatal: do_vec_wr err=%d\n",
- err);
- EXIT;
- goto ERR;
- }
- obd_down(&sbi->osi_list_mutex);
- goto again;
- }
- }
- }
+ tmp = inode_list;
+ num_io = 0;
+ num_obdos = 0;
+ while ( (tmp = tmp->prev) != inode_list && total_io < max_io) {
+ struct obdfs_inode_info *ii;
+ struct inode *inode;
+ int res;
+
+ ii = list_entry(tmp, struct obdfs_inode_info, oi_inodes);
+ inode = list_entry(ii, struct inode, u);
+ inodes[num_obdos] = inode;
+ obdos[num_obdos] = NULL;
+ CDEBUG(D_INFO, "checking inode %ld pages\n", inode->i_ino);
+
+ /* Make sure we reference "inode" and not "inodes[num_obdos]",
+ * as num_obdos will change after the loop is run.
+ */
+ if (!list_empty(obdfs_iplist(inode))) {
+ res = obdfs_enqueue_pages(inode, &obdos[num_obdos],
+ MAX_IOVEC - num_io,
+ &pages[num_io], &bufs[num_io],
+ &counts[num_io],
+ &offsets[num_io],
+ &flags[num_obdos],
+ check_time);
+ CDEBUG(D_INFO, "FLUSH inode %ld, pages flushed: %d\n",
+ inode->i_ino, res);
+ if ( res < 0 ) {
+ CDEBUG(D_INODE,
+ "fatal: unable to enqueue inode %ld (err %d)\n",
+ inode->i_ino, res);
+ /* XXX Move bad inode to end of list so we can
+ * continue with flushing list. This is a
+ * temporary measure to avoid machine lockups.
+ * Maybe if we have -ENOENT, simply discard.
+ */
+ list_del(tmp);
+ list_add(tmp, inode_list);
+ err = res;
+ EXIT;
+ goto BREAK;
+ }
+ if (res == 0)
+ continue;
+
+ num_io += res;
+ total_io += res;
+ bufs_per_obdo[num_obdos] = res;
+ num_obdos++;
+
+ if ( num_io == MAX_IOVEC ) {
+ obd_up(&sbi->osi_list_mutex);
+ err = obdfs_do_vec_wr(inodes, num_io, num_obdos,
+ obdos, bufs_per_obdo,
+ pages, bufs, counts,
+ offsets, flags);
+ if ( err ) {
+ CDEBUG(D_INODE,
+ "fatal: do_vec_wr err=%d\n",
+ err);
+ EXIT;
+ goto ERR;
+ }
+ obd_down(&sbi->osi_list_mutex);
+ goto again;
+ }
+ }
+ }
BREAK:
- obd_up(&sbi->osi_list_mutex);
-
- /* flush any remaining I/Os */
- if ( num_io ) {
- err = obdfs_do_vec_wr(inodes, num_io, num_obdos, obdos,
- bufs_per_obdo, pages, bufs, counts,
- offsets, flags);
- if (err)
- CDEBUG(D_INODE, "fatal: unable to do vec_wr (err %d)\n", err);
- num_io = 0;
- num_obdos = 0;
- }
-
- /* Remove inode from superblock dirty list when no more pages.
- * Make sure we don't point at the current inode with tmp
- * when we re-init the list on the inode, or we will loop.
- */
- obd_down(&sbi->osi_list_mutex);
- tmp = inode_list;
- while ( (tmp = tmp->prev) != inode_list ) {
- struct obdfs_inode_info *ii;
- struct inode *inode;
-
- ii = list_entry(tmp, struct obdfs_inode_info, oi_inodes);
- inode = list_entry(ii, struct inode, u);
- CDEBUG(D_INFO, "checking inode %ld empty\n", inode->i_ino);
- if (list_empty(obdfs_iplist(inode))) {
- CDEBUG(D_INFO, "remove inode %ld from dirty list\n",
- inode->i_ino);
- tmp = tmp->next;
- list_del(obdfs_islist(inode));
- /* decrement inode reference for page cache */
- inode->i_count--;
- INIT_LIST_HEAD(obdfs_islist(inode));
- }
- }
- obd_up(&sbi->osi_list_mutex);
-
- CDEBUG(D_INFO, "flushed %d pages in total\n", total_io);
- EXIT;
+ obd_up(&sbi->osi_list_mutex);
+
+ /* flush any remaining I/Os */
+ if ( num_io ) {
+ err = obdfs_do_vec_wr(inodes, num_io, num_obdos, obdos,
+ bufs_per_obdo, pages, bufs, counts,
+ offsets, flags);
+ if (err)
+ CDEBUG(D_INODE, "fatal: unable to do vec_wr (err %d)\n", err);
+ num_io = 0;
+ num_obdos = 0;
+ }
+
+ /* Remove inode from superblock dirty list when no more pages.
+ * Make sure we don't point at the current inode with tmp
+ * when we re-init the list on the inode, or we will loop.
+ */
+ obd_down(&sbi->osi_list_mutex);
+ tmp = inode_list;
+ while ( (tmp = tmp->prev) != inode_list ) {
+ struct obdfs_inode_info *ii;
+ struct inode *inode;
+
+ ii = list_entry(tmp, struct obdfs_inode_info, oi_inodes);
+ inode = list_entry(ii, struct inode, u);
+ CDEBUG(D_INFO, "checking inode %ld empty\n", inode->i_ino);
+ if (list_empty(obdfs_iplist(inode))) {
+ CDEBUG(D_INFO, "remove inode %ld from dirty list\n",
+ inode->i_ino);
+ tmp = tmp->next;
+ list_del(obdfs_islist(inode));
+ /* decrement inode reference for page cache */
+ atomic_dec(&inode->i_count);
+ INIT_LIST_HEAD(obdfs_islist(inode));
+ }
+ }
+ obd_up(&sbi->osi_list_mutex);
+
+ CDEBUG(D_INFO, "flushed %ld pages in total\n", total_io);
+ EXIT;
ERR:
- return err ? err : total_io;
+ return err ? err : total_io;
} /* obdfs_flush_reqs */
*/
int obdfs_flush_dirty_pages(unsigned long check_time)
{
- struct list_head *sl;
- int max = 0;
-
- ENTRY;
- sl = &obdfs_super_list;
- while ( (sl = sl->prev) != &obdfs_super_list ) {
- struct obdfs_sb_info *sbi =
- list_entry(sl, struct obdfs_sb_info, osi_list);
- int ret;
-
- /* walk write requests here, use the sb, check the time */
- ret = obdfs_flush_reqs(&sbi->osi_inodes, check_time);
- /* XXX handle error? What to do with it? */
-
- max = ret > max ? ret : max;
- }
- EXIT;
- return max;
+ struct list_head *sl;
+ int max = 0;
+
+ ENTRY;
+ sl = &obdfs_super_list;
+ while ( (sl = sl->prev) != &obdfs_super_list ) {
+ struct obdfs_sb_info *sbi =
+ list_entry(sl, struct obdfs_sb_info, osi_list);
+ int ret;
+
+ /* walk write requests here, use the sb, check the time */
+ ret = obdfs_flush_reqs(&sbi->osi_inodes, check_time);
+ /* XXX handle error? What to do with it? */
+
+ max = ret > max ? ret : max;
+ }
+ EXIT;
+ return max;
} /* obdfs_flush_dirty_pages */
static int pupdate(void *unused)
{
- int interval = pupd_prm.interval;
- long age = pupd_prm.age_buffer;
- int wrote = 0;
-
- exit_files(current);
- exit_mm(current);
-
- pupdated = current;
- pupdated->session = 1;
- pupdated->pgrp = 1;
- strcpy(pupdated->comm, "pupdated");
-
- printk("pupdated activated...\n");
-
- spin_lock_irq(&pupdated->sigmask_lock);
- sigfillset(&pupdated->blocked);
- siginitsetinv(&pupdated->blocked, sigmask(SIGTERM));
- recalc_sigpending(pupdated);
- spin_unlock_irq(&pupdated->sigmask_lock);
-
- for (;;) {
- long dirty_limit;
-
- /* update interval */
- if (interval) {
- set_task_state(pupdated, TASK_INTERRUPTIBLE);
- schedule_timeout(interval);
- }
- if (signal_pending(pupdated))
- {
- int stopped = 0;
- spin_lock_irq(&pupdated->sigmask_lock);
- if (sigismember(&pupdated->signal, SIGTERM))
- {
- sigdelset(&pupdated->signal, SIGTERM);
- stopped = 1;
- }
- recalc_sigpending(pupdated);
- spin_unlock_irq(&pupdated->sigmask_lock);
- if (stopped) {
- printk("pupdated stopped...\n");
- set_task_state(pupdated, TASK_STOPPED);
- pupdated = NULL;
- return 0;
- }
- }
- /* asynchronous setattr etc for the future ...
- obdfs_flush_dirty_inodes(jiffies - pupd_prm.age_super);
- */
- dirty_limit = nr_free_buffer_pages() * pupd_prm.nfract / 100;
-
- if (obdfs_cache_count > dirty_limit) {
- interval = 0;
- if ( wrote < pupd_prm.ndirty )
- age >>= 1;
- CDEBUG(D_CACHE, "wrote %d, age %ld, interval %d\n",
- wrote, age, interval);
- } else {
- if ( wrote < pupd_prm.ndirty >> 1 &&
- obdfs_cache_count < dirty_limit / 2) {
- interval = pupd_prm.interval;
- age = pupd_prm.age_buffer;
- CDEBUG(D_INFO,
- "wrote %d, age %ld, interval %d\n",
- wrote, age, interval);
- } else if (obdfs_cache_count > dirty_limit / 2) {
- interval >>= 1;
- if ( wrote < pupd_prm.ndirty )
- age >>= 1;
- CDEBUG(D_CACHE,
- "wrote %d, age %ld, interval %d\n",
- wrote, age, interval);
- }
- }
-
- wrote = obdfs_flush_dirty_pages(jiffies - age);
- if (wrote)
- CDEBUG(D_CACHE,
- "dirty_limit %ld, cache_count %ld, wrote %d\n",
- dirty_limit, obdfs_cache_count, wrote);
- }
+ int interval = pupd_prm.interval;
+ long age = pupd_prm.age_buffer;
+ int wrote = 0;
+
+ exit_files(current);
+ exit_mm(current);
+
+ pupdated = current;
+ pupdated->session = 1;
+ pupdated->pgrp = 1;
+ strcpy(pupdated->comm, "pupdated");
+
+ printk("pupdated activated...\n");
+
+ spin_lock_irq(&pupdated->sigmask_lock);
+ sigfillset(&pupdated->blocked);
+ siginitsetinv(&pupdated->blocked, sigmask(SIGTERM));
+ recalc_sigpending(pupdated);
+ spin_unlock_irq(&pupdated->sigmask_lock);
+
+ for (;;) {
+ long dirty_limit;
+
+ /* update interval */
+ if (interval) {
+ set_task_state(pupdated, TASK_INTERRUPTIBLE);
+ schedule_timeout(interval);
+ }
+ if (signal_pending(pupdated))
+ {
+ int stopped = 0;
+ spin_lock_irq(&pupdated->sigmask_lock);
+ if (sigismember(&pupdated->pending.signal, SIGTERM))
+ {
+ sigdelset(&pupdated->pending.signal, SIGTERM);
+ stopped = 1;
+ }
+ recalc_sigpending(pupdated);
+ spin_unlock_irq(&pupdated->sigmask_lock);
+ if (stopped) {
+ printk("pupdated stopped...\n");
+ set_task_state(pupdated, TASK_STOPPED);
+ pupdated = NULL;
+ return 0;
+ }
+ }
+ /* asynchronous setattr etc for the future ...
+ obdfs_flush_dirty_inodes(jiffies - pupd_prm.age_super);
+ */
+ dirty_limit = nr_free_buffer_pages() * pupd_prm.nfract / 100;
+
+ if (obdfs_cache_count > dirty_limit) {
+ interval = 0;
+ if ( wrote < pupd_prm.ndirty )
+ age >>= 1;
+ CDEBUG(D_CACHE, "wrote %d, age %ld, interval %d\n",
+ wrote, age, interval);
+ } else {
+ if ( wrote < pupd_prm.ndirty >> 1 &&
+ obdfs_cache_count < dirty_limit / 2) {
+ interval = pupd_prm.interval;
+ age = pupd_prm.age_buffer;
+ CDEBUG(D_INFO,
+ "wrote %d, age %ld, interval %d\n",
+ wrote, age, interval);
+ } else if (obdfs_cache_count > dirty_limit / 2) {
+ interval >>= 1;
+ if ( wrote < pupd_prm.ndirty )
+ age >>= 1;
+ CDEBUG(D_CACHE,
+ "wrote %d, age %ld, interval %d\n",
+ wrote, age, interval);
+ }
+ }
+
+ wrote = obdfs_flush_dirty_pages(jiffies - age);
+ if (wrote)
+ CDEBUG(D_CACHE,
+ "dirty_limit %ld, cache_count %ld, wrote %d\n",
+ dirty_limit, obdfs_cache_count, wrote);
+ }
}
int obdfs_flushd_init(void)
{
- /*
- kernel_thread(bdflush, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- */
- kernel_thread(pupdate, NULL, 0);
- CDEBUG(D_PSDEV, __FUNCTION__ ": flushd inited\n");
- return 0;
+ /*
+ kernel_thread(bdflush, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ */
+ kernel_thread(pupdate, NULL, 0);
+ CDEBUG(D_PSDEV, __FUNCTION__ ": flushd inited\n");
+ return 0;
}
int obdfs_flushd_cleanup(void)
{
- ENTRY;
-
- if (pupdated) /* for debugging purposes only */
- CDEBUG(D_CACHE, "pupdated->state = %lx\n", pupdated->state);
-
- /* deliver a signal to pupdated to shut it down */
- if (pupdated && (pupdated->state == TASK_RUNNING ||
- pupdated->state == TASK_INTERRUPTIBLE )) {
- unsigned long timeout = HZ/20;
- unsigned long count = 0;
- send_sig_info(SIGTERM, (struct siginfo *)1, pupdated);
- while (pupdated) {
- if ((count % 2*HZ) == timeout)
- printk(KERN_INFO "wait for pupdated to stop\n");
- count += timeout;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(timeout);
- }
- }
-
- EXIT;
- /* not reached */
- return 0;
+ ENTRY;
+
+ if (pupdated) /* for debugging purposes only */
+ CDEBUG(D_CACHE, "pupdated->state = %lx\n", pupdated->state);
+
+ /* deliver a signal to pupdated to shut it down */
+ if (pupdated && (pupdated->state == TASK_RUNNING ||
+ pupdated->state == TASK_INTERRUPTIBLE )) {
+ unsigned long timeout = HZ/20;
+ unsigned long count = 0;
+ send_sig_info(SIGTERM, (struct siginfo *)1, pupdated);
+ while (pupdated) {
+ if ((count % 2*HZ) == timeout)
+ printk(KERN_INFO "wait for pupdated to stop\n");
+ count += timeout;
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(timeout);
+ }
+ }
+
+ EXIT;
+ /* not reached */
+ return 0;
}