patch-2.1.63 linux/fs/ncpfs/inode.c
Next file: linux/fs/ncpfs/ioctl.c
Previous file: linux/fs/ncpfs/file.c
Back to the patch index
Back to the overall index
- Lines: 553
- Date:
Wed Nov 12 11:10:40 1997
- Orig file:
v2.1.62/linux/fs/ncpfs/inode.c
- Orig date:
Mon Aug 18 18:19:46 1997
diff -u --recursive --new-file v2.1.62/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 1995, 1996 by Volker Lendecke
* Modified for big endian by J.F. Chadima and David S. Miller
+ * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
*
*/
@@ -14,7 +15,6 @@
#include <asm/byteorder.h>
#include <linux/sched.h>
-#include <linux/ncp_fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/string.h>
@@ -28,84 +28,108 @@
#ifdef CONFIG_KERNELD
#include <linux/kerneld.h>
#endif
+
+#include <linux/ncp_fs.h>
#include "ncplib_kernel.h"
extern int close_fp(struct file *filp);
-static void ncp_put_inode(struct inode *);
static void ncp_read_inode(struct inode *);
+static void ncp_put_inode(struct inode *);
+static void ncp_delete_inode(struct inode *);
+static int ncp_notify_change(struct inode *, struct iattr *);
static void ncp_put_super(struct super_block *);
-static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
-static int ncp_notify_change(struct inode *inode, struct iattr *attr);
+static int ncp_statfs(struct super_block *, struct statfs *, int);
static struct super_operations ncp_sops =
{
ncp_read_inode, /* read inode */
- ncp_notify_change, /* notify change */
NULL, /* write inode */
ncp_put_inode, /* put inode */
+ ncp_delete_inode, /* delete inode */
+ ncp_notify_change, /* notify change */
ncp_put_super, /* put superblock */
NULL, /* write superblock */
ncp_statfs, /* stat filesystem */
- NULL
+ NULL /* remount */
};
-/* ncp_read_inode: Called from iget, it only traverses the allocated
- ncp_inode_info's and initializes the inode from the data found
- there. It does not allocate or deallocate anything. */
+static struct nw_file_info *read_nwinfo = NULL;
+static struct semaphore read_sem = MUTEX;
-static void ncp_read_inode(struct inode *inode)
+/*
+ * Fill in the ncpfs-specific information in the inode.
+ */
+void ncp_update_inode(struct inode *inode, struct nw_file_info *nwinfo)
{
- /* Our task should be extremely simple here. We only have to
- look up the information somebody else (ncp_iget) put into
- the inode tree. The address of this information is the
- inode->i_ino. Just to make sure everything went well, we
- check it's there. */
-
- struct ncp_inode_info *inode_info = ncp_find_inode(inode);
-
- if (inode_info == NULL) {
- /* Ok, now we're in trouble. The inode info is not there. What
- should we do now??? */
- printk("ncp_read_inode: inode info not found\n");
- return;
- }
- inode_info->state = NCP_INODE_VALID;
+ NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
+ NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
+ NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber;
+
+ NCP_FINFO(inode)->opened = nwinfo->opened;
+ NCP_FINFO(inode)->access = nwinfo->access;
+ NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle;
+ memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
+ sizeof(nwinfo->file_handle));
+#ifdef NCPFS_DEBUG_VERBOSE
+printk(KERN_DEBUG "ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
+nwinfo->i.entryName, NCP_FINFO(inode)->volNumber, NCP_FINFO(inode)->dirEntNum);
+#endif
+}
- NCP_INOP(inode) = inode_info;
- inode_info->inode = inode;
+/*
+ * Fill in the inode based on the nw_file_info structure.
+ */
+static void ncp_set_attr(struct inode *inode, struct nw_file_info *nwinfo)
+{
+ struct nw_info_struct *nwi = &nwinfo->i;
+ struct ncp_server *server = NCP_SERVER(inode);
- if (NCP_ISTRUCT(inode)->attributes & aDIR) {
- inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
+ if (nwi->attributes & aDIR) {
+ inode->i_mode = server->m.dir_mode;
/* for directories dataStreamSize seems to be some
Object ID ??? */
inode->i_size = 512;
} else {
- inode->i_mode = NCP_SERVER(inode)->m.file_mode;
- inode->i_size = le32_to_cpu(NCP_ISTRUCT(inode)->dataStreamSize);
+ inode->i_mode = server->m.file_mode;
+ inode->i_size = le32_to_cpu(nwi->dataStreamSize);
}
- DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
+ DDPRINTK(KERN_DEBUG "ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
inode->i_nlink = 1;
- inode->i_uid = NCP_SERVER(inode)->m.uid;
- inode->i_gid = NCP_SERVER(inode)->m.gid;
+ inode->i_uid = server->m.uid;
+ inode->i_gid = server->m.gid;
inode->i_blksize = 512;
inode->i_rdev = 0;
+ inode->i_blocks = 0;
if ((inode->i_blksize != 0) && (inode->i_size != 0)) {
inode->i_blocks =
(inode->i_size - 1) / inode->i_blksize + 1;
- } else {
- inode->i_blocks = 0;
}
- inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(NCP_ISTRUCT(inode)->modifyTime),
- le16_to_cpu(NCP_ISTRUCT(inode)->modifyDate));
- inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(NCP_ISTRUCT(inode)->creationTime),
- le16_to_cpu(NCP_ISTRUCT(inode)->creationDate));
+ inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
+ le16_to_cpu(nwi->modifyDate));
+ inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
+ le16_to_cpu(nwi->creationDate));
inode->i_atime = ncp_date_dos2unix(0,
- le16_to_cpu(NCP_ISTRUCT(inode)->lastAccessDate));
+ le16_to_cpu(nwi->lastAccessDate));
+ ncp_update_inode(inode, nwinfo);
+}
+
+/*
+ * This is called from iget() with the read semaphore held.
+ * The global ncpfs_file_info structure has been set up by ncp_iget.
+ */
+static void ncp_read_inode(struct inode *inode)
+{
+ if (read_nwinfo == NULL) {
+ printk(KERN_ERR "ncp_read_inode: invalid call\n");
+ return;
+ }
+
+ ncp_set_attr(inode, read_nwinfo);
if (S_ISREG(inode->i_mode)) {
inode->i_op = &ncp_file_inode_operations;
@@ -116,73 +140,103 @@
}
}
-static void ncp_put_inode(struct inode *inode)
+/*
+ * Set up the ncpfs_inode_info pointer and get a new inode.
+ */
+struct inode *
+ncp_iget(struct super_block *sb, struct ncpfs_inode_info *info)
{
- struct nw_file_info *finfo = NCP_FINFO(inode);
- struct super_block *sb = inode->i_sb;
+ struct inode *inode;
- lock_super(sb);
- if (finfo->opened != 0) {
- if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle) != 0) {
- /* We can't do anything but complain. */
- printk("ncp_put_inode: could not close\n");
- }
+ if (info == NULL) {
+ printk(KERN_ERR "ncp_iget: info is NULL\n");
+ return NULL;
}
- DDPRINTK("ncp_put_inode: put %s\n",
- finfo->i.entryName);
- ncp_free_inode_info(NCP_INOP(inode));
+ down(&read_sem);
+ read_nwinfo = &info->nw_info;
+ inode = iget(sb, info->ino);
+ read_nwinfo = NULL;
+ up(&read_sem);
+ if (!inode)
+ printk(KERN_ERR "ncp_iget: iget failed!\n");
+ return inode;
+}
+
+static void ncp_put_inode(struct inode *inode)
+{
+ if (inode->i_count == 1)
+ inode->i_nlink = 0;
+}
+static void
+ncp_delete_inode(struct inode *inode)
+{
if (S_ISDIR(inode->i_mode)) {
- DDPRINTK("ncp_put_inode: put directory %ld\n",
- inode->i_ino);
+ DDPRINTK(KERN_DEBUG "ncp_delete_inode: put directory %ld\n", inode->i_ino);
ncp_invalid_dir_cache(inode);
}
+
+ if (NCP_FINFO(inode)->opened && ncp_make_closed(inode) != 0) {
+ /* We can't do anything but complain. */
+ printk(KERN_ERR "ncp_delete_inode: could not close\n");
+ }
clear_inode(inode);
- unlock_super(sb);
+}
+
+static void ncp_init_root(struct ncp_server *server,
+ struct ncpfs_inode_info *info)
+{
+ struct ncp_inode_info *root = &(server->root);
+ struct nw_info_struct *i = &(root->finfo.i);
+ unsigned short dummy;
+
+ DPRINTK(KERN_DEBUG "ncp_init_root: i = %x\n", (int) i);
+
+ i->attributes = aDIR;
+ i->dataStreamSize= 1024;
+ i->dirEntNum = 0;
+ i->DosDirNum = 0;
+ i->volNumber = NCP_NUMBER_OF_VOLUMES + 1; /* illegal volnum */
+ ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
+ ncp_date_unix2dos(0, &(i->modifyTime ), &(i->modifyDate));
+ ncp_date_unix2dos(0, &(dummy ), &(i->lastAccessDate));
+ i->creationTime = le16_to_cpu(i->creationTime);
+ i->creationDate = le16_to_cpu(i->creationDate);
+ i->modifyTime = le16_to_cpu(i->modifyTime);
+ i->modifyDate = le16_to_cpu(i->modifyDate);
+ i->lastAccessDate= le16_to_cpu(i->lastAccessDate);
+ i->nameLen = 0;
+ i->entryName[0] = '\0';
+
+ root->finfo.opened= 0;
+ info->ino = 1;
+ info->nw_info = root->finfo;
}
struct super_block *
- ncp_read_super(struct super_block *sb, void *raw_data, int silent)
+ncp_read_super(struct super_block *sb, void *raw_data, int silent)
{
struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
struct ncp_server *server;
struct file *ncp_filp;
+ struct inode *root_inode;
kdev_t dev = sb->s_dev;
int error;
+ struct ncpfs_inode_info finfo;
- if (data == NULL) {
- printk("ncp_read_super: missing data argument\n");
- sb->s_dev = 0;
- return NULL;
- }
- if (data->version != NCP_MOUNT_VERSION) {
- printk("ncp warning: mount version %s than kernel\n",
- (data->version < NCP_MOUNT_VERSION) ?
- "older" : "newer");
- sb->s_dev = 0;
- return NULL;
- }
- if ((data->ncp_fd >= NR_OPEN)
- || ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
- || (!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))) {
- printk("ncp_read_super: invalid ncp socket\n");
- sb->s_dev = 0;
- return NULL;
- }
- /* We must malloc our own super-block info */
- server = (struct ncp_server *) ncp_kmalloc(sizeof(struct ncp_server),
- GFP_KERNEL);
-
- if (server == NULL) {
- printk("ncp_read_super: could not alloc ncp_server\n");
- return NULL;
- }
- ncp_filp->f_count++;
+ MOD_INC_USE_COUNT;
+ if (data == NULL)
+ goto out_no_data;
+ if (data->version != NCP_MOUNT_VERSION)
+ goto out_bad_mount;
+ if ((data->ncp_fd >= NR_OPEN) ||
+ ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL) ||
+ !S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))
+ goto out_bad_file;
lock_super(sb);
-
- NCP_SBP(sb) = server;
+ ncp_filp->f_count++;
sb->s_blocksize = 1024; /* Eh... Is this correct? */
sb->s_blocksize_bits = 10;
@@ -190,6 +244,13 @@
sb->s_dev = dev;
sb->s_op = &ncp_sops;
+ /* We must malloc our own super-block info */
+ server = (struct ncp_server *) ncp_kmalloc(sizeof(struct ncp_server),
+ GFP_KERNEL);
+ if (server == NULL)
+ goto out_no_server;
+ NCP_SBP(sb) = server;
+
server->ncp_filp = ncp_filp;
server->lock = 0;
server->wait = NULL;
@@ -202,7 +263,7 @@
now because of PATH_MAX changes.. */
if (server->m.time_out < 10) {
server->m.time_out = 10;
- printk("You need to recompile your ncpfs utils..\n");
+ printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
}
server->m.file_mode = (server->m.file_mode &
(S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
@@ -211,54 +272,74 @@
server->packet_size = NCP_PACKET_SIZE;
server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
+ if (server->packet == NULL)
+ goto out_no_packet;
- if (server->packet == NULL) {
- printk("ncpfs: could not alloc packet\n");
- error = -ENOMEM;
- unlock_super(sb);
- goto fail;
- }
ncp_lock_server(server);
error = ncp_connect(server);
ncp_unlock_server(server);
- unlock_super(sb);
+ if (error < 0)
+ goto out_no_connect;
+ DPRINTK(KERN_DEBUG "ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
+
+ error = ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
+ &(server->buffer_size));
+ if (error)
+ goto out_no_bufsize;
+ DPRINTK(KERN_DEBUG "ncpfs: bufsize = %d\n", server->buffer_size);
+
+ ncp_init_root(server, &finfo);
+ root_inode = ncp_iget(sb, &finfo);
+ if (!root_inode)
+ goto out_no_root;
+ DPRINTK(KERN_DEBUG "ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
+ sb->s_root = d_alloc_root(root_inode, NULL);
+ if (!sb->s_root)
+ goto out_no_root;
- if (error < 0) {
- sb->s_dev = 0;
- printk("ncp_read_super: Failed connection, bailing out "
- "(error = %d).\n", -error);
- ncp_kfree_s(server->packet, server->packet_size);
- goto fail;
- }
- DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
-
- ncp_init_root(server);
-
- if (!(sb->s_root = d_alloc_root(iget(sb,ncp_info_ino(server,
- &(server->root))),NULL))) {
- sb->s_dev = 0;
- printk("ncp_read_super: get root inode failed\n");
- goto disconnect;
- }
- if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
- &(server->buffer_size)) != 0) {
- sb->s_dev = 0;
- printk("ncp_read_super: could not get bufsize\n");
- goto disconnect;
- }
- DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
-
- MOD_INC_USE_COUNT;
+ unlock_super(sb);
return sb;
- disconnect:
+out_no_root:
+ printk(KERN_ERR "ncp_read_super: get root inode failed\n");
+ iput(root_inode);
+ goto out_disconnect;
+out_no_bufsize:
+ printk(KERN_ERR "ncp_read_super: could not get bufsize\n");
+out_disconnect:
ncp_lock_server(server);
ncp_disconnect(server);
ncp_unlock_server(server);
+ goto out_free_packet;
+out_no_connect:
+ printk(KERN_ERR "ncp_read_super: Failed connection, error=%d\n", error);
+out_free_packet:
ncp_kfree_s(server->packet, server->packet_size);
- fail:
- put_filp(ncp_filp);
+ goto out_free_server;
+out_no_packet:
+ printk(KERN_ERR "ncp_read_super: could not alloc packet\n");
+out_free_server:
ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
+ goto out_unlock;
+out_no_server:
+ printk(KERN_ERR "ncp_read_super: could not alloc ncp_server\n");
+out_unlock:
+ put_filp(ncp_filp);
+ unlock_super(sb);
+ goto out;
+
+out_bad_file:
+ printk(KERN_ERR "ncp_read_super: invalid ncp socket\n");
+ goto out;
+out_bad_mount:
+ printk(KERN_INFO "ncp_read_super: kernel requires mount version %d\n",
+ NCP_MOUNT_VERSION);
+ goto out;
+out_no_data:
+ printk(KERN_ERR "ncp_read_super: missing data argument\n");
+out:
+ sb->s_dev = 0;
+ MOD_DEC_USE_COUNT;
return NULL;
}
@@ -275,20 +356,17 @@
close_fp(server->ncp_filp);
kill_proc(server->m.wdog_pid, SIGTERM, 0);
- ncp_free_all_inodes(server);
-
ncp_kfree_s(server->packet, server->packet_size);
- sb->s_dev = 0;
ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
- NCP_SBP(sb) = NULL;
+ sb->s_dev = 0;
unlock_super(sb);
MOD_DEC_USE_COUNT;
}
-static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{
struct statfs tmp;
@@ -306,7 +384,7 @@
tmp.f_files = -1;
tmp.f_ffree = -1;
tmp.f_namelen = 12;
- copy_to_user(buf, &tmp, bufsiz);
+ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
static int ncp_notify_change(struct inode *inode, struct iattr *attr)
@@ -359,11 +437,9 @@
info.lastAccessDate = le16_to_cpu(info.lastAccessDate);
}
if (info_mask != 0) {
- if ((result =
- ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
- NCP_ISTRUCT(inode),
- info_mask,
- &info)) != 0) {
+ result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
+ inode, info_mask, &info);
+ if (result != 0) {
result = -EACCES;
if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
@@ -379,8 +455,7 @@
if ((attr->ia_valid & ATTR_SIZE) != 0) {
int written;
- DPRINTK("ncpfs: trying to change size of %s to %ld\n",
- NCP_ISTRUCT(inode)->entryName, attr->ia_size);
+ DPRINTK(KERN_DEBUG "ncpfs: trying to change size to %ld\n", attr->ia_size);
if ((result = ncp_make_open(inode, O_RDWR)) < 0) {
return -EACCES;
@@ -390,13 +465,12 @@
/* According to ndir, the changes only take effect after
closing the file */
- ncp_close_file(NCP_SERVER(inode),
- NCP_FINFO(inode)->file_handle);
- NCP_FINFO(inode)->opened = 0;
-
- result = 0;
+ result = ncp_make_closed(inode);
}
- ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
+ /*
+ * We need a dentry here ...
+ */
+ /* ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode); */
return result;
}
@@ -423,7 +497,10 @@
int init_module(void)
{
- DPRINTK("ncpfs: init_module called\n");
+ DPRINTK(KERN_DEBUG "ncpfs: init_module called\n");
+
+ read_sem = MUTEX;
+ read_nwinfo = NULL;
#ifdef DEBUG_NCP_MALLOC
ncp_malloced = 0;
@@ -436,12 +513,12 @@
void cleanup_module(void)
{
- DPRINTK("ncpfs: cleanup_module called\n");
+ DPRINTK(KERN_DEBUG "ncpfs: cleanup_module called\n");
ncp_free_dir_cache();
unregister_filesystem(&ncp_fs_type);
#ifdef DEBUG_NCP_MALLOC
- printk("ncp_malloced: %d\n", ncp_malloced);
- printk("ncp_current_malloced: %d\n", ncp_current_malloced);
+ printk(KERN_DEBUG "ncp_malloced: %d\n", ncp_malloced);
+ printk(KERN_DEBUG "ncp_current_malloced: %d\n", ncp_current_malloced);
#endif
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov