#include <linux/smp_lock.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
#include <linux/smp_lock.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
JOURNAL_PER_BALANCE_CNT * 2 +
2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
struct reiserfs_transaction_handle th;
JOURNAL_PER_BALANCE_CNT * 2 +
2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
struct reiserfs_transaction_handle th;
/* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
/* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
}
static void _make_cpu_key(struct cpu_key *key, int version, __u32 dirid,
}
static void _make_cpu_key(struct cpu_key *key, int version, __u32 dirid,
result = search_for_position_by_key(inode->i_sb, &key, &path);
if (result != POSITION_FOUND) {
pathrelse(&path);
result = search_for_position_by_key(inode->i_sb, &key, &path);
if (result != POSITION_FOUND) {
pathrelse(&path);
copy_item_head(&tmp_ih, ih);
/* we only want to kmap if we are reading the tail into the page.
copy_item_head(&tmp_ih, ih);
/* we only want to kmap if we are reading the tail into the page.
}
/* make sure we don't read more bytes than actually exist in
** the file. This can happen in odd cases where i_size isn't
}
/* make sure we don't read more bytes than actually exist in
** the file. This can happen in odd cases where i_size isn't
** extra bytes at the end of the direct item
*/
if ((le_ih_k_offset(ih) + path.pos_in_item) > inode->i_size)
** extra bytes at the end of the direct item
*/
if ((le_ih_k_offset(ih) + path.pos_in_item) > inode->i_size)
** -ENOENT instead of a valid buffer. block_prepare_write expects to
** be able to do i/o on the buffers returned, unless an error value
** is also returned.
** -ENOENT instead of a valid buffer. block_prepare_write expects to
** be able to do i/o on the buffers returned, unless an error value
** is also returned.
** So, this allows block_prepare_write to be used for reading a single block
** in a page. Where it does not produce a valid page for holes, or past the
** end of the file. This turns out to be exactly what we need for reading
** tails for conversion.
**
** The point of the wrapper is forcing a certain value for create, even
** So, this allows block_prepare_write to be used for reading a single block
** in a page. Where it does not produce a valid page for holes, or past the
** end of the file. This turns out to be exactly what we need for reading
** tails for conversion.
**
** The point of the wrapper is forcing a certain value for create, even
-** though the VFS layer is calling this function with create==1. If you
-** don't want to send create == GET_BLOCK_NO_HOLE to reiserfs_get_block,
+** though the VFS layer is calling this function with create==1. If you
+** don't want to send create == GET_BLOCK_NO_HOLE to reiserfs_get_block,
** don't use this function.
*/
static int reiserfs_get_block_create_0(struct inode *inode, sector_t block,
** don't use this function.
*/
static int reiserfs_get_block_create_0(struct inode *inode, sector_t block,
. 3 balancings in direct->indirect conversion
. 1 block involved into reiserfs_update_sd()
XXX in practically impossible worst case direct2indirect()
. 3 balancings in direct->indirect conversion
. 1 block involved into reiserfs_update_sd()
XXX in practically impossible worst case direct2indirect()
version = get_inode_item_key_version(inode);
if (!file_capable(inode, block)) {
version = get_inode_item_key_version(inode);
if (!file_capable(inode, block)) {
/* find number of block-th logical block of the file */
ret = _get_block_create_0(inode, block, bh_result,
create | GET_BLOCK_READ_DIRECT);
/* find number of block-th logical block of the file */
ret = _get_block_create_0(inode, block, bh_result,
create | GET_BLOCK_READ_DIRECT);
/* this loop could log more blocks than we had originally asked
** for. So, we have to allow the transaction to end if it is
/* this loop could log more blocks than we had originally asked
** for. So, we have to allow the transaction to end if it is
** consistent if we crash before the function returns
**
** release the path so that anybody waiting on the path before
** consistent if we crash before the function returns
**
** release the path so that anybody waiting on the path before
- /* inserting indirect pointers for a hole can take a
- ** long time. reschedule if needed
+ /*
+ * inserting indirect pointers for a hole can take a
+ * long time. reschedule if needed and also release the write
+ * lock for others.
retval = search_for_position_by_key(inode->i_sb, &key, &path);
if (retval == IO_ERROR) {
retval = search_for_position_by_key(inode->i_sb, &key, &path);
if (retval == IO_ERROR) {
REISERFS_I(inode)->i_trans_id = 0;
REISERFS_I(inode)->i_jl = NULL;
mutex_init(&(REISERFS_I(inode)->i_mmap));
REISERFS_I(inode)->i_trans_id = 0;
REISERFS_I(inode)->i_jl = NULL;
mutex_init(&(REISERFS_I(inode)->i_mmap));
update sd on unlink all that is required is to check for nlink
here. This bug was first found by Sizif when debugging
SquidNG/Butterfly, forgotten, and found again after Philippe
update sd on unlink all that is required is to check for nlink
here. This bug was first found by Sizif when debugging
SquidNG/Butterfly, forgotten, and found again after Philippe
More logical fix would require changes in fs/inode.c:iput() to
remove inode from hash-table _after_ fs cleaned disk stuff up and
More logical fix would require changes in fs/inode.c:iput() to
remove inode from hash-table _after_ fs cleaned disk stuff up and
inode = iget5_locked(s, key->on_disk_key.k_objectid,
reiserfs_find_actor, reiserfs_init_locked_inode,
(void *)(&args));
inode = iget5_locked(s, key->on_disk_key.k_objectid,
reiserfs_find_actor, reiserfs_init_locked_inode,
(void *)(&args));
** to properly mark inodes for datasync and such, but only actually
** does something when called for a synchronous update.
*/
** to properly mark inodes for datasync and such, but only actually
** does something when called for a synchronous update.
*/
if (inode->i_sb->s_flags & MS_RDONLY)
return -EROFS;
/* memory pressure can sometimes initiate write_inode calls with sync == 1,
if (inode->i_sb->s_flags & MS_RDONLY)
return -EROFS;
/* memory pressure can sometimes initiate write_inode calls with sync == 1,
** inode needs to reach disk for safety, and they can safely be
** ignored because the altered inode has already been logged.
*/
** inode needs to reach disk for safety, and they can safely be
** ignored because the altered inode has already been logged.
*/
reiserfs_write_lock(inode->i_sb);
if (!journal_begin(&th, inode->i_sb, jbegin_count)) {
reiserfs_update_sd(&th, inode);
reiserfs_write_lock(inode->i_sb);
if (!journal_begin(&th, inode->i_sb, jbegin_count)) {
reiserfs_update_sd(&th, inode);
/* inserts the stat data into the tree, and then calls
reiserfs_new_directory (to insert ".", ".." item if new object is
directory) or reiserfs_new_symlink (to insert symlink body if new
/* inserts the stat data into the tree, and then calls
reiserfs_new_directory (to insert ".", ".." item if new object is
directory) or reiserfs_new_symlink (to insert symlink body if new
NOTE! uid and gid must already be set in the inode. If we return
non-zero due to an error, we have to drop the quota previously allocated
NOTE! uid and gid must already be set in the inode. If we return
non-zero due to an error, we have to drop the quota previously allocated
if we return non-zero, we also end the transaction. */
int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
struct inode *dir, int mode, const char *symname,
if we return non-zero, we also end the transaction. */
int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
struct inode *dir, int mode, const char *symname,
strlen (symname) for symlinks) */
loff_t i_size, struct dentry *dentry,
strlen (symname) for symlinks) */
loff_t i_size, struct dentry *dentry,
** this is as good as reiserfs can do right now.
** note that the private part of inode isn't filled in yet, we have
** to use the directory.
** this is as good as reiserfs can do right now.
** note that the private part of inode isn't filled in yet, we have
** to use the directory.
REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;
sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode);
mutex_init(&(REISERFS_I(inode)->i_mmap));
REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;
sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode);
mutex_init(&(REISERFS_I(inode)->i_mmap));
- retval = reiserfs_inherit_default_acl(dir, dentry, inode);
+ retval = reiserfs_inherit_default_acl(th, dir, dentry, inode);
+ if (security->name) {
+ retval = reiserfs_security_write(th, inode, security);
+ if (retval) {
+ err = retval;
+ reiserfs_check_path(&path_to_key);
+ retval = journal_end(th, th->t_super,
+ th->t_blocks_allocated);
+ if (retval)
+ err = retval;
+ goto out_inserted_sd;
+ }
+ }
+
reiserfs_update_sd(th, inode);
reiserfs_check_path(&path_to_key);
reiserfs_update_sd(th, inode);
reiserfs_check_path(&path_to_key);
out_end_trans:
journal_end(th, th->t_super, th->t_blocks_allocated);
/* Drop can be outside and it needs more credits so it's better to have it outside */
out_end_trans:
journal_end(th, th->t_super, th->t_blocks_allocated);
/* Drop can be outside and it needs more credits so it's better to have it outside */
struct page **page_result,
struct buffer_head **bh_result)
{
struct page **page_result,
struct buffer_head **bh_result)
{
/* we want the page with the last byte in the file,
** not the page that will hold the next byte for appending
*/
/* we want the page with the last byte in the file,
** not the page that will hold the next byte for appending
*/
- unsigned long blocksize = p_s_inode->i_sb->s_blocksize;
- unsigned long offset = (p_s_inode->i_size) & (PAGE_CACHE_SIZE - 1);
+ unsigned long blocksize = inode->i_sb->s_blocksize;
+ unsigned long offset = (inode->i_size) & (PAGE_CACHE_SIZE - 1);
{
struct reiserfs_transaction_handle th;
/* we want the offset for the first byte after the end of the file */
{
struct reiserfs_transaction_handle th;
/* we want the offset for the first byte after the end of the file */
- unsigned long offset = p_s_inode->i_size & (PAGE_CACHE_SIZE - 1);
- unsigned blocksize = p_s_inode->i_sb->s_blocksize;
+ unsigned long offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
+ unsigned blocksize = inode->i_sb->s_blocksize;
- if (p_s_inode->i_size > 0) {
- if ((error = grab_tail_page(p_s_inode, &page, &bh))) {
- // -ENOENT means we truncated past the end of the file,
+ if (inode->i_size > 0) {
+ error = grab_tail_page(inode, &page, &bh);
+ if (error) {
+ // -ENOENT means we truncated past the end of the file,
- /* so, if page != NULL, we have a buffer head for the offset at
- ** the end of the file. if the bh is mapped, and bh->b_blocknr != 0,
- ** then we have an unformatted node. Otherwise, we have a direct item,
- ** and no zeroing is required on disk. We zero after the truncate,
- ** because the truncate might pack the item anyway
+ /* so, if page != NULL, we have a buffer head for the offset at
+ ** the end of the file. if the bh is mapped, and bh->b_blocknr != 0,
+ ** then we have an unformatted node. Otherwise, we have a direct item,
+ ** and no zeroing is required on disk. We zero after the truncate,
+ ** because the truncate might pack the item anyway
** (it will unmap bh if it packs).
*/
/* it is enough to reserve space in transaction for 2 balancings:
one for "save" link adding and another for the first
cut_from_item. 1 is for update_sd */
** (it will unmap bh if it packs).
*/
/* it is enough to reserve space in transaction for 2 balancings:
one for "save" link adding and another for the first
cut_from_item. 1 is for update_sd */
if (update_timestamps)
/* we are doing real truncate: if the system crashes before the last
transaction of truncating gets committed - on reboot the file
either appears truncated properly or not truncated at all */
if (update_timestamps)
/* we are doing real truncate: if the system crashes before the last
transaction of truncating gets committed - on reboot the file
either appears truncated properly or not truncated at all */
- add_save_link(&th, p_s_inode, 1);
- err2 = reiserfs_do_truncate(&th, p_s_inode, page, update_timestamps);
+ add_save_link(&th, inode, 1);
+ err2 = reiserfs_do_truncate(&th, inode, page, update_timestamps);
* start/recovery path as __block_write_full_page, along with special
* code to handle reiserfs tails.
*/
* start/recovery path as __block_write_full_page, along with special
* code to handle reiserfs tails.
*/
- * no io to be required without there being an error. Or,
- * someone else could have locked them and sent them down the
+ * no io to be required without there being an error. Or,
+ * someone else could have locked them and sent them down the
static int reiserfs_write_begin(struct file *file,
struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
static int reiserfs_write_begin(struct file *file,
struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
fix_tail_page_for_writing(page);
if (reiserfs_transaction_running(inode->i_sb)) {
struct reiserfs_transaction_handle *th;
fix_tail_page_for_writing(page);
if (reiserfs_transaction_running(inode->i_sb)) {
struct reiserfs_transaction_handle *th;
** transaction tracking stuff when the size changes. So, we have
** to do the i_size updates here.
*/
** transaction tracking stuff when the size changes. So, we have
** to do the i_size updates here.
*/
/* If the file have grown beyond the border where it
can have a tail, unmark it as needing a tail
packing */
/* If the file have grown beyond the border where it
can have a tail, unmark it as needing a tail
packing */
REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
ret = journal_begin(&myth, inode->i_sb, 1);
REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
ret = journal_begin(&myth, inode->i_sb, 1);
/*
* this will just nest into our transaction. It's important
* to use mark_inode_dirty so the inode gets pushed around on the
/*
* this will just nest into our transaction. It's important
* to use mark_inode_dirty so the inode gets pushed around on the
reiserfs_update_sd(&myth, inode);
update_sd = 1;
ret = journal_end(&myth, inode->i_sb, 1);
reiserfs_update_sd(&myth, inode);
update_sd = 1;
ret = journal_end(&myth, inode->i_sb, 1);
if (!update_sd)
reiserfs_update_sd(th, inode);
ret = reiserfs_end_persistent_transaction(th);
if (!update_sd)
reiserfs_update_sd(th, inode);
ret = reiserfs_end_persistent_transaction(th);
/* If the file have grown beyond the border where it
can have a tail, unmark it as needing a tail
packing */
/* If the file have grown beyond the border where it
can have a tail, unmark it as needing a tail
packing */
REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
ret = journal_begin(&myth, inode->i_sb, 1);
REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
ret = journal_begin(&myth, inode->i_sb, 1);
reiserfs_update_sd(&myth, inode);
update_sd = 1;
ret = journal_end(&myth, inode->i_sb, 1);
reiserfs_update_sd(&myth, inode);
update_sd = 1;
ret = journal_end(&myth, inode->i_sb, 1);
if (!update_sd)
reiserfs_update_sd(th, inode);
ret = reiserfs_end_persistent_transaction(th);
if (!update_sd)
reiserfs_update_sd(th, inode);
ret = reiserfs_end_persistent_transaction(th);
int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
/* must be turned off for recursive notify_change calls */
ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
/* must be turned off for recursive notify_change calls */
ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
+ if (!error) {
+ /*
+ * Relax the lock here, as it might truncate the
+ * inode pages and wait for inode pages locks.
+ * To release such page lock, the owner needs the
+ * reiserfs lock
+ */
+ reiserfs_write_unlock_once(inode->i_sb, depth);