static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { int err; struct nameidata nd; int mtdnr; if (!dev_name) return ERR_PTR(-EINVAL); D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name)); /* The preferred way of mounting in future; especially when CONFIG_BLK_DEV is implemented - we specify the underlying MTD device by number or by name, so that we don't require block device support to be present in the kernel. */ /* FIXME: How to do the root fs this way? */ if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') { /* Probably mounting without the blkdev crap */ if (dev_name[3] == ':') { struct mtd_info *mtd; /* Mount by MTD device name */ D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4)); for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) { mtd = get_mtd_device(NULL, mtdnr); if (mtd) { if (!strcmp(mtd->name, dev_name+4)) return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); put_mtd_device(mtd); } } printk(KERN_NOTICE "jffs2_get_sb(): MTD device with name \"%s\" not found.\n", dev_name+4); } else if (isdigit(dev_name[3])) { /* Mount by MTD device number name */ char *endptr; mtdnr = simple_strtoul(dev_name+3, &endptr, 0); if (!*endptr) { /* It was a valid number */ D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr)); return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); } } } /* Try the old way - the hack where we allowed users to mount /dev/mtdblock$(n) but didn't actually _use_ the blkdev */ err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); D1(printk(KERN_DEBUG "jffs2_get_sb(): path_lookup() returned %d, inode %p\n", err, nd.dentry->d_inode)); if (err) return ERR_PTR(err); err = -EINVAL; if (!S_ISBLK(nd.dentry->d_inode->i_mode)) goto out; if (nd.mnt->mnt_flags & MNT_NODEV) { err = -EACCES; goto out; } if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) { if (!(flags & MS_VERBOSE)) /* Yes I mean this. Strangely */ printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n", dev_name); goto out; } mtdnr = iminor(nd.dentry->d_inode); path_release(&nd); return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); out: path_release(&nd); return ERR_PTR(err); }
/* * parse the dirs= mount argument * * We don't need to lock the superblock private data's rwsem, as we get * called only by unionfs_read_super - it is still a long time before anyone * can even get a reference to us. */ static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info *lower_root_info, char *options) { struct nameidata nd; char *name; int err = 0; int branches = 1; int bindex = 0; int i = 0; int j = 0; struct dentry *dent1; struct dentry *dent2; if (options[0] == '\0') { printk(KERN_ERR "unionfs: no branches specified\n"); err = -EINVAL; goto out; } /* * Each colon means we have a separator, this is really just a rough * guess, since strsep will handle empty fields for us. */ for (i = 0; options[i]; i++) if (options[i] == ':') branches++; /* allocate space for underlying pointers to lower dentry */ UNIONFS_SB(sb)->data = kcalloc(branches, sizeof(struct unionfs_data), GFP_KERNEL); if (unlikely(!UNIONFS_SB(sb)->data)) { err = -ENOMEM; goto out; } lower_root_info->lower_paths = kcalloc(branches, sizeof(struct path), GFP_KERNEL); if (unlikely(!lower_root_info->lower_paths)) { err = -ENOMEM; goto out; } /* now parsing a string such as "b1:b2=rw:b3=ro:b4" */ branches = 0; while ((name = strsep(&options, ":")) != NULL) { int perms; char *mode = strchr(name, '='); if (!name) continue; if (!*name) { /* bad use of ':' (extra colons) */ err = -EINVAL; goto out; } branches++; /* strip off '=' if any */ if (mode) *mode++ = '\0'; err = parse_branch_mode(mode, &perms); if (err) { printk(KERN_ERR "unionfs: invalid mode \"%s\" for " "branch %d\n", mode, bindex); goto out; } /* ensure that leftmost branch is writeable */ if (!bindex && !(perms & MAY_WRITE)) { printk(KERN_ERR "unionfs: leftmost branch cannot be " "read-only (use \"-o ro\" to create a " "read-only union)\n"); err = -EINVAL; goto out; } err = path_lookup(name, LOOKUP_FOLLOW, &nd); if (err) { printk(KERN_ERR "unionfs: error accessing " "lower directory '%s' (error %d)\n", name, err); goto out; } err = check_branch(&nd); if (err) { printk(KERN_ERR "unionfs: lower directory " "'%s' is not a valid branch\n", name); path_release(&nd); goto out; } lower_root_info->lower_paths[bindex].dentry = nd.dentry; lower_root_info->lower_paths[bindex].mnt = nd.mnt; set_branchperms(sb, bindex, perms); set_branch_count(sb, bindex, 0); new_branch_id(sb, bindex); if (lower_root_info->bstart < 0) lower_root_info->bstart = bindex; lower_root_info->bend = bindex; bindex++; } if (branches == 0) { printk(KERN_ERR "unionfs: no branches specified\n"); err = -EINVAL; goto out; } BUG_ON(branches != (lower_root_info->bend + 1)); /* * Ensure that no overlaps exist in the branches. * * This test is required because the Linux kernel has no support * currently for ensuring coherency between stackable layers and * branches. If we were to allow overlapping branches, it would be * possible, for example, to delete a file via one branch, which * would not be reflected in another branch. Such incoherency could * lead to inconsistencies and even kernel oopses. Rather than * implement hacks to work around some of these cache-coherency * problems, we prevent branch overlapping, for now. A complete * solution will involve proper kernel/VFS support for cache * coherency, at which time we could safely remove this * branch-overlapping test. */ for (i = 0; i < branches; i++) { dent1 = lower_root_info->lower_paths[i].dentry; for (j = i + 1; j < branches; j++) { dent2 = lower_root_info->lower_paths[j].dentry; if (is_branch_overlap(dent1, dent2)) { printk(KERN_ERR "unionfs: branches %d and " "%d overlap\n", i, j); err = -EINVAL; goto out; } } } out: if (err) { for (i = 0; i < branches; i++) if (lower_root_info->lower_paths[i].dentry) { dput(lower_root_info->lower_paths[i].dentry); /* initialize: can't use unionfs_mntput here */ mntput(lower_root_info->lower_paths[i].mnt); } kfree(lower_root_info->lower_paths); kfree(UNIONFS_SB(sb)->data); /* * MUST clear the pointers to prevent potential double free if * the caller dies later on */ lower_root_info->lower_paths = NULL; UNIONFS_SB(sb)->data = NULL; } return err; }
int file_mkdir(const char * pathname, unsigned short perms, int recurse) { /* Welcome to the jungle... */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,41) /* DO NOT REFERENCE THIS VARIABLE */ /* It only exists to provide version compatibility */ struct path tmp_path; #endif struct path * path_ptr = NULL; struct dentry * dentry; int ret = 0; if (recurse != 0) { return mkdir_recursive(pathname, perms); } /* Before Linux 3.1 this was somewhat more difficult */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,41) { struct nameidata nd; // I'm not 100% sure about the version here, but it was around this time that the API changed #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38) ret = kern_path_parent(pathname, &nd); #else if (path_lookup(pathname, LOOKUP_DIRECTORY | LOOKUP_FOLLOW, &nd) == 0) { return 0; } if (path_lookup(pathname, LOOKUP_PARENT | LOOKUP_FOLLOW, &nd) != 0) { return -1; } #endif if (ret != 0) { printk(KERN_ERR "%s:%d - Error: kern_path_parent() returned error for (%s)\n", __FILE__, __LINE__, pathname); return -1; } dentry = lookup_create(&nd, 1); path_ptr = &(nd.path); } #else { dentry = kern_path_create(AT_FDCWD, pathname, &tmp_path, 1); if (IS_ERR(dentry)) { return 0; } path_ptr = &tmp_path; } #endif if (!IS_ERR(dentry)) { ret = vfs_mkdir(path_ptr->dentry->d_inode, dentry, perms); } mutex_unlock(&(path_ptr->dentry->d_inode->i_mutex)); path_put(path_ptr); return ret; }
static int bind_unix_socket(struct socket *sock, struct cpt_sock_image *si, cpt_context_t *ctx) { int err; char *name; struct sockaddr* addr; int addrlen; struct sockaddr_un sun; struct nameidata nd; if ((addrlen = si->cpt_laddrlen) <= 2) return 0; nd.path.dentry = NULL; name = ((char*)si->cpt_laddr) + 2; addr = (struct sockaddr *)si->cpt_laddr; if (name[0]) { if (path_lookup(name, 0, &nd)) nd.path.dentry = NULL; if (si->cpt_deleted) { if (nd.path.dentry == NULL && sock->ops->bind(sock, addr, addrlen) == 0) { sc_unlink(name); return 0; } addr = (struct sockaddr*)&sun; addr->sa_family = AF_UNIX; name = ((char*)addr) + 2; err = select_deleted_name(name, ctx); if (err) goto out; addrlen = 2 + strlen(name); } else if (nd.path.dentry) { if (!S_ISSOCK(nd.path.dentry->d_inode->i_mode)) { eprintk_ctx("bind_unix_socket: not a socket dentry\n"); err = -EINVAL; goto out; } sc_unlink(name); } } err = sock->ops->bind(sock, addr, addrlen); if (!err && name[0]) { if (nd.path.dentry) { sc_chown(name, nd.path.dentry->d_inode->i_uid, nd.path.dentry->d_inode->i_gid); sc_chmod(name, nd.path.dentry->d_inode->i_mode); } if (si->cpt_deleted) sc_unlink(name); } out: if (nd.path.dentry) path_put(&nd.path); return err; }
int main(int argc, char **argv) { int ret = -1; int count; char *mybuffer, *verify_buffer; int i; char path_name[PATH_SIZE]; TROVE_op_id op_id; TROVE_coll_id coll_id; TROVE_handle file_handle, parent_handle; TROVE_ds_state state; char *file_name; TROVE_keyval_s key, val; TROVE_context_id trove_context = -1; char *mem_offset_array[4] = {0}; TROVE_size mem_size_array[4] = { 5*MB, 5*MB, 5*MB, 5*MB }; int mem_count = 4; TROVE_offset stream_offset_array[1] = {0}; TROVE_size stream_size_array[1] = { 20*MB }; int stream_count = 1; TROVE_size output_size; void *user_ptr_array[1] = { (char *) 13 }; int test_failed = 0; TROVE_extent cur_extent; TROVE_handle_extent_array extent_array; /*************************************************************/ /* initialization stuff */ ret = trove_initialize( TROVE_METHOD_DBPF, NULL, storage_space, storage_space, 0); if (ret < 0) { fprintf(stderr, "initialize failed: run trove-mkfs first.\n"); return -1; } /* try to look up collection used to store file system */ ret = trove_collection_lookup( TROVE_METHOD_DBPF, file_system, &coll_id, NULL, &op_id); if (ret < 0) { fprintf(stderr, "collection lookup failed.\n"); return -1; } ret = trove_open_context(coll_id, &trove_context); if (ret < 0) { fprintf(stderr, "trove_open_context failed\n"); return -1; } /* find the parent directory name */ strcpy(path_name, path_to_file); for (i=strlen(path_name); i >= 0; i--) { if (path_name[i] != '/') path_name[i] = '\0'; else break; } file_name = path_to_file + strlen(path_name); printf("path is %s\n", path_name); printf("file is %s\n", file_name); /* find the parent directory handle */ ret = path_lookup(coll_id, trove_context, path_name, &parent_handle); if (ret < 0) { return -1; } file_handle = 0; cur_extent.first = cur_extent.last = requested_file_handle; extent_array.extent_count = 1; extent_array.extent_array = &cur_extent; ret = trove_dspace_create(coll_id, &extent_array, &file_handle, TROVE_TEST_FILE, NULL, TROVE_FORCE_REQUESTED_HANDLE, NULL, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) { fprintf(stderr, "dspace create failed.\n"); return -1; } /* TODO: set attributes of file? */ /* add new file name/handle pair to parent directory */ key.buffer = file_name; key.buffer_sz = strlen(file_name) + 1; val.buffer = &file_handle; val.buffer_sz = sizeof(file_handle); ret = trove_keyval_write(coll_id, parent_handle, &key, &val, 0, NULL, NULL, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) { fprintf(stderr, "keyval write failed.\n"); return -1; } /* memory buffer to xfer */ mybuffer = (char *)malloc(TEST_SIZE); if (!mybuffer) { fprintf(stderr, "mem.\n"); return(-1); } verify_buffer = (char *)malloc(TEST_SIZE); if (!verify_buffer) { fprintf(stderr, "mem.\n"); return(-1); } mem_offset_array[0] = mybuffer; mem_offset_array[2] = (mem_offset_array[0] + 5*MB); mem_offset_array[1] = (mem_offset_array[2] + 5*MB); mem_offset_array[3] = (mem_offset_array[1] + 5*MB); memset(mem_offset_array[0], 0xFE, 5*MB); memset(mem_offset_array[1], 0xFD, 5*MB); memset(mem_offset_array[2], 0xFC, 5*MB); memset(mem_offset_array[3], 0xFB, 5*MB); /********************************/ ret = trove_bstream_write_list(coll_id, parent_handle, mem_offset_array, mem_size_array, mem_count, stream_offset_array, stream_size_array, stream_count, &output_size, 0, /* flags */ NULL, /* vtag */ user_ptr_array, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) { fprintf(stderr, "listio write failed\n"); return -1; } mem_offset_array[0] = verify_buffer; mem_offset_array[2] = (mem_offset_array[0] + 5*MB); mem_offset_array[1] = (mem_offset_array[2] + 5*MB); mem_offset_array[3] = (mem_offset_array[1] + 5*MB); memset(mem_offset_array[0], 0xDE, 5*MB); memset(mem_offset_array[1], 0xDD, 5*MB); memset(mem_offset_array[2], 0xDC, 5*MB); memset(mem_offset_array[3], 0xDB, 5*MB); /* should read this back out and verify here */ ret = trove_bstream_read_list(coll_id, parent_handle, mem_offset_array, mem_size_array, mem_count, stream_offset_array, stream_size_array, stream_count, &output_size, 0, /* flags */ NULL, /* vtag */ user_ptr_array, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) { fprintf(stderr, "listio read failed\n"); return -1; } for(i = 0; i < TEST_SIZE; i++) { if (mybuffer[i] != verify_buffer[i]) { fprintf(stderr,"data mismatch at index %d (%x != %x)\n", i,mybuffer[i],verify_buffer[i]); test_failed = 1; break; } /* fprintf(stderr,"data match at index %d (%x == %x)\n", */ /* i,mybuffer[i],verify_buffer[i]); */ } free(mybuffer); free(verify_buffer); fprintf(stderr,"This bstream listio test %s\n", (test_failed ? "failed miserably" : "passed")); trove_close_context(coll_id, trove_context); trove_finalize(TROVE_METHOD_DBPF); return 0; }
static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) { /* client fsidtype fsid [path] */ char *buf; int len; struct auth_domain *dom = NULL; int err; int fsidtype; char *ep; struct svc_expkey key; if (mesg[mlen-1] != '\n') return -EINVAL; mesg[mlen-1] = 0; buf = kmalloc(PAGE_SIZE, GFP_KERNEL); err = -ENOMEM; if (!buf) goto out; err = -EINVAL; if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0) goto out; err = -ENOENT; dom = auth_domain_find(buf); if (!dom) goto out; dprintk("found domain %s\n", buf); err = -EINVAL; if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0) goto out; fsidtype = simple_strtoul(buf, &ep, 10); if (*ep) goto out; dprintk("found fsidtype %d\n", fsidtype); if (fsidtype > 2) goto out; if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0) goto out; dprintk("found fsid length %d\n", len); if (len != key_len(fsidtype)) goto out; /* OK, we seem to have a valid key */ key.h.flags = 0; key.h.expiry_time = get_expiry(&mesg); if (key.h.expiry_time == 0) goto out; key.ek_client = dom; key.ek_fsidtype = fsidtype; memcpy(key.ek_fsid, buf, len); /* now we want a pathname, or empty meaning NEGATIVE */ if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0) goto out; dprintk("Path seems to be <%s>\n", buf); err = 0; if (len == 0) { struct svc_expkey *ek; set_bit(CACHE_NEGATIVE, &key.h.flags); ek = svc_expkey_lookup(&key, 1); if (ek) expkey_put(&ek->h, &svc_expkey_cache); } else { struct nameidata nd; struct svc_expkey *ek; struct svc_export *exp; err = path_lookup(buf, 0, &nd); if (err) goto out; dprintk("Found the path %s\n", buf); exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL); err = -ENOENT; if (!exp) goto out_nd; key.ek_export = exp; dprintk("And found export\n"); ek = svc_expkey_lookup(&key, 1); if (ek) expkey_put(&ek->h, &svc_expkey_cache); exp_put(exp); err = 0; out_nd: path_release(&nd); } cache_flush(); out: if (dom) auth_domain_put(dom); if (buf) kfree(buf); return err; }
int main(int argc, char **argv) { int ret = -1; int count; void* mybuffer; int i; char path_name[PATH_SIZE]; TROVE_op_id op_id; TROVE_coll_id coll_id; TROVE_handle file_handle, parent_handle; TROVE_ds_state state; char *file_name; TROVE_keyval_s key, val; TROVE_context_id trove_context = -1; char *mem_offset_array[1]; TROVE_size mem_size_array[1] = { 4*1048576 }; int mem_count = 1; TROVE_offset stream_offset_array[1] = { 0 }; TROVE_size stream_size_array[1] = { 4*1048576 }; int stream_count = 1; TROVE_size output_size; void *user_ptr_array[1] = { (char *) 13 }; TROVE_extent cur_extent; TROVE_handle_extent_array extent_array; /*************************************************************/ /* initialization stuff */ ret = trove_initialize( TROVE_METHOD_DBPF, NULL, storage_space, 0); if (ret < 0) { fprintf(stderr, "initialize failed: run trove-mkfs first.\n"); return -1; } /* try to look up collection used to store file system */ ret = trove_collection_lookup( TROVE_METHOD_DBPF, file_system, &coll_id, NULL, &op_id); if (ret < 0) { fprintf(stderr, "collection lookup failed.\n"); return -1; } ret = trove_open_context(coll_id, &trove_context); if (ret < 0) { fprintf(stderr, "trove_open_context failed\n"); return -1; } /* find the parent directory name */ strcpy(path_name, path_to_file); for (i=strlen(path_name); i >= 0; i--) { if (path_name[i] != '/') path_name[i] = '\0'; else break; } file_name = path_to_file + strlen(path_name); printf("path is %s\n", path_name); printf("file is %s\n", file_name); /* find the parent directory handle */ ret = path_lookup(coll_id, trove_context, path_name, &parent_handle); if (ret < 0) { return -1; } file_handle = 0; cur_extent.first = cur_extent.last = requested_file_handle; extent_array.extent_count = 1; extent_array.extent_array = &cur_extent; ret = trove_dspace_create(coll_id, &extent_array, &file_handle, TROVE_TEST_FILE, NULL, TROVE_FORCE_REQUESTED_HANDLE, NULL, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) { fprintf(stderr, "dspace create failed.\n"); return -1; } /* TODO: set attributes of file? */ /* add new file name/handle pair to parent directory */ key.buffer = file_name; key.buffer_sz = strlen(file_name) + 1; val.buffer = &file_handle; val.buffer_sz = sizeof(file_handle); ret = trove_keyval_write(coll_id, parent_handle, &key, &val, 0, NULL, NULL, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) { fprintf(stderr, "keyval write failed.\n"); return -1; } /* memory buffer to xfer */ mybuffer = (void*)malloc(TEST_SIZE); if(!mybuffer) { fprintf(stderr, "mem.\n"); return(-1); } memset(mybuffer, 0, TEST_SIZE); mem_offset_array[0] = mybuffer; /********************************/ ret = trove_bstream_write_list(coll_id, parent_handle, mem_offset_array, mem_size_array, mem_count, stream_offset_array, stream_size_array, stream_count, &output_size, 0, /* flags */ NULL, /* vtag */ user_ptr_array, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) { fprintf(stderr, "listio write failed\n"); return -1; } trove_close_context(coll_id, trove_context); trove_finalize(TROVE_METHOD_DBPF); return 0; }
/* * Check if the given path is a mountpoint. * * If we are supplied with the file descriptor of an autofs * mount we're looking for a specific mount. In this case * the path is considered a mountpoint if it is itself a * mountpoint or contains a mount, such as a multi-mount * without a root mount. In this case we return 1 if the * path is a mount point and the super magic of the covering * mount if there is one or 0 if it isn't a mountpoint. * * If we aren't supplied with a file descriptor then we * lookup the nameidata of the path and check if it is the * root of a mount. If a type is given we are looking for * a particular autofs mount and if we don't find a match * we return fail. If the located nameidata path is the * root of a mount we return 1 along with the super magic * of the mount or 0 otherwise. * * In both cases the the device number (as returned by * new_encode_dev()) is also returned. */ static int autofs_dev_ioctl_ismountpoint(struct file *fp, struct autofs_sb_info *sbi, struct autofs_dev_ioctl *param) { struct nameidata nd; const char *path; unsigned int type; int err = -ENOENT; if (param->size <= sizeof(*param)) { err = -EINVAL; goto out; } path = param->path; type = param->arg1; param->arg1 = 0; param->arg2 = 0; if (!fp || param->ioctlfd == -1) { if (type == AUTOFS_TYPE_ANY) { struct super_block *sb; err = path_lookup(path, LOOKUP_FOLLOW, &nd); if (err) goto out; sb = nd.path.dentry->d_sb; param->arg1 = new_encode_dev(sb->s_dev); } else { struct autofs_info *ino; err = path_lookup(path, LOOKUP_PARENT, &nd); if (err) goto out; err = autofs_dev_ioctl_find_sbi_type(&nd, type); if (err) goto out_release; ino = autofs4_dentry_ino(nd.path.dentry); param->arg1 = autofs4_get_dev(ino->sbi); } err = 0; if (nd.path.dentry->d_inode && nd.path.mnt->mnt_root == nd.path.dentry) { err = 1; param->arg2 = nd.path.dentry->d_inode->i_sb->s_magic; } } else { dev_t devid = new_encode_dev(sbi->sb->s_dev); err = path_lookup(path, LOOKUP_PARENT, &nd); if (err) goto out; err = autofs_dev_ioctl_find_super(&nd, devid); if (err) goto out_release; param->arg1 = autofs4_get_dev(sbi); err = have_submounts(nd.path.dentry); if (nd.path.mnt->mnt_mountpoint != nd.path.mnt->mnt_root) { if (follow_down(&nd.path.mnt, &nd.path.dentry)) { struct inode *inode = nd.path.dentry->d_inode; param->arg2 = inode->i_sb->s_magic; } } } out_release: path_put(&nd.path); out: return err; }
int main(int argc, char **argv) { int ret, count, i, myuid, mygid; TROVE_op_id op_id; TROVE_coll_id coll_id; TROVE_handle file_handle, parent_handle; TROVE_ds_state state; TROVE_keyval_s key, val; TROVE_ds_attributes_s s_attr; char *file_name; char path_name[PATH_SIZE]; time_t mytime; TROVE_extent cur_extent; TROVE_handle_extent_array extent_array; TROVE_context_id trove_context = -1; ret = parse_args(argc, argv); if (ret < 0) { fprintf(stderr, "argument parsing failed.\n"); return -1; } ret = trove_initialize( TROVE_METHOD_DBPF, NULL, storage_space, 0); if (ret < 0) { fprintf(stderr, "initialize failed.\n"); return -1; } /* try to look up collection used to store file system */ ret = trove_collection_lookup( TROVE_METHOD_DBPF, file_system, &coll_id, NULL, &op_id); if (ret < 0) { fprintf(stderr, "collection lookup failed.\n"); return -1; } ret = trove_open_context(coll_id, &trove_context); if (ret < 0) { fprintf(stderr, "trove_open_context failed\n"); return -1; } myuid = getuid(); mygid = getgid(); mytime = time(NULL); /* find the parent directory name */ strcpy(path_name, path_to_file); for (i=strlen(path_name); i >= 0; i--) { if (path_name[i] != '/') path_name[i] = '\0'; else break; } file_name = path_to_file + strlen(path_name); #if 0 printf("path is %s\n", path_name); printf("file is %s\n", file_name); #endif /* find the parent directory handle */ ret = path_lookup(coll_id, path_name, &parent_handle); if (ret < 0) { return -1; } /* TODO: verify that this is in fact a directory! */ for (i=0; i < file_count; i++) { char tmp_file_name[PATH_SIZE]; file_handle = 0; cur_extent.first = cur_extent.last = requested_file_handle; extent_array.extent_count = 1; extent_array.extent_array = &cur_extent; ret = trove_dspace_create(coll_id, &extent_array, &file_handle, TROVE_TEST_FILE, NULL, TROVE_FORCE_REQUESTED_HANDLE, NULL, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) { fprintf(stderr, "dspace create failed.\n"); return -1; } s_attr.fs_id = coll_id; /* for now */ s_attr.handle = file_handle; s_attr.type = TROVE_TEST_FILE; /* shouldn't need to fill this one in. */ s_attr.uid = myuid; s_attr.gid = mygid; s_attr.mode = 0755; s_attr.ctime = mytime; count = 1; ret = trove_dspace_setattr(coll_id, file_handle, &s_attr, 0 /* flags */, NULL /* user ptr */, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) return -1; /* add new file name/handle pair to parent directory */ snprintf(tmp_file_name, PATH_SIZE, "%s/file%d", path_name, i); key.buffer = tmp_file_name; key.buffer_sz = strlen(tmp_file_name) + 1; val.buffer = &file_handle; val.buffer_sz = sizeof(file_handle); ret = trove_keyval_write(coll_id, parent_handle, &key, &val, 0, NULL, NULL, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) { fprintf(stderr, "keyval write failed.\n"); return -1; } } trove_close_context(coll_id, trove_context); trove_finalize(TROVE_METHOD_DBPF); return 0; }
int unionfs_ioctl_addbranch(struct inode *inode, unsigned int cmd, unsigned long arg) { int err; struct unionfs_addbranch_args *addargs = NULL; struct nameidata nd; char *path = NULL; int gen; int i; int pobjects; struct unionfs_usi_data *new_data = NULL; struct dentry **new_udi_dentry = NULL; struct inode **new_uii_inode = NULL; struct dentry *root = NULL; struct dentry *hidden_root = NULL; print_entry_location(); err = -ENOMEM; addargs = KMALLOC(sizeof(struct unionfs_addbranch_args), GFP_KERNEL); if (!addargs) goto out; err = -EFAULT; if (copy_from_user (addargs, (const void __user *)arg, sizeof(struct unionfs_addbranch_args))) goto out; err = -EINVAL; if (addargs->ab_perms & ~(MAY_READ | MAY_WRITE | MAY_NFSRO)) goto out; if (!(addargs->ab_perms & MAY_READ)) goto out; err = -E2BIG; if (sbend(inode->i_sb) > FD_SETSIZE) goto out; err = -ENOMEM; if (!(path = getname((const char __user *)addargs->ab_path))) goto out; err = path_lookup(path, LOOKUP_FOLLOW, &nd); RECORD_PATH_LOOKUP(&nd); if (err) goto out; if ((err = check_branch(&nd))) { path_release(&nd); RECORD_PATH_RELEASE(&nd); goto out; } unionfs_write_lock(inode->i_sb); lock_dentry(inode->i_sb->s_root); root = inode->i_sb->s_root; for (i = dbstart(inode->i_sb->s_root); i <= dbend(inode->i_sb->s_root); i++) { hidden_root = dtohd_index(root, i); if (is_branch_overlap(hidden_root, nd.dentry)) { err = -EINVAL; goto out; } } err = -EINVAL; if (addargs->ab_branch < 0 || (addargs->ab_branch > (sbend(inode->i_sb) + 1))) goto out; if ((err = newputmap(inode->i_sb))) goto out; stopd(inode->i_sb)->b_end++; dtopd(inode->i_sb->s_root)->udi_bcount++; set_dbend(inode->i_sb->s_root, dbend(inode->i_sb->s_root) + 1); itopd(inode->i_sb->s_root->d_inode)->b_end++; atomic_inc(&stopd(inode->i_sb)->usi_generation); gen = atomic_read(&stopd(inode->i_sb)->usi_generation); pobjects = sbend(inode->i_sb) + 1; /* Reallocate the dynamic structures. */ new_data = alloc_new_data(pobjects); new_udi_dentry = alloc_new_dentries(pobjects); new_uii_inode = KZALLOC(sizeof(struct inode *) * pobjects, GFP_KERNEL); if (!new_udi_dentry || !new_uii_inode || !new_data) { err = -ENOMEM; goto out; } /* Copy the in-place values to our new structure. */ for (i = 0; i < addargs->ab_branch; i++) { atomic_set(&(new_data[i].sbcount), branch_count(inode->i_sb, i)); new_data[i].branchperms = branchperms(inode->i_sb, i); new_data[i].hidden_mnt = stohiddenmnt_index(inode->i_sb, i); new_data[i].sb = stohs_index(inode->i_sb, i); new_udi_dentry[i] = dtohd_index(inode->i_sb->s_root, i); new_uii_inode[i] = itohi_index(inode->i_sb->s_root->d_inode, i); } /* Shift the ends to the right (only handle reallocated bits). */ for (i = sbend(inode->i_sb) - 1; i >= (int)addargs->ab_branch; i--) { int j = i + 1; int pmindex; atomic_set(&new_data[j].sbcount, branch_count(inode->i_sb, i)); new_data[j].branchperms = branchperms(inode->i_sb, i); new_data[j].hidden_mnt = stohiddenmnt_index(inode->i_sb, i); new_data[j].sb = stohs_index(inode->i_sb, i); new_udi_dentry[j] = dtohd_index(inode->i_sb->s_root, i); new_uii_inode[j] = itohi_index(inode->i_sb->s_root->d_inode, i); /* Update the newest putmap, so it is correct for later. */ pmindex = stopd(inode->i_sb)->usi_lastputmap; pmindex -= stopd(inode->i_sb)->usi_firstputmap; stopd(inode->i_sb)->usi_putmaps[pmindex]->map[i] = j; } /* Now we can free the old ones. */ KFREE(dtopd(inode->i_sb->s_root)->udi_dentry); KFREE(itopd(inode->i_sb->s_root->d_inode)->uii_inode); KFREE(stopd(inode->i_sb)->usi_data); /* Update the real pointers. */ dtohd_ptr(inode->i_sb->s_root) = new_udi_dentry; itohi_ptr(inode->i_sb->s_root->d_inode) = new_uii_inode; stopd(inode->i_sb)->usi_data = new_data; /* Re-NULL the new ones so we don't try to free them. */ new_data = NULL; new_udi_dentry = NULL; new_uii_inode = NULL; /* Put the new dentry information into it's slot. */ set_dtohd_index(inode->i_sb->s_root, addargs->ab_branch, nd.dentry); set_itohi_index(inode->i_sb->s_root->d_inode, addargs->ab_branch, IGRAB(nd.dentry->d_inode)); set_branchperms(inode->i_sb, addargs->ab_branch, addargs->ab_perms); set_branch_count(inode->i_sb, addargs->ab_branch, 0); set_stohiddenmnt_index(inode->i_sb, addargs->ab_branch, nd.mnt); set_stohs_index(inode->i_sb, addargs->ab_branch, nd.dentry->d_sb); atomic_set(&dtopd(inode->i_sb->s_root)->udi_generation, gen); atomic_set(&itopd(inode->i_sb->s_root->d_inode)->uii_generation, gen); fixputmaps(inode->i_sb); out: unlock_dentry(inode->i_sb->s_root); unionfs_write_unlock(inode->i_sb); KFREE(new_udi_dentry); KFREE(new_uii_inode); KFREE(new_data); KFREE(addargs); if (path) putname(path); print_exit_status(err); return err; }
int main( int argc, char **argv) { int ret = -1; int outcount = 0, count; struct BMI_unexpected_info request_info; flow_descriptor *flow_d = NULL; double time1, time2; int i; PINT_Request *req; char path_name[PATH_SIZE]; TROVE_op_id op_id; TROVE_coll_id coll_id; TROVE_handle file_handle, parent_handle; TROVE_ds_state state; char *file_name; TROVE_keyval_s key, val; bmi_context_id context; TROVE_context_id trove_context; PVFS_handle_extent cur_extent; PVFS_handle_extent_array extent_array; /*************************************************************/ /* initialization stuff */ /* set debugging level */ gossip_enable_stderr(); gossip_set_debug_mask( 0, (GOSSIP_FLOW_PROTO_DEBUG | GOSSIP_BMI_DEBUG_TCP)); /* Init dists */ PINT_dist_initialize(NULL); /* start up BMI */ ret = BMI_initialize("bmi_tcp", "tcp://NULL:3335", BMI_INIT_SERVER); if (ret < 0) { fprintf(stderr, "BMI init failure.\n"); return (-1); } ret = BMI_open_context(&context); if (ret < 0) { fprintf(stderr, "BMI_open_context() failure.\n"); return (-1); } ret = trove_initialize( TROVE_METHOD_DBPF, NULL, storage_space, storage_space, 0); if (ret < 0) { fprintf(stderr, "initialize failed: run trove-mkfs first.\n"); return -1; } /* initialize the flow interface */ ret = PINT_flow_initialize("flowproto_multiqueue", 0); if (ret < 0) { fprintf(stderr, "flow init failure.\n"); return (-1); } /* try to look up collection used to store file system */ ret = trove_collection_lookup( TROVE_METHOD_DBPF, file_system, &coll_id, NULL, &op_id); if (ret < 0) { fprintf(stderr, "collection lookup failed.\n"); return -1; } ret = trove_open_context(coll_id, &trove_context); if (ret < 0) { fprintf(stderr, "TROVE_open_context() failure.\n"); return (-1); } /* find the parent directory name */ strcpy(path_name, path_to_file); for (i = strlen(path_name); i >= 0; i--) { if (path_name[i] != '/') path_name[i] = '\0'; else break; } file_name = path_to_file + strlen(path_name); printf("path is %s\n", path_name); printf("file is %s\n", file_name); /* find the parent directory handle */ ret = path_lookup(coll_id, trove_context, path_name, &parent_handle); if (ret < 0) { return -1; } file_handle = 0; cur_extent.first = cur_extent.last = requested_file_handle; extent_array.extent_count = 1; extent_array.extent_array = &cur_extent; ret = trove_dspace_create(coll_id, &extent_array, &file_handle, TROVE_TEST_FILE, NULL, TROVE_FORCE_REQUESTED_HANDLE, NULL, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test(coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) { fprintf(stderr, "dspace create failed.\n"); return -1; } /* TODO: set attributes of file? */ /* add new file name/handle pair to parent directory */ key.buffer = file_name; key.buffer_sz = strlen(file_name) + 1; val.buffer = &file_handle; val.buffer_sz = sizeof(file_handle); ret = trove_keyval_write(coll_id, parent_handle, &key, &val, 0, NULL, NULL, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test(coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) { fprintf(stderr, "keyval write failed.\n"); return -1; } /* wait for an initial communication via BMI */ /* we don't give a crap about that message except that it tells us * where to find the client */ do { ret = BMI_testunexpected(1, &outcount, &request_info, 10); } while (ret == 0 && outcount == 0); if (ret < 0 || request_info.error_code != 0) { fprintf(stderr, "waitunexpected failure.\n"); return (-1); } BMI_unexpected_free(request_info.addr, request_info.buffer); /******************************************************/ /* setup request/dist stuff */ /* request description */ /* just want one contiguous region */ ret = PVFS_Request_contiguous(TEST_SIZE, PVFS_BYTE, &req); if (ret < 0) { fprintf(stderr, "PVFS_Request_contiguous() failure.\n"); return (-1); } /******************************************************/ /* setup communicaton stuff */ /* create a flow descriptor */ flow_d = PINT_flow_alloc(); if (!flow_d) { fprintf(stderr, "flow_alloc failed.\n"); return (-1); } /* file data */ flow_d->file_data.fsize = TEST_SIZE; flow_d->file_data.server_nr = 0; flow_d->file_data.server_ct = 1; flow_d->file_data.extend_flag = 1; flow_d->file_data.dist = PINT_dist_create("basic_dist"); if (!flow_d->file_data.dist) { fprintf(stderr, "Error: failed to create dist.\n"); return (-1); } ret = PINT_dist_lookup(flow_d->file_data.dist); if (ret != 0) { fprintf(stderr, "Error: failed to lookup dist.\n"); return (-1); } flow_d->file_req = req; flow_d->tag = 0; flow_d->user_ptr = NULL; flow_d->aggregate_size = TEST_SIZE; /* fill in flow details */ flow_d->src.endpoint_id = BMI_ENDPOINT; flow_d->src.u.bmi.address = request_info.addr; flow_d->dest.endpoint_id = TROVE_ENDPOINT; flow_d->dest.u.trove.handle = file_handle; flow_d->dest.u.trove.coll_id = coll_id; /*************************************************** * test bmi to file (analogous to a client side write) */ time1 = Wtime(); ret = block_on_flow(flow_d); if (ret < 0) { return (-1); } time2 = Wtime(); #if 0 printf("Server bw (recv): %f MB/sec\n", ((TEST_SIZE) / ((time2 - time1) * 1000000.0))); #endif /*******************************************************/ /* final cleanup and output */ PINT_flow_free(flow_d); /* shut down flow interface */ ret = PINT_flow_finalize(); if (ret < 0) { fprintf(stderr, "flow finalize failure.\n"); return (-1); } /* shut down BMI */ BMI_close_context(context); BMI_finalize(); trove_close_context(coll_id, trove_context); trove_finalize(TROVE_METHOD_DBPF); gossip_disable(); return (0); }
int main(int argc, char **argv) { int ret, count, i, fd; TROVE_op_id op_id; TROVE_coll_id coll_id; TROVE_handle file_handle, parent_handle; TROVE_ds_state state; TROVE_keyval_s key, val; TROVE_ds_attributes_s s_attr; TROVE_size f_size; char *file_name; char path_name[PATH_SIZE]; char *buf; TROVE_context_id trove_context = -1; ret = parse_args(argc, argv); if (ret < 0) { fprintf(stderr, "argument parsing failed.\n"); return -1; } if (optind + 1 >= argc) return -1; strcpy(path_to_file, argv[optind]); strcpy(path_to_unix, argv[optind+1]); ret = trove_initialize( TROVE_METHOD_DBPF, NULL, storage_space, 0); if (ret < 0) { fprintf(stderr, "initialize failed.\n"); return -1; } /* try to look up collection used to store file system */ ret = trove_collection_lookup( TROVE_METHOD_DBPF, file_system, &coll_id, NULL, &op_id); if (ret < 0) { fprintf(stderr, "collection lookup failed.\n"); return -1; } ret = trove_open_context(coll_id, &trove_context); if (ret < 0) { fprintf(stderr, "trove_open_context failed\n"); return -1; } /* find the parent directory name */ strcpy(path_name, path_to_file); for (i=strlen(path_name); i >= 0; i--) { if (path_name[i] != '/') path_name[i] = '\0'; else break; } file_name = path_to_file + strlen(path_name); #if 0 printf("path is %s\n", path_name); printf("file is %s\n", file_name); #endif /* find the parent directory handle */ ret = path_lookup(coll_id, path_name, &parent_handle); if (ret < 0) { return -1; } /* add new file name/handle pair to parent directory */ key.buffer = file_name; key.buffer_sz = strlen(file_name) + 1; val.buffer = &file_handle; val.buffer_sz = sizeof(file_handle); ret = trove_keyval_read(coll_id, parent_handle, &key, &val, 0, NULL, NULL, trove_context, &op_id, NULL); count = 1; while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) { fprintf(stderr, "keyval read failed.\n"); return -1; } ret = trove_dspace_getattr(coll_id, file_handle, &s_attr, 0 /* flags */, NULL, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) return -1; /* get a buffer */ buf = (char *) malloc((size_t) s_attr.u.datafile.b_size); if (buf == NULL) return -1; f_size = s_attr.u.datafile.b_size; /* read data from trove file */ ret = trove_bstream_read_at(coll_id, file_handle, buf, &f_size, 0, /* offset */ 0, /* flags */ NULL, /* vtag */ NULL, /* user ptr */ trove_context, &op_id, NULL); count = 1; while ( ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0 ) { fprintf(stderr, "bstream write failed.\n"); return -1; } /* open up the unix file */ fd = open(path_to_unix, O_RDWR | O_CREAT, 0644); if (fd < 0) { perror("open"); return -1; } /* write data to file */ write(fd, buf, f_size); close(fd); trove_close_context(coll_id, trove_context); trove_finalize(TROVE_METHOD_DBPF); #if 0 printf("created file %s (handle = %d)\n", file_name, (int) file_handle); #endif return 0; }
static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info *hidden_root_info, char *options) { struct nameidata nd; char *name; int err = 0; int branches = 1; int bindex = 0; int i = 0; int j = 0; struct dentry *dent1 = NULL; struct dentry *dent2 = NULL; if (options[0] == '\0') { printk(KERN_WARNING "unionfs: no branches specified\n"); err = -EINVAL; goto out; } /* Each colon means we have a separator, this is really just a rough * guess, since strsep will handle empty fields for us. */ for (i = 0; options[i]; i++) { if (options[i] == ':') branches++; } /* allocate space for underlying pointers to hidden dentry */ if (!(stopd(sb)->usi_data = alloc_new_data(branches))) { err = -ENOMEM; goto out; } if (!(hidden_root_info->udi_dentry = alloc_new_dentries(branches))) { err = -ENOMEM; goto out; } /* now parsing the string b1:b2=rw:b3=ro:b4 */ branches = 0; while ((name = strsep(&options, ":")) != NULL) { int perms; if (!*name) continue; branches++; /* strip off =rw or =ro if it is specified. */ perms = parse_branch_mode(name); if (!bindex && !(perms & MAY_WRITE)) { err = -EINVAL; goto out; } fist_dprint(4, "unionfs: using directory: %s (%c%c%c)\n", name, perms & MAY_READ ? 'r' : '-', perms & MAY_WRITE ? 'w' : '-', perms & MAY_NFSRO ? 'n' : '-'); err = path_lookup(name, LOOKUP_FOLLOW, &nd); RECORD_PATH_LOOKUP(&nd); if (err) { printk(KERN_WARNING "unionfs: error accessing " "hidden directory '%s' (error %d)\n", name, err); goto out; } if ((err = check_branch(&nd))) { printk(KERN_WARNING "unionfs: hidden directory " "'%s' is not a valid branch\n", name); path_release(&nd); RECORD_PATH_RELEASE(&nd); goto out; } hidden_root_info->udi_dentry[bindex] = nd.dentry; set_stohiddenmnt_index(sb, bindex, nd.mnt); set_branchperms(sb, bindex, perms); set_branch_count(sb, bindex, 0); if (hidden_root_info->udi_bstart < 0) hidden_root_info->udi_bstart = bindex; hidden_root_info->udi_bend = bindex; bindex++; } if (branches == 0) { printk(KERN_WARNING "unionfs: no branches specified\n"); err = -EINVAL; goto out; } BUG_ON(branches != (hidden_root_info->udi_bend + 1)); /* ensure that no overlaps exist in the branches */ for (i = 0; i < branches; i++) { for (j = i + 1; j < branches; j++) { dent1 = hidden_root_info->udi_dentry[i]; dent2 = hidden_root_info->udi_dentry[j]; if (is_branch_overlap(dent1, dent2)) { goto out_overlap; } } } out_overlap: if (i != branches) { printk(KERN_WARNING "unionfs: branches %d and %d overlap\n", i, j); err = -EINVAL; goto out; } out: if (err) { for (i = 0; i < branches; i++) { if (hidden_root_info->udi_dentry[i]) DPUT(hidden_root_info->udi_dentry[i]); } KFREE(hidden_root_info->udi_dentry); KFREE(stopd(sb)->usi_data); /* MUST clear the pointers to prevent potential double free if * the caller dies later on */ hidden_root_info->udi_dentry = NULL; stopd(sb)->usi_data = NULL; } return err; }
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; }
int main(int argc, char **argv) { int ret, count, i; char *file_name; char path_name[PATH_SIZE]; TROVE_op_id op_id; TROVE_coll_id coll_id; TROVE_handle file_handle, parent_handle; TROVE_ds_state state; TROVE_keyval_s key, val; TROVE_ds_attributes_s s_attr; TROVE_context_id trove_context = -1; ret = parse_args(argc, argv); if (ret < 0) { fprintf(stderr, "argument parsing failed.\n"); return -1; } ret = trove_initialize( TROVE_METHOD_DBPF, NULL, storage_space, storage_space, 0); if (ret < 0) { fprintf(stderr, "initialize failed.\n"); return -1; } /* try to look up collection used to store file system */ ret = trove_collection_lookup( TROVE_METHOD_DBPF, file_system, &coll_id, NULL, &op_id); if (ret < 0) { fprintf(stderr, "collection lookup failed.\n"); return -1; } ret = trove_open_context(coll_id, &trove_context); if (ret < 0) { fprintf(stderr, "trove_open_context failed\n"); return -1; } /* find the parent directory name */ strcpy(path_name, path_to_file); for (i=strlen(path_name); i >= 0; i--) { if (path_name[i] != '/') path_name[i] = '\0'; else break; } file_name = path_to_file + strlen(path_name); #if 0 printf("path is %s\n", path_name); printf("file is %s\n", file_name); #endif /* find the parent directory handle */ ret = path_lookup(coll_id, path_name, &parent_handle); if (ret < 0) { return -1; } /* TODO: make a is_dir function... maybe make a full blown stat(2)? */ /* look up the handle for the file */ memset(&key, 0, sizeof(key)); memset(&val, 0, sizeof(val)); key.buffer = file_name; key.buffer_sz = strlen(file_name)+1; val.buffer = &file_handle; val.buffer_sz = sizeof(TROVE_handle); /* it would be smart to verify that this is a directory first... */ ret = trove_keyval_read(coll_id, parent_handle, &key, &val, 0, NULL, NULL, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if ( ret < 0 || state == -1) { fprintf(stderr, "read failed for key %s\n", file_name); return -1; } ret = trove_dspace_getattr(coll_id, file_handle, &s_attr, 0 /* flags */, NULL, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) return -1; /* 'handles are everything': now that we've gotten a handle from the * file_name, we can wipe the keyval (via name) and the dspace (via * handle)*/ key.buffer = file_name; key.buffer_sz = strlen(file_name)+1; ret = trove_keyval_remove(coll_id, parent_handle, &key, NULL, 0, NULL, NULL, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0 ) { fprintf(stderr, "removal failed for %s\n", file_name); return -1; } /* the question: is it up to the caller to clean up the dspace if it removed the last entry? no no no*/ /* gar gar being dense: the dspace gets removed. */ ret = trove_dspace_remove(coll_id, file_handle, TROVE_SYNC, NULL, trove_context, &op_id, NULL); while (ret == 0) ret = trove_dspace_test( coll_id, op_id, trove_context, &count, NULL, NULL, &state, TROVE_DEFAULT_TEST_TIMEOUT); if (ret < 0) { fprintf(stderr, "dspace remove failed.\n"); return -1; } trove_close_context(coll_id, trove_context); trove_finalize(TROVE_METHOD_DBPF); printf("file %s removed (file handle = %d, parent handle = %d).\n", file_name, (int) file_handle, (int) parent_handle); return 0; }