aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/caps.c6
-rw-r--r--fs/ceph/dir.c21
-rw-r--r--fs/ceph/file.c22
-rw-r--r--fs/ceph/inode.c6
-rw-r--r--fs/ceph/super.h5
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
1814int ceph_fsync(struct file *file, int datasync) 1814int 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 }
503out:
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 */
1147static int ceph_dir_fsync(struct file *file, int datasync) 1152static 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);
1188out: 1199out:
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 */
1804int ceph_permission(struct inode *inode, int mask, unsigned int flags) 1804int 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);
695extern void ceph_queue_writeback(struct inode *inode); 695extern void ceph_queue_writeback(struct inode *inode);
696 696
697extern int ceph_do_getattr(struct inode *inode, int mask); 697extern int ceph_do_getattr(struct inode *inode, int mask);
698extern int ceph_permission(struct inode *inode, int mask, unsigned int flags); 698extern int ceph_permission(struct inode *inode, int mask);
699extern int ceph_setattr(struct dentry *dentry, struct iattr *attr); 699extern int ceph_setattr(struct dentry *dentry, struct iattr *attr);
700extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, 700extern 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
732extern void ceph_queue_caps_release(struct inode *inode); 732extern void ceph_queue_caps_release(struct inode *inode);
733extern int ceph_write_inode(struct inode *inode, struct writeback_control *wbc); 733extern int ceph_write_inode(struct inode *inode, struct writeback_control *wbc);
734extern int ceph_fsync(struct file *file, int datasync); 734extern int ceph_fsync(struct file *file, loff_t start, loff_t end,
735 int datasync);
735extern void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc, 736extern void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc,
736 struct ceph_mds_session *session); 737 struct ceph_mds_session *session);
737extern struct ceph_cap *ceph_get_cap_for_mds(struct ceph_inode_info *ci, 738extern struct ceph_cap *ceph_get_cap_for_mds(struct ceph_inode_info *ci,