Esempio n. 1
0
/**
 * ntfs_file_fsync - sync a file to disk
 * @filp:	file to be synced
 * @dentry:	dentry describing the file to sync
 * @datasync:	if non-zero only flush user data and not metadata
 *
 * Data integrity sync of a file to disk.  Used for fsync, fdatasync, and msync
 * system calls.  This function is inspired by fs/buffer.c::file_fsync().
 *
 * If @datasync is false, write the mft record and all associated extent mft
 * records as well as the $DATA attribute and then sync the block device.
 *
 * If @datasync is true and the attribute is non-resident, we skip the writing
 * of the mft record and all associated extent mft records (this might still
 * happen due to the write_inode_now() call).
 *
 * Also, if @datasync is true, we do not wait on the inode to be written out
 * but we always wait on the page cache pages to be written out.
 *
 * Note: In the past @filp could be NULL so we ignore it as we don't need it
 * anyway.
 *
 * Locking: Caller must hold i_sem on the inode.
 *
 * TODO: We should probably also write all attribute/index inodes associated
 * with this inode but since we have no simple way of getting to them we ignore
 * this problem for now.
 */
static int ntfs_file_fsync(struct file *filp, struct dentry *dentry,
		int datasync)
{
	struct inode *vi = dentry->d_inode;
	int err, ret = 0;

	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
	BUG_ON(S_ISDIR(vi->i_mode));
	if (!datasync || !NInoNonResident(NTFS_I(vi)))
		ret = ntfs_write_inode(vi, 1);
	write_inode_now(vi, !datasync);
	/*
	 * NOTE: If we were to use mapping->private_list (see ext2 and
	 * fs/buffer.c) for dirty blocks then we could optimize the below to be
	 * sync_mapping_buffers(vi->i_mapping).
	 */
	err = sync_blockdev(vi->i_sb->s_bdev);
	if (unlikely(err && !ret))
		ret = err;
	if (likely(!ret))
		ntfs_debug("Done.");
	else
		ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "
				"%u.", datasync ? "data" : "", vi->i_ino, -ret);
	return ret;
}
Esempio n. 2
0
/**
 * ntfs_get_dentry - find a dentry for the inode from a file handle sub-fragment
 * @sb:		super block identifying the mounted ntfs volume
 * @fh:		the file handle sub-fragment
 *
 * Find a dentry for the inode given a file handle sub-fragment.  This function
 * is called from fs/exportfs/expfs.c::find_exported_dentry() which in turn is
 * called from the default ->decode_fh() which is export_decode_fh() in the
 * same file.  The code is closely based on the default ->get_dentry() helper
 * fs/exportfs/expfs.c::get_object().
 *
 * The @fh contains two 32-bit unsigned values, the first one is the inode
 * number and the second one is the inode generation.
 *
 * Return the dentry on success or the error code on error (IS_ERR() is true).
 */
static struct dentry *ntfs_get_dentry(struct super_block *sb, void *fh)
{
	struct inode *vi;
	struct dentry *dent;
	unsigned long ino = ((u32 *)fh)[0];
	u32 gen = ((u32 *)fh)[1];

	ntfs_debug("Entering for inode 0x%lx, generation 0x%x.", ino, gen);
	vi = ntfs_iget(sb, ino);
	if (IS_ERR(vi)) {
		ntfs_error(sb, "Failed to get inode 0x%lx.", ino);
		return (struct dentry *)vi;
	}
	if (unlikely(is_bad_inode(vi) || vi->i_generation != gen)) {
		/* We didn't find the right inode. */
		ntfs_error(sb, "Inode 0x%lx, bad count: %d %d or version 0x%x "
				"0x%x.", vi->i_ino, vi->i_nlink,
				atomic_read(&vi->i_count), vi->i_generation,
				gen);
		iput(vi);
		return ERR_PTR(-ESTALE);
	}
	/* Now find a dentry.  If possible, get a well-connected one. */
	dent = d_alloc_anon(vi);
	if (unlikely(!dent)) {
		iput(vi);
		return ERR_PTR(-ENOMEM);
	}
	ntfs_debug("Done for inode 0x%lx, generation 0x%x.", ino, gen);
	return dent;
}
Esempio n. 3
0
File: fs.c Progetto: hugh712/Jollen
/* Called by the kernel when asking for stats. */
static int ntfs_statfs(struct super_block *sb, struct statfs *sf)
{
	struct inode *mft;
	ntfs_volume *vol;
	__s64 size;
	int error;

	ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n");
	vol = NTFS_SB2VOL(sb);
	sf->f_type = NTFS_SUPER_MAGIC;
	sf->f_bsize = vol->cluster_size;
	error = ntfs_get_volumesize(NTFS_SB2VOL(sb), &size);
	if (error)
		return error;
	sf->f_blocks = size;	/* Volumesize is in clusters. */
	size = (__s64)ntfs_get_free_cluster_count(vol->bitmap);
	/* Just say zero if the call failed. */
	if (size < 0LL)
		size = 0;
	sf->f_bfree = sf->f_bavail = size;
	ntfs_debug(DEBUG_OTHER, "ntfs_statfs: calling mft = iget(sb, "
			"FILE_Mft)\n");
	mft = iget(sb, FILE_Mft);
	ntfs_debug(DEBUG_OTHER, "ntfs_statfs: iget(sb, FILE_Mft) returned "
			"0x%x\n", mft);
	if (!mft)
		return -EIO;
	sf->f_files = mft->i_size >> vol->mft_record_size_bits;
	ntfs_debug(DEBUG_OTHER, "ntfs_statfs: calling iput(mft)\n");
	iput(mft);
	/* Should be read from volume. */
	sf->f_namelen = 255;
	return 0;
}
Esempio n. 4
0
File: fs.c Progetto: hugh712/Jollen
static void _ntfs_clear_inode(struct inode *inode)
{
	ntfs_inode *ino;
	ntfs_volume *vol;
	
	lock_kernel();
	ntfs_debug(DEBUG_OTHER, "_ntfs_clear_inode 0x%x\n", inode->i_ino);
	vol = NTFS_INO2VOL(inode);
	if (!vol)
		ntfs_error("_ntfs_clear_inode: vol = NTFS_INO2VOL(inode) is "
				"NULL.\n");
	switch (inode->i_ino) {
	case FILE_Mft:
		if (vol->mft_ino && ((vol->ino_flags & 1) == 0)) {
			ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
			ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
			vol->mft_ino = ino;
			vol->ino_flags |= 1;
			goto unl_out;
		}
		break;
	case FILE_MftMirr:
		if (vol->mftmirr && ((vol->ino_flags & 2) == 0)) {
			ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
			ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
			vol->mftmirr = ino;
			vol->ino_flags |= 2;
			goto unl_out;
		}
		break;
	case FILE_BitMap:
		if (vol->bitmap && ((vol->ino_flags & 4) == 0)) {
			ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
			ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
			vol->bitmap = ino;
			vol->ino_flags |= 4;
			goto unl_out;
		}
		break;
	default:
		/* Nothing. Just clear the inode and exit. */
	}
	ntfs_clear_inode(&inode->u.ntfs_i);
unl_out:
	unlock_kernel();
	return;
}

/* Called when umounting a filesystem by do_umount() in fs/super.c. */
static void ntfs_put_super(struct super_block *sb)
{
	ntfs_volume *vol;

	ntfs_debug(DEBUG_OTHER, "ntfs_put_super\n");
	vol = NTFS_SB2VOL(sb);
	ntfs_release_volume(vol);
	if (vol->nls_map)
		unload_nls(vol->nls_map);
	ntfs_debug(DEBUG_OTHER, "ntfs_put_super: done\n");
}
Esempio n. 5
0
static int
_linux_ntfs_mkdir(struct inode *dir, struct dentry* d, int mode)
{
	int error;
	struct inode *r = 0;
	ntfs_volume *vol;
	ntfs_inode *ino;
	ntfs_attribute *si;

	ntfs_debug (DEBUG_DIR1, "mkdir %s in %x\n",d->d_name.name, dir->i_ino);
	error = ENAMETOOLONG;
	if (d->d_name.len > /* FIXME */255)
		goto out;

	error = EIO;
	r = get_empty_inode();
	if (!r)
		goto out;
	
	vol = NTFS_INO2VOL(dir);
#ifdef NTFS_IN_LINUX_KERNEL
	ino = NTFS_LINO2NINO(r);
#else
	ino = ntfs_malloc(sizeof(ntfs_inode));
	error = ENOMEM;
	if(!ino)
		goto out;
	r->u.generic_ip = ino;
#endif
	error = ntfs_mkdir(NTFS_LINO2NINO(dir), 
			   d->d_name.name, d->d_name.len, ino);
	if(error)
		goto out;
	r->i_uid = vol->uid;
	r->i_gid = vol->gid;
	r->i_nlink = 1;
	r->i_sb = dir->i_sb;
	si = ntfs_find_attr(ino,vol->at_standard_information,NULL);
	if(si){
		char *attr = si->d.data;
		r->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr+0x18));
		r->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));
		r->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr+8));
	}
	/* It's a directory */
	r->i_op = &ntfs_dir_inode_operations;
	r->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
#ifdef CONFIG_NTFS_RW
	r->i_mode|=S_IWUGO;
#endif
	r->i_mode &= ~vol->umask;	
	
	insert_inode_hash(r);
	d_instantiate(d, r);
	error = 0;
 out:
 	ntfs_debug (DEBUG_DIR1, "mkdir returns %d\n", -error);
	return -error;
}
Esempio n. 6
0
/**
 * ntfs_usnjrnl_stamp - stamp the transaction log ($UsnJrnl) on an ntfs volume
 * @vol:	ntfs volume on which to stamp the transaction log
 *
 * Stamp the transaction log ($UsnJrnl) on the ntfs volume @vol and return 0
 * on success and errno on error.
 *
 * This function assumes that the transaction log has already been loaded and
 * consistency checked by a call to ntfs_vfsops.c::ntfs_usnjrnl_load().
 */
errno_t ntfs_usnjrnl_stamp(ntfs_volume *vol)
{
	ntfs_debug("Entering.");
	if (!NVolUsnJrnlStamped(vol)) {
		sle64 j_size, stamp;
		upl_t upl;
		upl_page_info_array_t pl;
		USN_HEADER *uh;
		ntfs_inode *max_ni;
		errno_t err;

		mtx_lock_spin(&vol->usnjrnl_j_ni->size_lock);
		j_size = vol->usnjrnl_j_ni->data_size;
		mtx_unlock_spin(&vol->usnjrnl_j_ni->size_lock);
		max_ni = vol->usnjrnl_max_ni;
		/*
		 * FIXME: Next If statement always false because of
		 * replacing vnode_get() with vhold()
		 */
		vhold(max_ni->vn);
		if (0) {
			ntfs_error(vol->mp, "Failed to get vnode for "
					"$UsnJrnl/$DATA/$Max.");
			return err;
		}
		sx_slock(&max_ni->lock);
		err = ntfs_page_map(max_ni, 0, &upl, &pl, (u8**)&uh, TRUE);
		if (err) {
			ntfs_error(vol->mp, "Failed to read from "
					"$UsnJrnl/$DATA/$Max attribute.");
			vdrop(max_ni->vn);
			return err;
		}
		stamp = ntfs_current_time();
		ntfs_debug("Stamping transaction log ($UsnJrnl): old "
				"journal_id 0x%llx, old lowest_valid_usn "
				"0x%llx, new journal_id 0x%llx, new "
				"lowest_valid_usn 0x%llx.",
				(unsigned long long)
				sle64_to_cpu(uh->journal_id),
				(unsigned long long)
				sle64_to_cpu(uh->lowest_valid_usn),
				(unsigned long long)sle64_to_cpu(stamp),
				(unsigned long long)j_size);
		uh->lowest_valid_usn = cpu_to_sle64(j_size);
		uh->journal_id = stamp;
		ntfs_page_unmap(max_ni, upl, pl, TRUE);
		sx_sunlock(&max_ni->lock);
		vdrop(max_ni->vn);
		/* Set the flag so we do not have to do it again on remount. */
		NVolSetUsnJrnlStamped(vol);
		// TODO: Should we mark any times on the base inode $UsnJrnl
		// for update here?
	}
	ntfs_debug("Done.");
	return 0;
}
Esempio n. 7
0
/* Called when umounting a filesystem by do_umount() in fs/super.c. */
static void ntfs_put_super(struct super_block *sb)
{
	ntfs_volume *vol;

	ntfs_debug(DEBUG_OTHER, "ntfs_put_super\n");
	vol = NTFS_SB2VOL(sb);
	ntfs_release_volume(vol);
	if (vol->nls_map)
		unload_nls(vol->nls_map);
	ntfs_debug(DEBUG_OTHER, "ntfs_put_super: done\n");
}
Esempio n. 8
0
/**
 * ntfs_inode_hash_lookup - find and return a loaded ntfs inode
 *
 * Search the ntfs inode hash for the ntfs inode matching @na and if present
 * return it.  If not present return NULL.
 *
 * If the found ntfs inode has a vnode attached, then get an iocount reference
 * on the vnode.
 */
ntfs_inode *ntfs_inode_hash_lookup(ntfs_volume *vol, const ntfs_attr *na)
{
	ntfs_inode_list_head *list;
	ntfs_inode *ni;

	ntfs_debug("Entering for mft_no 0x%llx, type 0x%x, name_len 0x%x.",
			(unsigned long long)na->mft_no,
			(unsigned)le32_to_cpu(na->type), na->name_len);
	list = ntfs_inode_hash_list(vol, na->mft_no);
	ni = ntfs_inode_hash_list_find(vol, list, na);
	ntfs_debug("Done (ntfs_inode %sfound in cache).", ni ? "" : "not ");
	return ni;
}
Esempio n. 9
0
File: fs.c Progetto: hugh712/Jollen
static int _linux_ntfs_mkdir(struct inode *dir, struct dentry* d, int mode)
{
	int error;
	struct inode *r = 0;
	ntfs_volume *vol;
	ntfs_inode *ino;
	ntfs_attribute *si;

	ntfs_debug (DEBUG_DIR1, "mkdir %s in %x\n", d->d_name.name, dir->i_ino);
	error = -ENAMETOOLONG;
	if (d->d_name.len > /* FIXME: */ 255)
		goto out;
	error = -EIO;
	r = new_inode(dir->i_sb);
	if (!r)
		goto out;
	vol = NTFS_INO2VOL(dir);
	ino = NTFS_LINO2NINO(r);
	error = ntfs_mkdir(NTFS_LINO2NINO(dir), d->d_name.name, d->d_name.len,
			   ino);
	if (error)
		goto out;
	/* Not doing this one was causing a huge amount of corruption! Now the
	 * bugger bytes the dust! (-8 (AIA) */
	r->i_ino = ino->i_number;
	r->i_uid = vol->uid;
	r->i_gid = vol->gid;
	si = ntfs_find_attr(ino, vol->at_standard_information, NULL);
	if (si) {
		char *attr = si->d.data;
		r->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 0x18));
		r->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));
		r->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 8));
	}
	/* It's a directory. */
	r->i_op = &ntfs_dir_inode_operations;
	r->i_fop = &ntfs_dir_operations;
	r->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
#ifdef CONFIG_NTFS_RW
	r->i_mode |= S_IWUGO;
#endif
	r->i_mode &= ~vol->umask;	
	
	insert_inode_hash(r);
	d_instantiate(d, r);
	error = 0;
 out:
 	ntfs_debug (DEBUG_DIR1, "mkdir returns %d\n", error);
	return error;
}
Esempio n. 10
0
File: fs.c Progetto: hugh712/Jollen
static ssize_t ntfs_write(struct file *filp, const char *buf, size_t count,
		loff_t *pos)
{
	int err;
	struct inode *vfs_ino = filp->f_dentry->d_inode;
	ntfs_inode *ntfs_ino = NTFS_LINO2NINO(vfs_ino);
	ntfs_attribute *data;
	ntfs_io io;
	struct ntfs_getuser_update_vm_s param;

	if (!ntfs_ino)
		return -EINVAL;
	ntfs_debug(DEBUG_LINUX, __FUNCTION__ "(): Entering for inode 0x%lx, "
			"*pos 0x%Lx, count 0x%x.\n", ntfs_ino->i_number, *pos,
			count);
	/* Allows to lock fs ro at any time. */
	if (vfs_ino->i_sb->s_flags & MS_RDONLY)
		return -EROFS;
	data = ntfs_find_attr(ntfs_ino, ntfs_ino->vol->at_data, NULL);
	if (!data)
		return -EINVAL;
	/* Evaluating O_APPEND is the file system's job... */
	if (filp->f_flags & O_APPEND)
		*pos = vfs_ino->i_size;
	if (!data->resident && *pos + count > data->allocated) {
		err = ntfs_extend_attr(ntfs_ino, data, *pos + count);
		if (err < 0)
			return err;
	}
	param.user = buf;
	param.ino = vfs_ino;
	param.off = *pos;
	io.fn_put = 0;
	io.fn_get = ntfs_getuser_update_vm;
	io.param = &param;
	io.size = count;
	io.do_read = 0;
	err = ntfs_readwrite_attr(ntfs_ino, data, *pos, &io);
	ntfs_debug(DEBUG_LINUX, __FUNCTION__ "(): Returning %i\n", -err);
	if (!err) {
		*pos += io.size;
		if (*pos > vfs_ino->i_size)
			vfs_ino->i_size = *pos;
		mark_inode_dirty(vfs_ino);
		return io.size;
	}
	return err;
}
Esempio n. 11
0
/**
 * ntfs_page_unmap - unmap a page belonging to a vnode from memory
 * @ni:		ntfs inode to which the page belongs
 * @upl:	page list of the page
 * @pl:		array of pages containing the page itself
 * @mark_dirty:	mark the page dirty
 *
 * Unmap the page belonging to the ntfs inode @ni from memory releasing it back
 * to the vm.
 *
 * The page is described by the page list @upl, the array of pages containing
 * the page @pl and the address of the mapped page contents @kaddr.
 *
 * If @mark_dirty is TRUE, tell the vm to mark the page dirty when releasing
 * the page.
 *
 * Locking: Caller must hold an iocount reference on the vnode of @ni.
 */
void ntfs_page_unmap(ntfs_inode *ni, upl_t upl, upl_page_info_array_t pl,
		const BOOL mark_dirty)
{
	kern_return_t kerr;
	BOOL was_valid, was_dirty;

	was_valid = upl_valid_page(pl, 0);
	/* The page dirty bit is only valid if the page was valid. */
	was_dirty = (was_valid && upl_dirty_page(pl, 0));
	ntfs_debug("Entering for inode 0x%llx, page was %svalid %s %sdirty%s.",
			(unsigned long long)ni->mft_no,
			was_valid ? "" : "not ",
			(int)was_valid ^ (int)was_dirty ? "but" : "and",
			was_dirty ? "" : "not ",
			mark_dirty ? ", marking it dirty" : "");
	/* Unmap the page from the kernel's address space. */
	kerr = ubc_upl_unmap(upl);
	if (kerr != KERN_SUCCESS)
		ntfs_warning(ni->vol->mp, "ubc_upl_unmap() failed (error %d).",
				(int)kerr);
	/*
	 * If the page was valid and dirty or is being made dirty or if caching
	 * for the vnode is enabled (as it will usually be the case for all
	 * metadata files), commit it thus releasing it into the vm taking care
	 * to preserve the dirty state and marking the page dirty if requested
	 * when committing the page.
	 *
	 * If the page was not valid or was valid but not dirty, it is not
	 * being marked dirty, and caching is disabled on the vnode, dump the
	 * page.
	 */
	if (was_dirty || mark_dirty || !vnode_isnocache(ni->vn)) {
		int commit_flags;

		commit_flags = UPL_COMMIT_FREE_ON_EMPTY |
				UPL_COMMIT_INACTIVATE;
		if (!was_valid && !mark_dirty)
			commit_flags |= UPL_COMMIT_CLEAR_DIRTY;
		else if (was_dirty || mark_dirty)
			commit_flags |= UPL_COMMIT_SET_DIRTY;
		ubc_upl_commit_range(upl, 0, PAGE_SIZE, commit_flags);
		ntfs_debug("Done (committed page).");
	} else {
		ubc_upl_abort_range(upl, 0, PAGE_SIZE, UPL_ABORT_DUMP_PAGES |
				UPL_ABORT_FREE_ON_EMPTY);
		ntfs_debug("Done (dumped page).");
	}
}
Esempio n. 12
0
static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *d)
{
	struct inode *res=0;
	char *item=0;
	ntfs_iterate_s walk;
	int error;
	ntfs_debug(DEBUG_NAME1, "Looking up %s in %x\n",d->d_name.name,
		   (unsigned)dir->i_ino);
	/* convert to wide string */
	error=ntfs_decodeuni(NTFS_INO2VOL(dir),(char*)d->d_name.name,
			     d->d_name.len,&walk.name,&walk.namelen);
	if(error)
		return ERR_PTR(-error);
	item=ntfs_malloc(ITEM_SIZE);
	if( !item )
		return ERR_PTR(-ENOMEM);
	/* ntfs_getdir will place the directory entry into item,
	   and the first long long is the MFT record number */
	walk.type=BY_NAME;
	walk.dir=NTFS_LINO2NINO(dir);
	walk.result=item;
	if(ntfs_getdir_byname(&walk))
	{
		res=iget(dir->i_sb,NTFS_GETU32(item));
	}
	d_add(d,res);
	ntfs_free(item);
	ntfs_free(walk.name);
	/* Always return success, the dcache will handle negative entries. */
	return NULL;
}
Esempio n. 13
0
/* Called by the kernel when asking for stats */
static int ntfs_statfs(struct super_block *sb, struct statfs *sf, int bufsize)
{
	struct statfs fs;
	struct inode *mft;
	ntfs_volume *vol;
	int error;

	ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n");
	vol=NTFS_SB2VOL(sb);
	memset(&fs,0,sizeof(fs));
	fs.f_type=NTFS_SUPER_MAGIC;
	fs.f_bsize=vol->clustersize;

	error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &fs.f_blocks );
	if( error )
		return -error;
	fs.f_bfree=ntfs_get_free_cluster_count(vol->bitmap);
	fs.f_bavail=fs.f_bfree;

	/* Number of files is limited by free space only, so we lie here */
	fs.f_ffree=0;
	mft=iget(sb,FILE_MFT);
	fs.f_files=mft->i_size/vol->mft_recordsize;
	iput(mft);

	/* should be read from volume */
	fs.f_namelen=255;
	copy_to_user(sf,&fs,bufsize);
	return 0;
}
Esempio n. 14
0
static ssize_t
ntfs_read(struct file * filp, char *buf, size_t count, loff_t *off)
{
	int error;
	ntfs_io io;
	ntfs_inode *ino=NTFS_LINO2NINO(filp->f_dentry->d_inode);

	/* inode is not properly initialized */
	if(!ino)return -EINVAL;
	ntfs_debug(DEBUG_OTHER, "ntfs_read %x,%x,%x ->",
		   (unsigned)ino->i_number,(unsigned)*off,(unsigned)count);
	/* inode has no unnamed data attribute */
	if(!ntfs_find_attr(ino,ino->vol->at_data,NULL))
		return -EINVAL;
	
	/* read the data */
	io.fn_put=ntfs_putuser;
	io.fn_get=0;
	io.param=buf;
	io.size=count;
	error=ntfs_read_attr(ino,ino->vol->at_data,NULL,*off,&io);
	if(error && !io.size)return -error;
	
	*off+=io.size;
	return io.size;
}
Esempio n. 15
0
/* Called by the kernel when asking for stats */
static int ntfs_statfs(struct super_block *sb, struct statfs *sf)
{
	struct inode *mft;
	ntfs_volume *vol;
	ntfs_u64 size;
	int error;

	ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n");
	vol=NTFS_SB2VOL(sb);
	sf->f_type=NTFS_SUPER_MAGIC;
	sf->f_bsize=vol->clustersize;

	error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &size );
	if( error )
		return -error;
	sf->f_blocks = size;	/* volumesize is in clusters */
	sf->f_bfree=ntfs_get_free_cluster_count(vol->bitmap);
	sf->f_bavail=sf->f_bfree;

	mft=iget(sb,FILE_MFT);
	if (!mft)
		return -EIO;
	/* So ... we lie... thus this following cast of loff_t value
	   is ok here.. */
	sf->f_files = (unsigned long)mft->i_size / vol->mft_recordsize;
	iput(mft);

	/* should be read from volume */
	sf->f_namelen=255;
	return 0;
}
Esempio n. 16
0
File: fs.c Progetto: hugh712/Jollen
static void ntfs_write_inode(struct inode *ino, int unused)
{
	lock_kernel();
	ntfs_debug(DEBUG_LINUX, "ntfs_write_inode 0x%x\n", ino->i_ino);
	ntfs_update_inode(NTFS_LINO2NINO(ino));
	unlock_kernel();
}
Esempio n. 17
0
/* Called when umounting a filesystem by do_umount() in fs/super.c */
static void ntfs_put_super(struct super_block *sb)
{
	ntfs_volume *vol;

	ntfs_debug(DEBUG_OTHER, "ntfs_put_super\n");

	vol=NTFS_SB2VOL(sb);

	ntfs_release_volume(vol);
	if(vol->nls_map)
		unload_nls(vol->nls_map);
#ifndef NTFS_IN_LINUX_KERNEL
	ntfs_free(vol);
#endif
	ntfs_debug(DEBUG_OTHER, "ntfs_put_super: done\n");
	MOD_DEC_USE_COUNT;
}
Esempio n. 18
0
/* readdir returns '..', then '.', then the directory entries in sequence
   As the root directory contains a entry for itself, '.' is not emulated
   for the root directory */
static int ntfs_readdir(struct file* filp, void *dirent, filldir_t filldir)
{
	struct ntfs_filldir cb;
	int error;
	struct inode *dir=filp->f_dentry->d_inode;

	ntfs_debug(DEBUG_OTHER, "ntfs_readdir ino %x mode %x\n",
	       (unsigned)dir->i_ino,(unsigned int)dir->i_mode);

	ntfs_debug(DEBUG_OTHER, "readdir: Looking for file %x dircount %d\n",
	       (unsigned)filp->f_pos,atomic_read(&dir->i_count));
	cb.pl=filp->f_pos & 0xFFFF;
	cb.ph=filp->f_pos >> 16;
	/* end of directory */
	if(cb.ph==0xFFFF){
		/* FIXME: Maybe we can return those with the previous call */
		switch(cb.pl){
		case 0: filldir(dirent,".",1,filp->f_pos,dir->i_ino,DT_DIR);
			filp->f_pos=0xFFFF0001;
			return 0;
			/* FIXME: parent directory */
		case 1: filldir(dirent,"..",2,filp->f_pos,0,DT_DIR);
			filp->f_pos=0xFFFF0002;
			return 0;
		}
		ntfs_debug(DEBUG_OTHER, "readdir: EOD\n");
		return 0;
	}
	cb.dir=dir;
	cb.filldir=filldir;
	cb.dirent=dirent;
	cb.type=NTFS_INO2VOL(dir)->ngt;
	do{
		ntfs_debug(DEBUG_OTHER,"looking for next file\n");
		error=ntfs_getdir_unsorted(NTFS_LINO2NINO(dir),&cb.ph,&cb.pl,
				   ntfs_printcb,&cb);
	}while(!error && cb.ph!=0xFFFFFFFF);
	filp->f_pos=(cb.ph<<16)|cb.pl;
	ntfs_debug(DEBUG_OTHER, "new position %x\n",(unsigned)filp->f_pos);
        /* -EINVAL is on user buffer full. This is not considered 
	   as an error by sys_getdents */
	if(error<0) 
		error=0;
	/* Otherwise (device error, inconsistent data), switch the sign */
	return -error;
}
Esempio n. 19
0
static int 
ntfs_bmap(struct inode *ino,int block)
{
	int ret=ntfs_vcn_to_lcn(NTFS_LINO2NINO(ino),block);
	ntfs_debug(DEBUG_OTHER, "bmap of %lx,block %x is %x\n",
	       ino->i_ino,block,ret);
	return (ret==-1) ? 0:ret;
}
Esempio n. 20
0
static int ntfs_collate_binary(ntfs_volume *vol,
        const void *data1, const int data1_len,
        const void *data2, const int data2_len)
{
    int rc;

    ntfs_debug("Entering.");
    rc = memcmp(data1, data2, min(data1_len, data2_len));
    if (!rc && (data1_len != data2_len)) {
        if (data1_len < data2_len)
            rc = -1;
        else
            rc = 1;
    }
    ntfs_debug("Done, returning %i", rc);
    return rc;
}
Esempio n. 21
0
File: fs.c Progetto: hugh712/Jollen
static int ntfs_create(struct inode* dir, struct dentry *d, int mode)
{
	struct inode *r = 0;
	ntfs_inode *ino = 0;
	ntfs_volume *vol;
	int error = 0;
	ntfs_attribute *si;

	r = new_inode(dir->i_sb);
	if (!r) {
		error = -ENOMEM;
		goto fail;
	}
	ntfs_debug(DEBUG_OTHER, "ntfs_create %s\n", d->d_name.name);
	vol = NTFS_INO2VOL(dir);
	ino = NTFS_LINO2NINO(r);
	error = ntfs_alloc_file(NTFS_LINO2NINO(dir), ino, (char*)d->d_name.name,
				d->d_name.len);
	if (error) {
		ntfs_error("ntfs_alloc_file FAILED: error = %i", error);
		goto fail;
	}
	/* Not doing this one was causing a huge amount of corruption! Now the
	 * bugger bytes the dust! (-8 (AIA) */
	r->i_ino = ino->i_number;
	error = ntfs_update_inode(ino);
	if (error)
		goto fail;
	error = ntfs_update_inode(NTFS_LINO2NINO(dir));
	if (error)
		goto fail;
	r->i_uid = vol->uid;
	r->i_gid = vol->gid;
	/* FIXME: dirty? dev? */
	/* Get the file modification times from the standard information. */
	si = ntfs_find_attr(ino, vol->at_standard_information, NULL);
	if (si) {
		char *attr = si->d.data;
		r->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 0x18));
		r->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));
		r->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 8));
	}
	/* It's not a directory */
	r->i_op = &ntfs_inode_operations;
	r->i_fop = &ntfs_file_operations;
	r->i_mode = S_IFREG | S_IRUGO;
#ifdef CONFIG_NTFS_RW
	r->i_mode |= S_IWUGO;
#endif
	r->i_mode &= ~vol->umask;
	insert_inode_hash(r);
	d_instantiate(d, r);
	return 0;
 fail:
	if (r)
		iput(r);
	return error;
}
Esempio n. 22
0
/**
 * ntfs_page_dump - discard a page belonging to a vnode from memory
 * @ni:		ntfs inode to which the page belongs
 * @upl:	page list of the page
 * @pl:		array of pages containing the page itself
 *
 * Unmap the page belonging to the ntfs inode @ni from memory throwing it away.
 * Note that if the page is dirty all changes to the page will be lost as it
 * will be discarded so use this function with extreme caution.
 *
 * The page is described by the page list @upl, the array of pages containing
 * the page @pl and the address of the mapped page contents @kaddr.
 *
 * Locking: Caller must hold an iocount reference on the vnode of @ni.
 */
void ntfs_page_dump(ntfs_inode *ni, upl_t upl,
		upl_page_info_array_t pl __unused)
{
	kern_return_t kerr;

	ntfs_debug("Entering for inode 0x%llx, page is %svalid, %sdirty.",
			(unsigned long long)ni->mft_no,
			upl_valid_page(pl, 0) ? "" : "not ",
			upl_dirty_page(pl, 0) ? "" : "not ");
	/* Unmap the page from the kernel's address space. */
	kerr = ubc_upl_unmap(upl);
	if (kerr != KERN_SUCCESS)
		ntfs_warning(ni->vol->mp, "ubc_upl_unmap() failed (error %d).",
				(int)kerr);
	/* Dump the page. */
	ubc_upl_abort_range(upl, 0, PAGE_SIZE, UPL_ABORT_DUMP_PAGES |
			UPL_ABORT_FREE_ON_EMPTY);
	ntfs_debug("Done.");
}
Esempio n. 23
0
/**
 * ntfs_file_fsync - sync a file to disk
 * @filp:	file to be synced
 * @dentry:	dentry describing the file to sync
 * @datasync:	if non-zero only flush user data and not metadata
 *
 * Data integrity sync of a file to disk.  Used for fsync, fdatasync, and msync
 * system calls.  This function is inspired by fs/buffer.c::file_fsync().
 *
 * If @datasync is false, write the mft record and all associated extent mft
 * records as well as the $DATA attribute and then sync the block device.
 *
 * If @datasync is true and the attribute is non-resident, we skip the writing
 * of the mft record and all associated extent mft records (this might still
 * happen due to the write_inode_now() call).
 *
 * Also, if @datasync is true, we do not wait on the inode to be written out
 * but we always wait on the page cache pages to be written out.
 *
 * Note: In the past @filp could be NULL so we ignore it as we don't need it
 * anyway.
 *
 * Locking: Caller must hold i_sem on the inode.
 *
 * TODO: We should probably also write all attribute/index inodes associated
 * with this inode but since we have no simple way of getting to them we ignore
 * this problem for now.
 */
static int ntfs_file_fsync(struct file *filp, struct dentry *dentry,
		int datasync)
{
	struct inode *vi = dentry->d_inode;
	int err, ret = 0;

	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
	BUG_ON(S_ISDIR(vi->i_mode));
	if (!datasync || !NInoNonResident(NTFS_I(vi)))
		ret = ntfs_write_inode(vi, 1);
	write_inode_now(vi, !datasync);
	err = sync_blockdev(vi->i_sb->s_bdev);
	if (unlikely(err && !ret))
		ret = err;
	if (likely(!ret))
		ntfs_debug("Done.");
	else
		ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "
				"%u.", datasync ? "data" : "", vi->i_ino, -ret);
	return ret;
}
Esempio n. 24
0
static ssize_t
ntfs_write(struct file *filp,const char* buf,size_t count,loff_t *pos)
{
	int ret;
	ntfs_io io;
	struct inode *inode = filp->f_dentry->d_inode;
	ntfs_inode *ino = NTFS_LINO2NINO(inode);
	struct ntfs_getuser_update_vm_s param;

	if (!ino)
		return -EINVAL;
	ntfs_debug (DEBUG_LINUX, "ntfs_write %x,%x,%x ->\n",
	       (unsigned)ino->i_number, (unsigned)*pos, (unsigned)count);
	/* Allows to lock fs ro at any time */
	if (inode->i_sb->s_flags & MS_RDONLY)
		return -ENOSPC;
	if (!ntfs_find_attr(ino,ino->vol->at_data,NULL))
		return -EINVAL;

	/* Evaluating O_APPEND is the file system's job... */
	if (filp->f_flags & O_APPEND)
		*pos = inode->i_size;
	param.user = buf;
	param.ino = inode;
	param.off = *pos;
	io.fn_put = 0;
	io.fn_get = ntfs_getuser_update_vm;
	io.param = &param;
	io.size = count;
	ret = ntfs_write_attr (ino, ino->vol->at_data, NULL, *pos, &io);
	ntfs_debug (DEBUG_LINUX, "write -> %x\n", ret);
	if(ret<0)
		return -EINVAL;

	*pos += io.size;
	if (*pos > inode->i_size)
		inode->i_size = *pos;
	mark_inode_dirty (filp->f_dentry->d_inode);
	return io.size;
}
Esempio n. 25
0
static int __init init_ntfs_fs(void)
{
	/* Comment this if you trust klogd. There are reasons not to trust it
	 */
#if defined(DEBUG) && !defined(MODULE)
	console_verbose();
#endif
	printk(KERN_NOTICE "NTFS version " NTFS_VERSION "\n");
	SYSCTL(1);
	ntfs_debug(DEBUG_OTHER, "registering %s\n",ntfs_fs_type.name);
	/* add this filesystem to the kernel table of filesystems */
	return register_filesystem(&ntfs_fs_type);
}
Esempio n. 26
0
static struct dentry *ntfs_get_parent(struct dentry *child_dent)
{
	struct inode *vi = child_dent->d_inode;
	ntfs_inode *ni = NTFS_I(vi);
	MFT_RECORD *mrec;
	ntfs_attr_search_ctx *ctx;
	ATTR_RECORD *attr;
	FILE_NAME_ATTR *fn;
	unsigned long parent_ino;
	int err;

	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
	
	mrec = map_mft_record(ni);
	if (IS_ERR(mrec))
		return (struct dentry *)mrec;
	
	ctx = ntfs_attr_get_search_ctx(ni, mrec);
	if (unlikely(!ctx)) {
		unmap_mft_record(ni);
		return ERR_PTR(-ENOMEM);
	}
try_next:
	err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, NULL,
			0, ctx);
	if (unlikely(err)) {
		ntfs_attr_put_search_ctx(ctx);
		unmap_mft_record(ni);
		if (err == -ENOENT)
			ntfs_error(vi->i_sb, "Inode 0x%lx does not have a "
					"file name attribute.  Run chkdsk.",
					vi->i_ino);
		return ERR_PTR(err);
	}
	attr = ctx->attr;
	if (unlikely(attr->non_resident))
		goto try_next;
	fn = (FILE_NAME_ATTR *)((u8 *)attr +
			le16_to_cpu(attr->data.resident.value_offset));
	if (unlikely((u8 *)fn + le32_to_cpu(attr->data.resident.value_length) >
			(u8*)attr + le32_to_cpu(attr->length)))
		goto try_next;
	
	parent_ino = MREF_LE(fn->parent_directory);
	
	ntfs_attr_put_search_ctx(ctx);
	unmap_mft_record(ni);

	return d_obtain_alias(ntfs_iget(vi->i_sb, parent_ino));
}
Esempio n. 27
0
/**
 * ntfs_inode_hash_init - initialize the ntfs inode hash
 *
 * Initialize the ntfs inode hash.
 */
errno_t ntfs_inode_hash_init(void)
{
	/* Create the ntfs inode hash. */
	ntfs_inode_hash_table = hashinit(desiredvnodes, M_TEMP,
			&ntfs_inode_hash_mask);
	if (!ntfs_inode_hash_table) {
		ntfs_error(NULL, "Failed to allocate ntfs inode hash table.");
		return ENOMEM;
	}
	ntfs_debug("ntfs_inode_hash_mask 0x%lx.", ntfs_inode_hash_mask);
	/* Initialize the ntfs inode hash lock. */
	mtx_init(&ntfs_inode_hash_lock, "ntfs inode hash lock", NULL, MTX_DEF);
	return 0;
}
Esempio n. 28
0
File: fs.c Progetto: hugh712/Jollen
/* loff_t is 64 bit signed, so is cool. */
static ssize_t ntfs_read(struct file *filp, char *buf, size_t count,loff_t *off)
{
	int error;
	ntfs_io io;
	ntfs_attribute *attr;
	ntfs_inode *ino = NTFS_LINO2NINO(filp->f_dentry->d_inode);

	/* Inode is not properly initialized. */
	if (!ino)
		return -EINVAL;
	ntfs_debug(DEBUG_OTHER, "ntfs_read %x, %Lx, %x ->",
		   (unsigned)ino->i_number, (unsigned long long)*off,
		   (unsigned)count);
	attr = ntfs_find_attr(ino, ino->vol->at_data, NULL);
	/* Inode has no unnamed data attribute. */
	if (!attr) {
		ntfs_debug(DEBUG_OTHER, "ntfs_read: $DATA not found!\n");
		return -EINVAL;
	}
	if (attr->flags & ATTR_IS_ENCRYPTED)
		return -EACCES;
	/* Read the data. */
	io.fn_put = ntfs_putuser;
	io.fn_get = 0;
	io.param = buf;
	io.size = count;
	error = ntfs_read_attr(ino, ino->vol->at_data, NULL, *off, &io);
	if (error && !io.size) {
		ntfs_debug(DEBUG_OTHER, "ntfs_read: read_attr failed with "
				"error %i, io size %u.\n", error, io.size);
		return error;
	}
	*off += io.size;
	ntfs_debug(DEBUG_OTHER, "ntfs_read: finished. read %u bytes.\n",
								io.size);
	return io.size;
}
Esempio n. 29
0
static int ntfs_collate_ntofs_ulong(ntfs_volume *vol,
        const void *data1, const int data1_len,
        const void *data2, const int data2_len)
{
    int rc;
    u32 d1, d2;

    ntfs_debug("Entering.");
    // FIXME:  We don't really want to bug here.
    BUG_ON(data1_len != data2_len);
    BUG_ON(data1_len != 4);
    d1 = le32_to_cpup(data1);
    d2 = le32_to_cpup(data2);
    if (d1 < d2)
        rc = -1;
    else {
        if (d1 == d2)
            rc = 0;
        else
            rc = 1;
    }
    ntfs_debug("Done, returning %i", rc);
    return rc;
}
Esempio n. 30
0
/**
 * ntfs_stamp_usnjrnl - stamp the transaction log ($UsnJrnl) on an ntfs volume
 * @vol:	ntfs volume on which to stamp the transaction log
 *
 * Stamp the transaction log ($UsnJrnl) on the ntfs volume @vol and return
 * 'true' on success and 'false' on error.
 *
 * This function assumes that the transaction log has already been loaded and
 * consistency checked by a call to fs/ntfs/super.c::load_and_init_usnjrnl().
 */
bool ntfs_stamp_usnjrnl(ntfs_volume *vol)
{
	ntfs_debug("Entering.");
	if (likely(!NVolUsnJrnlStamped(vol))) {
		sle64 stamp;
		struct page *page;
		USN_HEADER *uh;

		page = ntfs_map_page(vol->usnjrnl_max_ino->i_mapping, 0);
		if (IS_ERR(page)) {
			ntfs_error(vol->sb, "Failed to read from "
					"$UsnJrnl/$DATA/$Max attribute.");
			return false;
		}
		uh = (USN_HEADER*)page_address(page);
		stamp = get_current_ntfs_time();
		ntfs_debug("Stamping transaction log ($UsnJrnl): old "
				"journal_id 0x%llx, old lowest_valid_usn "
				"0x%llx, new journal_id 0x%llx, new "
				"lowest_valid_usn 0x%llx.",
				(long long)sle64_to_cpu(uh->journal_id),
				(long long)sle64_to_cpu(uh->lowest_valid_usn),
				(long long)sle64_to_cpu(stamp),
				i_size_read(vol->usnjrnl_j_ino));
		uh->lowest_valid_usn =
				cpu_to_sle64(i_size_read(vol->usnjrnl_j_ino));
		uh->journal_id = stamp;
		flush_dcache_page(page);
		set_page_dirty(page);
		ntfs_unmap_page(page);
		/* Set the flag so we do not have to do it again on remount. */
		NVolSetUsnJrnlStamped(vol);
	}
	ntfs_debug("Done.");
	return true;
}