Ejemplo n.º 1
0
/*
 * This is the callback from RPC telling us whether a reply was
 * received or some error occurred (timeout or socket shutdown).
 */
static void
nfs_readpage_result(struct rpc_task *task)
{
	struct nfs_rreq	*req = (struct nfs_rreq *) task->tk_calldata;
	struct page	*page = req->ra_page;
	unsigned long	address = page_address(page);
	int		result = task->tk_status;
	static int	succ = 0, fail = 0;

	dprintk("NFS: %4d received callback for page %lx, result %d\n",
			task->tk_pid, address, result);

	if (result >= 0) {
		result = req->ra_res.count;
		if (result < PAGE_SIZE) {
			memset((char *) address + result, 0, PAGE_SIZE - result);
		}
		nfs_refresh_inode(req->ra_inode, &req->ra_fattr);
		set_bit(PG_uptodate, &page->flags);
		succ++;
	} else {
		set_bit(PG_error, &page->flags);
		fail++;
		dprintk("NFS: %d successful reads, %d failures\n", succ, fail);
	}
	/* N.B. Use nfs_unlock_page here? */
	clear_bit(PG_locked, &page->flags);
	wake_up(&page->wait);

	free_page(address);

	rpc_release_task(task);
	kfree(req);
}
Ejemplo n.º 2
0
struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
			struct nfs_fattr *fattr)
{
	struct nfs_fattr newfattr;
	int error;
	struct inode *inode;

	if (!sb) {
		printk("nfs_fhget: super block is NULL\n");
		return NULL;
	}
	if (!fattr) {
		error = nfs_proc_getattr(&sb->u.nfs_sb.s_server, fhandle,
			&newfattr);
		if (error) {
			printk("nfs_fhget: getattr error = %d\n", -error);
			return NULL;
		}
		fattr = &newfattr;
	}
	if (!(inode = iget(sb, fattr->fileid))) {
		printk("nfs_fhget: iget failed\n");
		return NULL;
	}
	if (inode->i_dev == sb->s_dev) {
		if (inode->i_ino != fattr->fileid) {
			printk("nfs_fhget: unexpected inode from iget\n");
			return inode;
		}
		*NFS_FH(inode) = *fhandle;
		nfs_refresh_inode(inode, fattr);
	}
	return inode;
}
Ejemplo n.º 3
0
static int
nfs3_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
		dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr)
{
	struct nfs_fattr	dir_attr;
	struct nfs3_mknodargs	arg = { NFS_FH(dir), name->name, name->len, 0,
					sattr, rdev };
	struct nfs3_diropres	res = { &dir_attr, fh, fattr };
	int			status;

	switch (sattr->ia_mode & S_IFMT) {
	case S_IFBLK:	arg.type = NF3BLK;  break;
	case S_IFCHR:	arg.type = NF3CHR;  break;
	case S_IFIFO:	arg.type = NF3FIFO; break;
	case S_IFSOCK:	arg.type = NF3SOCK; break;
	default:	return -EINVAL;
	}

	dprintk("NFS call  mknod %s %x\n", name->name, rdev);
	dir_attr.valid = 0;
	fattr->valid = 0;
	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
	nfs_refresh_inode(dir, &dir_attr);
	dprintk("NFS reply mknod: %d\n", status);
	return status;
}
Ejemplo n.º 4
0
/*
 * The READDIR implementation is somewhat hackish - we pass the user buffer
 * to the encode function, which installs it in the receive iovec.
 * The decode function itself doesn't perform any decoding, it just makes
 * sure the reply is syntactically correct.
 *
 * Also note that this implementation handles both plain readdir and
 * readdirplus.
 */
static int
nfs3_proc_readdir(struct inode *dir, struct rpc_cred *cred,
		  u64 cookie, void *entry,
		  unsigned int size, int plus)
{
	struct nfs_fattr	dir_attr;
	struct nfs3_readdirargs	arg = { NFS_FH(dir), cookie, {0, 0}, 0, 0, 0 };
	struct nfs3_readdirres	res = { &dir_attr, 0, 0, 0, 0 };
	struct rpc_message	msg = { NFS3PROC_READDIR, &arg, &res, cred };
	u32			*verf = NFS_COOKIEVERF(dir);
	int			status;

	arg.buffer  = entry;
	arg.bufsiz  = size;
	arg.verf[0] = verf[0];
	arg.verf[1] = verf[1];
	arg.plus    = plus;
	res.buffer  = entry;
	res.bufsiz  = size;
	res.verf    = verf;
	res.plus    = plus;

	if (plus)
		msg.rpc_proc = NFS3PROC_READDIRPLUS;

	dprintk("NFS call  readdir%s %d\n",
			plus? "plus" : "", (unsigned int) cookie);

	dir_attr.valid = 0;
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	nfs_refresh_inode(dir, &dir_attr);
	dprintk("NFS reply readdir: %d\n", status);
	return status;
}
Ejemplo n.º 5
0
/*
 * Fill in inode information from the fattr.
 */
static void
nfs_fill_inode(struct inode *inode, struct nfs_fattr *fattr)
{
    /*
     * Check whether the mode has been set, as we only want to
     * do this once. (We don't allow inodes to change types.)
     */
    if (inode->i_mode == 0) {
        inode->i_mode = fattr->mode;
        if (S_ISREG(inode->i_mode))
            inode->i_op = &nfs_file_inode_operations;
        else if (S_ISDIR(inode->i_mode))
            inode->i_op = &nfs_dir_inode_operations;
        else if (S_ISLNK(inode->i_mode))
            inode->i_op = &nfs_symlink_inode_operations;
        else if (S_ISCHR(inode->i_mode)) {
            inode->i_op = &chrdev_inode_operations;
            inode->i_rdev = to_kdev_t(fattr->rdev);
        } else if (S_ISBLK(inode->i_mode)) {
            inode->i_op = &blkdev_inode_operations;
            inode->i_rdev = to_kdev_t(fattr->rdev);
        } else if (S_ISFIFO(inode->i_mode))
            init_fifo(inode);
        else
            inode->i_op = NULL;
        /*
         * Preset the size and mtime, as there's no need
         * to invalidate the caches.
         */
        inode->i_size  = fattr->size;
        inode->i_mtime = fattr->mtime.seconds;
        NFS_OLDMTIME(inode) = fattr->mtime.seconds;
    }
    nfs_refresh_inode(inode, fattr);
}
Ejemplo n.º 6
0
static inline int
nfs_direct_read_rpc(struct file *file, struct nfs_readargs *arg)
{
	int result;
	struct inode * inode = file->f_dentry->d_inode;
	struct nfs_fattr fattr;
        struct rpc_message msg;
        struct nfs_readres res = { &fattr, arg->count, 0 };

#ifdef CONFIG_NFS_V3
	msg.rpc_proc = (NFS_PROTO(inode)->version == 3) ?
						NFS3PROC_READ : NFSPROC_READ;
#else
	msg.rpc_proc = NFSPROC_READ;
#endif
	msg.rpc_argp = arg;
        msg.rpc_resp = &res;

	lock_kernel();
        msg.rpc_cred = nfs_file_cred(file);
        fattr.valid = 0;
        result = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
	nfs_refresh_inode(inode, &fattr);
	unlock_kernel();

	return result;
}
Ejemplo n.º 7
0
static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data)
{
	if (nfs3_async_handle_jukebox(task, data->inode))
		return -EAGAIN;
	nfs_refresh_inode(data->inode, data->res.fattr);
	return 0;
}
Ejemplo n.º 8
0
static int
nfs3_proc_access(struct inode *inode, int mode, int ruid)
{
	struct nfs_fattr	fattr;
	struct nfs3_accessargs	arg = { NFS_FH(inode), 0 };
	struct nfs3_accessres	res = { &fattr, 0 };
	int	status, flags;

	dprintk("NFS call  access\n");
	fattr.valid = 0;

	if (mode & MAY_READ)
		arg.access |= NFS3_ACCESS_READ;
	if (S_ISDIR(inode->i_mode)) {
		if (mode & MAY_WRITE)
			arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE;
		if (mode & MAY_EXEC)
			arg.access |= NFS3_ACCESS_LOOKUP;
	} else {
		if (mode & MAY_WRITE)
			arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND;
		if (mode & MAY_EXEC)
			arg.access |= NFS3_ACCESS_EXECUTE;
	}
	flags = (ruid) ? RPC_CALL_REALUID : 0;
	status = rpc_call(NFS_CLIENT(inode), NFS3PROC_ACCESS, &arg, &res, flags);
	nfs_refresh_inode(inode, &fattr);
	dprintk("NFS reply access\n");

	if (status == 0 && (arg.access & res.access) != arg.access)
		status = -EACCES;
	return status;
}
/*
 * This is called every time the dcache has a lookup hit,
 * and we should check whether we can really trust that
 * lookup.
 *
 * NOTE! The hit can be a negative hit too, don't assume
 * we have an inode!
 *
 * If the parent directory is seen to have changed, we throw out the
 * cached dentry and do a new lookup.
 */
static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
{
	struct inode *dir;
	struct inode *inode;
	int error;
	struct nfs_fh fhandle;
	struct nfs_fattr fattr;

	lock_kernel();
	dir = dentry->d_parent->d_inode;
	inode = dentry->d_inode;

	if (!inode) {
		if (nfs_neg_need_reval(dir, dentry))
			goto out_bad;
		goto out_valid;
	}

	if (is_bad_inode(inode)) {
		dfprintk(VFS, "nfs_lookup_validate: %s/%s has dud inode\n",
			dentry->d_parent->d_name.name, dentry->d_name.name);
		goto out_bad;
	}

	/* Force a full look up iff the parent directory has changed */
	if (nfs_check_verifier(dir, dentry)) {
		if (nfs_lookup_verify_inode(inode, flags))
			goto out_bad;
		goto out_valid;
	}

	if (NFS_STALE(inode))
		goto out_bad;

	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
	if (error)
		goto out_bad;
	if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0)
		goto out_bad;
	if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
		goto out_bad;

	nfs_renew_times(dentry);
 out_valid:
	unlock_kernel();
	return 1;
 out_bad:
	NFS_CACHEINV(dir);
	if (inode && S_ISDIR(inode->i_mode)) {
		/* Purge readdir caches. */
		nfs_zap_caches(inode);
		/* If we have submounts, don't unhash ! */
		if (have_submounts(dentry))
			goto out_valid;
		shrink_dcache_parent(dentry);
	}
	d_drop(dentry);
	unlock_kernel();
	return 0;
}
Ejemplo n.º 10
0
static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
		  struct posix_acl *dfacl)
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct nfs_fattr fattr;
	struct page *pages[NFSACL_MAXPAGES] = { };
	struct nfs3_setaclargs args = {
		.inode = inode,
		.mask = NFS_ACL,
		.acl_access = acl,
		.pages = pages,
	};
	int status, count;

	status = -EOPNOTSUPP;
	if (!nfs_server_capable(inode, NFS_CAP_ACLS))
		goto out;

	/* We are doing this here, because XDR marshalling can only
	   return -ENOMEM. */
	status = -ENOSPC;
	if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES)
		goto out;
	if (dfacl != NULL && dfacl->a_count > NFS_ACL_MAX_ENTRIES)
		goto out;
	if (S_ISDIR(inode->i_mode)) {
		args.mask |= NFS_DFACL;
		args.acl_default = dfacl;
	}

	dprintk("NFS call setacl\n");
	nfs_begin_data_update(inode);
	status = rpc_call(server->client_acl, ACLPROC3_SETACL,
			  &args, &fattr, 0);
	spin_lock(&inode->i_lock);
	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS;
	spin_unlock(&inode->i_lock);
	nfs_end_data_update(inode);
	dprintk("NFS reply setacl: %d\n", status);

	/* pages may have been allocated at the xdr layer. */
	for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
		__free_page(args.pages[count]);

	switch (status) {
		case 0:
			status = nfs_refresh_inode(inode, &fattr);
			break;
		case -EPFNOSUPPORT:
		case -EPROTONOSUPPORT:
			dprintk("NFS_V3_ACL SETACL RPC not supported"
					"(will not retry)\n");
			server->caps &= ~NFS_CAP_ACLS;
		case -ENOTSUPP:
			status = -EOPNOTSUPP;
	}
out:
	return status;
}
Ejemplo n.º 11
0
/*
 * Read a page synchronously.
 */
static int
nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page)
{
	struct nfs_rreq	rqst;
	unsigned long	offset = page->offset;
	char		*buffer = (char *) page_address(page);
	int		rsize = NFS_SERVER(inode)->rsize;
	int		result, refresh = 0;
	int		count = PAGE_SIZE;
	int		flags = IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0;

	dprintk("NFS: nfs_readpage_sync(%p)\n", page);
	clear_bit(PG_error, &page->flags);

	do {
		if (count < rsize)
			rsize = count;

		dprintk("NFS: nfs_proc_read(%s, (%s/%s), %ld, %d, %p)\n",
			NFS_SERVER(inode)->hostname,
			dentry->d_parent->d_name.name, dentry->d_name.name,
			offset, rsize, buffer);

		/* Set up arguments and perform rpc call */
		nfs_readreq_setup(&rqst, NFS_FH(dentry), offset, buffer, rsize);
		result = rpc_call(NFS_CLIENT(inode), NFSPROC_READ,
					&rqst.ra_args, &rqst.ra_res, flags);

		/*
		 * Even if we had a partial success we can't mark the page
		 * cache valid.
		 */
		if (result < 0) {
			if (result == -EISDIR)
				result = -EINVAL;
			goto io_error;
		}
		refresh = 1;
		count  -= result;
		offset += result;
		buffer += result;
		if (result < rsize)	/* NFSv2ism */
			break;
	} while (count);

	memset(buffer, 0, count);
	set_bit(PG_uptodate, &page->flags);
	result = 0;

io_error:
	/* Note: we don't refresh if the call returned error */
	if (refresh && result >= 0)
		nfs_refresh_inode(inode, &rqst.ra_fattr);
	/* N.B. Use nfs_unlock_page here? */
	clear_bit(PG_locked, &page->flags);
	wake_up(&page->wait);
	return result;
}
Ejemplo n.º 12
0
static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data)
{
	if (nfs3_async_handle_jukebox(task, data->inode))
		return -EAGAIN;

	nfs_invalidate_atime(data->inode);
	nfs_refresh_inode(data->inode, &data->fattr);
	return 0;
}
Ejemplo n.º 13
0
static int
nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
{
	struct nfs_fattr	dir_attr, fattr;
	struct nfs3_linkargs	arg = { NFS_FH(inode), NFS_FH(dir),
					name->name, name->len };
	struct nfs3_linkres	res = { &dir_attr, &fattr };
	int			status;

	dprintk("NFS call  link %s\n", name->name);
	dir_attr.valid = 0;
	fattr.valid = 0;
	status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0);
	nfs_refresh_inode(dir, &dir_attr);
	nfs_refresh_inode(inode, &fattr);
	dprintk("NFS reply link: %d\n", status);
	return status;
}
Ejemplo n.º 14
0
/*
 * This is the callback from nfsiod telling us whether a reply was
 * received or some error occurred (timeout or socket shutdown).
 */
static int
nfsiod_read_result(int result, struct nfsiod_req *req)
{
	struct nfs_server *server = NFS_SERVER(req->rq_inode);
	struct page	*page = req->rq_page;
	static int	succ = 0, fail = 0;
	int		i;

	dprintk("BIO: received callback for page %p, result %d\n",
			page, result);

	if (result >= 0) {
		struct nfs_fattr	fattr;

		result = nfs_proc_read_reply(&req->rq_rpcreq, &fattr);
		if (result >= 0) {
			nfs_refresh_inode(req->rq_inode, &fattr);
			if (result < PAGE_SIZE)
				memset((u8 *) page_address(page)+result,
						0, PAGE_SIZE-result);
		}
	} else
	if (result == -ETIMEDOUT && !(server->flags & NFS_MOUNT_SOFT)) {
		/* XXX: Theoretically, we'd have to increment the initial
		 * timeo here; but I'm not going to bother with this now
		 * because this old nfsiod stuff will soon die anyway.
		 */
		result = -EAGAIN;
	}

	if (result == -EAGAIN && req->rq_retries--) {
		dprintk("BIO: retransmitting request.\n");
		memset(&req->rq_rpcreq, 0, sizeof(struct rpc_ioreq));
		while (rpc_reserve(server->rsock, &req->rq_rpcreq, 1) < 0)
			schedule();
		current->fsuid = req->rq_fsuid;
		current->fsgid = req->rq_fsgid;
		for (i = 0; i < NGROUPS; i++)
			current->groups[i] = req->rq_groups[i];
		nfsiod_read_setup(req);
		return 0;
	}
	if (result >= 0) {
		set_bit(PG_uptodate, &page->flags);
		succ++;
	} else {
		dprintk("BIO: %d successful reads, %d failures\n", succ, fail);
		set_bit(PG_error, &page->flags);
		fail++;
	}
	clear_bit(PG_locked, &page->flags);
	wake_up(&page->wait);
	free_page(page_address(page));
	return 1;
}
Ejemplo n.º 15
0
/*
 * This function will be used to simulate weak cache consistency
 * under NFSv2 when the NFSv3 attribute patch is included.
 * For the moment, we just call nfs_refresh_inode().
 */
static __inline__ int
nfs_write_attributes(struct inode *inode, struct nfs_fattr *fattr)
{
	if ((fattr->valid & NFS_ATTR_FATTR) && !(fattr->valid & NFS_ATTR_WCC)) {
		fattr->pre_size  = NFS_CACHE_ISIZE(inode);
		fattr->pre_mtime = NFS_CACHE_MTIME(inode);
		fattr->pre_ctime = NFS_CACHE_CTIME(inode);
		fattr->valid |= NFS_ATTR_WCC;
	}
	return nfs_refresh_inode(inode, fattr);
}
Ejemplo n.º 16
0
static void
nfs3_proc_unlink_done(struct dentry *dir, struct rpc_message *msg)
{
	struct nfs_fattr	*dir_attr;

	if (msg->rpc_argp) {
		dir_attr = (struct nfs_fattr*)msg->rpc_resp;
		nfs_refresh_inode(dir->d_inode, dir_attr);
		kfree(msg->rpc_argp);
	}
}
Ejemplo n.º 17
0
static int nfs3_commit_done(struct rpc_task *task, struct nfs_commit_data *data)
{
    zql_control_test(NFS_SERVER(data->inode));
    if (data->commit_done_cb != NULL)
        return data->commit_done_cb(task, data);

    if (nfs3_async_handle_jukebox(task, data->inode))
        return -EAGAIN;
    nfs_refresh_inode(data->inode, data->res.fattr);
    return 0;
}
Ejemplo n.º 18
0
static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
{
	struct inode *inode = hdr->inode;

	if (nfs3_async_handle_jukebox(task, inode))
		return -EAGAIN;

	nfs_invalidate_atime(inode);
	nfs_refresh_inode(inode, &hdr->fattr);
	return 0;
}
Ejemplo n.º 19
0
static int
nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
		 struct inode *new_dir, struct qstr *new_name)
{
	struct nfs_fattr	old_dir_attr, new_dir_attr;
	struct nfs3_renameargs	arg = { NFS_FH(old_dir),
					old_name->name, old_name->len,
					NFS_FH(new_dir),
					new_name->name, new_name->len };
	struct nfs3_renameres	res = { &old_dir_attr, &new_dir_attr };
	int			status;

	dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
	old_dir_attr.valid = 0;
	new_dir_attr.valid = 0;
	status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0);
	nfs_refresh_inode(old_dir, &old_dir_attr);
	nfs_refresh_inode(new_dir, &new_dir_attr);
	dprintk("NFS reply rename: %d\n", status);
	return status;
}
Ejemplo n.º 20
0
static int
nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
{
	struct nfs_fattr	dir_attr;
	struct nfs3_diropargs	arg = { NFS_FH(dir), name->name, name->len };
	int			status;

	dprintk("NFS call  rmdir %s\n", name->name);
	dir_attr.valid = 0;
	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0);
	nfs_refresh_inode(dir, &dir_attr);
	dprintk("NFS reply rmdir: %d\n", status);
	return status;
}
Ejemplo n.º 21
0
static int nfs_file_write(struct inode *inode, struct file *file, char *buf,
			  int count)
{
	int result;
	int hunk;
	int i;
	int n;
	struct nfs_fattr fattr;
	char *data;
	int pos;

	if (!inode) {
		printk("nfs_file_write: inode = NULL\n");
		return -EINVAL;
	}
	if (!S_ISREG(inode->i_mode)) {
		printk("nfs_file_write: write to non-file, mode %07o\n",
			inode->i_mode);
		return -EINVAL;
	}
	if (count <= 0)
		return 0;
	pos = file->f_pos;
	if (file->f_flags & O_APPEND)
		pos = inode->i_size;
	n = NFS_SERVER(inode)->wsize;
	data = (char *) kmalloc(n, GFP_KERNEL);
	for (i = 0; i < count; i += n) {
		hunk = count - i;
		if (hunk >= n)
			hunk = n;
		memcpy_fromfs(data, buf, hunk);
		result = nfs_proc_write(NFS_SERVER(inode), NFS_FH(inode), 
			pos, hunk, data, &fattr);
		if (result < 0) {
			kfree_s(data, n);
			return result;
		}
		pos += hunk;
		buf += hunk;
		if (hunk < n) {
			i += hunk;
			break;
		}
	}
	file->f_pos = pos;
	kfree_s(data, n);
	nfs_refresh_inode(inode, &fattr);
	return i;
}
Ejemplo n.º 22
0
static int nfs_file_read(struct inode *inode, struct file *file, char *buf,
			 int count)
{
	int result;
	int hunk;
	int i;
	int n;
	struct nfs_fattr fattr;
	char *data;
	off_t pos;

	if (!inode) {
		printk("nfs_file_read: inode = NULL\n");
		return -EINVAL;
	}
	if (!S_ISREG(inode->i_mode)) {
		printk("nfs_file_read: read from non-file, mode %07o\n",
			inode->i_mode);
		return -EINVAL;
	}
	pos = file->f_pos;
	if (file->f_pos + count > inode->i_size)
		count = inode->i_size - pos;
	if (count <= 0)
		return 0;
	n = NFS_SERVER(inode)->rsize;
	data = (char *) kmalloc(n, GFP_KERNEL);
	for (i = 0; i < count; i += n) {
		hunk = count - i;
		if (hunk > n)
			hunk = n;
		result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode), 
			pos, hunk, data, &fattr);
		if (result < 0) {
			kfree_s(data, n);
			return result;
		}
		memcpy_tofs(buf, data, result);
		pos += result;
		buf += result;
		if (result < n) {
			i += result;
			break;
		}
	}
	file->f_pos = pos;
	kfree_s(data, n);
	nfs_refresh_inode(inode, &fattr);
	return i;
}
Ejemplo n.º 23
0
static inline int
do_read_nfs_sync(struct inode * inode, struct page * page)
{
	struct nfs_fattr fattr;
	int		result, refresh = 0;
	int		count = PAGE_SIZE;
	int		rsize = NFS_SERVER(inode)->rsize;
	char		*buf = (char *) page_address(page);
	unsigned long	pos = page->offset;

	dprintk("NFS: do_read_nfs_sync(%p)\n", page);

	set_bit(PG_locked, &page->flags);
	clear_bit(PG_error, &page->flags);

	do {
		if (count < rsize)
			rsize = count;
		result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode), 
			pos, rsize, buf, &fattr);
		dprintk("nfs_proc_read(%s, (%x,%lx), %ld, %d, %p) = %d\n",
				NFS_SERVER(inode)->hostname,
				inode->i_dev, inode->i_ino,
				pos, rsize, buf, result);
		/*
		 * Even if we had a partial success we can't mark the page
		 * cache valid.
		 */
		if (result < 0)
			goto io_error;
		refresh = 1;
		count -= result;
		pos += result;
		buf += result;
		if (result < rsize)
			break;
	} while (count);

	memset(buf, 0, count);
	set_bit(PG_uptodate, &page->flags);
	result = 0;

io_error:
	if (refresh)
		nfs_refresh_inode(inode, &fattr);
	clear_bit(PG_locked, &page->flags);
	wake_up(&page->wait);
	return result;
}
Ejemplo n.º 24
0
static int
nfs3_proc_remove(struct inode *dir, struct qstr *name)
{
	struct nfs_fattr	dir_attr;
	struct nfs3_diropargs	arg = { NFS_FH(dir), name->name, name->len };
	struct rpc_message	msg = { NFS3PROC_REMOVE, &arg, &dir_attr, NULL };
	int			status;

	dprintk("NFS call  remove %s\n", name->name);
	dir_attr.valid = 0;
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	nfs_refresh_inode(dir, &dir_attr);
	dprintk("NFS reply remove: %d\n", status);
	return status;
}
Ejemplo n.º 25
0
static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
{
    struct inode *inode = hdr->inode;

    zql_control_test(NFS_SERVER(inode));
    if (hdr->pgio_done_cb != NULL)
        return hdr->pgio_done_cb(task, hdr);

    if (nfs3_async_handle_jukebox(task, inode))
        return -EAGAIN;

    nfs_invalidate_atime(inode);
    nfs_refresh_inode(inode, &hdr->fattr);
    return 0;
}
Ejemplo n.º 26
0
/*
 * Fill in the supplied page for mmap
 */
static unsigned long nfs_file_mmap_nopage(struct vm_area_struct * area,
	unsigned long address, unsigned long page, int no_share)
{
	struct inode * inode = area->vm_inode;
	unsigned int clear;
	unsigned long tmp;
	int n;
	int i;
	int pos;
	struct nfs_fattr fattr;

	address &= PAGE_MASK;
	pos = address - area->vm_start + area->vm_offset;

	clear = 0;
	if (address + PAGE_SIZE > area->vm_end) {
		clear = address + PAGE_SIZE - area->vm_end;
	}

	n = NFS_SERVER(inode)->rsize; /* what we can read in one go */

	for (i = 0; i < (PAGE_SIZE - clear); i += n) {
		int hunk, result;

		hunk = PAGE_SIZE - i;
		if (hunk > n)
			hunk = n;
		result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode),
			pos, hunk, (char *) (page + i), &fattr, 0);
		if (result < 0)
			break;
		pos += result;
		if (result < n) {
			i += result;
			break;
		}
	}

#ifdef doweneedthishere
	nfs_refresh_inode(inode, &fattr);
#endif

	tmp = page + PAGE_SIZE;
	while (clear--) {
		*(char *)--tmp = 0;
	}
	return page;
}
Ejemplo n.º 27
0
static int
nfs3_proc_readlink(struct inode *inode, void *buffer, unsigned int buflen)
{
	struct nfs_fattr	fattr;
	struct nfs3_readlinkargs args = { NFS_FH(inode), buffer, buflen };
	struct nfs3_readlinkres	res = { &fattr, buffer, buflen };
	int			status;

	dprintk("NFS call  readlink\n");
	fattr.valid = 0;
	status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK,
			  &args, &res, 0);
	nfs_refresh_inode(inode, &fattr);
	dprintk("NFS reply readlink: %d\n", status);
	return status;
}
Ejemplo n.º 28
0
static int
nfs3_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
	struct nfs_fattr	dir_attr;
	struct nfs3_mkdirargs	arg = { NFS_FH(dir), name->name, name->len,
					sattr };
	struct nfs3_diropres	res = { &dir_attr, fhandle, fattr };
	int			status;

	dprintk("NFS call  mkdir %s\n", name->name);
	dir_attr.valid = 0;
	fattr->valid = 0;
	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
	nfs_refresh_inode(dir, &dir_attr);
	dprintk("NFS reply mkdir: %d\n", status);
	return status;
}
Ejemplo n.º 29
0
static int
nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
		  struct iattr *sattr, struct nfs_fh *fhandle,
		  struct nfs_fattr *fattr)
{
	struct nfs_fattr	dir_attr;
	struct nfs3_symlinkargs	arg = { NFS_FH(dir), name->name, name->len,
					path->name, path->len, sattr };
	struct nfs3_diropres	res = { &dir_attr, fhandle, fattr };
	int			status;

	dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
	dir_attr.valid = 0;
	fattr->valid = 0;
	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0);
	nfs_refresh_inode(dir, &dir_attr);
	dprintk("NFS reply symlink: %d\n", status);
	return status;
}
Ejemplo n.º 30
0
static inline void revalidate_dir(struct nfs_server * server, struct inode * dir)
{
	struct nfs_fattr fattr;

	if (jiffies - NFS_READTIME(dir) < NFS_ATTRTIMEO(dir))
		return;

	NFS_READTIME(dir) = jiffies;
	if (nfs_proc_getattr(server, NFS_FH(dir), &fattr) == 0) {
		nfs_refresh_inode(dir, &fattr);
		if (fattr.mtime.seconds == NFS_OLDMTIME(dir)) {
			if ((NFS_ATTRTIMEO(dir) <<= 1) > server->acdirmax)
				NFS_ATTRTIMEO(dir) = server->acdirmax;
			return;
		}
		NFS_OLDMTIME(dir) = fattr.mtime.seconds;
	}
	/* invalidate directory cache here when we _really_ start caching */
}