diff options
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/caps.c | 6 | ||||
-rw-r--r-- | fs/ceph/dir.c | 21 | ||||
-rw-r--r-- | fs/ceph/file.c | 22 | ||||
-rw-r--r-- | fs/ceph/inode.c | 6 | ||||
-rw-r--r-- | fs/ceph/super.h | 5 |
5 files changed, 46 insertions, 14 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index f605753c8fe9..8d74ad7ba556 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -1811,7 +1811,7 @@ out: | |||
1811 | spin_unlock(&ci->i_unsafe_lock); | 1811 | spin_unlock(&ci->i_unsafe_lock); |
1812 | } | 1812 | } |
1813 | 1813 | ||
1814 | int ceph_fsync(struct file *file, int datasync) | 1814 | int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync) |
1815 | { | 1815 | { |
1816 | struct inode *inode = file->f_mapping->host; | 1816 | struct inode *inode = file->f_mapping->host; |
1817 | struct ceph_inode_info *ci = ceph_inode(inode); | 1817 | struct ceph_inode_info *ci = ceph_inode(inode); |
@@ -1822,9 +1822,10 @@ int ceph_fsync(struct file *file, int datasync) | |||
1822 | dout("fsync %p%s\n", inode, datasync ? " datasync" : ""); | 1822 | dout("fsync %p%s\n", inode, datasync ? " datasync" : ""); |
1823 | sync_write_wait(inode); | 1823 | sync_write_wait(inode); |
1824 | 1824 | ||
1825 | ret = filemap_write_and_wait(inode->i_mapping); | 1825 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); |
1826 | if (ret < 0) | 1826 | if (ret < 0) |
1827 | return ret; | 1827 | return ret; |
1828 | mutex_lock(&inode->i_mutex); | ||
1828 | 1829 | ||
1829 | dirty = try_flush_caps(inode, NULL, &flush_tid); | 1830 | dirty = try_flush_caps(inode, NULL, &flush_tid); |
1830 | dout("fsync dirty caps are %s\n", ceph_cap_string(dirty)); | 1831 | dout("fsync dirty caps are %s\n", ceph_cap_string(dirty)); |
@@ -1841,6 +1842,7 @@ int ceph_fsync(struct file *file, int datasync) | |||
1841 | } | 1842 | } |
1842 | 1843 | ||
1843 | dout("fsync %p%s done\n", inode, datasync ? " datasync" : ""); | 1844 | dout("fsync %p%s done\n", inode, datasync ? " datasync" : ""); |
1845 | mutex_unlock(&inode->i_mutex); | ||
1844 | return ret; | 1846 | return ret; |
1845 | } | 1847 | } |
1846 | 1848 | ||
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 852ff8600ac9..382abc9a6a54 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -270,7 +270,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
270 | off = 1; | 270 | off = 1; |
271 | } | 271 | } |
272 | if (filp->f_pos == 1) { | 272 | if (filp->f_pos == 1) { |
273 | ino_t ino = filp->f_dentry->d_parent->d_inode->i_ino; | 273 | ino_t ino = parent_ino(filp->f_dentry); |
274 | dout("readdir off 1 -> '..'\n"); | 274 | dout("readdir off 1 -> '..'\n"); |
275 | if (filldir(dirent, "..", 2, ceph_make_fpos(0, 1), | 275 | if (filldir(dirent, "..", 2, ceph_make_fpos(0, 1), |
276 | ceph_translate_ino(inode->i_sb, ino), | 276 | ceph_translate_ino(inode->i_sb, ino), |
@@ -464,14 +464,19 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin) | |||
464 | loff_t retval; | 464 | loff_t retval; |
465 | 465 | ||
466 | mutex_lock(&inode->i_mutex); | 466 | mutex_lock(&inode->i_mutex); |
467 | retval = -EINVAL; | ||
467 | switch (origin) { | 468 | switch (origin) { |
468 | case SEEK_END: | 469 | case SEEK_END: |
469 | offset += inode->i_size + 2; /* FIXME */ | 470 | offset += inode->i_size + 2; /* FIXME */ |
470 | break; | 471 | break; |
471 | case SEEK_CUR: | 472 | case SEEK_CUR: |
472 | offset += file->f_pos; | 473 | offset += file->f_pos; |
474 | case SEEK_SET: | ||
475 | break; | ||
476 | default: | ||
477 | goto out; | ||
473 | } | 478 | } |
474 | retval = -EINVAL; | 479 | |
475 | if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) { | 480 | if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) { |
476 | if (offset != file->f_pos) { | 481 | if (offset != file->f_pos) { |
477 | file->f_pos = offset; | 482 | file->f_pos = offset; |
@@ -495,6 +500,7 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin) | |||
495 | if (offset > old_offset) | 500 | if (offset > old_offset) |
496 | fi->dir_release_count--; | 501 | fi->dir_release_count--; |
497 | } | 502 | } |
503 | out: | ||
498 | mutex_unlock(&inode->i_mutex); | 504 | mutex_unlock(&inode->i_mutex); |
499 | return retval; | 505 | return retval; |
500 | } | 506 | } |
@@ -592,7 +598,6 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | |||
592 | /* open (but not create!) intent? */ | 598 | /* open (but not create!) intent? */ |
593 | if (nd && | 599 | if (nd && |
594 | (nd->flags & LOOKUP_OPEN) && | 600 | (nd->flags & LOOKUP_OPEN) && |
595 | (nd->flags & LOOKUP_CONTINUE) == 0 && /* only open last component */ | ||
596 | !(nd->intent.open.flags & O_CREAT)) { | 601 | !(nd->intent.open.flags & O_CREAT)) { |
597 | int mode = nd->intent.open.create_mode & ~current->fs->umask; | 602 | int mode = nd->intent.open.create_mode & ~current->fs->umask; |
598 | return ceph_lookup_open(dir, dentry, nd, mode, 1); | 603 | return ceph_lookup_open(dir, dentry, nd, mode, 1); |
@@ -1144,7 +1149,8 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size, | |||
1144 | * an fsync() on a dir will wait for any uncommitted directory | 1149 | * an fsync() on a dir will wait for any uncommitted directory |
1145 | * operations to commit. | 1150 | * operations to commit. |
1146 | */ | 1151 | */ |
1147 | static int ceph_dir_fsync(struct file *file, int datasync) | 1152 | static int ceph_dir_fsync(struct file *file, loff_t start, loff_t end, |
1153 | int datasync) | ||
1148 | { | 1154 | { |
1149 | struct inode *inode = file->f_path.dentry->d_inode; | 1155 | struct inode *inode = file->f_path.dentry->d_inode; |
1150 | struct ceph_inode_info *ci = ceph_inode(inode); | 1156 | struct ceph_inode_info *ci = ceph_inode(inode); |
@@ -1154,6 +1160,11 @@ static int ceph_dir_fsync(struct file *file, int datasync) | |||
1154 | int ret = 0; | 1160 | int ret = 0; |
1155 | 1161 | ||
1156 | dout("dir_fsync %p\n", inode); | 1162 | dout("dir_fsync %p\n", inode); |
1163 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
1164 | if (ret) | ||
1165 | return ret; | ||
1166 | mutex_lock(&inode->i_mutex); | ||
1167 | |||
1157 | spin_lock(&ci->i_unsafe_lock); | 1168 | spin_lock(&ci->i_unsafe_lock); |
1158 | if (list_empty(head)) | 1169 | if (list_empty(head)) |
1159 | goto out; | 1170 | goto out; |
@@ -1187,6 +1198,8 @@ static int ceph_dir_fsync(struct file *file, int datasync) | |||
1187 | } while (req->r_tid < last_tid); | 1198 | } while (req->r_tid < last_tid); |
1188 | out: | 1199 | out: |
1189 | spin_unlock(&ci->i_unsafe_lock); | 1200 | spin_unlock(&ci->i_unsafe_lock); |
1201 | mutex_unlock(&inode->i_mutex); | ||
1202 | |||
1190 | return ret; | 1203 | return ret; |
1191 | } | 1204 | } |
1192 | 1205 | ||
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 45fbd69daabe..ce549d31eeb7 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -229,7 +229,7 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry, | |||
229 | struct ceph_mds_request *req; | 229 | struct ceph_mds_request *req; |
230 | struct dentry *ret; | 230 | struct dentry *ret; |
231 | int err; | 231 | int err; |
232 | int flags = nd->intent.open.flags - 1; /* silly vfs! */ | 232 | int flags = nd->intent.open.flags; |
233 | 233 | ||
234 | dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n", | 234 | dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n", |
235 | dentry, dentry->d_name.len, dentry->d_name.name, flags, mode); | 235 | dentry, dentry->d_name.len, dentry->d_name.name, flags, mode); |
@@ -797,13 +797,16 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin) | |||
797 | 797 | ||
798 | mutex_lock(&inode->i_mutex); | 798 | mutex_lock(&inode->i_mutex); |
799 | __ceph_do_pending_vmtruncate(inode); | 799 | __ceph_do_pending_vmtruncate(inode); |
800 | switch (origin) { | 800 | if (origin != SEEK_CUR || origin != SEEK_SET) { |
801 | case SEEK_END: | ||
802 | ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE); | 801 | ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE); |
803 | if (ret < 0) { | 802 | if (ret < 0) { |
804 | offset = ret; | 803 | offset = ret; |
805 | goto out; | 804 | goto out; |
806 | } | 805 | } |
806 | } | ||
807 | |||
808 | switch (origin) { | ||
809 | case SEEK_END: | ||
807 | offset += inode->i_size; | 810 | offset += inode->i_size; |
808 | break; | 811 | break; |
809 | case SEEK_CUR: | 812 | case SEEK_CUR: |
@@ -819,6 +822,19 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin) | |||
819 | } | 822 | } |
820 | offset += file->f_pos; | 823 | offset += file->f_pos; |
821 | break; | 824 | break; |
825 | case SEEK_DATA: | ||
826 | if (offset >= inode->i_size) { | ||
827 | ret = -ENXIO; | ||
828 | goto out; | ||
829 | } | ||
830 | break; | ||
831 | case SEEK_HOLE: | ||
832 | if (offset >= inode->i_size) { | ||
833 | ret = -ENXIO; | ||
834 | goto out; | ||
835 | } | ||
836 | offset = inode->i_size; | ||
837 | break; | ||
822 | } | 838 | } |
823 | 839 | ||
824 | if (offset < 0 || offset > inode->i_sb->s_maxbytes) { | 840 | if (offset < 0 || offset > inode->i_sb->s_maxbytes) { |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 5f0013aafa4b..095799ba9dd1 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -1801,17 +1801,17 @@ int ceph_do_getattr(struct inode *inode, int mask) | |||
1801 | * Check inode permissions. We verify we have a valid value for | 1801 | * Check inode permissions. We verify we have a valid value for |
1802 | * the AUTH cap, then call the generic handler. | 1802 | * the AUTH cap, then call the generic handler. |
1803 | */ | 1803 | */ |
1804 | int ceph_permission(struct inode *inode, int mask, unsigned int flags) | 1804 | int ceph_permission(struct inode *inode, int mask) |
1805 | { | 1805 | { |
1806 | int err; | 1806 | int err; |
1807 | 1807 | ||
1808 | if (flags & IPERM_FLAG_RCU) | 1808 | if (mask & MAY_NOT_BLOCK) |
1809 | return -ECHILD; | 1809 | return -ECHILD; |
1810 | 1810 | ||
1811 | err = ceph_do_getattr(inode, CEPH_CAP_AUTH_SHARED); | 1811 | err = ceph_do_getattr(inode, CEPH_CAP_AUTH_SHARED); |
1812 | 1812 | ||
1813 | if (!err) | 1813 | if (!err) |
1814 | err = generic_permission(inode, mask, flags, NULL); | 1814 | err = generic_permission(inode, mask); |
1815 | return err; | 1815 | return err; |
1816 | } | 1816 | } |
1817 | 1817 | ||
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 35dc9656e499..a23eed526f05 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -695,7 +695,7 @@ extern void ceph_queue_invalidate(struct inode *inode); | |||
695 | extern void ceph_queue_writeback(struct inode *inode); | 695 | extern void ceph_queue_writeback(struct inode *inode); |
696 | 696 | ||
697 | extern int ceph_do_getattr(struct inode *inode, int mask); | 697 | extern int ceph_do_getattr(struct inode *inode, int mask); |
698 | extern int ceph_permission(struct inode *inode, int mask, unsigned int flags); | 698 | extern int ceph_permission(struct inode *inode, int mask); |
699 | extern int ceph_setattr(struct dentry *dentry, struct iattr *attr); | 699 | extern int ceph_setattr(struct dentry *dentry, struct iattr *attr); |
700 | extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, | 700 | extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, |
701 | struct kstat *stat); | 701 | struct kstat *stat); |
@@ -731,7 +731,8 @@ extern void ceph_put_cap(struct ceph_mds_client *mdsc, | |||
731 | 731 | ||
732 | extern void ceph_queue_caps_release(struct inode *inode); | 732 | extern void ceph_queue_caps_release(struct inode *inode); |
733 | extern int ceph_write_inode(struct inode *inode, struct writeback_control *wbc); | 733 | extern int ceph_write_inode(struct inode *inode, struct writeback_control *wbc); |
734 | extern int ceph_fsync(struct file *file, int datasync); | 734 | extern int ceph_fsync(struct file *file, loff_t start, loff_t end, |
735 | int datasync); | ||
735 | extern void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc, | 736 | extern void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc, |
736 | struct ceph_mds_session *session); | 737 | struct ceph_mds_session *session); |
737 | extern struct ceph_cap *ceph_get_cap_for_mds(struct ceph_inode_info *ci, | 738 | extern struct ceph_cap *ceph_get_cap_for_mds(struct ceph_inode_info *ci, |