1dcb9dbe3SAneesh Kumar K.V /* 2af8b38b0SGreg Kurz * 9p backend 3dcb9dbe3SAneesh Kumar K.V * 4dcb9dbe3SAneesh Kumar K.V * Copyright IBM, Corp. 2011 5dcb9dbe3SAneesh Kumar K.V * 6dcb9dbe3SAneesh Kumar K.V * Authors: 7dcb9dbe3SAneesh Kumar K.V * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 8dcb9dbe3SAneesh Kumar K.V * 9dcb9dbe3SAneesh Kumar K.V * This work is licensed under the terms of the GNU GPL, version 2. See 10dcb9dbe3SAneesh Kumar K.V * the COPYING file in the top-level directory. 11dcb9dbe3SAneesh Kumar K.V * 12dcb9dbe3SAneesh Kumar K.V */ 13dcb9dbe3SAneesh Kumar K.V 14fbc04127SPeter Maydell #include "qemu/osdep.h" 15dcb9dbe3SAneesh Kumar K.V #include "fsdev/qemu-fsdev.h" 161de7afc9SPaolo Bonzini #include "qemu/thread.h" 1710817bf0SDaniel P. Berrange #include "qemu/coroutine.h" 18db725815SMarkus Armbruster #include "qemu/main-loop.h" 19fe52840cSWei Liu #include "coth.h" 20dcb9dbe3SAneesh Kumar K.V 21dd8151f4SChristian Schoenebeck /* 22dd8151f4SChristian Schoenebeck * Intended to be called from bottom-half (e.g. background I/O thread) 23dd8151f4SChristian Schoenebeck * context. 24dd8151f4SChristian Schoenebeck */ 25dd8151f4SChristian Schoenebeck static int do_readdir(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent **dent) 26dcb9dbe3SAneesh Kumar K.V { 27dd8151f4SChristian Schoenebeck int err = 0; 28bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 29635324e8SGreg Kurz struct dirent *entry; 30635324e8SGreg Kurz 31dcb9dbe3SAneesh Kumar K.V errno = 0; 32635324e8SGreg Kurz entry = s->ops->readdir(&s->ctx, &fidp->fs); 33635324e8SGreg Kurz if (!entry && errno) { 34dd8151f4SChristian Schoenebeck *dent = NULL; 35dcb9dbe3SAneesh Kumar K.V err = -errno; 36dcb9dbe3SAneesh Kumar K.V } else { 37635324e8SGreg Kurz *dent = entry; 38dcb9dbe3SAneesh Kumar K.V } 39dd8151f4SChristian Schoenebeck return err; 40dd8151f4SChristian Schoenebeck } 41dd8151f4SChristian Schoenebeck 42*2149675bSChristian Schoenebeck /* 43*2149675bSChristian Schoenebeck * TODO: This will be removed for performance reasons. 44*2149675bSChristian Schoenebeck * Use v9fs_co_readdir_many() instead. 45*2149675bSChristian Schoenebeck */ 46dd8151f4SChristian Schoenebeck int coroutine_fn v9fs_co_readdir(V9fsPDU *pdu, V9fsFidState *fidp, 47dd8151f4SChristian Schoenebeck struct dirent **dent) 48dd8151f4SChristian Schoenebeck { 49dd8151f4SChristian Schoenebeck int err; 50dd8151f4SChristian Schoenebeck 51dd8151f4SChristian Schoenebeck if (v9fs_request_cancelled(pdu)) { 52dd8151f4SChristian Schoenebeck return -EINTR; 53dd8151f4SChristian Schoenebeck } 54dd8151f4SChristian Schoenebeck v9fs_co_run_in_worker({ 55dd8151f4SChristian Schoenebeck err = do_readdir(pdu, fidp, dent); 56dcb9dbe3SAneesh Kumar K.V }); 57dcb9dbe3SAneesh Kumar K.V return err; 58dcb9dbe3SAneesh Kumar K.V } 59dcb9dbe3SAneesh Kumar K.V 60*2149675bSChristian Schoenebeck /* 61*2149675bSChristian Schoenebeck * This is solely executed on a background IO thread. 62*2149675bSChristian Schoenebeck * 63*2149675bSChristian Schoenebeck * See v9fs_co_readdir_many() (as its only user) below for details. 64*2149675bSChristian Schoenebeck */ 65*2149675bSChristian Schoenebeck static int do_readdir_many(V9fsPDU *pdu, V9fsFidState *fidp, 66*2149675bSChristian Schoenebeck struct V9fsDirEnt **entries, off_t offset, 67*2149675bSChristian Schoenebeck int32_t maxsize, bool dostat) 68*2149675bSChristian Schoenebeck { 69*2149675bSChristian Schoenebeck V9fsState *s = pdu->s; 70*2149675bSChristian Schoenebeck V9fsString name; 71*2149675bSChristian Schoenebeck int len, err = 0; 72*2149675bSChristian Schoenebeck int32_t size = 0; 73*2149675bSChristian Schoenebeck off_t saved_dir_pos; 74*2149675bSChristian Schoenebeck struct dirent *dent; 75*2149675bSChristian Schoenebeck struct V9fsDirEnt *e = NULL; 76*2149675bSChristian Schoenebeck V9fsPath path; 77*2149675bSChristian Schoenebeck struct stat stbuf; 78*2149675bSChristian Schoenebeck 79*2149675bSChristian Schoenebeck *entries = NULL; 80*2149675bSChristian Schoenebeck v9fs_path_init(&path); 81*2149675bSChristian Schoenebeck 82*2149675bSChristian Schoenebeck /* 83*2149675bSChristian Schoenebeck * TODO: Here should be a warn_report_once() if lock failed. 84*2149675bSChristian Schoenebeck * 85*2149675bSChristian Schoenebeck * With a good 9p client we should not get into concurrency here, 86*2149675bSChristian Schoenebeck * because a good client would not use the same fid for concurrent 87*2149675bSChristian Schoenebeck * requests. We do the lock here for safety reasons though. However 88*2149675bSChristian Schoenebeck * the client would then suffer performance issues, so better log that 89*2149675bSChristian Schoenebeck * issue here. 90*2149675bSChristian Schoenebeck */ 91*2149675bSChristian Schoenebeck v9fs_readdir_lock(&fidp->fs.dir); 92*2149675bSChristian Schoenebeck 93*2149675bSChristian Schoenebeck /* seek directory to requested initial position */ 94*2149675bSChristian Schoenebeck if (offset == 0) { 95*2149675bSChristian Schoenebeck s->ops->rewinddir(&s->ctx, &fidp->fs); 96*2149675bSChristian Schoenebeck } else { 97*2149675bSChristian Schoenebeck s->ops->seekdir(&s->ctx, &fidp->fs, offset); 98*2149675bSChristian Schoenebeck } 99*2149675bSChristian Schoenebeck 100*2149675bSChristian Schoenebeck /* save the directory position */ 101*2149675bSChristian Schoenebeck saved_dir_pos = s->ops->telldir(&s->ctx, &fidp->fs); 102*2149675bSChristian Schoenebeck if (saved_dir_pos < 0) { 103*2149675bSChristian Schoenebeck err = saved_dir_pos; 104*2149675bSChristian Schoenebeck goto out; 105*2149675bSChristian Schoenebeck } 106*2149675bSChristian Schoenebeck 107*2149675bSChristian Schoenebeck while (true) { 108*2149675bSChristian Schoenebeck /* interrupt loop if request was cancelled by a Tflush request */ 109*2149675bSChristian Schoenebeck if (v9fs_request_cancelled(pdu)) { 110*2149675bSChristian Schoenebeck err = -EINTR; 111*2149675bSChristian Schoenebeck break; 112*2149675bSChristian Schoenebeck } 113*2149675bSChristian Schoenebeck 114*2149675bSChristian Schoenebeck /* get directory entry from fs driver */ 115*2149675bSChristian Schoenebeck err = do_readdir(pdu, fidp, &dent); 116*2149675bSChristian Schoenebeck if (err || !dent) { 117*2149675bSChristian Schoenebeck break; 118*2149675bSChristian Schoenebeck } 119*2149675bSChristian Schoenebeck 120*2149675bSChristian Schoenebeck /* 121*2149675bSChristian Schoenebeck * stop this loop as soon as it would exceed the allowed maximum 122*2149675bSChristian Schoenebeck * response message size for the directory entries collected so far, 123*2149675bSChristian Schoenebeck * because anything beyond that size would need to be discarded by 124*2149675bSChristian Schoenebeck * 9p controller (main thread / top half) anyway 125*2149675bSChristian Schoenebeck */ 126*2149675bSChristian Schoenebeck v9fs_string_init(&name); 127*2149675bSChristian Schoenebeck v9fs_string_sprintf(&name, "%s", dent->d_name); 128*2149675bSChristian Schoenebeck len = v9fs_readdir_response_size(&name); 129*2149675bSChristian Schoenebeck v9fs_string_free(&name); 130*2149675bSChristian Schoenebeck if (size + len > maxsize) { 131*2149675bSChristian Schoenebeck /* this is not an error case actually */ 132*2149675bSChristian Schoenebeck break; 133*2149675bSChristian Schoenebeck } 134*2149675bSChristian Schoenebeck 135*2149675bSChristian Schoenebeck /* append next node to result chain */ 136*2149675bSChristian Schoenebeck if (!e) { 137*2149675bSChristian Schoenebeck *entries = e = g_malloc0(sizeof(V9fsDirEnt)); 138*2149675bSChristian Schoenebeck } else { 139*2149675bSChristian Schoenebeck e = e->next = g_malloc0(sizeof(V9fsDirEnt)); 140*2149675bSChristian Schoenebeck } 141*2149675bSChristian Schoenebeck e->dent = g_malloc0(sizeof(struct dirent)); 142*2149675bSChristian Schoenebeck memcpy(e->dent, dent, sizeof(struct dirent)); 143*2149675bSChristian Schoenebeck 144*2149675bSChristian Schoenebeck /* perform a full stat() for directory entry if requested by caller */ 145*2149675bSChristian Schoenebeck if (dostat) { 146*2149675bSChristian Schoenebeck err = s->ops->name_to_path( 147*2149675bSChristian Schoenebeck &s->ctx, &fidp->path, dent->d_name, &path 148*2149675bSChristian Schoenebeck ); 149*2149675bSChristian Schoenebeck if (err < 0) { 150*2149675bSChristian Schoenebeck err = -errno; 151*2149675bSChristian Schoenebeck break; 152*2149675bSChristian Schoenebeck } 153*2149675bSChristian Schoenebeck 154*2149675bSChristian Schoenebeck err = s->ops->lstat(&s->ctx, &path, &stbuf); 155*2149675bSChristian Schoenebeck if (err < 0) { 156*2149675bSChristian Schoenebeck err = -errno; 157*2149675bSChristian Schoenebeck break; 158*2149675bSChristian Schoenebeck } 159*2149675bSChristian Schoenebeck 160*2149675bSChristian Schoenebeck e->st = g_malloc0(sizeof(struct stat)); 161*2149675bSChristian Schoenebeck memcpy(e->st, &stbuf, sizeof(struct stat)); 162*2149675bSChristian Schoenebeck } 163*2149675bSChristian Schoenebeck 164*2149675bSChristian Schoenebeck size += len; 165*2149675bSChristian Schoenebeck saved_dir_pos = dent->d_off; 166*2149675bSChristian Schoenebeck } 167*2149675bSChristian Schoenebeck 168*2149675bSChristian Schoenebeck /* restore (last) saved position */ 169*2149675bSChristian Schoenebeck s->ops->seekdir(&s->ctx, &fidp->fs, saved_dir_pos); 170*2149675bSChristian Schoenebeck 171*2149675bSChristian Schoenebeck out: 172*2149675bSChristian Schoenebeck v9fs_readdir_unlock(&fidp->fs.dir); 173*2149675bSChristian Schoenebeck v9fs_path_free(&path); 174*2149675bSChristian Schoenebeck if (err < 0) { 175*2149675bSChristian Schoenebeck return err; 176*2149675bSChristian Schoenebeck } 177*2149675bSChristian Schoenebeck return size; 178*2149675bSChristian Schoenebeck } 179*2149675bSChristian Schoenebeck 180*2149675bSChristian Schoenebeck /** 181*2149675bSChristian Schoenebeck * @brief Reads multiple directory entries in one rush. 182*2149675bSChristian Schoenebeck * 183*2149675bSChristian Schoenebeck * Retrieves the requested (max. amount of) directory entries from the fs 184*2149675bSChristian Schoenebeck * driver. This function must only be called by the main IO thread (top half). 185*2149675bSChristian Schoenebeck * Internally this function call will be dispatched to a background IO thread 186*2149675bSChristian Schoenebeck * (bottom half) where it is eventually executed by the fs driver. 187*2149675bSChristian Schoenebeck * 188*2149675bSChristian Schoenebeck * @discussion Acquiring multiple directory entries in one rush from the fs 189*2149675bSChristian Schoenebeck * driver, instead of retrieving each directory entry individually, is very 190*2149675bSChristian Schoenebeck * beneficial from performance point of view. Because for every fs driver 191*2149675bSChristian Schoenebeck * request latency is added, which in practice could lead to overall 192*2149675bSChristian Schoenebeck * latencies of several hundred ms for reading all entries (of just a single 193*2149675bSChristian Schoenebeck * directory) if every directory entry was individually requested from fs 194*2149675bSChristian Schoenebeck * driver. 195*2149675bSChristian Schoenebeck * 196*2149675bSChristian Schoenebeck * @note You must @b ALWAYS call @c v9fs_free_dirents(entries) after calling 197*2149675bSChristian Schoenebeck * v9fs_co_readdir_many(), both on success and on error cases of this 198*2149675bSChristian Schoenebeck * function, to avoid memory leaks once @p entries are no longer needed. 199*2149675bSChristian Schoenebeck * 200*2149675bSChristian Schoenebeck * @param pdu - the causing 9p (T_readdir) client request 201*2149675bSChristian Schoenebeck * @param fidp - already opened directory where readdir shall be performed on 202*2149675bSChristian Schoenebeck * @param entries - output for directory entries (must not be NULL) 203*2149675bSChristian Schoenebeck * @param offset - initial position inside the directory the function shall 204*2149675bSChristian Schoenebeck * seek to before retrieving the directory entries 205*2149675bSChristian Schoenebeck * @param maxsize - maximum result message body size (in bytes) 206*2149675bSChristian Schoenebeck * @param dostat - whether a stat() should be performed and returned for 207*2149675bSChristian Schoenebeck * each directory entry 208*2149675bSChristian Schoenebeck * @returns resulting response message body size (in bytes) on success, 209*2149675bSChristian Schoenebeck * negative error code otherwise 210*2149675bSChristian Schoenebeck */ 211*2149675bSChristian Schoenebeck int coroutine_fn v9fs_co_readdir_many(V9fsPDU *pdu, V9fsFidState *fidp, 212*2149675bSChristian Schoenebeck struct V9fsDirEnt **entries, 213*2149675bSChristian Schoenebeck off_t offset, int32_t maxsize, 214*2149675bSChristian Schoenebeck bool dostat) 215*2149675bSChristian Schoenebeck { 216*2149675bSChristian Schoenebeck int err = 0; 217*2149675bSChristian Schoenebeck 218*2149675bSChristian Schoenebeck if (v9fs_request_cancelled(pdu)) { 219*2149675bSChristian Schoenebeck return -EINTR; 220*2149675bSChristian Schoenebeck } 221*2149675bSChristian Schoenebeck v9fs_co_run_in_worker({ 222*2149675bSChristian Schoenebeck err = do_readdir_many(pdu, fidp, entries, offset, maxsize, dostat); 223*2149675bSChristian Schoenebeck }); 224*2149675bSChristian Schoenebeck return err; 225*2149675bSChristian Schoenebeck } 226*2149675bSChristian Schoenebeck 227bccacf6cSAneesh Kumar K.V off_t v9fs_co_telldir(V9fsPDU *pdu, V9fsFidState *fidp) 228dcb9dbe3SAneesh Kumar K.V { 229dcb9dbe3SAneesh Kumar K.V off_t err; 230bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 231dcb9dbe3SAneesh Kumar K.V 232bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 233bccacf6cSAneesh Kumar K.V return -EINTR; 234bccacf6cSAneesh Kumar K.V } 235dcb9dbe3SAneesh Kumar K.V v9fs_co_run_in_worker( 236dcb9dbe3SAneesh Kumar K.V { 237cc720ddbSAneesh Kumar K.V err = s->ops->telldir(&s->ctx, &fidp->fs); 238dcb9dbe3SAneesh Kumar K.V if (err < 0) { 239dcb9dbe3SAneesh Kumar K.V err = -errno; 240dcb9dbe3SAneesh Kumar K.V } 241dcb9dbe3SAneesh Kumar K.V }); 242dcb9dbe3SAneesh Kumar K.V return err; 243dcb9dbe3SAneesh Kumar K.V } 244dcb9dbe3SAneesh Kumar K.V 2455bdade66SGreg Kurz void coroutine_fn v9fs_co_seekdir(V9fsPDU *pdu, V9fsFidState *fidp, 2465bdade66SGreg Kurz off_t offset) 247dcb9dbe3SAneesh Kumar K.V { 248bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 249bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 250bccacf6cSAneesh Kumar K.V return; 251bccacf6cSAneesh Kumar K.V } 252dcb9dbe3SAneesh Kumar K.V v9fs_co_run_in_worker( 253dcb9dbe3SAneesh Kumar K.V { 254cc720ddbSAneesh Kumar K.V s->ops->seekdir(&s->ctx, &fidp->fs, offset); 255dcb9dbe3SAneesh Kumar K.V }); 256dcb9dbe3SAneesh Kumar K.V } 257dcb9dbe3SAneesh Kumar K.V 2585bdade66SGreg Kurz void coroutine_fn v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp) 259dcb9dbe3SAneesh Kumar K.V { 260bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 261bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 262bccacf6cSAneesh Kumar K.V return; 263bccacf6cSAneesh Kumar K.V } 264dcb9dbe3SAneesh Kumar K.V v9fs_co_run_in_worker( 265dcb9dbe3SAneesh Kumar K.V { 266cc720ddbSAneesh Kumar K.V s->ops->rewinddir(&s->ctx, &fidp->fs); 267dcb9dbe3SAneesh Kumar K.V }); 268dcb9dbe3SAneesh Kumar K.V } 269d0884642SVenkateswararao Jujjuri 2705bdade66SGreg Kurz int coroutine_fn v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, 2715bdade66SGreg Kurz V9fsString *name, mode_t mode, uid_t uid, 2725bdade66SGreg Kurz gid_t gid, struct stat *stbuf) 273d0884642SVenkateswararao Jujjuri { 274d0884642SVenkateswararao Jujjuri int err; 275d0884642SVenkateswararao Jujjuri FsCred cred; 2762289be19SAneesh Kumar K.V V9fsPath path; 277bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 278d0884642SVenkateswararao Jujjuri 279bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 2803a93113aSDong Xu Wang return -EINTR; 281bccacf6cSAneesh Kumar K.V } 282d0884642SVenkateswararao Jujjuri cred_init(&cred); 283d0884642SVenkateswararao Jujjuri cred.fc_mode = mode; 284d0884642SVenkateswararao Jujjuri cred.fc_uid = uid; 285d0884642SVenkateswararao Jujjuri cred.fc_gid = gid; 286532decb7SAneesh Kumar K.V v9fs_path_read_lock(s); 287d0884642SVenkateswararao Jujjuri v9fs_co_run_in_worker( 288d0884642SVenkateswararao Jujjuri { 2892289be19SAneesh Kumar K.V err = s->ops->mkdir(&s->ctx, &fidp->path, name->data, &cred); 29002cb7f3aSAneesh Kumar K.V if (err < 0) { 29102cb7f3aSAneesh Kumar K.V err = -errno; 29202cb7f3aSAneesh Kumar K.V } else { 2932289be19SAneesh Kumar K.V v9fs_path_init(&path); 2942289be19SAneesh Kumar K.V err = v9fs_name_to_path(s, &fidp->path, name->data, &path); 2952289be19SAneesh Kumar K.V if (!err) { 2962289be19SAneesh Kumar K.V err = s->ops->lstat(&s->ctx, &path, stbuf); 297d0884642SVenkateswararao Jujjuri if (err < 0) { 298d0884642SVenkateswararao Jujjuri err = -errno; 299d0884642SVenkateswararao Jujjuri } 30002cb7f3aSAneesh Kumar K.V } 3012289be19SAneesh Kumar K.V v9fs_path_free(&path); 3022289be19SAneesh Kumar K.V } 303d0884642SVenkateswararao Jujjuri }); 304532decb7SAneesh Kumar K.V v9fs_path_unlock(s); 305d0884642SVenkateswararao Jujjuri return err; 306d0884642SVenkateswararao Jujjuri } 307f6b7f0abSAneesh Kumar K.V 3085bdade66SGreg Kurz int coroutine_fn v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState *fidp) 309f6b7f0abSAneesh Kumar K.V { 310f6b7f0abSAneesh Kumar K.V int err; 311bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 312f6b7f0abSAneesh Kumar K.V 313bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 3143a93113aSDong Xu Wang return -EINTR; 315bccacf6cSAneesh Kumar K.V } 316532decb7SAneesh Kumar K.V v9fs_path_read_lock(s); 317f6b7f0abSAneesh Kumar K.V v9fs_co_run_in_worker( 318f6b7f0abSAneesh Kumar K.V { 319cc720ddbSAneesh Kumar K.V err = s->ops->opendir(&s->ctx, &fidp->path, &fidp->fs); 320cc720ddbSAneesh Kumar K.V if (err < 0) { 321f6b7f0abSAneesh Kumar K.V err = -errno; 322f6b7f0abSAneesh Kumar K.V } else { 323f6b7f0abSAneesh Kumar K.V err = 0; 324f6b7f0abSAneesh Kumar K.V } 325f6b7f0abSAneesh Kumar K.V }); 326532decb7SAneesh Kumar K.V v9fs_path_unlock(s); 32795f65511SAneesh Kumar K.V if (!err) { 32895f65511SAneesh Kumar K.V total_open_fd++; 32995f65511SAneesh Kumar K.V if (total_open_fd > open_fd_hw) { 330bccacf6cSAneesh Kumar K.V v9fs_reclaim_fd(pdu); 33195f65511SAneesh Kumar K.V } 33295f65511SAneesh Kumar K.V } 333f6b7f0abSAneesh Kumar K.V return err; 334f6b7f0abSAneesh Kumar K.V } 335bed4352cSAneesh Kumar K.V 3365bdade66SGreg Kurz int coroutine_fn v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState *fs) 337bed4352cSAneesh Kumar K.V { 338bed4352cSAneesh Kumar K.V int err; 339bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 340bed4352cSAneesh Kumar K.V 341bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 3423a93113aSDong Xu Wang return -EINTR; 343bccacf6cSAneesh Kumar K.V } 344bed4352cSAneesh Kumar K.V v9fs_co_run_in_worker( 345bed4352cSAneesh Kumar K.V { 346cc720ddbSAneesh Kumar K.V err = s->ops->closedir(&s->ctx, fs); 347bed4352cSAneesh Kumar K.V if (err < 0) { 348bed4352cSAneesh Kumar K.V err = -errno; 349bed4352cSAneesh Kumar K.V } 350bed4352cSAneesh Kumar K.V }); 35195f65511SAneesh Kumar K.V if (!err) { 35295f65511SAneesh Kumar K.V total_open_fd--; 35395f65511SAneesh Kumar K.V } 354bed4352cSAneesh Kumar K.V return err; 355bed4352cSAneesh Kumar K.V } 356