/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/sysmacros.h>
#include <sys/resource.h>
#include <sys/pathname.h>
#include <sys/bootconf.h>
#include <vm/seg_kmem.h>
#ifdef DEBUG
#endif
/*
* WORKSAROUND to the buffer cache crap
* If the requested block exists in the buffer cache
* buffer cache does not care about the count
* it just returns the old buffer(does not even
* set resid value). Same problem exists if the
* block that is requested is not the first block
* in the cached buffer then this will return
* a different buffer. We work around the above by
* using a fixed size request to the buffer cache
* all the time. This is currently udf_lbsize.
* (Actually it is restricted to udf_lbsize
* because iget always does udf_lbsize requests)
*/
/*
* allocate blkcount blocks continuously
* near "proximity" block in partion defined by prn.
* if proximity != 0 means less_is_ok = 0
* return the starting block no and count
* of blocks allocated in start_blkno & size
* if less_is_ok == 0 then allocate only if
* entire requirement can be met.
*/
{
ud_printf("ud_alloc_space\n");
/*
* prom_printf("ud_alloc_space %x %x %x %x\n",
* proximity, blkcount, less_is_ok, metadata);
*/
if (blkcount == 0) {
*start_blkno = 0;
*size = 0;
return (0);
}
break;
}
ud_part ++;
}
return (1);
}
*start_blkno = 0;
*size = 0;
if (metadata) {
if (error == 0) {
*size = 1;
return (0);
}
}
} else {
}
if (error == 0) {
}
} else {
}
/*
* prom_printf("end %x %x %x\n", error, *start_blkno, *size);
*/
return (error);
}
#ifdef SKIP_USED_BLOCKS
/*
* This table is manually constructed
*/
8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};
#endif
{
ud_printf("ud_alloc_space_bmap\n");
if (ud_part->udp_unall_len == 0) {
return (ENOSPC);
}
if (proximity != 0) {
/*
* directly try allocating
* at proximity
*/
if (temp != 0) {
*start_blkno = proximity;
return (0);
}
}
*start_blkno = 0;
*size = 0;
}
while (loop_count--) {
/*
* Each bread is restricted to lbsize
* due to the way bread is implemented
*/
}
return (EIO);
}
}
} else {
}
return (0);
}
if (less_is_ok) {
}
}
if (new_size != 0) {
} else {
#ifdef SKIP_USED_BLOCKS
/*
* Skipping 0's
* implement a allocated block skip
* using a while loop with an
* preinitialised array of 256 elements
* for number of blocks skipped
*/
bno &= ~3;
bno += 8;
#else
bno++;
#endif
}
if (!fragmented) {
}
}
}
if (loop_count) {
loop_begin = 0;
}
}
if ((old_size == 0) && (!fragmented)) {
goto retry;
}
if (less_is_ok && (old_size != 0)) {
/*
* Check once again
* somebody else might have
* already allocated behind us
*/
if (old_size != 0) {
*start_blkno = old_loc;
return (0);
}
}
/*
* Failed what ever the reason
*/
goto retry;
}
return (ENOSPC);
}
/*
* start is the block from the begining
* of the partition ud_part
*/
{
/*
* Adjust start for the header
*/
/*
* Read just on block worth of bitmap
*/
return (EIO);
}
/*
* Adjust the count if necessary
*/
}
return (1);
}
return (0);
}
{
int32_t i = 0;
for (i = 0; i < count; i++) {
break;
}
break;
}
start ++;
}
return (i);
}
void
{
int32_t i = 0;
for (i = 0; i < count; i++) {
start++;
}
}
void
{
int32_t i = 0;
for (i = 0; i < count; i++) {
start++;
}
}
/* ARGSUSED */
{
ud_printf("ud_alloc_space_stbl\n");
if (ud_part->udp_unall_len == 0) {
return (ENOSPC);
}
if (adesc == ICB_FLAG_SHORT_AD) {
/*
* Search the entire list for
* a extent which can give the entire data
* Do only first fit
*/
larg_index = larg_sz = 0;
/*
* We found the right fit
* return the values and
* compress the table
*/
less_is_ok = 1;
larg_index = index;
goto compress_sad;
/*
* We found an entry larger than the
* requirement. Change the start block
* number and the count to reflect the
* allocation
*/
goto end;
}
/*
* Let us keep track of the largest
* extent available if less_is_ok.
*/
if (less_is_ok) {
larg_index = index;
}
}
}
if ((less_is_ok) && (larg_sz != 0)) {
/*
* If we came here we could
* not find a extent to cover the entire size
* return whatever could be allocated
* and compress the table
*/
sad += larg_index;
}
} else {
}
goto end;
} else if (adesc == ICB_FLAG_LONG_AD) {
/*
* Search the entire list for
* a extent which can give the entire data
* Do only first fit
*/
larg_index = larg_sz = 0;
/*
* We found the right fit
* return the values and
* compress the table
*/
less_is_ok = 1;
larg_index = index;
goto compress_lad;
/*
* We found an entry larger than the
* requirement. Change the start block
* number and the count to reflect the
* allocation
*/
goto end;
}
/*
* Let us keep track of the largest
* extent available if less_is_ok.
*/
if (less_is_ok) {
larg_index = index;
}
}
}
if ((less_is_ok) && (larg_sz != 0)) {
/*
* If we came here we could
* not find a extent to cover the entire size
* return whatever could be allocated
* and compress the table
*/
lad += larg_index;
}
} else {
}
goto end;
} else {
}
end:
if (!error) {
} else {
}
return (error);
}
/*
* release blkcount blocks starting from beginblk
*/
void
{
ud_printf("ud_free_space\n");
if (blkcount == 0) {
return;
}
break;
}
ud_part ++;
}
return;
}
} else {
}
if (error) {
}
}
/*
* If there is a freed table then
* release blocks to the freed table
* other wise release to the un allocated table.
* Findout the offset into the bitmap and
* mark the blocks as free blocks
*/
{
ud_printf("ud_free_space_bmap\n");
/*
* prom_printf("%x %x\n", udblock, udcount);
*/
if ((ud_part->udp_freed_len == 0) &&
(ud_part->udp_unall_len == 0)) {
return (ENOSPC);
}
/*
* decide unallocated/freed table to use
*/
if (ud_part->udp_freed_len == 0) {
} else {
}
return (ENOSPC);
}
/* adjust for the bitmap header */
return (EIO);
}
/*
* add freed blocks to the bitmap
*/
} else {
}
/*
* if (begin != end) {
* printf("%x %x %x %x %x %x\n",
* begin, end, block, blkno, count);
* printf("%x %x %x\n", bp->b_un.b_addr, blkno, count);
* }
*/
if (ud_part->udp_freed_len == 0) {
}
}
return (0);
}
/* ARGSUSED */
/*
* search the entire table if there is
* a entry with which we can merge the
* current entry. Other wise create
* a new entry at the end of the table
*/
{
ud_printf("ud_free_space_stbl\n");
return (ENOSPC);
}
if (ud_part->udp_freed_len != 0) {
} else {
}
if (adesc == ICB_FLAG_SHORT_AD) {
/*
* Check if the blocks being freed
* are continuous with any of the
* existing extents
*/
udf_vfsp->udf_lbsize))) {
goto end;
goto end;
}
}
/*
* We need to add a new entry
* Check if we space.
*/
udf_vfsp->udf_lbsize) {
goto end;
}
/*
* We have enough space
* just add the entry at the end
*/
} else if (adesc == ICB_FLAG_LONG_AD) {
/*
* Check if the blocks being freed
* are continuous with any of the
* existing extents
*/
udf_vfsp->udf_lbsize))) {
goto end;
goto end;
}
}
/*
* We need to add a new entry
* Check if we space.
*/
udf_vfsp->udf_lbsize) {
goto end;
}
/*
* We have enough space
* just add the entry at the end
*/
} else {
goto end;
}
end:
if (!error) {
} else {
}
return (error);
}
/* ARGSUSED */
{
ud_printf("ud_ialloc\n");
return (EOVERFLOW);
return (err);
}
return (EIO);
}
/*
* To determine the group-id of the created file:
* 1) If the gid is set in the attribute list (non-Sun & pre-4.0
* clients are not likely to set the gid), then use it if
* the process is privileged, belongs to the target group,
* or the group is the same as the parent directory.
* 2) If the filesystem was not mounted with the Old-BSD-compatible
* GRPID option, and the directory's set-gid bit is clear,
* then use the process's gid.
* 3) Otherwise, set the group-id to the gid of the parent directory.
*/
secpolicy_vnode_create_gid(cr) == 0)) {
/*
* XXX - is this only the case when a 4.0 NFS client, or a
* client derived from that code, makes a call over the wire?
*/
} else {
}
/*
* Under solaris only the owner can
* change the attributes of files so set
* the change attribute bit only for user
*/
/*
* File delete permissions on Solaris are
* the permissions on the directory but not the file
* when we create a file just inherit the directorys
* write permission to be the file delete permissions
* Atleast we will be consistent in the files we create
*/
/*
* udf does not have a "." entry in dir's
* so even directories have only one link
*/
fe->fe_info_len = 0;
gethrestime(&now);
} else
} else
udf_vfsp->udf_maxuniq++;
ea_len = 0;
}
fe->fe_len_adesc = 0;
icb->itag_prnde = 0;
icb->itag_param = 0;
case VREG :
break;
case VDIR :
break;
case VBLK :
break;
case VCHR :
break;
case VLNK :
break;
case VFIFO :
break;
case VSOCK :
break;
default :
goto error;
}
icb->itag_lb_loc = 0;
icb->itag_lb_prn = 0;
} else {
}
}
flags |= ICB_FLAG_SETUID;
}
flags |= ICB_FLAG_SETGID;
}
flags |= ICB_FLAG_STICKY;
}
} else {
udf_vfsp->udf_nfiles++;
}
#ifdef DEBUG
{
}
}
#endif
return (err);
}
return (0);
return (ENOSPC);
}
void
{
ud_printf("ud_ifree\n");
return;
}
/*
* Error get rid of bp
*/
} else {
/*
* Just trash the inode
*/
}
}
} else {
if (udf_vfsp->udf_nfiles > 0) {
udf_vfsp->udf_nfiles --;
}
}
}
/*
* Free storage space associated with the specified inode. The portion
* to be freed is specified by lp->l_start and lp->l_len (already
* normalized to a "whence" of 0).
*
* This is an experimental facility whose continued existence is not
* guaranteed. Currently, we only support the special case
* of l_len == 0, meaning free to end of file.
*
* Blocks are freed in reverse order. This FILO algorithm will tend to
* maintain a contiguous free list much longer than FIFO.
* See also ufs_itrunc() in ufs_inode.c.
*
* Bug: unused bytes in the last retained block are not cleared.
* This may result in a "hole" in the file that does not read as zeroes.
*/
{
int32_t i;
ud_printf("udf_freesp\n");
return (EINVAL);
}
return (0);
}
/*
* Check if there is any active mandatory lock on the
*/
/*
* "Truncate up" case: need to make sure there
* is no lock beyond current end-of-file. To
* do so, we need to set l_start to the size
* of the file temporarily.
*/
}
return (i ? i : EAGAIN);
}
}
/*
* Make sure a write isn't in progress (allocating blocks)
* by acquiring i_rwlock (we promised ufs_bmap we wouldn't
* truncate while it was allocating blocks).
* Grab the locks in the right order.
*/
return (error);
}
/*
* Cache is implemented by
* allocating a cluster of blocks
*/
{
ud_printf("ud_alloc_from_cache\n");
if (part->udp_cache_count == 0) {
/* allocate new cluster */
return (error);
}
if (sz == 0) {
return (ENOSPC);
}
if (part->udp_cache_count == 0) {
}
} else {
free = 1;
}
}
part->udp_cache_count--;
if (free) {
}
return (0);
}
/*
* Will be called from unmount
*/
{
ud_printf("ud_release_cache\n");
if (part->udp_cache_count) {
part->udp_cache_count = 0;
}
}
return (error);
}