int
ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
{
- char *path, *pathpage, *datapage, *argv[4];
+ char *path, *pathpage, *datapage = NULL, *argv[4];
struct file *mntinfo_fd = NULL;
int cleanup_phase = 0, rc = 0;
struct ll_sb_info *sbi;
- struct dentry *dchild;
+ struct dentry *dchild = NULL;
ENTRY;
LASSERT(dentry->d_inode != NULL);
path = d_path(dentry, mnt, pathpage, PAGE_SIZE);
if (IS_ERR(path)) {
CERROR("can't build mount object path, err %d\n",
- (int)PTR_ERR(dchild));
- GOTO(cleanup, rc = PTR_ERR(dchild));
+ (int)PTR_ERR(path));
+ GOTO(cleanup, rc = PTR_ERR(path));
}
/* synchronizing with possible /proc/fs/...write */
strlen(sbi->ll_gns_oname));
up(&sbi->ll_gns_sem);
- cleanup_phase = 2;
-
if (IS_ERR(dchild)) {
rc = PTR_ERR(dchild);
CERROR("can't find mount object %*s/%*s err = %d.\n",
}
/* mount object is not found */
- if (!dchild->d_inode)
+ if (!dchild->d_inode) {
+ dput(dchild);
GOTO(cleanup, rc = -ENOENT);
+ }
/* check if found child is regular file */
- if (!S_ISREG(dchild->d_inode->i_mode))
+ if (!S_ISREG(dchild->d_inode->i_mode)) {
+ dput(dchild);
GOTO(cleanup, rc = -EBADF);
-
- mntget(mnt);
+ }
/* ok, mount object if found, opening it. */
- mntinfo_fd = dentry_open(dchild, mnt, 0);
+ mntinfo_fd = dentry_open(dchild, mntget(mnt), 0);
if (IS_ERR(mntinfo_fd)) {
CERROR("can't open mount object %*s/%*s err = %d.\n",
(int)dentry->d_name.len, dentry->d_name.name,
strlen(sbi->ll_gns_oname), sbi->ll_gns_oname,
(int)PTR_ERR(mntinfo_fd));
mntput(mnt);
+ dput(dchild);
GOTO(cleanup, rc = PTR_ERR(mntinfo_fd));
}
- cleanup_phase = 3;
+ cleanup_phase = 2;
+
+ /* make sure that inode size is up-to-date */
+ rc = ll_inode_revalidate_it(mntinfo_fd->f_dentry);
+ if (rc < 0) {
+ CERROR("can't revalidate mount object %*s/%*s, err %d\n",
+ (int)dentry->d_name.len, dentry->d_name.name,
+ strlen(sbi->ll_gns_oname), sbi->ll_gns_oname,
+ rc);
+ GOTO(cleanup, rc);
+ }
if (mntinfo_fd->f_dentry->d_inode->i_size > PAGE_SIZE - 1) {
CERROR("mount object %*s/%*s is too big (%Ld)\n",
if (!datapage)
GOTO(cleanup, rc = -ENOMEM);
- cleanup_phase = 4;
+ cleanup_phase = 3;
/* read data from mount object. */
rc = kernel_read(mntinfo_fd, 0, datapage, PAGE_SIZE - 1);
EXIT;
cleanup:
switch (cleanup_phase) {
- case 4:
- free_page((unsigned long)datapage);
case 3:
- if (mntinfo_fd != NULL)
- fput(mntinfo_fd);
+ free_page((unsigned long)datapage);
case 2:
- if (dchild != NULL)
- dput(dchild);
+ if (mntinfo_fd != NULL) {
+ fput(mntinfo_fd);
+ dchild = NULL;
+ }
case 1:
free_page((unsigned long)pathpage);
case 0:
}
/* GNS control thread function. */
-static int ll_gns_thread_main(void *arg)
+static int ll_gns_thread(void *arg)
{
struct ll_gns_ctl *ctl = arg;
unsigned long flags;
* starts GNS control thread and waits for a signal it is up and work may be
* continued.
*/
-int ll_gns_start_thread(void)
+int ll_gns_thread_start(void)
{
int rc;
ENTRY;
init_completion(&gns_ctl.gc_finishing);
init_waitqueue_head(&gns_thread.t_ctl_waitq);
- rc = kernel_thread(ll_gns_thread_main, &gns_ctl,
+ rc = kernel_thread(ll_gns_thread, &gns_ctl,
(CLONE_VM | CLONE_FILES));
if (rc < 0) {
CERROR("cannot start GNS control thread, "
}
/* stops GNS control thread and waits its actual stop. */
-void ll_gns_stop_thread(void)
+void ll_gns_thread_stop(void)
{
ENTRY;
gns_thread.t_flags = SVC_STOPPING;