Ejemplo n.º 1
0
static int panic_notifier(struct notifier_block *self, unsigned long unused1,
                         void *unused2)
{
        if (libcfs_panic_in_progress)
                return 0;

        libcfs_panic_in_progress = 1;
        mb();

#ifdef LNET_DUMP_ON_PANIC
        /* This is currently disabled because it spews far too much to the
         * console on the rare cases it is ever triggered. */

        if (in_interrupt()) {
                cfs_trace_debug_print();
        } else {
# ifdef HAVE_KERNEL_LOCKED
		while (kernel_locked())
			unlock_kernel();
# endif
                libcfs_debug_dumplog_internal((void *)(long)cfs_curproc_pid());
        }
#endif
        return 0;
}
Ejemplo n.º 2
0
void libcfs_debug_dumplog(void)
{
        cfs_waitlink_t wait;
        cfs_task_t    *dumper;
        ENTRY;

        /* we're being careful to ensure that the kernel thread is
         * able to set our state to running as it exits before we
         * get to schedule() */
        cfs_waitlink_init(&wait);
        cfs_set_current_state(CFS_TASK_INTERRUPTIBLE);
        cfs_waitq_add(&debug_ctlwq, &wait);

        dumper = cfs_kthread_run(libcfs_debug_dumplog_thread,
                                 (void*)(long)cfs_curproc_pid(),
                                 "libcfs_debug_dumper");
        if (IS_ERR(dumper))
                printk(CFS_KERN_ERR "LustreError: cannot start log dump thread:"
                       " %ld\n", PTR_ERR(dumper));
        else
                cfs_waitq_wait(&wait, CFS_TASK_INTERRUPTIBLE);

        /* be sure to teardown if cfs_create_thread() failed */
        cfs_waitq_del(&debug_ctlwq, &wait);
        cfs_set_current_state(CFS_TASK_RUNNING);
}
Ejemplo n.º 3
0
void
set_ptldebug_header(struct ptldebug_header *header, int subsys, int mask,
                    const int line, unsigned long stack)
{
	struct timeval tv;
	
	/*
	 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
	 * from here: this will lead to infinite recursion.
	 */
	do_gettimeofday(&tv);
	header->ph_subsys = subsys;
	header->ph_mask = mask;
	header->ph_cpu_id = cfs_smp_processor_id();
	header->ph_type = 0;
	header->ph_sec = (__u32)tv.tv_sec;
	header->ph_usec = tv.tv_usec;
	header->ph_stack = stack;
	header->ph_pid = cfs_curproc_pid();
	header->ph_line_num = line;
	header->ph_extern_pid = (__u32)current_thread();
}
Ejemplo n.º 4
0
struct lc_watchdog *lc_watchdog_add(int timeout,
                                    void (*callback)(pid_t, void *),
                                    void *data)
{
        struct lc_watchdog *lcw = NULL;
        ENTRY;

        LIBCFS_ALLOC(lcw, sizeof(*lcw));
        if (lcw == NULL) {
                CDEBUG(D_INFO, "Could not allocate new lc_watchdog\n");
                RETURN(ERR_PTR(-ENOMEM));
        }

        cfs_spin_lock_init(&lcw->lcw_lock);
        lcw->lcw_refcount = 1; /* refcount for owner */
        lcw->lcw_task     = cfs_current();
        lcw->lcw_pid      = cfs_curproc_pid();
        lcw->lcw_callback = (callback != NULL) ? callback : lc_watchdog_dumplog;
        lcw->lcw_data     = data;
        lcw->lcw_state    = LC_WATCHDOG_DISABLED;

        CFS_INIT_LIST_HEAD(&lcw->lcw_list);
        cfs_timer_init(&lcw->lcw_timer, lcw_cb, lcw);

        cfs_down(&lcw_refcount_sem);
        if (++lcw_refcount == 1)
                lcw_dispatch_start();
        cfs_up(&lcw_refcount_sem);

        /* Keep this working in case we enable them by default */
        if (lcw->lcw_state == LC_WATCHDOG_ENABLED) {
                lcw->lcw_last_touched = cfs_time_current();
                cfs_timer_arm(&lcw->lcw_timer, cfs_time_seconds(timeout) +
                              cfs_time_current());
        }

        RETURN(lcw);
}
Ejemplo n.º 5
0
/* Must be called under the lov_stripe_lock() */
int lov_adjust_kms(struct obd_export *exp, struct lov_stripe_md *lsm,
                   obd_off size, int shrink)
{
    struct lov_oinfo *loi;
    int stripe = 0;
    __u64 kms;
    ENTRY;

    LASSERT_SPIN_LOCKED(&lsm->lsm_lock);
#ifdef __KERNEL__
    LASSERT(lsm->lsm_lock_owner == cfs_curproc_pid());
#endif

    if (shrink) {
        for (; stripe < lsm->lsm_stripe_count; stripe++) {
            struct lov_oinfo *loi = lsm->lsm_oinfo[stripe];
            kms = lov_size_to_stripe(lsm, size, stripe);
            CDEBUG(D_INODE,
                   "stripe %d KMS %sing "LPU64"->"LPU64"\n",
                   stripe, kms > loi->loi_kms ? "increas":"shrink",
                   loi->loi_kms, kms);
            loi_kms_set(loi, loi->loi_lvb.lvb_size = kms);
        }
        RETURN(0);
    }

    if (size > 0)
        stripe = lov_stripe_number(lsm, size - 1);
    kms = lov_size_to_stripe(lsm, size, stripe);
    loi = lsm->lsm_oinfo[stripe];

    CDEBUG(D_INODE, "stripe %d KMS %sincreasing "LPU64"->"LPU64"\n",
           stripe, kms > loi->loi_kms ? "" : "not ", loi->loi_kms, kms);
    if (kms > loi->loi_kms)
        loi_kms_set(loi, kms);

    RETURN(0);
}
Ejemplo n.º 6
0
static
int ll_getxattr_common(struct inode *inode, const char *name,
                       void *buffer, size_t size, __u64 valid)
{
        struct ll_sb_info *sbi = ll_i2sbi(inode);
        struct ptlrpc_request *req = NULL;
        struct mdt_body *body;
        int xattr_type, rc;
        void *xdata;
        struct obd_capa *oc;
        struct rmtacl_ctl_entry *rce = NULL;
        ENTRY;

        CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
               inode->i_ino, inode->i_generation, inode);

        /* listxattr have slightly different behavior from of ext3:
         * without 'user_xattr' ext3 will list all xattr names but
         * filtered out "^user..*"; we list them all for simplicity.
         */
        if (!name) {
                xattr_type = XATTR_OTHER_T;
                goto do_getxattr;
        }

        xattr_type = get_xattr_type(name);
        rc = xattr_type_filter(sbi, xattr_type);
        if (rc)
                RETURN(rc);

        /* b15587: ignore security.capability xattr for now */
        if ((xattr_type == XATTR_SECURITY_T &&
            strcmp(name, "security.capability") == 0))
                RETURN(-ENODATA);

        /* LU-549:  Disable security.selinux when selinux is disabled */
        if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() &&
            strcmp(name, "security.selinux") == 0)
                RETURN(-EOPNOTSUPP);

#ifdef CONFIG_FS_POSIX_ACL
        if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
            (xattr_type == XATTR_ACL_ACCESS_T ||
            xattr_type == XATTR_ACL_DEFAULT_T)) {
                rce = rct_search(&sbi->ll_rct, cfs_curproc_pid());
                if (rce == NULL ||
                    (rce->rce_ops != RMT_LSETFACL &&
                    rce->rce_ops != RMT_LGETFACL &&
                    rce->rce_ops != RMT_RSETFACL &&
                    rce->rce_ops != RMT_RGETFACL))
                        RETURN(-EOPNOTSUPP);
        }

        /* posix acl is under protection of LOOKUP lock. when calling to this,
         * we just have path resolution to the target inode, so we have great
         * chance that cached ACL is uptodate.
         */
        if (xattr_type == XATTR_ACL_ACCESS_T &&
            !(sbi->ll_flags & LL_SBI_RMT_CLIENT)) {
                struct ll_inode_info *lli = ll_i2info(inode);
                struct posix_acl *acl;

		spin_lock(&lli->lli_lock);
		acl = posix_acl_dup(lli->lli_posix_acl);
		spin_unlock(&lli->lli_lock);

                if (!acl)
                        RETURN(-ENODATA);

                rc = posix_acl_to_xattr(acl, buffer, size);
                posix_acl_release(acl);
                RETURN(rc);
        }
        if (xattr_type == XATTR_ACL_DEFAULT_T && !S_ISDIR(inode->i_mode))
                RETURN(-ENODATA);
#endif

do_getxattr:
        oc = ll_mdscapa_get(inode);
        rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
                         valid | (rce ? rce_ops2valid(rce->rce_ops) : 0),
                         name, NULL, 0, size, 0, &req);
        capa_put(oc);
        if (rc) {
                if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
                        LCONSOLE_INFO("Disabling user_xattr feature because "
                                      "it is not supported on the server\n");
                        sbi->ll_flags &= ~LL_SBI_USER_XATTR;
                }
                RETURN(rc);
        }

        body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
        LASSERT(body);

        /* only detect the xattr size */
        if (size == 0)
                GOTO(out, rc = body->eadatasize);

        if (size < body->eadatasize) {
                CERROR("server bug: replied size %u > %u\n",
                       body->eadatasize, (int)size);
                GOTO(out, rc = -ERANGE);
        }

        if (body->eadatasize == 0)
                GOTO(out, rc = -ENODATA);

        /* do not need swab xattr data */
        xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA,
                                             body->eadatasize);
        if (!xdata)
                GOTO(out, rc = -EFAULT);

#ifdef CONFIG_FS_POSIX_ACL
        if (body->eadatasize >= 0 && rce && rce->rce_ops == RMT_LSETFACL) {
                ext_acl_xattr_header *acl;

                acl = lustre_posix_acl_xattr_2ext((posix_acl_xattr_header *)xdata,
                                                  body->eadatasize);
                if (IS_ERR(acl))
                        GOTO(out, rc = PTR_ERR(acl));

                rc = ee_add(&sbi->ll_et, cfs_curproc_pid(), ll_inode2fid(inode),
                            xattr_type, acl);
                if (unlikely(rc < 0)) {
                        lustre_ext_acl_xattr_free(acl);
                        GOTO(out, rc);
                }
        }
#endif

        if (body->eadatasize == 0) {
                rc = -ENODATA;
        } else {
                LASSERT(buffer);
                memcpy(buffer, xdata, body->eadatasize);
                rc = body->eadatasize;
        }
        EXIT;
out:
        ptlrpc_req_finished(req);
        return rc;
}
Ejemplo n.º 7
0
static
int ll_setxattr_common(struct inode *inode, const char *name,
                       const void *value, size_t size,
                       int flags, __u64 valid)
{
        struct ll_sb_info *sbi = ll_i2sbi(inode);
        struct ptlrpc_request *req;
        int xattr_type, rc;
        struct obd_capa *oc;
        posix_acl_xattr_header *new_value = NULL;
        struct rmtacl_ctl_entry *rce = NULL;
        ext_acl_xattr_header *acl = NULL;
        const char *pv = value;
        ENTRY;

        xattr_type = get_xattr_type(name);
        rc = xattr_type_filter(sbi, xattr_type);
        if (rc)
                RETURN(rc);

        /* b10667: ignore lustre special xattr for now */
        if ((xattr_type == XATTR_TRUSTED_T && strcmp(name, "trusted.lov") == 0) ||
            (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0))
                RETURN(0);

        /* b15587: ignore security.capability xattr for now */
        if ((xattr_type == XATTR_SECURITY_T &&
            strcmp(name, "security.capability") == 0))
                RETURN(0);

        /* LU-549:  Disable security.selinux when selinux is disabled */
        if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() &&
            strcmp(name, "security.selinux") == 0)
                RETURN(-EOPNOTSUPP);

#ifdef CONFIG_FS_POSIX_ACL
        if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
            (xattr_type == XATTR_ACL_ACCESS_T ||
            xattr_type == XATTR_ACL_DEFAULT_T)) {
                rce = rct_search(&sbi->ll_rct, cfs_curproc_pid());
                if (rce == NULL ||
                    (rce->rce_ops != RMT_LSETFACL &&
                    rce->rce_ops != RMT_RSETFACL))
                        RETURN(-EOPNOTSUPP);

                if (rce->rce_ops == RMT_LSETFACL) {
                        struct eacl_entry *ee;

                        ee = et_search_del(&sbi->ll_et, cfs_curproc_pid(),
                                           ll_inode2fid(inode), xattr_type);
                        LASSERT(ee != NULL);
                        if (valid & OBD_MD_FLXATTR) {
                                acl = lustre_acl_xattr_merge2ext(
                                                (posix_acl_xattr_header *)value,
                                                size, ee->ee_acl);
                                if (IS_ERR(acl)) {
                                        ee_free(ee);
                                        RETURN(PTR_ERR(acl));
                                }
                                size =  CFS_ACL_XATTR_SIZE(\
                                                le32_to_cpu(acl->a_count), \
                                                ext_acl_xattr);
                                pv = (const char *)acl;
                        }
                        ee_free(ee);
                } else if (rce->rce_ops == RMT_RSETFACL) {
                        size = lustre_posix_acl_xattr_filter(
                                                (posix_acl_xattr_header *)value,
                                                size, &new_value);
                        if (unlikely(size < 0))
                                RETURN(size);

                        pv = (const char *)new_value;
                } else
                        RETURN(-EOPNOTSUPP);

                valid |= rce_ops2valid(rce->rce_ops);
        }
#endif
        oc = ll_mdscapa_get(inode);
        rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
                         valid, name, pv, size, 0, flags, ll_i2suppgid(inode),
                         &req);
        capa_put(oc);
#ifdef CONFIG_FS_POSIX_ACL
        if (new_value != NULL)
                lustre_posix_acl_xattr_free(new_value, size);
        if (acl != NULL)
                lustre_ext_acl_xattr_free(acl);
#endif
        if (rc) {
                if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
                        LCONSOLE_INFO("Disabling user_xattr feature because "
                                      "it is not supported on the server\n");
                        sbi->ll_flags &= ~LL_SBI_USER_XATTR;
                }
                RETURN(rc);
        }

        ptlrpc_req_finished(req);
        RETURN(0);
}
Ejemplo n.º 8
0
/** Merge the lock value block(&lvb) attributes and KMS from each of the
 * stripes in a file into a single lvb. It is expected that the caller
 * initializes the current atime, mtime, ctime to avoid regressing a more
 * uptodate time on the local client.
 */
int lov_merge_lvb_kms(struct lov_stripe_md *lsm,
                      struct ost_lvb *lvb, __u64 *kms_place)
{
    __u64 size = 0;
    __u64 kms = 0;
    __u64 blocks = 0;
    obd_time current_mtime = lvb->lvb_mtime;
    obd_time current_atime = lvb->lvb_atime;
    obd_time current_ctime = lvb->lvb_ctime;
    int i;
    int rc = 0;

    LASSERT_SPIN_LOCKED(&lsm->lsm_lock);
#ifdef __KERNEL__
    LASSERT(lsm->lsm_lock_owner == cfs_curproc_pid());
#endif

    CDEBUG(D_INODE, "MDT FID "DFID" initial value: s="LPU64" m="LPU64
           " a="LPU64" c="LPU64" b="LPU64"\n",
           lsm->lsm_object_seq, (__u32)lsm->lsm_object_id,
           (__u32)(lsm->lsm_object_id >> 32), lvb->lvb_size,
           lvb->lvb_mtime, lvb->lvb_atime, lvb->lvb_ctime, lvb->lvb_blocks);
    for (i = 0; i < lsm->lsm_stripe_count; i++) {
        struct lov_oinfo *loi = lsm->lsm_oinfo[i];
        obd_size lov_size, tmpsize;

        if (OST_LVB_IS_ERR(loi->loi_lvb.lvb_blocks)) {
            rc = OST_LVB_GET_ERR(loi->loi_lvb.lvb_blocks);
            continue;
        }

        tmpsize = loi->loi_kms;
        lov_size = lov_stripe_size(lsm, tmpsize, i);
        if (lov_size > kms)
            kms = lov_size;

        if (loi->loi_lvb.lvb_size > tmpsize)
            tmpsize = loi->loi_lvb.lvb_size;

        lov_size = lov_stripe_size(lsm, tmpsize, i);
        if (lov_size > size)
            size = lov_size;
        /* merge blocks, mtime, atime */
        blocks += loi->loi_lvb.lvb_blocks;
        if (loi->loi_lvb.lvb_mtime > current_mtime)
            current_mtime = loi->loi_lvb.lvb_mtime;
        if (loi->loi_lvb.lvb_atime > current_atime)
            current_atime = loi->loi_lvb.lvb_atime;
        if (loi->loi_lvb.lvb_ctime > current_ctime)
            current_ctime = loi->loi_lvb.lvb_ctime;
        CDEBUG(D_INODE, "MDT FID "DFID" on OST[%u]: s="LPU64" m="LPU64
               " a="LPU64" c="LPU64" b="LPU64"\n",
               lsm->lsm_object_seq, (__u32)lsm->lsm_object_id,
               (__u32)(lsm->lsm_object_id >> 32), loi->loi_ost_idx,
               loi->loi_lvb.lvb_size, loi->loi_lvb.lvb_mtime,
               loi->loi_lvb.lvb_atime, loi->loi_lvb.lvb_ctime,
               loi->loi_lvb.lvb_blocks);
    }

    *kms_place = kms;
    lvb->lvb_size = size;
    lvb->lvb_blocks = blocks;
    lvb->lvb_mtime = current_mtime;
    lvb->lvb_atime = current_atime;
    lvb->lvb_ctime = current_ctime;
    RETURN(rc);
}