static int coda_fill_super(struct super_block *sb, void *data, int silent) { struct inode *root = NULL; struct venus_comm *vc; struct CodaFid fid; int error; int idx; idx = get_device_index((struct coda_mount_data *) data); /* Ignore errors in data, for backward compatibility */ if(idx == -1) idx = 0; printk(KERN_INFO "coda_read_super: device index: %i\n", idx); vc = &coda_comms[idx]; mutex_lock(&vc->vc_mutex); if (!vc->vc_inuse) { printk("coda_read_super: No pseudo device\n"); error = -EINVAL; goto unlock_out; } if (vc->vc_sb) { printk("coda_read_super: Device already mounted\n"); error = -EBUSY; goto unlock_out; } error = bdi_setup_and_register(&vc->bdi, "coda", BDI_CAP_MAP_COPY); if (error) goto unlock_out; vc->vc_sb = sb; mutex_unlock(&vc->vc_mutex); sb->s_fs_info = vc; sb->s_flags |= MS_NOATIME; sb->s_blocksize = 4096; /* XXXXX what do we put here?? */ sb->s_blocksize_bits = 12; sb->s_magic = CODA_SUPER_MAGIC; sb->s_op = &coda_super_operations; sb->s_d_op = &coda_dentry_operations; sb->s_bdi = &vc->bdi; /* get root fid from Venus: this needs the root inode */ error = venus_rootfid(sb, &fid); if ( error ) { printk("coda_read_super: coda_get_rootfid failed with %d\n", error); goto error; } printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid)); /* make root inode */ error = coda_cnode_make(&root, &fid, sb); if ( error || !root ) { printk("Failure of coda_cnode_make for root: error %d\n", error); goto error; } printk("coda_read_super: rootinode is %ld dev %s\n", root->i_ino, root->i_sb->s_id); sb->s_root = d_make_root(root); if (!sb->s_root) { error = -EINVAL; goto error; } return 0; error: if (root) iput(root); mutex_lock(&vc->vc_mutex); bdi_destroy(&vc->bdi); vc->vc_sb = NULL; sb->s_fs_info = NULL; unlock_out: mutex_unlock(&vc->vc_mutex); return error; }
static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) { struct ncp_mount_data_kernel data; struct ncp_server *server; struct file *ncp_filp; struct inode *root_inode; struct inode *sock_inode; struct socket *sock; int error; int default_bufsize; #ifdef CONFIG_NCPFS_PACKET_SIGNING int options; #endif struct ncp_entry_info finfo; memset(&data, 0, sizeof(data)); server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL); if (!server) return -ENOMEM; sb->s_fs_info = server; error = -EFAULT; if (raw_data == NULL) goto out; switch (*(int*)raw_data) { case NCP_MOUNT_VERSION: { struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data; data.flags = md->flags; data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE; data.mounted_uid = md->mounted_uid; data.wdog_pid = find_get_pid(md->wdog_pid); data.ncp_fd = md->ncp_fd; data.time_out = md->time_out; data.retry_count = md->retry_count; data.uid = md->uid; data.gid = md->gid; data.file_mode = md->file_mode; data.dir_mode = md->dir_mode; data.info_fd = -1; memcpy(data.mounted_vol, md->mounted_vol, NCP_VOLNAME_LEN+1); } break; case NCP_MOUNT_VERSION_V4: { struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data; data.flags = md->flags; data.mounted_uid = md->mounted_uid; data.wdog_pid = find_get_pid(md->wdog_pid); data.ncp_fd = md->ncp_fd; data.time_out = md->time_out; data.retry_count = md->retry_count; data.uid = md->uid; data.gid = md->gid; data.file_mode = md->file_mode; data.dir_mode = md->dir_mode; data.info_fd = -1; } break; default: error = -ECHRNG; if (memcmp(raw_data, "vers", 4) == 0) { error = ncp_parse_options(&data, raw_data); } if (error) goto out; break; } error = -EBADF; ncp_filp = fget(data.ncp_fd); if (!ncp_filp) goto out; error = -ENOTSOCK; sock_inode = ncp_filp->f_path.dentry->d_inode; if (!S_ISSOCK(sock_inode->i_mode)) goto out_fput; sock = SOCKET_I(sock_inode); if (!sock) goto out_fput; if (sock->type == SOCK_STREAM) default_bufsize = 0xF000; else default_bufsize = 1024; sb->s_flags |= MS_NODIRATIME; /* probably even noatime */ sb->s_maxbytes = 0xFFFFFFFFU; sb->s_blocksize = 1024; /* Eh... Is this correct? */ sb->s_blocksize_bits = 10; sb->s_magic = NCP_SUPER_MAGIC; sb->s_op = &ncp_sops; sb->s_d_op = &ncp_dentry_operations; sb->s_bdi = &server->bdi; server = NCP_SBP(sb); memset(server, 0, sizeof(*server)); error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY); if (error) goto out_fput; server->ncp_filp = ncp_filp; server->ncp_sock = sock; if (data.info_fd != -1) { struct socket *info_sock; error = -EBADF; server->info_filp = fget(data.info_fd); if (!server->info_filp) goto out_bdi; error = -ENOTSOCK; sock_inode = server->info_filp->f_path.dentry->d_inode; if (!S_ISSOCK(sock_inode->i_mode)) goto out_fput2; info_sock = SOCKET_I(sock_inode); if (!info_sock) goto out_fput2; error = -EBADFD; if (info_sock->type != SOCK_STREAM) goto out_fput2; server->info_sock = info_sock; } /* server->lock = 0; */ mutex_init(&server->mutex); server->packet = NULL; /* server->buffer_size = 0; */ /* server->conn_status = 0; */ /* server->root_dentry = NULL; */ /* server->root_setuped = 0; */ mutex_init(&server->root_setup_lock); #ifdef CONFIG_NCPFS_PACKET_SIGNING /* server->sign_wanted = 0; */ /* server->sign_active = 0; */ #endif init_rwsem(&server->auth_rwsem); server->auth.auth_type = NCP_AUTH_NONE; /* server->auth.object_name_len = 0; */ /* server->auth.object_name = NULL; */ /* server->auth.object_type = 0; */ /* server->priv.len = 0; */ /* server->priv.data = NULL; */ server->m = data; /* Although anything producing this is buggy, it happens now because of PATH_MAX changes.. */ if (server->m.time_out < 1) { server->m.time_out = 10; printk(KERN_INFO "You need to recompile your ncpfs utils..\n"); } server->m.time_out = server->m.time_out * HZ / 100; server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG; server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR; #ifdef CONFIG_NCPFS_NLS /* load the default NLS charsets */ server->nls_vol = load_nls_default(); server->nls_io = load_nls_default(); #endif /* CONFIG_NCPFS_NLS */ atomic_set(&server->dentry_ttl, 0); /* no caching */ INIT_LIST_HEAD(&server->tx.requests); mutex_init(&server->rcv.creq_mutex); server->tx.creq = NULL; server->rcv.creq = NULL; init_timer(&server->timeout_tm); #undef NCP_PACKET_SIZE #define NCP_PACKET_SIZE 131072 error = -ENOMEM; server->packet_size = NCP_PACKET_SIZE; server->packet = vmalloc(NCP_PACKET_SIZE); if (server->packet == NULL) goto out_nls; server->txbuf = vmalloc(NCP_PACKET_SIZE); if (server->txbuf == NULL) goto out_packet; server->rxbuf = vmalloc(NCP_PACKET_SIZE); if (server->rxbuf == NULL) goto out_txbuf; lock_sock(sock->sk); server->data_ready = sock->sk->sk_data_ready; server->write_space = sock->sk->sk_write_space; server->error_report = sock->sk->sk_error_report; sock->sk->sk_user_data = server; sock->sk->sk_data_ready = ncp_tcp_data_ready; sock->sk->sk_error_report = ncp_tcp_error_report; if (sock->type == SOCK_STREAM) { server->rcv.ptr = (unsigned char*)&server->rcv.buf; server->rcv.len = 10; server->rcv.state = 0; INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc); INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc); sock->sk->sk_write_space = ncp_tcp_write_space; } else { INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc); INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc); server->timeout_tm.data = (unsigned long)server; server->timeout_tm.function = ncpdgram_timeout_call; } release_sock(sock->sk); ncp_lock_server(server); error = ncp_connect(server); ncp_unlock_server(server); if (error < 0) goto out_rxbuf; DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb)); error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */ #ifdef CONFIG_NCPFS_PACKET_SIGNING if (ncp_negotiate_size_and_options(server, default_bufsize, NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0) { if (options != NCP_DEFAULT_OPTIONS) { if (ncp_negotiate_size_and_options(server, default_bufsize, options & 2, &(server->buffer_size), &options) != 0) { goto out_disconnect; } } ncp_lock_server(server); if (options & 2) server->sign_wanted = 1; ncp_unlock_server(server); } else #endif /* CONFIG_NCPFS_PACKET_SIGNING */ if (ncp_negotiate_buffersize(server, default_bufsize, &(server->buffer_size)) != 0) goto out_disconnect; DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size); memset(&finfo, 0, sizeof(finfo)); finfo.i.attributes = aDIR; finfo.i.dataStreamSize = 0; /* ignored */ finfo.i.dirEntNum = 0; finfo.i.DosDirNum = 0; #ifdef CONFIG_NCPFS_SMALLDOS finfo.i.NSCreator = NW_NS_DOS; #endif finfo.volume = NCP_NUMBER_OF_VOLUMES; /* set dates of mountpoint to Jan 1, 1986; 00:00 */ finfo.i.creationTime = finfo.i.modifyTime = cpu_to_le16(0x0000); finfo.i.creationDate = finfo.i.modifyDate = finfo.i.lastAccessDate = cpu_to_le16(0x0C21); finfo.i.nameLen = 0; finfo.i.entryName[0] = '\0'; finfo.opened = 0; finfo.ino = 2; /* tradition */ server->name_space[finfo.volume] = NW_NS_DOS; error = -ENOMEM; root_inode = ncp_iget(sb, &finfo); if (!root_inode) goto out_disconnect; DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber); sb->s_root = d_make_root(root_inode); if (!sb->s_root) goto out_disconnect; return 0; out_disconnect: ncp_lock_server(server); ncp_disconnect(server); ncp_unlock_server(server); out_rxbuf: ncp_stop_tasks(server); vfree(server->rxbuf); out_txbuf: vfree(server->txbuf); out_packet: vfree(server->packet); out_nls: #ifdef CONFIG_NCPFS_NLS unload_nls(server->nls_io); unload_nls(server->nls_vol); #endif mutex_destroy(&server->rcv.creq_mutex); mutex_destroy(&server->root_setup_lock); mutex_destroy(&server->mutex); out_fput2: if (server->info_filp) fput(server->info_filp); out_bdi: bdi_destroy(&server->bdi); out_fput: /* 23/12/1998 Marcin Dalecki <*****@*****.**>: * * The previously used put_filp(ncp_filp); was bogus, since * it doesn't perform proper unlocking. */ fput(ncp_filp); out: put_pid(data.wdog_pid); sb->s_fs_info = NULL; kfree(server); return error; }
static int cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, const char *devname, int silent) { struct inode *inode; struct cifs_sb_info *cifs_sb; int rc = 0; cifs_sb = CIFS_SB(sb); spin_lock_init(&cifs_sb->tlink_tree_lock); cifs_sb->tlink_tree = RB_ROOT; rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); if (rc) return rc; cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; rc = cifs_mount(sb, cifs_sb, volume_info, devname); if (rc) { if (!silent) cERROR(1, "cifs_mount failed w/return code = %d", rc); goto out_mount_failed; } sb->s_magic = CIFS_MAGIC_NUMBER; sb->s_op = &cifs_super_ops; sb->s_bdi = &cifs_sb->bdi; sb->s_blocksize = CIFS_MAX_MSGSIZE; sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ inode = cifs_root_iget(sb); if (IS_ERR(inode)) { rc = PTR_ERR(inode); inode = NULL; goto out_no_root; } sb->s_root = d_alloc_root(inode); if (!sb->s_root) { rc = -ENOMEM; goto out_no_root; } /* do that *after* d_alloc_root() - we want NULL ->d_op for root here */ if (cifs_sb_master_tcon(cifs_sb)->nocase) sb->s_d_op = &cifs_ci_dentry_ops; else sb->s_d_op = &cifs_dentry_ops; #ifdef CIFS_NFSD_EXPORT if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { cFYI(1, "export ops supported"); sb->s_export_op = &cifs_export_ops; } #endif /* CIFS_NFSD_EXPORT */ return 0; out_no_root: cERROR(1, "cifs_read_super: get root inode failed"); if (inode) iput(inode); cifs_umount(sb, cifs_sb); out_mount_failed: bdi_destroy(&cifs_sb->bdi); return rc; }
int zfs_domount(struct super_block *sb, void *data, int silent) { zpl_mount_data_t *zmd = data; const char *osname = zmd->z_osname; zfs_sb_t *zsb; struct inode *root_inode; uint64_t recordsize; int error; error = zfs_sb_create(osname, &zsb); if (error) return (error); if ((error = dsl_prop_get_integer(osname, "recordsize", &recordsize, NULL))) goto out; zsb->z_sb = sb; sb->s_fs_info = zsb; sb->s_magic = ZFS_SUPER_MAGIC; sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_time_gran = 1; sb->s_blocksize = recordsize; sb->s_blocksize_bits = ilog2(recordsize); #ifdef HAVE_BDI /* * 2.6.32 API change, * Added backing_device_info (BDI) per super block interfaces. A BDI * must be configured when using a non-device backed filesystem for * proper writeback. This is not required for older pdflush kernels. * * NOTE: Linux read-ahead is disabled in favor of zfs read-ahead. */ zsb->z_bdi.ra_pages = 0; sb->s_bdi = &zsb->z_bdi; error = -bdi_setup_and_register(&zsb->z_bdi, "zfs", BDI_CAP_MAP_COPY); if (error) goto out; #endif /* HAVE_BDI */ /* Set callback operations for the file system. */ sb->s_op = &zpl_super_operations; sb->s_xattr = zpl_xattr_handlers; sb->s_export_op = &zpl_export_operations; #ifdef HAVE_S_D_OP sb->s_d_op = &zpl_dentry_operations; #endif /* HAVE_S_D_OP */ /* Set features for file system. */ zfs_set_fuid_feature(zsb); if (dmu_objset_is_snapshot(zsb->z_os)) { uint64_t pval; atime_changed_cb(zsb, B_FALSE); readonly_changed_cb(zsb, B_TRUE); if ((error = dsl_prop_get_integer(osname,"xattr",&pval,NULL))) goto out; xattr_changed_cb(zsb, pval); zsb->z_issnap = B_TRUE; zsb->z_os->os_sync = ZFS_SYNC_DISABLED; mutex_enter(&zsb->z_os->os_user_ptr_lock); dmu_objset_set_user(zsb->z_os, zsb); mutex_exit(&zsb->z_os->os_user_ptr_lock); } else { error = zfs_sb_setup(zsb, B_TRUE); } /* Allocate a root inode for the filesystem. */ error = zfs_root(zsb, &root_inode); if (error) { (void) zfs_umount(sb); goto out; } /* Allocate a root dentry for the filesystem */ sb->s_root = d_make_root(root_inode); if (sb->s_root == NULL) { (void) zfs_umount(sb); error = ENOMEM; goto out; } if (!zsb->z_issnap) zfsctl_create(zsb); out: if (error) { dmu_objset_disown(zsb->z_os, zsb); zfs_sb_free(zsb); } return (error); }
static int cifs_read_super(struct super_block *sb, void *data, const char *devname, int silent) { struct inode *inode; struct cifs_sb_info *cifs_sb; int rc = 0; /* BB should we make this contingent on mount parm? */ sb->s_flags |= MS_NODIRATIME | MS_NOATIME; sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); cifs_sb = CIFS_SB(sb); if (cifs_sb == NULL) return -ENOMEM; spin_lock_init(&cifs_sb->tlink_tree_lock); cifs_sb->tlink_tree = RB_ROOT; rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); if (rc) { kfree(cifs_sb); return rc; } cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; #ifdef CONFIG_CIFS_DFS_UPCALL /* copy mount params to sb for use in submounts */ /* BB: should we move this after the mount so we * do not have to do the copy on failed mounts? * BB: May be it is better to do simple copy before * complex operation (mount), and in case of fail * just exit instead of doing mount and attempting * undo it if this copy fails?*/ if (data) { int len = strlen(data); cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); if (cifs_sb->mountdata == NULL) { bdi_destroy(&cifs_sb->bdi); kfree(sb->s_fs_info); sb->s_fs_info = NULL; return -ENOMEM; } strncpy(cifs_sb->mountdata, data, len + 1); cifs_sb->mountdata[len] = '\0'; } #endif rc = cifs_mount(sb, cifs_sb, data, devname); if (rc) { if (!silent) cERROR(1, "cifs_mount failed w/return code = %d", rc); goto out_mount_failed; } sb->s_magic = CIFS_MAGIC_NUMBER; sb->s_op = &cifs_super_ops; sb->s_bdi = &cifs_sb->bdi; sb->s_blocksize = CIFS_MAX_MSGSIZE; sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ inode = cifs_root_iget(sb, ROOT_I); if (IS_ERR(inode)) { rc = PTR_ERR(inode); inode = NULL; goto out_no_root; } sb->s_root = d_alloc_root(inode); if (!sb->s_root) { rc = -ENOMEM; goto out_no_root; } /* do that *after* d_alloc_root() - we want NULL ->d_op for root here */ if (cifs_sb_master_tcon(cifs_sb)->nocase) sb->s_d_op = &cifs_ci_dentry_ops; else sb->s_d_op = &cifs_dentry_ops; #ifdef CONFIG_CIFS_EXPERIMENTAL if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { cFYI(1, "export ops supported"); sb->s_export_op = &cifs_export_ops; } #endif /* EXPERIMENTAL */ return 0; out_no_root: cERROR(1, "cifs_read_super: get root inode failed"); if (inode) iput(inode); cifs_umount(sb, cifs_sb); out_mount_failed: if (cifs_sb) { #ifdef CONFIG_CIFS_DFS_UPCALL if (cifs_sb->mountdata) { kfree(cifs_sb->mountdata); cifs_sb->mountdata = NULL; } #endif unload_nls(cifs_sb->local_nls); bdi_destroy(&cifs_sb->bdi); kfree(cifs_sb); } return rc; }
/* * lookup a volume by name * - this can be one of the following: * "%[cell:]volume[.]" R/W volume * "#[cell:]volume[.]" R/O or R/W volume (rwparent=0), * or R/W (rwparent=1) volume * "%[cell:]volume.readonly" R/O volume * "#[cell:]volume.readonly" R/O volume * "%[cell:]volume.backup" Backup volume * "#[cell:]volume.backup" Backup volume * * The cell name is optional, and defaults to the current cell. * * See "The Rules of Mount Point Traversal" in Chapter 5 of the AFS SysAdmin * Guide * - Rule 1: Explicit type suffix forces access of that type or nothing * (no suffix, then use Rule 2 & 3) * - Rule 2: If parent volume is R/O, then mount R/O volume by preference, R/W * if not available * - Rule 3: If parent volume is R/W, then only mount R/W volume unless * explicitly told otherwise */ struct afs_volume *afs_volume_lookup(struct afs_mount_params *params) { struct afs_vlocation *vlocation = NULL; struct afs_volume *volume = NULL; struct afs_server *server = NULL; char srvtmask; int ret, loop; _enter("{%*.*s,%d}", params->volnamesz, params->volnamesz, params->volname, params->rwpath); /* lookup the volume location record */ vlocation = afs_vlocation_lookup(params->cell, params->key, params->volname, params->volnamesz); if (IS_ERR(vlocation)) { ret = PTR_ERR(vlocation); vlocation = NULL; goto error; } /* make the final decision on the type we want */ ret = -ENOMEDIUM; if (params->force && !(vlocation->vldb.vidmask & (1 << params->type))) goto error; srvtmask = 0; for (loop = 0; loop < vlocation->vldb.nservers; loop++) srvtmask |= vlocation->vldb.srvtmask[loop]; if (params->force) { if (!(srvtmask & (1 << params->type))) goto error; } else if (srvtmask & AFS_VOL_VTM_RO) { params->type = AFSVL_ROVOL; } else if (srvtmask & AFS_VOL_VTM_RW) { params->type = AFSVL_RWVOL; } else { goto error; } down_write(¶ms->cell->vl_sem); /* is the volume already active? */ if (vlocation->vols[params->type]) { /* yes - re-use it */ volume = vlocation->vols[params->type]; afs_get_volume(volume); goto success; } /* create a new volume record */ _debug("creating new volume record"); ret = -ENOMEM; volume = kzalloc(sizeof(struct afs_volume), GFP_KERNEL); if (!volume) goto error_up; atomic_set(&volume->usage, 1); volume->type = params->type; volume->type_force = params->force; volume->cell = params->cell; volume->vid = vlocation->vldb.vid[params->type]; ret = bdi_setup_and_register(&volume->bdi, "afs", BDI_CAP_MAP_COPY); if (ret) goto error_bdi; init_rwsem(&volume->server_sem); /* look up all the applicable server records */ for (loop = 0; loop < 8; loop++) { if (vlocation->vldb.srvtmask[loop] & (1 << volume->type)) { server = afs_lookup_server( volume->cell, &vlocation->vldb.servers[loop]); if (IS_ERR(server)) { ret = PTR_ERR(server); goto error_discard; } volume->servers[volume->nservers] = server; volume->nservers++; } } /* attach the cache and volume location */ #ifdef CONFIG_AFS_FSCACHE volume->cache = fscache_acquire_cookie(vlocation->cache, &afs_volume_cache_index_def, volume, true); #endif afs_get_vlocation(vlocation); volume->vlocation = vlocation; vlocation->vols[volume->type] = volume; success: _debug("kAFS selected %s volume %08x", afs_voltypes[volume->type], volume->vid); up_write(¶ms->cell->vl_sem); afs_put_vlocation(vlocation); _leave(" = %p", volume); return volume; /* clean up */ error_up: up_write(¶ms->cell->vl_sem); error: afs_put_vlocation(vlocation); _leave(" = %d", ret); return ERR_PTR(ret); error_discard: bdi_destroy(&volume->bdi); error_bdi: up_write(¶ms->cell->vl_sem); for (loop = volume->nservers - 1; loop >= 0; loop--) afs_put_server(volume->servers[loop]); kfree(volume); goto error; }
static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi, unsigned table_count) { struct exofs_sb_info *sbi = *psbi; struct osd_dev *fscb_od; struct osd_obj_id obj = {.partition = sbi->layout.s_pid, .id = EXOFS_DEVTABLE_ID}; struct exofs_device_table *dt; unsigned table_bytes = table_count * sizeof(dt->dt_dev_table[0]) + sizeof(*dt); unsigned numdevs, i; int ret; dt = kmalloc(table_bytes, GFP_KERNEL); if (unlikely(!dt)) { EXOFS_ERR("ERROR: allocating %x bytes for device table\n", table_bytes); return -ENOMEM; } fscb_od = sbi->layout.s_ods[0]; sbi->layout.s_ods[0] = NULL; sbi->layout.s_numdevs = 0; ret = exofs_read_kern(fscb_od, sbi->s_cred, &obj, 0, dt, table_bytes); if (unlikely(ret)) { EXOFS_ERR("ERROR: reading device table\n"); goto out; } numdevs = le64_to_cpu(dt->dt_num_devices); if (unlikely(!numdevs)) { ret = -EINVAL; goto out; } WARN_ON(table_count != numdevs); ret = _read_and_match_data_map(sbi, numdevs, dt); if (unlikely(ret)) goto out; if (likely(numdevs > 1)) { unsigned size = numdevs * sizeof(sbi->layout.s_ods[0]); sbi = krealloc(sbi, sizeof(*sbi) + size, GFP_KERNEL); if (unlikely(!sbi)) { ret = -ENOMEM; goto out; } memset(&sbi->layout.s_ods[1], 0, size - sizeof(sbi->layout.s_ods[0])); *psbi = sbi; } for (i = 0; i < numdevs; i++) { struct exofs_fscb fscb; struct osd_dev_info odi; struct osd_dev *od; if (exofs_devs_2_odi(&dt->dt_dev_table[i], &odi)) { EXOFS_ERR("ERROR: Read all-zeros device entry\n"); ret = -EINVAL; goto out; } printk(KERN_NOTICE "Add device[%d]: osd_name-%s\n", i, odi.osdname); /* On all devices the device table is identical. The user can * specify any one of the participating devices on the command * line. We always keep them in device-table order. */ if (fscb_od && osduld_device_same(fscb_od, &odi)) { sbi->layout.s_ods[i] = fscb_od; ++sbi->layout.s_numdevs; fscb_od = NULL; continue; } od = osduld_info_lookup(&odi); if (unlikely(IS_ERR(od))) { ret = PTR_ERR(od); EXOFS_ERR("ERROR: device requested is not found " "osd_name-%s =>%d\n", odi.osdname, ret); goto out; } sbi->layout.s_ods[i] = od; ++sbi->layout.s_numdevs; /* Read the fscb of the other devices to make sure the FS * partition is there. */ ret = exofs_read_kern(od, sbi->s_cred, &obj, 0, &fscb, sizeof(fscb)); if (unlikely(ret)) { EXOFS_ERR("ERROR: Malformed participating device " "error reading fscb osd_name-%s\n", odi.osdname); goto out; } /* TODO: verify other information is correct and FS-uuid * matches. Benny what did you say about device table * generation and old devices? */ } out: kfree(dt); if (unlikely(!ret && fscb_od)) { EXOFS_ERR( "ERROR: Bad device-table container device not present\n"); osduld_put_device(fscb_od); ret = -EINVAL; } return ret; } /* * Read the superblock from the OSD and fill in the fields */ static int exofs_fill_super(struct super_block *sb, void *data, int silent) { struct inode *root; struct exofs_mountopt *opts = data; struct exofs_sb_info *sbi; /*extended info */ struct osd_dev *od; /* Master device */ struct exofs_fscb fscb; /*on-disk superblock info */ struct osd_obj_id obj; unsigned table_count; int ret; sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) return -ENOMEM; ret = bdi_setup_and_register(&sbi->bdi, "exofs", BDI_CAP_MAP_COPY); if (ret) goto free_bdi; /* use mount options to fill superblock */ od = osduld_path_lookup(opts->dev_name); if (IS_ERR(od)) { ret = PTR_ERR(od); goto free_sbi; } /* Default layout in case we do not have a device-table */ sbi->layout.stripe_unit = PAGE_SIZE; sbi->layout.mirrors_p1 = 1; sbi->layout.group_width = 1; sbi->layout.group_depth = -1; sbi->layout.group_count = 1; sbi->layout.s_ods[0] = od; sbi->layout.s_numdevs = 1; sbi->layout.s_pid = opts->pid; sbi->s_timeout = opts->timeout; /* fill in some other data by hand */ memset(sb->s_id, 0, sizeof(sb->s_id)); strcpy(sb->s_id, "exofs"); sb->s_blocksize = EXOFS_BLKSIZE; sb->s_blocksize_bits = EXOFS_BLKSHIFT; sb->s_maxbytes = MAX_LFS_FILESIZE; atomic_set(&sbi->s_curr_pending, 0); sb->s_bdev = NULL; sb->s_dev = 0; obj.partition = sbi->layout.s_pid; obj.id = EXOFS_SUPER_ID; exofs_make_credential(sbi->s_cred, &obj); ret = exofs_read_kern(od, sbi->s_cred, &obj, 0, &fscb, sizeof(fscb)); if (unlikely(ret)) goto free_sbi; sb->s_magic = le16_to_cpu(fscb.s_magic); sbi->s_nextid = le64_to_cpu(fscb.s_nextid); sbi->s_numfiles = le32_to_cpu(fscb.s_numfiles); /* make sure what we read from the object store is correct */ if (sb->s_magic != EXOFS_SUPER_MAGIC) { if (!silent) EXOFS_ERR("ERROR: Bad magic value\n"); ret = -EINVAL; goto free_sbi; } if (le32_to_cpu(fscb.s_version) != EXOFS_FSCB_VER) { EXOFS_ERR("ERROR: Bad FSCB version expected-%d got-%d\n", EXOFS_FSCB_VER, le32_to_cpu(fscb.s_version)); ret = -EINVAL; goto free_sbi; } /* start generation numbers from a random point */ get_random_bytes(&sbi->s_next_generation, sizeof(u32)); spin_lock_init(&sbi->s_next_gen_lock); table_count = le64_to_cpu(fscb.s_dev_table_count); if (table_count) { ret = exofs_read_lookup_dev_table(&sbi, table_count); if (unlikely(ret)) goto free_sbi; } /* set up operation vectors */ sb->s_bdi = &sbi->bdi; sb->s_fs_info = sbi; sb->s_op = &exofs_sops; sb->s_export_op = &exofs_export_ops; root = exofs_iget(sb, EXOFS_ROOT_ID - EXOFS_OBJ_OFF); if (IS_ERR(root)) { EXOFS_ERR("ERROR: exofs_iget failed\n"); ret = PTR_ERR(root); goto free_sbi; } sb->s_root = d_alloc_root(root); if (!sb->s_root) { iput(root); EXOFS_ERR("ERROR: get root inode failed\n"); ret = -ENOMEM; goto free_sbi; } if (!S_ISDIR(root->i_mode)) { dput(sb->s_root); sb->s_root = NULL; EXOFS_ERR("ERROR: corrupt root inode (mode = %hd)\n", root->i_mode); ret = -EINVAL; goto free_sbi; } _exofs_print_device("Mounting", opts->dev_name, sbi->layout.s_ods[0], sbi->layout.s_pid); return 0; free_sbi: bdi_destroy(&sbi->bdi); free_bdi: EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n", opts->dev_name, sbi->layout.s_pid, ret); exofs_free_sbi(sbi); return ret; } /* * Set up the superblock (calls exofs_fill_super eventually) */ static struct dentry *exofs_mount(struct file_system_type *type, int flags, const char *dev_name, void *data) { struct exofs_mountopt opts; int ret; ret = parse_options(data, &opts); if (ret) return ERR_PTR(ret); opts.dev_name = dev_name; return mount_nodev(type, flags, &opts, exofs_fill_super); } /* * Return information about the file system state in the buffer. This is used * by the 'df' command, for example. */ static int exofs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; struct exofs_sb_info *sbi = sb->s_fs_info; struct exofs_io_state *ios; struct osd_attr attrs[] = { ATTR_DEF(OSD_APAGE_PARTITION_QUOTAS, OSD_ATTR_PQ_CAPACITY_QUOTA, sizeof(__be64)), ATTR_DEF(OSD_APAGE_PARTITION_INFORMATION, OSD_ATTR_PI_USED_CAPACITY, sizeof(__be64)), }; uint64_t capacity = ULLONG_MAX; uint64_t used = ULLONG_MAX; uint8_t cred_a[OSD_CAP_LEN]; int ret; ret = exofs_get_io_state(&sbi->layout, &ios); if (ret) { EXOFS_DBGMSG("exofs_get_io_state failed.\n"); return ret; } exofs_make_credential(cred_a, &ios->obj); ios->cred = sbi->s_cred; ios->in_attr = attrs; ios->in_attr_len = ARRAY_SIZE(attrs); ret = exofs_sbi_read(ios); if (unlikely(ret)) goto out; ret = extract_attr_from_ios(ios, &attrs[0]); if (likely(!ret)) { capacity = get_unaligned_be64(attrs[0].val_ptr); if (unlikely(!capacity)) capacity = ULLONG_MAX; } else EXOFS_DBGMSG("exofs_statfs: get capacity failed.\n"); ret = extract_attr_from_ios(ios, &attrs[1]); if (likely(!ret)) used = get_unaligned_be64(attrs[1].val_ptr); else EXOFS_DBGMSG("exofs_statfs: get used-space failed.\n"); /* fill in the stats buffer */ buf->f_type = EXOFS_SUPER_MAGIC; buf->f_bsize = EXOFS_BLKSIZE; buf->f_blocks = capacity >> 9; buf->f_bfree = (capacity - used) >> 9; buf->f_bavail = buf->f_bfree; buf->f_files = sbi->s_numfiles; buf->f_ffree = EXOFS_MAX_ID - sbi->s_numfiles; buf->f_namelen = EXOFS_NAME_LEN; out: exofs_put_io_state(ios); return ret; } static const struct super_operations exofs_sops = { .alloc_inode = exofs_alloc_inode, .destroy_inode = exofs_destroy_inode, .write_inode = exofs_write_inode, .evict_inode = exofs_evict_inode, .put_super = exofs_put_super, .write_super = exofs_write_super, .sync_fs = exofs_sync_fs, .statfs = exofs_statfs, }; /****************************************************************************** * EXPORT OPERATIONS *****************************************************************************/ struct dentry *exofs_get_parent(struct dentry *child) { unsigned long ino = exofs_parent_ino(child); if (!ino) return NULL; return d_obtain_alias(exofs_iget(child->d_inode->i_sb, ino)); }
static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) { struct smb_sb_info *server; struct smb_mount_data_kernel *mnt; struct smb_mount_data *oldmnt; struct inode *root_inode; struct smb_fattr root; int ver; void *mem; static int warn_count; lock_kernel(); if (warn_count < 5) { warn_count++; printk(KERN_EMERG "smbfs is deprecated and will be removed" " from the 2.6.37 kernel. Please migrate to cifs\n"); } if (!raw_data) goto out_no_data; oldmnt = (struct smb_mount_data *) raw_data; ver = oldmnt->version; if (ver != SMB_MOUNT_OLDVERSION && cpu_to_be32(ver) != SMB_MOUNT_ASCII) goto out_wrong_data; sb->s_flags |= MS_NODIRATIME; sb->s_blocksize = 1024; /* Eh... Is this correct? */ sb->s_blocksize_bits = 10; sb->s_magic = SMB_SUPER_MAGIC; sb->s_op = &smb_sops; sb->s_time_gran = 100; server = kzalloc(sizeof(struct smb_sb_info), GFP_KERNEL); if (!server) goto out_no_server; sb->s_fs_info = server; if (bdi_setup_and_register(&server->bdi, "smbfs", BDI_CAP_MAP_COPY)) goto out_bdi; sb->s_bdi = &server->bdi; server->super_block = sb; server->mnt = NULL; server->sock_file = NULL; init_waitqueue_head(&server->conn_wq); init_MUTEX(&server->sem); INIT_LIST_HEAD(&server->entry); INIT_LIST_HEAD(&server->xmitq); INIT_LIST_HEAD(&server->recvq); server->conn_error = 0; server->conn_pid = NULL; server->state = CONN_INVALID; /* no connection yet */ server->generation = 0; /* Allocate the global temp buffer and some superblock helper structs */ /* FIXME: move these to the smb_sb_info struct */ VERBOSE("alloc chunk = %lu\n", sizeof(struct smb_ops) + sizeof(struct smb_mount_data_kernel)); mem = kmalloc(sizeof(struct smb_ops) + sizeof(struct smb_mount_data_kernel), GFP_KERNEL); if (!mem) goto out_no_mem; server->ops = mem; smb_install_null_ops(server->ops); server->mnt = mem + sizeof(struct smb_ops); /* Setup NLS stuff */ server->remote_nls = NULL; server->local_nls = NULL; mnt = server->mnt; memset(mnt, 0, sizeof(struct smb_mount_data_kernel)); strlcpy(mnt->codepage.local_name, CONFIG_NLS_DEFAULT, SMB_NLS_MAXNAMELEN); strlcpy(mnt->codepage.remote_name, SMB_NLS_REMOTE, SMB_NLS_MAXNAMELEN); mnt->ttl = SMB_TTL_DEFAULT; if (ver == SMB_MOUNT_OLDVERSION) { mnt->version = oldmnt->version; SET_UID(mnt->uid, oldmnt->uid); SET_GID(mnt->gid, oldmnt->gid); mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG; mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR; mnt->flags = (oldmnt->file_mode >> 9) | SMB_MOUNT_UID | SMB_MOUNT_GID | SMB_MOUNT_FMODE | SMB_MOUNT_DMODE; } else {
static HgfsSuperInfo * HgfsInitSuperInfo(void *rawData, // IN: Passed down from the user uint32 mountInfoVersion) // IN: version { HgfsSuperInfo *si = NULL; int result = 0; int len; char *tmpName = NULL; Bool hostValid; uint32 mntFlags = 0; uint32 ttl = 0; uid_t uid = 0; gid_t gid = 0; mode_t fmask = 0; mode_t dmask = 0; const char *shareHost; const char *shareDir; si = kmalloc(sizeof *si, GFP_KERNEL); if (!si) { result = -ENOMEM; goto out_error_si; } memset(si, 0, sizeof *si); #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) result = bdi_setup_and_register(&si->bdi, HGFS_NAME); if (result) { LOG(6, (KERN_DEBUG "VMware hgfs: %s: initialize backing device info" "failed. (%d)\n", __func__, result)); goto out_error_si; } #endif result = HgfsGetMountInfo(rawData, mountInfoVersion, &mntFlags, &ttl, &uid, &gid, &fmask, &dmask, &shareHost, &shareDir); if (result < 0) { LOG(6, (KERN_DEBUG LGPFX "%s: error: get mount info %d\n", __func__, result)); goto out_error_last; } /* * Initialize with the default flags. */ si->mntFlags = mntFlags; si->uid = current_uid(); if ((si->mntFlags & HGFS_MNT_SET_UID) != 0) { kuid_t mntUid = make_kuid(current_user_ns(), uid); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) if (uid_valid(mntUid)) #endif si->uid = mntUid; } si->gid = current_gid(); if ((si->mntFlags & HGFS_MNT_SET_GID) != 0) { kgid_t mntGid = make_kgid(current_user_ns(), gid); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) if (gid_valid(mntGid)) #endif si->gid = mntGid; } si->fmask = fmask; si->dmask = dmask; si->ttl = ttl * HZ; // in ticks /* * We don't actually care about this field (though we may care in the * future). For now, just make sure it is set to ".host" as a sanity check. * * We can't call getname() directly because on certain kernels we can't call * putname() directly. For more details, see the change description of * change 464782 or the second comment in bug 159623, which fixed the same * problem for vmblock. */ tmpName = compat___getname(); if (!tmpName) { LOG(6, (KERN_DEBUG "VMware hgfs: HgfsInitSuperInfo: could not obtain " "memory for filename\n")); result = -ENOMEM; goto out_error_last; } len = strncpy_from_user(tmpName, shareHost, PATH_MAX); if (len < 0 || len >= PATH_MAX) { LOG(6, (KERN_DEBUG "VMware hgfs: HgfsInitSuperInfo: strncpy_from_user " "on host string failed\n")); result = len < 0 ? len : -ENAMETOOLONG; goto out_error_last; } hostValid = strcmp(tmpName, ".host") == 0; if (!hostValid) { LOG(6, (KERN_DEBUG "VMware hgfs: HgfsInitSuperInfo: host string is " "invalid\n")); result = -EINVAL; goto out_error_last; } /* * Perform a simple sanity check on the directory portion: it must begin * with forward slash. */ len = strncpy_from_user(tmpName, shareDir, PATH_MAX); if (len < 0 || len >= PATH_MAX) { LOG(6, (KERN_DEBUG "VMware hgfs: HgfsInitSuperInfo: strncpy_from_user " "on dir string failed\n")); result = len < 0 ? len : -ENAMETOOLONG; goto out_error_last; } if (*tmpName != '/') { LOG(6, (KERN_DEBUG "VMware hgfs: HgfsInitSuperInfo: dir string is " "invalid\n")); result = -EINVAL; goto out_error_last; } /* * The SELinux audit subsystem will delay the putname() of a string until * the end of a system call so that it may be audited at any point. At that * time, it also unconditionally calls putname() on every string allocated * by getname(). * * This means we can't safely retain strings allocated by getname() beyond * the syscall boundary. So after getting the string, use kstrdup() to * duplicate it, and store that (audit-safe) result in the SuperInfo struct. */ si->shareName = compat_kstrdup(tmpName, GFP_KERNEL); if (si->shareName == NULL) { LOG(6, (KERN_DEBUG "VMware hgfs: HgfsInitSuperInfo: kstrdup on " "dir string failed\n")); result = -ENOMEM; goto out_error_last; } si->shareNameLen = strlen(si->shareName); out_error_last: if (tmpName) { compat___putname(tmpName); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) if (result) { bdi_destroy(&si->bdi); } #endif out_error_si: if (result) { kfree(si); si = ERR_PTR(result); } return si; }
static struct dentry *lofs_mount( struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data) { static const struct qstr slash = { .name = "/", .len = 1 }; struct super_block *s; struct lofs_sb_info *sbi; struct lofs_dentry_info *root_info; struct inode *inode; const char *err = "Getting sb failed"; struct path path; int rc; sbi = kmem_cache_zalloc(lofs_sb_info_cache, GFP_KERNEL); if (!sbi) { rc = -ENOMEM; goto out; } s = sget(fs_type, NULL, set_anon_super, NULL); if (IS_ERR(s)) { rc = PTR_ERR(s); goto out; } s->s_flags = flags; #if defined(HAVE_BACKING_DEV) rc = bdi_setup_and_register(&sbi->bdi, "lofs", BDI_CAP_MAP_COPY); if (rc) goto out1; s->s_bdi = &sbi->bdi; #endif lofs_set_superblock_private(s, sbi); /* ->kill_sb() will take care of sbi after that point */ sbi = NULL; s->s_op = &lofs_sops; s->s_d_op = &lofs_dops; err = "Reading sb failed"; rc = kern_path(slash.name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); if (rc) { lofs_printk(KERN_WARNING, "kern_path() failed\n"); goto out1; } lofs_set_superblock_lower(s, path.dentry->d_sb); s->s_maxbytes = path.dentry->d_sb->s_maxbytes; s->s_blocksize = path.dentry->d_sb->s_blocksize; s->s_magic = 0x10f5; inode = lofs_get_inode(path.dentry->d_inode, s); rc = PTR_ERR(inode); if (IS_ERR(inode)) { goto out_free; } #ifdef HAVE_D_MAKE_ROOT s->s_root = d_make_root(inode); #else s->s_root = d_alloc_root(inode); if (!s->s_root) { iput(inode); } #endif if (!s->s_root) { rc = -ENOMEM; goto out_free; } rc = -ENOMEM; root_info = kmem_cache_zalloc(lofs_dentry_info_cache, GFP_KERNEL); if (!root_info) goto out_free; /* ->kill_sb() will take care of root_info */ lofs_set_dentry_private(s->s_root, root_info); lofs_set_dentry_lower(s->s_root, path.dentry); lofs_set_dentry_lower_mnt(s->s_root, path.mnt); s->s_flags |= MS_ACTIVE; return dget(s->s_root); out_free: path_put(&path); out1: deactivate_locked_super(s); out: if (sbi) { kmem_cache_free(lofs_sb_info_cache, sbi); } printk(KERN_ERR "%s; rc = [%d]\n", err, rc); return ERR_PTR(rc); } /** * lofs_kill_block_super * @sb: The lofs super block * * Used to bring the superblock down and free the private data. */ static void lofs_kill_block_super(struct super_block *sb) { struct lofs_sb_info *sb_info = lofs_superblock_to_private(sb); kill_anon_super(sb); #if defined(HAVE_BACKING_DEV) if (sb_info) { bdi_destroy(&sb_info->bdi); } #endif kmem_cache_free(lofs_sb_info_cache, sb_info); } #else /* !HAVE_MOUNT_IN_FS_TYPE */ /** * lofs_fill_super * @sb: The lofs super block * @raw_data: The options passed to mount * @silent: Not used but required by function prototype * * Sets up what we can of the sb, rest is done in lofs_read_super * * Returns zero on success; non-zero otherwise */ static int lofs_fill_super(struct super_block *sb, void *raw_data, int silent) { int rc = 0; struct inode *inode; struct nameidata nd; /* Released in lofs_put_super() */ struct lofs_sb_info *sbi; sbi = kmem_cache_zalloc(lofs_sb_info_cache, GFP_KERNEL); if (!sbi) { lofs_printk(KERN_WARNING, "Out of memory\n"); return -ENOMEM; } lofs_set_superblock_private(sb, sbi); sb->s_op = (struct super_operations *) &lofs_sops; /* Released through deactivate_super(sb) from get_sb_nodev */ #if defined(HAVE_S_D_OP) sb->s_d_op = &lofs_dops; #endif rc = path_lookup("/", LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd); if (rc) { lofs_printk(KERN_WARNING, "path_lookup() failed\n"); return rc; } lofs_set_superblock_lower(sb, NAMEIDATA_TO_DENTRY(&nd)->d_sb); sb->s_maxbytes = NAMEIDATA_TO_DENTRY(&nd)->d_sb->s_maxbytes; sb->s_blocksize = NAMEIDATA_TO_DENTRY(&nd)->d_sb->s_blocksize; #ifdef HAVE_ADDRESS_SPACE_OPS_EXT sb->s_flags |= MS_HAS_NEW_AOPS; #endif /* Get the root inode and dentry. We have to bootstrap this one, * since it doesn't get created via the regular lookup mechanism. */ inode = lofs_get_inode(NAMEIDATA_TO_DENTRY(&nd)->d_inode, sb); if (IS_ERR(inode)) { dput(NAMEIDATA_TO_DENTRY(&nd)); mntput(NAMEIDATA_TO_VFSMNT(&nd)); return PTR_ERR(inode); } sb->s_root = d_alloc_root(inode); if (!sb->s_root) { iput(inode); dput(NAMEIDATA_TO_DENTRY(&nd)); mntput(NAMEIDATA_TO_VFSMNT(&nd)); return -ENOMEM; } lofs_set_dentry_private(sb->s_root, kmem_cache_zalloc(lofs_dentry_info_cache, GFP_KERNEL)); lofs_set_dentry_lower(sb->s_root, NAMEIDATA_TO_DENTRY(&nd)); lofs_set_dentry_lower_mnt(sb->s_root, NAMEIDATA_TO_VFSMNT(&nd)); #if !defined(HAVE_S_D_OP) sb->s_root->d_op = (struct dentry_operations *) &lofs_dops; #endif return 0; }