/* * 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); }
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; }
/* * 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); }
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; }