ceph: don't allow access to MDS-private inodes
[linux-2.6-microblaze.git] / fs / ceph / inode.c
index 156f849..8c6811e 100644 (file)
@@ -56,6 +56,9 @@ struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino)
 {
        struct inode *inode;
 
+       if (ceph_vino_is_reserved(vino))
+               return ERR_PTR(-EREMOTEIO);
+
        inode = iget5_locked(sb, (unsigned long)vino.ino, ceph_ino_compare,
                             ceph_set_ino_cb, &vino);
        if (!inode)
@@ -87,14 +90,15 @@ struct inode *ceph_get_snapdir(struct inode *parent)
        inode->i_mtime = parent->i_mtime;
        inode->i_ctime = parent->i_ctime;
        inode->i_atime = parent->i_atime;
-       inode->i_op = &ceph_snapdir_iops;
-       inode->i_fop = &ceph_snapdir_fops;
-       ci->i_snap_caps = CEPH_CAP_PIN; /* so we can open */
        ci->i_rbytes = 0;
        ci->i_btime = ceph_inode(parent)->i_btime;
 
-       if (inode->i_state & I_NEW)
+       if (inode->i_state & I_NEW) {
+               inode->i_op = &ceph_snapdir_iops;
+               inode->i_fop = &ceph_snapdir_fops;
+               ci->i_snap_caps = CEPH_CAP_PIN; /* so we can open */
                unlock_new_inode(inode);
+       }
 
        return inode;
 }
@@ -616,10 +620,11 @@ int ceph_fill_file_size(struct inode *inode, int issued,
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
        int queue_trunc = 0;
+       loff_t isize = i_size_read(inode);
 
        if (ceph_seq_cmp(truncate_seq, ci->i_truncate_seq) > 0 ||
-           (truncate_seq == ci->i_truncate_seq && size > inode->i_size)) {
-               dout("size %lld -> %llu\n", inode->i_size, size);
+           (truncate_seq == ci->i_truncate_seq && size > isize)) {
+               dout("size %lld -> %llu\n", isize, size);
                if (size > 0 && S_ISDIR(inode->i_mode)) {
                        pr_err("fill_file_size non-zero size for directory\n");
                        size = 0;
@@ -894,6 +899,7 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
                        ci->i_rfiles = le64_to_cpu(info->rfiles);
                        ci->i_rsubdirs = le64_to_cpu(info->rsubdirs);
                        ci->i_dir_pin = iinfo->dir_pin;
+                       ci->i_rsnaps = iinfo->rsnaps;
                        ceph_decode_timespec64(&ci->i_rctime, &info->rctime);
                }
        }
@@ -1787,7 +1793,7 @@ bool ceph_inode_set_size(struct inode *inode, loff_t size)
        bool ret;
 
        spin_lock(&ci->i_ceph_lock);
-       dout("set_size %p %llu -> %llu\n", inode, inode->i_size, size);
+       dout("set_size %p %llu -> %llu\n", inode, i_size_read(inode), size);
        i_size_write(inode, size);
        inode->i_blocks = calc_inode_blocks(size);
 
@@ -1863,6 +1869,7 @@ static void ceph_do_invalidate_pages(struct inode *inode)
        orig_gen = ci->i_rdcache_gen;
        spin_unlock(&ci->i_ceph_lock);
 
+       ceph_fscache_invalidate(inode);
        if (invalidate_inode_pages2(inode->i_mapping) < 0) {
                pr_err("invalidate_pages %p fails\n", inode);
        }
@@ -2093,20 +2100,19 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
                }
        }
        if (ia_valid & ATTR_SIZE) {
-               dout("setattr %p size %lld -> %lld\n", inode,
-                    inode->i_size, attr->ia_size);
-               if ((issued & CEPH_CAP_FILE_EXCL) &&
-                   attr->ia_size > inode->i_size) {
+               loff_t isize = i_size_read(inode);
+
+               dout("setattr %p size %lld -> %lld\n", inode, isize, attr->ia_size);
+               if ((issued & CEPH_CAP_FILE_EXCL) && attr->ia_size > isize) {
                        i_size_write(inode, attr->ia_size);
                        inode->i_blocks = calc_inode_blocks(attr->ia_size);
                        ci->i_reported_size = attr->ia_size;
                        dirtied |= CEPH_CAP_FILE_EXCL;
                        ia_valid |= ATTR_MTIME;
                } else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
-                          attr->ia_size != inode->i_size) {
+                          attr->ia_size != isize) {
                        req->r_args.setattr.size = cpu_to_le64(attr->ia_size);
-                       req->r_args.setattr.old_size =
-                               cpu_to_le64(inode->i_size);
+                       req->r_args.setattr.old_size = cpu_to_le64(isize);
                        mask |= CEPH_SETATTR_SIZE;
                        release |= CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_EXCL |
                                   CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
@@ -2216,7 +2222,7 @@ int ceph_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                return err;
 
        if ((attr->ia_valid & ATTR_SIZE) &&
-           attr->ia_size > max(inode->i_size, fsc->max_file_size))
+           attr->ia_size > max(i_size_read(inode), fsc->max_file_size))
                return -EFBIG;
 
        if ((attr->ia_valid & ATTR_SIZE) &&