static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) { struct mm_struct *mm = vma->vm_mm; struct file *file = vma->vm_file; struct proc_maps_private *priv = m->private; vm_flags_t flags = vma->vm_flags; unsigned long ino = 0; unsigned long long pgoff = 0; unsigned long start, end; dev_t dev = 0; const char *name = NULL; if (file) { struct inode *inode = file_inode(vma->vm_file); dev = inode->i_sb->s_dev; ino = inode->i_ino; pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; } /* We don't show the stack guard page in /proc/maps */ start = vma->vm_start; if (stack_guard_page_start(vma, start)) start += PAGE_SIZE; end = vma->vm_end; if (stack_guard_page_end(vma, end)) end -= PAGE_SIZE; seq_setwidth(m, 25 + sizeof(void *) * 6 - 1); seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ", start, end, flags & VM_READ ? 'r' : '-', flags & VM_WRITE ? 'w' : '-', flags & VM_EXEC ? 'x' : '-', flags & VM_MAYSHARE ? 's' : 'p', pgoff, MAJOR(dev), MINOR(dev), ino); /* * Print the dentry name for named mappings, and a * special [heap] marker for the heap: */ if (file) { seq_pad(m, ' '); seq_path(m, &file->f_path, "\n"); goto done; } if (vma->vm_ops && vma->vm_ops->name) { name = vma->vm_ops->name(vma); if (name) goto done; } name = arch_vma_name(vma); if (!name) { pid_t tid; if (!mm) { name = "[vdso]"; goto done; } if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { name = "[heap]"; goto done; } tid = pid_of_stack(priv, vma, is_pid); if (tid != 0) { /* * Thread stack in /proc/PID/task/TID/maps or * the main process stack. */ if (!is_pid || (vma->vm_start <= mm->start_stack && vma->vm_end >= mm->start_stack)) { name = "[stack]"; } else { /* Thread stack in /proc/PID/maps */ seq_pad(m, ' '); seq_printf(m, "[stack:%d]", tid); } } } done: if (name) { seq_pad(m, ' '); seq_puts(m, name); } seq_putc(m, '\n'); }
dev_t name_to_dev_t(char *name) { char s[32]; char *p; dev_t res = 0; int part; if (strncmp(name, "/dev/", 5) != 0) { unsigned maj, min; if (sscanf(name, "%u:%u", &maj, &min) == 2) { res = MKDEV(maj, min); if (maj != MAJOR(res) || min != MINOR(res)) goto fail; } else { res = new_decode_dev(simple_strtoul(name, &p, 16)); if (*p) goto fail; } goto done; } name += 5; res = Root_NFS; if (strcmp(name, "nfs") == 0) goto done; res = Root_RAM0; if (strcmp(name, "ram") == 0) goto done; if (strlen(name) > 31) goto fail; strcpy(s, name); for (p = s; *p; p++) if (*p == '/') *p = '!'; res = blk_lookup_devt(s, 0); if (res) goto done; /* * try non-existant, but valid partition, which may only exist * after revalidating the disk, like partitioned md devices */ while (p > s && isdigit(p[-1])) p--; if (p == s || !*p || *p == '0') goto fail; /* try disk name without <part number> */ part = simple_strtoul(p, NULL, 10); *p = '\0'; res = blk_lookup_devt(s, part); if (res) goto done; /* try disk name without p<part number> */ if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p') goto fail; p[-1] = '\0'; res = blk_lookup_devt(s, part); if (res) goto done; fail: return 0; done: return res; }
/* * First routine called when the kernel module is loaded */ static int __init tf_device_register(void) { int error; struct tf_device *dev = &g_tf_dev; dprintk(KERN_INFO "tf_device_register()\n"); /* * Initialize the device */ dev->dev_number = MKDEV(device_major_number, TF_DEVICE_MINOR_NUMBER); cdev_init(&dev->cdev, &g_tf_device_file_ops); dev->cdev.owner = THIS_MODULE; INIT_LIST_HEAD(&dev->connection_list); spin_lock_init(&dev->connection_list_lock); #if defined(MODULE) && defined(CONFIG_TF_ZEBRA) error = (*tf_comm_early_init)(); if (error) goto module_early_init_failed; error = tf_device_mshield_init(smc_mem); if (error) goto mshield_init_failed; #ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS error = tf_crypto_hmac_module_init(); if (error) goto hmac_init_failed; error = tf_self_test_register_device(); if (error) goto self_test_register_device_failed; #endif #endif /* register the sysfs object driver stats */ error = kobject_init_and_add(&dev->kobj, &tf_ktype, NULL, "%s", TF_DEVICE_BASE_NAME); if (error) { printk(KERN_ERR "tf_device_register(): " "kobject_init_and_add failed (error %d)!\n", error); kobject_put(&dev->kobj); goto kobject_init_and_add_failed; } /* * Register the system device. */ register_syscore_ops(&g_tf_device_syscore_ops); /* * Register the char device. */ printk(KERN_INFO "Registering char device %s (%u:%u)\n", TF_DEVICE_BASE_NAME, MAJOR(dev->dev_number), MINOR(dev->dev_number)); error = register_chrdev_region(dev->dev_number, 1, TF_DEVICE_BASE_NAME); if (error != 0) { printk(KERN_ERR "tf_device_register():" " register_chrdev_region failed (error %d)!\n", error); goto register_chrdev_region_failed; } error = cdev_add(&dev->cdev, dev->dev_number, 1); if (error != 0) { printk(KERN_ERR "tf_device_register(): " "cdev_add failed (error %d)!\n", error); goto cdev_add_failed; } /* * Initialize the communication with the Secure World. */ #ifdef CONFIG_TF_TRUSTZONE dev->sm.soft_int_irq = soft_interrupt; #endif error = tf_init(&g_tf_dev.sm); if (error != S_SUCCESS) { dprintk(KERN_ERR "tf_device_register(): " "tf_init failed (error %d)!\n", error); goto init_failed; } #ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS error = tf_self_test_post_init(&(dev_stats->kobj)); /* N.B. error > 0 indicates a POST failure, which will not prevent the module from loading. */ if (error < 0) { dprintk(KERN_ERR "tf_device_register(): " "tf_self_test_post_vectors failed (error %d)!\n", error); goto post_failed; } #endif #ifdef CONFIG_ANDROID tf_class = class_create(THIS_MODULE, TF_DEVICE_BASE_NAME); device_create(tf_class, NULL, dev->dev_number, NULL, TF_DEVICE_BASE_NAME); #endif #ifdef CONFIG_TF_ZEBRA /* * Initializes the /dev/tf_ctrl device node. */ error = tf_ctrl_device_register(); if (error) goto ctrl_failed; #endif #ifdef CONFIG_TF_DRIVER_DEBUG_SUPPORT address_cache_property((unsigned long) &tf_device_register); #endif /* * Successful completion. */ dprintk(KERN_INFO "tf_device_register(): Success\n"); return 0; /* * Error: undo all operations in the reverse order */ #ifdef CONFIG_TF_ZEBRA ctrl_failed: #endif #ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS tf_self_test_post_exit(); post_failed: #endif init_failed: cdev_del(&dev->cdev); cdev_add_failed: unregister_chrdev_region(dev->dev_number, 1); register_chrdev_region_failed: unregister_syscore_ops(&g_tf_device_syscore_ops); kobject_init_and_add_failed: kobject_del(&g_tf_dev.kobj); #if defined(MODULE) && defined(CONFIG_TF_ZEBRA) #ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS tf_self_test_unregister_device(); self_test_register_device_failed: tf_crypto_hmac_module_exit(); hmac_init_failed: #endif tf_device_mshield_exit(); mshield_init_failed: module_early_init_failed: #endif dprintk(KERN_INFO "tf_device_register(): Failure (error %d)\n", error); return error; }
/* Startup */ static int __init init_blkmtd(void) { struct file *file = NULL; struct inode *inode; mtd_raw_dev_data_t *rawdevice = NULL; int maj, min; int i, blocksize, blocksize_bits; loff_t size = 0; int readonly = 0; int erase_size = CONFIG_MTD_BLKDEV_ERASESIZE; kdev_t rdev; int err; int mode; int totalsize = 0, total_sectors = 0; int regions; mtd_info = NULL; // Check args if(device == 0) { printk("blkmtd: error, missing `device' name\n"); return 1; } if(ro) readonly = 1; if(erasesz) erase_size = erasesz; DEBUG(1, "blkmtd: got device = `%s' erase size = %dK readonly = %s\n", device, erase_size, readonly ? "yes" : "no"); // Get a handle on the device mode = (readonly) ? O_RDONLY : O_RDWR; file = filp_open(device, mode, 0); if(IS_ERR(file)) { DEBUG(2, "blkmtd: open_namei returned %ld\n", PTR_ERR(file)); return 1; } /* determine is this is a block device and if so get its major and minor numbers */ inode = file->f_dentry->d_inode; if(!S_ISBLK(inode->i_mode)) { printk("blkmtd: %s not a block device\n", device); filp_close(file, NULL); return 1; } rdev = inode->i_rdev; //filp_close(file, NULL); DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n", MAJOR(rdev), MINOR(rdev)); maj = MAJOR(rdev); min = MINOR(rdev); if(maj == MTD_BLOCK_MAJOR) { printk("blkmtd: attempting to use an MTD device as a block device\n"); return 1; } DEBUG(1, "blkmtd: devname = %s\n", bdevname(rdev)); blocksize = BLOCK_SIZE; if(bs) { blocksize = bs; } else { if (blksize_size[maj] && blksize_size[maj][min]) { DEBUG(2, "blkmtd: blksize_size = %d\n", blksize_size[maj][min]); blocksize = blksize_size[maj][min]; } } i = blocksize; blocksize_bits = 0; while(i != 1) { blocksize_bits++; i >>= 1; } if(count) { size = count; } else { if (blk_size[maj]) { size = ((loff_t) blk_size[maj][min] << BLOCK_SIZE_BITS) >> blocksize_bits; } } total_sectors = size; size *= blocksize; totalsize = size; DEBUG(1, "blkmtd: size = %ld\n", (long int)size); if(size == 0) { printk("blkmtd: cant determine size\n"); return 1; } rawdevice = (mtd_raw_dev_data_t *)kmalloc(sizeof(mtd_raw_dev_data_t), GFP_KERNEL); if(rawdevice == NULL) { err = -ENOMEM; goto init_err; } memset(rawdevice, 0, sizeof(mtd_raw_dev_data_t)); // get the block device rawdevice->binding = bdget(kdev_t_to_nr(MKDEV(maj, min))); err = blkdev_get(rawdevice->binding, mode, 0, BDEV_RAW); if (err) { goto init_err; } rawdevice->totalsize = totalsize; rawdevice->total_sectors = total_sectors; rawdevice->sector_size = blocksize; rawdevice->sector_bits = blocksize_bits; rawdevice->readonly = readonly; DEBUG(2, "sector_size = %d, sector_bits = %d\n", rawdevice->sector_size, rawdevice->sector_bits); mtd_info = (struct mtd_info *)kmalloc(sizeof(struct mtd_info), GFP_KERNEL); if (mtd_info == NULL) { err = -ENOMEM; goto init_err; } memset(mtd_info, 0, sizeof(*mtd_info)); // Setup the MTD structure mtd_info->name = "blkmtd block device"; if(readonly) { mtd_info->type = MTD_ROM; mtd_info->flags = MTD_CAP_ROM; mtd_info->erasesize = erase_size << 10; } else { mtd_info->type = MTD_RAM; mtd_info->flags = MTD_CAP_RAM; mtd_info->erasesize = erase_size << 10; } mtd_info->size = size; mtd_info->erase = blkmtd_erase; mtd_info->read = blkmtd_read; mtd_info->write = blkmtd_write; mtd_info->sync = blkmtd_sync; mtd_info->point = 0; mtd_info->unpoint = 0; mtd_info->priv = rawdevice; regions = calc_erase_regions(NULL, erase_size << 10, size); DEBUG(1, "blkmtd: init: found %d erase regions\n", regions); mtd_info->eraseregions = kmalloc(regions * sizeof(struct mtd_erase_region_info), GFP_KERNEL); if(mtd_info->eraseregions == NULL) { } mtd_info->numeraseregions = regions; calc_erase_regions(mtd_info->eraseregions, erase_size << 10, size); /* setup the page cache info */ INIT_LIST_HEAD(&rawdevice->as.clean_pages); INIT_LIST_HEAD(&rawdevice->as.dirty_pages); INIT_LIST_HEAD(&rawdevice->as.locked_pages); rawdevice->as.nrpages = 0; rawdevice->as.a_ops = &blkmtd_aops; rawdevice->as.host = inode; rawdevice->as.i_mmap = NULL; rawdevice->as.i_mmap_shared = NULL; spin_lock_init(&rawdevice->as.i_shared_lock); rawdevice->as.gfp_mask = GFP_KERNEL; rawdevice->file = file; file->private_data = rawdevice; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) mtd_info->module = THIS_MODULE; #endif if (add_mtd_device(mtd_info)) { err = -EIO; goto init_err; } init_waitqueue_head(&thr_wq); init_waitqueue_head(&mtbd_sync_wq); DEBUG(3, "blkmtd: init: kernel task @ %p\n", write_queue_task); DEBUG(2, "blkmtd: init: starting kernel task\n"); kernel_thread(write_queue_task, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); DEBUG(2, "blkmtd: init: started\n"); printk("blkmtd loaded: version = %s using %s erase_size = %dK %s\n", VERSION, device, erase_size, (readonly) ? "(read-only)" : ""); return 0; init_err: if(!rawdevice) { if(rawdevice->binding) blkdev_put(rawdevice->binding, BDEV_RAW); kfree(rawdevice); rawdevice = NULL; } if(mtd_info) { if(mtd_info->eraseregions) kfree(mtd_info->eraseregions); kfree(mtd_info); mtd_info = NULL; } return err; }
static ssize_t resume_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf,"%d:%d\n", MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); }
/** * <Ring 1> Make a available Orange'S FS in the disk. It will * - Write a super block to sector 1. * - Create three special files: dev_tty0, dev_tty1, dev_tty2 * - Create a file cmd.tar * - Create the inode map * - Create the sector map * - Create the inodes of the files * - Create `/', the root directory *****************************************************************************/ PRIVATE void mkfs() { MESSAGE driver_msg; int i, j; /************************/ /* super block */ /************************/ /* get the geometry of ROOTDEV */ struct part_info geo; driver_msg.type = DEV_IOCTL; driver_msg.DEVICE = MINOR(ROOT_DEV); driver_msg.REQUEST = DIOCTL_GET_GEO; driver_msg.BUF = &geo; driver_msg.PROC_NR = TASK_FS; assert(dd_map[MAJOR(ROOT_DEV)].driver_nr != INVALID_DRIVER); send_recv(BOTH, dd_map[MAJOR(ROOT_DEV)].driver_nr, &driver_msg); printl("{FS} dev size: 0x%x sectors\n", geo.size); int bits_per_sect = SECTOR_SIZE * 8; /* 8 bits per byte */ /* generate a super block */ struct super_block sb; sb.magic = MAGIC_V1; /* 0x111 */ sb.nr_inodes = bits_per_sect; sb.nr_inode_sects = sb.nr_inodes * INODE_SIZE / SECTOR_SIZE; sb.nr_sects = geo.size; /* partition size in sector */ sb.nr_imap_sects = 1; sb.nr_smap_sects = sb.nr_sects / bits_per_sect + 1; sb.n_1st_sect = 1 + 1 + /* boot sector & super block */ sb.nr_imap_sects + sb.nr_smap_sects + sb.nr_inode_sects; sb.root_inode = ROOT_INODE; sb.inode_size = INODE_SIZE; struct inode x; sb.inode_isize_off= (int)&x.i_size - (int)&x; sb.inode_start_off= (int)&x.i_start_sect - (int)&x; sb.dir_ent_size = DIR_ENTRY_SIZE; struct dir_entry de; sb.dir_ent_inode_off = (int)&de.inode_nr - (int)&de; sb.dir_ent_fname_off = (int)&de.name - (int)&de; memset(fsbuf, 0x90, SECTOR_SIZE); memcpy(fsbuf, &sb, SUPER_BLOCK_SIZE); /* write the super block */ WR_SECT(ROOT_DEV, 1); printl("{FS} devbase:0x%x00, sb:0x%x00, imap:0x%x00, smap:0x%x00\n" " inodes:0x%x00, 1st_sector:0x%x00\n", geo.base * 2, (geo.base + 1) * 2, (geo.base + 1 + 1) * 2, (geo.base + 1 + 1 + sb.nr_imap_sects) * 2, (geo.base + 1 + 1 + sb.nr_imap_sects + sb.nr_smap_sects) * 2, (geo.base + sb.n_1st_sect) * 2); /************************/ /* inode map */ /************************/ memset(fsbuf, 0, SECTOR_SIZE); for (i = 0; i < (NR_CONSOLES + 3); i++) fsbuf[0] |= 1 << i; assert(fsbuf[0] == 0x3F);/* 0011 1111 : * || |||| * || |||`--- bit 0 : reserved * || ||`---- bit 1 : the first inode, * || || which indicates `/' * || |`----- bit 2 : /dev_tty0 * || `------ bit 3 : /dev_tty1 * |`-------- bit 4 : /dev_tty2 * `--------- bit 5 : /cmd.tar */ WR_SECT(ROOT_DEV, 2); /************************/ /* secter map */ /************************/ memset(fsbuf, 0, SECTOR_SIZE); int nr_sects = NR_DEFAULT_FILE_SECTS + 1; /* ~~~~~~~~~~~~~~~~~~~|~ | * | `--- bit 0 is reserved * `-------- for `/' */ for (i = 0; i < nr_sects / 8; i++) fsbuf[i] = 0xFF; for (j = 0; j < nr_sects % 8; j++) fsbuf[i] |= (1 << j); WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects); /* zeromemory the rest sector-map */ memset(fsbuf, 0, SECTOR_SIZE); for (i = 1; i < sb.nr_smap_sects; i++) WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + i); /* cmd.tar */ /* make sure it'll not be overwritten by the disk log */ assert(INSTALL_START_SECT + INSTALL_NR_SECTS < sb.nr_sects - NR_SECTS_FOR_LOG); int bit_offset = INSTALL_START_SECT - sb.n_1st_sect + 1; /* sect M <-> bit (M - sb.n_1stsect + 1) */ int bit_off_in_sect = bit_offset % (SECTOR_SIZE * 8); int bit_left = INSTALL_NR_SECTS; int cur_sect = bit_offset / (SECTOR_SIZE * 8); RD_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect); while (bit_left) { int byte_off = bit_off_in_sect / 8; /* this line is ineffecient in a loop, but I don't care */ fsbuf[byte_off] |= 1 << (bit_off_in_sect % 8); bit_left--; bit_off_in_sect++; if (bit_off_in_sect == (SECTOR_SIZE * 8)) { WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect); cur_sect++; RD_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect); bit_off_in_sect = 0; } } WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect); /************************/ /* inodes */ /************************/ /* inode of `/' */ memset(fsbuf, 0, SECTOR_SIZE); struct inode * pi = (struct inode*)fsbuf; pi->i_mode = I_DIRECTORY; pi->i_size = DIR_ENTRY_SIZE * 5; /* 5 files: * `.', * `dev_tty0', `dev_tty1', `dev_tty2', * `cmd.tar' */ pi->i_start_sect = sb.n_1st_sect; pi->i_nr_sects = NR_DEFAULT_FILE_SECTS; /* inode of `/dev_tty0~2' */ for (i = 0; i < NR_CONSOLES; i++) { pi = (struct inode*)(fsbuf + (INODE_SIZE * (i + 1))); pi->i_mode = I_CHAR_SPECIAL; pi->i_size = 0; pi->i_start_sect = MAKE_DEV(DEV_CHAR_TTY, i); pi->i_nr_sects = 0; } /* inode of `/cmd.tar' */ pi = (struct inode*)(fsbuf + (INODE_SIZE * (NR_CONSOLES + 1))); pi->i_mode = I_REGULAR; pi->i_size = INSTALL_NR_SECTS * SECTOR_SIZE; pi->i_start_sect = INSTALL_START_SECT; pi->i_nr_sects = INSTALL_NR_SECTS; WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + sb.nr_smap_sects); /************************/ /* `/' */ /************************/ memset(fsbuf, 0, SECTOR_SIZE); struct dir_entry * pde = (struct dir_entry *)fsbuf; pde->inode_nr = 1; strcpy(pde->name, "."); /* dir entries of `/dev_tty0~2' */ for (i = 0; i < NR_CONSOLES; i++) { pde++; pde->inode_nr = i + 2; /* dev_tty0's inode_nr is 2 */ sprintf(pde->name, "dev_tty%d", i); } (++pde)->inode_nr = NR_CONSOLES + 2; strcpy(pde->name, "cmd.tar"); WR_SECT(ROOT_DEV, sb.n_1st_sect); }
static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt) { struct mount *r = real_mount(mnt); int err = 0; struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; struct super_block *sb = mnt_path.dentry->d_sb; if (sb->s_op->show_devname) { err = sb->s_op->show_devname(m, mnt_path.dentry); if (err) goto out; } else { mangle(m, r->mnt_devname ? r->mnt_devname : "none"); } seq_putc(m, ' '); seq_path(m, &mnt_path, " \t\n\\"); seq_putc(m, ' '); show_type(m, sb); seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw"); err = show_sb_opts(m, sb); if (err) goto out; show_mnt_opts(m, mnt); if (sb->s_op->show_options2) err = sb->s_op->show_options2(mnt, m, mnt_path.dentry); else if (sb->s_op->show_options) err = sb->s_op->show_options(m, mnt_path.dentry); seq_puts(m, " 0 0\n"); out: return err; } static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt) { struct proc_mounts *p = proc_mounts(m); struct mount *r = real_mount(mnt); struct super_block *sb = mnt->mnt_sb; struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; struct path root = p->root; int err = 0; seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id, MAJOR(sb->s_dev), MINOR(sb->s_dev)); if (sb->s_op->show_path) err = sb->s_op->show_path(m, mnt->mnt_root); else seq_dentry(m, mnt->mnt_root, " \t\n\\"); if (err) goto out; seq_putc(m, ' '); /* mountpoints outside of chroot jail will give SEQ_SKIP on this */ err = seq_path_root(m, &mnt_path, &root, " \t\n\\"); if (err) goto out; seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw"); show_mnt_opts(m, mnt); /* Tagged fields ("foo:X" or "bar") */ if (IS_MNT_SHARED(r)) seq_printf(m, " shared:%i", r->mnt_group_id); if (IS_MNT_SLAVE(r)) { int master = r->mnt_master->mnt_group_id; int dom = get_dominating_id(r, &p->root); seq_printf(m, " master:%i", master); if (dom && dom != master) seq_printf(m, " propagate_from:%i", dom); } if (IS_MNT_UNBINDABLE(r)) seq_puts(m, " unbindable"); /* Filesystem specific data */ seq_puts(m, " - "); show_type(m, sb); seq_putc(m, ' '); if (sb->s_op->show_devname) err = sb->s_op->show_devname(m, mnt->mnt_root); else mangle(m, r->mnt_devname ? r->mnt_devname : "none"); if (err) goto out; seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw"); err = show_sb_opts(m, sb); if (err) goto out; if (sb->s_op->show_options2) { err = sb->s_op->show_options2(mnt, m, mnt->mnt_root); } else if (sb->s_op->show_options) err = sb->s_op->show_options(m, mnt->mnt_root); seq_putc(m, '\n'); out: return err; } static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt) { struct mount *r = real_mount(mnt); struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; struct super_block *sb = mnt_path.dentry->d_sb; int err = 0; /* device */ if (sb->s_op->show_devname) { seq_puts(m, "device "); err = sb->s_op->show_devname(m, mnt_path.dentry); } else { if (r->mnt_devname) { seq_puts(m, "device "); mangle(m, r->mnt_devname); } else seq_puts(m, "no device"); } /* mount point */ seq_puts(m, " mounted on "); seq_path(m, &mnt_path, " \t\n\\"); seq_putc(m, ' '); /* file system type */ seq_puts(m, "with fstype "); show_type(m, sb); /* optional statistics */ if (sb->s_op->show_stats) { seq_putc(m, ' '); if (!err) err = sb->s_op->show_stats(m, mnt_path.dentry); } seq_putc(m, '\n'); return err; } static int mounts_open_common(struct inode *inode, struct file *file, int (*show)(struct seq_file *, struct vfsmount *)) { struct task_struct *task = get_proc_task(inode); struct nsproxy *nsp; struct mnt_namespace *ns = NULL; struct path root; struct proc_mounts *p; int ret = -EINVAL; if (!task) goto err; rcu_read_lock(); nsp = task_nsproxy(task); if (!nsp) { rcu_read_unlock(); put_task_struct(task); goto err; } ns = nsp->mnt_ns; if (!ns) { rcu_read_unlock(); put_task_struct(task); goto err; } get_mnt_ns(ns); rcu_read_unlock(); task_lock(task); if (!task->fs) { task_unlock(task); put_task_struct(task); ret = -ENOENT; goto err_put_ns; } get_fs_root(task->fs, &root); task_unlock(task); put_task_struct(task); ret = -ENOMEM; p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL); if (!p) goto err_put_path; file->private_data = &p->m; ret = seq_open(file, &mounts_op); if (ret) goto err_free; p->ns = ns; p->root = root; p->m.poll_event = ns->event; p->show = show; return 0; err_free: kfree(p); err_put_path: path_put(&root); err_put_ns: put_mnt_ns(ns); err: return ret; } static int mounts_release(struct inode *inode, struct file *file) { struct proc_mounts *p = proc_mounts(file->private_data); path_put(&p->root); put_mnt_ns(p->ns); return seq_release(inode, file); } static int mounts_open(struct inode *inode, struct file *file) { return mounts_open_common(inode, file, show_vfsmnt); } static int mountinfo_open(struct inode *inode, struct file *file) { return mounts_open_common(inode, file, show_mountinfo); } static int mountstats_open(struct inode *inode, struct file *file) { return mounts_open_common(inode, file, show_vfsstat); } const struct file_operations proc_mounts_operations = { .open = mounts_open, .read = seq_read, .llseek = seq_lseek, .release = mounts_release, .poll = mounts_poll, }; const struct file_operations proc_mountinfo_operations = { .open = mountinfo_open, .read = seq_read, .llseek = seq_lseek, .release = mounts_release, .poll = mounts_poll, }; const struct file_operations proc_mountstats_operations = { .open = mountstats_open, .read = seq_read, .llseek = seq_lseek, .release = mounts_release, };
struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info) { struct ptp_clock *ptp; int err = 0, index, major = MAJOR(ptp_devt); if (info->n_alarm > PTP_MAX_ALARMS) return ERR_PTR(-EINVAL); /* Find a free clock slot and reserve it. */ err = -EBUSY; mutex_lock(&ptp_clocks_mutex); index = find_first_zero_bit(ptp_clocks_map, PTP_MAX_CLOCKS); if (index < PTP_MAX_CLOCKS) set_bit(index, ptp_clocks_map); else goto no_slot; /* Initialize a clock structure. */ err = -ENOMEM; ptp = kzalloc(sizeof(struct ptp_clock), GFP_KERNEL); if (ptp == NULL) goto no_memory; ptp->clock.ops = ptp_clock_ops; ptp->clock.release = delete_ptp_clock; ptp->info = info; ptp->devid = MKDEV(major, index); ptp->index = index; spin_lock_init(&ptp->tsevq.lock); mutex_init(&ptp->tsevq_mux); init_waitqueue_head(&ptp->tsev_wq); /* Create a new device in our class. */ ptp->dev = device_create(ptp_class, NULL, ptp->devid, ptp, "ptp%d", ptp->index); if (IS_ERR(ptp->dev)) goto no_device; dev_set_drvdata(ptp->dev, ptp); err = ptp_populate_sysfs(ptp); if (err) goto no_sysfs; /* Register a new PPS source. */ if (info->pps) { struct pps_source_info pps; memset(&pps, 0, sizeof(pps)); snprintf(pps.name, PPS_MAX_NAME_LEN, "ptp%d", index); pps.mode = PTP_PPS_MODE; pps.owner = info->owner; ptp->pps_source = pps_register_source(&pps, PTP_PPS_DEFAULTS); if (!ptp->pps_source) { pr_err("failed to register pps source\n"); goto no_pps; } } /* Create a posix clock. */ err = posix_clock_register(&ptp->clock, ptp->devid); if (err) { pr_err("failed to create posix clock\n"); goto no_clock; } mutex_unlock(&ptp_clocks_mutex); return ptp; no_clock: if (ptp->pps_source) pps_unregister_source(ptp->pps_source); no_pps: ptp_cleanup_sysfs(ptp); no_sysfs: device_destroy(ptp_class, ptp->devid); no_device: mutex_destroy(&ptp->tsevq_mux); kfree(ptp); no_memory: clear_bit(index, ptp_clocks_map); no_slot: mutex_unlock(&ptp_clocks_mutex); return ERR_PTR(err); }
STATIC int xfs_vn_mknod( struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { struct inode *inode; struct xfs_inode *ip = NULL; struct posix_acl *default_acl = NULL; struct xfs_name name; int error; /* * Irix uses Missed'em'V split, but doesn't want to see * the upper 5 bits of (14bit) major. */ if (S_ISCHR(mode) || S_ISBLK(mode)) { if (unlikely(!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff)) return -EINVAL; rdev = sysv_encode_dev(rdev); } else { rdev = 0; } if (IS_POSIXACL(dir)) { default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT); if (IS_ERR(default_acl)) return PTR_ERR(default_acl); if (!default_acl) mode &= ~current_umask(); } xfs_dentry_to_name(&name, dentry); error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip); if (unlikely(error)) goto out_free_acl; inode = VFS_I(ip); error = xfs_init_security(inode, dir, &dentry->d_name); if (unlikely(error)) goto out_cleanup_inode; if (default_acl) { error = -xfs_inherit_acl(inode, default_acl); default_acl = NULL; if (unlikely(error)) goto out_cleanup_inode; } d_instantiate(dentry, inode); return -error; out_cleanup_inode: xfs_cleanup_inode(dir, inode, dentry); out_free_acl: posix_acl_release(default_acl); return -error; }
static ssize_t id_show(struct gfs2_sbd *sdp, char *buf) { return snprintf(buf, PAGE_SIZE, "%u:%u\n", MAJOR(sdp->sd_vfs->s_dev), MINOR(sdp->sd_vfs->s_dev)); }
/* * There's very little reason to use this, you should really * have a struct block_device just about everywhere and use * bdevname() instead. */ const char *__bdevname(dev_t dev, char *buffer) { scnprintf(buffer, BDEVNAME_SIZE, "unknown-block(%u,%u)", MAJOR(dev), MINOR(dev)); return buffer; }
int init_module(void) { int ret,cdev_ret; int counter; char tmp[512]; printk("dev_init\n"); mychardev=kmalloc( sizeof(struct my_char_dev) * num_of_dev, GFP_KERNEL ); ret=alloc_chrdev_region(&mychardev[0].dev,0, num_of_dev,DEVICE_NAME); if (ret<0) { printk(KERN_ALERT "Registering char device failed\n"); return -EFAULT; } Major=MAJOR(mychardev[0].dev); for(counter=0; counter < num_of_dev; counter++) { cdev_init( &mychardev[counter].mycdev, &fops); dev=MKDEV(Major, MINOR(dev)+counter); mychardev[counter].dev_open_counter=0; sema_init(&mychardev[counter].sem,1); cdev_ret=cdev_add( &mychardev[counter].mycdev, dev,1); } if(cdev_ret) goto cdev_error; printk(KERN_ALERT "cdev is added\n"); charmodule_class=class_create(THIS_MODULE, DEVICE_NAME); if (IS_ERR(charmodule_class)) goto class_create_error; printk(KERN_ALERT "%s class is created\n",DEVICE_NAME); for(counter=0; counter < num_of_dev; counter++) { memset(tmp,'\0',sizeof(tmp)); // sprintf(tmp,"%s",DEVICE_NAME); sprintf(tmp,"%s%d",DEVICE_NAME,counter); // sprintf(&tmpchar,"%d",counter); // strcat(tmp,&tmpchar); printk("device create %s\n",tmp); device_create(charmodule_class, NULL, MKDEV(Major,counter) , NULL,tmp); } printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major); printk(KERN_INFO "the driver, create a dev file at /dev/%s \n", DEVICE_NAME); printk(KERN_INFO "Try various minor numbers. Try to cat and echo to\n"); printk(KERN_INFO "the device file.\n"); printk(KERN_INFO "Remove the device file and module when done.\n"); return SUCCESS; class_create_error: for(counter=0; counter < num_of_dev; counter++) { cdev_del(&mychardev[counter].mycdev); } kfree(mychardev); cdev_error: unregister_chrdev_region(dev,num_of_dev); return -EFAULT; }
static dev_t try_name(char *name, int part) { char path[64]; char buf[32]; int range; dev_t res; char *s; int len; int fd; unsigned int maj, min; /* read device number from .../dev */ sprintf(path, "/sys/block/%s/dev", name); fd = sys_open(path, 0, 0); if (fd < 0) goto fail; len = sys_read(fd, buf, 32); sys_close(fd); if (len <= 0 || len == 32 || buf[len - 1] != '\n') goto fail; buf[len - 1] = '\0'; if (sscanf(buf, "%u:%u", &maj, &min) == 2) { /* * Try the %u:%u format -- see print_dev_t() */ res = MKDEV(maj, min); if (maj != MAJOR(res) || min != MINOR(res)) goto fail; } else { /* * Nope. Try old-style "0321" */ res = new_decode_dev(simple_strtoul(buf, &s, 16)); if (*s) goto fail; } /* if it's there and we are not looking for a partition - that's it */ if (!part) return res; /* otherwise read range from .../range */ sprintf(path, "/sys/block/%s/range", name); fd = sys_open(path, 0, 0); if (fd < 0) goto fail; len = sys_read(fd, buf, 32); sys_close(fd); if (len <= 0 || len == 32 || buf[len - 1] != '\n') goto fail; buf[len - 1] = '\0'; range = simple_strtoul(buf, &s, 10); if (*s) goto fail; /* if partition is within range - we got it */ if (part < range) return res + part; fail: return 0; }
dev_t name_to_dev_t(char *name) { char s[32]; char *p; dev_t res = 0; int part; #ifdef CONFIG_SYSFS int mkdir_err = sys_mkdir("/sys", 0700); if (sys_mount("sysfs", "/sys", "sysfs", 0, NULL) < 0) goto out; #endif if (strncmp(name, "/dev/", 5) != 0) { unsigned maj, min; if (sscanf(name, "%u:%u", &maj, &min) == 2) { res = MKDEV(maj, min); if (maj != MAJOR(res) || min != MINOR(res)) goto fail; } else { res = new_decode_dev(simple_strtoul(name, &p, 16)); if (*p) goto fail; } goto done; } name += 5; res = Root_NFS; if (strcmp(name, "nfs") == 0) goto done; res = Root_RAM0; if (strcmp(name, "ram") == 0) goto done; if (strlen(name) > 31) goto fail; strcpy(s, name); for (p = s; *p; p++) if (*p == '/') *p = '!'; res = try_name(s, 0); if (res) goto done; while (p > s && isdigit(p[-1])) p--; if (p == s || !*p || *p == '0') goto fail; part = simple_strtoul(p, NULL, 10); *p = '\0'; res = try_name(s, part); if (res) goto done; if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p') goto fail; p[-1] = '\0'; res = try_name(s, part); done: #ifdef CONFIG_SYSFS sys_umount("/sys", 0); out: if (!mkdir_err) sys_rmdir("/sys"); #endif return res; fail: res = 0; goto done; }
/** * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. * * @perm: Permission. * @param: Pointer to "struct tomoyo_acl_param". * * Returns 0 on success, negative value otherwise. */ static int tomoyo_update_path_number_acl(const u8 perm, struct tomoyo_acl_param *param) { struct tomoyo_path_number_acl e = { .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, .perm = perm }; int error; if (!tomoyo_parse_name_union(param, &e.name) || !tomoyo_parse_number_union(param, &e.number)) error = -EINVAL; else error = tomoyo_update_domain(&e.head, sizeof(e), param, tomoyo_same_path_number_acl, tomoyo_merge_path_number_acl); tomoyo_put_name_union(&e.name); tomoyo_put_number_union(&e.number); return error; } /** * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp". * * @type: Type of operation. * @path: Pointer to "struct path". * @number: Number. * * Returns 0 on success, negative value otherwise. */ int tomoyo_path_number_perm(const u8 type, struct path *path, unsigned long number) { struct tomoyo_request_info r; struct tomoyo_obj_info obj = { .path1 = { .mnt = path->mnt, .dentry = path->dentry }, }; int error = -ENOMEM; struct tomoyo_path_info buf; int idx; if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type]) == TOMOYO_CONFIG_DISABLED || !path->dentry) return 0; idx = tomoyo_read_lock(); if (!tomoyo_get_realpath(&buf, path)) goto out; r.obj = &obj; if (type == TOMOYO_TYPE_MKDIR) tomoyo_add_slash(&buf); r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; r.param.path_number.operation = type; r.param.path_number.filename = &buf; r.param.path_number.number = number; do { tomoyo_check_acl(&r, tomoyo_check_path_number_acl); error = tomoyo_audit_path_number_log(&r); } while (error == TOMOYO_RETRY_REQUEST); kfree(buf.name); out: tomoyo_read_unlock(idx); if (r.mode != TOMOYO_CONFIG_ENFORCING) error = 0; return error; } /** * tomoyo_check_open_permission - Check permission for "read" and "write". * * @domain: Pointer to "struct tomoyo_domain_info". * @path: Pointer to "struct path". * @flag: Flags for open(). * * Returns 0 on success, negative value otherwise. */ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, struct path *path, const int flag) { const u8 acc_mode = ACC_MODE(flag); int error = 0; struct tomoyo_path_info buf; struct tomoyo_request_info r; struct tomoyo_obj_info obj = { .path1 = { .mnt = path->mnt, .dentry = path->dentry }, }; int idx; buf.name = NULL; r.mode = TOMOYO_CONFIG_DISABLED; idx = tomoyo_read_lock(); if (acc_mode && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) != TOMOYO_CONFIG_DISABLED) { if (!tomoyo_get_realpath(&buf, path)) { error = -ENOMEM; goto out; } r.obj = &obj; if (acc_mode & MAY_READ) error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ, &buf); if (!error && (acc_mode & MAY_WRITE)) error = tomoyo_path_permission(&r, (flag & O_APPEND) ? TOMOYO_TYPE_APPEND : TOMOYO_TYPE_WRITE, &buf); } out: kfree(buf.name); tomoyo_read_unlock(idx); if (r.mode != TOMOYO_CONFIG_ENFORCING) error = 0; return error; } /** * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount". * * @operation: Type of operation. * @path: Pointer to "struct path". * @target: Symlink's target if @operation is TOMOYO_TYPE_SYMLINK, * NULL otherwise. * * Returns 0 on success, negative value otherwise. */ int tomoyo_path_perm(const u8 operation, const struct path *path, const char *target) { struct tomoyo_request_info r; struct tomoyo_obj_info obj = { .path1 = { .mnt = path->mnt, .dentry = path->dentry }, }; int error; struct tomoyo_path_info buf; bool is_enforce; struct tomoyo_path_info symlink_target; int idx; if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) == TOMOYO_CONFIG_DISABLED) return 0; is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING); error = -ENOMEM; buf.name = NULL; idx = tomoyo_read_lock(); if (!tomoyo_get_realpath(&buf, path)) goto out; r.obj = &obj; switch (operation) { case TOMOYO_TYPE_RMDIR: case TOMOYO_TYPE_CHROOT: tomoyo_add_slash(&buf); break; case TOMOYO_TYPE_SYMLINK: symlink_target.name = tomoyo_encode(target); if (!symlink_target.name) goto out; tomoyo_fill_path_info(&symlink_target); obj.symlink_target = &symlink_target; break; } error = tomoyo_path_permission(&r, operation, &buf); if (operation == TOMOYO_TYPE_SYMLINK) kfree(symlink_target.name); out: kfree(buf.name); tomoyo_read_unlock(idx); if (!is_enforce) error = 0; return error; } /** * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar". * * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK) * @path: Pointer to "struct path". * @mode: Create mode. * @dev: Device number. * * Returns 0 on success, negative value otherwise. */ int tomoyo_mkdev_perm(const u8 operation, struct path *path, const unsigned int mode, unsigned int dev) { struct tomoyo_request_info r; struct tomoyo_obj_info obj = { .path1 = { .mnt = path->mnt, .dentry = path->dentry }, }; int error = -ENOMEM; struct tomoyo_path_info buf; int idx; if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation]) == TOMOYO_CONFIG_DISABLED) return 0; idx = tomoyo_read_lock(); error = -ENOMEM; if (tomoyo_get_realpath(&buf, path)) { r.obj = &obj; dev = new_decode_dev(dev); r.param_type = TOMOYO_TYPE_MKDEV_ACL; r.param.mkdev.filename = &buf; r.param.mkdev.operation = operation; r.param.mkdev.mode = mode; r.param.mkdev.major = MAJOR(dev); r.param.mkdev.minor = MINOR(dev); tomoyo_check_acl(&r, tomoyo_check_mkdev_acl); error = tomoyo_audit_mkdev_log(&r); kfree(buf.name); } tomoyo_read_unlock(idx); if (r.mode != TOMOYO_CONFIG_ENFORCING) error = 0; return error; } /** * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". * * @operation: Type of operation. * @path1: Pointer to "struct path". * @path2: Pointer to "struct path". * * Returns 0 on success, negative value otherwise. */ int tomoyo_path2_perm(const u8 operation, struct path *path1, struct path *path2) { int error = -ENOMEM; struct tomoyo_path_info buf1; struct tomoyo_path_info buf2; struct tomoyo_request_info r; struct tomoyo_obj_info obj = { .path1 = { .mnt = path1->mnt, .dentry = path1->dentry }, .path2 = { .mnt = path2->mnt, .dentry = path2->dentry } };
static int __init mount_nfs_root(void) { char *root_dev, *root_data; unsigned int timeout; int try, err; err = nfs_root_data(&root_dev, &root_data); if (err != 0) return 0; /* * The server or network may not be ready, so try several * times. Stop after a few tries in case the client wants * to fall back to other boot methods. */ timeout = NFSROOT_TIMEOUT_MIN; for (try = 1; ; try++) { err = do_mount_root(root_dev, "nfs", root_mountflags, root_data); if (err == 0) return 1; if (try > NFSROOT_RETRY_MAX) break; /* Wait, in case the server refused us immediately */ ssleep(timeout); timeout <<= 1; if (timeout > NFSROOT_TIMEOUT_MAX) timeout = NFSROOT_TIMEOUT_MAX; } return 0; } #endif #if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD) void __init change_floppy(char *fmt, ...) { struct termios termios; char buf[80]; char c; int fd; va_list args; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0); if (fd >= 0) { sys_ioctl(fd, FDEJECT, 0); sys_close(fd); } printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf); fd = sys_open("/dev/console", O_RDWR, 0); if (fd >= 0) { sys_ioctl(fd, TCGETS, (long)&termios); termios.c_lflag &= ~ICANON; sys_ioctl(fd, TCSETSF, (long)&termios); sys_read(fd, &c, 1); termios.c_lflag |= ICANON; sys_ioctl(fd, TCSETSF, (long)&termios); sys_close(fd); } } #endif void __init mount_root(void) { #ifdef CONFIG_ROOT_NFS if (ROOT_DEV == Root_NFS) { if (mount_nfs_root()) return; printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); ROOT_DEV = Root_FD0; } #endif #ifdef CONFIG_BLK_DEV_FD if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { /* rd_doload is 2 for a dual initrd/ramload setup */ if (rd_doload==2) { if (rd_load_disk(1)) { ROOT_DEV = Root_RAM1; root_device_name = NULL; } } else change_floppy("root floppy"); } #endif #ifdef CONFIG_BLOCK create_dev("/dev/root", ROOT_DEV); mount_block_root("/dev/root", root_mountflags); #endif } /* * Prepare the namespace - decide what/where to mount, load ramdisks, etc. */ void __init prepare_namespace(void) { int is_floppy; if (root_delay) { printk(KERN_INFO "Waiting %d sec before mounting root device...\n", root_delay); ssleep(root_delay); } /* * wait for the known devices to complete their probing * * Note: this is a potential source of long boot delays. * For example, it is not atypical to wait 5 seconds here * for the touchpad of a laptop to initialize. */ wait_for_device_probe(); md_run_setup(); if (saved_root_name[0]) { root_device_name = saved_root_name; if (!strncmp(root_device_name, "mtd", 3) || !strncmp(root_device_name, "ubi", 3)) { mount_block_root(root_device_name, root_mountflags); goto out; } ROOT_DEV = name_to_dev_t(root_device_name); if (strncmp(root_device_name, "/dev/", 5) == 0) root_device_name += 5; } if (initrd_load()) goto out; /* wait for any asynchronous scanning to complete */ if ((ROOT_DEV == 0) && root_wait) { printk(KERN_INFO "Waiting for root device %s...\n", saved_root_name); while (driver_probe_done() != 0 || (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0) msleep(100); async_synchronize_full(); } is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; if (is_floppy && rd_doload && rd_load_disk(0)) ROOT_DEV = Root_RAM0; mount_root(); out: devtmpfs_mount("dev"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); }
static int rmidev_init_device(struct rmi_char_device *cd) { struct rmi_device *rmi_dev = cd->rmi_dev; struct rmidev_data *data; dev_t dev_no; int retval; struct device *device_ptr; if (rmidev_major_num) { dev_no = MKDEV(rmidev_major_num, cd->rmi_dev->number); retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME); } else { retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME); /* let kernel allocate a major for us */ rmidev_major_num = MAJOR(dev_no); printk( "DTUCH : Device(%s) major number of rmidev(%d)\n", dev_name( &rmi_dev->dev ), rmidev_major_num ); } if (retval < 0) { printk( "DTUCH : Device(%s) failed to get minor dev number%d(%d)\n", dev_name( &rmi_dev->dev ), cd->rmi_dev->number, retval ); return retval; } else printk( "DTUCH : Device(%s) allocated rmidev %d %d\n", dev_name( &rmi_dev->dev ), MAJOR( dev_no ), MINOR( dev_no ) ); data = kzalloc(sizeof(struct rmidev_data), GFP_KERNEL); if (!data) { printk( "DTUCH : Device(%s) failed to allocate rmidev_data\n", dev_name( &rmi_dev->dev ) ); /* unregister the char device region */ __unregister_chrdev(rmidev_major_num, MINOR(dev_no), 1, CHAR_DEVICE_NAME); return -ENOMEM; } mutex_init(&data->file_mutex); data->rmi_dev = cd->rmi_dev; cd->data = data; cdev_init(&data->main_dev, &rmidev_fops); retval = cdev_add(&data->main_dev, dev_no, 1); if (retval) { printk( "DTUCH : Device(%s) error %d adding rmi_char_dev\n", dev_name( &cd->rmi_dev->dev ), retval ); rmidev_device_cleanup(data); return retval; } dev_set_name(&cd->dev, "rmidev%d", MINOR(dev_no)); data->device_class = rmidev_device_class; device_ptr = device_create( data->device_class, NULL, dev_no, NULL, CHAR_DEVICE_NAME"%d", MINOR(dev_no)); if (IS_ERR(device_ptr)) { printk( "DTUCH : Device(%s) failed to create rmi device\n", dev_name( &cd->rmi_dev->dev ) ); rmidev_device_cleanup(data); return -ENODEV; } return 0; }
static int watchdog_cdev_register(struct watchdog_device *wdd, dev_t devno) { struct watchdog_core_data *wd_data; int err; wd_data = kzalloc(sizeof(struct watchdog_core_data), GFP_KERNEL); if (!wd_data) return -ENOMEM; kref_init(&wd_data->kref); mutex_init(&wd_data->lock); wd_data->wdd = wdd; wdd->wd_data = wd_data; if (IS_ERR_OR_NULL(watchdog_kworker)) return -ENODEV; kthread_init_work(&wd_data->work, watchdog_ping_work); hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); wd_data->timer.function = watchdog_timer_expired; if (wdd->id == 0) { old_wd_data = wd_data; watchdog_miscdev.parent = wdd->parent; err = misc_register(&watchdog_miscdev); if (err != 0) { pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n", wdd->info->identity, WATCHDOG_MINOR, err); if (err == -EBUSY) pr_err("%s: a legacy watchdog module is probably present.\n", wdd->info->identity); old_wd_data = NULL; kfree(wd_data); return err; } } /* Fill in the data structures */ cdev_init(&wd_data->cdev, &watchdog_fops); wd_data->cdev.owner = wdd->ops->owner; /* Add the device */ err = cdev_add(&wd_data->cdev, devno, 1); if (err) { pr_err("watchdog%d unable to add device %d:%d\n", wdd->id, MAJOR(watchdog_devt), wdd->id); if (wdd->id == 0) { misc_deregister(&watchdog_miscdev); old_wd_data = NULL; kref_put(&wd_data->kref, watchdog_core_data_release); } return err; } /* Record time of most recent heartbeat as 'just before now'. */ wd_data->last_hw_keepalive = ktime_sub(ktime_get(), 1); /* * If the watchdog is running, prevent its driver from being unloaded, * and schedule an immediate ping. */ if (watchdog_hw_running(wdd)) { __module_get(wdd->ops->owner); kref_get(&wd_data->kref); if (handle_boot_enabled) hrtimer_start(&wd_data->timer, 0, HRTIMER_MODE_REL); else pr_info("watchdog%d running and kernel based pre-userspace handler disabled\n", wdd->id); } return 0; }
static int nfs3_proc_remove(struct inode *dir, struct qstr *name) { struct nfs_removeargs arg = { .fh = NFS_FH(dir), .name.len = name->len, .name.name = name->name, }; struct nfs_removeres res; struct rpc_message msg = { .rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE], .rpc_argp = &arg, .rpc_resp = &res, }; int status = -ENOMEM; dprintk("NFS call remove %s\n", name->name); res.dir_attr = nfs_alloc_fattr(); if (res.dir_attr == NULL) goto out; status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); nfs_post_op_update_inode(dir, res.dir_attr); nfs_free_fattr(res.dir_attr); out: dprintk("NFS reply remove: %d\n", status); return status; } static void nfs3_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) { msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE]; } static int nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir) { struct nfs_removeres *res; if (nfs3_async_handle_jukebox(task, dir)) return 0; res = task->tk_msg.rpc_resp; nfs_post_op_update_inode(dir, res->dir_attr); return 1; } static void nfs3_proc_rename_setup(struct rpc_message *msg, struct inode *dir) { msg->rpc_proc = &nfs3_procedures[NFS3PROC_RENAME]; } static int nfs3_proc_rename_done(struct rpc_task *task, struct inode *old_dir, struct inode *new_dir) { struct nfs_renameres *res; if (nfs3_async_handle_jukebox(task, old_dir)) return 0; res = task->tk_msg.rpc_resp; nfs_post_op_update_inode(old_dir, res->old_fattr); nfs_post_op_update_inode(new_dir, res->new_fattr); return 1; } static int nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name, struct inode *new_dir, struct qstr *new_name) { struct nfs_renameargs arg = { .old_dir = NFS_FH(old_dir), .old_name = old_name, .new_dir = NFS_FH(new_dir), .new_name = new_name, }; struct nfs_renameres res; struct rpc_message msg = { .rpc_proc = &nfs3_procedures[NFS3PROC_RENAME], .rpc_argp = &arg, .rpc_resp = &res, }; int status = -ENOMEM; dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); res.old_fattr = nfs_alloc_fattr(); res.new_fattr = nfs_alloc_fattr(); if (res.old_fattr == NULL || res.new_fattr == NULL) goto out; status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0); nfs_post_op_update_inode(old_dir, res.old_fattr); nfs_post_op_update_inode(new_dir, res.new_fattr); out: nfs_free_fattr(res.old_fattr); nfs_free_fattr(res.new_fattr); dprintk("NFS reply rename: %d\n", status); return status; } static int nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) { struct nfs3_linkargs arg = { .fromfh = NFS_FH(inode), .tofh = NFS_FH(dir), .toname = name->name, .tolen = name->len }; struct nfs3_linkres res; struct rpc_message msg = { .rpc_proc = &nfs3_procedures[NFS3PROC_LINK], .rpc_argp = &arg, .rpc_resp = &res, }; int status = -ENOMEM; dprintk("NFS call link %s\n", name->name); res.fattr = nfs_alloc_fattr(); res.dir_attr = nfs_alloc_fattr(); if (res.fattr == NULL || res.dir_attr == NULL) goto out; status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); nfs_post_op_update_inode(dir, res.dir_attr); nfs_post_op_update_inode(inode, res.fattr); out: nfs_free_fattr(res.dir_attr); nfs_free_fattr(res.fattr); dprintk("NFS reply link: %d\n", status); return status; } static int nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, unsigned int len, struct iattr *sattr) { struct nfs3_createdata *data; int status = -ENOMEM; if (len > NFS3_MAXPATHLEN) return -ENAMETOOLONG; dprintk("NFS call symlink %s\n", dentry->d_name.name); data = nfs3_alloc_createdata(); if (data == NULL) goto out; data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK]; data->arg.symlink.fromfh = NFS_FH(dir); data->arg.symlink.fromname = dentry->d_name.name; data->arg.symlink.fromlen = dentry->d_name.len; data->arg.symlink.pages = &page; data->arg.symlink.pathlen = len; data->arg.symlink.sattr = sattr; status = nfs3_do_create(dir, dentry, data); nfs3_free_createdata(data); out: dprintk("NFS reply symlink: %d\n", status); return status; } static int nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) { struct nfs3_createdata *data; int mode = sattr->ia_mode; int status = -ENOMEM; dprintk("NFS call mkdir %s\n", dentry->d_name.name); sattr->ia_mode &= ~current_umask(); data = nfs3_alloc_createdata(); if (data == NULL) goto out; data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR]; data->arg.mkdir.fh = NFS_FH(dir); data->arg.mkdir.name = dentry->d_name.name; data->arg.mkdir.len = dentry->d_name.len; data->arg.mkdir.sattr = sattr; status = nfs3_do_create(dir, dentry, data); if (status != 0) goto out; status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); out: nfs3_free_createdata(data); dprintk("NFS reply mkdir: %d\n", status); return status; } static int nfs3_proc_rmdir(struct inode *dir, struct qstr *name) { struct nfs_fattr *dir_attr; struct nfs3_diropargs arg = { .fh = NFS_FH(dir), .name = name->name, .len = name->len }; struct rpc_message msg = { .rpc_proc = &nfs3_procedures[NFS3PROC_RMDIR], .rpc_argp = &arg, }; int status = -ENOMEM; dprintk("NFS call rmdir %s\n", name->name); dir_attr = nfs_alloc_fattr(); if (dir_attr == NULL) goto out; msg.rpc_resp = dir_attr; status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); nfs_post_op_update_inode(dir, dir_attr); nfs_free_fattr(dir_attr); out: dprintk("NFS reply rmdir: %d\n", status); return status; } /* * The READDIR implementation is somewhat hackish - we pass the user buffer * to the encode function, which installs it in the receive iovec. * The decode function itself doesn't perform any decoding, it just makes * sure the reply is syntactically correct. * * Also note that this implementation handles both plain readdir and * readdirplus. */ static int nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, u64 cookie, struct page **pages, unsigned int count, int plus) { struct inode *dir = dentry->d_inode; __be32 *verf = NFS_I(dir)->cookieverf; struct nfs3_readdirargs arg = { .fh = NFS_FH(dir), .cookie = cookie, .verf = {verf[0], verf[1]}, .plus = plus, .count = count, .pages = pages }; struct nfs3_readdirres res = { .verf = verf, .plus = plus }; struct rpc_message msg = { .rpc_proc = &nfs3_procedures[NFS3PROC_READDIR], .rpc_argp = &arg, .rpc_resp = &res, .rpc_cred = cred }; int status = -ENOMEM; if (plus) msg.rpc_proc = &nfs3_procedures[NFS3PROC_READDIRPLUS]; dprintk("NFS call readdir%s %d\n", plus? "plus" : "", (unsigned int) cookie); res.dir_attr = nfs_alloc_fattr(); if (res.dir_attr == NULL) goto out; status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); nfs_invalidate_atime(dir); nfs_refresh_inode(dir, res.dir_attr); nfs_free_fattr(res.dir_attr); out: dprintk("NFS reply readdir%s: %d\n", plus? "plus" : "", status); return status; } static int nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, dev_t rdev) { struct nfs3_createdata *data; mode_t mode = sattr->ia_mode; int status = -ENOMEM; dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name, MAJOR(rdev), MINOR(rdev)); sattr->ia_mode &= ~current_umask(); data = nfs3_alloc_createdata(); if (data == NULL) goto out; data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD]; data->arg.mknod.fh = NFS_FH(dir); data->arg.mknod.name = dentry->d_name.name; data->arg.mknod.len = dentry->d_name.len; data->arg.mknod.sattr = sattr; data->arg.mknod.rdev = rdev; switch (sattr->ia_mode & S_IFMT) { case S_IFBLK: data->arg.mknod.type = NF3BLK; break; case S_IFCHR: data->arg.mknod.type = NF3CHR; break; case S_IFIFO: data->arg.mknod.type = NF3FIFO; break; case S_IFSOCK: data->arg.mknod.type = NF3SOCK; break; default: status = -EINVAL; goto out; } status = nfs3_do_create(dir, dentry, data); if (status != 0) goto out; status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); out: nfs3_free_createdata(data); dprintk("NFS reply mknod: %d\n", status); return status; } static int nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *stat) { struct rpc_message msg = { .rpc_proc = &nfs3_procedures[NFS3PROC_FSSTAT], .rpc_argp = fhandle, .rpc_resp = stat, }; int status; dprintk("NFS call fsstat\n"); nfs_fattr_init(stat->fattr); status = rpc_call_sync(server->client, &msg, 0); dprintk("NFS reply fsstat: %d\n", status); return status; } static int do_proc_fsinfo(struct rpc_clnt *client, struct nfs_fh *fhandle, struct nfs_fsinfo *info) { struct rpc_message msg = { .rpc_proc = &nfs3_procedures[NFS3PROC_FSINFO], .rpc_argp = fhandle, .rpc_resp = info, }; int status; dprintk("NFS call fsinfo\n"); nfs_fattr_init(info->fattr); status = rpc_call_sync(client, &msg, 0); dprintk("NFS reply fsinfo: %d\n", status); return status; } /* * Bare-bones access to fsinfo: this is for nfs_get_root/nfs_get_sb via * nfs_create_server */ static int nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *info) { int status; status = do_proc_fsinfo(server->client, fhandle, info); if (status && server->nfs_client->cl_rpcclient != server->client) status = do_proc_fsinfo(server->nfs_client->cl_rpcclient, fhandle, info); return status; } static int nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_pathconf *info) { struct rpc_message msg = { .rpc_proc = &nfs3_procedures[NFS3PROC_PATHCONF], .rpc_argp = fhandle, .rpc_resp = info, }; int status; dprintk("NFS call pathconf\n"); nfs_fattr_init(info->fattr); status = rpc_call_sync(server->client, &msg, 0); dprintk("NFS reply pathconf: %d\n", status); return status; } static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data) { struct inode *inode = data->header->inode; if (nfs3_async_handle_jukebox(task, inode)) return -EAGAIN; nfs_invalidate_atime(inode); nfs_refresh_inode(inode, &data->fattr); return 0; } static void nfs3_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) { msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ]; } static int nfs3_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) { rpc_call_start(task); return 0; }
#include <sys/stat.h> #include <sys/socket.h> #include <sys/un.h> #include <sys/ioctl.h> #include <sys/mount.h> #include <sys/uio.h> #include <sys/utsname.h> #include <sys/vfs.h> #include "os.h" #include "user.h" #include "kern_util.h" static void copy_stat(struct uml_stat *dst, struct stat64 *src) { *dst = ((struct uml_stat) { .ust_major = MAJOR(src->st_dev), /* device */ .ust_minor = MINOR(src->st_dev), .ust_ino = src->st_ino, /* inode */ .ust_mode = src->st_mode, /* protection */ .ust_nlink = src->st_nlink, /* number of hard links */ .ust_uid = src->st_uid, /* user ID of owner */ .ust_gid = src->st_gid, /* group ID of owner */ .ust_size = src->st_size, /* total size, in bytes */ .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */ .ust_blocks = src->st_blocks, /* number of blocks allocated */ .ust_atime = src->st_atime, /* time of last access */ .ust_mtime = src->st_mtime, /* time of last modification */ .ust_ctime = src->st_ctime, /* time of last change */ .ust_rmajor = MAJOR(src->st_rdev), .ust_rminor = MINOR(src->st_rdev), });
static int frandom_init_module(void) { int result; /* The buffer size MUST be at least 256 bytes, because we assume that minimal length in init_rand_state(). */ if (frandom_bufsize < 256) { pr_err("frandom: Invalid frandom_bufsize: %d\n", frandom_bufsize); return -EINVAL; } if ((frandom_chunklimit != 0) && (frandom_chunklimit < 256)) { pr_err("frandom: Invalid frandom_chunklimit: %d\n", frandom_chunklimit); return -EINVAL; } erandom_state = kmalloc(sizeof(struct frandom_state), GFP_KERNEL); if (!erandom_state) return -ENOMEM; /* This specific buffer is only used for seeding, so we need 256 bytes exactly */ erandom_state->buf = kmalloc(256, GFP_KERNEL); if (!erandom_state->buf) { kfree(erandom_state); return -ENOMEM; } sema_init(&erandom_state->sem, 1); /* Init semaphore as a mutex */ erandom_seeded = 0; frandom_class = class_create(THIS_MODULE, "fastrng"); if (IS_ERR(frandom_class)) { result = PTR_ERR(frandom_class); pr_warn("frandom: Failed to register class fastrng\n"); goto error0; } /* * Register your major, and accept a dynamic number. This is the * first thing to do, in order to avoid releasing other module's * fops in frandom_cleanup_module() */ result = alloc_chrdev_region(&frandom_devt, 0, NR_FRANDOM_DEVS, "frandom"); if (result < 0) { pr_warn("frandom: failed to alloc frandom region\n"); goto error1; } frandom_minor = MINOR(frandom_devt); erandom_minor = frandom_minor + 1; erandom_devt = MKDEV(MAJOR(frandom_devt), erandom_minor); cdev_init(&frandom_cdev, &frandom_fops); frandom_cdev.owner = THIS_MODULE; result = cdev_add(&frandom_cdev, frandom_devt, 1); if (result) { pr_warn("frandom: Failed to add cdev for /dev/frandom\n"); goto error2; } frandom_device = device_create(frandom_class, NULL, frandom_devt, NULL, "frandom"); if (IS_ERR(frandom_device)) { pr_warn("frandom: Failed to create frandom device\n"); goto error3; } cdev_init(&erandom_cdev, &frandom_fops); erandom_cdev.owner = THIS_MODULE; result = cdev_add(&erandom_cdev, erandom_devt, 1); if (result) { pr_warn("frandom: Failed to add cdev for /dev/erandom\n"); goto error4; } erandom_device = device_create(frandom_class, NULL, erandom_devt, NULL, "erandom"); if (IS_ERR(erandom_device)) { pr_warn("frandom: Failed to create erandom device\n"); goto error5; } return 0; /* succeed */ error5: cdev_del(&erandom_cdev); error4: device_destroy(frandom_class, frandom_devt); error3: cdev_del(&frandom_cdev); error2: unregister_chrdev_region(frandom_devt, NR_FRANDOM_DEVS); error1: class_destroy(frandom_class); error0: kfree(erandom_state->buf); kfree(erandom_state); return result; }
STATIC int linvfs_mknod( struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { struct inode *ip; vattr_t va; vnode_t *vp = NULL, *dvp = LINVFS_GET_VP(dir); xfs_acl_t *default_acl = NULL; attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; int error; /* * Irix uses Missed'em'V split, but doesn't want to see * the upper 5 bits of (14bit) major. */ if (!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff) return -EINVAL; if (test_default_acl && test_default_acl(dvp)) { if (!_ACL_ALLOC(default_acl)) return -ENOMEM; if (!_ACL_GET_DEFAULT(dvp, default_acl)) { _ACL_FREE(default_acl); default_acl = NULL; } } if (IS_POSIXACL(dir) && !default_acl && has_fs_struct(current)) mode &= ~current->fs->umask; memset(&va, 0, sizeof(va)); va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; va.va_mode = mode; switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: va.va_rdev = sysv_encode_dev(rdev); va.va_mask |= XFS_AT_RDEV; /*FALLTHROUGH*/ case S_IFREG: VOP_CREATE(dvp, dentry, &va, &vp, NULL, error); break; case S_IFDIR: VOP_MKDIR(dvp, dentry, &va, &vp, NULL, error); break; default: error = EINVAL; break; } if (!error) { error = linvfs_init_security(vp, dir); if (error) cleanup_inode(dvp, vp, dentry, mode); } if (default_acl) { if (!error) { error = _ACL_INHERIT(vp, &va, default_acl); if (!error) VMODIFY(vp); else cleanup_inode(dvp, vp, dentry, mode); } _ACL_FREE(default_acl); } if (!error) { ASSERT(vp); ip = LINVFS_GET_IP(vp); if (S_ISCHR(mode) || S_ISBLK(mode)) ip->i_rdev = rdev; else if (S_ISDIR(mode)) validate_fields(ip); d_instantiate(dentry, ip); validate_fields(dir); } return -error; }
/** * software_resume - Resume from a saved hibernation image. * * This routine is called as a late initcall, when all devices have been * discovered and initialized already. * * The image reading code is called to see if there is a hibernation image * available for reading. If that is the case, devices are quiesced and the * contents of memory is restored from the saved image. * * If this is successful, control reappears in the restored target kernel in * hibernation_snaphot() which returns to hibernate(). Otherwise, the routine * attempts to recover gracefully and make the kernel return to the normal mode * of operation. */ static int software_resume(void) { int error; unsigned int flags; /* * If the user said "noresume".. bail out early. */ if (noresume || !capable(CAP_COMPROMISE_KERNEL)) return 0; /* * name_to_dev_t() below takes a sysfs buffer mutex when sysfs * is configured into the kernel. Since the regular hibernate * trigger path is via sysfs which takes a buffer mutex before * calling hibernate functions (which take pm_mutex) this can * cause lockdep to complain about a possible ABBA deadlock * which cannot happen since we're in the boot code here and * sysfs can't be invoked yet. Therefore, we use a subclass * here to avoid lockdep complaining. */ mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING); if (swsusp_resume_device) goto Check_image; if (!strlen(resume_file)) { error = -ENOENT; goto Unlock; } pr_debug("PM: Checking hibernation image partition %s\n", resume_file); if (resume_delay) { printk(KERN_INFO "Waiting %dsec before reading resume device...\n", resume_delay); ssleep(resume_delay); } /* Check if the device is there */ swsusp_resume_device = name_to_dev_t(resume_file); /* * name_to_dev_t is ineffective to verify parition if resume_file is in * integer format. (e.g. major:minor) */ if (isdigit(resume_file[0]) && resume_wait) { int partno; while (!get_gendisk(swsusp_resume_device, &partno)) msleep(10); } if (!swsusp_resume_device) { /* * Some device discovery might still be in progress; we need * to wait for this to finish. */ wait_for_device_probe(); if (resume_wait) { while ((swsusp_resume_device = name_to_dev_t(resume_file)) == 0) msleep(10); async_synchronize_full(); } swsusp_resume_device = name_to_dev_t(resume_file); if (!swsusp_resume_device) { error = -ENODEV; goto Unlock; } } Check_image: pr_debug("PM: Hibernation image partition %d:%d present\n", MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); pr_debug("PM: Looking for hibernation image.\n"); error = swsusp_check(); if (error) goto Unlock; /* The snapshot device should not be opened while we're running */ if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { error = -EBUSY; swsusp_close(FMODE_READ); goto Unlock; } pm_prepare_console(); error = pm_notifier_call_chain(PM_RESTORE_PREPARE); if (error) goto close_finish; error = create_basic_memory_bitmaps(); if (error) goto close_finish; pr_debug("PM: Preparing processes for restore.\n"); error = freeze_processes(); if (error) { swsusp_close(FMODE_READ); goto Done; } pr_debug("PM: Loading hibernation image.\n"); error = swsusp_read(&flags); swsusp_close(FMODE_READ); if (!error) hibernation_restore(flags & SF_PLATFORM_MODE); printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n"); swsusp_free(); thaw_processes(); Done: free_basic_memory_bitmaps(); Finish: pm_notifier_call_chain(PM_POST_RESTORE); pm_restore_console(); atomic_inc(&snapshot_device_available); /* For success case, the suspend path will release the lock */ Unlock: mutex_unlock(&pm_mutex); pr_debug("PM: Hibernation image not present or could not be loaded.\n"); return error; close_finish: swsusp_close(FMODE_READ); goto Finish; }
int fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh) { /* ref_fh is a reference file handle. * if it is non-null and for the same filesystem, then we should compose * a filehandle which is of the same version, where possible. * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca * Then create a 32byte filehandle using nfs_fhbase_old * */ u8 ref_fh_version = 0; u8 ref_fh_fsid_type = 0; struct inode * inode = dentry->d_inode; struct dentry *parent = dentry->d_parent; __u32 *datap; dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev; dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n", MAJOR(ex_dev), MINOR(ex_dev), (long) exp->ex_dentry->d_inode->i_ino, parent->d_name.name, dentry->d_name.name, (inode ? inode->i_ino : 0)); if (ref_fh && ref_fh->fh_export == exp) { ref_fh_version = ref_fh->fh_handle.fh_version; if (ref_fh_version == 0xca) ref_fh_fsid_type = 0; else ref_fh_fsid_type = ref_fh->fh_handle.fh_fsid_type; if (ref_fh_fsid_type > 3) ref_fh_fsid_type = 0; /* make sure ref_fh type works for given export */ if (ref_fh_fsid_type == 1 && !(exp->ex_flags & NFSEXP_FSID)) { /* if we don't have an fsid, we cannot provide one... */ ref_fh_fsid_type = 0; } } else if (exp->ex_flags & NFSEXP_FSID) ref_fh_fsid_type = 1; if (!old_valid_dev(ex_dev) && ref_fh_fsid_type == 0) { /* for newer device numbers, we must use a newer fsid format */ ref_fh_version = 1; ref_fh_fsid_type = 3; } if (old_valid_dev(ex_dev) && (ref_fh_fsid_type == 2 || ref_fh_fsid_type == 3)) /* must use type1 for smaller device numbers */ ref_fh_fsid_type = 0; if (ref_fh == fhp) fh_put(ref_fh); if (fhp->fh_locked || fhp->fh_dentry) { printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n", parent->d_name.name, dentry->d_name.name); } if (fhp->fh_maxsize < NFS_FHSIZE) printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n", fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name); fhp->fh_dentry = dget(dentry); /* our internal copy */ fhp->fh_export = exp; cache_get(&exp->h); if (ref_fh_version == 0xca) { /* old style filehandle please */ memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); fhp->fh_handle.fh_size = NFS_FHSIZE; fhp->fh_handle.ofh_dcookie = 0xfeebbaca; fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev); fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_dentry->d_inode->i_ino); fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry)); if (inode) _fh_update_old(dentry, exp, &fhp->fh_handle); } else { int len; fhp->fh_handle.fh_version = 1; fhp->fh_handle.fh_auth_type = 0; datap = fhp->fh_handle.fh_auth+0; fhp->fh_handle.fh_fsid_type = ref_fh_fsid_type; switch (ref_fh_fsid_type) { case 0: /* * fsid_type 0: * 2byte major, 2byte minor, 4byte inode */ mk_fsid_v0(datap, ex_dev, exp->ex_dentry->d_inode->i_ino); break; case 1: /* fsid_type 1 == 4 bytes filesystem id */ mk_fsid_v1(datap, exp->ex_fsid); break; case 2: /* * fsid_type 2: * 4byte major, 4byte minor, 4byte inode */ mk_fsid_v2(datap, ex_dev, exp->ex_dentry->d_inode->i_ino); break; case 3: /* * fsid_type 3: * 4byte devicenumber, 4byte inode */ mk_fsid_v3(datap, ex_dev, exp->ex_dentry->d_inode->i_ino); break; } len = key_len(ref_fh_fsid_type); datap += len/4; fhp->fh_handle.fh_size = 4 + len; if (inode) { int size = (fhp->fh_maxsize-len-4)/4; fhp->fh_handle.fh_fileid_type = _fh_update(dentry, exp, datap, &size); fhp->fh_handle.fh_size += size*4; } if (fhp->fh_handle.fh_fileid_type == 255) return nfserr_opnotsupp; } nfsd_nr_verified++; return 0; }
/* Write out a tar header for the specified file/directory/whatever */ static int writeTarHeader(struct TarBallInfo *tbInfo, const char *header_name, const char *real_name, struct stat *statbuf) { long chksum=0; struct TarHeader header; const unsigned char *cp = (const unsigned char *) &header; ssize_t size = sizeof(struct TarHeader); memset( &header, 0, size); strncpy(header.name, header_name, sizeof(header.name)); putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */ putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); strncpy(header.magic, TAR_MAGIC TAR_VERSION, TAR_MAGIC_LEN + TAR_VERSION_LEN ); /* Enter the user and group names (default to root if it fails) */ my_getpwuid(header.uname, statbuf->st_uid); if (! *header.uname) strcpy(header.uname, "root"); my_getgrgid(header.gname, statbuf->st_gid); if (! *header.uname) strcpy(header.uname, "root"); if (tbInfo->hlInfo) { /* This is a hard link */ header.typeflag = LNKTYPE; strncpy(header.linkname, tbInfo->hlInfo->name, sizeof(header.linkname)); } else if (S_ISLNK(statbuf->st_mode)) { char *lpath = xreadlink(real_name); if (!lpath) /* Already printed err msg inside xreadlink() */ return ( FALSE); header.typeflag = SYMTYPE; strncpy(header.linkname, lpath, sizeof(header.linkname)); free(lpath); } else if (S_ISDIR(statbuf->st_mode)) { header.typeflag = DIRTYPE; strncat(header.name, "/", sizeof(header.name)); } else if (S_ISCHR(statbuf->st_mode)) { header.typeflag = CHRTYPE; putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev)); putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev)); } else if (S_ISBLK(statbuf->st_mode)) { header.typeflag = BLKTYPE; putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev)); putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev)); } else if (S_ISFIFO(statbuf->st_mode)) { header.typeflag = FIFOTYPE; } else if (S_ISREG(statbuf->st_mode)) { header.typeflag = REGTYPE; putOctal(header.size, sizeof(header.size), statbuf->st_size); } else { error_msg("%s: Unknown file type", real_name); return ( FALSE); } /* Calculate and store the checksum (i.e., the sum of all of the bytes of * the header). The checksum field must be filled with blanks for the * calculation. The checksum field is formatted differently from the * other fields: it has [6] digits, a null, then a space -- rather than * digits, followed by a null like the other fields... */ memset(header.chksum, ' ', sizeof(header.chksum)); cp = (const unsigned char *) &header; while (size-- > 0) chksum += *cp++; putOctal(header.chksum, 7, chksum); /* Now write the header out to disk */ if ((size=full_write(tbInfo->tarFd, (char*)&header, sizeof(struct TarHeader))) < 0) { error_msg(io_error, real_name, strerror(errno)); return ( FALSE); } /* Pad the header up to the tar block size */ for (; size<TAR_BLOCK_SIZE; size++) { write(tbInfo->tarFd, "\0", 1); } /* Now do the verbose thing (or not) */ if (tbInfo->verboseFlag==TRUE) { FILE *vbFd = stdout; if (tbInfo->tarFd == fileno(stdout)) // If the archive goes to stdout, verbose to stderr vbFd = stderr; fprintf(vbFd, "%s\n", header.name); } return ( TRUE); }
static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, const struct gfs2_inum_host *inum, unsigned int mode, unsigned int uid, unsigned int gid, const u64 *generation, dev_t dev, const char *symname, unsigned size, struct buffer_head **bhp) { struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); struct gfs2_dinode *di; struct buffer_head *dibh; struct timespec tv = CURRENT_TIME; dibh = gfs2_meta_new(gl, inum->no_addr); gfs2_trans_add_bh(gl, dibh, 1); gfs2_metatype_set(dibh, GFS2_METATYPE_DI, GFS2_FORMAT_DI); gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); di = (struct gfs2_dinode *)dibh->b_data; di->di_num.no_formal_ino = cpu_to_be64(inum->no_formal_ino); di->di_num.no_addr = cpu_to_be64(inum->no_addr); di->di_mode = cpu_to_be32(mode); di->di_uid = cpu_to_be32(uid); di->di_gid = cpu_to_be32(gid); di->di_nlink = 0; di->di_size = cpu_to_be64(size); di->di_blocks = cpu_to_be64(1); di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec); di->di_major = cpu_to_be32(MAJOR(dev)); di->di_minor = cpu_to_be32(MINOR(dev)); di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr); di->di_generation = cpu_to_be64(*generation); di->di_flags = 0; di->__pad1 = 0; di->di_payload_format = cpu_to_be32(S_ISDIR(mode) ? GFS2_FORMAT_DE : 0); di->di_height = 0; di->__pad2 = 0; di->__pad3 = 0; di->di_depth = 0; di->di_entries = 0; memset(&di->__pad4, 0, sizeof(di->__pad4)); di->di_eattr = 0; di->di_atime_nsec = cpu_to_be32(tv.tv_nsec); di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec); di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec); memset(&di->di_reserved, 0, sizeof(di->di_reserved)); switch(mode & S_IFMT) { case S_IFREG: if ((dip->i_diskflags & GFS2_DIF_INHERIT_JDATA) || gfs2_tune_get(sdp, gt_new_files_jdata)) di->di_flags |= cpu_to_be32(GFS2_DIF_JDATA); break; case S_IFDIR: di->di_flags |= cpu_to_be32(dip->i_diskflags & GFS2_DIF_INHERIT_JDATA); di->di_flags |= cpu_to_be32(GFS2_DIF_JDATA); di->di_size = cpu_to_be64(sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)); di->di_entries = cpu_to_be32(2); gfs2_init_dir(dibh, dip); break; case S_IFLNK: memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, size); break; } set_buffer_uptodate(dibh); *bhp = dibh; }
/** Initialize the module - Register the character device */ static int qres_init_module(void) { qos_rv rv; kal_irq_state flags; //kal_spin_lock_irqsave(rres_get_spinlock(), &flags); qres_init(); qos_log_debug("Initing QSUP"); if ((rv = qsup_init_ks()) != QOS_OK) { qos_log_crit("qsup_init_ks() failed: %s", qos_strerror(rv)); qres_cleanup(); goto err; } // start_timer_thread(); #ifdef QSUP_DYNAMIC_RECLAIM write_lock(&hook_lock); old_block_hook = block_hook; old_unblock_hook = unblock_hook; old_stop_hook = stop_hook; old_continue_hook = continue_hook; block_hook = qres_block_hook; unblock_hook = qres_unblock_hook; stop_hook = qres_stop_hook; continue_hook = qres_continue_hook; write_unlock(&hook_lock); #endif qos_log_debug("qres module initialization finished"); //kal_spin_unlock_irqrestore(rres_get_spinlock(), &flags); /* Device registration should be done when kernel module is * already able to accept ioctl requests. Furthermore, spinlocks * cannot be held because it might sleep. */ if (qos_dev_register(&qres_dev_info, QRES_DEV_NAME, QRES_MAJOR_NUM, &Fops) != QOS_OK) { qos_log_crit("Registration of device %s failed", QRES_DEV_NAME); } else { qos_log_info("Registered QRES device with major device number %d.", MAJOR(qres_dev_info.dev_num)); qos_log_info("If you want to talk to the device driver,"); qos_log_info("you'll have to create a device file. "); qos_log_info("We suggest you use:"); qos_log_info("mknod %s c %d 0", QRES_DEV_NAME, MAJOR(qres_dev_info.dev_num)); } qsup_dev_register(); /** ProcFS-related functions may sleep, so no spinlock should be held **/ if (qres_proc_register()) qos_log_err("Failed to register qres module in /proc filesystem"); return 0; err: //kal_spin_unlock_irqrestore(rres_get_spinlock(), &flags); return -1; }
int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) { sector_t sector_size = bdev_logical_block_size(bdev) / 512; Sector sect; unsigned char *data; struct partition *p; struct fat_boot_sector *fb; int slot; data = read_dev_sector(bdev, 0, §); if (!data) return -1; if (!msdos_magic_present(data + 510)) { put_dev_sector(sect); return 0; } if (aix_magic_present(data, bdev)) { put_dev_sector(sect); printk( " [AIX]"); return 0; } #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) if(179 == MAJOR(bdev->bd_dev)) { printk("\n%s..%d... ==== Begin to parse sdcard-partition. ====xbw[mmc0]===\n",__FUNCTION__, __LINE__); } #endif /* * Now that the 55aa signature is present, this is probably * either the boot sector of a FAT filesystem or a DOS-type * partition table. Reject this in case the boot indicator * is not 0 or 0x80. */ p = (struct partition *) (data + 0x1be); for (slot = 1; slot <= 4; slot++, p++) { if (p->boot_ind != 0 && p->boot_ind != 0x80) { #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) if(179 == MAJOR(bdev->bd_dev)) { printk("%s..%d... ==== The sdcard has not MBR. ====xbw[mmc0]===\n",__FUNCTION__, __LINE__); } #endif /* * Even without a valid boot inidicator value * its still possible this is valid FAT filesystem * without a partition table. */ fb = (struct fat_boot_sector *) data; if (slot == 1 && fb->reserved && fb->fats && fat_valid_media(fb->media)) { printk("\n"); put_dev_sector(sect); #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) if(179 == MAJOR(bdev->bd_dev)) { printk("%s..%d... ==== The DBR(slot=%d) is valid. ====xbw[mmc0]===\n",__FUNCTION__, __LINE__, slot); } #endif return 1; } else { put_dev_sector(sect); #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) if(179 == MAJOR(bdev->bd_dev)) { printk("%s..%d... ==== The DBR is invalid. ====xbw[mmc0]===\n",__FUNCTION__, __LINE__); } #endif return 0; } } } #ifdef CONFIG_EFI_PARTITION p = (struct partition *) (data + 0x1be); for (slot = 1 ; slot <= 4 ; slot++, p++) { /* If this is an EFI GPT disk, msdos should ignore it. */ if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) { put_dev_sector(sect); return 0; } } #endif p = (struct partition *) (data + 0x1be); /* * Look for partitions in two passes: * First find the primary and DOS-type extended partitions. * On the second pass look inside *BSD, Unixware and Solaris partitions. */ #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) if(179 == MAJOR(bdev->bd_dev)) { printk("%s..%d... ==== The sdcard has MBR. ====xbw[mmc0]===\n", __FUNCTION__, __LINE__); } #endif state->next = 5; for (slot = 1 ; slot <= 4 ; slot++, p++) { sector_t start = start_sect(p)*sector_size; sector_t size = nr_sects(p)*sector_size; if (!size) continue; #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) if(179 == MAJOR(bdev->bd_dev)) { printk("%s..%d... ==== partition-%d, size=%luKB ====xbw[mmc0]===\n",\ __FUNCTION__, __LINE__, slot, size/2); } #endif if (is_extended_partition(p)) { /* * prevent someone doing mkfs or mkswap on an * extended partition, but leave room for LILO * FIXME: this uses one logical sector for > 512b * sector, although it may not be enough/proper. */ sector_t n = 2; n = min(size, max(sector_size, n)); #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) if(179 == MAJOR(bdev->bd_dev)) { printk("%s...%d... ==== extend partition-%d....====xbw[mmc0]===\n",__FUNCTION__, __LINE__, slot); } #endif put_partition(state, slot, start, n); printk(" <"); parse_extended(state, bdev, start, size); printk(" >"); continue; } #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) if(179 == MAJOR(bdev->bd_dev)) { printk("%s..%d... ==== main partition-%d....====xbw[mmc0]===\n",__FUNCTION__, __LINE__, slot); } #endif put_partition(state, slot, start, size); if (SYS_IND(p) == LINUX_RAID_PARTITION) state->parts[slot].flags = 1; if (SYS_IND(p) == DM6_PARTITION) printk("[DM]"); if (SYS_IND(p) == EZD_PARTITION) printk("[EZD]"); } printk("\n"); /* second pass - output for each on a separate line */ p = (struct partition *) (0x1be + data); for (slot = 1 ; slot <= 4 ; slot++, p++) { unsigned char id = SYS_IND(p); int n; if (!nr_sects(p)) continue; for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++) ; if (!subtypes[n].parse) continue; subtypes[n].parse(state, bdev, start_sect(p)*sector_size, nr_sects(p)*sector_size, slot); } put_dev_sector(sect); return 1; }
int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, dev_t device_number) { int rc = -EPERM; unsigned int xid; int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; struct cifs_sb_info *cifs_sb; struct tcon_link *tlink; struct cifs_tcon *pTcon; struct cifs_io_parms io_parms; char *full_path = NULL; struct inode *newinode = NULL; int oplock = 0; u16 fileHandle; FILE_ALL_INFO *buf = NULL; unsigned int bytes_written; struct win_dev *pdev; if (!old_valid_dev(device_number)) return -EINVAL; cifs_sb = CIFS_SB(inode->i_sb); tlink = cifs_sb_tlink(cifs_sb); if (IS_ERR(tlink)) return PTR_ERR(tlink); pTcon = tlink_tcon(tlink); xid = get_xid(); full_path = build_path_from_dentry(direntry); if (full_path == NULL) { rc = -ENOMEM; goto mknod_out; } if (pTcon->unix_ext) { struct cifs_unix_set_info_args args = { .mode = mode & ~current_umask(), .ctime = NO_CHANGE_64, .atime = NO_CHANGE_64, .mtime = NO_CHANGE_64, .device = device_number, }; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { args.uid = current_fsuid(); args.gid = current_fsgid(); } else { args.uid = INVALID_UID; /* no change */ args.gid = INVALID_GID; /* no change */ } rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) goto mknod_out; rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb, xid); if (rc == 0) d_instantiate(direntry, newinode); goto mknod_out; } if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) goto mknod_out; cifs_dbg(FYI, "sfu compat create special file\n"); buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); if (buf == NULL) { kfree(full_path); rc = -ENOMEM; free_xid(xid); return rc; } if (backup_cred(cifs_sb)) create_options |= CREATE_OPEN_BACKUP_INTENT; rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, GENERIC_WRITE, create_options, &fileHandle, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) goto mknod_out; /* BB Do not bother to decode buf since no local inode yet to put * timestamps in, but we can reuse it safely */ pdev = (struct win_dev *)buf; io_parms.netfid = fileHandle; io_parms.pid = current->tgid; io_parms.tcon = pTcon; io_parms.offset = 0; io_parms.length = sizeof(struct win_dev); if (S_ISCHR(mode)) { memcpy(pdev->type, "IntxCHR", 8); pdev->major = cpu_to_le64(MAJOR(device_number)); pdev->minor = cpu_to_le64(MINOR(device_number)); rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, NULL, 0); } else if (S_ISBLK(mode)) { memcpy(pdev->type, "IntxBLK", 8); pdev->major = cpu_to_le64(MAJOR(device_number)); pdev->minor = cpu_to_le64(MINOR(device_number)); rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, NULL, 0); } /* else if (S_ISFIFO) */ CIFSSMBClose(xid, pTcon, fileHandle); d_drop(direntry); /* FIXME: add code here to set EAs */ mknod_out: kfree(full_path); kfree(buf); free_xid(xid); cifs_put_tlink(tlink); return rc; }
/*模块加载方法*/ static int __init hello_init(void){ int err = -1; dev_t dev = 0; struct device* temp = NULL; printk(KERN_ALERT"Initializing hello device.\n"); /*动态分配主设备和从设备号*/ err = alloc_chrdev_region(&dev, 0, 1, HELLO_DEVICE_NODE_NAME); if(err < 0) { printk(KERN_ALERT"Failed to alloc char dev region.\n"); goto fail; } hello_major = MAJOR(dev); hello_minor = MINOR(dev); /*分配helo设备结构体变量*/ hello_dev = kmalloc(sizeof(struct hello_android_dev), GFP_KERNEL); if(!hello_dev) { err = -ENOMEM; printk(KERN_ALERT"Failed to alloc hello_dev.\n"); goto unregister; } /*初始化设备*/ err = __hello_setup_dev(hello_dev); if(err) { printk(KERN_ALERT"Failed to setup dev: %d.\n", err); goto cleanup; } /*在/sys/class/目录下创建设备类别目录hello*/ hello_class = class_create(THIS_MODULE, HELLO_DEVICE_CLASS_NAME); if(IS_ERR(hello_class)) { err = PTR_ERR(hello_class); printk(KERN_ALERT"Failed to create hello class.\n"); goto destroy_cdev; } /*在/dev/目录和/sys/class/hello目录下分别创建设备文件hello*/ temp = device_create(hello_class, NULL, dev, "%s", HELLO_DEVICE_FILE_NAME); if(IS_ERR(temp)) { err = PTR_ERR(temp); printk(KERN_ALERT"Failed to create hello device."); goto destroy_class; } /*在/sys/class/hello/hello目录下创建属性文件val*/ err = device_create_file(temp, &dev_attr_val); if(err < 0) { printk(KERN_ALERT"Failed to create attribute val."); goto destroy_device; } dev_set_drvdata(temp, hello_dev); /*创建/proc/hello文件*/ /*hello_create_proc();*/ printk(KERN_ALERT"Succedded to initialize hello device.\n"); return 0; destroy_device: device_destroy(hello_class, dev); destroy_class: class_destroy(hello_class); destroy_cdev: cdev_del(&(hello_dev->dev)); cleanup: kfree(hello_dev); unregister: unregister_chrdev_region(MKDEV(hello_major, hello_minor), 1); fail: return err; }