root/fs/ceph/ioctl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ceph_ioctl_get_layout
  2. __validate_layout
  3. ceph_ioctl_set_layout
  4. ceph_ioctl_set_layout_policy
  5. ceph_ioctl_get_dataloc
  6. ceph_ioctl_lazyio
  7. ceph_ioctl_syncio
  8. ceph_ioctl

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/ceph/ceph_debug.h>
   3 #include <linux/in.h>
   4 
   5 #include "super.h"
   6 #include "mds_client.h"
   7 #include "ioctl.h"
   8 #include <linux/ceph/striper.h>
   9 
  10 /*
  11  * ioctls
  12  */
  13 
  14 /*
  15  * get and set the file layout
  16  */
  17 static long ceph_ioctl_get_layout(struct file *file, void __user *arg)
  18 {
  19         struct ceph_inode_info *ci = ceph_inode(file_inode(file));
  20         struct ceph_ioctl_layout l;
  21         int err;
  22 
  23         err = ceph_do_getattr(file_inode(file), CEPH_STAT_CAP_LAYOUT, false);
  24         if (!err) {
  25                 l.stripe_unit = ci->i_layout.stripe_unit;
  26                 l.stripe_count = ci->i_layout.stripe_count;
  27                 l.object_size = ci->i_layout.object_size;
  28                 l.data_pool = ci->i_layout.pool_id;
  29                 l.preferred_osd = -1;
  30                 if (copy_to_user(arg, &l, sizeof(l)))
  31                         return -EFAULT;
  32         }
  33 
  34         return err;
  35 }
  36 
  37 static long __validate_layout(struct ceph_mds_client *mdsc,
  38                               struct ceph_ioctl_layout *l)
  39 {
  40         int i, err;
  41 
  42         /* validate striping parameters */
  43         if ((l->object_size & ~PAGE_MASK) ||
  44             (l->stripe_unit & ~PAGE_MASK) ||
  45             ((unsigned)l->stripe_unit != 0 &&
  46              ((unsigned)l->object_size % (unsigned)l->stripe_unit)))
  47                 return -EINVAL;
  48 
  49         /* make sure it's a valid data pool */
  50         mutex_lock(&mdsc->mutex);
  51         err = -EINVAL;
  52         for (i = 0; i < mdsc->mdsmap->m_num_data_pg_pools; i++)
  53                 if (mdsc->mdsmap->m_data_pg_pools[i] == l->data_pool) {
  54                         err = 0;
  55                         break;
  56                 }
  57         mutex_unlock(&mdsc->mutex);
  58         if (err)
  59                 return err;
  60 
  61         return 0;
  62 }
  63 
  64 static long ceph_ioctl_set_layout(struct file *file, void __user *arg)
  65 {
  66         struct inode *inode = file_inode(file);
  67         struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
  68         struct ceph_mds_request *req;
  69         struct ceph_ioctl_layout l;
  70         struct ceph_inode_info *ci = ceph_inode(file_inode(file));
  71         struct ceph_ioctl_layout nl;
  72         int err;
  73 
  74         if (copy_from_user(&l, arg, sizeof(l)))
  75                 return -EFAULT;
  76 
  77         /* validate changed params against current layout */
  78         err = ceph_do_getattr(file_inode(file), CEPH_STAT_CAP_LAYOUT, false);
  79         if (err)
  80                 return err;
  81 
  82         memset(&nl, 0, sizeof(nl));
  83         if (l.stripe_count)
  84                 nl.stripe_count = l.stripe_count;
  85         else
  86                 nl.stripe_count = ci->i_layout.stripe_count;
  87         if (l.stripe_unit)
  88                 nl.stripe_unit = l.stripe_unit;
  89         else
  90                 nl.stripe_unit = ci->i_layout.stripe_unit;
  91         if (l.object_size)
  92                 nl.object_size = l.object_size;
  93         else
  94                 nl.object_size = ci->i_layout.object_size;
  95         if (l.data_pool)
  96                 nl.data_pool = l.data_pool;
  97         else
  98                 nl.data_pool = ci->i_layout.pool_id;
  99 
 100         /* this is obsolete, and always -1 */
 101         nl.preferred_osd = -1;
 102 
 103         err = __validate_layout(mdsc, &nl);
 104         if (err)
 105                 return err;
 106 
 107         req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETLAYOUT,
 108                                        USE_AUTH_MDS);
 109         if (IS_ERR(req))
 110                 return PTR_ERR(req);
 111         req->r_inode = inode;
 112         ihold(inode);
 113         req->r_num_caps = 1;
 114 
 115         req->r_inode_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_EXCL;
 116 
 117         req->r_args.setlayout.layout.fl_stripe_unit =
 118                 cpu_to_le32(l.stripe_unit);
 119         req->r_args.setlayout.layout.fl_stripe_count =
 120                 cpu_to_le32(l.stripe_count);
 121         req->r_args.setlayout.layout.fl_object_size =
 122                 cpu_to_le32(l.object_size);
 123         req->r_args.setlayout.layout.fl_pg_pool = cpu_to_le32(l.data_pool);
 124 
 125         err = ceph_mdsc_do_request(mdsc, NULL, req);
 126         ceph_mdsc_put_request(req);
 127         return err;
 128 }
 129 
 130 /*
 131  * Set a layout policy on a directory inode. All items in the tree
 132  * rooted at this inode will inherit this layout on creation,
 133  * (It doesn't apply retroactively )
 134  * unless a subdirectory has its own layout policy.
 135  */
 136 static long ceph_ioctl_set_layout_policy (struct file *file, void __user *arg)
 137 {
 138         struct inode *inode = file_inode(file);
 139         struct ceph_mds_request *req;
 140         struct ceph_ioctl_layout l;
 141         int err;
 142         struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
 143 
 144         /* copy and validate */
 145         if (copy_from_user(&l, arg, sizeof(l)))
 146                 return -EFAULT;
 147 
 148         err = __validate_layout(mdsc, &l);
 149         if (err)
 150                 return err;
 151 
 152         req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETDIRLAYOUT,
 153                                        USE_AUTH_MDS);
 154 
 155         if (IS_ERR(req))
 156                 return PTR_ERR(req);
 157         req->r_inode = inode;
 158         ihold(inode);
 159         req->r_num_caps = 1;
 160 
 161         req->r_args.setlayout.layout.fl_stripe_unit =
 162                         cpu_to_le32(l.stripe_unit);
 163         req->r_args.setlayout.layout.fl_stripe_count =
 164                         cpu_to_le32(l.stripe_count);
 165         req->r_args.setlayout.layout.fl_object_size =
 166                         cpu_to_le32(l.object_size);
 167         req->r_args.setlayout.layout.fl_pg_pool =
 168                         cpu_to_le32(l.data_pool);
 169 
 170         err = ceph_mdsc_do_request(mdsc, inode, req);
 171         ceph_mdsc_put_request(req);
 172         return err;
 173 }
 174 
 175 /*
 176  * Return object name, size/offset information, and location (OSD
 177  * number, network address) for a given file offset.
 178  */
 179 static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg)
 180 {
 181         struct ceph_ioctl_dataloc dl;
 182         struct inode *inode = file_inode(file);
 183         struct ceph_inode_info *ci = ceph_inode(inode);
 184         struct ceph_osd_client *osdc =
 185                 &ceph_sb_to_client(inode->i_sb)->client->osdc;
 186         struct ceph_object_locator oloc;
 187         CEPH_DEFINE_OID_ONSTACK(oid);
 188         u32 xlen;
 189         u64 tmp;
 190         struct ceph_pg pgid;
 191         int r;
 192 
 193         /* copy and validate */
 194         if (copy_from_user(&dl, arg, sizeof(dl)))
 195                 return -EFAULT;
 196 
 197         down_read(&osdc->lock);
 198         ceph_calc_file_object_mapping(&ci->i_layout, dl.file_offset, 1,
 199                                       &dl.object_no, &dl.object_offset, &xlen);
 200         dl.file_offset -= dl.object_offset;
 201         dl.object_size = ci->i_layout.object_size;
 202         dl.block_size = ci->i_layout.stripe_unit;
 203 
 204         /* block_offset = object_offset % block_size */
 205         tmp = dl.object_offset;
 206         dl.block_offset = do_div(tmp, dl.block_size);
 207 
 208         snprintf(dl.object_name, sizeof(dl.object_name), "%llx.%08llx",
 209                  ceph_ino(inode), dl.object_no);
 210 
 211         oloc.pool = ci->i_layout.pool_id;
 212         oloc.pool_ns = ceph_try_get_string(ci->i_layout.pool_ns);
 213         ceph_oid_printf(&oid, "%s", dl.object_name);
 214 
 215         r = ceph_object_locator_to_pg(osdc->osdmap, &oid, &oloc, &pgid);
 216 
 217         ceph_oloc_destroy(&oloc);
 218         if (r < 0) {
 219                 up_read(&osdc->lock);
 220                 return r;
 221         }
 222 
 223         dl.osd = ceph_pg_to_acting_primary(osdc->osdmap, &pgid);
 224         if (dl.osd >= 0) {
 225                 struct ceph_entity_addr *a =
 226                         ceph_osd_addr(osdc->osdmap, dl.osd);
 227                 if (a)
 228                         memcpy(&dl.osd_addr, &a->in_addr, sizeof(dl.osd_addr));
 229         } else {
 230                 memset(&dl.osd_addr, 0, sizeof(dl.osd_addr));
 231         }
 232         up_read(&osdc->lock);
 233 
 234         /* send result back to user */
 235         if (copy_to_user(arg, &dl, sizeof(dl)))
 236                 return -EFAULT;
 237 
 238         return 0;
 239 }
 240 
 241 static long ceph_ioctl_lazyio(struct file *file)
 242 {
 243         struct ceph_file_info *fi = file->private_data;
 244         struct inode *inode = file_inode(file);
 245         struct ceph_inode_info *ci = ceph_inode(inode);
 246 
 247         if ((fi->fmode & CEPH_FILE_MODE_LAZY) == 0) {
 248                 spin_lock(&ci->i_ceph_lock);
 249                 fi->fmode |= CEPH_FILE_MODE_LAZY;
 250                 ci->i_nr_by_mode[ffs(CEPH_FILE_MODE_LAZY)]++;
 251                 spin_unlock(&ci->i_ceph_lock);
 252                 dout("ioctl_layzio: file %p marked lazy\n", file);
 253 
 254                 ceph_check_caps(ci, 0, NULL);
 255         } else {
 256                 dout("ioctl_layzio: file %p already lazy\n", file);
 257         }
 258         return 0;
 259 }
 260 
 261 static long ceph_ioctl_syncio(struct file *file)
 262 {
 263         struct ceph_file_info *fi = file->private_data;
 264 
 265         fi->flags |= CEPH_F_SYNC;
 266         return 0;
 267 }
 268 
 269 long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 270 {
 271         dout("ioctl file %p cmd %u arg %lu\n", file, cmd, arg);
 272         switch (cmd) {
 273         case CEPH_IOC_GET_LAYOUT:
 274                 return ceph_ioctl_get_layout(file, (void __user *)arg);
 275 
 276         case CEPH_IOC_SET_LAYOUT:
 277                 return ceph_ioctl_set_layout(file, (void __user *)arg);
 278 
 279         case CEPH_IOC_SET_LAYOUT_POLICY:
 280                 return ceph_ioctl_set_layout_policy(file, (void __user *)arg);
 281 
 282         case CEPH_IOC_GET_DATALOC:
 283                 return ceph_ioctl_get_dataloc(file, (void __user *)arg);
 284 
 285         case CEPH_IOC_LAZYIO:
 286                 return ceph_ioctl_lazyio(file);
 287 
 288         case CEPH_IOC_SYNCIO:
 289                 return ceph_ioctl_syncio(file);
 290         }
 291 
 292         return -ENOTTY;
 293 }

/* [<][>][^][v][top][bottom][index][help] */