pc_node.c revision a0f9c00cd82d49a710cee8aeb83ce42b5fb293a9
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/sysmacros.h>
extern krwlock_t pcnodes_lock;
/*
* fake entry for root directory, since this does not have a parent
* pointing to it.
*/
struct pcdir pcfs_rootdirentry = {
"",
"",
};
void
pc_init(void)
{
int i;
for (i = 0; i < NPCHASH; i++) {
}
}
struct pcnode *
int offset, /* offset of dir entry in block */
{
ep = &pcfs_rootdirentry;
scluster = 0;
} else {
}
/*
* First look for active nodes.
* File nodes are identified by the location (blkno, offset) of
* its directory entry.
* Directory nodes are identified by the starting cluster number
* for the entries.
*/
return (pcp);
}
}
} else {
return (pcp);
}
}
}
/*
* Cannot find node in active list. Allocate memory for a new node
* initialize it, and put it on the active list.
*/
if (scluster == 0) {
pc_cluster32_t ncl = 0;
"corruption, scluster=%d\n",
scluster);
}
} else {
}
} else {
pc_cluster32_t ncl = 0;
"scluster=%d\n", scluster);
}
}
} else {
fsp->pcfs_frefs++;
}
fsp->pcfs_nrefs++;
return (pcp);
}
int
{
int err;
err = 0;
else
return (err);
}
void
{
int err;
/*
* If the file was removed while active it may be safely
* truncated now.
*/
(void) pc_truncate(pcp, 0);
(void) pc_nodeupdate(pcp);
}
if (err) {
}
}
if (vn_has_cached_data(vp)) {
/*
* pvn_vplist_dirty will abort all old pages
*/
}
(void) pc_syncfat(fsp);
if (vn_has_cached_data(vp)) {
goto retry;
}
return;
}
/*
* XXX - old code had a check for !(pcp->pc_flags & PC_INVAL)
* here. Seems superfluous/incorrect, but then earlier on PC_INVAL
* was never set anywhere in PCFS. Now it is, and we _have_ to drop
*/
fsp->pcfs_frefs--;
}
fsp->pcfs_nrefs--;
if (fsp->pcfs_nrefs < 0) {
panic("pc_rele: nrefs count");
}
if (fsp->pcfs_frefs < 0) {
panic("pc_rele: frefs count");
}
vn_invalid(vp);
}
/*
* Mark a pcnode as modified with the current time.
*/
/* ARGSUSED */
void
{
return;
gethrestime(&now);
"conversion, curtime = %lld\n",
}
/*
* Mark a pcnode as accessed with the current time.
*/
void
{
return;
gethrestime(&now);
"conversion, curtime = %lld\n",
return;
}
/*
* We don't really want to write the adate for every access
* on flash media; make sure it really changed !
*/
}
}
/*
* Truncate a file to a length.
* Node must be locked.
*/
int
{
int error = 0;
return (EIO);
/*
* directories are always truncated to zero and are not marked
*/
return (error);
}
/*
* If length is the same as the current size
* just mark the pcnode and return.
*/
/*
* We are extending a file.
* Extend it with _one_ call to pc_balloc (no holes)
* since we don't need to use the block number(s).
*/
}
if (error) {
pc_cluster32_t ncl = 0;
/*
* probably ran out disk space;
* determine current file size
*/
}
} else
/*
* We are shrinking a file.
* Free blocks after the block that length points to.
*/
/*
* Truncation to a block (cluster size) boundary only
* requires us to invalidate everything after the new
* end of the file.
*/
} else {
/*
* pvn_vpzero() cannot deal with more than MAXBSIZE
* chunks. Since the FAT clustersize can get larger
* than that, we'll zero from the new length to the
* end of the cluster for clustersizes smaller than
* MAXBSIZE - or the end of the MAXBSIZE block in
* case we've got a large clustersize.
*/
}
}
/*
* This is the only place in PCFS code where pc_mark_mod() is called
* without setting PC_MOD. May be a historical artifact ...
*/
return (error);
}
/*
* Get block for entry.
*/
static int
{
} else {
fsp->pcfs_secsize);
}
return (EIO);
}
return (0);
}
/*
* Sync all data associated with a file.
* Flush all the blocks in the buffer cache out to disk, sync the FAT and
* update the directory entry.
*/
int
{
int err;
err = 0;
/*
* Flush all data blocks from buffer cache and
* update the FAT which points to the data.
*/
return (err);
else {
return (EIO);
}
}
}
/*
* update the directory entry
*/
(void) pc_nodeupdate(pcp);
return (err);
}
/*
* Update the node's directory entry.
*/
int
{
int error;
/* no node to update */
return (0);
}
panic("pc_nodeupdate");
}
return (0);
return (error);
}
}
if (error) {
}
return (error);
}
/*
* Verify that the disk in the drive is the same one that we
* got the pcnode from.
* MUST be called with node unlocked.
*/
int
{
int fdstatus = 0;
int error = 0;
return (EIO);
/*
* This "has it been removed" check should better be
* modified for removeable media that are not floppies.
* this ioctl.
*/
if (error) {
/*
* See comment above. This is a workaround
* for removeable media that don't understand
* floppy ioctls.
*/
error = 0;
} else {
PC_DPRINTF1(1,
"pc_verify: FDGETCHANGE ioctl failed: %d\n",
error);
}
} else if (fsp->pcfs_fatjustread) {
/*
* Ignore the results of the ioctl if we just
* read the FAT. There is a good chance that
* the disk changed bit will be on, because
* we've just mounted and we don't want to
* give a false positive that the sky is falling.
*/
fsp->pcfs_fatjustread = 0;
} else {
/*
* Oddly enough we can't check just one flag here. The
* x86 floppy driver sets a different flag
* (FDGC_DETECTED) than the sparc driver does.
* I think this MAY be a bug, and I filed 4165938
* to get someone to look at the behavior
* a bit more closely. In the meantime, my testing and
* code examination seem to indicate it is safe to
* check for either bit being set.
*/
}
}
}
}
return (error);
}
/*
* The disk has changed, pulling the rug out from beneath us.
* Mark the FS as being in an irrecoverable state.
* In a short while we'll clean up.
*/
void
{
/*
* Locking failed, which currently would
* only happen if the FS were already
* marked as hosed. If another reason for
* failure were to arise in the future, this
* routine would have to change.
*/
return;
}
"Disk was changed during an update or\n"
"an irrecoverable error was encountered.\n"
"File damage is possible. To prevent further\n"
"damage, this pcfs instance will now be frozen.\n"
"Use umount(1M) to release the instance.\n");
(void) pc_unlockfs(fsp);
}
}
/*
* The disk has been changed!
*/
void
{
/*
* Eliminate all pcnodes (dir & file) associated with this fs.
* If the node is internal, ie, no references outside of
* pcfs itself, then release the associated vnode structure.
* Invalidate the in core FAT.
* Invalidate cached data blocks and blocks waiting for I/O.
*/
continue;
}
(void) pvn_vplist_dirty(vp,
(u_offset_t)0, pcfs_putapage,
}
fsp->pcfs_nrefs --;
}
}
}
continue;
}
(void) pvn_vplist_dirty(vp,
(u_offset_t)0, pcfs_putapage,
}
fsp->pcfs_frefs--;
fsp->pcfs_nrefs--;
}
}
}
#ifdef undef
if (fsp->pcfs_frefs) {
panic("pc_diskchanged: frefs");
}
if (fsp->pcfs_nrefs) {
panic("pc_diskchanged: nrefs");
}
#endif
} else {
}
}