18f4e91deSSage Weil #include <linux/in.h> 28f4e91deSSage Weil 38f4e91deSSage Weil #include "super.h" 4*3d14c5d2SYehuda Sadeh #include "mds_client.h" 5*3d14c5d2SYehuda Sadeh #include <linux/ceph/ceph_debug.h> 6*3d14c5d2SYehuda Sadeh 7*3d14c5d2SYehuda Sadeh #include "ioctl.h" 88f4e91deSSage Weil 98f4e91deSSage Weil 108f4e91deSSage Weil /* 118f4e91deSSage Weil * ioctls 128f4e91deSSage Weil */ 138f4e91deSSage Weil 148f4e91deSSage Weil /* 158f4e91deSSage Weil * get and set the file layout 168f4e91deSSage Weil */ 178f4e91deSSage Weil static long ceph_ioctl_get_layout(struct file *file, void __user *arg) 188f4e91deSSage Weil { 198f4e91deSSage Weil struct ceph_inode_info *ci = ceph_inode(file->f_dentry->d_inode); 208f4e91deSSage Weil struct ceph_ioctl_layout l; 218f4e91deSSage Weil int err; 228f4e91deSSage Weil 238f4e91deSSage Weil err = ceph_do_getattr(file->f_dentry->d_inode, CEPH_STAT_CAP_LAYOUT); 248f4e91deSSage Weil if (!err) { 258f4e91deSSage Weil l.stripe_unit = ceph_file_layout_su(ci->i_layout); 268f4e91deSSage Weil l.stripe_count = ceph_file_layout_stripe_count(ci->i_layout); 278f4e91deSSage Weil l.object_size = ceph_file_layout_object_size(ci->i_layout); 288f4e91deSSage Weil l.data_pool = le32_to_cpu(ci->i_layout.fl_pg_pool); 2933d4909cSSage Weil l.preferred_osd = 3033d4909cSSage Weil (s32)le32_to_cpu(ci->i_layout.fl_pg_preferred); 318f4e91deSSage Weil if (copy_to_user(arg, &l, sizeof(l))) 328f4e91deSSage Weil return -EFAULT; 338f4e91deSSage Weil } 348f4e91deSSage Weil 358f4e91deSSage Weil return err; 368f4e91deSSage Weil } 378f4e91deSSage Weil 388f4e91deSSage Weil static long ceph_ioctl_set_layout(struct file *file, void __user *arg) 398f4e91deSSage Weil { 408f4e91deSSage Weil struct inode *inode = file->f_dentry->d_inode; 418f4e91deSSage Weil struct inode *parent_inode = file->f_dentry->d_parent->d_inode; 42*3d14c5d2SYehuda Sadeh struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; 438f4e91deSSage Weil struct ceph_mds_request *req; 448f4e91deSSage Weil struct ceph_ioctl_layout l; 458f4e91deSSage Weil int err, i; 468f4e91deSSage Weil 478f4e91deSSage Weil /* copy and validate */ 488f4e91deSSage Weil if (copy_from_user(&l, arg, sizeof(l))) 498f4e91deSSage Weil return -EFAULT; 508f4e91deSSage Weil 518f4e91deSSage Weil if ((l.object_size & ~PAGE_MASK) || 528f4e91deSSage Weil (l.stripe_unit & ~PAGE_MASK) || 538f4e91deSSage Weil !l.stripe_unit || 548f4e91deSSage Weil (l.object_size && 558f4e91deSSage Weil (unsigned)l.object_size % (unsigned)l.stripe_unit)) 568f4e91deSSage Weil return -EINVAL; 578f4e91deSSage Weil 588f4e91deSSage Weil /* make sure it's a valid data pool */ 598f4e91deSSage Weil if (l.data_pool > 0) { 608f4e91deSSage Weil mutex_lock(&mdsc->mutex); 618f4e91deSSage Weil err = -EINVAL; 628f4e91deSSage Weil for (i = 0; i < mdsc->mdsmap->m_num_data_pg_pools; i++) 638f4e91deSSage Weil if (mdsc->mdsmap->m_data_pg_pools[i] == l.data_pool) { 648f4e91deSSage Weil err = 0; 658f4e91deSSage Weil break; 668f4e91deSSage Weil } 678f4e91deSSage Weil mutex_unlock(&mdsc->mutex); 688f4e91deSSage Weil if (err) 698f4e91deSSage Weil return err; 708f4e91deSSage Weil } 718f4e91deSSage Weil 728f4e91deSSage Weil req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETLAYOUT, 738f4e91deSSage Weil USE_AUTH_MDS); 748f4e91deSSage Weil if (IS_ERR(req)) 758f4e91deSSage Weil return PTR_ERR(req); 768f4e91deSSage Weil req->r_inode = igrab(inode); 778f4e91deSSage Weil req->r_inode_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_EXCL; 788f4e91deSSage Weil 798f4e91deSSage Weil req->r_args.setlayout.layout.fl_stripe_unit = 808f4e91deSSage Weil cpu_to_le32(l.stripe_unit); 818f4e91deSSage Weil req->r_args.setlayout.layout.fl_stripe_count = 828f4e91deSSage Weil cpu_to_le32(l.stripe_count); 838f4e91deSSage Weil req->r_args.setlayout.layout.fl_object_size = 848f4e91deSSage Weil cpu_to_le32(l.object_size); 858f4e91deSSage Weil req->r_args.setlayout.layout.fl_pg_pool = cpu_to_le32(l.data_pool); 8633d4909cSSage Weil req->r_args.setlayout.layout.fl_pg_preferred = 8733d4909cSSage Weil cpu_to_le32(l.preferred_osd); 888f4e91deSSage Weil 898f4e91deSSage Weil err = ceph_mdsc_do_request(mdsc, parent_inode, req); 908f4e91deSSage Weil ceph_mdsc_put_request(req); 918f4e91deSSage Weil return err; 928f4e91deSSage Weil } 938f4e91deSSage Weil 948f4e91deSSage Weil /* 958f4e91deSSage Weil * Return object name, size/offset information, and location (OSD 968f4e91deSSage Weil * number, network address) for a given file offset. 978f4e91deSSage Weil */ 988f4e91deSSage Weil static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg) 998f4e91deSSage Weil { 1008f4e91deSSage Weil struct ceph_ioctl_dataloc dl; 1018f4e91deSSage Weil struct inode *inode = file->f_dentry->d_inode; 1028f4e91deSSage Weil struct ceph_inode_info *ci = ceph_inode(inode); 103*3d14c5d2SYehuda Sadeh struct ceph_osd_client *osdc = 104*3d14c5d2SYehuda Sadeh &ceph_sb_to_client(inode->i_sb)->client->osdc; 1058f4e91deSSage Weil u64 len = 1, olen; 1068f4e91deSSage Weil u64 tmp; 1078f4e91deSSage Weil struct ceph_object_layout ol; 10851042122SSage Weil struct ceph_pg pgid; 1098f4e91deSSage Weil 1108f4e91deSSage Weil /* copy and validate */ 1118f4e91deSSage Weil if (copy_from_user(&dl, arg, sizeof(dl))) 1128f4e91deSSage Weil return -EFAULT; 1138f4e91deSSage Weil 1148f4e91deSSage Weil down_read(&osdc->map_sem); 1158f4e91deSSage Weil ceph_calc_file_object_mapping(&ci->i_layout, dl.file_offset, &len, 1168f4e91deSSage Weil &dl.object_no, &dl.object_offset, &olen); 1178f4e91deSSage Weil dl.file_offset -= dl.object_offset; 1188f4e91deSSage Weil dl.object_size = ceph_file_layout_object_size(ci->i_layout); 1198f4e91deSSage Weil dl.block_size = ceph_file_layout_su(ci->i_layout); 1208f4e91deSSage Weil 1218f4e91deSSage Weil /* block_offset = object_offset % block_size */ 1228f4e91deSSage Weil tmp = dl.object_offset; 1238f4e91deSSage Weil dl.block_offset = do_div(tmp, dl.block_size); 1248f4e91deSSage Weil 1258f4e91deSSage Weil snprintf(dl.object_name, sizeof(dl.object_name), "%llx.%08llx", 1268f4e91deSSage Weil ceph_ino(inode), dl.object_no); 1278f4e91deSSage Weil ceph_calc_object_layout(&ol, dl.object_name, &ci->i_layout, 1288f4e91deSSage Weil osdc->osdmap); 1298f4e91deSSage Weil 13051042122SSage Weil pgid = ol.ol_pgid; 1318f4e91deSSage Weil dl.osd = ceph_calc_pg_primary(osdc->osdmap, pgid); 1328f4e91deSSage Weil if (dl.osd >= 0) { 1338f4e91deSSage Weil struct ceph_entity_addr *a = 1348f4e91deSSage Weil ceph_osd_addr(osdc->osdmap, dl.osd); 1358f4e91deSSage Weil if (a) 1368f4e91deSSage Weil memcpy(&dl.osd_addr, &a->in_addr, sizeof(dl.osd_addr)); 1378f4e91deSSage Weil } else { 1388f4e91deSSage Weil memset(&dl.osd_addr, 0, sizeof(dl.osd_addr)); 1398f4e91deSSage Weil } 1408f4e91deSSage Weil up_read(&osdc->map_sem); 1418f4e91deSSage Weil 1428f4e91deSSage Weil /* send result back to user */ 1438f4e91deSSage Weil if (copy_to_user(arg, &dl, sizeof(dl))) 1448f4e91deSSage Weil return -EFAULT; 1458f4e91deSSage Weil 1468f4e91deSSage Weil return 0; 1478f4e91deSSage Weil } 1488f4e91deSSage Weil 1498c6e9229SSage Weil static long ceph_ioctl_lazyio(struct file *file) 1508c6e9229SSage Weil { 1518c6e9229SSage Weil struct ceph_file_info *fi = file->private_data; 1528c6e9229SSage Weil struct inode *inode = file->f_dentry->d_inode; 1538c6e9229SSage Weil struct ceph_inode_info *ci = ceph_inode(inode); 1548c6e9229SSage Weil 1558c6e9229SSage Weil if ((fi->fmode & CEPH_FILE_MODE_LAZY) == 0) { 1568c6e9229SSage Weil spin_lock(&inode->i_lock); 1578c6e9229SSage Weil ci->i_nr_by_mode[fi->fmode]--; 1588c6e9229SSage Weil fi->fmode |= CEPH_FILE_MODE_LAZY; 1598c6e9229SSage Weil ci->i_nr_by_mode[fi->fmode]++; 1608c6e9229SSage Weil spin_unlock(&inode->i_lock); 1618c6e9229SSage Weil dout("ioctl_layzio: file %p marked lazy\n", file); 1628c6e9229SSage Weil 1638c6e9229SSage Weil ceph_check_caps(ci, 0, NULL); 1648c6e9229SSage Weil } else { 1658c6e9229SSage Weil dout("ioctl_layzio: file %p already lazy\n", file); 1668c6e9229SSage Weil } 1678c6e9229SSage Weil return 0; 1688c6e9229SSage Weil } 1698c6e9229SSage Weil 1708f4e91deSSage Weil long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 1718f4e91deSSage Weil { 1728f4e91deSSage Weil dout("ioctl file %p cmd %u arg %lu\n", file, cmd, arg); 1738f4e91deSSage Weil switch (cmd) { 1748f4e91deSSage Weil case CEPH_IOC_GET_LAYOUT: 1758f4e91deSSage Weil return ceph_ioctl_get_layout(file, (void __user *)arg); 1768f4e91deSSage Weil 1778f4e91deSSage Weil case CEPH_IOC_SET_LAYOUT: 1788f4e91deSSage Weil return ceph_ioctl_set_layout(file, (void __user *)arg); 1798f4e91deSSage Weil 1808f4e91deSSage Weil case CEPH_IOC_GET_DATALOC: 1818f4e91deSSage Weil return ceph_ioctl_get_dataloc(file, (void __user *)arg); 1828c6e9229SSage Weil 1838c6e9229SSage Weil case CEPH_IOC_LAZYIO: 1848c6e9229SSage Weil return ceph_ioctl_lazyio(file); 1858f4e91deSSage Weil } 1868f4e91deSSage Weil return -ENOTTY; 1878f4e91deSSage Weil } 188