예제 #1
0
/*
 * Allocate and initialise a request structure
 */
static struct smb_request *smb_do_alloc_request(struct smb_sb_info *server,
						int bufsize)
{
	struct smb_request *req;
	unsigned char *buf = NULL;

	req = kmem_cache_alloc(req_cachep, SLAB_KERNEL);
	VERBOSE("allocating request: %p\n", req);
	if (!req)
		goto out;

	if (bufsize > 0) {
		buf = smb_kmalloc(bufsize, GFP_NOFS);
		if (!buf) {
			kmem_cache_free(req_cachep, req);
			return NULL;
		}
	}

	memset(req, 0, sizeof(struct smb_request));
	req->rq_buffer = buf;
	req->rq_bufsize = bufsize;
	req->rq_server = server;
	init_waitqueue_head(&req->rq_wait);
	INIT_LIST_HEAD(&req->rq_queue);
	atomic_set(&req->rq_count, 1);

out:
	return req;
}
예제 #2
0
파일: dir.c 프로젝트: rohsaini/mkunity
static int
smb_create(struct inode *dir, const char *name, int len, int mode,
	   struct inode **result)
{
	int error;
	struct smb_dirent entry;
	struct smb_inode_info *new_inode_info;

	*result = NULL;

	if (!dir || !S_ISDIR(dir->i_mode))
	{
		printk("smb_create: inode is NULL or not a directory\n");
		iput(dir);
		return -ENOENT;
	}
	new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info),
				     GFP_KERNEL);
	if (new_inode_info == NULL)
	{
		iput(dir);
		return -ENOMEM;
	}
	error = smb_proc_create(dir, name, len, 0, CURRENT_TIME);
	if (error < 0)
	{
		smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info));
		iput(dir);
		return error;
	}
	smb_invalid_dir_cache(dir->i_ino);

	if ((error = smb_proc_getattr(dir, name, len, &entry)) < 0)
	{
		smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info));
		iput(dir);
		return error;
	}
	entry.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1);

	new_inode_info->finfo = entry;

	if ((*result = smb_iget(dir, new_inode_info)) == NULL)
	{
		iput(dir);
		return error;
	}
	iput(dir);
	return 0;
}
예제 #3
0
파일: dir.c 프로젝트: rohsaini/mkunity
static int
smb_lookup(struct inode *dir, const char *name, int len,
	   struct inode **result)
{
	struct smb_dirent finfo;
	struct smb_inode_info *result_info;
	int error;
	int found_in_cache;

	struct smb_inode_info *new_inode_info = NULL;

	*result = NULL;

	if (!dir || !S_ISDIR(dir->i_mode))
	{
		printk("smb_lookup: inode is NULL or not a directory.\n");
		iput(dir);
		return -ENOENT;
	}
	DDPRINTK("smb_lookup: %s\n", name);

	/* Fast cheat for . */
	if (len == 0 || (len == 1 && name[0] == '.'))
	{
		*result = dir;
		return 0;
	}
	/* ..and for .. */
	if (len == 2 && name[0] == '.' && name[1] == '.')
	{
		struct smb_inode_info *parent = SMB_INOP(dir)->dir;

		if (parent->state == SMB_INODE_CACHED)
		{
			parent->state = SMB_INODE_LOOKED_UP;
		}
		*result = iget(dir->i_sb, smb_info_ino(parent));
		iput(dir);
		if (*result == 0)
		{
			return -EACCES;
		}
		return 0;
	}
	result_info = smb_find_dir_inode(dir, name, len);

      in_tree:
	if (result_info != NULL)
	{
		if (result_info->state == SMB_INODE_CACHED)
		{
			result_info->state = SMB_INODE_LOOKED_UP;
		}
		*result = iget(dir->i_sb, smb_info_ino(result_info));
		iput(dir);

		if (new_inode_info != NULL)
		{
			smb_kfree_s(new_inode_info,
				    sizeof(struct smb_inode_info));
		}
		if (*result == NULL)
		{
			return -EACCES;
		}
		return 0;
	}
	/* If the file is in the dir cache, we do not have to ask the
	   server. */
	found_in_cache = 0;

	if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino) && (c_size != 0))
	{
		int first = c_last_returned_index;
		int i;

		i = first;
		do
		{
			if (compare_filename(SMB_SERVER(dir), name, len,
					     &(c_entry[i])) == 0)
			{
				finfo = c_entry[i];
				found_in_cache = 1;
				break;
			}
			i = (i + 1) % c_size;
		}
		while (i != first);
	}
	if (found_in_cache == 0)
	{
		DPRINTK("smb_lookup: not found in cache: %s\n", name);
		if (len > SMB_MAXNAMELEN)
		{
			iput(dir);
			return -ENAMETOOLONG;
		}
		error = smb_proc_getattr(dir, name, len, &finfo);
		if (error < 0)
		{
			iput(dir);
			return error;
		}
		finfo.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1);
	}
	new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info),
				     GFP_KERNEL);

	/* Here somebody else might have inserted the inode */

	result_info = smb_find_dir_inode(dir, name, len);
	if (result_info != NULL)
	{
		goto in_tree;
	}

	if (new_inode_info == NULL)
	{
		iput(dir);
		return -ENOMEM;
	}
	new_inode_info->finfo = finfo;

	DPRINTK("attr: %x\n", finfo.attr);

	if ((*result = smb_iget(dir, new_inode_info)) == NULL)
	{
		iput(dir);
		return -EACCES;
	}
	DDPRINTK("smb_lookup: %s => %lu\n", name, (unsigned long) result_info);
	iput(dir);
	return 0;
}
예제 #4
0
/* Hmm, should we do this like the NFS mount command does? Guess so.. */
struct super_block *
smb_read_super(struct super_block *sb, void *raw_data, int silent)
{
	struct smb_mount_data *data = (struct smb_mount_data *) raw_data;
	struct smb_server *server;
        struct smb_sb_info *smb_sb;
	unsigned int fd;
	struct file *filp;
	kdev_t dev = sb->s_dev;
	int error;

	if (!data) {
		printk("smb_read_super: missing data argument\n");
		sb->s_dev = 0;
		return NULL;
	}
	fd = data->fd;
	if (data->version != SMB_MOUNT_VERSION) {
		printk("smb warning: mount version %s than kernel\n",
		       (data->version < SMB_MOUNT_VERSION) ?
                       "older" : "newer");
	}
	if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) {
		printk("smb_read_super: invalid file descriptor\n");
		sb->s_dev = 0;
		return NULL;
	}
	if (!S_ISSOCK(filp->f_inode->i_mode)) {
		printk("smb_read_super: not a socket!\n");
		sb->s_dev = 0;
		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) {
                printk("smb_read_super: could not alloc smb_sb_info\n");
                return NULL;
        }

	filp->f_count += 1; 

	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;

        smb_init_root(server);

        /*
         * Make the connection to the server
         */
        
	error = smb_proc_connect(server);

	unlock_super(sb);

	if (error < 0) {
		sb->s_dev = 0;
		printk("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");
                smb_kfree_s(server->packet, server->max_xmit);
                goto fail;
	}

	if ((error = smb_stat_root(server)) < 0) {
		sb->s_dev = 0;
		printk("smb_read_super: could not get root dir attributes\n");
                smb_kfree_s(server->packet, server->max_xmit);
                goto fail;
	}

	DPRINTK("smb_read_super : %u %u %u %u\n",
                SMB_SBP(sb)->s_attr.total,
                SMB_SBP(sb)->s_attr.blocksize,
                SMB_SBP(sb)->s_attr.allocblocks,
                SMB_SBP(sb)->s_attr.free);

        DPRINTK("smb_read_super: SMB_SBP(sb) = %x\n", (int)SMB_SBP(sb));

	if (!(sb->s_mounted = iget(sb, (int)&(server->root)))) {
		sb->s_dev = 0;
		printk("smb_read_super: get root inode failed\n");
                smb_kfree_s(server->packet, server->max_xmit);
                goto fail;
	}

        MOD_INC_USE_COUNT;
	return sb;

 fail:
	filp->f_count -= 1; 
        smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));
        return NULL;
}
예제 #5
0
static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
{
	struct smb_sb_info *server;
	struct smb_mount_data_kernel *mnt;
	struct smb_mount_data *oldmnt;
	struct inode *root_inode;
	struct smb_fattr root;
	int ver;
	void *mem;

	if (!raw_data)
		goto out_no_data;

	oldmnt = (struct smb_mount_data *) raw_data;
	ver = oldmnt->version;
	if (ver != SMB_MOUNT_OLDVERSION && cpu_to_be32(ver) != SMB_MOUNT_ASCII)
		goto out_wrong_data;

	sb->s_flags |= MS_NODIRATIME;
	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
	sb->s_blocksize_bits = 10;
	sb->s_magic = SMB_SUPER_MAGIC;
	sb->s_op = &smb_sops;
	sb->s_time_gran = 100;

	server = smb_kmalloc(sizeof(struct smb_sb_info), GFP_KERNEL);
	if (!server)
		goto out_no_server;
	sb->s_fs_info = server;
	memset(server, 0, sizeof(struct smb_sb_info));

	server->super_block = sb;
	server->mnt = NULL;
	server->sock_file = NULL;
	init_waitqueue_head(&server->conn_wq);
	init_MUTEX(&server->sem);
	INIT_LIST_HEAD(&server->entry);
	INIT_LIST_HEAD(&server->xmitq);
	INIT_LIST_HEAD(&server->recvq);
	server->conn_error = 0;
	server->conn_pid = 0;
	server->state = CONN_INVALID; /* no connection yet */
	server->generation = 0;

	/* Allocate the global temp buffer and some superblock helper structs */
	/* FIXME: move these to the smb_sb_info struct */
	VERBOSE("alloc chunk = %d\n", sizeof(struct smb_ops) +
		sizeof(struct smb_mount_data_kernel));
	mem = smb_kmalloc(sizeof(struct smb_ops) +
			  sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
	if (!mem)
		goto out_no_mem;

	server->ops = mem;
	smb_install_null_ops(server->ops);
	server->mnt = mem + sizeof(struct smb_ops);

	/* Setup NLS stuff */
	server->remote_nls = NULL;
	server->local_nls = NULL;

	mnt = server->mnt;

	memset(mnt, 0, sizeof(struct smb_mount_data_kernel));
	strlcpy(mnt->codepage.local_name, CONFIG_NLS_DEFAULT,
		SMB_NLS_MAXNAMELEN);
	strlcpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
		SMB_NLS_MAXNAMELEN);

	mnt->ttl = SMB_TTL_DEFAULT;
	if (ver == SMB_MOUNT_OLDVERSION) {
		mnt->version = oldmnt->version;

		SET_UID(mnt->uid, oldmnt->uid);
		SET_GID(mnt->gid, oldmnt->gid);

		mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
		mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;

		mnt->flags = (oldmnt->file_mode >> 9) | SMB_MOUNT_UID |
			SMB_MOUNT_GID | SMB_MOUNT_FMODE | SMB_MOUNT_DMODE;
	} else {