Beispiel #1
0
/*
 * return post-operation attributes using stat cache
 *
 * fd_decomp must be called before to fill the stat cache
 */
post_op_attr get_post_cached(struct svc_req * req)
{
    if (!st_cache_valid)
        return error_attr;

    return get_post_buf(st_cache, req);
}
Beispiel #2
0
LOOKUP3res *nfsproc3_lookup_3_svc(LOOKUP3args * argp, struct svc_req * rqstp)
{
    static LOOKUP3res result;
    unfs3_fh_t *fh;
    char *path;
    char obj[NFS_MAXPATHLEN];
    backend_statstruct buf;
    int res;
    uint32 gen;

    PREP(path, argp->what.dir);
    result.status = cat_name(path, argp->what.name, obj);

    cluster_lookup(obj, rqstp, &result.status);

    if (result.status == NFS3_OK) {
	res = backend_lstat(obj, &buf);
	if (res == -1)
	    result.status = lookup_err();
	else {
	    if (strcmp(argp->what.name, ".") == 0 ||
		strcmp(argp->what.name, "..") == 0) {
		fh = fh_comp_ptr(obj, rqstp, 0);
	    } else {
		gen = backend_get_gen(buf, FD_NONE, obj);
		fh = fh_extend(argp->what.dir, buf.st_dev, buf.st_ino, gen);
		fh_cache_add(buf.st_dev, buf.st_ino, obj);
	    }

	    if (fh) {
		result.LOOKUP3res_u.resok.object.data.data_len =
		    fh_length(fh);
		result.LOOKUP3res_u.resok.object.data.data_val = (char *) fh;
		result.LOOKUP3res_u.resok.obj_attributes =
		    get_post_buf(buf, rqstp);
	    } else {
		/* path was too long */
		result.status = NFS3ERR_NAMETOOLONG;
	    }
	}
    }

    /* overlaps with resfail */
    result.LOOKUP3res_u.resok.dir_attributes = get_post_stat(path, rqstp);

    return &result;
}
Beispiel #3
0
/*
 * lowlevel routine for getting post-operation attributes
 */
static post_op_attr get_post_ll(const char *path, uint32 dev, uint64 ino,
                                struct svc_req *req)
{
    backend_statstruct buf;
    int res;

    if (!path)
        return error_attr;

    res = backend_lstat(path, &buf);
    if (res == -1)
        return error_attr;

    /* protect against local fs race */
    if (dev != buf.st_dev || ino != buf.st_ino)
        return error_attr;

    return get_post_buf(buf, req);
}
Beispiel #4
0
CREATE3res *nfsproc3_create_3_svc(CREATE3args * argp, struct svc_req * rqstp)
{
    static CREATE3res result;
    char *path;
    char obj[NFS_MAXPATHLEN];
    sattr3 new_attr;
    int fd = -1, res = -1;
    backend_statstruct buf;
    uint32 gen;
    int flags = O_RDWR | O_CREAT | O_TRUNC | O_NONBLOCK;

    PREP(path, argp->where.dir);
    result.status = join(cat_name(path, argp->where.name, obj), exports_rw());

    cluster_create(obj, rqstp, &result.status);

    /* GUARDED and EXCLUSIVE maps to Unix exclusive create */
    if (argp->how.mode != UNCHECKED)
	flags = flags | O_EXCL;

    if (argp->how.mode != EXCLUSIVE) {
	new_attr = argp->how.createhow3_u.obj_attributes;
	result.status = join(result.status, atomic_attr(new_attr));
    }

    /* Try to open the file */
    if (result.status == NFS3_OK) {
	if (argp->how.mode != EXCLUSIVE) {
	    fd = backend_open_create(obj, flags, create_mode(new_attr));
	} else {
	    fd = backend_open_create(obj, flags, create_mode(new_attr));
	}
    }

    if (fd != -1) {
	/* Successful open */
	res = backend_fstat(fd, &buf);
	if (res != -1) {
	    /* Successful stat */
	    if (argp->how.mode == EXCLUSIVE) {
		/* Save verifier in atime and mtime */
		res =
		    backend_store_create_verifier(obj,
						  argp->how.createhow3_u.
						  verf);
	    }
	}

	if (res != -1) {
	    /* So far, so good */
	    gen = backend_get_gen(buf, fd, obj);
	    fh_cache_add(buf.st_dev, buf.st_ino, obj);
	    backend_close(fd);

	    result.CREATE3res_u.resok.obj =
		fh_extend_post(argp->where.dir, buf.st_dev, buf.st_ino, gen);
	    result.CREATE3res_u.resok.obj_attributes =
		get_post_buf(buf, rqstp);
	}

	if (res == -1) {
	    /* backend_fstat() or backend_store_create_verifier() failed */
	    backend_close(fd);
	    result.status = NFS3ERR_IO;
	}

    } else if (result.status == NFS3_OK) {
	/* open() failed */
	if (argp->how.mode == EXCLUSIVE && errno == EEXIST) {
	    /* Check if verifier matches */
	    fd = backend_open(obj, O_NONBLOCK);
	    if (fd != -1) {
		res = backend_fstat(fd, &buf);
	    }

	    if (res != -1) {
		if (backend_check_create_verifier
		    (&buf, argp->how.createhow3_u.verf)) {
		    /* The verifier matched. Return success */
		    gen = backend_get_gen(buf, fd, obj);
		    fh_cache_add(buf.st_dev, buf.st_ino, obj);
		    backend_close(fd);

		    result.CREATE3res_u.resok.obj =
			fh_extend_post(argp->where.dir, buf.st_dev,
				       buf.st_ino, gen);
		    result.CREATE3res_u.resok.obj_attributes =
			get_post_buf(buf, rqstp);
		} else {
		    /* The verifier doesn't match */
		    result.status = NFS3ERR_EXIST;
		}
	    }
	}
	if (res == -1) {
	    result.status = create_err();
	}
    }

    /* overlaps with resfail */
    result.CREATE3res_u.resok.dir_wcc.before = get_pre_cached();
    result.CREATE3res_u.resok.dir_wcc.after = get_post_stat(path, rqstp);

    return &result;
}