Ejemplo n.º 1
0
void jfs_clear_inode(struct inode *inode)
{
	struct jfs_inode_info *ji = JFS_IP(inode);

	if (is_bad_inode(inode))
		/*
		 * We free the fs-dependent structure before making the
		 * inode bad
		 */
		return;

	jfs_info("jfs_clear_inode called ip = 0x%p", inode);

	if (ji->active_ag != -1) {
		struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap;
		atomic_dec(&bmap->db_active[ji->active_ag]);
	}

	ASSERT(list_empty(&ji->anon_inode_list));

	if (ji->atlhead) {
		jfs_err("jfs_clear_inode: inode %p has anonymous tlocks",
			inode);
		jfs_err("i_state = 0x%lx, cflag = 0x%lx", inode->i_state,
			ji->cflag);
	}

	free_jfs_inode(inode);
}
Ejemplo n.º 2
0
/*
 * NAME:    jfs_strtoUCS()
 *
 * FUNCTION:    Convert character string to unicode string
 *
 */
static int jfs_strtoUCS(wchar_t * to, const unsigned char *from, int len,
        struct nls_table *codepage)
{
    int charlen;
    int i;

    if (codepage) {
        for (i = 0; len && *from; i++, from += charlen, len -= charlen)
        {
            charlen = codepage->char2uni(from, len, &to[i]);
            if (charlen < 1) {
                jfs_err("jfs_strtoUCS: char2uni returned %d.",
                    charlen);
                jfs_err("charset = %s, char = 0x%x",
                    codepage->charset, *from);
                return charlen;
            }
        }
    } else {
        for (i = 0; (i < len) && from[i]; i++)
            to[i] = (wchar_t) from[i];
    }

    to[i] = 0;
    return i;
}
Ejemplo n.º 3
0
static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd)
{
	struct btstack btstack;
	ino_t inum;
	struct inode *ip;
	struct component_name key;
	int rc;

	jfs_info("jfs_lookup: name = %s", dentry->d_name.name);

	if ((rc = get_UCSname(&key, dentry)))
		return ERR_PTR(rc);
	rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP);
	free_UCSname(&key);
	if (rc == -ENOENT) {
		ip = NULL;
	} else if (rc) {
		jfs_err("jfs_lookup: dtSearch returned %d", rc);
		ip = ERR_PTR(rc);
	} else {
		ip = jfs_iget(dip->i_sb, inum);
		if (IS_ERR(ip))
			jfs_err("jfs_lookup: iget failed on inum %d", (uint)inum);
	}

	return d_splice_alias(ip, dentry);
}
/*
 * NAME:	jfs_mount_rw(sb, remount)
 *
 * FUNCTION:	Completes read-write mount, or remounts read-only volume
 *		as read-write
 */
int jfs_mount_rw(struct super_block *sb, int remount)
{
	struct jfs_sb_info *sbi = JFS_SBI(sb);  
	int rc;

	/*
	 * If we are re-mounting a previously read-only volume, we want to
	 * re-read the inode and block maps, since fsck.jfs may have updated
	 * them.
	 */
	if (remount) {
		if (chkSuper(sb) || (sbi->state != FM_CLEAN))
			return -EINVAL;

		truncate_inode_pages(sbi->ipimap->i_mapping, 0);
		truncate_inode_pages(sbi->ipbmap->i_mapping, 0);
		diUnmount(sbi->ipimap, 1);
		if ((rc = diMount(sbi->ipimap))) {
			jfs_err("jfs_mount_rw: diMount failed!");
			return rc;
		}

		dbUnmount(sbi->ipbmap, 1);
		if ((rc = dbMount(sbi->ipbmap))) {
			jfs_err("jfs_mount_rw: dbMount failed!");
			return rc;
		}
	}

	/*
	 * open/initialize log
	 */
	if ((rc = lmLogOpen(sb)))
		return rc;

	/*
	 * update file system superblock;
	 */
	if ((rc = updateSuper(sb, FM_MOUNT))) {
		jfs_err("jfs_mount: updateSuper failed w/rc = %d", rc);
		lmLogClose(sb);
		return rc;
	}

	/*
	 * write MOUNT log record of the file system
	 */
	logMOUNT(sb);

	/*
	 * Set page cache allocation policy
	 */
	mapping_set_gfp_mask(sb->s_bdev->bd_inode->i_mapping, GFP_NOFS);

	return rc;
}
Ejemplo n.º 5
0
static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd)
{
	struct btstack btstack;
	ino_t inum;
	struct inode *ip;
	struct component_name key;
	const char *name = dentry->d_name.name;
	int len = dentry->d_name.len;
	int rc;

	jfs_info("jfs_lookup: name = %s", name);


	if ((name[0] == '.') && (len == 1))
		inum = dip->i_ino;
	else if (strcmp(name, "..") == 0)
		inum = PARENT(dip);
	else {
		if ((rc = get_UCSname(&key, dentry)))
			return ERR_PTR(rc);
		rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP);
		free_UCSname(&key);
		if (rc == -ENOENT) {
			d_add(dentry, NULL);
			return ERR_PTR(0);
		} else if (rc) {
			jfs_err("jfs_lookup: dtSearch returned %d", rc);
			return ERR_PTR(rc);
		}
	}

	ip = iget(dip->i_sb, inum);
	if (ip == NULL || is_bad_inode(ip)) {
		jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum);
		if (ip)
			iput(ip);
		return ERR_PTR(-EACCES);
	}

	if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)
		dentry->d_op = &jfs_ci_dentry_operations;

	dentry = d_splice_alias(ip, dentry);

	if (dentry && (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2))
		dentry->d_op = &jfs_ci_dentry_operations;

	return dentry;
}
Ejemplo n.º 6
0
static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry)
{
	struct btstack btstack;
	ino_t inum;
	struct inode *ip;
	struct component_name key;
	const char *name = dentry->d_name.name;
	int len = dentry->d_name.len;
	int rc;

	jfs_info("jfs_lookup: name = %s", name);


	if ((name[0] == '.') && (len == 1))
		inum = dip->i_ino;
	else if (strcmp(name, "..") == 0)
		inum = PARENT(dip);
	else {
		if ((rc =
		     get_UCSname(&key, dentry, JFS_SBI(dip->i_sb)->nls_tab)))
			return ERR_PTR(rc);
		rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP);
		free_UCSname(&key);
		if (rc == -ENOENT) {
			d_add(dentry, NULL);
			return ERR_PTR(0);
		} else if (rc) {
			jfs_err("jfs_lookup: dtSearch returned %d", rc);
			return ERR_PTR(rc);
		}
	}

	ip = iget(dip->i_sb, inum);
	if (ip == NULL) {
		jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum);
		return ERR_PTR(-EACCES);
	}
	if (is_bad_inode(ip)) {
		jfs_err("jfs_lookup: iget returned bad inode, inum = %d",
			(uint) inum);
		iput(ip);
		return ERR_PTR(-EACCES);
	}

	d_add(dentry, ip);

	return ERR_PTR(0);
}
Ejemplo n.º 7
0
void jfs_dirty_inode(struct inode *inode)
{
	static int noisy = 5;

	if (isReadOnly(inode)) {
		if (!special_file(inode->i_mode) && noisy) {
			/* kernel allows writes to devices on read-only
			 * partitions and may try to mark inode dirty
			 */
			jfs_err("jfs_dirty_inode called on read-only volume");
			jfs_err("Is remount racy?");
			noisy--;
		}
		return;
	}

	set_cflag(COMMIT_Dirty, inode);
}
Ejemplo n.º 8
0
/*
 * NAME:	jfs_strtoUCS()
 *
 * FUNCTION:	Convert character string to unicode string
 *
 */
int jfs_strtoUCS(wchar_t * to,
		 const char *from, int len, struct nls_table *codepage)
{
	int charlen;
	int i;

	for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
		charlen = codepage->char2uni(from, len, &to[i]);
		if (charlen < 1) {
			jfs_err("jfs_strtoUCS: char2uni returned %d.", charlen);
			jfs_err("charset = %s, char = 0x%x",
				codepage->charset, (unsigned char) *from);
			return charlen;
		}
	}

	to[i] = 0;
	return i;
}
Ejemplo n.º 9
0
/*
 * Workhorse of both fsync & write_inode
 */
int jfs_commit_inode(struct inode *inode, int wait)
{
	int rc = 0;
	tid_t tid;
	static int noisy = 5;

	jfs_info("In jfs_commit_inode, inode = 0x%p", inode);

	/*
	 * Don't commit if inode has been committed since last being
	 * marked dirty, or if it has been deleted.
	 */
	if (inode->i_nlink == 0 || !test_cflag(COMMIT_Dirty, inode))
		return 0;

	if (isReadOnly(inode)) {
		/* kernel allows writes to devices on read-only
		 * partitions and may think inode is dirty
		 */
		if (!special_file(inode->i_mode) && noisy) {
			jfs_err("jfs_commit_inode(0x%p) called on "
				   "read-only volume", inode);
			jfs_err("Is remount racy?");
			noisy--;
		}
		return 0;
	}

	tid = txBegin(inode->i_sb, COMMIT_INODE);
	mutex_lock(&JFS_IP(inode)->commit_mutex);

	/*
	 * Retest inode state after taking commit_mutex
	 */
	if (inode->i_nlink && test_cflag(COMMIT_Dirty, inode))
		rc = txCommit(tid, 1, &inode, wait ? COMMIT_SYNC : 0);

	txEnd(tid);
	mutex_unlock(&JFS_IP(inode)->commit_mutex);
	return rc;
}
Ejemplo n.º 10
0
void jfs_clear_inode(struct inode *inode)
{
	struct jfs_inode_info *ji = JFS_IP(inode);

	if (is_bad_inode(inode))
		/*
		 * We free the fs-dependent structure before making the
		 * inode bad
		 */
		return;

	jfs_info("jfs_clear_inode called ip = 0x%p", inode);

	if (ji->active_ag != -1) {
		struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap;
		atomic_dec(&bmap->db_active[ji->active_ag]);
	}

	ASSERT(list_empty(&ji->anon_inode_list));

#ifdef CONFIG_JFS_POSIX_ACL
	if (ji->i_acl != JFS_ACL_NOT_CACHED) {
		posix_acl_release(ji->i_acl);
		ji->i_acl = JFS_ACL_NOT_CACHED;
	}
	if (ji->i_default_acl != JFS_ACL_NOT_CACHED) {
		posix_acl_release(ji->i_default_acl);
		ji->i_default_acl = JFS_ACL_NOT_CACHED;
	}
#endif

	if (ji->atlhead) {
		jfs_err("jfs_clear_inode: inode %p has anonymous tlocks",
			inode);
		jfs_err("i_state = 0x%lx, cflag = 0x%lx", inode->i_state,
			ji->cflag);
	}

	free_jfs_inode(inode);
}
Ejemplo n.º 11
0
static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd)
{
    struct btstack btstack;
    ino_t inum;
    struct inode *ip;
    struct component_name key;
    const char *name = dentry->d_name.name;
    int len = dentry->d_name.len;
    int rc;

    jfs_info("jfs_lookup: name = %s", name);

    if ((name[0] == '.') && (len == 1))
        inum = dip->i_ino;
    else if (strcmp(name, "..") == 0)
        inum = PARENT(dip);
    else {
        if ((rc = get_UCSname(&key, dentry)))
            return ERR_PTR(rc);
        rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP);
        free_UCSname(&key);
        if (rc == -ENOENT) {
            d_add(dentry, NULL);
            return NULL;
        } else if (rc) {
            jfs_err("jfs_lookup: dtSearch returned %d", rc);
            return ERR_PTR(rc);
        }
    }

    ip = jfs_iget(dip->i_sb, inum);
    if (IS_ERR(ip)) {
        jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum);
        return ERR_CAST(ip);
    }

    return d_splice_alias(ip, dentry);
}
Ejemplo n.º 12
0
int jfs_mount_rw(struct super_block *sb, int remount)
{
	struct jfs_sb_info *sbi = JFS_SBI(sb);
	int rc;

	if (remount) {
		if (chkSuper(sb) || (sbi->state != FM_CLEAN))
			return -EINVAL;

		truncate_inode_pages(sbi->ipimap->i_mapping, 0);
		truncate_inode_pages(sbi->ipbmap->i_mapping, 0);
		diUnmount(sbi->ipimap, 1);
		if ((rc = diMount(sbi->ipimap))) {
			jfs_err("jfs_mount_rw: diMount failed!");
			return rc;
		}

		dbUnmount(sbi->ipbmap, 1);
		if ((rc = dbMount(sbi->ipbmap))) {
			jfs_err("jfs_mount_rw: dbMount failed!");
			return rc;
		}
	}

	if ((rc = lmLogOpen(sb)))
		return rc;

	if ((rc = updateSuper(sb, FM_MOUNT))) {
		jfs_err("jfs_mount: updateSuper failed w/rc = %d", rc);
		lmLogClose(sb);
		return rc;
	}

	logMOUNT(sb);

	return rc;
}
Ejemplo n.º 13
0
/*
 *	dbSync()
 */
int dbSync(struct inode *ipbmap)
{
	struct dbmap_disk *dbmp_le;
	struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
	struct metapage *mp;
	int i;

	/*
	 * write bmap global control page
	 */
	/* get the buffer for the on-disk bmap descriptor. */
	mp = read_metapage(ipbmap,
			   BMAPBLKNO << JFS_SBI(ipbmap->i_sb)->l2nbperpage,
			   PSIZE, 0);
	if (mp == NULL) {
		jfs_err("dbSync: read_metapage failed!");
		return -EIO;
	}
	/* copy the in-memory version of the bmap to the on-disk version */
	dbmp_le = (struct dbmap_disk *) mp->data;
	dbmp_le->dn_mapsize = cpu_to_le64(bmp->db_mapsize);
	dbmp_le->dn_nfree = cpu_to_le64(bmp->db_nfree);
	dbmp_le->dn_l2nbperpage = cpu_to_le32(bmp->db_l2nbperpage);
	dbmp_le->dn_numag = cpu_to_le32(bmp->db_numag);
	dbmp_le->dn_maxlevel = cpu_to_le32(bmp->db_maxlevel);
	dbmp_le->dn_maxag = cpu_to_le32(bmp->db_maxag);
	dbmp_le->dn_agpref = cpu_to_le32(bmp->db_agpref);
	dbmp_le->dn_aglevel = cpu_to_le32(bmp->db_aglevel);
	dbmp_le->dn_agheight = cpu_to_le32(bmp->db_agheight);
	dbmp_le->dn_agwidth = cpu_to_le32(bmp->db_agwidth);
	dbmp_le->dn_agstart = cpu_to_le32(bmp->db_agstart);
	dbmp_le->dn_agl2size = cpu_to_le32(bmp->db_agl2size);
	for (i = 0; i < MAXAG; i++)
		dbmp_le->dn_agfree[i] = cpu_to_le64(bmp->db_agfree[i]);
	dbmp_le->dn_agsize = cpu_to_le64(bmp->db_agsize);
	dbmp_le->dn_maxfreebud = bmp->db_maxfreebud;

	/* write the buffer */
	write_metapage(mp);

	/*
	 * write out dirty pages of bmap
	 */
	filemap_write_and_wait(ipbmap->i_mapping);

	diWriteSpecial(ipbmap, 0);

	return (0);
}
Ejemplo n.º 14
0
/*
 *	updateSuper()
 *
 * update synchronously superblock if it is mounted read-write.
 */
int updateSuper(struct super_block *sb, uint state)
{
	struct jfs_superblock *j_sb;
	struct jfs_sb_info *sbi = JFS_SBI(sb);
	struct buffer_head *bh;
	int rc;

	if (sbi->flag & JFS_NOINTEGRITY) {
		if (state == FM_DIRTY) {
			sbi->p_state = state;
			return 0;
		} else if (state == FM_MOUNT) {
			sbi->p_state = sbi->state;
			state = FM_DIRTY;
		} else if (state == FM_CLEAN) {
			state = sbi->p_state;
		} else
			jfs_err("updateSuper: bad state");
	} else if (sbi->state == FM_DIRTY)
		return 0;
	
	if ((rc = readSuper(sb, &bh)))
		return rc;

	j_sb = (struct jfs_superblock *)bh->b_data;

	j_sb->s_state = cpu_to_le32(state);
	sbi->state = state;

	if (state == FM_MOUNT) {
		/* record log's dev_t and mount serial number */
		j_sb->s_logdev = cpu_to_le32(sbi->log->bdev->bd_dev);
		j_sb->s_logserial = cpu_to_le32(sbi->log->serial);
	} else if (state == FM_CLEAN) {
		/*
		 * If this volume is shared with OS/2, OS/2 will need to
		 * recalculate DASD usage, since we don't deal with it.
		 */
		if (j_sb->s_flag & cpu_to_le32(JFS_DASD_ENABLED))
			j_sb->s_flag |= cpu_to_le32(JFS_DASD_PRIME);
	}

	mark_buffer_dirty(bh);
	ll_rw_block(WRITE, 1, &bh);
	wait_on_buffer(bh);
	brelse(bh);

	return 0;
}
Ejemplo n.º 15
0
void jfs_write_inode(struct inode *inode, int wait)
{
	/*
	 * If COMMIT_DIRTY is not set, the inode isn't really dirty.
	 * It has been committed since the last change, but was still
	 * on the dirty inode list
	 */
	if (test_cflag(COMMIT_Nolink, inode) ||
	    !test_cflag(COMMIT_Dirty, inode))
		return;

	if (jfs_commit_inode(inode, wait)) {
		jfs_err("jfs_write_inode: jfs_commit_inode failed!");
	}
}
Ejemplo n.º 16
0
int updateSuper(struct super_block *sb, uint state)
{
	struct jfs_superblock *j_sb;
	struct jfs_sb_info *sbi = JFS_SBI(sb);
	struct buffer_head *bh;
	int rc;

	if (sbi->flag & JFS_NOINTEGRITY) {
		if (state == FM_DIRTY) {
			sbi->p_state = state;
			return 0;
		} else if (state == FM_MOUNT) {
			sbi->p_state = sbi->state;
			state = FM_DIRTY;
		} else if (state == FM_CLEAN) {
			state = sbi->p_state;
		} else
			jfs_err("updateSuper: bad state");
	} else if (sbi->state == FM_DIRTY)
		return 0;

	if ((rc = readSuper(sb, &bh)))
		return rc;

	j_sb = (struct jfs_superblock *)bh->b_data;

	j_sb->s_state = cpu_to_le32(state);
	sbi->state = state;

	if (state == FM_MOUNT) {
		
		j_sb->s_logdev = cpu_to_le32(new_encode_dev(sbi->log->bdev->bd_dev));
		j_sb->s_logserial = cpu_to_le32(sbi->log->serial);
	} else if (state == FM_CLEAN) {
		if (j_sb->s_flag & cpu_to_le32(JFS_DASD_ENABLED))
			j_sb->s_flag |= cpu_to_le32(JFS_DASD_PRIME);
	}

	mark_buffer_dirty(bh);
	sync_dirty_buffer(bh);
	brelse(bh);

	return 0;
}
Ejemplo n.º 17
0
void jfs_write_inode(struct inode *inode, int wait)
{
	if (test_cflag(COMMIT_Nolink, inode))
		return;
	/*
	 * If COMMIT_DIRTY is not set, the inode isn't really dirty.
	 * It has been committed since the last change, but was still
	 * on the dirty inode list.
	 */
	 if (!test_cflag(COMMIT_Dirty, inode)) {
		/* Make sure committed changes hit the disk */
		jfs_flush_journal(JFS_SBI(inode->i_sb)->log, wait);
		return;
	 }

	if (jfs_commit_inode(inode, wait)) {
		jfs_err("jfs_write_inode: jfs_commit_inode failed!");
	}
}
Ejemplo n.º 18
0
int jfs_write_inode(struct inode *inode, struct writeback_control *wbc)
{
	int wait = 1; /* XXX fix fsync and use wbc->sync_mode == WB_SYNC_ALL; */

	if (test_cflag(COMMIT_Nolink, inode))
		return 0;
	/*
	 * If COMMIT_DIRTY is not set, the inode isn't really dirty.
	 * It has been committed since the last change, but was still
	 * on the dirty inode list.
	 */
	 if (!test_cflag(COMMIT_Dirty, inode)) {
		/* Make sure committed changes hit the disk */
		jfs_flush_journal(JFS_SBI(inode->i_sb)->log, wait);
		return 0;
	 }

	if (jfs_commit_inode(inode, wait)) {
		jfs_err("jfs_write_inode: jfs_commit_inode failed!");
		return -EIO;
	} else
		return 0;
}
Ejemplo n.º 19
0
/*
 * NAME:	jfs_rename
 *
 * FUNCTION:	rename a file or directory
 */
static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                      struct inode *new_dir, struct dentry *new_dentry)
{
    struct btstack btstack;
    ino_t ino;
    struct component_name new_dname;
    struct inode *new_ip;
    struct component_name old_dname;
    struct inode *old_ip;
    int rc;
    tid_t tid;
    struct tlock *tlck;
    struct dt_lock *dtlck;
    struct lv *lv;
    int ipcount;
    struct inode *iplist[4];
    struct tblock *tblk;
    s64 new_size = 0;
    int commit_flag;


    jfs_info("jfs_rename: %s %s", old_dentry->d_name.name,
             new_dentry->d_name.name);

    dquot_initialize(old_dir);
    dquot_initialize(new_dir);

    old_ip = old_dentry->d_inode;
    new_ip = new_dentry->d_inode;

    if ((rc = get_UCSname(&old_dname, old_dentry)))
        goto out1;

    if ((rc = get_UCSname(&new_dname, new_dentry)))
        goto out2;

    /*
     * Make sure source inode number is what we think it is
     */
    rc = dtSearch(old_dir, &old_dname, &ino, &btstack, JFS_LOOKUP);
    if (rc || (ino != old_ip->i_ino)) {
        rc = -ENOENT;
        goto out3;
    }

    /*
     * Make sure dest inode number (if any) is what we think it is
     */
    rc = dtSearch(new_dir, &new_dname, &ino, &btstack, JFS_LOOKUP);
    if (!rc) {
        if ((!new_ip) || (ino != new_ip->i_ino)) {
            rc = -ESTALE;
            goto out3;
        }
    } else if (rc != -ENOENT)
        goto out3;
    else if (new_ip) {
        /* no entry exists, but one was expected */
        rc = -ESTALE;
        goto out3;
    }

    if (S_ISDIR(old_ip->i_mode)) {
        if (new_ip) {
            if (!dtEmpty(new_ip)) {
                rc = -ENOTEMPTY;
                goto out3;
            }
        } else if ((new_dir != old_dir) &&
                   (new_dir->i_nlink == JFS_LINK_MAX)) {
            rc = -EMLINK;
            goto out3;
        }
    } else if (new_ip) {
        IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL);
        /* Init inode for quota operations. */
        dquot_initialize(new_ip);
    }

    /*
     * The real work starts here
     */
    tid = txBegin(new_dir->i_sb, 0);

    /*
     * How do we know the locking is safe from deadlocks?
     * The vfs does the hard part for us.  Any time we are taking nested
     * commit_mutexes, the vfs already has i_mutex held on the parent.
     * Here, the vfs has already taken i_mutex on both old_dir and new_dir.
     */
    mutex_lock_nested(&JFS_IP(new_dir)->commit_mutex, COMMIT_MUTEX_PARENT);
    mutex_lock_nested(&JFS_IP(old_ip)->commit_mutex, COMMIT_MUTEX_CHILD);
    if (old_dir != new_dir)
        mutex_lock_nested(&JFS_IP(old_dir)->commit_mutex,
                          COMMIT_MUTEX_SECOND_PARENT);

    if (new_ip) {
        mutex_lock_nested(&JFS_IP(new_ip)->commit_mutex,
                          COMMIT_MUTEX_VICTIM);
        /*
         * Change existing directory entry to new inode number
         */
        ino = new_ip->i_ino;
        rc = dtModify(tid, new_dir, &new_dname, &ino,
                      old_ip->i_ino, JFS_RENAME);
        if (rc)
            goto out4;
        drop_nlink(new_ip);
        if (S_ISDIR(new_ip->i_mode)) {
            drop_nlink(new_ip);
            if (new_ip->i_nlink) {
                mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
                if (old_dir != new_dir)
                    mutex_unlock(&JFS_IP(old_dir)->commit_mutex);
                mutex_unlock(&JFS_IP(old_ip)->commit_mutex);
                mutex_unlock(&JFS_IP(new_dir)->commit_mutex);
                if (!S_ISDIR(old_ip->i_mode) && new_ip)
                    IWRITE_UNLOCK(new_ip);
                jfs_error(new_ip->i_sb,
                          "jfs_rename: new_ip->i_nlink != 0");
                return -EIO;
            }
            tblk = tid_to_tblock(tid);
            tblk->xflag |= COMMIT_DELETE;
            tblk->u.ip = new_ip;
        } else if (new_ip->i_nlink == 0) {
            assert(!test_cflag(COMMIT_Nolink, new_ip));
            /* free block resources */
            if ((new_size = commitZeroLink(tid, new_ip)) < 0) {
                txAbort(tid, 1);	/* Marks FS Dirty */
                rc = new_size;
                goto out4;
            }
            tblk = tid_to_tblock(tid);
            tblk->xflag |= COMMIT_DELETE;
            tblk->u.ip = new_ip;
        } else {
            new_ip->i_ctime = CURRENT_TIME;
            mark_inode_dirty(new_ip);
        }
    } else {
        /*
         * Add new directory entry
         */
        rc = dtSearch(new_dir, &new_dname, &ino, &btstack,
                      JFS_CREATE);
        if (rc) {
            jfs_err("jfs_rename didn't expect dtSearch to fail "
                    "w/rc = %d", rc);
            goto out4;
        }

        ino = old_ip->i_ino;
        rc = dtInsert(tid, new_dir, &new_dname, &ino, &btstack);
        if (rc) {
            if (rc == -EIO)
                jfs_err("jfs_rename: dtInsert returned -EIO");
            goto out4;
        }
        if (S_ISDIR(old_ip->i_mode))
            inc_nlink(new_dir);
    }
    /*
     * Remove old directory entry
     */

    ino = old_ip->i_ino;
    rc = dtDelete(tid, old_dir, &old_dname, &ino, JFS_REMOVE);
    if (rc) {
        jfs_err("jfs_rename did not expect dtDelete to return rc = %d",
                rc);
        txAbort(tid, 1);	/* Marks Filesystem dirty */
        goto out4;
    }
    if (S_ISDIR(old_ip->i_mode)) {
        drop_nlink(old_dir);
        if (old_dir != new_dir) {
            /*
             * Change inode number of parent for moved directory
             */

            JFS_IP(old_ip)->i_dtroot.header.idotdot =
                cpu_to_le32(new_dir->i_ino);

            /* Linelock header of dtree */
            tlck = txLock(tid, old_ip,
                          (struct metapage *) &JFS_IP(old_ip)->bxflag,
                          tlckDTREE | tlckBTROOT | tlckRELINK);
            dtlck = (struct dt_lock *) & tlck->lock;
            ASSERT(dtlck->index == 0);
            lv = & dtlck->lv[0];
            lv->offset = 0;
            lv->length = 1;
            dtlck->index++;
        }
    }

    /*
     * Update ctime on changed/moved inodes & mark dirty
     */
    old_ip->i_ctime = CURRENT_TIME;
    mark_inode_dirty(old_ip);

    new_dir->i_ctime = new_dir->i_mtime = current_fs_time(new_dir->i_sb);
    mark_inode_dirty(new_dir);

    /* Build list of inodes modified by this transaction */
    ipcount = 0;
    iplist[ipcount++] = old_ip;
    if (new_ip)
        iplist[ipcount++] = new_ip;
    iplist[ipcount++] = old_dir;

    if (old_dir != new_dir) {
        iplist[ipcount++] = new_dir;
        old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
        mark_inode_dirty(old_dir);
    }

    /*
     * Incomplete truncate of file data can
     * result in timing problems unless we synchronously commit the
     * transaction.
     */
    if (new_size)
        commit_flag = COMMIT_SYNC;
    else
        commit_flag = 0;

    rc = txCommit(tid, ipcount, iplist, commit_flag);

out4:
    txEnd(tid);
    if (new_ip)
        mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
    if (old_dir != new_dir)
        mutex_unlock(&JFS_IP(old_dir)->commit_mutex);
    mutex_unlock(&JFS_IP(old_ip)->commit_mutex);
    mutex_unlock(&JFS_IP(new_dir)->commit_mutex);

    while (new_size && (rc == 0)) {
        tid = txBegin(new_ip->i_sb, 0);
        mutex_lock(&JFS_IP(new_ip)->commit_mutex);
        new_size = xtTruncate_pmap(tid, new_ip, new_size);
        if (new_size < 0) {
            txAbort(tid, 1);
            rc = new_size;
        } else
            rc = txCommit(tid, 1, &new_ip, COMMIT_SYNC);
        txEnd(tid);
        mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
    }
    if (new_ip && (new_ip->i_nlink == 0))
        set_cflag(COMMIT_Nolink, new_ip);
out3:
    free_UCSname(&new_dname);
out2:
    free_UCSname(&old_dname);
out1:
    if (new_ip && !S_ISDIR(new_ip->i_mode))
        IWRITE_UNLOCK(new_ip);
    /*
     * Truncating the directory index table is not guaranteed.  It
     * may need to be done iteratively
     */
    if (test_cflag(COMMIT_Stale, old_dir)) {
        if (old_dir->i_size > 1)
            jfs_truncate_nolock(old_dir, 0);

        clear_cflag(COMMIT_Stale, old_dir);
    }

    jfs_info("jfs_rename: returning %d", rc);
    return rc;
}
Ejemplo n.º 20
0
static int jfs_symlink(struct inode *dip, struct dentry *dentry,
		const char *name)
{
	int rc;
	tid_t tid;
	ino_t ino = 0;
	struct component_name dname;
	int ssize;		/* source pathname size */
	struct btstack btstack;
	struct inode *ip = dentry->d_inode;
	unchar *i_fastsymlink;
	s64 xlen = 0;
	int bmask = 0, xsize;
	s64 xaddr;
	struct metapage *mp;
	struct super_block *sb;
	struct tblock *tblk;

	struct inode *iplist[2];

	jfs_info("jfs_symlink: dip:0x%p name:%s", dip, name);

	ssize = strlen(name) + 1;

	/*
	 * search parent directory for entry/freespace
	 * (dtSearch() returns parent directory page pinned)
	 */

	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab)))
		goto out1;

	/*
	 * allocate on-disk/in-memory inode for symbolic link:
	 * (iAlloc() returns new, locked inode)
	 */
	ip = ialloc(dip, S_IFLNK | 0777);
	if (ip == NULL) {
		rc = -ENOSPC;
		goto out2;
	}

	tid = txBegin(dip->i_sb, 0);

	down(&JFS_IP(dip)->commit_sem);
	down(&JFS_IP(ip)->commit_sem);

	if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE)))
		goto out3;

	tblk = tid_to_tblock(tid);
	tblk->xflag |= COMMIT_CREATE;
	tblk->ip = ip;

	/*
	 * create entry for symbolic link in parent directory
	 */

	ino = ip->i_ino;



	if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
		jfs_err("jfs_symlink: dtInsert returned %d", rc);
		/* discard ne inode */
		goto out3;

	}

	/* fix symlink access permission
	 * (dir_create() ANDs in the u.u_cmask, 
	 * but symlinks really need to be 777 access)
	 */
	ip->i_mode |= 0777;

	/*
	   *       write symbolic link target path name
	 */
	xtInitRoot(tid, ip);

	/*
	 * write source path name inline in on-disk inode (fast symbolic link)
	 */

	if (ssize <= IDATASIZE) {
		ip->i_op = &jfs_symlink_inode_operations;

		i_fastsymlink = JFS_IP(ip)->i_inline;
		memcpy(i_fastsymlink, name, ssize);
		ip->i_size = ssize - 1;

		/*
		 * if symlink is > 128 bytes, we don't have the space to
		 * store inline extended attributes
		 */
		if (ssize > sizeof (JFS_IP(ip)->i_inline))
			JFS_IP(ip)->mode2 &= ~INLINEEA;

		jfs_info("jfs_symlink: fast symlink added  ssize:%d name:%s ",
			 ssize, name);
	}
	/*
	 * write source path name in a single extent
	 */
	else {
		jfs_info("jfs_symlink: allocate extent ip:0x%p", ip);

		ip->i_op = &page_symlink_inode_operations;
		ip->i_mapping->a_ops = &jfs_aops;

		/*
		 * even though the data of symlink object (source 
		 * path name) is treated as non-journaled user data,
		 * it is read/written thru buffer cache for performance.
		 */
		sb = ip->i_sb;
		bmask = JFS_SBI(sb)->bsize - 1;
		xsize = (ssize + bmask) & ~bmask;
		xaddr = 0;
		xlen = xsize >> JFS_SBI(sb)->l2bsize;
		if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0)) == 0) {
			ip->i_size = ssize - 1;
			while (ssize) {
				int copy_size = min(ssize, PSIZE);

				mp = get_metapage(ip, xaddr, PSIZE, 1);

				if (mp == NULL) {
					dtDelete(tid, dip, &dname, &ino,
						 JFS_REMOVE);
					rc = -EIO;
					goto out3;
				}
				memcpy(mp->data, name, copy_size);
				flush_metapage(mp);
#if 0
				mark_buffer_uptodate(bp, 1);
				mark_buffer_dirty(bp, 1);
				if (IS_SYNC(dip)) {
					ll_rw_block(WRITE, 1, &bp);
					wait_on_buffer(bp);
				}
				brelse(bp);
#endif				/* 0 */
				ssize -= copy_size;
				xaddr += JFS_SBI(sb)->nbperpage;
			}
			ip->i_blocks = LBLK2PBLK(sb, xlen);
		} else {
			dtDelete(tid, dip, &dname, &ino, JFS_REMOVE);
			rc = -ENOSPC;
			goto out3;
		}
	}

	insert_inode_hash(ip);
	mark_inode_dirty(ip);
	d_instantiate(dentry, ip);

	/*
	 * commit update of parent directory and link object
	 *
	 * if extent allocation failed (ENOSPC),
	 * the parent inode is committed regardless to avoid
	 * backing out parent directory update (by dtInsert())
	 * and subsequent dtDelete() which is harmless wrt 
	 * integrity concern.  
	 * the symlink inode will be freed by iput() at exit
	 * as it has a zero link count (by dtDelete()) and 
	 * no permanant resources. 
	 */

	iplist[0] = dip;
	if (rc == 0) {
		iplist[1] = ip;
		rc = txCommit(tid, 2, &iplist[0], 0);
	} else
		rc = txCommit(tid, 1, &iplist[0], 0);

      out3:
	txEnd(tid);
	up(&JFS_IP(dip)->commit_sem);
	up(&JFS_IP(ip)->commit_sem);
	if (rc) {
		ip->i_nlink = 0;
		iput(ip);
	}

      out2:
	free_UCSname(&dname);

      out1:
	jfs_info("jfs_symlink: rc:%d", rc);
	return rc;
}
Ejemplo n.º 21
0
/*
 * NAME:	jfs_mount(sb)
 *
 * FUNCTION:	vfs_mount()
 *
 * PARAMETER:	sb	- super block
 *
 * RETURN:	-EBUSY	- device already mounted or open for write
 *		-EBUSY	- cvrdvp already mounted;
 *		-EBUSY	- mount table full
 *		-ENOTDIR- cvrdvp not directory on a device mount
 *		-ENXIO	- device open failure
 */
int jfs_mount(struct super_block *sb)
{
	int rc = 0;		/* Return code          */
	struct jfs_sb_info *sbi = JFS_SBI(sb);
	struct inode *ipaimap = NULL;
	struct inode *ipaimap2 = NULL;
	struct inode *ipimap = NULL;
	struct inode *ipbmap = NULL;

	/*
	 * read/validate superblock 
	 * (initialize mount inode from the superblock)
	 */
	if ((rc = chkSuper(sb))) {
		goto errout20;
	}

	ipaimap = diReadSpecial(sb, AGGREGATE_I, 0);
	if (ipaimap == NULL) {
		jfs_err("jfs_mount: Faild to read AGGREGATE_I");
		rc = -EIO;
		goto errout20;
	}
	sbi->ipaimap = ipaimap;

	jfs_info("jfs_mount: ipaimap:0x%p", ipaimap);

	/*
	 * initialize aggregate inode allocation map
	 */
	if ((rc = diMount(ipaimap))) {
		jfs_err("jfs_mount: diMount(ipaimap) failed w/rc = %d", rc);
		goto errout21;
	}

	/*
	 * open aggregate block allocation map
	 */
	ipbmap = diReadSpecial(sb, BMAP_I, 0);
	if (ipbmap == NULL) {
		rc = -EIO;
		goto errout22;
	}

	jfs_info("jfs_mount: ipbmap:0x%p", ipbmap);

	sbi->ipbmap = ipbmap;

	/*
	 * initialize aggregate block allocation map
	 */
	if ((rc = dbMount(ipbmap))) {
		jfs_err("jfs_mount: dbMount failed w/rc = %d", rc);
		goto errout22;
	}

	/*
	 * open the secondary aggregate inode allocation map
	 *
	 * This is a duplicate of the aggregate inode allocation map.
	 *
	 * hand craft a vfs in the same fashion as we did to read ipaimap.
	 * By adding INOSPEREXT (32) to the inode number, we are telling
	 * diReadSpecial that we are reading from the secondary aggregate
	 * inode table.  This also creates a unique entry in the inode hash
	 * table.
	 */
	if ((sbi->mntflag & JFS_BAD_SAIT) == 0) {
		ipaimap2 = diReadSpecial(sb, AGGREGATE_I, 1);
		if (ipaimap2 == 0) {
			jfs_err("jfs_mount: Faild to read AGGREGATE_I");
			rc = -EIO;
			goto errout35;
		}
		sbi->ipaimap2 = ipaimap2;

		jfs_info("jfs_mount: ipaimap2:0x%p", ipaimap2);

		/*
		 * initialize secondary aggregate inode allocation map
		 */
		if ((rc = diMount(ipaimap2))) {
			jfs_err("jfs_mount: diMount(ipaimap2) failed, rc = %d",
				rc);
			goto errout35;
		}
	} else
		/* Secondary aggregate inode table is not valid */
		sbi->ipaimap2 = NULL;

	/*
	 *      mount (the only/single) fileset
	 */
	/*
	 * open fileset inode allocation map (aka fileset inode)
	 */
	ipimap = diReadSpecial(sb, FILESYSTEM_I, 0);
	if (ipimap == NULL) {
		jfs_err("jfs_mount: Failed to read FILESYSTEM_I");
		/* open fileset secondary inode allocation map */
		rc = -EIO;
		goto errout40;
	}
	jfs_info("jfs_mount: ipimap:0x%p", ipimap);

	/* map further access of per fileset inodes by the fileset inode */
	sbi->ipimap = ipimap;

	/* initialize fileset inode allocation map */
	if ((rc = diMount(ipimap))) {
		jfs_err("jfs_mount: diMount failed w/rc = %d", rc);
		goto errout41;
	}

	goto out;

	/*
	 *      unwind on error
	 */
      errout41:		/* close fileset inode allocation map inode */
	diFreeSpecial(ipimap);

      errout40:		/* fileset closed */

	/* close secondary aggregate inode allocation map */
	if (ipaimap2) {
		diUnmount(ipaimap2, 1);
		diFreeSpecial(ipaimap2);
	}

      errout35:

	/* close aggregate block allocation map */
	dbUnmount(ipbmap, 1);
	diFreeSpecial(ipbmap);

      errout22:		/* close aggregate inode allocation map */

	diUnmount(ipaimap, 1);

      errout21:		/* close aggregate inodes */
	diFreeSpecial(ipaimap);
      errout20:		/* aggregate closed */

      out:

	if (rc)
		jfs_err("Mount JFS Failure: %d", rc);

	return rc;
}
Ejemplo n.º 22
0
/*
 * NAME:	jfs_create(dip, dentry, mode)
 *
 * FUNCTION:	create a regular file in the parent directory <dip>
 *		with name = <from dentry> and mode = <mode>
 *
 * PARAMETER:	dip	- parent directory vnode
 *		dentry	- dentry of new file
 *		mode	- create mode (rwxrwxrwx).
 *		nd- nd struct
 *
 * RETURN:	Errors from subroutines
 *
 */
static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
                      struct nameidata *nd)
{
    int rc = 0;
    tid_t tid;		/* transaction id */
    struct inode *ip = NULL;	/* child directory inode */
    ino_t ino;
    struct component_name dname;	/* child directory name */
    struct btstack btstack;
    struct inode *iplist[2];
    struct tblock *tblk;

    jfs_info("jfs_create: dip:0x%p name:%s", dip, dentry->d_name.name);

    dquot_initialize(dip);

    /*
     * search parent directory for entry/freespace
     * (dtSearch() returns parent directory page pinned)
     */
    if ((rc = get_UCSname(&dname, dentry)))
        goto out1;

    /*
     * Either iAlloc() or txBegin() may block.  Deadlock can occur if we
     * block there while holding dtree page, so we allocate the inode &
     * begin the transaction before we search the directory.
     */
    ip = ialloc(dip, mode);
    if (IS_ERR(ip)) {
        rc = PTR_ERR(ip);
        goto out2;
    }

    tid = txBegin(dip->i_sb, 0);

    mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
    mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);

    rc = jfs_init_acl(tid, ip, dip);
    if (rc)
        goto out3;

    rc = jfs_init_security(tid, ip, dip, &dentry->d_name);
    if (rc) {
        txAbort(tid, 0);
        goto out3;
    }

    if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
        jfs_err("jfs_create: dtSearch returned %d", rc);
        txAbort(tid, 0);
        goto out3;
    }

    tblk = tid_to_tblock(tid);
    tblk->xflag |= COMMIT_CREATE;
    tblk->ino = ip->i_ino;
    tblk->u.ixpxd = JFS_IP(ip)->ixpxd;

    iplist[0] = dip;
    iplist[1] = ip;

    /*
     * initialize the child XAD tree root in-line in inode
     */
    xtInitRoot(tid, ip);

    /*
     * create entry in parent directory for child directory
     * (dtInsert() releases parent directory page)
     */
    ino = ip->i_ino;
    if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
        if (rc == -EIO) {
            jfs_err("jfs_create: dtInsert returned -EIO");
            txAbort(tid, 1);	/* Marks Filesystem dirty */
        } else
            txAbort(tid, 0);	/* Filesystem full */
        goto out3;
    }

    ip->i_op = &jfs_file_inode_operations;
    ip->i_fop = &jfs_file_operations;
    ip->i_mapping->a_ops = &jfs_aops;

    mark_inode_dirty(ip);

    dip->i_ctime = dip->i_mtime = CURRENT_TIME;

    mark_inode_dirty(dip);

    rc = txCommit(tid, 2, &iplist[0], 0);

out3:
    txEnd(tid);
    mutex_unlock(&JFS_IP(ip)->commit_mutex);
    mutex_unlock(&JFS_IP(dip)->commit_mutex);
    if (rc) {
        free_ea_wmap(ip);
        ip->i_nlink = 0;
        unlock_new_inode(ip);
        iput(ip);
    } else {
        d_instantiate(dentry, ip);
        unlock_new_inode(ip);
    }

out2:
    free_UCSname(&dname);

out1:

    jfs_info("jfs_create: rc:%d", rc);
    return rc;
}
Ejemplo n.º 23
0
/*
 *	chkSuper()
 *
 * validate the superblock of the file system to be mounted and 
 * get the file system parameters.
 *
 * returns
 *	0 with fragsize set if check successful
 *	error code if not successful
 */
static int chkSuper(struct super_block *sb)
{
	int rc = 0;
	struct jfs_sb_info *sbi = JFS_SBI(sb);
	struct jfs_superblock *j_sb;
	struct buffer_head *bh;
	int AIM_bytesize, AIT_bytesize;
	int expected_AIM_bytesize, expected_AIT_bytesize;
	s64 AIM_byte_addr, AIT_byte_addr, fsckwsp_addr;
	s64 byte_addr_diff0, byte_addr_diff1;
	s32 bsize;

	if ((rc = readSuper(sb, &bh)))
		return rc;
	j_sb = (struct jfs_superblock *)bh->b_data;

	/*
	 * validate superblock
	 */
	/* validate fs signature */
	if (strncmp(j_sb->s_magic, JFS_MAGIC, 4) ||
	    le32_to_cpu(j_sb->s_version) > JFS_VERSION) {
		rc = -EINVAL;
		goto out;
	}

	bsize = le32_to_cpu(j_sb->s_bsize);
#ifdef _JFS_4K
	if (bsize != PSIZE) {
		jfs_err("Currently only 4K block size supported!");
		rc = -EINVAL;
		goto out;
	}
#endif				/* _JFS_4K */

	jfs_info("superblock: flag:0x%08x state:0x%08x size:0x%Lx",
		 le32_to_cpu(j_sb->s_flag), le32_to_cpu(j_sb->s_state),
		 (unsigned long long) le64_to_cpu(j_sb->s_size));

	/* validate the descriptors for Secondary AIM and AIT */
	if ((j_sb->s_flag & cpu_to_le32(JFS_BAD_SAIT)) !=
	    cpu_to_le32(JFS_BAD_SAIT)) {
		expected_AIM_bytesize = 2 * PSIZE;
		AIM_bytesize = lengthPXD(&(j_sb->s_aim2)) * bsize;
		expected_AIT_bytesize = 4 * PSIZE;
		AIT_bytesize = lengthPXD(&(j_sb->s_ait2)) * bsize;
		AIM_byte_addr = addressPXD(&(j_sb->s_aim2)) * bsize;
		AIT_byte_addr = addressPXD(&(j_sb->s_ait2)) * bsize;
		byte_addr_diff0 = AIT_byte_addr - AIM_byte_addr;
		fsckwsp_addr = addressPXD(&(j_sb->s_fsckpxd)) * bsize;
		byte_addr_diff1 = fsckwsp_addr - AIT_byte_addr;
		if ((AIM_bytesize != expected_AIM_bytesize) ||
		    (AIT_bytesize != expected_AIT_bytesize) ||
		    (byte_addr_diff0 != AIM_bytesize) ||
		    (byte_addr_diff1 <= AIT_bytesize))
			j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT);
	}

	if ((j_sb->s_flag & cpu_to_le32(JFS_GROUPCOMMIT)) !=
	    cpu_to_le32(JFS_GROUPCOMMIT))
		j_sb->s_flag |= cpu_to_le32(JFS_GROUPCOMMIT);

	/* validate fs state */
	if (j_sb->s_state != cpu_to_le32(FM_CLEAN) &&
	    !(sb->s_flags & MS_RDONLY)) {
		jfs_err("jfs_mount: Mount Failure: File System Dirty.");
		rc = -EINVAL;
		goto out;
	}

	sbi->state = le32_to_cpu(j_sb->s_state);
	sbi->mntflag = le32_to_cpu(j_sb->s_flag);

	/*
	 * JFS always does I/O by 4K pages.  Don't tell the buffer cache
	 * that we use anything else (leave s_blocksize alone).
	 */
	sbi->bsize = bsize;
	sbi->l2bsize = le16_to_cpu(j_sb->s_l2bsize);

	/*
	 * For now, ignore s_pbsize, l2bfactor.  All I/O going through buffer
	 * cache.
	 */
	sbi->nbperpage = PSIZE >> sbi->l2bsize;
	sbi->l2nbperpage = L2PSIZE - sbi->l2bsize;
	sbi->l2niperblk = sbi->l2bsize - L2DISIZE;
	if (sbi->mntflag & JFS_INLINELOG)
		sbi->logpxd = j_sb->s_logpxd;
	else {
		sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev));
		memcpy(sbi->uuid, j_sb->s_uuid, sizeof(sbi->uuid));
		memcpy(sbi->loguuid, j_sb->s_loguuid, sizeof(sbi->uuid));
	}
	sbi->fsckpxd = j_sb->s_fsckpxd;
	sbi->ait2 = j_sb->s_ait2;

      out:
	brelse(bh);
	return rc;
}
Ejemplo n.º 24
0
/*
 * NAME:	jfs_unlink(dip, dentry)
 *
 * FUNCTION:	remove a link to object <vp> named by <name>
 *		from parent directory <dvp>
 *
 * PARAMETER:	dip	- inode of parent directory
 *		dentry	- dentry of object to be removed
 *
 * RETURN:	errors from subroutines
 *
 * note:
 * temporary file: if one or more processes have the file open
 * when the last link is removed, the link will be removed before
 * unlink() returns, but the removal of the file contents will be
 * postponed until all references to the files are closed.
 *
 * JFS does NOT support unlink() on directories.
 *
 */
static int jfs_unlink(struct inode *dip, struct dentry *dentry)
{
    int rc;
    tid_t tid;		/* transaction id */
    struct inode *ip = dentry->d_inode;
    ino_t ino;
    struct component_name dname;	/* object name */
    struct inode *iplist[2];
    struct tblock *tblk;
    s64 new_size = 0;
    int commit_flag;

    jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name);

    /* Init inode for quota operations. */
    dquot_initialize(dip);
    dquot_initialize(ip);

    if ((rc = get_UCSname(&dname, dentry)))
        goto out;

    IWRITE_LOCK(ip, RDWRLOCK_NORMAL);

    tid = txBegin(dip->i_sb, 0);

    mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
    mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);

    iplist[0] = dip;
    iplist[1] = ip;

    /*
     * delete the entry of target file from parent directory
     */
    ino = ip->i_ino;
    if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) {
        jfs_err("jfs_unlink: dtDelete returned %d", rc);
        if (rc == -EIO)
            txAbort(tid, 1);	/* Marks FS Dirty */
        txEnd(tid);
        mutex_unlock(&JFS_IP(ip)->commit_mutex);
        mutex_unlock(&JFS_IP(dip)->commit_mutex);
        IWRITE_UNLOCK(ip);
        goto out1;
    }

    ASSERT(ip->i_nlink);

    ip->i_ctime = dip->i_ctime = dip->i_mtime = CURRENT_TIME;
    mark_inode_dirty(dip);

    /* update target's inode */
    inode_dec_link_count(ip);

    /*
     *	commit zero link count object
     */
    if (ip->i_nlink == 0) {
        assert(!test_cflag(COMMIT_Nolink, ip));
        /* free block resources */
        if ((new_size = commitZeroLink(tid, ip)) < 0) {
            txAbort(tid, 1);	/* Marks FS Dirty */
            txEnd(tid);
            mutex_unlock(&JFS_IP(ip)->commit_mutex);
            mutex_unlock(&JFS_IP(dip)->commit_mutex);
            IWRITE_UNLOCK(ip);
            rc = new_size;
            goto out1;
        }
        tblk = tid_to_tblock(tid);
        tblk->xflag |= COMMIT_DELETE;
        tblk->u.ip = ip;
    }

    /*
     * Incomplete truncate of file data can
     * result in timing problems unless we synchronously commit the
     * transaction.
     */
    if (new_size)
        commit_flag = COMMIT_SYNC;
    else
        commit_flag = 0;

    /*
     * If xtTruncate was incomplete, commit synchronously to avoid
     * timing complications
     */
    rc = txCommit(tid, 2, &iplist[0], commit_flag);

    txEnd(tid);

    mutex_unlock(&JFS_IP(ip)->commit_mutex);
    mutex_unlock(&JFS_IP(dip)->commit_mutex);

    while (new_size && (rc == 0)) {
        tid = txBegin(dip->i_sb, 0);
        mutex_lock(&JFS_IP(ip)->commit_mutex);
        new_size = xtTruncate_pmap(tid, ip, new_size);
        if (new_size < 0) {
            txAbort(tid, 1);	/* Marks FS Dirty */
            rc = new_size;
        } else
            rc = txCommit(tid, 2, &iplist[0], COMMIT_SYNC);
        txEnd(tid);
        mutex_unlock(&JFS_IP(ip)->commit_mutex);
    }

    if (ip->i_nlink == 0)
        set_cflag(COMMIT_Nolink, ip);

    IWRITE_UNLOCK(ip);

    /*
     * Truncating the directory index table is not guaranteed.  It
     * may need to be done iteratively
     */
    if (test_cflag(COMMIT_Stale, dip)) {
        if (dip->i_size > 1)
            jfs_truncate_nolock(dip, 0);

        clear_cflag(COMMIT_Stale, dip);
    }

out1:
    free_UCSname(&dname);
out:
    jfs_info("jfs_unlink: rc:%d", rc);
    return rc;
}
Ejemplo n.º 25
0
/*
 * NAME:	jfs_rmdir(dip, dentry)
 *
 * FUNCTION:	remove a link to child directory
 *
 * PARAMETER:	dip	- parent inode
 *		dentry	- child directory dentry
 *
 * RETURN:	-EINVAL	- if name is . or ..
 *		-EINVAL - if . or .. exist but are invalid.
 *		errors from subroutines
 *
 * note:
 * if other threads have the directory open when the last link
 * is removed, the "." and ".." entries, if present, are removed before
 * rmdir() returns and no new entries may be created in the directory,
 * but the directory is not removed until the last reference to
 * the directory is released (cf.unlink() of regular file).
 */
static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
{
    int rc;
    tid_t tid;		/* transaction id */
    struct inode *ip = dentry->d_inode;
    ino_t ino;
    struct component_name dname;
    struct inode *iplist[2];
    struct tblock *tblk;

    jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name);

    /* Init inode for quota operations. */
    dquot_initialize(dip);
    dquot_initialize(ip);

    /* directory must be empty to be removed */
    if (!dtEmpty(ip)) {
        rc = -ENOTEMPTY;
        goto out;
    }

    if ((rc = get_UCSname(&dname, dentry))) {
        goto out;
    }

    tid = txBegin(dip->i_sb, 0);

    mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
    mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);

    iplist[0] = dip;
    iplist[1] = ip;

    tblk = tid_to_tblock(tid);
    tblk->xflag |= COMMIT_DELETE;
    tblk->u.ip = ip;

    /*
     * delete the entry of target directory from parent directory
     */
    ino = ip->i_ino;
    if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) {
        jfs_err("jfs_rmdir: dtDelete returned %d", rc);
        if (rc == -EIO)
            txAbort(tid, 1);
        txEnd(tid);
        mutex_unlock(&JFS_IP(ip)->commit_mutex);
        mutex_unlock(&JFS_IP(dip)->commit_mutex);

        goto out2;
    }

    /* update parent directory's link count corresponding
     * to ".." entry of the target directory deleted
     */
    dip->i_ctime = dip->i_mtime = CURRENT_TIME;
    inode_dec_link_count(dip);

    /*
     * OS/2 could have created EA and/or ACL
     */
    /* free EA from both persistent and working map */
    if (JFS_IP(ip)->ea.flag & DXD_EXTENT) {
        /* free EA pages */
        txEA(tid, ip, &JFS_IP(ip)->ea, NULL);
    }
    JFS_IP(ip)->ea.flag = 0;

    /* free ACL from both persistent and working map */
    if (JFS_IP(ip)->acl.flag & DXD_EXTENT) {
        /* free ACL pages */
        txEA(tid, ip, &JFS_IP(ip)->acl, NULL);
    }
    JFS_IP(ip)->acl.flag = 0;

    /* mark the target directory as deleted */
    clear_nlink(ip);
    mark_inode_dirty(ip);

    rc = txCommit(tid, 2, &iplist[0], 0);

    txEnd(tid);

    mutex_unlock(&JFS_IP(ip)->commit_mutex);
    mutex_unlock(&JFS_IP(dip)->commit_mutex);

    /*
     * Truncating the directory index table is not guaranteed.  It
     * may need to be done iteratively
     */
    if (test_cflag(COMMIT_Stale, dip)) {
        if (dip->i_size > 1)
            jfs_truncate_nolock(dip, 0);

        clear_cflag(COMMIT_Stale, dip);
    }

out2:
    free_UCSname(&dname);

out:
    jfs_info("jfs_rmdir: rc:%d", rc);
    return rc;
}
Ejemplo n.º 26
0
int jfs_mount(struct super_block *sb)
{
	int rc = 0;		
	struct jfs_sb_info *sbi = JFS_SBI(sb);
	struct inode *ipaimap = NULL;
	struct inode *ipaimap2 = NULL;
	struct inode *ipimap = NULL;
	struct inode *ipbmap = NULL;

	if ((rc = chkSuper(sb))) {
		goto errout20;
	}

	ipaimap = diReadSpecial(sb, AGGREGATE_I, 0);
	if (ipaimap == NULL) {
		jfs_err("jfs_mount: Failed to read AGGREGATE_I");
		rc = -EIO;
		goto errout20;
	}
	sbi->ipaimap = ipaimap;

	jfs_info("jfs_mount: ipaimap:0x%p", ipaimap);

	if ((rc = diMount(ipaimap))) {
		jfs_err("jfs_mount: diMount(ipaimap) failed w/rc = %d", rc);
		goto errout21;
	}

	ipbmap = diReadSpecial(sb, BMAP_I, 0);
	if (ipbmap == NULL) {
		rc = -EIO;
		goto errout22;
	}

	jfs_info("jfs_mount: ipbmap:0x%p", ipbmap);

	sbi->ipbmap = ipbmap;

	if ((rc = dbMount(ipbmap))) {
		jfs_err("jfs_mount: dbMount failed w/rc = %d", rc);
		goto errout22;
	}

	if ((sbi->mntflag & JFS_BAD_SAIT) == 0) {
		ipaimap2 = diReadSpecial(sb, AGGREGATE_I, 1);
		if (!ipaimap2) {
			jfs_err("jfs_mount: Failed to read AGGREGATE_I");
			rc = -EIO;
			goto errout35;
		}
		sbi->ipaimap2 = ipaimap2;

		jfs_info("jfs_mount: ipaimap2:0x%p", ipaimap2);

		if ((rc = diMount(ipaimap2))) {
			jfs_err("jfs_mount: diMount(ipaimap2) failed, rc = %d",
				rc);
			goto errout35;
		}
	} else
		
		sbi->ipaimap2 = NULL;

	ipimap = diReadSpecial(sb, FILESYSTEM_I, 0);
	if (ipimap == NULL) {
		jfs_err("jfs_mount: Failed to read FILESYSTEM_I");
		
		rc = -EIO;
		goto errout40;
	}
	jfs_info("jfs_mount: ipimap:0x%p", ipimap);

	
	sbi->ipimap = ipimap;

	
	if ((rc = diMount(ipimap))) {
		jfs_err("jfs_mount: diMount failed w/rc = %d", rc);
		goto errout41;
	}

	goto out;

      errout41:		
	diFreeSpecial(ipimap);

      errout40:		

	
	if (ipaimap2) {
		diUnmount(ipaimap2, 1);
		diFreeSpecial(ipaimap2);
	}

      errout35:

	
	dbUnmount(ipbmap, 1);
	diFreeSpecial(ipbmap);

      errout22:		

	diUnmount(ipaimap, 1);

      errout21:		
	diFreeSpecial(ipaimap);
      errout20:		

      out:

	if (rc)
		jfs_err("Mount JFS Failure: %d", rc);

	return rc;
}
Ejemplo n.º 27
0
/*
 * NAME:	jfs_mkdir(dip, dentry, mode)
 *
 * FUNCTION:	create a child directory in the parent directory <dip>
 *		with name = <from dentry> and mode = <mode>
 *
 * PARAMETER:	dip 	- parent directory vnode
 *		dentry	- dentry of child directory
 *		mode	- create mode (rwxrwxrwx).
 *
 * RETURN:	Errors from subroutines
 *
 * note:
 * EACCESS: user needs search+write permission on the parent directory
 */
static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
{
	int rc = 0;
	tid_t tid;		/* transaction id */
	struct inode *ip = NULL;	/* child directory inode */
	ino_t ino;
	struct component_name dname;	/* child directory name */
	struct btstack btstack;
	struct inode *iplist[2];
	struct tblock *tblk;

	jfs_info("jfs_mkdir: dip:0x%p name:%s", dip, dentry->d_name.name);

	/* link count overflow on parent directory ? */
	if (dip->i_nlink == JFS_LINK_MAX) {
		rc = -EMLINK;
		goto out1;
	}

	/*
	 * search parent directory for entry/freespace
	 * (dtSearch() returns parent directory page pinned)
	 */
	if ((rc = get_UCSname(&dname, dentry)))
		goto out1;

	/*
	 * Either iAlloc() or txBegin() may block.  Deadlock can occur if we
	 * block there while holding dtree page, so we allocate the inode &
	 * begin the transaction before we search the directory.
	 */
	ip = ialloc(dip, S_IFDIR | mode);
	if (ip == NULL) {
		rc = -ENOSPC;
		goto out2;
	}

	tid = txBegin(dip->i_sb, 0);

	mutex_lock(&JFS_IP(dip)->commit_mutex);
	mutex_lock(&JFS_IP(ip)->commit_mutex);

	rc = jfs_init_acl(tid, ip, dip);
	if (rc)
		goto out3;

	rc = jfs_init_security(tid, ip, dip);
	if (rc) {
		txAbort(tid, 0);
		goto out3;
	}

	if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
		jfs_err("jfs_mkdir: dtSearch returned %d", rc);
		txAbort(tid, 0);
		goto out3;
	}

	tblk = tid_to_tblock(tid);
	tblk->xflag |= COMMIT_CREATE;
	tblk->ino = ip->i_ino;
	tblk->u.ixpxd = JFS_IP(ip)->ixpxd;

	iplist[0] = dip;
	iplist[1] = ip;

	/*
	 * initialize the child directory in-line in inode
	 */
	dtInitRoot(tid, ip, dip->i_ino);

	/*
	 * create entry in parent directory for child directory
	 * (dtInsert() releases parent directory page)
	 */
	ino = ip->i_ino;
	if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
		if (rc == -EIO) {
			jfs_err("jfs_mkdir: dtInsert returned -EIO");
			txAbort(tid, 1);	/* Marks Filesystem dirty */
		} else
			txAbort(tid, 0);	/* Filesystem full */
		goto out3;
	}

	ip->i_nlink = 2;	/* for '.' */
	ip->i_op = &jfs_dir_inode_operations;
	ip->i_fop = &jfs_dir_operations;

	insert_inode_hash(ip);
	mark_inode_dirty(ip);

	/* update parent directory inode */
	dip->i_nlink++;		/* for '..' from child directory */
	dip->i_ctime = dip->i_mtime = CURRENT_TIME;
	mark_inode_dirty(dip);

	rc = txCommit(tid, 2, &iplist[0], 0);

      out3:
	txEnd(tid);
	mutex_unlock(&JFS_IP(ip)->commit_mutex);
	mutex_unlock(&JFS_IP(dip)->commit_mutex);
	if (rc) {
		free_ea_wmap(ip);
		ip->i_nlink = 0;
		iput(ip);
	} else
		d_instantiate(dentry, ip);

      out2:
	free_UCSname(&dname);


      out1:

	jfs_info("jfs_mkdir: rc:%d", rc);
	return rc;
}
Ejemplo n.º 28
0
/*
 * NAME:	jfs_create(dip, dentry, mode)
 *
 * FUNCTION:	create a regular file in the parent directory <dip>
 *		with name = <from dentry> and mode = <mode>
 *
 * PARAMETER:	dip 	- parent directory vnode
 *		dentry	- dentry of new file
 *		mode	- create mode (rwxrwxrwx).
 *
 * RETURN:	Errors from subroutines
 *
 */
static int jfs_create(struct inode *dip, struct dentry *dentry, int mode)
{
	int rc = 0;
	tid_t tid;		/* transaction id */
	struct inode *ip = NULL;	/* child directory inode */
	ino_t ino;
	struct component_name dname;	/* child directory name */
	struct btstack btstack;
	struct inode *iplist[2];
	struct tblock *tblk;

	jfs_info("jfs_create: dip:0x%p name:%s", dip, dentry->d_name.name);

	/*
	 * search parent directory for entry/freespace
	 * (dtSearch() returns parent directory page pinned)
	 */
	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab)))
		goto out1;

	/*
	 * Either iAlloc() or txBegin() may block.  Deadlock can occur if we
	 * block there while holding dtree page, so we allocate the inode &
	 * begin the transaction before we search the directory.
	 */
	ip = ialloc(dip, mode);
	if (ip == NULL) {
		rc = -ENOSPC;
		goto out2;
	}

	tid = txBegin(dip->i_sb, 0);

	down(&JFS_IP(dip)->commit_sem);
	down(&JFS_IP(ip)->commit_sem);

	if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
		jfs_err("jfs_create: dtSearch returned %d", rc);
		goto out3;
	}

	tblk = tid_to_tblock(tid);
	tblk->xflag |= COMMIT_CREATE;
	tblk->ip = ip;

	iplist[0] = dip;
	iplist[1] = ip;

	/*
	 * initialize the child XAD tree root in-line in inode
	 */
	xtInitRoot(tid, ip);

	/*
	 * create entry in parent directory for child directory
	 * (dtInsert() releases parent directory page)
	 */
	ino = ip->i_ino;
	if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
		jfs_err("jfs_create: dtInsert returned %d", rc);
		if (rc == -EIO)
			txAbort(tid, 1);	/* Marks Filesystem dirty */
		else
			txAbort(tid, 0);	/* Filesystem full */
		goto out3;
	}

	ip->i_op = &jfs_file_inode_operations;
	ip->i_fop = &jfs_file_operations;
	ip->i_mapping->a_ops = &jfs_aops;

	insert_inode_hash(ip);
	mark_inode_dirty(ip);
	d_instantiate(dentry, ip);

	dip->i_ctime = dip->i_mtime = CURRENT_TIME;

	mark_inode_dirty(dip);

	rc = txCommit(tid, 2, &iplist[0], 0);

      out3:
	txEnd(tid);
	up(&JFS_IP(dip)->commit_sem);
	up(&JFS_IP(ip)->commit_sem);
	if (rc) {
		ip->i_nlink = 0;
		iput(ip);
	}

      out2:
	free_UCSname(&dname);

      out1:

	jfs_info("jfs_create: rc:%d", rc);
	return rc;
}