obdfs/flushd.c: pass "check_time" parameter to flush routines
obdfs/namei.c: fixed rename call to getpage to use offset, not index
snap/*: tested snapshots with new vector I/O, async writes - OK
tests/snaprun.sh: small script to step through testing of some snapshot features
+# A routine to display a command, and prompt user if it should be run
+qrun () {
+ echo
+ echo -n "Run '$*' [Y/n]?'";
+ read JUNK
+
+ case $JUNK in
+ n*|N*) echo "'$*' not run" ;;
+ *) plog $* ;;
+ esac
+}
/* OBDFS inode information */
#define OIDEBUG(inode) { \
ICDEBUG(inode);\
/* OBDFS inode information */
#define OIDEBUG(inode) { \
ICDEBUG(inode);\
- printk("oinfo: flags 0x%08x\n", OBDFS_INFO(inode)->oi_flags);\
+ printk("oinfo: flags 0x%08x\n", obdfs_i2info(inode)->oi_flags);\
/* obdfs_print_plist(inode); */\
}
/* obdfs_print_plist(inode); */\
}
void obdfs_read_inode(struct inode *inode);
/* flush.c */
void obdfs_read_inode(struct inode *inode);
/* flush.c */
-int flushd_init(void);
-
+int obdfs_flushd_init(void);
+int obdfs_flushd_cleanup(void);
+int obdfs_flush_reqs(struct list_head *inode_list, int check_time);
+void obdfs_flush_dirty_pages(int check_time);
/* rw.c */
int obdfs_do_writepage(struct inode *, struct page *, int sync);
/* rw.c */
int obdfs_do_writepage(struct inode *, struct page *, int sync);
void obdfs_cleanup_pgrqcache(void);
int obdfs_readpage(struct dentry *dentry, struct page *page);
int obdfs_writepage(struct dentry *dentry, struct page *page);
void obdfs_cleanup_pgrqcache(void);
int obdfs_readpage(struct dentry *dentry, struct page *page);
int obdfs_writepage(struct dentry *dentry, struct page *page);
-struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create, int locked);
-int obdfs_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf);
+struct page *obdfs_getpage(struct inode *inode, unsigned long offset,
+ int create, int locked);
+int obdfs_write_one_page(struct file *file, struct page *page,
+ unsigned long offset, unsigned long bytes,
+ const char * buf);
void obdfs_dequeue_reqs(struct inode *inode);
/* namei.c */
void obdfs_dequeue_reqs(struct inode *inode);
/* namei.c */
int obdfs_rmdir(struct inode *dir, struct dentry *dentry);
int obdfs_unlink(struct inode *dir, struct dentry *dentry);
int obdfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev);
int obdfs_rmdir(struct inode *dir, struct dentry *dentry);
int obdfs_unlink(struct inode *dir, struct dentry *dentry);
int obdfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev);
-int obdfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
-int obdfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry);
-int obdfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry);
+int obdfs_symlink(struct inode *dir, struct dentry *dentry,
+ const char *symname);
+int obdfs_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry);
+int obdfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry);
+
/* dir.c */
int obdfs_check_dir_entry (const char * function, struct inode * dir,
struct ext2_dir_entry_2 * de, struct page * page,
unsigned long offset);
/* dir.c */
int obdfs_check_dir_entry (const char * function, struct inode * dir,
struct ext2_dir_entry_2 * de, struct page * page,
unsigned long offset);
/* symlink.c */
int obdfs_readlink (struct dentry *, char *, int);
/* symlink.c */
int obdfs_readlink (struct dentry *, char *, int);
-struct dentry *obdfs_follow_link(struct dentry *, struct dentry *, unsigned int);
+struct dentry *obdfs_follow_link(struct dentry *, struct dentry *,
+ unsigned int);
/* list of all OBDFS super blocks */
/* list of all OBDFS super blocks */
char oi_inline[OBD_INLINESZ];
};
char oi_inline[OBD_INLINESZ];
};
-#define OBDFS_INFO(inode) ((struct obdfs_inode_info *)(&(inode)->u.generic_ip))
+static inline struct obdfs_inode_info *obdfs_i2info(struct inode *inode)
+{
+ return (struct obdfs_inode_info *)&(inode->u.generic_ip);
+}
static inline struct obdfs_sb_info *obdfs_i2sbi(struct inode *inode)
{
static inline struct obdfs_sb_info *obdfs_i2sbi(struct inode *inode)
{
- struct obdfs_sb_info *sbi;
-
- sbi = (struct obdfs_sb_info *) &(inode->i_sb->u.generic_sbp);
- return sbi;
+ return (struct obdfs_sb_info *) &(inode->i_sb->u.generic_sbp);
}
static inline struct list_head *obdfs_iplist(struct inode *inode)
{
}
static inline struct list_head *obdfs_iplist(struct inode *inode)
{
- struct obdfs_inode_info *info = (struct obdfs_inode_info *)&inode->u.generic_ip;
+ struct obdfs_inode_info *info = obdfs_i2info(inode);
return &info->oi_pages;
}
static inline struct list_head *obdfs_islist(struct inode *inode)
{
return &info->oi_pages;
}
static inline struct list_head *obdfs_islist(struct inode *inode)
{
- struct obdfs_inode_info *info = (struct obdfs_inode_info *)&inode->u.generic_ip;
+ struct obdfs_inode_info *info = obdfs_i2info(inode);
return &info->oi_inodes;
}
return &info->oi_inodes;
}
static inline struct list_head *obdfs_slist(struct inode *inode)
{
struct obdfs_sb_info *sbi = obdfs_i2sbi(inode);
static inline struct list_head *obdfs_slist(struct inode *inode)
{
struct obdfs_sb_info *sbi = obdfs_i2sbi(inode);
return &sbi->osi_inodes;
}
return &sbi->osi_inodes;
}
static inline int obdfs_has_inline(struct inode *inode)
{
static inline int obdfs_has_inline(struct inode *inode)
{
- return (OBDFS_INFO(inode)->oi_flags & OBD_FL_INLINEDATA);
+ return (obdfs_i2info(inode)->oi_flags & OBD_FL_INLINEDATA);
}
static void inline obdfs_from_inode(struct obdo *oa, struct inode *inode)
{
}
static void inline obdfs_from_inode(struct obdo *oa, struct inode *inode)
{
- struct obdfs_inode_info *oinfo = OBDFS_INFO(inode);
+ struct obdfs_inode_info *oinfo = obdfs_i2info(inode);
CDEBUG(D_INODE, "src inode %ld, dst obdo %ld valid 0x%08x\n",
inode->i_ino, (long)oa->o_id, oa->o_valid);
CDEBUG(D_INODE, "src inode %ld, dst obdo %ld valid 0x%08x\n",
inode->i_ino, (long)oa->o_id, oa->o_valid);
static void inline obdfs_to_inode(struct inode *inode, struct obdo *oa)
{
static void inline obdfs_to_inode(struct inode *inode, struct obdo *oa)
{
- struct obdfs_inode_info *oinfo = OBDFS_INFO(inode);
+ struct obdfs_inode_info *oinfo = obdfs_i2info(inode);
CDEBUG(D_INODE, "src obdo %ld valid 0x%08x, dst inode %ld\n",
(long)oa->o_id, oa->o_valid, inode->i_ino);
CDEBUG(D_INODE, "src obdo %ld valid 0x%08x, dst inode %ld\n",
(long)oa->o_id, oa->o_valid, inode->i_ino);
struct {
int nfract; /* Percentage of buffer cache dirty to
activate bdflush */
struct {
int nfract; /* Percentage of buffer cache dirty to
activate bdflush */
/* } pupd_prm = {40, 500, 64, 256, 5*HZ, 30*HZ, 5*HZ }; */
} pupd_prm = {40, 500, 64, 256, 10*HZ, 30*HZ, 5*HZ };
/* } pupd_prm = {40, 500, 64, 256, 5*HZ, 30*HZ, 5*HZ }; */
} pupd_prm = {40, 500, 64, 256, 10*HZ, 30*HZ, 5*HZ };
/* Called with the superblock list lock */
static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo,
int nr_slots, struct page **pages, char **bufs,
/* Called with the superblock list lock */
static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo,
int nr_slots, struct page **pages, char **bufs,
+} /* obdfs_enqueue_pages */
/* dequeue requests for a dying inode */
void obdfs_dequeue_reqs(struct inode *inode)
/* dequeue requests for a dying inode */
void obdfs_dequeue_reqs(struct inode *inode)
}
iput(inode);
obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
}
iput(inode);
obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
+} /* obdfs_dequeue_reqs */
/* Remove writeback requests for the superblock */
int obdfs_flush_reqs(struct list_head *inode_list, int check_time)
/* Remove writeback requests for the superblock */
int obdfs_flush_reqs(struct list_head *inode_list, int check_time)
&pages[num_io], &bufs[num_io],
&counts[num_io],
&offsets[num_io],
&pages[num_io], &bufs[num_io],
&counts[num_io],
&offsets[num_io],
+ &flags[num_obdos],
+ check_time);
CDEBUG(D_INODE, "FLUSHED inode %ld, pages flushed: %d\n",
inode->i_ino, res);
if ( res < 0 ) {
CDEBUG(D_INODE, "FLUSHED inode %ld, pages flushed: %d\n",
inode->i_ino, res);
if ( res < 0 ) {
sl = &obdfs_super_list;
while ( (sl = sl->next) != &obdfs_super_list ) {
struct obdfs_sb_info *sbi =
list_entry(sl, struct obdfs_sb_info, osi_list);
/* walk write requests here, use the sb, check the time */
sl = &obdfs_super_list;
while ( (sl = sl->next) != &obdfs_super_list ) {
struct obdfs_sb_info *sbi =
list_entry(sl, struct obdfs_sb_info, osi_list);
/* walk write requests here, use the sb, check the time */
- obdfs_flush_reqs(&sbi->osi_inodes, 0);
+ obdfs_flush_reqs(&sbi->osi_inodes, check_time);
}
static struct task_struct *pupdated;
}
static struct task_struct *pupdated;
static int pupdate(void *unused)
{
struct task_struct * tsk = current;
static int pupdate(void *unused)
{
struct task_struct * tsk = current;
sprintf(tsk->comm, "pupdated");
pupdated = current;
sprintf(tsk->comm, "pupdated");
pupdated = current;
+ MOD_INC_USE_COUNT; /* XXX until send_sig works */
printk("pupdated activated...\n");
/* sigstop and sigcont will stop and wakeup pupdate */
printk("pupdated activated...\n");
/* sigstop and sigcont will stop and wakeup pupdate */
- obdfs_flush_dirty_pages(0);
tsk->state = TASK_STOPPED;
tsk->state = TASK_STOPPED;
- /* MOD_DEC_USE_COUNT; */
+ MOD_DEC_USE_COUNT; /* XXX until send_sig works */
printk("pupdated stopped...\n");
return 0;
}
printk("pupdated stopped...\n");
return 0;
}
if (stopped)
goto stop_pupdate;
}
if (stopped)
goto stop_pupdate;
}
- /* asynchronous setattr etc for the future ... */
- /* flush_inodes(); */
+ /* asynchronous setattr etc for the future ...
+ flush_inodes();
+ */
+ /* we don't currently check the time on the pages
obdfs_flush_dirty_pages(1);
obdfs_flush_dirty_pages(1);
+ */
+ obdfs_flush_dirty_pages(0);
+int obdfs_flushd_init(void)
{
/*
kernel_thread(bdflush, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
*/
{
/*
kernel_thread(bdflush, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
*/
- /* MOD_INC_USE_COUNT; */
kernel_thread(pupdate, NULL, 0);
printk("flushd inited\n");
return 0;
}
kernel_thread(pupdate, NULL, 0);
printk("flushd inited\n");
return 0;
}
-int flushd_cleanup(void)
+int obdfs_flushd_cleanup(void)
- /* this should deliver a signal to */
-
-
- /* XXX Andreas, we will do this later, for now, you must kill
- pupdated with a SIGTERM from userland, before unloading obdfs.o
- */
+ ENTRY;
+ /* deliver a signal to pupdated to shut it down
+ XXX need to kill it from user space for now XXX
- /* then let it run at least once, before continuing */
-
- /* XXX need to do something like this here:
- send_sig(SIGTERM, current, 0);
- */
- 1;
- /*obdfs_flush_dirty_pages(0); */
+ send_sig_info(SIGTERM, 1, pupdated);
/* not reached */
return 0;
/* not reached */
return 0;
for (l = 0; l < inode->i_sb->s_blocksize - 1 && symname [l]; l++)
;
for (l = 0; l < inode->i_sb->s_blocksize - 1 && symname [l]; l++)
;
- oinfo = OBDFS_INFO(inode);
+ oinfo = obdfs_i2info(inode);
if (l >= sizeof(oinfo->oi_inline)) {
CDEBUG(D_INODE, "l=%d, normal symlink\n", l);
if (l >= sizeof(oinfo->oi_inline)) {
CDEBUG(D_INODE, "l=%d, normal symlink\n", l);
old_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
mark_inode_dirty(old_dir);
if (dir_page) {
old_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
mark_inode_dirty(old_dir);
if (dir_page) {
- PARENT_INO(page_address(dir_page)) = le32_to_cpu(new_dir->i_ino);
+ PARENT_INO(page_address(dir_page)) =le32_to_cpu(new_dir->i_ino);
+ err = obdfs_do_writepage(old_inode, dir_page,
+ IS_SYNC(old_inode));
- err = obdfs_do_writepage(old_inode, dir_page, IS_SYNC(old_inode));
old_dir->i_nlink--;
mark_inode_dirty(old_dir);
if (new_inode) {
old_dir->i_nlink--;
mark_inode_dirty(old_dir);
if (new_inode) {
/* lock the old_page and release unlocked copy */
CDEBUG(D_INODE, "old_page at %p\n", old_page);
page_cache_release(old_page);
/* lock the old_page and release unlocked copy */
CDEBUG(D_INODE, "old_page at %p\n", old_page);
page_cache_release(old_page);
- old_page = obdfs_getpage(old_dir, index >> PAGE_SHIFT, 0, LOCKED);
+ old_page = obdfs_getpage(old_dir, index << PAGE_SHIFT, 0,
+ LOCKED);
CDEBUG(D_INODE, "old_page at %p\n", old_page);
CDEBUG(D_INODE, "old_page at %p\n", old_page);
err = obdfs_do_writepage(old_dir, old_page, IS_SYNC(old_dir));
err = obdfs_do_writepage(old_dir, old_page, IS_SYNC(old_dir));
}
err = obdfs_do_writepage(new_dir, new_page, IS_SYNC(new_dir));
}
err = obdfs_do_writepage(new_dir, new_page, IS_SYNC(new_dir));
if (dir_page)
page_cache_release(dir_page);
if (dir_page)
page_cache_release(dir_page);
return err;
} /* obdfs_rename */
return err;
} /* obdfs_rename */
-int obdfs_flush_reqs(struct list_head *page_list,
- int flush_inode, int check_time);
-
-void obdfs_flush_dirty_pages(int check_time);
-
/* SYNCHRONOUS I/O for an inode */
static int obdfs_brw(int rw, struct inode *inode, struct page *page, int create)
{
/* SYNCHRONOUS I/O for an inode */
static int obdfs_brw(int rw, struct inode *inode, struct page *page, int create)
{
- obd_count num_oa = 1;
- obd_count oa_bufs = 1;
+ obd_count num_obdo = 1;
+ obd_count bufs_per_obdo = 1;
struct obdo *oa;
char *buf = (char *)page_address(page);
obd_size count = PAGE_SIZE;
struct obdo *oa;
char *buf = (char *)page_address(page);
obd_size count = PAGE_SIZE;
}
obdfs_from_inode(oa, inode);
}
obdfs_from_inode(oa, inode);
- err = IOPS(inode, brw)(rw, IID(inode), num_oa, &oa, &oa_bufs, &buf,
- &count, &offset, &flags);
+ err = IOPS(inode, brw)(rw, IID(inode), num_obdo, &oa, &bufs_per_obdo,
+ &buf, &count, &offset, &flags);
if ( !err )
obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */
if ( !err )
obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */
} /* obdfs_readpage */
static kmem_cache_t *obdfs_pgrq_cachep = NULL;
} /* obdfs_readpage */
static kmem_cache_t *obdfs_pgrq_cachep = NULL;
+
+/* XXX should probably have one of these per superblock */
static int obdfs_cache_count = 0;
int obdfs_init_pgrqcache(void)
static int obdfs_cache_count = 0;
int obdfs_init_pgrqcache(void)
inline void obdfs_pgrq_del(struct obdfs_pgrq *pgrq)
{
obdfs_cache_count--;
inline void obdfs_pgrq_del(struct obdfs_pgrq *pgrq)
{
obdfs_cache_count--;
- CDEBUG(D_INODE, "deleting page %p from list [count %d]\n", pgrq->rq_page, obdfs_cache_count);
+ CDEBUG(D_INODE, "deleting page %p from list [count %d]\n",
+ pgrq->rq_page, obdfs_cache_count);
list_del(&pgrq->rq_plist);
kmem_cache_free(obdfs_pgrq_cachep, pgrq);
}
list_del(&pgrq->rq_plist);
kmem_cache_free(obdfs_pgrq_cachep, pgrq);
}
/* called with the list lock held */
/* called with the list lock held */
-static struct page* obdfs_find_page_index(struct inode *inode, unsigned long index)
+static struct page* obdfs_find_page_index(struct inode *inode,
+ unsigned long index)
{
struct list_head *page_list = obdfs_iplist(inode);
struct list_head *tmp;
{
struct list_head *page_list = obdfs_iplist(inode);
struct list_head *tmp;
pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist);
page = pgrq->rq_page;
if (index == page->index) {
pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist);
page = pgrq->rq_page;
if (index == page->index) {
- CDEBUG(D_INODE, "INDEX SEARCH found page %p in list, index %ld\n", page, index);
+ CDEBUG(D_INODE,
+ "INDEX SEARCH found page %p, index %ld\n",
+ page, index);
/* release the pages from the page cache */
while ( num_io > 0 ) {
num_io--;
/* release the pages from the page cache */
while ( num_io > 0 ) {
num_io--;
- CDEBUG(D_INODE, "calling put_page for %p, index %ld\n", pages[num_io], pages[num_io]->index);
+ CDEBUG(D_INODE, "calling put_page for %p, index %ld\n",
+ pages[num_io], pages[num_io]->index);
put_page(pages[num_io]);
}
put_page(pages[num_io]);
}
pgrq->rq_page = page;
get_page(pgrq->rq_page);
list_add(&pgrq->rq_plist, obdfs_iplist(inode));
pgrq->rq_page = page;
get_page(pgrq->rq_page);
list_add(&pgrq->rq_plist, obdfs_iplist(inode));
}
/* If inode isn't already on the superblock inodes list, add it,
}
/* If inode isn't already on the superblock inodes list, add it,
} /* obdfs_add_page_to_cache */
} /* obdfs_add_page_to_cache */
*
* modeled on NFS code.
*/
*
* modeled on NFS code.
*/
-struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create, int locked)
+struct page *obdfs_getpage(struct inode *inode, unsigned long offset,
+ int create, int locked)
{
struct page *page_cache;
int index;
{
struct page *page_cache;
int index;
offset = offset & PAGE_CACHE_MASK;
CDEBUG(D_INODE, "ino: %ld, offset %ld, create %d, locked %d\n",
inode->i_ino, offset, create, locked);
offset = offset & PAGE_CACHE_MASK;
CDEBUG(D_INODE, "ino: %ld, offset %ld, create %d, locked %d\n",
inode->i_ino, offset, create, locked);
- index = offset >> PAGE_CACHE_SHIFT;
+ index = offset >> PAGE_CACHE_SHIFT;
if ( obdfs_find_page_index(inode, index) ) {
if ( obdfs_find_page_index(inode, index) ) {
- printk("OVERWRITE: found dirty page %p, index %ld\n", page, page->index);
+ CDEBUG(D_INODE, "OVERWRITE: found dirty page %p, index %ld\n",
+ page, page->index);
}
err = obdfs_brw(READ, inode, page, create);
}
err = obdfs_brw(READ, inode, page, create);
+ /* list of dirty inodes, and a mutex to hold while modifying it */
INIT_LIST_HEAD(&sbi->osi_inodes);
sema_init(&sbi->osi_list_mutex, 1);
INIT_LIST_HEAD(&sbi->osi_inodes);
sema_init(&sbi->osi_list_mutex, 1);
-/* XXX remove the super to the obdfs_super_list */
static void obdfs_put_super(struct super_block *sb)
{
struct obdfs_sb_info *sbi;
ENTRY;
static void obdfs_put_super(struct super_block *sb)
{
struct obdfs_sb_info *sbi;
ENTRY;
sbi = (struct obdfs_sb_info *) &sb->u.generic_sbp;
sbi = (struct obdfs_sb_info *) &sb->u.generic_sbp;
+ obdfs_flush_reqs(&sbi->osi_inodes, 0);
OPS(sb,disconnect)(ID(sb));
list_del(&sbi->osi_list);
OPS(sb,disconnect)(ID(sb));
list_del(&sbi->osi_list);
- memset(sbi, 0, sizeof(* sbi));
+ memset(sbi, 0, sizeof(*sbi));
printk("OBDFS: Bye bye.\n");
printk("OBDFS: Bye bye.\n");
} else {
init_special_inode(inode, inode->i_mode,
/* XXX need to fill in the ext2 side */
} else {
init_special_inode(inode, inode->i_mode,
/* XXX need to fill in the ext2 side */
- ((long *)OBDFS_INFO(inode)->oi_inline)[0]);
+ ((long *)obdfs_i2info(inode)->oi_inline)[0]);
return register_filesystem(&obdfs_fs_type);
}
return register_filesystem(&obdfs_fs_type);
}
+ obdfs_flushd_cleanup();
obdfs_sysctl_clean();
obdfs_cleanup_pgrqcache();
unregister_filesystem(&obdfs_fs_type);
obdfs_sysctl_clean();
obdfs_cleanup_pgrqcache();
unregister_filesystem(&obdfs_fs_type);
- link = OBDFS_INFO(inode)->oi_inline;
+ link = obdfs_i2info(inode)->oi_inline;
if (!obdfs_has_inline(inode)) {
OIDEBUG(inode);
page = obdfs_getpage(inode, 0, 0, 0);
if (!obdfs_has_inline(inode)) {
OIDEBUG(inode);
page = obdfs_getpage(inode, 0, 0, 0);
if (buflen > inode->i_sb->s_blocksize - 1)
buflen = inode->i_sb->s_blocksize - 1;
if (buflen > inode->i_sb->s_blocksize - 1)
buflen = inode->i_sb->s_blocksize - 1;
- link = OBDFS_INFO(inode)->oi_inline;
+ link = obdfs_i2info(inode)->oi_inline;
if (!obdfs_has_inline(inode)) {
OIDEBUG(inode);
page = obdfs_getpage(inode, 0, 0, 0);
if (!obdfs_has_inline(inode)) {
OIDEBUG(inode);
page = obdfs_getpage(inode, 0, 0, 0);