{
struct ceph_client *cl;
struct ceph_entity_addr *myaddr = 0;
- int err;
+ int err = -ENOMEM;
cl = kzalloc(sizeof(*cl), GFP_KERNEL);
if (cl == NULL)
spin_lock_init(&cl->sb_lock);
get_client_counter();
+ cl->wb_wq = create_workqueue("ceph-writeback");
+ if (cl->wb_wq == 0)
+ goto fail;
+
/* messenger */
if (args->flags & CEPH_MOUNT_MYIP)
myaddr = &args->my_addr;
ceph_messenger_destroy(cl->msgr);
put_client_counter();
+ destroy_workqueue(cl->wb_wq);
kfree(cl);
dout(10, "destroy_client %p done\n", cl);
}
wake_up(&ci->i_cap_wq);
if (writeback_now) {
/*
- * _queue_ inode for writeback, but don't actually
- * call writepages from this context!!
+ * queue inode for writeback; we can't actually call
+ * write_inode_now, writepages, etc. from this
+ * context.
*/
dout(10, "queueing %p for writeback\n", inode);
- spin_lock(&inode_lock);
- list_move(&inode->i_list, &inode->i_sb->s_more_io);
- spin_unlock(&inode_lock);
- wakeup_pdflush(0); /* this is overkill? */
+ ceph_queue_writeback(ceph_client(inode->i_sb), ci);
}
if (invalidate)
invalidate_mapping_pages(&inode->i_data, 0, -1);
return reply;
}
+void ceph_inode_writeback(struct work_struct *work)
+{
+ struct ceph_inode_info *ci = container_of(work, struct ceph_inode_info,
+ i_wb_work);
+ dout(10, "writeback %p\n", &ci->vfs_inode);
+ write_inode_now(&ci->vfs_inode, 0);
+}
+
+
void apply_truncate(struct inode *inode, loff_t size)
{
struct ceph_inode_info *ci = ceph_inode(inode);
ci->i_hashval = 0;
+ INIT_WORK(&ci->i_wb_work, ceph_inode_writeback);
+
return &ci->vfs_inode;
}
struct ceph_mds_client mdsc;
struct ceph_osd_client osdc;
+ /* writeback */
+ struct workqueue_struct *wb_wq;
+
/* lets ignore all this until later */
spinlock_t sb_lock;
int num_sb; /* ref count (for each sb_info that points to me) */
struct list_head sb_list;
};
-
/*
* CEPH per-mount superblock info
*/
unsigned long i_hashval;
+ struct work_struct i_wb_work; /* writeback work */
+
struct inode vfs_inode; /* at end */
};
extern void ceph_revoke_inode_lease(struct ceph_inode_info *ci, int mask);
extern void ceph_revoke_dentry_lease(struct dentry *dentry);
+static inline void ceph_queue_writeback(struct ceph_client *cl,
+ struct ceph_inode_info *ci)
+{
+ queue_work(cl->wb_wq, &ci->i_wb_work);
+}
+
+
/*
* ino_t is <64 bits on many architectures... blech
*/
extern void ceph_get_mode(struct ceph_inode_info *ci, int mode);
extern void ceph_put_mode(struct ceph_inode_info *ci, int mode);
extern void ceph_inode_set_size(struct inode *inode, loff_t size);
+extern void ceph_inode_writeback(struct work_struct *work);
extern int ceph_setattr(struct dentry *dentry, struct iattr *attr);
extern int ceph_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,