linux/fs/ocfs2/ioctl.c
<<
>>
Prefs
   1/*
   2 * linux/fs/ocfs2/ioctl.c
   3 *
   4 * Copyright (C) 2006 Herbert Poetzl
   5 * adapted from Remy Card's ext2/ioctl.c
   6 */
   7
   8#include <linux/fs.h>
   9#include <linux/mount.h>
  10#include <linux/compat.h>
  11
  12#include <cluster/masklog.h>
  13
  14#include "ocfs2.h"
  15#include "alloc.h"
  16#include "dlmglue.h"
  17#include "file.h"
  18#include "inode.h"
  19#include "journal.h"
  20
  21#include "ocfs2_fs.h"
  22#include "ioctl.h"
  23#include "resize.h"
  24#include "refcounttree.h"
  25#include "sysfile.h"
  26#include "dir.h"
  27#include "buffer_head_io.h"
  28#include "suballoc.h"
  29#include "move_extents.h"
  30
  31#define o2info_from_user(a, b)  \
  32                copy_from_user(&(a), (b), sizeof(a))
  33#define o2info_to_user(a, b)    \
  34                copy_to_user((typeof(a) __user *)b, &(a), sizeof(a))
  35
  36/*
  37 * This call is void because we are already reporting an error that may
  38 * be -EFAULT.  The error will be returned from the ioctl(2) call.  It's
  39 * just a best-effort to tell userspace that this request caused the error.
  40 */
  41static inline void o2info_set_request_error(struct ocfs2_info_request *kreq,
  42                                        struct ocfs2_info_request __user *req)
  43{
  44        kreq->ir_flags |= OCFS2_INFO_FL_ERROR;
  45        (void)put_user(kreq->ir_flags, (__u32 __user *)&(req->ir_flags));
  46}
  47
  48static inline void o2info_set_request_filled(struct ocfs2_info_request *req)
  49{
  50        req->ir_flags |= OCFS2_INFO_FL_FILLED;
  51}
  52
  53static inline void o2info_clear_request_filled(struct ocfs2_info_request *req)
  54{
  55        req->ir_flags &= ~OCFS2_INFO_FL_FILLED;
  56}
  57
  58static inline int o2info_coherent(struct ocfs2_info_request *req)
  59{
  60        return (!(req->ir_flags & OCFS2_INFO_FL_NON_COHERENT));
  61}
  62
  63static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags)
  64{
  65        int status;
  66
  67        status = ocfs2_inode_lock(inode, NULL, 0);
  68        if (status < 0) {
  69                mlog_errno(status);
  70                return status;
  71        }
  72        ocfs2_get_inode_flags(OCFS2_I(inode));
  73        *flags = OCFS2_I(inode)->ip_attr;
  74        ocfs2_inode_unlock(inode, 0);
  75
  76        return status;
  77}
  78
  79static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
  80                                unsigned mask)
  81{
  82        struct ocfs2_inode_info *ocfs2_inode = OCFS2_I(inode);
  83        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
  84        handle_t *handle = NULL;
  85        struct buffer_head *bh = NULL;
  86        unsigned oldflags;
  87        int status;
  88
  89        mutex_lock(&inode->i_mutex);
  90
  91        status = ocfs2_inode_lock(inode, &bh, 1);
  92        if (status < 0) {
  93                mlog_errno(status);
  94                goto bail;
  95        }
  96
  97        status = -EACCES;
  98        if (!inode_owner_or_capable(inode))
  99                goto bail_unlock;
 100
 101        if (!S_ISDIR(inode->i_mode))
 102                flags &= ~OCFS2_DIRSYNC_FL;
 103
 104        handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
 105        if (IS_ERR(handle)) {
 106                status = PTR_ERR(handle);
 107                mlog_errno(status);
 108                goto bail_unlock;
 109        }
 110
 111        oldflags = ocfs2_inode->ip_attr;
 112        flags = flags & mask;
 113        flags |= oldflags & ~mask;
 114
 115        /*
 116         * The IMMUTABLE and APPEND_ONLY flags can only be changed by
 117         * the relevant capability.
 118         */
 119        status = -EPERM;
 120        if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
 121                (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
 122                if (!capable(CAP_LINUX_IMMUTABLE))
 123                        goto bail_commit;
 124        }
 125
 126        ocfs2_inode->ip_attr = flags;
 127        ocfs2_set_inode_flags(inode);
 128
 129        status = ocfs2_mark_inode_dirty(handle, inode, bh);
 130        if (status < 0)
 131                mlog_errno(status);
 132
 133bail_commit:
 134        ocfs2_commit_trans(osb, handle);
 135bail_unlock:
 136        ocfs2_inode_unlock(inode, 1);
 137bail:
 138        mutex_unlock(&inode->i_mutex);
 139
 140        brelse(bh);
 141
 142        return status;
 143}
 144
 145int ocfs2_info_handle_blocksize(struct inode *inode,
 146                                struct ocfs2_info_request __user *req)
 147{
 148        int status = -EFAULT;
 149        struct ocfs2_info_blocksize oib;
 150
 151        if (o2info_from_user(oib, req))
 152                goto bail;
 153
 154        oib.ib_blocksize = inode->i_sb->s_blocksize;
 155
 156        o2info_set_request_filled(&oib.ib_req);
 157
 158        if (o2info_to_user(oib, req))
 159                goto bail;
 160
 161        status = 0;
 162bail:
 163        if (status)
 164                o2info_set_request_error(&oib.ib_req, req);
 165
 166        return status;
 167}
 168
 169int ocfs2_info_handle_clustersize(struct inode *inode,
 170                                  struct ocfs2_info_request __user *req)
 171{
 172        int status = -EFAULT;
 173        struct ocfs2_info_clustersize oic;
 174        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 175
 176        if (o2info_from_user(oic, req))
 177                goto bail;
 178
 179        oic.ic_clustersize = osb->s_clustersize;
 180
 181        o2info_set_request_filled(&oic.ic_req);
 182
 183        if (o2info_to_user(oic, req))
 184                goto bail;
 185
 186        status = 0;
 187bail:
 188        if (status)
 189                o2info_set_request_error(&oic.ic_req, req);
 190
 191        return status;
 192}
 193
 194int ocfs2_info_handle_maxslots(struct inode *inode,
 195                               struct ocfs2_info_request __user *req)
 196{
 197        int status = -EFAULT;
 198        struct ocfs2_info_maxslots oim;
 199        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 200
 201        if (o2info_from_user(oim, req))
 202                goto bail;
 203
 204        oim.im_max_slots = osb->max_slots;
 205
 206        o2info_set_request_filled(&oim.im_req);
 207
 208        if (o2info_to_user(oim, req))
 209                goto bail;
 210
 211        status = 0;
 212bail:
 213        if (status)
 214                o2info_set_request_error(&oim.im_req, req);
 215
 216        return status;
 217}
 218
 219int ocfs2_info_handle_label(struct inode *inode,
 220                            struct ocfs2_info_request __user *req)
 221{
 222        int status = -EFAULT;
 223        struct ocfs2_info_label oil;
 224        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 225
 226        if (o2info_from_user(oil, req))
 227                goto bail;
 228
 229        memcpy(oil.il_label, osb->vol_label, OCFS2_MAX_VOL_LABEL_LEN);
 230
 231        o2info_set_request_filled(&oil.il_req);
 232
 233        if (o2info_to_user(oil, req))
 234                goto bail;
 235
 236        status = 0;
 237bail:
 238        if (status)
 239                o2info_set_request_error(&oil.il_req, req);
 240
 241        return status;
 242}
 243
 244int ocfs2_info_handle_uuid(struct inode *inode,
 245                           struct ocfs2_info_request __user *req)
 246{
 247        int status = -EFAULT;
 248        struct ocfs2_info_uuid oiu;
 249        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 250
 251        if (o2info_from_user(oiu, req))
 252                goto bail;
 253
 254        memcpy(oiu.iu_uuid_str, osb->uuid_str, OCFS2_TEXT_UUID_LEN + 1);
 255
 256        o2info_set_request_filled(&oiu.iu_req);
 257
 258        if (o2info_to_user(oiu, req))
 259                goto bail;
 260
 261        status = 0;
 262bail:
 263        if (status)
 264                o2info_set_request_error(&oiu.iu_req, req);
 265
 266        return status;
 267}
 268
 269int ocfs2_info_handle_fs_features(struct inode *inode,
 270                                  struct ocfs2_info_request __user *req)
 271{
 272        int status = -EFAULT;
 273        struct ocfs2_info_fs_features oif;
 274        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 275
 276        if (o2info_from_user(oif, req))
 277                goto bail;
 278
 279        oif.if_compat_features = osb->s_feature_compat;
 280        oif.if_incompat_features = osb->s_feature_incompat;
 281        oif.if_ro_compat_features = osb->s_feature_ro_compat;
 282
 283        o2info_set_request_filled(&oif.if_req);
 284
 285        if (o2info_to_user(oif, req))
 286                goto bail;
 287
 288        status = 0;
 289bail:
 290        if (status)
 291                o2info_set_request_error(&oif.if_req, req);
 292
 293        return status;
 294}
 295
 296int ocfs2_info_handle_journal_size(struct inode *inode,
 297                                   struct ocfs2_info_request __user *req)
 298{
 299        int status = -EFAULT;
 300        struct ocfs2_info_journal_size oij;
 301        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 302
 303        if (o2info_from_user(oij, req))
 304                goto bail;
 305
 306        oij.ij_journal_size = osb->journal->j_inode->i_size;
 307
 308        o2info_set_request_filled(&oij.ij_req);
 309
 310        if (o2info_to_user(oij, req))
 311                goto bail;
 312
 313        status = 0;
 314bail:
 315        if (status)
 316                o2info_set_request_error(&oij.ij_req, req);
 317
 318        return status;
 319}
 320
 321int ocfs2_info_scan_inode_alloc(struct ocfs2_super *osb,
 322                                struct inode *inode_alloc, u64 blkno,
 323                                struct ocfs2_info_freeinode *fi, u32 slot)
 324{
 325        int status = 0, unlock = 0;
 326
 327        struct buffer_head *bh = NULL;
 328        struct ocfs2_dinode *dinode_alloc = NULL;
 329
 330        if (inode_alloc)
 331                mutex_lock(&inode_alloc->i_mutex);
 332
 333        if (o2info_coherent(&fi->ifi_req)) {
 334                status = ocfs2_inode_lock(inode_alloc, &bh, 0);
 335                if (status < 0) {
 336                        mlog_errno(status);
 337                        goto bail;
 338                }
 339                unlock = 1;
 340        } else {
 341                status = ocfs2_read_blocks_sync(osb, blkno, 1, &bh);
 342                if (status < 0) {
 343                        mlog_errno(status);
 344                        goto bail;
 345                }
 346        }
 347
 348        dinode_alloc = (struct ocfs2_dinode *)bh->b_data;
 349
 350        fi->ifi_stat[slot].lfi_total =
 351                le32_to_cpu(dinode_alloc->id1.bitmap1.i_total);
 352        fi->ifi_stat[slot].lfi_free =
 353                le32_to_cpu(dinode_alloc->id1.bitmap1.i_total) -
 354                le32_to_cpu(dinode_alloc->id1.bitmap1.i_used);
 355
 356bail:
 357        if (unlock)
 358                ocfs2_inode_unlock(inode_alloc, 0);
 359
 360        if (inode_alloc)
 361                mutex_unlock(&inode_alloc->i_mutex);
 362
 363        brelse(bh);
 364
 365        return status;
 366}
 367
 368int ocfs2_info_handle_freeinode(struct inode *inode,
 369                                struct ocfs2_info_request __user *req)
 370{
 371        u32 i;
 372        u64 blkno = -1;
 373        char namebuf[40];
 374        int status = -EFAULT, type = INODE_ALLOC_SYSTEM_INODE;
 375        struct ocfs2_info_freeinode *oifi = NULL;
 376        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 377        struct inode *inode_alloc = NULL;
 378
 379        oifi = kzalloc(sizeof(struct ocfs2_info_freeinode), GFP_KERNEL);
 380        if (!oifi) {
 381                status = -ENOMEM;
 382                mlog_errno(status);
 383                goto out_err;
 384        }
 385
 386        if (o2info_from_user(*oifi, req))
 387                goto bail;
 388
 389        oifi->ifi_slotnum = osb->max_slots;
 390
 391        for (i = 0; i < oifi->ifi_slotnum; i++) {
 392                if (o2info_coherent(&oifi->ifi_req)) {
 393                        inode_alloc = ocfs2_get_system_file_inode(osb, type, i);
 394                        if (!inode_alloc) {
 395                                mlog(ML_ERROR, "unable to get alloc inode in "
 396                                    "slot %u\n", i);
 397                                status = -EIO;
 398                                goto bail;
 399                        }
 400                } else {
 401                        ocfs2_sprintf_system_inode_name(namebuf,
 402                                                        sizeof(namebuf),
 403                                                        type, i);
 404                        status = ocfs2_lookup_ino_from_name(osb->sys_root_inode,
 405                                                            namebuf,
 406                                                            strlen(namebuf),
 407                                                            &blkno);
 408                        if (status < 0) {
 409                                status = -ENOENT;
 410                                goto bail;
 411                        }
 412                }
 413
 414                status = ocfs2_info_scan_inode_alloc(osb, inode_alloc, blkno, oifi, i);
 415                if (status < 0)
 416                        goto bail;
 417
 418                iput(inode_alloc);
 419                inode_alloc = NULL;
 420        }
 421
 422        o2info_set_request_filled(&oifi->ifi_req);
 423
 424        if (o2info_to_user(*oifi, req))
 425                goto bail;
 426
 427        status = 0;
 428bail:
 429        if (status)
 430                o2info_set_request_error(&oifi->ifi_req, req);
 431
 432        kfree(oifi);
 433out_err:
 434        return status;
 435}
 436
 437static void o2ffg_update_histogram(struct ocfs2_info_free_chunk_list *hist,
 438                                   unsigned int chunksize)
 439{
 440        int index;
 441
 442        index = __ilog2_u32(chunksize);
 443        if (index >= OCFS2_INFO_MAX_HIST)
 444                index = OCFS2_INFO_MAX_HIST - 1;
 445
 446        hist->fc_chunks[index]++;
 447        hist->fc_clusters[index] += chunksize;
 448}
 449
 450static void o2ffg_update_stats(struct ocfs2_info_freefrag_stats *stats,
 451                               unsigned int chunksize)
 452{
 453        if (chunksize > stats->ffs_max)
 454                stats->ffs_max = chunksize;
 455
 456        if (chunksize < stats->ffs_min)
 457                stats->ffs_min = chunksize;
 458
 459        stats->ffs_avg += chunksize;
 460        stats->ffs_free_chunks_real++;
 461}
 462
 463void ocfs2_info_update_ffg(struct ocfs2_info_freefrag *ffg,
 464                           unsigned int chunksize)
 465{
 466        o2ffg_update_histogram(&(ffg->iff_ffs.ffs_fc_hist), chunksize);
 467        o2ffg_update_stats(&(ffg->iff_ffs), chunksize);
 468}
 469
 470int ocfs2_info_freefrag_scan_chain(struct ocfs2_super *osb,
 471                                   struct inode *gb_inode,
 472                                   struct ocfs2_dinode *gb_dinode,
 473                                   struct ocfs2_chain_rec *rec,
 474                                   struct ocfs2_info_freefrag *ffg,
 475                                   u32 chunks_in_group)
 476{
 477        int status = 0, used;
 478        u64 blkno;
 479
 480        struct buffer_head *bh = NULL;
 481        struct ocfs2_group_desc *bg = NULL;
 482
 483        unsigned int max_bits, num_clusters;
 484        unsigned int offset = 0, cluster, chunk;
 485        unsigned int chunk_free, last_chunksize = 0;
 486
 487        if (!le32_to_cpu(rec->c_free))
 488                goto bail;
 489
 490        do {
 491                if (!bg)
 492                        blkno = le64_to_cpu(rec->c_blkno);
 493                else
 494                        blkno = le64_to_cpu(bg->bg_next_group);
 495
 496                if (bh) {
 497                        brelse(bh);
 498                        bh = NULL;
 499                }
 500
 501                if (o2info_coherent(&ffg->iff_req))
 502                        status = ocfs2_read_group_descriptor(gb_inode,
 503                                                             gb_dinode,
 504                                                             blkno, &bh);
 505                else
 506                        status = ocfs2_read_blocks_sync(osb, blkno, 1, &bh);
 507
 508                if (status < 0) {
 509                        mlog(ML_ERROR, "Can't read the group descriptor # "
 510                             "%llu from device.", (unsigned long long)blkno);
 511                        status = -EIO;
 512                        goto bail;
 513                }
 514
 515                bg = (struct ocfs2_group_desc *)bh->b_data;
 516
 517                if (!le16_to_cpu(bg->bg_free_bits_count))
 518                        continue;
 519
 520                max_bits = le16_to_cpu(bg->bg_bits);
 521                offset = 0;
 522
 523                for (chunk = 0; chunk < chunks_in_group; chunk++) {
 524                        /*
 525                         * last chunk may be not an entire one.
 526                         */
 527                        if ((offset + ffg->iff_chunksize) > max_bits)
 528                                num_clusters = max_bits - offset;
 529                        else
 530                                num_clusters = ffg->iff_chunksize;
 531
 532                        chunk_free = 0;
 533                        for (cluster = 0; cluster < num_clusters; cluster++) {
 534                                used = ocfs2_test_bit(offset,
 535                                                (unsigned long *)bg->bg_bitmap);
 536                                /*
 537                                 * - chunk_free counts free clusters in #N chunk.
 538                                 * - last_chunksize records the size(in) clusters
 539                                 *   for the last real free chunk being counted.
 540                                 */
 541                                if (!used) {
 542                                        last_chunksize++;
 543                                        chunk_free++;
 544                                }
 545
 546                                if (used && last_chunksize) {
 547                                        ocfs2_info_update_ffg(ffg,
 548                                                              last_chunksize);
 549                                        last_chunksize = 0;
 550                                }
 551
 552                                offset++;
 553                        }
 554
 555                        if (chunk_free == ffg->iff_chunksize)
 556                                ffg->iff_ffs.ffs_free_chunks++;
 557                }
 558
 559                /*
 560                 * need to update the info for last free chunk.
 561                 */
 562                if (last_chunksize)
 563                        ocfs2_info_update_ffg(ffg, last_chunksize);
 564
 565        } while (le64_to_cpu(bg->bg_next_group));
 566
 567bail:
 568        brelse(bh);
 569
 570        return status;
 571}
 572
 573int ocfs2_info_freefrag_scan_bitmap(struct ocfs2_super *osb,
 574                                    struct inode *gb_inode, u64 blkno,
 575                                    struct ocfs2_info_freefrag *ffg)
 576{
 577        u32 chunks_in_group;
 578        int status = 0, unlock = 0, i;
 579
 580        struct buffer_head *bh = NULL;
 581        struct ocfs2_chain_list *cl = NULL;
 582        struct ocfs2_chain_rec *rec = NULL;
 583        struct ocfs2_dinode *gb_dinode = NULL;
 584
 585        if (gb_inode)
 586                mutex_lock(&gb_inode->i_mutex);
 587
 588        if (o2info_coherent(&ffg->iff_req)) {
 589                status = ocfs2_inode_lock(gb_inode, &bh, 0);
 590                if (status < 0) {
 591                        mlog_errno(status);
 592                        goto bail;
 593                }
 594                unlock = 1;
 595        } else {
 596                status = ocfs2_read_blocks_sync(osb, blkno, 1, &bh);
 597                if (status < 0) {
 598                        mlog_errno(status);
 599                        goto bail;
 600                }
 601        }
 602
 603        gb_dinode = (struct ocfs2_dinode *)bh->b_data;
 604        cl = &(gb_dinode->id2.i_chain);
 605
 606        /*
 607         * Chunksize(in) clusters from userspace should be
 608         * less than clusters in a group.
 609         */
 610        if (ffg->iff_chunksize > le16_to_cpu(cl->cl_cpg)) {
 611                status = -EINVAL;
 612                goto bail;
 613        }
 614
 615        memset(&ffg->iff_ffs, 0, sizeof(struct ocfs2_info_freefrag_stats));
 616
 617        ffg->iff_ffs.ffs_min = ~0U;
 618        ffg->iff_ffs.ffs_clusters =
 619                        le32_to_cpu(gb_dinode->id1.bitmap1.i_total);
 620        ffg->iff_ffs.ffs_free_clusters = ffg->iff_ffs.ffs_clusters -
 621                        le32_to_cpu(gb_dinode->id1.bitmap1.i_used);
 622
 623        chunks_in_group = le16_to_cpu(cl->cl_cpg) / ffg->iff_chunksize + 1;
 624
 625        for (i = 0; i < le16_to_cpu(cl->cl_next_free_rec); i++) {
 626                rec = &(cl->cl_recs[i]);
 627                status = ocfs2_info_freefrag_scan_chain(osb, gb_inode,
 628                                                        gb_dinode,
 629                                                        rec, ffg,
 630                                                        chunks_in_group);
 631                if (status)
 632                        goto bail;
 633        }
 634
 635        if (ffg->iff_ffs.ffs_free_chunks_real)
 636                ffg->iff_ffs.ffs_avg = (ffg->iff_ffs.ffs_avg /
 637                                        ffg->iff_ffs.ffs_free_chunks_real);
 638bail:
 639        if (unlock)
 640                ocfs2_inode_unlock(gb_inode, 0);
 641
 642        if (gb_inode)
 643                mutex_unlock(&gb_inode->i_mutex);
 644
 645        if (gb_inode)
 646                iput(gb_inode);
 647
 648        brelse(bh);
 649
 650        return status;
 651}
 652
 653int ocfs2_info_handle_freefrag(struct inode *inode,
 654                               struct ocfs2_info_request __user *req)
 655{
 656        u64 blkno = -1;
 657        char namebuf[40];
 658        int status = -EFAULT, type = GLOBAL_BITMAP_SYSTEM_INODE;
 659
 660        struct ocfs2_info_freefrag *oiff;
 661        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 662        struct inode *gb_inode = NULL;
 663
 664        oiff = kzalloc(sizeof(struct ocfs2_info_freefrag), GFP_KERNEL);
 665        if (!oiff) {
 666                status = -ENOMEM;
 667                mlog_errno(status);
 668                goto out_err;
 669        }
 670
 671        if (o2info_from_user(*oiff, req))
 672                goto bail;
 673        /*
 674         * chunksize from userspace should be power of 2.
 675         */
 676        if ((oiff->iff_chunksize & (oiff->iff_chunksize - 1)) ||
 677            (!oiff->iff_chunksize)) {
 678                status = -EINVAL;
 679                goto bail;
 680        }
 681
 682        if (o2info_coherent(&oiff->iff_req)) {
 683                gb_inode = ocfs2_get_system_file_inode(osb, type,
 684                                                       OCFS2_INVALID_SLOT);
 685                if (!gb_inode) {
 686                        mlog(ML_ERROR, "unable to get global_bitmap inode\n");
 687                        status = -EIO;
 688                        goto bail;
 689                }
 690        } else {
 691                ocfs2_sprintf_system_inode_name(namebuf, sizeof(namebuf), type,
 692                                                OCFS2_INVALID_SLOT);
 693                status = ocfs2_lookup_ino_from_name(osb->sys_root_inode,
 694                                                    namebuf,
 695                                                    strlen(namebuf),
 696                                                    &blkno);
 697                if (status < 0) {
 698                        status = -ENOENT;
 699                        goto bail;
 700                }
 701        }
 702
 703        status = ocfs2_info_freefrag_scan_bitmap(osb, gb_inode, blkno, oiff);
 704        if (status < 0)
 705                goto bail;
 706
 707        o2info_set_request_filled(&oiff->iff_req);
 708
 709        if (o2info_to_user(*oiff, req))
 710                goto bail;
 711
 712        status = 0;
 713bail:
 714        if (status)
 715                o2info_set_request_error(&oiff->iff_req, req);
 716
 717        kfree(oiff);
 718out_err:
 719        return status;
 720}
 721
 722int ocfs2_info_handle_unknown(struct inode *inode,
 723                              struct ocfs2_info_request __user *req)
 724{
 725        int status = -EFAULT;
 726        struct ocfs2_info_request oir;
 727
 728        if (o2info_from_user(oir, req))
 729                goto bail;
 730
 731        o2info_clear_request_filled(&oir);
 732
 733        if (o2info_to_user(oir, req))
 734                goto bail;
 735
 736        status = 0;
 737bail:
 738        if (status)
 739                o2info_set_request_error(&oir, req);
 740
 741        return status;
 742}
 743
 744/*
 745 * Validate and distinguish OCFS2_IOC_INFO requests.
 746 *
 747 * - validate the magic number.
 748 * - distinguish different requests.
 749 * - validate size of different requests.
 750 */
 751int ocfs2_info_handle_request(struct inode *inode,
 752                              struct ocfs2_info_request __user *req)
 753{
 754        int status = -EFAULT;
 755        struct ocfs2_info_request oir;
 756
 757        if (o2info_from_user(oir, req))
 758                goto bail;
 759
 760        status = -EINVAL;
 761        if (oir.ir_magic != OCFS2_INFO_MAGIC)
 762                goto bail;
 763
 764        switch (oir.ir_code) {
 765        case OCFS2_INFO_BLOCKSIZE:
 766                if (oir.ir_size == sizeof(struct ocfs2_info_blocksize))
 767                        status = ocfs2_info_handle_blocksize(inode, req);
 768                break;
 769        case OCFS2_INFO_CLUSTERSIZE:
 770                if (oir.ir_size == sizeof(struct ocfs2_info_clustersize))
 771                        status = ocfs2_info_handle_clustersize(inode, req);
 772                break;
 773        case OCFS2_INFO_MAXSLOTS:
 774                if (oir.ir_size == sizeof(struct ocfs2_info_maxslots))
 775                        status = ocfs2_info_handle_maxslots(inode, req);
 776                break;
 777        case OCFS2_INFO_LABEL:
 778                if (oir.ir_size == sizeof(struct ocfs2_info_label))
 779                        status = ocfs2_info_handle_label(inode, req);
 780                break;
 781        case OCFS2_INFO_UUID:
 782                if (oir.ir_size == sizeof(struct ocfs2_info_uuid))
 783                        status = ocfs2_info_handle_uuid(inode, req);
 784                break;
 785        case OCFS2_INFO_FS_FEATURES:
 786                if (oir.ir_size == sizeof(struct ocfs2_info_fs_features))
 787                        status = ocfs2_info_handle_fs_features(inode, req);
 788                break;
 789        case OCFS2_INFO_JOURNAL_SIZE:
 790                if (oir.ir_size == sizeof(struct ocfs2_info_journal_size))
 791                        status = ocfs2_info_handle_journal_size(inode, req);
 792                break;
 793        case OCFS2_INFO_FREEINODE:
 794                if (oir.ir_size == sizeof(struct ocfs2_info_freeinode))
 795                        status = ocfs2_info_handle_freeinode(inode, req);
 796                break;
 797        case OCFS2_INFO_FREEFRAG:
 798                if (oir.ir_size == sizeof(struct ocfs2_info_freefrag))
 799                        status = ocfs2_info_handle_freefrag(inode, req);
 800                break;
 801        default:
 802                status = ocfs2_info_handle_unknown(inode, req);
 803                break;
 804        }
 805
 806bail:
 807        return status;
 808}
 809
 810int ocfs2_get_request_ptr(struct ocfs2_info *info, int idx,
 811                          u64 *req_addr, int compat_flag)
 812{
 813        int status = -EFAULT;
 814        u64 __user *bp = NULL;
 815
 816        if (compat_flag) {
 817#ifdef CONFIG_COMPAT
 818                /*
 819                 * pointer bp stores the base address of a pointers array,
 820                 * which collects all addresses of separate request.
 821                 */
 822                bp = (u64 __user *)(unsigned long)compat_ptr(info->oi_requests);
 823#else
 824                BUG();
 825#endif
 826        } else
 827                bp = (u64 __user *)(unsigned long)(info->oi_requests);
 828
 829        if (o2info_from_user(*req_addr, bp + idx))
 830                goto bail;
 831
 832        status = 0;
 833bail:
 834        return status;
 835}
 836
 837/*
 838 * OCFS2_IOC_INFO handles an array of requests passed from userspace.
 839 *
 840 * ocfs2_info_handle() recevies a large info aggregation, grab and
 841 * validate the request count from header, then break it into small
 842 * pieces, later specific handlers can handle them one by one.
 843 *
 844 * Idea here is to make each separate request small enough to ensure
 845 * a better backward&forward compatibility, since a small piece of
 846 * request will be less likely to be broken if disk layout get changed.
 847 */
 848int ocfs2_info_handle(struct inode *inode, struct ocfs2_info *info,
 849                      int compat_flag)
 850{
 851        int i, status = 0;
 852        u64 req_addr;
 853        struct ocfs2_info_request __user *reqp;
 854
 855        if ((info->oi_count > OCFS2_INFO_MAX_REQUEST) ||
 856            (!info->oi_requests)) {
 857                status = -EINVAL;
 858                goto bail;
 859        }
 860
 861        for (i = 0; i < info->oi_count; i++) {
 862
 863                status = ocfs2_get_request_ptr(info, i, &req_addr, compat_flag);
 864                if (status)
 865                        break;
 866
 867                reqp = (struct ocfs2_info_request __user *)(unsigned long)req_addr;
 868                if (!reqp) {
 869                        status = -EINVAL;
 870                        goto bail;
 871                }
 872
 873                status = ocfs2_info_handle_request(inode, reqp);
 874                if (status)
 875                        break;
 876        }
 877
 878bail:
 879        return status;
 880}
 881
 882long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 883{
 884        struct inode *inode = filp->f_path.dentry->d_inode;
 885        unsigned int flags;
 886        int new_clusters;
 887        int status;
 888        struct ocfs2_space_resv sr;
 889        struct ocfs2_new_group_input input;
 890        struct reflink_arguments args;
 891        const char __user *old_path;
 892        const char __user *new_path;
 893        bool preserve;
 894        struct ocfs2_info info;
 895        void __user *argp = (void __user *)arg;
 896
 897        switch (cmd) {
 898        case OCFS2_IOC_GETFLAGS:
 899                status = ocfs2_get_inode_attr(inode, &flags);
 900                if (status < 0)
 901                        return status;
 902
 903                flags &= OCFS2_FL_VISIBLE;
 904                return put_user(flags, (int __user *) arg);
 905        case OCFS2_IOC_SETFLAGS:
 906                if (get_user(flags, (int __user *) arg))
 907                        return -EFAULT;
 908
 909                status = mnt_want_write_file(filp);
 910                if (status)
 911                        return status;
 912                status = ocfs2_set_inode_attr(inode, flags,
 913                        OCFS2_FL_MODIFIABLE);
 914                mnt_drop_write_file(filp);
 915                return status;
 916        case OCFS2_IOC_RESVSP:
 917        case OCFS2_IOC_RESVSP64:
 918        case OCFS2_IOC_UNRESVSP:
 919        case OCFS2_IOC_UNRESVSP64:
 920                if (copy_from_user(&sr, (int __user *) arg, sizeof(sr)))
 921                        return -EFAULT;
 922
 923                return ocfs2_change_file_space(filp, cmd, &sr);
 924        case OCFS2_IOC_GROUP_EXTEND:
 925                if (!capable(CAP_SYS_RESOURCE))
 926                        return -EPERM;
 927
 928                if (get_user(new_clusters, (int __user *)arg))
 929                        return -EFAULT;
 930
 931                status = mnt_want_write_file(filp);
 932                if (status)
 933                        return status;
 934                status = ocfs2_group_extend(inode, new_clusters);
 935                mnt_drop_write_file(filp);
 936                return status;
 937        case OCFS2_IOC_GROUP_ADD:
 938        case OCFS2_IOC_GROUP_ADD64:
 939                if (!capable(CAP_SYS_RESOURCE))
 940                        return -EPERM;
 941
 942                if (copy_from_user(&input, (int __user *) arg, sizeof(input)))
 943                        return -EFAULT;
 944
 945                status = mnt_want_write_file(filp);
 946                if (status)
 947                        return status;
 948                status = ocfs2_group_add(inode, &input);
 949                mnt_drop_write_file(filp);
 950                return status;
 951        case OCFS2_IOC_REFLINK:
 952                if (copy_from_user(&args, argp, sizeof(args)))
 953                        return -EFAULT;
 954                old_path = (const char __user *)(unsigned long)args.old_path;
 955                new_path = (const char __user *)(unsigned long)args.new_path;
 956                preserve = (args.preserve != 0);
 957
 958                return ocfs2_reflink_ioctl(inode, old_path, new_path, preserve);
 959        case OCFS2_IOC_INFO:
 960                if (copy_from_user(&info, argp, sizeof(struct ocfs2_info)))
 961                        return -EFAULT;
 962
 963                return ocfs2_info_handle(inode, &info, 0);
 964        case FITRIM:
 965        {
 966                struct super_block *sb = inode->i_sb;
 967                struct fstrim_range range;
 968                int ret = 0;
 969
 970                if (!capable(CAP_SYS_ADMIN))
 971                        return -EPERM;
 972
 973                if (copy_from_user(&range, argp, sizeof(range)))
 974                        return -EFAULT;
 975
 976                ret = ocfs2_trim_fs(sb, &range);
 977                if (ret < 0)
 978                        return ret;
 979
 980                if (copy_to_user(argp, &range, sizeof(range)))
 981                        return -EFAULT;
 982
 983                return 0;
 984        }
 985        case OCFS2_IOC_MOVE_EXT:
 986                return ocfs2_ioctl_move_extents(filp, argp);
 987        default:
 988                return -ENOTTY;
 989        }
 990}
 991
 992#ifdef CONFIG_COMPAT
 993long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 994{
 995        bool preserve;
 996        struct reflink_arguments args;
 997        struct inode *inode = file->f_path.dentry->d_inode;
 998        struct ocfs2_info info;
 999        void __user *argp = (void __user *)arg;
1000
1001        switch (cmd) {
1002        case OCFS2_IOC32_GETFLAGS:
1003                cmd = OCFS2_IOC_GETFLAGS;
1004                break;
1005        case OCFS2_IOC32_SETFLAGS:
1006                cmd = OCFS2_IOC_SETFLAGS;
1007                break;
1008        case OCFS2_IOC_RESVSP:
1009        case OCFS2_IOC_RESVSP64:
1010        case OCFS2_IOC_UNRESVSP:
1011        case OCFS2_IOC_UNRESVSP64:
1012        case OCFS2_IOC_GROUP_EXTEND:
1013        case OCFS2_IOC_GROUP_ADD:
1014        case OCFS2_IOC_GROUP_ADD64:
1015        case FITRIM:
1016                break;
1017        case OCFS2_IOC_REFLINK:
1018                if (copy_from_user(&args, argp, sizeof(args)))
1019                        return -EFAULT;
1020                preserve = (args.preserve != 0);
1021
1022                return ocfs2_reflink_ioctl(inode, compat_ptr(args.old_path),
1023                                           compat_ptr(args.new_path), preserve);
1024        case OCFS2_IOC_INFO:
1025                if (copy_from_user(&info, argp, sizeof(struct ocfs2_info)))
1026                        return -EFAULT;
1027
1028                return ocfs2_info_handle(inode, &info, 1);
1029        case OCFS2_IOC_MOVE_EXT:
1030                break;
1031        default:
1032                return -ENOIOCTLCMD;
1033        }
1034
1035        return ocfs2_ioctl(file, cmd, arg);
1036}
1037#endif
1038
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.