コード例 #1
0
ファイル: sound.c プロジェクト: 325116067/semc-qsd8x50
static int __snd_open(struct inode *inode, struct file *file)
{
	unsigned int minor = iminor(inode);
	struct snd_minor *mptr = NULL;
	const struct file_operations *old_fops;
	int err = 0;

	if (minor >= ARRAY_SIZE(snd_minors))
		return -ENODEV;
	mptr = snd_minors[minor];
	if (mptr == NULL) {
#ifdef CONFIG_MODULES
		int dev = SNDRV_MINOR_DEVICE(minor);
		if (dev == SNDRV_MINOR_CONTROL) {
			/* /dev/aloadC? */
			int card = SNDRV_MINOR_CARD(minor);
			if (snd_cards[card] == NULL)
				snd_request_card(card);
		} else if (dev == SNDRV_MINOR_GLOBAL) {
			/* /dev/aloadSEQ */
			snd_request_other(minor);
		}
#ifndef CONFIG_SND_DYNAMIC_MINORS
		/* /dev/snd/{controlC?,seq} */
		mptr = snd_minors[minor];
		if (mptr == NULL)
#endif
#endif
			return -ENODEV;
	}
	old_fops = file->f_op;
	file->f_op = fops_get(mptr->f_ops);
	if (file->f_op == NULL) {
		file->f_op = old_fops;
		return -ENODEV;
	}
	if (file->f_op->open)
		err = file->f_op->open(inode, file);
	if (err) {
		fops_put(file->f_op);
		file->f_op = fops_get(old_fops);
	}
	fops_put(old_fops);
	return err;
}
コード例 #2
0
ファイル: 2.c プロジェクト: iproha94/BmstuOperatingSystems
struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) {
 	struct file *f = // get an empty file structure
 	f->f_flags = flags;

 	// call open() used inode
 	struct inode = dentry->d_inode;
 	
 	f->f_op = fops_get(inode->i_fop);
 	f->f_op = open(inode, f);
 }
コード例 #3
0
static int phone_open(struct inode *inode, struct file *file)
{
    unsigned int minor = MINOR(inode->i_rdev);
    int err = 0;
    struct phone_device *p;
    struct file_operations *old_fops, *new_fops = NULL;

    if (minor >= PHONE_NUM_DEVICES)
        return -ENODEV;

    down(&phone_lock);
    p = phone_device[minor];
    if (p)
        new_fops = fops_get(p->f_op);
    if (!new_fops) {
        char modname[32];

        up(&phone_lock);
        sprintf(modname, "char-major-%d-%d", PHONE_MAJOR, minor);
        request_module(modname);
        down(&phone_lock);
        p = phone_device[minor];
        if (p == NULL || (new_fops = fops_get(p->f_op)) == NULL)
        {
            err=-ENODEV;
            goto end;
        }
    }
    old_fops = file->f_op;
    file->f_op = new_fops;
    if (p->open)
        err = p->open(p, file);	/* Tell the device it is open */
    if (err) {
        fops_put(file->f_op);
        file->f_op = fops_get(old_fops);
    }
    fops_put(old_fops);
end:
    up(&phone_lock);
    return err;
}
コード例 #4
0
static int phone_open(struct inode *inode, struct file *file)
{
	unsigned int minor = iminor(inode);
	int err = 0;
	struct phone_device *p;
	const struct file_operations *old_fops, *new_fops = NULL;

	if (minor >= PHONE_NUM_DEVICES)
		return -ENODEV;

	lock_kernel();
	mutex_lock(&phone_lock);
	p = phone_device[minor];
	if (p)
		new_fops = fops_get(p->f_op);
	if (!new_fops) {
		mutex_unlock(&phone_lock);
		request_module("char-major-%d-%d", PHONE_MAJOR, minor);
		mutex_lock(&phone_lock);
		p = phone_device[minor];
		if (p == NULL || (new_fops = fops_get(p->f_op)) == NULL)
		{
			err=-ENODEV;
			goto end;
		}
	}
	old_fops = file->f_op;
	file->f_op = new_fops;
	if (p->open)
		err = p->open(p, file);	/* Tell the device it is open */
	if (err) {
		fops_put(file->f_op);
		file->f_op = fops_get(old_fops);
	}
	fops_put(old_fops);
end:
	mutex_unlock(&phone_lock);
	unlock_kernel();
	return err;
}
コード例 #5
0
static int snd_open(struct inode *inode, struct file *file)
{
	
	unsigned int minor = iminor(inode);
	struct snd_minor *mptr = NULL;
	const struct file_operations *old_fops;
	int err = 0;

	if (minor >= ARRAY_SIZE(snd_minors))
		return -ENODEV;
	mutex_lock(&sound_mutex);
	mptr = snd_minors[minor];
	if (mptr == NULL) {
		mptr = autoload_device(minor);
		if (!mptr) {
			mutex_unlock(&sound_mutex);
			return -ENODEV;
		}
	}
	old_fops = file->f_op;
	file->f_op = fops_get(mptr->f_ops);
	if (file->f_op == NULL) {
		file->f_op = old_fops;
		err = -ENODEV;
	}
	mutex_unlock(&sound_mutex);
	if (err < 0)
		return err;

	if (file->f_op->open) {
		err = file->f_op->open(inode, file);
		if (err) {
			fops_put(file->f_op);
			file->f_op = fops_get(old_fops);
		}
	}
	fops_put(old_fops);
	return err;
}
コード例 #6
0
ファイル: dvbdev.c プロジェクト: OpenPE/openpctv
static int dvb_device_open(struct inode *inode, struct file *file)
{
	struct dvb_device *dvbdev;

	mutex_lock(&dvbdev_mutex);
	down_read(&minor_rwsem);
	dvbdev = dvb_minors[iminor(inode)];

	if (dvbdev && dvbdev->fops) {
		int err = 0;
		const struct file_operations *old_fops;

		file->private_data = dvbdev;
		old_fops = file->f_op;
		file->f_op = fops_get(dvbdev->fops);
		if (file->f_op == NULL) {
			file->f_op = old_fops;
			goto fail;
		}
		if(file->f_op->open) {
                     mutex_unlock(&dvbdev_mutex);
			err = file->f_op->open(inode,file);
                     mutex_lock(&dvbdev_mutex);
              }
		if (err) {
			fops_put(file->f_op);
			file->f_op = fops_get(old_fops);
		}
		fops_put(old_fops);
		up_read(&minor_rwsem);
		mutex_unlock(&dvbdev_mutex);
		return err;
	}
fail:
	up_read(&minor_rwsem);
	mutex_unlock(&dvbdev_mutex);
	return -ENODEV;
}
コード例 #7
0
ファイル: osi_file.c プロジェクト: maxendpoint/openafs_cvs
void *
osi_UFSOpen(afs_int32 ainode)
{
    register struct osi_file *afile = NULL;
    extern int cacheDiskType;
    afs_int32 code = 0;
    struct inode *tip = NULL;
    struct file *filp = NULL;
    AFS_STATCNT(osi_UFSOpen);
    if (cacheDiskType != AFS_FCACHE_TYPE_UFS) {
	osi_Panic("UFSOpen called for non-UFS cache\n");
    }
    if (!afs_osicred_initialized) {
	/* valid for alpha_osf, SunOS, Ultrix */
	memset((char *)&afs_osi_cred, 0, sizeof(struct AFS_UCRED));
	crhold(&afs_osi_cred);	/* don't let it evaporate, since it is static */
	afs_osicred_initialized = 1;
    }
    afile = (struct osi_file *)osi_AllocLargeSpace(sizeof(struct osi_file));
    AFS_GUNLOCK();
    if (!afile) {
	osi_Panic("osi_UFSOpen: Failed to allocate %d bytes for osi_file.\n",
		  sizeof(struct osi_file));
    }
    memset(afile, 0, sizeof(struct osi_file));
    filp = &afile->file;
    filp->f_dentry = &afile->dentry;
    tip = iget(afs_cacheSBp, (u_long) ainode);
    if (!tip)
	osi_Panic("Can't get inode %d\n", ainode);
    FILE_INODE(filp) = tip;
    tip->i_flags |= MS_NOATIME;	/* Disable updating access times. */
    filp->f_flags = O_RDWR;
#if defined(AFS_LINUX24_ENV)
    filp->f_mode = FMODE_READ|FMODE_WRITE;
    filp->f_op = fops_get(tip->i_fop);
#else
    filp->f_op = tip->i_op->default_file_ops;
#endif
    if (filp->f_op && filp->f_op->open)
	code = filp->f_op->open(tip, filp);
    if (code)
	osi_Panic("Can't open inode %d\n", ainode);
    afile->size = i_size_read(tip);
    AFS_GLOCK();
    afile->offset = 0;
    afile->proc = (int (*)())0;
    afile->inum = ainode;	/* for hint validity checking */
    return (void *)afile;
}
コード例 #8
0
static int soundcore_open(struct inode *inode, struct file *file)
{
    int chain;
    int unit = iminor(inode);
    struct sound_unit *s;
    const struct file_operations *new_fops = NULL;

    lock_kernel ();

    chain=unit&0x0F;
    if(chain==4 || chain==5)	/* dsp/audio/dsp16 */
    {
        unit&=0xF0;
        unit|=3;
        chain=3;
    }

    spin_lock(&sound_loader_lock);
    s = __look_for_unit(chain, unit);
    if (s)
        new_fops = fops_get(s->unit_fops);
    if (!new_fops) {
        spin_unlock(&sound_loader_lock);
        /*
         *  Please, don't change this order or code.
         *  For ALSA slot means soundcard and OSS emulation code
         *  comes as add-on modules which aren't depend on
         *  ALSA toplevel modules for soundcards, thus we need
         *  load them at first.	  [Jaroslav Kysela <*****@*****.**>]
         */
        request_module("sound-slot-%i", unit>>4);
        request_module("sound-service-%i-%i", unit>>4, chain);
        spin_lock(&sound_loader_lock);
        s = __look_for_unit(chain, unit);
        if (s)
            new_fops = fops_get(s->unit_fops);
    }
コード例 #9
0
ファイル: open.c プロジェクト: EmbolismSoil/Linux-2.4.0-
struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
{
	struct file * f;
	struct inode *inode;
	int error;

	error = -ENFILE;
	f = get_empty_filp();
	if (!f)
		goto cleanup_dentry;
	f->f_flags = flags;
	f->f_mode = (flags+1) & O_ACCMODE;
	inode = dentry->d_inode;
	if (f->f_mode & FMODE_WRITE) {
		error = get_write_access(inode);
		if (error)
			goto cleanup_file;
	}

	f->f_dentry = dentry;
	f->f_vfsmnt = mnt;
	f->f_pos = 0;
	f->f_reada = 0;
	f->f_op = fops_get(inode->i_fop);
	if (inode->i_sb)
		file_move(f, &inode->i_sb->s_files);
	if (f->f_op && f->f_op->open) {
		error = f->f_op->open(inode,f);
		if (error)
			goto cleanup_all;
	}
	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	return f;

cleanup_all:
	fops_put(f->f_op);
	if (f->f_mode & FMODE_WRITE)
		put_write_access(inode);
	f->f_dentry = NULL;
	f->f_vfsmnt = NULL;
cleanup_file:
	put_filp(f);
cleanup_dentry:
	dput(dentry);
	mntput(mnt);
	return ERR_PTR(error);
}
コード例 #10
0
ファイル: virtual.c プロジェクト: DanieleDeSensi/mammut
static struct file *vperfctr_get_filp(void)
{
	struct file *filp;
	struct inode *inode;
	struct dentry *dentry;

	inode = vperfctr_get_inode();
	if (!inode)
		goto out;
	dentry = vperfctr_d_alloc_root(inode);
	if (!dentry)
		goto out_inode;
	/*
	 * Create the filp _after_ the inode and dentry, to avoid
	 * needing access to put_filp(), which is no longer exported
	 * starting with kernel 2.6.10-rc1. fput() is available but
	 * doesn't work on incomplete files. We now need access to
	 * dput() instead, but that's Ok.
	 */
	filp = get_empty_filp();
	if (!filp)
		goto out_dentry;

	filp_vfsmnt(filp) = mntget(vperfctr_mnt);
	filp_dentry(filp) = dentry;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,2)
	filp->f_mapping = dentry->d_inode->i_mapping;
#endif

	filp->f_pos = 0;
	filp->f_flags = 0;
	filp->f_op = fops_get(&vperfctr_file_ops); /* fops_get() for MODULE */
	filp->f_mode = FMODE_READ;
	filp->f_version = 0;

	return filp;

 out_dentry:
	dput(dentry);
	goto out; /* dput() also does iput() */
 out_inode:
	iput(inode);
 out:
	return NULL;
}
コード例 #11
0
ファイル: fifo.c プロジェクト: Aniruddha-Paul/openss7
/*
 *  fifo_open: - open a fifo device node
 *  @inode: the external filesystem inode
 *  @file: the external filesystem file pointer
 *
 *  fifo_open() is only used to open a fifo device (named pipe) from a character device node in an
 *  external filesystem.  This is never called for direct opens of a specfs device node (for direct
 *  opens, see spec_dev_open() in strspecfs.c).  The character device inode is opened directly and
 *  no inode in the shadow filesystem is addressed.
 */
STATIC int
fifo_open(struct inode *inode, struct file *file)
{
	int err;
	dev_t dev = makedevice(fifo_cdev.d_modid, 0);

	{
		struct file_operations *f_op;

		err = -ENXIO;
		if (!(f_op = fops_get(fifo_cdev.d_fop))) {
			goto error;
		}
		fops_put(file->f_op);
		file->f_op = f_op;
	}
	file->private_data = &dev;	/* use this device number instead of inode number */
	file->f_flags &= ~O_CLONE;	/* FIFOs never clone */
	err = file->f_op->open(inode, file);
      error:
	return (err);
}
コード例 #12
0
ファイル: open.c プロジェクト: wpwrak/ben-wpan-linux
static int do_dentry_open(struct file *f,
			  int (*open)(struct inode *, struct file *),
			  const struct cred *cred)
{
	static const struct file_operations empty_fops = {};
	struct inode *inode;
	int error;

	f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
				FMODE_PREAD | FMODE_PWRITE;

	if (unlikely(f->f_flags & O_PATH))
		f->f_mode = FMODE_PATH;

	path_get(&f->f_path);
	inode = f->f_inode = f->f_path.dentry->d_inode;
	if (f->f_mode & FMODE_WRITE) {
		error = __get_file_write_access(inode, f->f_path.mnt);
		if (error)
			goto cleanup_file;
		if (!special_file(inode->i_mode))
			file_take_write(f);
	}

	f->f_mapping = inode->i_mapping;
	file_sb_list_add(f, inode->i_sb);

	if (unlikely(f->f_mode & FMODE_PATH)) {
		f->f_op = &empty_fops;
		return 0;
	}

	f->f_op = fops_get(inode->i_fop);

	error = security_file_open(f, cred);
	if (error)
		goto cleanup_all;

	error = break_lease(inode, f->f_flags);
	if (error)
		goto cleanup_all;

	if (!open && f->f_op)
		open = f->f_op->open;
	if (open) {
		error = open(inode, f);
		if (error)
			goto cleanup_all;
	}
	if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
		i_readcount_inc(inode);

	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);

	return 0;

cleanup_all:
	fops_put(f->f_op);
	file_sb_list_del(f);
	if (f->f_mode & FMODE_WRITE) {
		put_write_access(inode);
		if (!special_file(inode->i_mode)) {
			/*
			 * We don't consider this a real
			 * mnt_want/drop_write() pair
			 * because it all happenend right
			 * here, so just reset the state.
			 */
			file_reset_write(f);
			__mnt_drop_write(f->f_path.mnt);
		}
	}
cleanup_file:
	path_put(&f->f_path);
	f->f_path.mnt = NULL;
	f->f_path.dentry = NULL;
	f->f_inode = NULL;
	return error;
}
コード例 #13
0
ファイル: open.c プロジェクト: niubl/camera_project
struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
{
    struct file * f;
    struct inode *inode;
    static LIST_HEAD(kill_list);
    int error;

    error = -ENFILE;
    f = get_empty_filp();
    if (!f)
        goto cleanup_dentry;
    f->f_flags = flags;
    f->f_mode = (flags+1) & O_ACCMODE;
    inode = dentry->d_inode;
    if (f->f_mode & FMODE_WRITE) {
        error = get_write_access(inode);
        if (error)
            goto cleanup_file;
    }

    f->f_dentry = dentry;
    f->f_vfsmnt = mnt;
    f->f_pos = 0;
    f->f_reada = 0;
    f->f_op = fops_get(inode->i_fop);
    file_move(f, &inode->i_sb->s_files);

    /* preallocate kiobuf for O_DIRECT */
    f->f_iobuf = NULL;
    f->f_iobuf_lock = 0;
    if (f->f_flags & O_DIRECT) {
        error = alloc_kiovec(1, &f->f_iobuf);
        if (error)
            goto cleanup_all;
    }

    if (f->f_op && f->f_op->open) {
        error = f->f_op->open(inode,f);
        if (error)
            goto cleanup_all;
    }
    f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

    return f;

cleanup_all:
    if (f->f_iobuf)
        free_kiovec(1, &f->f_iobuf);
    fops_put(f->f_op);
    if (f->f_mode & FMODE_WRITE)
        put_write_access(inode);
    file_move(f, &kill_list); /* out of the way.. */
    f->f_dentry = NULL;
    f->f_vfsmnt = NULL;
cleanup_file:
    put_filp(f);
cleanup_dentry:
    dput(dentry);
    mntput(mnt);
    return ERR_PTR(error);
}
コード例 #14
0
ファイル: open.c プロジェクト: mpalmer/linux-2.6
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
					int flags, struct file *f,
					int (*open)(struct inode *, struct file *))
{
	struct inode *inode;
	int error;

	f->f_flags = flags;
	f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK |
				FMODE_PREAD | FMODE_PWRITE;
	inode = dentry->d_inode;
	if (f->f_mode & FMODE_WRITE) {
		error = __get_file_write_access(inode, mnt);
		if (error)
			goto cleanup_file;
		if (!special_file(inode->i_mode))
			file_take_write(f);
	}

	f->f_mapping = inode->i_mapping;
	f->f_path.dentry = dentry;
	f->f_path.mnt = mnt;
	f->f_pos = 0;
	f->f_op = fops_get(inode->i_fop);
	file_move(f, &inode->i_sb->s_files);

	error = security_dentry_open(f);
	if (error)
		goto cleanup_all;

	if (!open && f->f_op)
		open = f->f_op->open;
	if (open) {
		error = open(inode, f);
		if (error)
			goto cleanup_all;
	}

	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);

	/* NB: we're sure to have correct a_ops only after f_op->open */
	if (f->f_flags & O_DIRECT) {
		if (!f->f_mapping->a_ops ||
		    ((!f->f_mapping->a_ops->direct_IO) &&
		    (!f->f_mapping->a_ops->get_xip_mem))) {
			fput(f);
			f = ERR_PTR(-EINVAL);
		}
	}

	return f;

cleanup_all:
	fops_put(f->f_op);
	if (f->f_mode & FMODE_WRITE) {
		put_write_access(inode);
		if (!special_file(inode->i_mode)) {
			/*
			 * We don't consider this a real
			 * mnt_want/drop_write() pair
			 * because it all happenend right
			 * here, so just reset the state.
			 */
			file_reset_write(f);
			mnt_drop_write(mnt);
		}
	}
	file_kill(f);
	f->f_path.dentry = NULL;
	f->f_path.mnt = NULL;
cleanup_file:
	put_filp(f);
	dput(dentry);
	mntput(mnt);
	return ERR_PTR(error);
}
コード例 #15
0
ファイル: open.c プロジェクト: ruigulala/helgrind_uml
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
					int flags, struct file *f,
					int (*open)(struct inode *, struct file *))
{
	struct inode *inode;
	int error;

	f->f_flags = flags;
	f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK |
				FMODE_PREAD | FMODE_PWRITE;
	inode = dentry->d_inode;
	if (f->f_mode & FMODE_WRITE) {
		error = get_write_access(inode);
		if (error)
			goto cleanup_file;
	}

	f->f_mapping = inode->i_mapping;
	f->f_path.dentry = dentry;
	f->f_path.mnt = mnt;
	f->f_pos = 0;
	f->f_op = fops_get(inode->i_fop);
	file_move(f, &inode->i_sb->s_files);

	if (!open && f->f_op)
		open = f->f_op->open;
	if (open) {
		error = open(inode, f);
		if (error)
			goto cleanup_all;
	}

	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);

	/* NB: we're sure to have correct a_ops only after f_op->open */
	if (f->f_flags & O_DIRECT) {
		if (!f->f_mapping->a_ops ||
		    ((!f->f_mapping->a_ops->direct_IO) &&
		    (!f->f_mapping->a_ops->get_xip_page))) {
			fput(f);
			f = ERR_PTR(-EINVAL);
		}
	}

	return f;

cleanup_all:
	fops_put(f->f_op);
	if (f->f_mode & FMODE_WRITE)
		put_write_access(inode);
	file_kill(f);
	f->f_path.dentry = NULL;
	f->f_path.mnt = NULL;
cleanup_file:
	put_filp(f);
	dput(dentry);
	mntput(mnt);
	return ERR_PTR(error);
}
コード例 #16
0
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, struct file *f)
{
	struct inode *inode;
	static LIST_HEAD(kill_list);
	int error;

	f->f_flags = flags;
	f->f_mode = (flags+1) & O_ACCMODE;
	inode = dentry->d_inode;
	if (f->f_mode & FMODE_WRITE) {
		error = get_write_access(inode);
		if (error)
			goto cleanup_file;
	}

	f->f_dentry = dentry;
	f->f_vfsmnt = mnt;
	f->f_pos = 0;
	f->f_reada = 0;
	f->f_op = fops_get(inode->i_fop);
	file_move(f, &inode->i_sb->s_files);

	/* preallocate kiobuf for O_DIRECT */
	f->f_iobuf = NULL;
	f->f_iobuf_lock = 0;
	if (f->f_flags & O_DIRECT) {
		error = alloc_kiovec(1, &f->f_iobuf);
		if (error)
			goto cleanup_all;
	}

	if (f->f_op && f->f_op->open) {
		error = f->f_op->open(inode,f);
		if (error)
			goto cleanup_all;
	}
	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	/* NB: we're sure to have correct a_ops only after f_op->open */
	if (f->f_flags & O_DIRECT) {
		if (!inode->i_mapping || !inode->i_mapping->a_ops ||
		    !(inode->i_mapping->a_ops->direct_IO ||
		      inode->i_mapping->a_ops->direct_sector_IO)) {
			fput(f);
			f = ERR_PTR(-EINVAL);
		}
	}

	return f;

cleanup_all:
	if (f->f_iobuf)
		free_kiovec(1, &f->f_iobuf);
	fops_put(f->f_op);
	if (f->f_mode & FMODE_WRITE)
		put_write_access(inode);
	file_move(f, &kill_list); /* out of the way.. */
	f->f_dentry = NULL;
	f->f_vfsmnt = NULL;
cleanup_file:
	put_filp(f);
	dput(dentry);
	mntput(mnt);
	return ERR_PTR(error);
}
コード例 #17
0
static struct file *__dentry_open(struct _dentry *dentry, struct vfsmount *mnt,
					int flags, struct file *f,
					int (*open)(struct _inode *, struct file *))
{
	struct _inode *inode;
	int error;
	struct super_block *sb;
	struct _file *_f = tx_cache_get_file(f);

	_f->f_flags = flags;
	_f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK |
		 		FMODE_PREAD | FMODE_PWRITE;
	inode = d_get_inode(dentry);
	sb = inode->i_sb;

	if (_f->f_mode & FMODE_WRITE) {
		error = get_write_access(parent(inode));
		if (error)
			goto cleanup_file;
	}

	f->f_mapping = inode->i_mapping;
	_f->f_path.dentry = parent(dentry);
	_f->f_path.mnt = mnt;
	_f->f_pos = 0;
	f->f_op = fops_get(inode->i_fop);
	file_move(f, &sb->s_files);

	if (!open && f->f_op)
		open = f->f_op->open;
	if (open) {
		error = open(inode, f);
		if (error)
			goto cleanup_all;
	}

	_f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	file_ra_state_init(&f->f_ra, 
			   tx_cache_get_inode(f->f_mapping->host)->i_mapping);

	/* NB: we're sure to have correct a_ops only after f_op->open */
	if (_f->f_flags & O_DIRECT) {
		if (!f->f_mapping->a_ops ||
		    ((!f->f_mapping->a_ops->direct_IO) &&
		    (!f->f_mapping->a_ops->get_xip_page))) {
			fput(f);
			f = ERR_PTR(-EINVAL);
		}
	}

	return f;

cleanup_all:
	fops_put(f->f_op);
	if (_f->f_mode & FMODE_WRITE)
		put_write_access(parent(inode));
	file_kill(f);
	_f->f_path.dentry = NULL;
	_f->f_path.mnt = NULL;
cleanup_file:
	/* Avoid issues if we recycle this object */
	if(live_transaction())
		early_release(&f->xobj, 1);
	put_filp(f);
	dput(parent(dentry));
	mntput(mnt);
	return ERR_PTR(error);
}
コード例 #18
0
ファイル: open.c プロジェクト: GAXUSXX/G935FGaXusKernel2
static int do_dentry_open(struct file *f,
			  int (*open)(struct inode *, struct file *),
			  const struct cred *cred)
{
	static const struct file_operations empty_fops = {};
	struct inode *inode;
	int error;

	f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
				FMODE_PREAD | FMODE_PWRITE;

	path_get(&f->f_path);
	inode = f->f_inode = f->f_path.dentry->d_inode;
	f->f_mapping = inode->i_mapping;

	if (unlikely(f->f_flags & O_PATH)) {
		f->f_mode = FMODE_PATH;
		f->f_op = &empty_fops;
		return 0;
	}

	if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) {
		error = get_write_access(inode);
		if (unlikely(error))
			goto cleanup_file;
		error = __mnt_want_write(f->f_path.mnt);
		if (unlikely(error)) {
			put_write_access(inode);
			goto cleanup_file;
		}
		f->f_mode |= FMODE_WRITER;
	}

	/* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */
	if (S_ISREG(inode->i_mode))
		f->f_mode |= FMODE_ATOMIC_POS;

	f->f_op = fops_get(inode->i_fop);
	if (unlikely(WARN_ON(!f->f_op))) {
		error = -ENODEV;
		goto cleanup_all;
	}

	error = security_file_open(f, cred);
	if (error)
		goto cleanup_all;

	error = break_lease(inode, f->f_flags);
	if (error)
		goto cleanup_all;

	if (!open)
		open = f->f_op->open;
	if (open) {
		error = open(inode, f);
		if (error)
			goto cleanup_all;
	}
	if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
		i_readcount_inc(inode);
	if ((f->f_mode & FMODE_READ) &&
	     likely(f->f_op->read || f->f_op->aio_read || f->f_op->read_iter))
		f->f_mode |= FMODE_CAN_READ;
	if ((f->f_mode & FMODE_WRITE) &&
	     likely(f->f_op->write || f->f_op->aio_write || f->f_op->write_iter))
		f->f_mode |= FMODE_CAN_WRITE;

	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);

	return 0;

cleanup_all:
	fops_put(f->f_op);
	if (f->f_mode & FMODE_WRITER) {
		put_write_access(inode);
		__mnt_drop_write(f->f_path.mnt);
	}
cleanup_file:
	path_put(&f->f_path);
	f->f_path.mnt = NULL;
	f->f_path.dentry = NULL;
	f->f_inode = NULL;
	return error;
}
コード例 #19
0
ファイル: open.c プロジェクト: boa19861105/Blackout-Monarudo
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
					struct file *f,
					int (*open)(struct inode *, struct file *),
					const struct cred *cred)
{
	static const struct file_operations empty_fops = {};
	struct inode *inode;
	int error;

	f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
				FMODE_PREAD | FMODE_PWRITE;

	if (unlikely(f->f_flags & O_PATH))
		f->f_mode = FMODE_PATH;

	inode = dentry->d_inode;
	if (f->f_mode & FMODE_WRITE) {
		error = __get_file_write_access(inode, mnt);
		if (error)
			goto cleanup_file;
		if (!special_file(inode->i_mode))
			file_take_write(f);
	}

	f->f_mapping = inode->i_mapping;
	f->f_path.dentry = dentry;
	f->f_path.mnt = mnt;
	f->f_pos = 0;
	file_sb_list_add(f, inode->i_sb);

	if (unlikely(f->f_mode & FMODE_PATH)) {
		f->f_op = &empty_fops;
		return f;
	}

	f->f_op = fops_get(inode->i_fop);

	error = security_dentry_open(f, cred);
	if (error)
		goto cleanup_all;

	error = break_lease(inode, f->f_flags);
	if (error)
		goto cleanup_all;

	if (!open && f->f_op)
		open = f->f_op->open;
	if (open) {
		error = open(inode, f);
		if (error)
			goto cleanup_all;
	}
	if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
		i_readcount_inc(inode);

	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);

	/* NB: we're sure to have correct a_ops only after f_op->open */
	if (f->f_flags & O_DIRECT) {
		if (!f->f_mapping->a_ops ||
		    ((!f->f_mapping->a_ops->direct_IO) &&
		    (!f->f_mapping->a_ops->get_xip_mem))) {
			fput(f);
			f = ERR_PTR(-EINVAL);
		}
	}

	return f;

cleanup_all:
	fops_put(f->f_op);
	if (f->f_mode & FMODE_WRITE) {
		put_write_access(inode);
		if (!special_file(inode->i_mode)) {
			/*
			 * We don't consider this a real
			 * mnt_want/drop_write() pair
			 * because it all happenend right
			 * here, so just reset the state.
			 */
			file_reset_write(f);
			mnt_drop_write(mnt);
		}
	}
	file_sb_list_del(f);
	f->f_path.dentry = NULL;
	f->f_path.mnt = NULL;
cleanup_file:
	put_filp(f);
	dput(dentry);
	mntput(mnt);
	return ERR_PTR(error);
}
コード例 #20
0
ファイル: mvfs_linux_shadow.c プロジェクト: dagwieers/mvfs71
extern int
vnode_shadow_fop_open(
    INODE_T *inode,
    FILE_T *file
)
{
    int err = 0;
    INODE_T *real_inode;
    DENT_T *rdentry = NULL;
    DENT_T *oldent;
    struct file_operations *oldfops;
    struct vfsmount *oldmnt, *newmnt;
    VNODE_T *cvp;

    oldmnt = file->f_vfsmnt;

    oldent = file->f_dentry;
    ASSERT(D_COUNT(oldent));
    /* The Linux kernel has stopped ignoring the O_DIRECT flag.
     * The problem is that they wait until after they call the fop open
     * function to check the inode to see if it will support direct I/O.
     * But they get the inode pointer before they call us and check the
     * inode after we return so they never check the actual inode we open
     * but only the shadow one.  Their error handling never comes back to
     * us and they release their old pointers and not our new ones.  The
     * only choice we have is to not allow O_DIRECT on shadow files.
     */
    if (file->f_flags & O_DIRECT) {
        err = -EINVAL;
        goto out_nolock;
    }
    /* Get the real dentry */
    rdentry = REALDENTRY_LOCKED(oldent, &cvp);
    if (rdentry == NULL) {
        err = -ENOENT;
	goto out_nolock;
    }
    VNODE_DGET(rdentry);                 /* protect rdentry->d_inode */
    if (rdentry->d_inode == NULL) {
        /* delete race */
        err = -ENOENT;
        goto out;
    }
    newmnt = MDKI_MNTGET(REALVFSMNT(oldent));
    if (newmnt == NULL) {
        err = -EOPNOTSUPP;             /* XXX */
        goto out;
    }

    /* Check that we can write to this file.  Clean up the count on the
     * shadow inode.
     */
    if (file->f_mode & FMODE_WRITE) {
        err = get_write_access(rdentry->d_inode);
        if (err) {
            MDKI_MNTPUT(newmnt);
            goto out;
        }
    }
    real_inode = rdentry->d_inode;

    /* 
     * Swap the file structure contents to point at the underlying object.
     */
    /* In Linux 2.6 they added the mapping stuff to the file so we have to set
    ** that up here, too.
    */
    file->f_mapping = real_inode->i_mapping;
    VNLAYER_RA_STATE_INIT(&(file->f_ra), file->f_mapping);
    file->f_dentry = VNODE_DGET(rdentry);
    oldfops = file->f_op;
    file->f_vfsmnt = newmnt;
    file->f_op = fops_get(real_inode->i_fop);
    if (real_inode->i_fop && !file->f_op)
        /* If we failed to get the reference to a non-NULL op, bail out */
        err = -EIO;                     /* XXX? better error code */
    if (!err) {
	/* Move the file to the file list for the real superblock 
	 * and remove it from the shadow list
	 */
        /* It would be better to use file_move() but it's not exported */
	file_list_lock();
        list_del(&file->f_list);
        list_add(&file->f_list, &real_inode->i_sb->s_files);
	file_list_unlock();
	if (file->f_op && file->f_op->open) {
            err = (*file->f_op->open)(real_inode, file);
            if (err) {
	        /* restore our file to the list on our super block */
	        file_list_lock();
	        list_del(&file->f_list);
	        list_add(&file->f_list, &oldent->d_inode->i_sb->s_files);
	        file_list_unlock();
	    }
	}
    }
    if (err) {
        /* MUST put back old dentry/fops to get accounting right in upper
         * layer. */
        put_write_access(rdentry->d_inode);
        if (file->f_dentry)
            VNODE_DPUT(file->f_dentry);
        if (file->f_op)
            fops_put(file->f_op);
        MDKI_MNTPUT(file->f_vfsmnt);
        file->f_vfsmnt = oldmnt;
        file->f_dentry = oldent;
        file->f_op = oldfops;
    } else {
        put_write_access(oldent->d_inode);
        VNODE_DPUT(oldent);
        /* Drop reference now that we've dropped our use of the file ops */
        fops_put(oldfops);
        MDKI_MNTPUT(oldmnt);
    }
  out:
    VNODE_DPUT(rdentry);
    REALDENTRY_UNLOCK(oldent, cvp);
  out_nolock:
    MDKI_TRACE(TRACE_OPEN, "%s: opened vp=%p fp=%p rdent=%p rdcnt=%d fcnt=%d"
              ", err %d\n", __func__,
              inode, file, rdentry, rdentry ? D_COUNT(rdentry) : 0, F_COUNT(file), -err);
    return(err);
}