/* this is common implementation of set_plug_in_inode method of file plugin */ int set_plug_in_inode_common(struct inode *object /* inode to set plugin on */ , struct inode *parent /* parent object */ , reiser4_object_create_data * data /* creational * data */ ) { __u64 mask; object->i_mode = data->mode; /* this should be plugin decision */ object->i_uid = current->cred->fsuid; object->i_mtime = object->i_atime = object->i_ctime = CURRENT_TIME; /* support for BSD style group-id assignment. See mount's manual page description of bsdgroups ext2 mount options for more details */ if (reiser4_is_set(object->i_sb, REISER4_BSD_GID)) object->i_gid = parent->i_gid; else if (parent->i_mode & S_ISGID) { /* parent directory has sguid bit */ object->i_gid = parent->i_gid; if (S_ISDIR(object->i_mode)) /* sguid is inherited by sub-directories */ object->i_mode |= S_ISGID; } else object->i_gid = current->cred->fsgid; /* this object doesn't have stat-data yet */ reiser4_inode_set_flag(object, REISER4_NO_SD); #if 0 /* this is now called after all inode plugins are initialized: do_create_vfs_child after adjust_to_parent */ /* setup inode and file-operations for this inode */ setup_inode_ops(object, data); #endif object->i_nlink = 0; reiser4_seal_init(&reiser4_inode_data(object)->sd_seal, NULL, NULL); mask = (1 << UNIX_STAT) | (1 << LIGHT_WEIGHT_STAT); if (!reiser4_is_set(object->i_sb, REISER4_32_BIT_TIMES)) mask |= (1 << LARGE_TIMES_STAT); reiser4_inode_data(object)->extmask = mask; return 0; }
static int change_file(struct inode *inode, reiser4_plugin * plugin, pset_member memb) { /* cannot change object plugin of already existing object */ if (memb == PSET_FILE) return RETERR(-EINVAL); /* Change PSET_CREATE */ return aset_set_unsafe(&reiser4_inode_data(inode)->pset, memb, plugin); }
/* this is common implementation of key_by_inode method of file plugin */ int key_by_inode_and_offset_common(struct inode *inode, loff_t off, reiser4_key * key) { reiser4_key_init(key); set_key_locality(key, reiser4_inode_data(inode)->locality_id); set_key_ordering(key, get_inode_ordering(inode)); set_key_objectid(key, get_inode_oid(inode)); /*FIXME: inode->i_ino */ set_key_type(key, KEY_BODY_MINOR); set_key_offset(key, (__u64) off); return 0; }
static int change_cluster(struct inode *inode, reiser4_plugin * plugin, pset_member memb) { assert("edward-1324", inode != NULL); assert("edward-1325", plugin != NULL); assert("edward-1326", is_reiser4_inode(inode)); assert("edward-1327", plugin->h.type_id == REISER4_CLUSTER_PLUGIN_TYPE); /* Can't change the cluster plugin for already existent regular files */ if (!plugin_of_group(inode_file_plugin(inode), REISER4_DIRECTORY_FILE)) return RETERR(-EINVAL); /* If matches, nothing to change. */ if (inode_hash_plugin(inode) != NULL && inode_hash_plugin(inode)->h.id == plugin->h.id) return 0; return aset_set_unsafe(&reiser4_inode_data(inode)->pset, PSET_CLUSTER, plugin); }
static int change_compression(struct inode *inode, reiser4_plugin * plugin, pset_member memb) { assert("edward-1316", inode != NULL); assert("edward-1317", plugin != NULL); assert("edward-1318", is_reiser4_inode(inode)); assert("edward-1319", plugin->h.type_id == REISER4_COMPRESSION_PLUGIN_TYPE); /* cannot change compression plugin of already existing regular object */ if (!plugin_of_group(inode_file_plugin(inode), REISER4_DIRECTORY_FILE)) return RETERR(-EINVAL); /* If matches, nothing to change. */ if (inode_hash_plugin(inode) != NULL && inode_hash_plugin(inode)->h.id == plugin->h.id) return 0; return aset_set_unsafe(&reiser4_inode_data(inode)->pset, PSET_COMPRESSION, plugin); }
/* for every page of file: read page, cut part of extent pointing to this page, put data of page tree by tail item */ int extent2tail(struct file * file, struct unix_file_info *uf_info) { int result; struct inode *inode; struct page *page; unsigned long num_pages, i; unsigned long start_page; reiser4_key from; reiser4_key to; unsigned count; __u64 offset; assert("nikita-3362", ea_obtained(uf_info)); inode = unix_file_info_to_inode(uf_info); assert("nikita-3412", !IS_RDONLY(inode)); assert("vs-1649", uf_info->container != UF_CONTAINER_TAILS); assert("", !reiser4_inode_get_flag(inode, REISER4_PART_IN_CONV)); offset = 0; if (reiser4_inode_get_flag(inode, REISER4_PART_MIXED)) { /* * file is marked on disk as there was a conversion which did * not complete due to either crash or some error. Find which * offset tail conversion stopped at */ result = find_start(inode, EXTENT_POINTER_ID, &offset); if (result == -ENOENT) { /* no extent found, everything is converted */ uf_info->container = UF_CONTAINER_TAILS; complete_conversion(inode); return 0; } else if (result != 0) /* some other error */ return result; } reiser4_inode_set_flag(inode, REISER4_PART_IN_CONV); /* number of pages in the file */ num_pages = (inode->i_size + - offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; start_page = offset >> PAGE_CACHE_SHIFT; inode_file_plugin(inode)->key_by_inode(inode, offset, &from); to = from; result = 0; for (i = 0; i < num_pages; i++) { __u64 start_byte; result = reserve_extent2tail_iteration(inode); if (result != 0) break; if (i == 0 && offset == 0) { reiser4_inode_set_flag(inode, REISER4_PART_MIXED); reiser4_update_sd(inode); } page = read_mapping_page(inode->i_mapping, (unsigned)(i + start_page), NULL); if (IS_ERR(page)) { result = PTR_ERR(page); break; } wait_on_page_locked(page); if (!PageUptodate(page)) { page_cache_release(page); result = RETERR(-EIO); break; } /* cut part of file we have read */ start_byte = (__u64) ((i + start_page) << PAGE_CACHE_SHIFT); set_key_offset(&from, start_byte); set_key_offset(&to, start_byte + PAGE_CACHE_SIZE - 1); /* * reiser4_cut_tree_object() returns -E_REPEAT to allow atom * commits during over-long truncates. But * extent->tail conversion should be performed in one * transaction. */ result = reiser4_cut_tree(reiser4_tree_by_inode(inode), &from, &to, inode, 0); if (result) { page_cache_release(page); break; } /* put page data into tree via tail_write */ count = PAGE_CACHE_SIZE; if ((i == (num_pages - 1)) && (inode->i_size & ~PAGE_CACHE_MASK)) /* last page can be incompleted */ count = (inode->i_size & ~PAGE_CACHE_MASK); while (count) { loff_t pos = start_byte; assert("edward-1537", file != NULL && file->f_dentry != NULL); assert("edward-1538", file->f_dentry->d_inode == inode); result = reiser4_write_tail(file, inode, (char __user *)kmap(page), count, &pos); reiser4_free_file_fsdata(file); if (result <= 0) { warning("", "reiser4_write_tail failed"); page_cache_release(page); reiser4_inode_clr_flag(inode, REISER4_PART_IN_CONV); return result; } count -= result; } /* release page */ lock_page(page); /* page is already detached from jnode and mapping. */ assert("vs-1086", page->mapping == NULL); assert("nikita-2690", (!PagePrivate(page) && jprivate(page) == 0)); /* waiting for writeback completion with page lock held is * perfectly valid. */ wait_on_page_writeback(page); reiser4_drop_page(page); /* release reference taken by read_cache_page() above */ page_cache_release(page); drop_exclusive_access(uf_info); /* * throttle the conversion. * FIXME-EDWARD: Calculate and pass the precise number * of pages that was dirtied */ reiser4_throttle_write(inode, 1); get_exclusive_access(uf_info); /* * nobody is allowed to complete conversion but a process which * started it */ assert("", reiser4_inode_get_flag(inode, REISER4_PART_MIXED)); } reiser4_inode_clr_flag(inode, REISER4_PART_IN_CONV); if (i == num_pages) { /* file is converted to formatted items */ assert("vs-1698", reiser4_inode_get_flag(inode, REISER4_PART_MIXED)); assert("vs-1260", inode_has_no_jnodes(reiser4_inode_data(inode))); uf_info->container = UF_CONTAINER_TAILS; complete_conversion(inode); return 0; } /* * conversion is not complete. Inode was already marked as * REISER4_PART_MIXED and stat-data were updated at the first * iteration of the loop above. */ warning("nikita-2282", "Partial conversion of %llu: %lu of %lu: %i", (unsigned long long)get_inode_oid(inode), i, num_pages, result); /* this flag should be cleared, otherwise get_exclusive_access_careful() will fall into infinite loop */ assert("edward-1550", !reiser4_inode_get_flag(inode, REISER4_PART_IN_CONV)); return result; }