summaryrefslogtreecommitdiffstats
path: root/fs/smbfs/inode.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-09-12 01:29:55 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-09-12 01:29:55 +0000
commit545f435ebcfd94a1e7c20b46efe81b4d6ac4e698 (patch)
treee9ce4bc598d06374bda906f18365984bf22a526a /fs/smbfs/inode.c
parent4291a610eef89d0d5c69d9a10ee6560e1aa36c74 (diff)
Merge with Linux 2.1.55. More bugfixes and goodies from my private
CVS archive.
Diffstat (limited to 'fs/smbfs/inode.c')
-rw-r--r--fs/smbfs/inode.c431
1 files changed, 170 insertions, 261 deletions
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 75d3dbff7..edea04905 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -2,6 +2,7 @@
* inode.c
*
* Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
+ * Copyright (C) 1997 by Volker Lendecke
*
*/
@@ -28,328 +29,237 @@
extern int close_fp(struct file *filp);
static void smb_put_inode(struct inode *);
+static void smb_delete_inode(struct inode *);
static void smb_read_inode(struct inode *);
static void smb_put_super(struct super_block *);
-static void smb_statfs(struct super_block *, struct statfs *, int bufsiz);
+static int smb_statfs(struct super_block *, struct statfs *, int);
static struct super_operations smb_sops =
{
smb_read_inode, /* read inode */
- smb_notify_change, /* notify change */
NULL, /* write inode */
smb_put_inode, /* put inode */
+ smb_delete_inode, /* delete inode */
+ smb_notify_change, /* notify change */
smb_put_super, /* put superblock */
NULL, /* write superblock */
smb_statfs, /* stat filesystem */
- NULL
+ NULL /* remount filesystem */
};
-/* smb_read_inode: Called from iget, it only traverses the allocated
- smb_inode_info's and initializes the inode from the data found
- there. It does not allocate or deallocate anything. */
+/* FIXME: Look at all inodes whether so that we do not get duplicate
+ * inode numbers. */
+
+unsigned long
+smb_invent_inos(unsigned long n)
+{
+ static unsigned long ino = 1;
+
+ if (ino + 2*n < ino)
+ {
+ /* wrap around */
+ ino += n;
+ }
+ ino += n;
+ return ino;
+}
+
+static struct smb_fattr *read_fattr;
+static struct semaphore read_semaphore = MUTEX;
+
+struct inode *
+smb_iget(struct super_block *sb, struct smb_fattr *fattr)
+{
+ struct inode *result;
+
+ pr_debug("smb_iget: %p\n", fattr);
+
+ down(&read_semaphore);
+ read_fattr = fattr;
+ result = iget(sb, fattr->f_ino);
+ up(&read_semaphore);
+ return result;
+}
static void
smb_read_inode(struct inode *inode)
{
- /* Our task should be extremely simple here. We only have to
- look up the information somebody else (smb_iget) put into
- the inode tree. */
- struct smb_server *server = SMB_SERVER(inode);
- struct smb_inode_info *inode_info
- = smb_find_inode(server, inode->i_ino);
-
- if (inode_info == NULL)
+ pr_debug("smb_iget: %p\n", read_fattr);
+
+ if ((atomic_read(&read_semaphore.count) == 1) ||
+ (inode->i_ino != read_fattr->f_ino))
{
- /* Ok, now we're in trouble. The inode info is not
- there. What should we do now??? */
- printk("smb_read_inode: inode info not found\n");
+ printk("smb_read_inode called from invalid point\n");
return;
}
- inode_info->state = SMB_INODE_VALID;
-
- SMB_INOP(inode) = inode_info;
- inode->i_mode = inode_info->finfo.f_mode;
- inode->i_nlink = inode_info->finfo.f_nlink;
- inode->i_uid = inode_info->finfo.f_uid;
- inode->i_gid = inode_info->finfo.f_gid;
- inode->i_rdev = inode_info->finfo.f_rdev;
- inode->i_size = inode_info->finfo.f_size;
- inode->i_mtime = inode_info->finfo.f_mtime;
- inode->i_ctime = inode_info->finfo.f_ctime;
- inode->i_atime = inode_info->finfo.f_atime;
- inode->i_blksize = inode_info->finfo.f_blksize;
- inode->i_blocks = inode_info->finfo.f_blocks;
+ inode->i_mode = read_fattr->f_mode;
+ inode->i_nlink = read_fattr->f_nlink;
+ inode->i_uid = read_fattr->f_uid;
+ inode->i_gid = read_fattr->f_gid;
+ inode->i_rdev = read_fattr->f_rdev;
+ inode->i_size = read_fattr->f_size;
+ inode->i_mtime = read_fattr->f_mtime;
+ inode->i_ctime = read_fattr->f_ctime;
+ inode->i_atime = read_fattr->f_atime;
+ inode->i_blksize = read_fattr->f_blksize;
+ inode->i_blocks = read_fattr->f_blocks;
+
+ memset(&(inode->u.smbfs_i), 0, sizeof(inode->u.smbfs_i));
if (S_ISREG(inode->i_mode))
- {
inode->i_op = &smb_file_inode_operations;
- } else if (S_ISDIR(inode->i_mode))
- {
+ else if (S_ISDIR(inode->i_mode))
inode->i_op = &smb_dir_inode_operations;
- } else
- {
+ else
inode->i_op = NULL;
- }
+}
+
+void
+smb_invalidate_inodes(struct smb_sb_info *server)
+{
+ printk("smb_invalidate_inodes\n");
+}
+
+int
+smb_revalidate_inode(struct inode *i)
+{
+ pr_debug("smb_revalidate_inode\n");
+ return 0;
+}
+
+int
+smb_refresh_inode(struct inode *i)
+{
+ pr_debug("smb_refresh_inode\n");
+ return 0;
}
static void
-smb_put_inode(struct inode *inode)
+smb_put_inode(struct inode *ino)
{
- struct smb_dirent *finfo = SMB_FINFO(inode);
- struct smb_server *server = SMB_SERVER(inode);
- struct smb_inode_info *info = SMB_INOP(inode);
+ pr_debug("smb_put_inode: count = %d\n", ino->i_count);
- if (S_ISDIR(inode->i_mode))
- {
- smb_invalid_dir_cache(inode->i_ino);
- }
- if (finfo->opened != 0)
- {
- if (smb_proc_close(server, finfo->fileid, inode->i_mtime))
- {
- /* We can't do anything but complain. */
- DPRINTK("smb_put_inode: could not close\n");
- }
- }
- smb_free_inode_info(info);
- clear_inode(inode);
+ if (smb_close(ino))
+ printk("smbfs: could not close inode\n");
}
static void
-smb_put_super(struct super_block *sb)
+smb_delete_inode(struct inode *i)
{
- struct smb_server *server = &(SMB_SBP(sb)->s_server);
+ pr_debug("smb_delete_inode\n");
+}
- smb_proc_disconnect(server);
- smb_dont_catch_keepalive(server);
- close_fp(server->sock_file);
+static void
+smb_put_super(struct super_block *sb)
+{
+ struct smb_sb_info *server = &(sb->u.smbfs_sb);
lock_super(sb);
- smb_free_all_inodes(server);
+ if (server->sock_file) {
+ smb_proc_disconnect(server);
+ smb_dont_catch_keepalive(server);
+ close_fp(server->sock_file);
+ }
- smb_vfree(server->packet);
- server->packet = NULL;
+ if (server->conn_pid)
+ kill_proc(server->conn_pid, SIGTERM, 0);
+ if (server->packet)
+ smb_vfree(server->packet);
sb->s_dev = 0;
- smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));
unlock_super(sb);
MOD_DEC_USE_COUNT;
}
-struct smb_mount_data_v4
-{
- int version;
- unsigned int fd;
- uid_t mounted_uid;
- struct sockaddr_in addr;
-
- char server_name[17];
- char client_name[17];
- char service[64];
- char root_path[64];
-
- char username[64];
- char password[64];
-
- unsigned short max_xmit;
-
- uid_t uid;
- gid_t gid;
- mode_t file_mode;
- mode_t dir_mode;
-};
-
-static int
-smb_get_mount_data(struct smb_mount_data *target, void *source)
-{
- struct smb_mount_data_v4 *v4 = (struct smb_mount_data_v4 *) source;
- struct smb_mount_data *cur = (struct smb_mount_data *) source;
-
- if (source == NULL)
- {
- return 1;
- }
- if (cur->version == SMB_MOUNT_VERSION)
- {
- memcpy(target, cur, sizeof(struct smb_mount_data));
- return 0;
- }
- if (v4->version == 4)
- {
- target->version = 5;
- target->fd = v4->fd;
- target->mounted_uid = v4->mounted_uid;
- target->addr = v4->addr;
-
- memcpy(target->server_name, v4->server_name, 17);
- memcpy(target->client_name, v4->client_name, 17);
- memcpy(target->service, v4->service, 64);
- memcpy(target->root_path, v4->root_path, 64);
- memcpy(target->username, v4->username, 64);
- memcpy(target->password, v4->password, 64);
-
- target->max_xmit = v4->max_xmit;
- target->uid = v4->uid;
- target->gid = v4->gid;
- target->file_mode = v4->file_mode;
- target->dir_mode = v4->dir_mode;
-
- memset(target->domain, 0, 64);
- strcpy(target->domain, "?");
- return 0;
- }
- return 1;
-}
-
struct super_block *
smb_read_super(struct super_block *sb, void *raw_data, int silent)
{
- struct smb_mount_data data;
- struct smb_server *server;
- struct smb_sb_info *smb_sb;
- unsigned int fd;
- struct file *filp;
+ struct smb_mount_data *data = (struct smb_mount_data *)raw_data;
+ struct smb_fattr root;
kdev_t dev = sb->s_dev;
- int error;
+ unsigned char *packet;
- if (smb_get_mount_data(&data, raw_data) != 0)
- {
- printk("smb_read_super: wrong data argument\n");
- sb->s_dev = 0;
- return NULL;
- }
- fd = data.fd;
- if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
- {
- printk("smb_read_super: invalid file descriptor\n");
+ MOD_INC_USE_COUNT;
+
+ if (!data) {
+ printk("smb_read_super: missing data argument\n");
sb->s_dev = 0;
+ MOD_DEC_USE_COUNT;
return NULL;
}
- if (!S_ISSOCK(filp->f_inode->i_mode))
+
+ if (data->version != SMB_MOUNT_VERSION)
{
- printk("smb_read_super: not a socket!\n");
+ printk(KERN_ERR "smb_read_super: wrong data argument."
+ " Recompile smbmount.\n");
sb->s_dev = 0;
+ MOD_DEC_USE_COUNT;
return NULL;
}
- /* We must malloc our own super-block info */
- smb_sb = (struct smb_sb_info *) smb_kmalloc(sizeof(struct smb_sb_info),
- GFP_KERNEL);
- if (smb_sb == NULL)
+ packet = smb_vmalloc(SMB_INITIAL_PACKET_SIZE);
+ if (!packet)
{
- printk("smb_read_super: could not alloc smb_sb_info\n");
- return NULL;
- }
- filp->f_count++;
+ pr_debug("smb_read_super: could not alloc packet\n");
+ sb->s_dev = 0;
+ MOD_DEC_USE_COUNT;
+ return NULL;
+ }
lock_super(sb);
- SMB_SBP(sb) = smb_sb;
-
sb->s_blocksize = 1024; /* Eh... Is this correct? */
sb->s_blocksize_bits = 10;
sb->s_magic = SMB_SUPER_MAGIC;
sb->s_dev = dev;
sb->s_op = &smb_sops;
- server = &(SMB_SBP(sb)->s_server);
- server->sock_file = filp;
- server->lock = 0;
- server->wait = NULL;
- server->packet = NULL;
- server->max_xmit = data.max_xmit;
- if (server->max_xmit <= 0)
- {
- server->max_xmit = SMB_DEF_MAX_XMIT;
- }
- server->tid = 0;
- server->pid = current->pid;
- server->mid = current->pid + 20;
-
- server->m = data;
- server->m.file_mode = (server->m.file_mode &
- (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
- server->m.dir_mode = (server->m.dir_mode &
- (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;
+ sb->u.smbfs_sb.sock_file = NULL;
+ sb->u.smbfs_sb.sem = MUTEX;
+ sb->u.smbfs_sb.conn_pid = 0;
+ sb->u.smbfs_sb.packet = packet;
+ sb->u.smbfs_sb.packet_size = SMB_INITIAL_PACKET_SIZE;
+ sb->u.smbfs_sb.generation = 1;
- smb_init_root(server);
+ sb->u.smbfs_sb.m = *data;
+ sb->u.smbfs_sb.m.file_mode = (sb->u.smbfs_sb.m.file_mode &
+ (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
+ sb->u.smbfs_sb.m.dir_mode = (sb->u.smbfs_sb.m.dir_mode &
+ (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;
- error = smb_proc_connect(server);
+ smb_init_root_dirent(&(sb->u.smbfs_sb), &root);
unlock_super(sb);
- if (error < 0)
+ sb->s_root = d_alloc_root(smb_iget(sb, &root), NULL);
+ if (!sb->s_root)
{
sb->s_dev = 0;
- DPRINTK("smb_read_super: Failed connection, bailing out "
- "(error = %d).\n", -error);
- goto fail;
- }
- if (server->protocol >= PROTOCOL_LANMAN2)
- {
- server->case_handling = CASE_DEFAULT;
- } else
- {
- server->case_handling = CASE_LOWER;
- }
-
- if ((error = smb_proc_dskattr(sb, &(SMB_SBP(sb)->s_attr))) < 0)
- {
- sb->s_dev = 0;
- printk("smb_read_super: could not get super block "
- "attributes\n");
- goto fail;
- }
- smb_init_root_dirent(server, &(server->root.finfo));
-
- if (!(sb->s_mounted = iget(sb, smb_info_ino(&(server->root)))))
- {
- sb->s_dev = 0;
- printk("smb_read_super: get root inode failed\n");
- goto fail;
+ printk(KERN_ERR "smb_read_super: get root inode failed\n");
+ smb_vfree(sb->u.smbfs_sb.packet);
+ MOD_DEC_USE_COUNT;
+ return NULL;
}
- MOD_INC_USE_COUNT;
return sb;
-
- fail:
- if (server->packet != NULL)
- {
- smb_vfree(server->packet);
- server->packet = NULL;
- }
- put_filp(filp);
- smb_dont_catch_keepalive(server);
- smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));
- return NULL;
}
-static void
+static int
smb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{
- int error;
- struct smb_dskattr attr;
- struct statfs tmp;
+ struct statfs attr;
- error = smb_proc_dskattr(sb, &attr);
+ memset(&attr, 0, sizeof(attr));
- if (error)
- {
- printk("smb_statfs: dskattr error = %d\n", -error);
- attr.total = attr.allocblocks = attr.blocksize =
- attr.free = 0;
- }
- tmp.f_type = SMB_SUPER_MAGIC;
- tmp.f_bsize = attr.blocksize * attr.allocblocks;
- tmp.f_blocks = attr.total;
- tmp.f_bfree = attr.free;
- tmp.f_bavail = attr.free;
- tmp.f_files = -1;
- tmp.f_ffree = -1;
- tmp.f_namelen = SMB_MAXPATHLEN;
- copy_to_user(buf, &tmp, bufsiz);
+ smb_proc_dskattr(sb, &attr);
+
+ attr.f_type = SMB_SUPER_MAGIC;
+ attr.f_files = -1;
+ attr.f_ffree = -1;
+ attr.f_namelen = SMB_MAXPATHLEN;
+ return copy_to_user(buf, &attr, bufsiz) ? -EFAULT : 0;
}
int
@@ -374,50 +284,48 @@ smb_notify_change(struct inode *inode, struct iattr *attr)
if ((attr->ia_valid & ATTR_SIZE) != 0)
{
-
- if ((error = smb_make_open(inode, O_WRONLY)) < 0)
+ if ((error = smb_open(inode, O_WRONLY)) < 0)
goto fail;
if ((error = smb_proc_trunc(SMB_SERVER(inode),
- SMB_FINFO(inode)->fileid,
+ inode->u.smbfs_i.fileid,
attr->ia_size)) < 0)
goto fail;
-
}
if ((attr->ia_valid & (ATTR_CTIME | ATTR_MTIME | ATTR_ATIME)) != 0)
{
- struct smb_dirent finfo;
+ struct smb_fattr fattr;
- finfo.attr = 0;
- finfo.f_size = inode->i_size;
- finfo.f_blksize = inode->i_blksize;
+ fattr.attr = 0;
+ fattr.f_size = inode->i_size;
+ fattr.f_blksize = inode->i_blksize;
if ((attr->ia_valid & ATTR_CTIME) != 0)
- finfo.f_ctime = attr->ia_ctime;
+ fattr.f_ctime = attr->ia_ctime;
else
- finfo.f_ctime = inode->i_ctime;
+ fattr.f_ctime = inode->i_ctime;
if ((attr->ia_valid & ATTR_MTIME) != 0)
- finfo.f_mtime = attr->ia_mtime;
+ fattr.f_mtime = attr->ia_mtime;
else
- finfo.f_mtime = inode->i_mtime;
+ fattr.f_mtime = inode->i_mtime;
if ((attr->ia_valid & ATTR_ATIME) != 0)
- finfo.f_atime = attr->ia_atime;
+ fattr.f_atime = attr->ia_atime;
else
- finfo.f_atime = inode->i_atime;
+ fattr.f_atime = inode->i_atime;
if ((error = smb_proc_setattr(SMB_SERVER(inode),
- inode, &finfo)) >= 0)
+ inode, &fattr)) >= 0)
{
- inode->i_ctime = finfo.f_ctime;
- inode->i_mtime = finfo.f_mtime;
- inode->i_atime = finfo.f_atime;
+ inode->i_ctime = fattr.f_ctime;
+ inode->i_mtime = fattr.f_mtime;
+ inode->i_atime = fattr.f_atime;
}
}
fail:
- smb_invalid_dir_cache(smb_info_ino(SMB_INOP(inode)->dir));
+/* smb_invalid_dir_cache(smb_info_ino(SMB_INOP(inode)->dir));*/
return error;
}
@@ -447,7 +355,7 @@ EXPORT_NO_SYMBOLS;
int
init_module(void)
{
- DPRINTK("smbfs: init_module called\n");
+ pr_debug("smbfs: init_module called\n");
#ifdef DEBUG_SMB_MALLOC
smb_malloced = 0;
@@ -456,6 +364,7 @@ init_module(void)
#endif
smb_init_dir_cache();
+ read_semaphore = MUTEX;
return init_smb_fs();
}
@@ -463,13 +372,13 @@ init_module(void)
void
cleanup_module(void)
{
- DPRINTK("smbfs: cleanup_module called\n");
+ pr_debug("smbfs: cleanup_module called\n");
smb_free_dir_cache();
unregister_filesystem(&smb_fs_type);
#ifdef DEBUG_SMB_MALLOC
- printk("smb_malloced: %d\n", smb_malloced);
- printk("smb_current_kmalloced: %d\n", smb_current_kmalloced);
- printk("smb_current_vmalloced: %d\n", smb_current_vmalloced);
+ printk(KERN_DEBUG "smb_malloced: %d\n", smb_malloced);
+ printk(KERN_DEBUG "smb_current_kmalloced: %d\n",smb_current_kmalloced);
+ printk(KERN_DEBUG "smb_current_vmalloced: %d\n",smb_current_vmalloced);
#endif
}