1*8f4e91deSSage Weil #include <linux/in.h> 2*8f4e91deSSage Weil 3*8f4e91deSSage Weil #include "ioctl.h" 4*8f4e91deSSage Weil #include "super.h" 5*8f4e91deSSage Weil #include "ceph_debug.h" 6*8f4e91deSSage Weil 7*8f4e91deSSage Weil 8*8f4e91deSSage Weil /* 9*8f4e91deSSage Weil * ioctls 10*8f4e91deSSage Weil */ 11*8f4e91deSSage Weil 12*8f4e91deSSage Weil /* 13*8f4e91deSSage Weil * get and set the file layout 14*8f4e91deSSage Weil */ 15*8f4e91deSSage Weil static long ceph_ioctl_get_layout(struct file *file, void __user *arg) 16*8f4e91deSSage Weil { 17*8f4e91deSSage Weil struct ceph_inode_info *ci = ceph_inode(file->f_dentry->d_inode); 18*8f4e91deSSage Weil struct ceph_ioctl_layout l; 19*8f4e91deSSage Weil int err; 20*8f4e91deSSage Weil 21*8f4e91deSSage Weil err = ceph_do_getattr(file->f_dentry->d_inode, CEPH_STAT_CAP_LAYOUT); 22*8f4e91deSSage Weil if (!err) { 23*8f4e91deSSage Weil l.stripe_unit = ceph_file_layout_su(ci->i_layout); 24*8f4e91deSSage Weil l.stripe_count = ceph_file_layout_stripe_count(ci->i_layout); 25*8f4e91deSSage Weil l.object_size = ceph_file_layout_object_size(ci->i_layout); 26*8f4e91deSSage Weil l.data_pool = le32_to_cpu(ci->i_layout.fl_pg_pool); 27*8f4e91deSSage Weil if (copy_to_user(arg, &l, sizeof(l))) 28*8f4e91deSSage Weil return -EFAULT; 29*8f4e91deSSage Weil } 30*8f4e91deSSage Weil 31*8f4e91deSSage Weil return err; 32*8f4e91deSSage Weil } 33*8f4e91deSSage Weil 34*8f4e91deSSage Weil static long ceph_ioctl_set_layout(struct file *file, void __user *arg) 35*8f4e91deSSage Weil { 36*8f4e91deSSage Weil struct inode *inode = file->f_dentry->d_inode; 37*8f4e91deSSage Weil struct inode *parent_inode = file->f_dentry->d_parent->d_inode; 38*8f4e91deSSage Weil struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc; 39*8f4e91deSSage Weil struct ceph_mds_request *req; 40*8f4e91deSSage Weil struct ceph_ioctl_layout l; 41*8f4e91deSSage Weil int err, i; 42*8f4e91deSSage Weil 43*8f4e91deSSage Weil /* copy and validate */ 44*8f4e91deSSage Weil if (copy_from_user(&l, arg, sizeof(l))) 45*8f4e91deSSage Weil return -EFAULT; 46*8f4e91deSSage Weil 47*8f4e91deSSage Weil if ((l.object_size & ~PAGE_MASK) || 48*8f4e91deSSage Weil (l.stripe_unit & ~PAGE_MASK) || 49*8f4e91deSSage Weil !l.stripe_unit || 50*8f4e91deSSage Weil (l.object_size && 51*8f4e91deSSage Weil (unsigned)l.object_size % (unsigned)l.stripe_unit)) 52*8f4e91deSSage Weil return -EINVAL; 53*8f4e91deSSage Weil 54*8f4e91deSSage Weil /* make sure it's a valid data pool */ 55*8f4e91deSSage Weil if (l.data_pool > 0) { 56*8f4e91deSSage Weil mutex_lock(&mdsc->mutex); 57*8f4e91deSSage Weil err = -EINVAL; 58*8f4e91deSSage Weil for (i = 0; i < mdsc->mdsmap->m_num_data_pg_pools; i++) 59*8f4e91deSSage Weil if (mdsc->mdsmap->m_data_pg_pools[i] == l.data_pool) { 60*8f4e91deSSage Weil err = 0; 61*8f4e91deSSage Weil break; 62*8f4e91deSSage Weil } 63*8f4e91deSSage Weil mutex_unlock(&mdsc->mutex); 64*8f4e91deSSage Weil if (err) 65*8f4e91deSSage Weil return err; 66*8f4e91deSSage Weil } 67*8f4e91deSSage Weil 68*8f4e91deSSage Weil req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETLAYOUT, 69*8f4e91deSSage Weil USE_AUTH_MDS); 70*8f4e91deSSage Weil if (IS_ERR(req)) 71*8f4e91deSSage Weil return PTR_ERR(req); 72*8f4e91deSSage Weil req->r_inode = igrab(inode); 73*8f4e91deSSage Weil req->r_inode_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_EXCL; 74*8f4e91deSSage Weil 75*8f4e91deSSage Weil req->r_args.setlayout.layout.fl_stripe_unit = 76*8f4e91deSSage Weil cpu_to_le32(l.stripe_unit); 77*8f4e91deSSage Weil req->r_args.setlayout.layout.fl_stripe_count = 78*8f4e91deSSage Weil cpu_to_le32(l.stripe_count); 79*8f4e91deSSage Weil req->r_args.setlayout.layout.fl_object_size = 80*8f4e91deSSage Weil cpu_to_le32(l.object_size); 81*8f4e91deSSage Weil req->r_args.setlayout.layout.fl_pg_pool = cpu_to_le32(l.data_pool); 82*8f4e91deSSage Weil req->r_args.setlayout.layout.fl_pg_preferred = cpu_to_le32((s32)-1); 83*8f4e91deSSage Weil 84*8f4e91deSSage Weil err = ceph_mdsc_do_request(mdsc, parent_inode, req); 85*8f4e91deSSage Weil ceph_mdsc_put_request(req); 86*8f4e91deSSage Weil return err; 87*8f4e91deSSage Weil } 88*8f4e91deSSage Weil 89*8f4e91deSSage Weil /* 90*8f4e91deSSage Weil * Return object name, size/offset information, and location (OSD 91*8f4e91deSSage Weil * number, network address) for a given file offset. 92*8f4e91deSSage Weil */ 93*8f4e91deSSage Weil static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg) 94*8f4e91deSSage Weil { 95*8f4e91deSSage Weil struct ceph_ioctl_dataloc dl; 96*8f4e91deSSage Weil struct inode *inode = file->f_dentry->d_inode; 97*8f4e91deSSage Weil struct ceph_inode_info *ci = ceph_inode(inode); 98*8f4e91deSSage Weil struct ceph_osd_client *osdc = &ceph_client(inode->i_sb)->osdc; 99*8f4e91deSSage Weil u64 len = 1, olen; 100*8f4e91deSSage Weil u64 tmp; 101*8f4e91deSSage Weil struct ceph_object_layout ol; 102*8f4e91deSSage Weil union ceph_pg pgid; 103*8f4e91deSSage Weil 104*8f4e91deSSage Weil /* copy and validate */ 105*8f4e91deSSage Weil if (copy_from_user(&dl, arg, sizeof(dl))) 106*8f4e91deSSage Weil return -EFAULT; 107*8f4e91deSSage Weil 108*8f4e91deSSage Weil down_read(&osdc->map_sem); 109*8f4e91deSSage Weil ceph_calc_file_object_mapping(&ci->i_layout, dl.file_offset, &len, 110*8f4e91deSSage Weil &dl.object_no, &dl.object_offset, &olen); 111*8f4e91deSSage Weil dl.file_offset -= dl.object_offset; 112*8f4e91deSSage Weil dl.object_size = ceph_file_layout_object_size(ci->i_layout); 113*8f4e91deSSage Weil dl.block_size = ceph_file_layout_su(ci->i_layout); 114*8f4e91deSSage Weil 115*8f4e91deSSage Weil /* block_offset = object_offset % block_size */ 116*8f4e91deSSage Weil tmp = dl.object_offset; 117*8f4e91deSSage Weil dl.block_offset = do_div(tmp, dl.block_size); 118*8f4e91deSSage Weil 119*8f4e91deSSage Weil snprintf(dl.object_name, sizeof(dl.object_name), "%llx.%08llx", 120*8f4e91deSSage Weil ceph_ino(inode), dl.object_no); 121*8f4e91deSSage Weil ceph_calc_object_layout(&ol, dl.object_name, &ci->i_layout, 122*8f4e91deSSage Weil osdc->osdmap); 123*8f4e91deSSage Weil 124*8f4e91deSSage Weil pgid.pg64 = le64_to_cpu(ol.ol_pgid); 125*8f4e91deSSage Weil dl.osd = ceph_calc_pg_primary(osdc->osdmap, pgid); 126*8f4e91deSSage Weil if (dl.osd >= 0) { 127*8f4e91deSSage Weil struct ceph_entity_addr *a = 128*8f4e91deSSage Weil ceph_osd_addr(osdc->osdmap, dl.osd); 129*8f4e91deSSage Weil if (a) 130*8f4e91deSSage Weil memcpy(&dl.osd_addr, &a->in_addr, sizeof(dl.osd_addr)); 131*8f4e91deSSage Weil } else { 132*8f4e91deSSage Weil memset(&dl.osd_addr, 0, sizeof(dl.osd_addr)); 133*8f4e91deSSage Weil } 134*8f4e91deSSage Weil up_read(&osdc->map_sem); 135*8f4e91deSSage Weil 136*8f4e91deSSage Weil /* send result back to user */ 137*8f4e91deSSage Weil if (copy_to_user(arg, &dl, sizeof(dl))) 138*8f4e91deSSage Weil return -EFAULT; 139*8f4e91deSSage Weil 140*8f4e91deSSage Weil return 0; 141*8f4e91deSSage Weil } 142*8f4e91deSSage Weil 143*8f4e91deSSage Weil long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 144*8f4e91deSSage Weil { 145*8f4e91deSSage Weil dout("ioctl file %p cmd %u arg %lu\n", file, cmd, arg); 146*8f4e91deSSage Weil switch (cmd) { 147*8f4e91deSSage Weil case CEPH_IOC_GET_LAYOUT: 148*8f4e91deSSage Weil return ceph_ioctl_get_layout(file, (void __user *)arg); 149*8f4e91deSSage Weil 150*8f4e91deSSage Weil case CEPH_IOC_SET_LAYOUT: 151*8f4e91deSSage Weil return ceph_ioctl_set_layout(file, (void __user *)arg); 152*8f4e91deSSage Weil 153*8f4e91deSSage Weil case CEPH_IOC_GET_DATALOC: 154*8f4e91deSSage Weil return ceph_ioctl_get_dataloc(file, (void __user *)arg); 155*8f4e91deSSage Weil } 156*8f4e91deSSage Weil return -ENOTTY; 157*8f4e91deSSage Weil } 158