return size - left;
}
+static int ceph_dir_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+ struct inode *inode = dentry->d_inode;
+ int ret, err;
+ struct ceph_mds_request *req;
+ u64 nexttid = 0;
+
+ ret = 0;
+ dout(0, "sync on directory\n");
+
+ do {
+ req = ceph_mdsc_get_listener_req(inode, nexttid);
+
+ if (!req)
+ break;
+ nexttid = req->r_tid + 1;
+
+ if (req->r_timeout) {
+ err = wait_for_completion_timeout(&req->r_safe_completion,
+ req->r_timeout);
+ if (err == 0)
+ ret = -EIO; /* timed out */
+ } else {
+ wait_for_completion(&req->r_safe_completion);
+ }
+ ceph_mdsc_put_request(req);
+ } while (req);
+
+ return ret;
+}
+
const struct file_operations ceph_dir_fops = {
.read = ceph_read_dir,
.readdir = ceph_readdir,
.open = ceph_open,
.release = ceph_release,
.unlocked_ioctl = ceph_ioctl,
+ .fsync = ceph_dir_fsync,
};
const struct inode_operations ceph_dir_iops = {
struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
struct ceph_mds_client *mdsc = &client->mdsc;
struct file *file = nd->intent.open.file;
- struct inode *parent_inode = file->f_dentry->d_parent->d_inode;
+ struct inode *parent_inode = get_dentry_parent_inode(file->f_dentry);
struct ceph_mds_request *req;
int err;
int flags = nd->intent.open.flags - 1; /* silly vfs! */
static int ceph_fsync(struct file *file, struct dentry *dentry, int datasync)
{
struct inode *inode = dentry->d_inode;
- int ret, err;
- struct ceph_mds_request *req;
- u64 nexttid = 0;
+ int ret;
dout(10, "fsync on inode %p\n", inode);
ret = write_inode_now(inode, 1);
if (ret < 0)
return ret;
-
- ret = 0;
- if ((inode->i_mode & S_IFMT) == S_IFDIR) {
- dout(0, "sync on directory\n");
-
- do {
- req = ceph_mdsc_get_listener_req(inode, nexttid);
-
- if (!req)
- break;
- nexttid = req->r_tid + 1;
-
- if (req->r_timeout) {
- err = wait_for_completion_timeout(&req->r_safe_completion,
- req->r_timeout);
- if (err == 0)
- ret = -EIO; /* timed out */
- } else {
- wait_for_completion(&req->r_safe_completion);
- }
- ceph_mdsc_put_request(req);
- } while (req);
- }
-
/*
* HMM: should we also ensure that caps are flushed to mds?
* It's not strictly necessary, since with the data on the
spin_lock(&ci->i_listener_lock);
got = radix_tree_gang_lookup(&ci->i_listener_tree,
- (void **)&req, 0, 1);
+ (void **)&req, tid, 1);
- if (got >= 0) {
+ if (got > 0)
get_request(req);
- }
+
spin_unlock(&ci->i_listener_lock);
return req;
dout(10, "handle_reply %p expected_cap=%p\n", req, req->r_expected_cap);
mds = le32_to_cpu(msg->hdr.src.name.num);
if (req->r_got_reply) {
- if (req->r_reply_info.head->safe) {
+ if (head->safe) {
/*
We already handled the unsafe response, now do the cleanup.
Shouldn't we check the safe response to see if it matches
*/
complete(&req->r_safe_completion);
__unregister_request(mdsc, req);
- dout(10, "got another reply %llu, mds%d\n",
+ dout(10, "got safe reply %llu, mds%d\n",
tid, mds);
ceph_msg_put(req->r_request);
req->r_request = NULL;
} else {
+ mutex_unlock(&mdsc->mutex);
dout(0, "got another _unsafe_ reply %llu, mds%d\n",
tid, mds);
}
extern int ceph_proc_init(void);
extern void ceph_proc_cleanup(void);
+static inline struct inode *get_dentry_parent_inode(struct dentry *dentry)
+{
+ if (dentry && dentry->d_parent)
+ return dentry->d_parent->d_inode;
+
+ return NULL;
+}
+
#endif /* _FS_CEPH_SUPER_H */